diff --git a/docs/plans/2026-09-13_queue-as-data.md b/docs/plans/2026-09-13_queue-as-data.md new file mode 100644 index 00000000..0e57399e --- /dev/null +++ b/docs/plans/2026-09-13_queue-as-data.md @@ -0,0 +1,126 @@ +# Queue as data: the process stops being prose (#1508) + +Owner of the plan: Jason. Coordinator: the Claude session. Builder: darkwing. +Tracking: #1508. Rows 9 to 13 in `docs/plans/QUEUE.md`, state `required`. + +Jason, 2026-09-13: "It all starts out great, then goes off the rails. I want +this iron-clad." This page is the plan, the decomposition, and the briefs. +It is not a design discussion. Each piece below has one owner, one gate, +and one commit-sized scope. Nothing on this page is optional and nothing +moves to DEFERRED.md; a piece that cannot ship gets a Blocked line in +QUEUE.md with the reason. + +## Problem, in one paragraph + +The entry point for "what is next" was prose in four files (AGENTS.md, +CURRENT.md, ROADMAP.md, CONDUCTOR.md), edited by hand by any seat in one +shared checkout. State lived in sentences, so it drifted: three "Next +action" paragraphs, edits swept into other seats' commits, 160 review files +invented as a side channel, and Jason unable to find the next step. The fix +is the same fix already applied to decisions (`brain.py` is the only writer) +and to seat identity (`registration.json` is the only record): the queue +becomes a record with one writer and checks that fail loudly. + +## Ordering and preconditions + +Starts after piece 5 (darkwing on point, QUEUE row 6) reaches Gate F or is +blocked, whichever comes first. Runs before the fleet migration (row 8). +Pieces A to E below ship in order; each is one issue comment on #1508 and +one QUEUE row move. Nothing on this page waits for the WebUI, the comms MVP, +or the orchestrator to be finished. + +## Piece A: queue record and `mosaic queue` (QUEUE row 9) + +**Owner:** darkwing. **Reviewer:** filbert. **Package:** `packages/queue`, +same shape as `packages/seat`. **Files owned:** `packages/queue/**`, +`scripts/mosaic` (subcommand dispatch only), `docs/plans/QUEUE.md`. + +**What ships** + +- One file, `/docs/plans/queue.json`, committed. It is the queue. + Array of rows: `id` (integer, never reused), `piece` (one line), `owner` + (seat name, `jason`, `coordinator`, or `unassigned`), `issue` (integer or + null), `state` (`queued` | `briefed` | `in-progress` | `in-review` | + `waiting-on-jason` | `done` | `blocked` | `parked` | `required`), `gate` + (one sentence), `brief` (repo path plus optional section), `updatedAt`, + `updatedBy` (from `MOSAIC_AGENT_NAME`, or `--by`, else refused), `note` + (one line, optional), `blockedReason` (required when state is blocked). +- `scripts/mosaic queue list [--owner SEAT] [--json]`, `queue next [SEAT]` + (prints the one row that seat should work on, or "nothing" with exit 0), + `queue add --piece --owner --gate --brief [--issue]`, `queue move ID STATE + [--reason]`, `queue assign ID SEAT`, `queue note ID TEXT`. All writes + through the CLI; the CLI validates the transitions below and refuses + anything else with one line on stderr and exit 2. +- Transitions: queued→briefed→in-progress→in-review→waiting-on-jason→done; + any→blocked (reason required) and blocked→previous; required→in-progress + only; parked only from queued or briefed and only with `--by jason`; + done and parked rows never change. A seat may move only rows it owns; + `coordinator` and `jason` may move any row. +- `docs/plans/QUEUE.md` becomes a rendered view: `mosaic queue render` + writes the table between two marker comments and the CLI runs it after + every write. The header text above the markers stays hand-written. +- Tests: fixtures for every transition and every refusal; render is + byte-stable; `queue next` picks the first row by id, not by file order. + +**Out of scope:** Gitea sync, board display, the ledger, hooks, any change +under `packages/seat`, `packages/control-board`, `packages/ledger`. + +**Gate G (Jason):** a seat launched fresh, with no prior session, is told +only "run `mosaic queue next` and do it". It finds its piece, opens the +brief the row names, and starts, with zero further human messages. Jason +watches from the board. Pass or fail, one sentence on #1508. + +## Piece B: seats read the queue, not CURRENT.md (QUEUE row 10) + +**Owner:** coordinator. **Done 2026-09-13** for the cadence and pointer +lines in AGENTS.md (cbf24b01). Remaining under this piece, after Piece A: +the cadence line says `mosaic queue next` instead of naming the file, and +`agents/*/AGENTS.md` or context files that still point at CURRENT.md for +"what now" are changed to the command. One commit. No gate; verified by +Gate G. + +## Piece C: brief template (QUEUE row 11) + +**Owner:** darkwing, as part of Piece A's review round. **File:** +`docs/plans/BRIEF-TEMPLATE.md`, one page, these headings only: Problem, +Owner and reviewer, Files owned, What ships, Out of scope, Gate (who says +yes, on what evidence). `mosaic queue add` refuses a `--brief` path that +does not exist. The pieces on this page are written in that shape and are +the first three uses. Passing: Piece A's brief and one later brief are +accepted by Jason without a follow-up question about scope. + +## Piece D: reviews through a channel, not files (QUEUE row 12) + +**Owner:** darkwing. **After Piece A.** Review requests and receipts go as +issue comments on the piece's issue (`scripts/gitea-api.sh` exists) or as +board messages once the comms MVP has a record; no new files under +`docs/plans/reviews/`. The existing 160 files stay as history. `mosaic +queue move ID in-review` posts the request comment itself from the row's +data, so the seat does not write one. Passing: one full review round on a +later piece with zero new files under `docs/plans/reviews/`. + +## Piece E: ledger checks the queue (QUEUE row 13) + +**Owner:** darkwing. **Reviewer:** filbert. **After Piece A.** `packages/ +ledger` gains a "queue" section: every open Gitea issue with a `#N` in a +queue row has that row not done; every `in-progress` or `in-review` row has +an owner seat with a live registration; every `done` row's issue is closed; +every `required` row older than 14 days is listed by name. Violations print +above the weekly table and in `--json`. First run Monday 2026-09-21 with the +weekly number. Passing: zero violations, or every violation has a row moved +within the day. + +## What "iron-clad" means here, so it can be checked + +1. The queue has one writer (`mosaic queue`) and refuses bad transitions. +2. Seats are told a command, not a file, so nothing to reinterpret. +3. Every row names an owner, a gate, and a brief that exists. +4. The ledger reports drift weekly, next to the number Jason already reads. +5. `required` rows cannot be parked; only Jason moves them. + +If any of the five stops being true, that is a finding on #1508, reopened. + +## Log + +- 2026-09-13 — page written by the coordinator after Jason's "iron-clad" + ruling; #1508 opened; QUEUE rows 9 to 13 point here. diff --git a/docs/plans/QUEUE.md b/docs/plans/QUEUE.md index 34abeaed..89551d93 100644 --- a/docs/plans/QUEUE.md +++ b/docs/plans/QUEUE.md @@ -34,11 +34,11 @@ Gaps found while working go to `docs/plans/DEFERRED.md`, not here. | 6 | Darkwing on point: darkwing assigns and gates filbert's work (piece 5 on the plan page) | darkwing | none yet | briefed; Jason: send the start message from the board on Sunday 2026-09-13 | F: filbert's item closes with zero human messages from Jason | plan page, "Piece 5: darkwing on point" | | 7 | Weekly ledger run and rails number | Jason | — | recurring, end of Monday 2026-09-14 | under 10 human messages per closed issue for the week of 2026-09-13 | `packages/ledger/README.md` | | 8 | Fleet seats (`~/.mosaic`) onto `mosaic launch` | unassigned | — | queued; not before row 6 is done | Jason's call | none yet | -| 9 | Queue as data: JSON registry, `mosaic queue` is the only writer (list, add, move, assign) | darkwing | #1508 | required; starts when row 6 is done, before row 8 | G: a fresh seat with no prior context finds and starts its piece from the queue alone, zero human messages | #1508 | -| 10 | AGENTS.md cadence reads the queue first; CURRENT.md is narrative only | coordinator | #1508 | done 2026-09-13 (AGENTS.md cadence and pointer lines) | — | #1508 | -| 11 | Brief template: goal, gate, owner, out of scope, files owned; one page, linked from the row | darkwing | #1508 | required; with row 9 | rows 9 and 12 use it | #1508 | -| 12 | Reviews and receipts through the board or issue comments, not files in `docs/plans/reviews/` | darkwing | #1508 | required; after row 9 | one review round with no new file under reviews/ | #1508 | -| 13 | Ledger checks: open issue has a row; in-progress row has a live seat; done row has a closed issue | darkwing | #1508 | required; after row 9 | violations printed with the weekly number, first run Monday 2026-09-21 | #1508 | +| 9 | Queue as data: `docs/plans/queue.json`, `mosaic queue` is the only writer | darkwing; filbert reviews | #1508 | required; starts when row 6 is done, before row 8 | G: a fresh seat told only "run `mosaic queue next` and do it" starts its piece with zero human messages | `2026-09-13_queue-as-data.md`, Piece A | +| 10 | Seats read the queue, not CURRENT.md (AGENTS.md cadence, seat context files) | coordinator | #1508 | required; AGENTS.md lines done 2026-09-13, rest after row 9 | verified by Gate G | `2026-09-13_queue-as-data.md`, Piece B | +| 11 | Brief template `docs/plans/BRIEF-TEMPLATE.md`; `queue add` refuses a missing brief | darkwing | #1508 | required; with row 9 | two briefs accepted by Jason with no scope question | `2026-09-13_queue-as-data.md`, Piece C | +| 12 | Reviews as issue comments posted by `queue move ID in-review`, not files in `docs/plans/reviews/` | darkwing | #1508 | required; after row 9 | one review round with no new file under reviews/ | `2026-09-13_queue-as-data.md`, Piece D | +| 13 | Ledger "queue" section: issue/row/seat drift printed with the weekly number | darkwing; filbert reviews | #1508 | required; after row 9 | first run Monday 2026-09-21, zero violations or every one moved same day | `2026-09-13_queue-as-data.md`, Piece E | Start message for row 6, sent from the board to darkwing: "Read docs/plans/QUEUE.md, then the plan page section "Piece 5: darkwing on @@ -61,3 +61,4 @@ Gate F or when blocked." - 2026-09-13 — rows 9 to 13 added (#1508): the process itself becomes data with one writer and ledger checks. Jason: "I want this iron-clad." Required, not parked; rule: these rows cannot be moved to parked, only to done. - 2026-09-13 — dewey: WebUI row advanced to Jason-owned Gate E after Filbert approval, exact committed-tree 208/208 and remote-verified ea00ec66 publication. No other row changed. +- 2026-09-13 — rows 9 to 13 now point at the plan page `2026-09-13_queue-as-data.md` (pieces A to E, Gate G).