feat(queue): deterministic select-queue.sh — stop re-deriving the selector by hand #461

Merged
timothy merged 1 commits from feat/select-queue-script into main 2026-07-19 10:46:19 +02:00
Owner

What

Adds scripts/select-queue.sh — a deterministic queue selector for the #237 pickup protocol — and rewires the handoff to run it instead of re-deriving the selector's mechanical claims by hand.

Why (operator-requested this session)

"rather than have the 'lore' make us do all the work the selector already did all over again, why don't we just improve the selector?"

The kickoff dispatches a cheap model to rank the backlog; the lore then makes the orchestrator re-derive its output because a small model repeatedly got the mechanical parts wrong — reported blocked issues as deps:clear, mis-tiered on the no-op ?milestones= filter, ranked by issue number instead of priority-within-tier, missed live in-progress. Re-deriving all of that every session is the tax. The fix is to stop asking a model to do arithmetic.

What's deterministic now (trust it, don't re-derive)

  • Dependency exclusion — GET /issues/{n}/dependencies on every candidate; any OPEN blocker → skipped (prints skip #395: blocked-by open #381).
  • Tiering — LOCAL .milestone.state=="open" / review / priority: filters (never the server ?milestones= name filter).
  • Ordering — (tier, priority high>med>low, issue#).
  • Exclusions — in-progress, parked, PRs.

What stays judgment (the script flags, doesn't decide)

  • CLAIM? — a claim can precede the in-progress label; flags candidates whose recent comments look like a live claim.
  • UMBRELLA? — flags bodies opening with epic/umbrella framing (computed in the jq pass).
  • Arc tier — arc order is #237 prose (currently CLOSED), not label-derivable; script deliberately doesn't rank it.

Verification

  • Reproduces this session's hand-verified state exactly (#350 top, #404 clear(was #388), #395 correctly skipped as blocked-by open #381).
  • Non-vacuity: UMBRELLA? fires on #383 not #350; CLAIM? distinguishes claim language from normal comments.
  • Fail-open on no-creds / unreachable / bad-creds (exit 0, no-op). shellcheck clean. ~1.3s.
  • Handoff lore: the three "cheap selector unreliable" bullets kept as the evidence for the script; prescription redirected to "run the script."

Review scope

Docs + tooling leaf, no server-state effect → independent adversarial review skipped per the skip rubric (stated exemption). No /api, SPA, migration, or decisions.md change (workflow lore lives in the handoff, not decisions.md).

## What Adds `scripts/select-queue.sh` — a deterministic queue selector for the #237 pickup protocol — and rewires the handoff to run it instead of re-deriving the selector's mechanical claims by hand. ## Why (operator-requested this session) > "rather than have the 'lore' make us do all the work the selector already did all over again, why don't we just improve the selector?" The kickoff dispatches a cheap model to rank the backlog; the lore then makes the orchestrator **re-derive** its output because a small model repeatedly got the *mechanical* parts wrong — reported blocked issues as `deps:clear`, mis-tiered on the no-op `?milestones=` filter, ranked by issue number instead of priority-within-tier, missed live `in-progress`. Re-deriving all of that every session is the tax. The fix is to stop asking a model to do arithmetic. ## What's deterministic now (trust it, don't re-derive) - **Dependency exclusion** — `GET /issues/{n}/dependencies` on every candidate; any OPEN blocker → skipped (prints `skip #395: blocked-by open #381`). - **Tiering** — LOCAL `.milestone.state=="open"` / `review` / `priority:` filters (never the server `?milestones=` name filter). - **Ordering** — `(tier, priority high>med>low, issue#)`. - **Exclusions** — `in-progress`, `parked`, PRs. ## What stays judgment (the script *flags*, doesn't decide) - `CLAIM?` — a claim can precede the `in-progress` label; flags candidates whose recent comments look like a live claim. - `UMBRELLA?` — flags bodies opening with epic/umbrella framing (computed in the jq pass). - **Arc tier** — arc order is #237 prose (currently CLOSED), not label-derivable; script deliberately doesn't rank it. ## Verification - Reproduces this session's hand-verified state exactly (#350 top, #404 `clear(was #388)`, #395 correctly skipped as blocked-by open #381). - Non-vacuity: `UMBRELLA?` fires on #383 not #350; `CLAIM?` distinguishes claim language from normal comments. - Fail-open on no-creds / unreachable / bad-creds (exit 0, no-op). `shellcheck` clean. ~1.3s. - Handoff lore: the three "cheap selector unreliable" bullets kept as the **evidence** for the script; prescription redirected to "run the script." ## Review scope Docs + tooling leaf, no server-state effect → independent adversarial review **skipped per the skip rubric** (stated exemption). No `/api`, SPA, migration, or decisions.md change (workflow lore lives in the handoff, not decisions.md).
timothy added 1 commit 2026-07-19 01:10:22 +02:00
feat(queue): deterministic scripts/select-queue.sh — stop re-deriving the selector by hand
Build ErsatzTV Image / CI image pin matches docker/ci (pull_request) Successful in 7s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 9s
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 10s
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 16s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 1m23s
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 14m52s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 18m23s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 18m48s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
708e602197
The kickoff dispatches a cheap model to rank the backlog, and the lore then made the
orchestrator re-derive its mechanical claims (deps, milestone tiering, priority order,
in-progress state) because a small model kept getting them wrong. This pays that tax down:
the mechanical checks are now CODE — GET /dependencies exclusion, LOCAL
.milestone.state/review/priority tiering (never the no-op ?milestones= filter),
(tier,priority,issue#) ordering, in-progress/parked/PR exclusion — leaving only two
JUDGMENT flags (CLAIM?, UMBRELLA?) for a human/model to resolve.

- scripts/select-queue.sh: fail-open on no-creds/unreachable; ~1.3s; shellcheck clean;
  UMBRELLA? computed in the jq pass (no per-candidate body fetch).
- handoff kickoff: run the script FIRST; trust its deps/tiering/ordering, recheck only flags.
- handoff lore: the three 'cheap selector unreliable → re-derive by hand' bullets kept as the
  EVIDENCE for why the script exists; the prescription is redirected to 'run the script'.

Operator-requested this session: 'rather than have the lore make us redo the selector's work,
improve the selector.'

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
timothy merged commit 996c545161 into main 2026-07-19 10:46:19 +02:00
Sign in to join this conversation.