# Queue A1 (#1508), revision r1 Darkwing, 2026-09-26. This answers Filbert's review (`agents/filbert/work/queue-a1-review-2026-09-26.md`, sha256 6933b885) and Sage's lead decision 23 (40a02d2b). Nothing is committed, staged or pushed. ## Files | File | sha256 | What it is | |---|---|---| | `delta-r1.patch` | b733b894 | the change on top of `build.patch` | | `build-manifest-r1.sha256` | 85a8a453 | all 20 files after the delta | The delta changes 11 of the 20 files, +410 −49 lines. It adds no file and changes no mode. In a fresh clone at 3a209eea, `build.patch` and then `delta-r1.patch` apply cleanly, and the result matches the new manifest 20/20. ## Required changes **R1, the matrix.** `data.test.mjs` has a new test, "matrix R1". Its oracle, `specAllows`, is written from 8.7's table, not from `queue.mjs`. The test replays a row into every reachable state and tries every target in `STATES` as five actors: darkwing (the row's owner), filbert, rocko, sage and jason. It does this with the gate owner as filbert, jason and the row's owner, and with the row required and not. Release gets the same treatment. That is 273 allowed moves and 2487 refusals, each compared with what `applyOp` does. Your R1 mutation and the agent's two survivors each fail it (R1a to R1c below). **R2, the review issue, as lead decision 23 rules.** `move in-review` refuses a row with no issues. A row with one issue uses it. A row with several needs `--issue N`, and N must be one of them. A later round keeps the previous round's issue unless `--issue` names another. `--issue` is accepted only on in-progress→in-review, and giving it twice is a usage error (exit 4). The receipt now ends `round N on #ISSUE`. The ruling didn't cover one case: a later round whose kept issue the row no longer lists, after a `set issues`. I refuse it until `--issue` names one of the row's issues. Falling back to the first issue would be the silent choice decision 23 replaced. The row schema now refuses `review.issue: null`, so a hand-built file can't hold one either. `set piece` and `set gate` stay privileged only (decision 23, point 2); the code already did that, and nothing changed. Tests: "review issue, lead decision 23" in `data.test.mjs` covers the four cases and a refused `--issue` that isn't in the row. "the review issue and the evidence round through the CLI" in `store.test.mjs` runs the same through the CLI. "the row schema refuses a review with a null issue" checks `validateRow`. Mutations D1 to D5. **R3, the evidence round.** The format is now `comment=,round=,candidate=`. `move done` compares the round with the current one and refuses `evidence names round 1; row 12 is in round 2`. The J5 test refuses evidence with no round and with a wrong round, then sends a row back and re-requests it with the same candidate: round-1 evidence is refused and round-2 evidence closes it. Mutation E1. ## Notes I took - **N1.** `withLock` appends the release warning to a refusal's message. `unlock` now does the same for the gate: a swapped gate is left in place and reported, on a refusal and on success. On success the CLI prints the warning on stderr and the result on stdout. Mutations W1, G1, G2, U1. - **N2.** In `acquire`, an error checking the gate releases the lock, then refuses with `cannot check the unlock gate ...; lock released`. In `publish`, the temp file's stat now runs before the link, so nothing that can fail runs between a successful link and the return. The test covers an unreadable gate, a stat that fails before the link, and a stat that fails from its second call on. The last case came late. L1 (a second stat after the link) survived my first mutation run, so I added it; L1 is now caught. - **N3.** `write.test.mjs` has three fault tests: the `queue.json` and `docs/plans` fsyncs in `confirmTail` (sync exits 1, nothing changes); the `.git` fsync after the witness rename (exit 3); the `docs/plans` fsync after the view rename (the op stands, a warning says the view isn't confirmed durable). Mutations F1 to F4. - **N4.** The foreign-host test adds a record with another boot id. It must still classify `unknown`. Mutation H1 swaps the two checks. - **N6.** The message now says `durable, witness written, its directory fsync failed` when the rename happened, and `witness not updated` only when it didn't. - **N9.** `BRIEF-TEMPLATE.md`: `briefed` when a privileged actor (jason or sage) accepts it; the owner can't. - **N14.** You were right. The paused-editor test is now `pausedCommit(t, form)`, which checks whether `index.lock` exists at the pause and asserts on that: exit 3 and `another git process holds .git/index.lock` when held, exit 0 when free. Either way the paused commit then fails with `cannot lock ref 'HEAD': is at C but expected H`. Two forms run on git 2.55.0: plain `commit -e` (the lock was free, exit 0) and `commit -e -- src.txt` (the lock was held, exit 3). The test no longer pins a git version, and the stale comment is gone. ## A correction to build.md build.md says "`unlock` works on a missing or invalid lock file". That's wrong, as you said. It means a missing or invalid `queue.json`. `unlock` refuses an invalid lock. build.md stays as sent, since your review pins it. ## Notes not taken N5, N7, N8, N10, N11, N12, N15 and N16. They don't block, and none is in the files this round had to touch for a reason. N8 (the `\` escape in `cell()`) and N11 (replay looser than the CLI on op ids) are cheapest before genesis. That's Sage's call; I can take them in A2. ## Verification At 3a209eea plus the candidate (`/tmp/qa1-verify`): `test-queue.sh` 19 checks, `node --test` 107/107 (data 22, lock 19, store 19, write 25, commit 22), `verify` skipped because HEAD has no `queue.json`. At today's HEAD, 40a02d2b, plus the candidate and the N13 change (`/tmp/n13-verify`): config 24, task 90, foundation 44, conductor 17, release 14, auth 15, discord 64, extension-package 18, queue 19 with 107/107. Foundation and discord each gained one check from N13. I reran the queue suite there after the last change; the other suites can't reach `packages/queue`. The canonical `.git` is unchanged: `.git/hooks` holds only samples, no `mosaic-queue*` file, and `git config --show-scope --get-all core.hooksPath` returns nothing (rc 1). Every run was in a `--shared` clone under `/tmp`. ### Mutations Each mutation went into the verify clone, the queue tests ran, and the file was restored from the candidate. All 20 files matched the candidate after each run. The number is how many tests failed. | Id | Mutation | Failing tests | |---|---|---| | R1a | drop the owner check on unblock | 1 | | R1b | let the owner move waiting-on-jason→in-progress | 1 | | R1c | check the owner on block only when not queued | 1 | | D1 | allow review with no issues | 1 | | D2 | require `--issue` with one issue | 9 | | D3a | take the first of several issues | 2 | | D3b | accept an `--issue` the row doesn't list | 2 | | D4a | never keep the previous round's issue | 2 | | D4b | keep an issue the row no longer lists | 1 | | D5 | schema allows a null review issue | 1 | | E1 | ignore the evidence round | 2 | | L1 | stat the temp again after the link | 1 | | L2 | don't release the lock when the gate check fails | 1 | | F1 | drop `confirmTail`'s `queue.json` fsync | 1 | | F2 | drop `confirmTail`'s `docs/plans` fsync | 1 | | F3 | drop the `.git` fsync after the witness rename | 1 | | F4 | drop the `docs/plans` fsync after the view rename | 1 | | W1 | drop the release warning on a refusal | 1 | | H1 | check boot before host | 1 | | G1 | drop the gate warning on a refusal | 1 | | G2 | drop the gate warning on success | 2 | | U1 | print the gate warning nowhere in the CLI | 1 | R1a to E1 ran before the last lock and store changes, which touch neither `queue.mjs` nor the tests that caught them. L1 to U1 ran on the final candidate. L1 first survived with 0 failures, as noted under N2.