diff --git a/engdocs/architecture/dispatch.md b/engdocs/architecture/dispatch.md index 50dac19d32..b51d36cbdc 100644 --- a/engdocs/architecture/dispatch.md +++ b/engdocs/architecture/dispatch.md @@ -159,13 +159,18 @@ resolution and predicates: `bdReadyPoolDemandShell(limitFlag)` reads the canonical `gc.routed_to=` route with `--include-ephemeral`, and the temporary migration predicate reads `gc.run_target=` only on `gc.kind=workflow` roots that predate root `gc.routed_to` stamping. The -work-query form appends `--sort oldest --limit=1` to the canonical probe +work-query form appends `--sort hybrid --limit=20` to the canonical probe and prints the first match, then filters the migration probe to roots with -empty `gc.routed_to`. That is an intentional routed-queue policy: -unassigned routed pool work is FIFO before priority, so newer -high-priority work does not jump ahead of older ready work already queued -for the same target. The count form unions canonical and migration -probes and deduplicates by bead ID before piping through `jq 'length'`. +empty `gc.routed_to`. The `hybrid` sort is the routed-queue ordering policy +(ADR-0035): fresh work (`< 48h`) is ordered by bead priority, so a newly +routed P1 is claimed ahead of an older P2/P3, while work `>= 48h` old drains +strictly oldest-first, preserving the age-based anti-starvation drain the +prior `--sort oldest` was chosen for. `--limit=20` is an anti-self-block +lookahead (a self-blocked head falls through to ready work behind it), not a +priority window. The count form unions canonical and migration probes and +deduplicates by bead ID before piping through `jq 'length'`; it passes no +`--sort` (order is irrelevant to a length), so the worker-claim ordering does +not perturb the reconciler's spawn count. Targets resolve to `Agent.PoolName` when set and `Agent.QualifiedName()` otherwise, so pool instances and pool templates land on the same routed queue. @@ -260,7 +265,7 @@ regressions. worker and reconciler must also share the temporary migration predicate for `gc.run_target=` on `gc.kind=workflow` roots with empty `gc.routed_to`; only the worker's first-row form adds native - `bd ready --sort oldest --limit=1` selection to the canonical probe. + `bd ready --sort hybrid --limit=20` selection to the canonical probe. Any pool-demand predicate change to one (added filter, modified target resolution, new state) MUST be reflected in the other. Diverging the two re-introduces the protocol-mismatch class — the reconciler @@ -372,7 +377,7 @@ name = "coder" pool = { min = 1, max = 3, check = "echo 2" } # Default sling_query: bd update {} --set-metadata gc.routed_to=coder # Default work_query: bd ready --include-ephemeral --metadata-field gc.routed_to=coder -# --unassigned --exclude-type=epic --json --sort oldest --limit=1, +# --unassigned --exclude-type=epic --json --sort hybrid --limit=20, # then a temporary gc.run_target workflow-root migration fallback ``` diff --git a/internal/config/config_test.go b/internal/config/config_test.go index f22f158e30..476c34c262 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -1912,7 +1912,7 @@ func TestEffectiveWorkQueryDefault(t *testing.T) { if strings.Contains(got, `--include-ephemeral`) { t.Errorf("EffectiveWorkQuery() default must be bd 1.0.4-compatible without --include-ephemeral: %q", got) } - if !strings.Contains(got, `bd ready --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort oldest --limit=20`) { + if !strings.Contains(got, `bd ready --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort hybrid --limit=20`) { t.Errorf("EffectiveWorkQuery() missing tier 3 pool-demand probe: %q", got) } if !strings.Contains(got, "-- mayor") { @@ -1934,7 +1934,7 @@ func TestEffectiveWorkQueryDefault(t *testing.T) { func TestEffectiveWorkQueryBD105CompatibilityOptIn(t *testing.T) { a := Agent{Name: "mayor"} got := a.EffectiveWorkQueryForBeads(BeadsConfig{BDCompatibility: BeadsBDCompatibility105}) - if !strings.Contains(got, `bd ready --include-ephemeral --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort oldest --limit=20`) { + if !strings.Contains(got, `bd ready --include-ephemeral --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort hybrid --limit=20`) { t.Errorf("EffectiveWorkQueryForBeads(bd-1.0.5) missing include-ephemeral routed probe: %q", got) } if !strings.Contains(got, `bd ready --include-ephemeral --assignee="$id" --json --limit=1`) { @@ -2307,13 +2307,13 @@ func TestEffectiveWorkQueryControlDispatcherClaimsLegacyUnassignedRoute(t *testi out := runEffectiveWorkQuery(t, a, nil, `#!/bin/sh set -eu case "$*" in - *"ready --include-ephemeral"*"--metadata-field gc.routed_to=gascity/control-dispatcher"*"--unassigned"*"--exclude-type=epic"*"--json"*"--sort oldest"*"--limit=20"*) + *"ready --include-ephemeral"*"--metadata-field gc.routed_to=gascity/control-dispatcher"*"--unassigned"*"--exclude-type=epic"*"--json"*"--sort hybrid"*"--limit=20"*) printf '[]' ;; - *"ready --metadata-field gc.routed_to=gascity/control-dispatcher"*"--unassigned"*"--exclude-type=epic"*"--json"*"--sort oldest"*"--limit=20"*) + *"ready --metadata-field gc.routed_to=gascity/control-dispatcher"*"--unassigned"*"--exclude-type=epic"*"--json"*"--sort hybrid"*"--limit=20"*) printf '[]' ;; - *"ready --metadata-field gc.routed_to=gascity/workflow-control"*"--unassigned"*"--exclude-type=epic"*"--json"*"--sort oldest"*"--limit=20"*) + *"ready --metadata-field gc.routed_to=gascity/workflow-control"*"--unassigned"*"--exclude-type=epic"*"--json"*"--sort hybrid"*"--limit=20"*) printf '[{"id":"ga-legacy-route"}]' ;; *) @@ -2326,7 +2326,11 @@ esac } } -func TestEffectiveWorkQueryRoutedQueueUsesNativeOldestSortAcrossReadyTiers(t *testing.T) { +func TestEffectiveWorkQueryRoutedQueueUsesNativeHybridSortAcrossReadyTiers(t *testing.T) { + // ADR-0035 (vc-zv4y): Tier 3 delegates ordering to bd's NATIVE --sort + // (hybrid), not a jq-side re-sort, and returns bd's first row. This pins the + // native-sort composition and the first-row-only contract; the sort policy + // itself is asserted by TestEffectiveWorkQueryRoutedQueueUsesHybridSortHonoringPriority. a := Agent{Name: "worker", Dir: "hello-world"} got := a.EffectiveWorkQuery() for _, want := range []string{ @@ -2342,19 +2346,19 @@ func TestEffectiveWorkQueryRoutedQueueUsesNativeOldestSortAcrossReadyTiers(t *te }, `#!/bin/sh set -eu case "$*" in - "ready --metadata-field gc.routed_to=hello-world/worker --unassigned --exclude-type=epic --json --sort oldest --limit=20") - printf '[{"id":"older-no-history","priority":2,"created_at":"2026-05-20T06:09:30Z","no_history":true}]' + "ready --metadata-field gc.routed_to=hello-world/worker --unassigned --exclude-type=epic --json --sort hybrid --limit=20") + printf '[{"id":"first-routed","priority":2,"created_at":"2026-05-20T06:09:30Z","no_history":true}]' ;; *) printf '[]' ;; esac `) - if !strings.Contains(out, "older-no-history") { - t.Fatalf("EffectiveWorkQuery() did not pick oldest routed work: %q", out) + if !strings.Contains(out, "first-routed") { + t.Fatalf("EffectiveWorkQuery() did not return bd's first routed row (native hybrid sort): %q", out) } - if strings.Contains(out, "newer-durable") { - t.Fatalf("EffectiveWorkQuery() returned more than first oldest routed work: %q", out) + if strings.Contains(out, "second-routed") { + t.Fatalf("EffectiveWorkQuery() returned more than the first routed row: %q", out) } } @@ -2380,26 +2384,37 @@ func TestGeneratedBdReadCommandsStayBd104StorageCompatible(t *testing.T) { } } -func TestEffectiveWorkQueryRoutedQueueUsesOldestBeforePriority(t *testing.T) { - a := Agent{Name: "worker", Dir: "hello-world"} - out := runEffectiveWorkQuery(t, a, map[string]string{ - "GC_SESSION_ORIGIN": "ephemeral", - }, `#!/bin/sh -set -eu -case "$*" in - *"ready --metadata-field gc.routed_to=hello-world/worker"*"--unassigned"*"--exclude-type=epic"*"--json"*"--sort oldest"*"--limit=20"*) - printf '[{"id":"older-p2","priority":2,"created_at":"2026-05-20T06:09:30Z"}]' - ;; - *) - printf '[]' - ;; -esac -`) - if !strings.Contains(out, "older-p2") { - t.Fatalf("EffectiveWorkQuery() did not pick oldest routed work across priorities: %q", out) +func TestEffectiveWorkQueryRoutedQueueUsesHybridSortHonoringPriority(t *testing.T) { + // ADR-0035 (vc-zv4y): the canonical Tier-3 routed predicate selects bd's + // `hybrid` sort so fresh work (<48h) is ordered by priority — a P1 created + // "now" ranks ahead of an older P2/P3 — while aged work (>=48h) still drains + // oldest-first (anti-starvation preserved). gascity's contract is SELECTING + // hybrid on the routed tier; bd owns the ORDER BY, and the end-to-end rank + // (P1 49 -> 1) is re-measured live post-deploy (ADR-0035 AC 3), which a mock + // bd cannot reproduce. This replaces the former ...UsesOldestBeforePriority + // test, which pinned the priority-blind FIFO this change removes. + mayor := Agent{Name: "mayor"} + cases := []struct { + name string + got string + }{ + {"bd104", mayor.EffectiveWorkQuery()}, + {"bd105", mayor.EffectiveWorkQueryForBeads(BeadsConfig{BDCompatibility: BeadsBDCompatibility105})}, } - if strings.Contains(out, "newer-p0") { - t.Fatalf("EffectiveWorkQuery() returned newer high-priority routed work before oldest: %q", out) + for _, tc := range cases { + // Canonical routed tier honors priority for fresh work via hybrid. + if !strings.Contains(tc.got, `--unassigned --exclude-type=epic --json --sort hybrid --limit=20`) { + t.Errorf("%s: routed tier must select bd --sort hybrid: %q", tc.name, tc.got) + } + // ...and must NOT revert to the priority-blind FIFO on the routed tier. + if strings.Contains(tc.got, `gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort oldest`) { + t.Errorf("%s: routed tier still uses priority-blind --sort oldest: %q", tc.name, tc.got) + } + // The retiring migration probe (ga-dhf44) deliberately stays --sort + // oldest; the fix does not touch workquery.go:54. + if !strings.Contains(tc.got, `gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20`) { + t.Errorf("%s: migration probe must remain --sort oldest (unchanged): %q", tc.name, tc.got) + } } } @@ -2410,7 +2425,7 @@ func TestEffectiveWorkQueryRoutedFallbackUsesNativeOldestSort(t *testing.T) { }, `#!/bin/sh set -eu case "$*" in - *"ready --metadata-field gc.routed_to=hello-world/worker"*"--unassigned"*"--exclude-type=epic"*"--json"*"--sort oldest"*"--limit=20"*) + *"ready --metadata-field gc.routed_to=hello-world/worker"*"--unassigned"*"--exclude-type=epic"*"--json"*"--sort hybrid"*"--limit=20"*) printf '[]' ;; *"ready --metadata-field gc.run_target=hello-world/worker"*"--metadata-field gc.kind=workflow"*"--unassigned"*"--exclude-type=epic"*"--json"*"--sort oldest"*"--limit=20"*) @@ -2821,7 +2836,7 @@ func TestPoolDemandPredicateSharedWithWorkQuery(t *testing.T) { t.Run(tt.name, func(t *testing.T) { wq := tt.agent.EffectiveWorkQuery() demand := tt.agent.EffectivePoolDemandQuery() - workPredicate := bdReadyPoolDemandShell("--sort oldest --limit=20", false) + workPredicate := bdReadyPoolDemandShell("--sort hybrid --limit=20", false) if !strings.Contains(wq, workPredicate) { t.Errorf("EffectiveWorkQuery() missing shared predicate %q in %q", workPredicate, wq) } diff --git a/internal/config/testdata/workquery/legacy_RoutedPool_bd104.golden b/internal/config/testdata/workquery/legacy_RoutedPool_bd104.golden index 609e0c392f..9aaa3b89a8 100644 --- a/internal/config/testdata/workquery/legacy_RoutedPool_bd104.golden +++ b/internal/config/testdata/workquery/legacy_RoutedPool_bd104.golden @@ -1 +1 @@ -sh -c 'case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$({ bd query --json '\''ephemeral=true AND status=open'\'' --limit=0 2>/dev/null | jq --arg target "$target" '\''[.[] | select((.assignee // "") == "") | select(((.metadata["gc.routed_to"] // "") == $target) or (((.metadata["gc.routed_to"] // "") == "") and ((.metadata["gc.run_target"] // "") == $target) and ((.metadata["gc.kind"] // "") == "workflow"))) | select(((.issue_type // .type // "") != "epic")) | select(([ (.dependencies // [])[] | select((.type // .dep_type // "") as $t | ($t == "blocks" or $t == "waits-for" or $t == "conditional-blocks")) | select((.status // .depends_on_status // "") != "closed") ] | length) == 0)] | sort_by(.created_at // "") | .[:20]'\'' 2>/dev/null; } || printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; probe_pool_demand "$2"; printf "[]"' -- rig/control-dispatcher rig/workflow-control \ No newline at end of file +sh -c 'case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort hybrid --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$({ bd query --json '\''ephemeral=true AND status=open'\'' --limit=0 2>/dev/null | jq --arg target "$target" '\''[.[] | select((.assignee // "") == "") | select(((.metadata["gc.routed_to"] // "") == $target) or (((.metadata["gc.routed_to"] // "") == "") and ((.metadata["gc.run_target"] // "") == $target) and ((.metadata["gc.kind"] // "") == "workflow"))) | select(((.issue_type // .type // "") != "epic")) | select(([ (.dependencies // [])[] | select((.type // .dep_type // "") as $t | ($t == "blocks" or $t == "waits-for" or $t == "conditional-blocks")) | select((.status // .depends_on_status // "") != "closed") ] | length) == 0)] | sort_by(.created_at // "") | .[:20]'\'' 2>/dev/null; } || printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; probe_pool_demand "$2"; printf "[]"' -- rig/control-dispatcher rig/workflow-control \ No newline at end of file diff --git a/internal/config/testdata/workquery/legacy_RoutedPool_bd105.golden b/internal/config/testdata/workquery/legacy_RoutedPool_bd105.golden index 878bb63f9b..1209aee0cd 100644 --- a/internal/config/testdata/workquery/legacy_RoutedPool_bd105.golden +++ b/internal/config/testdata/workquery/legacy_RoutedPool_bd105.golden @@ -1 +1 @@ -sh -c 'case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --include-ephemeral --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --include-ephemeral --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$(printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; probe_pool_demand "$2"; printf "[]"' -- rig/control-dispatcher rig/workflow-control \ No newline at end of file +sh -c 'case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --include-ephemeral --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort hybrid --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --include-ephemeral --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$(printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; probe_pool_demand "$2"; printf "[]"' -- rig/control-dispatcher rig/workflow-control \ No newline at end of file diff --git a/internal/config/testdata/workquery/legacy_Work_bd104.golden b/internal/config/testdata/workquery/legacy_Work_bd104.golden index 4503cfefda..d7ce7991c4 100644 --- a/internal/config/testdata/workquery/legacy_Work_bd104.golden +++ b/internal/config/testdata/workquery/legacy_Work_bd104.golden @@ -1 +1 @@ -sh -c 'for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; legacy=""; case "$id" in *control-dispatcher) legacy="${id%control-dispatcher}workflow-control";; esac; for cand in "$id" "$legacy"; do [ -z "$cand" ] && continue; r=$(bd list --status in_progress --assignee="$cand" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; r=$(bd query --json '\''ephemeral=true AND status=in_progress'\'' --limit=0 2>/dev/null | jq --arg id "$cand" '\''[.[] | select((.assignee // "") == $id)] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; done; for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; legacy=""; case "$id" in *control-dispatcher) legacy="${id%control-dispatcher}workflow-control";; esac; for cand in "$id" "$legacy"; do [ -z "$cand" ] && continue; r=$(bd ready --assignee="$cand" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; r=$(bd query --json '\''ephemeral=true AND status=open'\'' --limit=0 2>/dev/null | jq --arg id "$cand" '\''[.[] | select((.assignee // "") == $id) | select(((.issue_type // .type // "") != "epic")) | select(([ (.dependencies // [])[] | select((.type // .dep_type // "") as $t | ($t == "blocks" or $t == "waits-for" or $t == "conditional-blocks")) | select((.status // .depends_on_status // "") != "closed") ] | length) == 0)] | sort_by(.created_at // "") | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; done; case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$({ bd query --json '\''ephemeral=true AND status=open'\'' --limit=0 2>/dev/null | jq --arg target "$target" '\''[.[] | select((.assignee // "") == "") | select(((.metadata["gc.routed_to"] // "") == $target) or (((.metadata["gc.routed_to"] // "") == "") and ((.metadata["gc.run_target"] // "") == $target) and ((.metadata["gc.kind"] // "") == "workflow"))) | select(((.issue_type // .type // "") != "epic")) | select(([ (.dependencies // [])[] | select((.type // .dep_type // "") as $t | ($t == "blocks" or $t == "waits-for" or $t == "conditional-blocks")) | select((.status // .depends_on_status // "") != "closed") ] | length) == 0)] | sort_by(.created_at // "") | .[:20]'\'' 2>/dev/null; } || printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; probe_pool_demand "$2"; printf "[]"' -- rig/control-dispatcher rig/workflow-control \ No newline at end of file +sh -c 'for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; legacy=""; case "$id" in *control-dispatcher) legacy="${id%control-dispatcher}workflow-control";; esac; for cand in "$id" "$legacy"; do [ -z "$cand" ] && continue; r=$(bd list --status in_progress --assignee="$cand" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; r=$(bd query --json '\''ephemeral=true AND status=in_progress'\'' --limit=0 2>/dev/null | jq --arg id "$cand" '\''[.[] | select((.assignee // "") == $id)] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; done; for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; legacy=""; case "$id" in *control-dispatcher) legacy="${id%control-dispatcher}workflow-control";; esac; for cand in "$id" "$legacy"; do [ -z "$cand" ] && continue; r=$(bd ready --assignee="$cand" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; r=$(bd query --json '\''ephemeral=true AND status=open'\'' --limit=0 2>/dev/null | jq --arg id "$cand" '\''[.[] | select((.assignee // "") == $id) | select(((.issue_type // .type // "") != "epic")) | select(([ (.dependencies // [])[] | select((.type // .dep_type // "") as $t | ($t == "blocks" or $t == "waits-for" or $t == "conditional-blocks")) | select((.status // .depends_on_status // "") != "closed") ] | length) == 0)] | sort_by(.created_at // "") | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; done; case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort hybrid --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$({ bd query --json '\''ephemeral=true AND status=open'\'' --limit=0 2>/dev/null | jq --arg target "$target" '\''[.[] | select((.assignee // "") == "") | select(((.metadata["gc.routed_to"] // "") == $target) or (((.metadata["gc.routed_to"] // "") == "") and ((.metadata["gc.run_target"] // "") == $target) and ((.metadata["gc.kind"] // "") == "workflow"))) | select(((.issue_type // .type // "") != "epic")) | select(([ (.dependencies // [])[] | select((.type // .dep_type // "") as $t | ($t == "blocks" or $t == "waits-for" or $t == "conditional-blocks")) | select((.status // .depends_on_status // "") != "closed") ] | length) == 0)] | sort_by(.created_at // "") | .[:20]'\'' 2>/dev/null; } || printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; probe_pool_demand "$2"; printf "[]"' -- rig/control-dispatcher rig/workflow-control \ No newline at end of file diff --git a/internal/config/testdata/workquery/legacy_Work_bd105.golden b/internal/config/testdata/workquery/legacy_Work_bd105.golden index e964e14562..feb8e9a1be 100644 --- a/internal/config/testdata/workquery/legacy_Work_bd105.golden +++ b/internal/config/testdata/workquery/legacy_Work_bd105.golden @@ -1 +1 @@ -sh -c 'for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; legacy=""; case "$id" in *control-dispatcher) legacy="${id%control-dispatcher}workflow-control";; esac; for cand in "$id" "$legacy"; do [ -z "$cand" ] && continue; r=$(bd list --status in_progress --assignee="$cand" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; r=$(bd query --json '\''ephemeral=true AND status=in_progress'\'' --limit=0 2>/dev/null | jq --arg id "$cand" '\''[.[] | select((.assignee // "") == $id)] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; done; for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; legacy=""; case "$id" in *control-dispatcher) legacy="${id%control-dispatcher}workflow-control";; esac; for cand in "$id" "$legacy"; do [ -z "$cand" ] && continue; r=$(bd ready --include-ephemeral --assignee="$cand" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; done; case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --include-ephemeral --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --include-ephemeral --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$(printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; probe_pool_demand "$2"; printf "[]"' -- rig/control-dispatcher rig/workflow-control \ No newline at end of file +sh -c 'for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; legacy=""; case "$id" in *control-dispatcher) legacy="${id%control-dispatcher}workflow-control";; esac; for cand in "$id" "$legacy"; do [ -z "$cand" ] && continue; r=$(bd list --status in_progress --assignee="$cand" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; r=$(bd query --json '\''ephemeral=true AND status=in_progress'\'' --limit=0 2>/dev/null | jq --arg id "$cand" '\''[.[] | select((.assignee // "") == $id)] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; done; for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; legacy=""; case "$id" in *control-dispatcher) legacy="${id%control-dispatcher}workflow-control";; esac; for cand in "$id" "$legacy"; do [ -z "$cand" ] && continue; r=$(bd ready --include-ephemeral --assignee="$cand" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; done; case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --include-ephemeral --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort hybrid --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --include-ephemeral --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$(printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; probe_pool_demand "$2"; printf "[]"' -- rig/control-dispatcher rig/workflow-control \ No newline at end of file diff --git a/internal/config/testdata/workquery/normal_RoutedPool_bd104.golden b/internal/config/testdata/workquery/normal_RoutedPool_bd104.golden index 677340ce24..92ebb16d73 100644 --- a/internal/config/testdata/workquery/normal_RoutedPool_bd104.golden +++ b/internal/config/testdata/workquery/normal_RoutedPool_bd104.golden @@ -1 +1 @@ -sh -c 'case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$({ bd query --json '\''ephemeral=true AND status=open'\'' --limit=0 2>/dev/null | jq --arg target "$target" '\''[.[] | select((.assignee // "") == "") | select(((.metadata["gc.routed_to"] // "") == $target) or (((.metadata["gc.routed_to"] // "") == "") and ((.metadata["gc.run_target"] // "") == $target) and ((.metadata["gc.kind"] // "") == "workflow"))) | select(((.issue_type // .type // "") != "epic")) | select(([ (.dependencies // [])[] | select((.type // .dep_type // "") as $t | ($t == "blocks" or $t == "waits-for" or $t == "conditional-blocks")) | select((.status // .depends_on_status // "") != "closed") ] | length) == 0)] | sort_by(.created_at // "") | .[:20]'\'' 2>/dev/null; } || printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; printf "[]"' -- worker \ No newline at end of file +sh -c 'case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort hybrid --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$({ bd query --json '\''ephemeral=true AND status=open'\'' --limit=0 2>/dev/null | jq --arg target "$target" '\''[.[] | select((.assignee // "") == "") | select(((.metadata["gc.routed_to"] // "") == $target) or (((.metadata["gc.routed_to"] // "") == "") and ((.metadata["gc.run_target"] // "") == $target) and ((.metadata["gc.kind"] // "") == "workflow"))) | select(((.issue_type // .type // "") != "epic")) | select(([ (.dependencies // [])[] | select((.type // .dep_type // "") as $t | ($t == "blocks" or $t == "waits-for" or $t == "conditional-blocks")) | select((.status // .depends_on_status // "") != "closed") ] | length) == 0)] | sort_by(.created_at // "") | .[:20]'\'' 2>/dev/null; } || printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; printf "[]"' -- worker \ No newline at end of file diff --git a/internal/config/testdata/workquery/normal_RoutedPool_bd105.golden b/internal/config/testdata/workquery/normal_RoutedPool_bd105.golden index 013cf36483..0bf9eaed44 100644 --- a/internal/config/testdata/workquery/normal_RoutedPool_bd105.golden +++ b/internal/config/testdata/workquery/normal_RoutedPool_bd105.golden @@ -1 +1 @@ -sh -c 'case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --include-ephemeral --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --include-ephemeral --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$(printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; printf "[]"' -- worker \ No newline at end of file +sh -c 'case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --include-ephemeral --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort hybrid --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --include-ephemeral --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$(printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; printf "[]"' -- worker \ No newline at end of file diff --git a/internal/config/testdata/workquery/normal_Work_bd104.golden b/internal/config/testdata/workquery/normal_Work_bd104.golden index 80ff645607..5c34c06552 100644 --- a/internal/config/testdata/workquery/normal_Work_bd104.golden +++ b/internal/config/testdata/workquery/normal_Work_bd104.golden @@ -1 +1 @@ -sh -c 'for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; r=$(bd list --status in_progress --assignee="$id" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; r=$(bd query --json '\''ephemeral=true AND status=in_progress'\'' --limit=0 2>/dev/null | jq --arg id "$id" '\''[.[] | select((.assignee // "") == $id)] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; r=$(bd ready --assignee="$id" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; r=$(bd query --json '\''ephemeral=true AND status=open'\'' --limit=0 2>/dev/null | jq --arg id "$id" '\''[.[] | select((.assignee // "") == $id) | select(((.issue_type // .type // "") != "epic")) | select(([ (.dependencies // [])[] | select((.type // .dep_type // "") as $t | ($t == "blocks" or $t == "waits-for" or $t == "conditional-blocks")) | select((.status // .depends_on_status // "") != "closed") ] | length) == 0)] | sort_by(.created_at // "") | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$({ bd query --json '\''ephemeral=true AND status=open'\'' --limit=0 2>/dev/null | jq --arg target "$target" '\''[.[] | select((.assignee // "") == "") | select(((.metadata["gc.routed_to"] // "") == $target) or (((.metadata["gc.routed_to"] // "") == "") and ((.metadata["gc.run_target"] // "") == $target) and ((.metadata["gc.kind"] // "") == "workflow"))) | select(((.issue_type // .type // "") != "epic")) | select(([ (.dependencies // [])[] | select((.type // .dep_type // "") as $t | ($t == "blocks" or $t == "waits-for" or $t == "conditional-blocks")) | select((.status // .depends_on_status // "") != "closed") ] | length) == 0)] | sort_by(.created_at // "") | .[:20]'\'' 2>/dev/null; } || printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; printf "[]"' -- worker \ No newline at end of file +sh -c 'for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; r=$(bd list --status in_progress --assignee="$id" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; r=$(bd query --json '\''ephemeral=true AND status=in_progress'\'' --limit=0 2>/dev/null | jq --arg id "$id" '\''[.[] | select((.assignee // "") == $id)] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; r=$(bd ready --assignee="$id" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; r=$(bd query --json '\''ephemeral=true AND status=open'\'' --limit=0 2>/dev/null | jq --arg id "$id" '\''[.[] | select((.assignee // "") == $id) | select(((.issue_type // .type // "") != "epic")) | select(([ (.dependencies // [])[] | select((.type // .dep_type // "") as $t | ($t == "blocks" or $t == "waits-for" or $t == "conditional-blocks")) | select((.status // .depends_on_status // "") != "closed") ] | length) == 0)] | sort_by(.created_at // "") | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort hybrid --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$({ bd query --json '\''ephemeral=true AND status=open'\'' --limit=0 2>/dev/null | jq --arg target "$target" '\''[.[] | select((.assignee // "") == "") | select(((.metadata["gc.routed_to"] // "") == $target) or (((.metadata["gc.routed_to"] // "") == "") and ((.metadata["gc.run_target"] // "") == $target) and ((.metadata["gc.kind"] // "") == "workflow"))) | select(((.issue_type // .type // "") != "epic")) | select(([ (.dependencies // [])[] | select((.type // .dep_type // "") as $t | ($t == "blocks" or $t == "waits-for" or $t == "conditional-blocks")) | select((.status // .depends_on_status // "") != "closed") ] | length) == 0)] | sort_by(.created_at // "") | .[:20]'\'' 2>/dev/null; } || printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; printf "[]"' -- worker \ No newline at end of file diff --git a/internal/config/testdata/workquery/normal_Work_bd105.golden b/internal/config/testdata/workquery/normal_Work_bd105.golden index 12f10e1769..2d1c4f72f7 100644 --- a/internal/config/testdata/workquery/normal_Work_bd105.golden +++ b/internal/config/testdata/workquery/normal_Work_bd105.golden @@ -1 +1 @@ -sh -c 'for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; r=$(bd list --status in_progress --assignee="$id" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; r=$(bd query --json '\''ephemeral=true AND status=in_progress'\'' --limit=0 2>/dev/null | jq --arg id "$id" '\''[.[] | select((.assignee // "") == $id)] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; r=$(bd ready --include-ephemeral --assignee="$id" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --include-ephemeral --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --include-ephemeral --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$(printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; printf "[]"' -- worker \ No newline at end of file +sh -c 'for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; r=$(bd list --status in_progress --assignee="$id" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; r=$(bd query --json '\''ephemeral=true AND status=in_progress'\'' --limit=0 2>/dev/null | jq --arg id "$id" '\''[.[] | select((.assignee // "") == $id)] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; r=$(bd ready --include-ephemeral --assignee="$id" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --include-ephemeral --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort hybrid --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --include-ephemeral --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$(printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; printf "[]"' -- worker \ No newline at end of file diff --git a/internal/config/testdata/workquery/pool_RoutedPool_bd104.golden b/internal/config/testdata/workquery/pool_RoutedPool_bd104.golden index e19015055e..7624248fdf 100644 --- a/internal/config/testdata/workquery/pool_RoutedPool_bd104.golden +++ b/internal/config/testdata/workquery/pool_RoutedPool_bd104.golden @@ -1 +1 @@ -sh -c 'case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$({ bd query --json '\''ephemeral=true AND status=open'\'' --limit=0 2>/dev/null | jq --arg target "$target" '\''[.[] | select((.assignee // "") == "") | select(((.metadata["gc.routed_to"] // "") == $target) or (((.metadata["gc.routed_to"] // "") == "") and ((.metadata["gc.run_target"] // "") == $target) and ((.metadata["gc.kind"] // "") == "workflow"))) | select(((.issue_type // .type // "") != "epic")) | select(([ (.dependencies // [])[] | select((.type // .dep_type // "") as $t | ($t == "blocks" or $t == "waits-for" or $t == "conditional-blocks")) | select((.status // .depends_on_status // "") != "closed") ] | length) == 0)] | sort_by(.created_at // "") | .[:20]'\'' 2>/dev/null; } || printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; printf "[]"' -- worker-pool \ No newline at end of file +sh -c 'case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort hybrid --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$({ bd query --json '\''ephemeral=true AND status=open'\'' --limit=0 2>/dev/null | jq --arg target "$target" '\''[.[] | select((.assignee // "") == "") | select(((.metadata["gc.routed_to"] // "") == $target) or (((.metadata["gc.routed_to"] // "") == "") and ((.metadata["gc.run_target"] // "") == $target) and ((.metadata["gc.kind"] // "") == "workflow"))) | select(((.issue_type // .type // "") != "epic")) | select(([ (.dependencies // [])[] | select((.type // .dep_type // "") as $t | ($t == "blocks" or $t == "waits-for" or $t == "conditional-blocks")) | select((.status // .depends_on_status // "") != "closed") ] | length) == 0)] | sort_by(.created_at // "") | .[:20]'\'' 2>/dev/null; } || printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; printf "[]"' -- worker-pool \ No newline at end of file diff --git a/internal/config/testdata/workquery/pool_RoutedPool_bd105.golden b/internal/config/testdata/workquery/pool_RoutedPool_bd105.golden index cee51ba3b9..1ef332e796 100644 --- a/internal/config/testdata/workquery/pool_RoutedPool_bd105.golden +++ b/internal/config/testdata/workquery/pool_RoutedPool_bd105.golden @@ -1 +1 @@ -sh -c 'case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --include-ephemeral --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --include-ephemeral --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$(printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; printf "[]"' -- worker-pool \ No newline at end of file +sh -c 'case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --include-ephemeral --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort hybrid --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --include-ephemeral --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$(printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; printf "[]"' -- worker-pool \ No newline at end of file diff --git a/internal/config/testdata/workquery/pool_Work_bd104.golden b/internal/config/testdata/workquery/pool_Work_bd104.golden index 6c5b3e64b8..168ce473b4 100644 --- a/internal/config/testdata/workquery/pool_Work_bd104.golden +++ b/internal/config/testdata/workquery/pool_Work_bd104.golden @@ -1 +1 @@ -sh -c 'for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; r=$(bd list --status in_progress --assignee="$id" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; r=$(bd query --json '\''ephemeral=true AND status=in_progress'\'' --limit=0 2>/dev/null | jq --arg id "$id" '\''[.[] | select((.assignee // "") == $id)] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; r=$(bd ready --assignee="$id" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; r=$(bd query --json '\''ephemeral=true AND status=open'\'' --limit=0 2>/dev/null | jq --arg id "$id" '\''[.[] | select((.assignee // "") == $id) | select(((.issue_type // .type // "") != "epic")) | select(([ (.dependencies // [])[] | select((.type // .dep_type // "") as $t | ($t == "blocks" or $t == "waits-for" or $t == "conditional-blocks")) | select((.status // .depends_on_status // "") != "closed") ] | length) == 0)] | sort_by(.created_at // "") | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$({ bd query --json '\''ephemeral=true AND status=open'\'' --limit=0 2>/dev/null | jq --arg target "$target" '\''[.[] | select((.assignee // "") == "") | select(((.metadata["gc.routed_to"] // "") == $target) or (((.metadata["gc.routed_to"] // "") == "") and ((.metadata["gc.run_target"] // "") == $target) and ((.metadata["gc.kind"] // "") == "workflow"))) | select(((.issue_type // .type // "") != "epic")) | select(([ (.dependencies // [])[] | select((.type // .dep_type // "") as $t | ($t == "blocks" or $t == "waits-for" or $t == "conditional-blocks")) | select((.status // .depends_on_status // "") != "closed") ] | length) == 0)] | sort_by(.created_at // "") | .[:20]'\'' 2>/dev/null; } || printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; printf "[]"' -- worker-pool \ No newline at end of file +sh -c 'for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; r=$(bd list --status in_progress --assignee="$id" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; r=$(bd query --json '\''ephemeral=true AND status=in_progress'\'' --limit=0 2>/dev/null | jq --arg id "$id" '\''[.[] | select((.assignee // "") == $id)] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; r=$(bd ready --assignee="$id" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; r=$(bd query --json '\''ephemeral=true AND status=open'\'' --limit=0 2>/dev/null | jq --arg id "$id" '\''[.[] | select((.assignee // "") == $id) | select(((.issue_type // .type // "") != "epic")) | select(([ (.dependencies // [])[] | select((.type // .dep_type // "") as $t | ($t == "blocks" or $t == "waits-for" or $t == "conditional-blocks")) | select((.status // .depends_on_status // "") != "closed") ] | length) == 0)] | sort_by(.created_at // "") | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort hybrid --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$({ bd query --json '\''ephemeral=true AND status=open'\'' --limit=0 2>/dev/null | jq --arg target "$target" '\''[.[] | select((.assignee // "") == "") | select(((.metadata["gc.routed_to"] // "") == $target) or (((.metadata["gc.routed_to"] // "") == "") and ((.metadata["gc.run_target"] // "") == $target) and ((.metadata["gc.kind"] // "") == "workflow"))) | select(((.issue_type // .type // "") != "epic")) | select(([ (.dependencies // [])[] | select((.type // .dep_type // "") as $t | ($t == "blocks" or $t == "waits-for" or $t == "conditional-blocks")) | select((.status // .depends_on_status // "") != "closed") ] | length) == 0)] | sort_by(.created_at // "") | .[:20]'\'' 2>/dev/null; } || printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; printf "[]"' -- worker-pool \ No newline at end of file diff --git a/internal/config/testdata/workquery/pool_Work_bd105.golden b/internal/config/testdata/workquery/pool_Work_bd105.golden index cd56002718..1eb55ca1c5 100644 --- a/internal/config/testdata/workquery/pool_Work_bd105.golden +++ b/internal/config/testdata/workquery/pool_Work_bd105.golden @@ -1 +1 @@ -sh -c 'for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; r=$(bd list --status in_progress --assignee="$id" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; r=$(bd query --json '\''ephemeral=true AND status=in_progress'\'' --limit=0 2>/dev/null | jq --arg id "$id" '\''[.[] | select((.assignee // "") == $id)] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; r=$(bd ready --include-ephemeral --assignee="$id" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --include-ephemeral --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --include-ephemeral --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$(printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; printf "[]"' -- worker-pool \ No newline at end of file +sh -c 'for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; r=$(bd list --status in_progress --assignee="$id" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; r=$(bd query --json '\''ephemeral=true AND status=in_progress'\'' --limit=0 2>/dev/null | jq --arg id "$id" '\''[.[] | select((.assignee // "") == $id)] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; for id in "$GC_SESSION_ID" "$GC_SESSION_NAME" "$GC_ALIAS"; do [ -z "$id" ] && continue; r=$(bd ready --include-ephemeral --assignee="$id" --json --limit=1 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; done; case "$GC_SESSION_ORIGIN" in ephemeral|"") ;; *) exit 0 ;; esac; probe_pool_demand() { target="$1"; [ -z "$target" ] && return 1; r=$(bd ready --include-ephemeral --metadata-field "gc.routed_to=$target" --unassigned --exclude-type=epic --json --sort hybrid --limit=20 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_candidates=$(bd ready --include-ephemeral --metadata-field "gc.run_target=$target" --metadata-field "gc.kind=workflow" --unassigned --exclude-type=epic --json --sort oldest --limit=20 2>/dev/null); r=$(printf "%s" "$legacy_candidates" | jq '\''[.[] | select((.metadata["gc.routed_to"] // "") == "")] | .[:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; legacy_ephemeral_candidates=$(printf "[]"); r=$(printf "%s" "$legacy_ephemeral_candidates" | jq '\''.[0:1]'\'' 2>/dev/null); [ -n "$r" ] && [ "$r" != "[]" ] && printf "%s" "$r" && exit 0; return 1; }; probe_pool_demand "$1"; printf "[]"' -- worker-pool \ No newline at end of file diff --git a/internal/config/workquery.go b/internal/config/workquery.go index b29226067a..e06a92db41 100644 --- a/internal/config/workquery.go +++ b/internal/config/workquery.go @@ -124,13 +124,26 @@ func poolDemandFirstRowFunctionScript(includeEphemeralReady bool) string { } func routedReadyTierCommand(includeEphemeralReady bool) string { - // The shared predicate stays order-free so the count-form does no wasted - // sorting; the worker first-row path asks bd for the oldest candidates. + // Pool dispatch ordering policy (ADR-0035, vc-zv4y). The worker first-row + // path asks bd for candidates under `--sort hybrid`, so routed pool work + // honors bead priority for fresh work (< 48h: by P-level) while still + // draining aged work (>= 48h: strictly oldest-first). This keeps the + // age-based anti-starvation property that the prior `--sort oldest` was + // chosen for AND stops a fresh P1 from starving behind an older P2/P3 — + // under `oldest`, priority was decorative for the pool tier. hybrid's + // 48h seam is a bd 1.1.0 constant (internal/storage/sqlbuild/ready.go). + // + // The count-form predicate (poolDemandCountShell) deliberately passes no + // --sort — order is irrelevant to a length — so this ordering change does + // NOT perturb the reconciler's spawn decision; the two paths still share + // the same demand predicate shape. + // // The tier is widened past a single row (limit=20, not limit=1) so a // self-blocked head (is_blocked / status==blocked) has Ready routed work // behind it to fall through to instead of idle-exiting; the hook layer // (filterUnreadyHookCandidates) strips the blocked head from the result. - return bdReadyPoolDemandShell("--sort oldest --limit=20", includeEphemeralReady) + ` 2>/dev/null` + // --limit=20 is an anti-self-block lookahead, NOT a priority window. + return bdReadyPoolDemandShell("--sort hybrid --limit=20", includeEphemeralReady) + ` 2>/dev/null` } // poolDemandCountShell emits the reconciler count-form for target: it counts