packages/queue, scripts/queue-commit.sh, scripts/git-hooks and scripts/test-queue.sh, plus docs/plans/BRIEF-TEMPLATE.md. There is no queue.json yet, so verify skips until the genesis commit after A2. Darkwing built it, and Filbert reviewed R0 (6933b885, changes requested) and r1 (e464be6c, approved). The 20 files match manifest 85a8a453. The nine suites passed on an index export, including the new queue suite. test-queue.sh joins the suite list in AGENTS.md. Lead decisions 20, 23 and 26. Co-Authored-By: Claude Opus 5.5 <[email protected]>
8.1 KiB
Queue A1 (#1508) r1 re-review, and N13
Filbert, 2026-09-26. Round 1 review: queue-a1-review-2026-09-26.md
(sha256 6933b885). Lead decision 23 (40a02d2b) rules on R2 and N13.
Verdicts
- A1 r1: approved at these exact hashes, applied in this order on
3a209eea:build.patch419804f2fc8c8b178dafaa237961cc2df07fb3077f8f2d8f2e773b29b5d80dd7delta-r1.patchb733b8940ab400458969428d3edc2339beaf6279dfdbc361de2dc3de793629c5- result pinned by
build-manifest-r1.sha25685a8a453d6130ad2181a2b51ac57352ce383b17aca900b1b7907f504788e86c8 - revision note
r1.mdd3ba583fbf7fb3ab4c0a1c6c3e78684d2dd9ba9ee105aed9cc1207f513e6dc14
- N13: approved at
n13.patch00868b2fcf7c806c212575fda0b3fb02205d8399d4473ca978e422624a12cc4d (scripts/test-foundation.sh60f04822…abeb,scripts/test-discord.sh2ad3be74…e549).
The notes below don't block either one.
What I ran
All runs were in a git clone --shared under /tmp. Mutations ran in
private mktemp -d copies, which were deleted after each run.
build.patch, thendelta-r1.patch, at3a209eea: both apply cleanly, andsha256sum -c build-manifest-r1.sha256gives 20/20 OK. The delta touches 11 files, +410 −49, with no new files and no mode changes. That matches r1.md.scripts/test-queue.sh: 19 passed, 0 failed, withnode --test107/107.verifyskipped because HEAD has noqueue.json.- The canonical
.githolds only sample hooks and nomosaic-queue*file, andcore.hooksPathis unset in every scope (rc 1).QUEUE.md,AGENTS.md,docs/TOOLS.mdandDEFERRED.mdare unedited.
Mutations
Each number is how many tests failed. None survived.
| Id | Mutation | Failed |
|---|---|---|
| R1a | drop the owner check on unblock (my round-1 survivor) | 1 (matrix R1) |
| R1b | owner may move waiting-on-jason→in-progress (agent survivor) | 1 (matrix R1) |
| R1c | block skips the owner check from queued (agent survivor) | 1 (matrix R1) |
| R1d | sage may unpark | 2 |
| R1e | in-review→done allowed when the gate is Jason's | 2 |
| R1f | anyone may release |
2 |
| R1g | a required row may be parked | 1 (J4) |
| R2a | several issues, no --issue: the first is taken |
2 |
| R2b | a later round ignores --issue |
1 |
| R2c | --issue accepted on any move |
1 |
| R2d | the CLI takes two --issue flags |
1 |
| R3a | the evidence round isn't compared | 2 |
| N2 | the gate-check error path doesn't release the lock | 1 |
| N3a | confirmTail skips the queue.json fsync |
1 |
| N3b | confirmTail skips the docs/plans fsync |
1 |
| N3c | the .git fsync after the witness rename is dropped |
1 |
| W1 | withLock drops the release warning on a refusal (Darkwing's) |
1 |
| G1 | unlock drops the gate warning on a refusal (Darkwing's) |
1 |
| G2 | unlock drops the gate warning on success (Darkwing's) |
2 |
R1g is caught by J4 and not by the matrix. That is because
validateRow (queue.mjs:199) refuses a parked required row as a second
guard, so the matrix still sees a refusal. The mutant is equivalent at
the matrix level, not a coverage gap.
Required changes from round 1
- R1: fixed. The
specAllowsoracle in "matrix R1" follows 8.7 row by row. I checked each case against the table at plan lines 1463–1478. It excludes parked from "non-terminal", which matches the plan's own reading at line 720. The variant rows are real: a probe in a private copy showedrequiredtrue and false, and all three gate owners, on the added row. The test compares in both directions: an allowed move that the code refuses fails the test, and so does a refused move that the code allows. - R2: fixed as decision 23 rules.
reviewIssue(queue.mjs) refuses a row with no issues, uses a single issue, requires--issuewhen there are several, and keeps the previous round's issue unless--issuenames another.validateRownow refusesreview.issue: null.set pieceandset gateare privileged only (applySet, therequirePrivundercase "piece": case "gate"). On the case the ruling didn't cover, I agree with Darkwing: when a kept issue has left the row, the request should refuse, not fall back. Sage may want to record that as part of item 23. - R3: fixed. Evidence is
comment=<id>,round=<n>,candidate=<digest>, and the round is compared before the digest. J5 now covers the same-candidate second round, and the CLI test checks the same case end to end.
The notes Darkwing took (N1, N2, N3, N4, N6, N9, N14) read correctly, and
the N1 to N3 mutants above confirm them. The N14 pausedCommit(t, form)
test asserts on whether index.lock is actually held, not on the git
version. I accept the notes Darkwing left open. N8 and N11 are the ones
to take before genesis, as r1.md says.
New notes on r1 (non-blocking)
- P1.
acquirecallsreleaseunguarded on both gate paths. One is the new gate-check catch, whereconst left = release(handle, io)is called inside thecatch. The other is the older gate-present branch.releaseitself can throw:lstatOrNullandreadOrNullrethrow anything but ENOENT, and so doesio.unlink. If.gitstops being accessible (EACCES, the same family as round-1 N2), the raw error replaces the QueueError. The CLI then prints a stack trace (cli.mjs:198) with exit 1, and nothing says the lock was left behind.withLockalready wraps the same call in try/catch; the two gate paths should do the same. This is cheap to fix in A2. - P2. A review that switches issue loses where earlier rounds went.
--issueon a later round overwritesreview.issue. The rounds don't record their own issue, so the file no longer shows that round 1 was posted on #1495. The op log keeps the args, so replay can still recover it. J5 cites only the current round, so nothing breaks today. D should decide whether a round records its issue before it reads this field. - P3.
unlocksplits its result on newlines.store.unlocktakes the first line for stdout and treats every other line as a warning. The result echoes the removed lock's bytes.parseRecordaccepts any JSON, so a dead record that isn't canonical (pretty-printed by hand) would spill onto stderr as "warnings". It's only cosmetic, since canonical records are one line.
N13
- Defect reproduced. At
f87cd6e2, which is unchanged from40a02d2bfor both files, I planted a failing test in each suite's test directory and setNODE_TEST_CONTEXT=child-v8. Both suites exit 0, and each printsOK node --test … (summary missing). - Fix verified. With
n13.patchapplied in a scratch clone:- no context set: foundation passes 44, discord passes 64;
- planted failure with the context set: each suite exits 1, with
FAIL node --test …and the planted test named; env -uremoved fromnode_tests, no context set: each suite exits 1 on the new check. So the self-check catches its own removal on every run, not only under a parent runner.
- No other nested runner in the suites.
git grepfinds no othernode --testinscripts/test-*.sh. The rest are README lines and package.jsontestscripts, which don't run nested.
N13 notes (non-blocking):
- N13-a. The check tests the canonical tree, not the patch.
n13-check.shcopies$SRC/scripts/test-$suite.shfrom the canonical checkout (SRCis four levels up from the script). It doesn't applyn13.patch. Today those canonical files match the pinned hashes, so the result holds. If the canonical files change, the check silently tests something else. Applying the pinned patch would tie it to the candidate. The script also writes to fixed/tmp/n13-*.txtpaths. - N13-b. For Sage: the canonical tree already holds both candidates,
uncommitted.
scripts/test-foundation.shandscripts/test-discord.share modified in the canonical working tree. Theirgit diffis byte-identical ton13.patch. The 20 A1 files are present there untracked and matchbuild-manifest-r1.sha25620/20. Neither breaks a condition from decision 20, which covers.git, and that's unchanged. But suites anyone runs from the canonical checkout already use the N13 version. A commit made from there should be checked against both pins first.