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, #404clear(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.
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).
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>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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)
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 livein-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)
GET /issues/{n}/dependencieson every candidate; any OPEN blocker → skipped (printsskip #395: blocked-by open #381)..milestone.state=="open"/review/priority:filters (never the server?milestones=name filter).(tier, priority high>med>low, issue#).in-progress,parked, PRs.What stays judgment (the script flags, doesn't decide)
CLAIM?— a claim can precede thein-progresslabel; flags candidates whose recent comments look like a live claim.UMBRELLA?— flags bodies opening with epic/umbrella framing (computed in the jq pass).Verification
clear(was #388), #395 correctly skipped as blocked-by open #381).UMBRELLA?fires on #383 not #350;CLAIM?distinguishes claim language from normal comments.shellcheckclean. ~1.3s.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).