diff --git a/docs/handoffs/chicorytv-issue-queue.md b/docs/handoffs/chicorytv-issue-queue.md index 191f19c1a..dcf1ef5cc 100644 --- a/docs/handoffs/chicorytv-issue-queue.md +++ b/docs/handoffs/chicorytv-issue-queue.md @@ -32,12 +32,32 @@ Everything else (claiming, worktrees, dispatching implementers, CI monitoring, p bookkeeping, routine merges of green reviewed PRs with user consent) stays at your level. Then work the queue: -1. Read the pinned tracker **ersatztv#237** — body = goal + ordered arc + session protocol — - and its most recent session comments; list open issues in the `Blazor removal (#91 phase b)` - milestone and with the `review` label; ALSO list open `ersatztv`-labeled issues in - **timothy/adversarial-reviewer** — unclaimed audits there are pickup candidates too - (read-only, parallel-safe; see the tracker's "Pending adversarial reviews" section). -2. Pick the top arc item that is open and NOT labeled `in-progress` (or the item the user names). +1. Read the pinned tracker **ersatztv#237** — body = goal + ordered arc + session protocol — and + its **last ~6 session comments** (newest-first; the full comment payload is large, so stop at ~6). + **SOURCE OF TRUTH = live Gitea issue state, NEVER the prose.** The arc body carries ORDER + goal + only; a session comment's "Recommended next" is a forward *guess* written before the next session + acted. Both go stale the instant an item closes (especially under parallel sessions narrating each + other's work as "the gate that unblocks X"). So derive the candidate set from LIVE state, not from + any inline marker or a prior comment's "next": the **current gate = the lowest-numbered OPEN arc + item in #237's arc list**; its open children are the gate cluster (query them by the `review` + label). Cross-check every arc / "recommended" item's real open/closed state (issue **and** + milestone) before trusting it — do NOT hardcode which issue is the frontier; read it. ALSO list + open `ersatztv`-labeled issues in **timothy/adversarial-reviewer** — unclaimed audits there are + pickup candidates too (read-only, parallel-safe; see the tracker's "Pending adversarial reviews" + section). If the Gitea MCP is down, hit the REST API directly (creds in your global CLAUDE.md): + `curl -u : http://192.168.1.95:3000/api/v1/repos/timothy/ersatztv/issues/237`. + **The authoritative pickup + ranking protocol lives in #237's "Session protocol" section — this is a summary; if the two ever disagree, #237 wins.** +2. Pick the highest-ranked OPEN, un-`in-progress` candidate (or the item the user names). **Rank by + labels, not just arc position** (labels are live state; prose is not): (1) arc order in #237, then + (2) **gate vs backlog** — an item marked gate by the `review` label OR membership in an open gate + milestone outranks anything unmilestoned; then (3) **`priority:`** label — `high` > `medium` > + `low` within a tier. Pick order across the three pools: the **arc frontier** (lowest-numbered open + arc item) first; an unclaimed Blocker/High **priority-pickup** (`review` + `priority: high`, e.g. + #253) beats a *non-frontier* arc item; reviewer-repo **audits** are read-only and run in parallel. + **Confirm the pick is genuinely OPEN in Gitea first.** If the prose says "recommended next / now + unblocked" but the issue (or its milestone) is already CLOSED, it is done — skip it and fix the + stale line in your session comment. Prose lags live state; live state wins; milestone + `priority:` + labels decide gate-vs-backlog, not the prose. (This mirrors #237's Session-protocol ranking — #237 is canonical.) 3. **Claim it**: add the `in-progress` label + a "claiming" comment on the issue(s); reviewer-repo audits are claimed by comment only. 4. Read the issue bodies (they carry the task context/evidence) and work the item under the @@ -282,3 +302,20 @@ HARD CONSTRAINTS: transport/timeout exceptions must be caught and turned into a response (a `-32603`), else the failure escapes the handler and the client hangs awaiting a reply that never comes. Proved live with a black-hole socket (accept, never respond) → 1s timeout → error in ~1s, no hang. +- **Queue-drift root cause + standing rule (2026-07-12, user-surfaced)**: pickups repeatedly re-picked + already-done work — #91b was framed "recommended next / now unblocked" for two sessions *after* it had + merged (2026-07-11), and the #251/#252 priority-pickups sat listed "open" after closing — requiring a + reactive body correction (tracker comment 16:00). ROOT CAUSE: DONE/OPEN status was read from **prose** (the + arc body's inline "DONE" markers + each session comment's "Recommended next"), which is append-only and + hand-edited, so it lags real issue state — worst under parallel sessions that narrate each other's merges as + "the gate that unblocks X" (#271 got cast as the last gate for an already-merged #91b). It is a *structural* + bug, not a stale-writer bug: any status embedded in prose will drift. STANDING FIX (don't just re-patch the + body next time): **live Gitea state is the ONLY source of truth for status.** The arc body carries order+goal; + a comment's "Recommended next" is a *candidate* that MUST be re-verified OPEN (issue **and** milestone) at + pickup. When prose disagrees with live state, live state wins — correct the prose in your session comment, + never propagate it. STRUCTURAL CURE (2026-07-12 review, Fable): #237's arc no longer carries inline `DONE` + markers — closed items move to a "Done (history)" section, so status lives ONLY in live Gitea state and can't + drift; and the gate/frontier is defined **structurally** (lowest-numbered open arc item), never hardcoded to + an issue number. Beware: the *first* pass at this fix re-planted the very bug by hardcoding "#197 cluster" / + "#91b milestone CLOSED" into the kickoff — if you name today's frontier issue in this standing file, you are + writing the next drift. Gate cluster = open `review`-labeled issues serving the current open arc item.