Filbert approved round 1 (f167b85e). Manifest 782bcb62, 21 files, plus the QUEUE.md markers and the TOOLS.md section. Lead decision 35. Co-Authored-By: Claude Opus 5.5 <[email protected]>
203 lines
11 KiB
Markdown
203 lines
11 KiB
Markdown
# Queue A2 (#1508), candidate for review
|
|
|
|
Darkwing, 2026-09-27. A2 is migration, render and dispatch (lead decision
|
|
20), plus every item Sage carried forward from A1's review (decision 26:
|
|
N5, N8, N10, N11, N12, P1, P2, P3). Base is HEAD c9539baa; A1 is 34a72af9.
|
|
Filbert reviews. Sage commits, then installs the hook and runs genesis.
|
|
Nothing is committed, staged or pushed.
|
|
|
|
## Files
|
|
|
|
`build.patch` (sha256 `dc0be7ce74aaaaaf43deebe68af439d1b2b80c77aad6538420e929de35e2f21f`) changes 13 files and adds 8.
|
|
`build-manifest.sha256` (sha256 `782bcb62e555659333a35888d418d986da63bdf522f38cafa447db7ddd0074b7`) pins all 21 after the patch.
|
|
In a fresh clone at c9539baa the patch applies and the result matches
|
|
the manifest 21/21, file modes included. `git apply` warns about one
|
|
blank line at the end of `fixtures/genesis-render.md`. It belongs there:
|
|
the render ends with one, and the golden has to match byte for byte.
|
|
|
|
- `packages/queue/src/`: `queue.mjs` (N8, N10, N11, P2), `store.mjs` (N12,
|
|
N11's shared check, P1's helper, P3's caller), `lock.mjs` (P1, P3),
|
|
`io.mjs` (N5), `cli.mjs` (usage comment).
|
|
- `scripts/mosaic`: `queue` execs `packages/queue/src/cli.mjs` with the
|
|
remaining arguments. Every other call reaches the seat CLI as before.
|
|
- `scripts/test-queue.sh`: syntax checks for `scripts/mosaic` and the new
|
|
fixture; `scripts/mosaic queue help` always; after genesis, `verify` and
|
|
`render --check` on the live queue through `scripts/mosaic queue`.
|
|
- `packages/queue/README.md`: the dispatch, N5, N7, N8, N10, N12, P2, the
|
|
map and `map-check.mjs`, two new test files.
|
|
- Tests: 107 in A1, 122 now. New: `dispatch.test.mjs` (3),
|
|
`migration.test.mjs` (3), and 9 more in data, lock, store and write.
|
|
Fixtures: `mosaic-pre-a2.sh` (the script before A2), `queue-marked.md`
|
|
(QUEUE.md with the markers), `genesis-render.md` (the golden render).
|
|
- `agents/darkwing/work/queue-migration-map.md`: the genesis input.
|
|
- `agents/darkwing/work/queue-a2/map-check.mjs`: the drift check.
|
|
- `agents/darkwing/work/queue-a2/carry-forward.md`: the item list Sage
|
|
confirmed (773dbd75), with the r1 section added after it.
|
|
|
|
Outside the patch, for Sage to apply (condition 2 keeps them out of A2):
|
|
|
|
- `queue-md.patch` (sha256 `2ca8f689e1dcda5bb30e9af4c3f867242d5239d72e13001369c7b7aca7956402`): the two markers, a header that points
|
|
seats at `scripts/mosaic queue next`, and a line freezing the old log of
|
|
table changes. It applies to HEAD.
|
|
- `tools-md.patch` (sha256 `c53aea1f6e871e17d04335ef60250adcdbe64f6466d9ff641042c00094d1c3a8`): a "Work queue" section in
|
|
`docs/TOOLS.md`. It applies to HEAD. Optional; the README already has
|
|
the detail.
|
|
|
|
## The five conditions
|
|
|
|
1. **Nothing ran against the canonical `.git`.** Tests use scratch
|
|
repositories under the temp directory. The dry run below used
|
|
`/tmp/qa2-dry`. Checked after all runs: no `mosaic-queue*` file in
|
|
`.git/`, `.git/hooks/pre-commit` absent, `core.hooksPath` unset in every
|
|
scope, nothing staged.
|
|
2. **No QUEUE.md, AGENTS.md or TOOLS.md edits.** The two proposals are
|
|
patch files. `git status` shows none of the three modified.
|
|
3. **`scripts/test-queue.sh` is green at a HEAD with no `queue.json`:**
|
|
24/24, the live checks skipped. After the dry-run genesis it ran 26/26, with `verify` and
|
|
`render --check` on the live queue.
|
|
4. **H is recorded before the canary.** `queue-commit.sh` is unchanged
|
|
from A1, and its test "F1: H is recorded before the canary, so HEAD
|
|
moving during the canary makes update-ref fail" passes.
|
|
5. **The fault layer is reachable only from tests.** N5 narrows this
|
|
further: tmpfs was the one fault-free path open to the CLI, and now
|
|
only a layer with `allowTmpfs: true` gets it. The test asserts
|
|
`realIo` has no such key and that `"yes"` doesn't count.
|
|
|
|
## Carried-forward items
|
|
|
|
| Item | Change | Test |
|
|
|---|---|---|
|
|
| N8 | `piece`, `gate`, `note`, move `reason`, brief anchor and `blockedReason` refuse `\` and `<`, at the CLI and in replay | "text the table shows refuses \ and <, everywhere it enters"; "every accepted text renders to nine cells on every row" (GFM's cell rule, no `marked` import) |
|
|
| N11 | Replay holds every log entry, round op and claim op to `CALLER_OP_RE` and refuses `.outcome`, genesis and `accept-history` included. `LOG_OP_RE` stays for Piece D's derived ids; no verb derives one yet | "replay holds every op id to the caller's rule" |
|
|
| N10 | `set issues` moves `closes` only if it equalled the old issues; a narrowed `closes` keeps its intersection, and the receipt says `(kept narrowed)` | "set issues keeps a logged narrowing of closes" |
|
|
| P2 | Each round records `issue`; `review` is `{rounds}` only. A later round keeps the last round's issue | "the row schema refuses a round with a null issue, and the A1 review shape", and A1's R2 tests updated |
|
|
| P1 | Both gate paths in `acquire` release through `releaseOrWarn`; a failed release is a message naming the lock, not a stack trace | "a release that fails on a gate path is reported, never a stack trace" |
|
|
| P3 | `lock.unlock` returns `{result, warning}`; nothing splits on newlines | "unlock keeps a multi-line lock record on stdout" |
|
|
| N5 | tmpfs left `FS_TYPES`; only `allowTmpfs === true` admits it | "tmpfs passes only a test layer that allows it" |
|
|
| N12 | `--by` still wins; a different non-empty `MOSAIC_AGENT_NAME` adds a stderr warning on success and on refusal. Nothing is logged | "--by that differs from MOSAIC_AGENT_NAME warns on stderr and logs nothing more" |
|
|
|
|
The rest, as `carry-forward.md` records and decision 26 confirmed: N7 is a
|
|
README line (the leftover `.git/mosaic-queue.lock.<pid>.<hex>.tmp` is
|
|
removed by hand). N15, N16, N13-a and ext2/ext3 are won't-do.
|
|
|
|
## Migration
|
|
|
|
The map (`queue-migration-map.md`) is built from QUEUE.md blob c8e3d34e,
|
|
which HEAD has. `node agents/darkwing/work/queue-a2/map-check.mjs` prints
|
|
`ok: QUEUE.md matches the map (blob c8e3d34e)`. Run it again just before
|
|
genesis. It exits 1 and lists the rows if QUEUE.md moved.
|
|
|
|
map-check did its job once already. HEAD moved from 8dba3ff7 to c9539baa
|
|
while I worked, and it reported row 5 (the CHAT-03 brief pinned, lead
|
|
decision 33). I rebuilt row 5's note, `queue-md.patch`, the marked fixture
|
|
and the golden render against the new blob. No other row changed.
|
|
|
|
The map's "Choices Sage should check" has eight items. None blocks review.
|
|
The ones that change what genesis writes: row 7 stays a live row (decision
|
|
27), row 10's owner stays `coordinator` with `queue assign 10 sage`
|
|
recommended as the first op, rows 12 and 13 have Sage as gate owner, row 16
|
|
stays `waiting-on-jason` unless #1510 is closed, and rows 9 to 12 close
|
|
nothing so row 13 closes #1508. Rows 9 to 13 have no `after`: decision 29
|
|
took the wait on row 6 off them, and `after: 9 done` on row 10 would wait
|
|
on a gate that needs row 10.
|
|
|
|
Dry run in a shared clone (`/tmp/qa2-dry`), the candidate plus
|
|
`queue-md.patch` and `tools-md.patch` committed on top of c9539baa. I
|
|
reran it from scratch after the rebase:
|
|
|
|
0. `map-check.mjs`: `ok: QUEUE.md matches the map (blob c8e3d34e)`.
|
|
1. `scripts/test-queue.sh`: 24/24, live checks skipped.
|
|
2. `scripts/queue-commit.sh --install-hook --by sage`: installed; canary
|
|
passed.
|
|
3. `scripts/mosaic queue genesis --root /tmp/qa2-dry --branch a2-dry --map
|
|
… --op genesis-2026-09-27 --by sage`: `ok genesis-2026-09-27 rev 0
|
|
genesis 30 rows`.
|
|
4. `scripts/queue-commit.sh --genesis`: committed.
|
|
5. `verify --current`: briefs match HEAD. `render --check`: current.
|
|
`legacyView` equals the marked body byte for byte, and `mapBlob` is the
|
|
map's blob.
|
|
6. `next`: darkwing resumes 9, sage resumes 7, dewey resumes 5, filbert
|
|
and rocko have nothing.
|
|
7. `scripts/test-queue.sh`: 26/26 with the live checks.
|
|
8. `queue assign 10 sage --op assign-10-dry --by sage`: `ok … rev 1 row 10 owner:
|
|
coordinator→sage`.
|
|
|
|
The dry clone's hook is `.git/hooks/pre-commit`, mode 0755, blob
|
|
abdf14e7. `core.hooksPath` is unset there too.
|
|
|
|
## Choices I made
|
|
|
|
- **N8 refuses instead of escaping.** An escape has to be right for every
|
|
Markdown renderer that reads QUEUE.md; a refusal doesn't. No line in
|
|
today's table has either character.
|
|
- **P2 drops `review.issue`.** The last round's issue is the kept one, so
|
|
a second copy could only disagree. Piece D reads `rounds[].issue`.
|
|
- **N10's edge.** A `closes` narrowed to nothing stays empty whatever the
|
|
new issues are. `set closes` with a reason is the way to widen it again.
|
|
- **N12 warns on a refusal too,** so a seat that mistyped `--by` sees it on
|
|
the error it was reading anyway.
|
|
- **`scripts/mosaic queue` uses `exec`,** so exit codes and signals are the
|
|
queue CLI's own. Any first argument other than exactly `queue` goes to
|
|
the seat CLI, as before; the dispatch test compares argv, cwd,
|
|
environment and stdin against the pre-A2 script.
|
|
|
|
## Mutations
|
|
|
|
Each mutation ran alone in a shared clone of the candidate, with
|
|
`node --test packages/queue/tests/`. A killed mutation fails at least one
|
|
test.
|
|
|
|
46 mutations. Each one below failed at least one test; the number is
|
|
how many.
|
|
|
|
| Item | Mutations |
|
|
|---|---|
|
|
| N8 | backslash 2, lt 2, noteVerb 1, rowNote 2, anchor 1, reason 1 |
|
|
| N11 | entryShape 1, outcome 2, genesisOnly 1, roundOp 1, claimOp 1 |
|
|
| N10 | always 2, noIntersect 1, receipt 1 |
|
|
| P2 | keptFirst 1, noCheck 1, reviewIssue 10 |
|
|
| P1 | gateErr 1, gatePresent 1, gatePresentMsg 1, withLock 1 |
|
|
| P3 | joined 2, storeSplit 1 |
|
|
| N5 | inTypes 1, truthy 1, anyType 1 |
|
|
| N12 | noWarnOk 1, noWarnErr 1, envWins 1, emptyEnv 1 |
|
|
| Dispatch | noShift 1, unsetArg 1, prefix 1, noExec 1 |
|
|
| Golden render | mapGate 1, mapState 1 |
|
|
| map-check | fixed26 1, owner 1, issues 1, lineDiff 1, parkedPiece 1 |
|
|
|
|
Five of them survived the first pass. Each now has a test that kills it:
|
|
|
|
- N11 roundOp and claimOp (replay stops checking a review round's op or a
|
|
claim's op). The N11 test now builds a claimed row and a reviewed row and
|
|
refuses an op of 73 characters and one ending `.outcome` in each.
|
|
- P1 withLock (the post-op release goes back to the throwing `release`).
|
|
New write test: the lock's unlink fails with EACCES after the op, and the
|
|
receipt and a refusal both carry "cannot release the queue lock (EACCES)".
|
|
- N12 emptyEnv (an empty `MOSAIC_AGENT_NAME` warns). The N12 test now runs
|
|
with it empty and expects no stderr.
|
|
- Dispatch noExec (`node` without `exec`, so a successful queue call falls
|
|
through to the seat CLI). The dispatch test now runs a queue call that
|
|
exits 0 and checks that only the queue CLI ran.
|
|
|
|
The map and golden-render mutations ran again after the rebase and were
|
|
still killed.
|
|
|
|
## Suites
|
|
|
|
All nine green at the final candidate: config 24, task 90, foundation
|
|
44, conductor 17, release 14, auth 15, discord 64, extension-package 18,
|
|
queue 24 (no `queue.json` at HEAD). `node --test packages/queue/tests/`:
|
|
122/122.
|
|
|
|
## After approval (Sage)
|
|
|
|
1. Check the canonical tree against `build-manifest.sha256`, then commit
|
|
the 21 files by path.
|
|
2. Apply `queue-md.patch` (and `tools-md.patch` if wanted) and commit.
|
|
3. `node agents/darkwing/work/queue-a2/map-check.mjs` must print `ok`.
|
|
4. `scripts/queue-commit.sh --install-hook --by sage`.
|
|
5. `scripts/mosaic queue genesis --root /mnt/storage/src/mosaic-stack
|
|
--branch refactor --map agents/darkwing/work/queue-migration-map.md
|
|
--op <id> --by sage`.
|
|
6. `scripts/queue-commit.sh --genesis -m MSG`.
|
|
7. `scripts/test-queue.sh` runs the live checks from here on.
|