Files
stack/agents/filbert/work/queue-a1-review-r1-2026-09-26.md
T
jason.woltjeandClaude Opus 5.5 34a72af912 feat(queue): queue as data A1, journal, lock, CLI and verify (#1508)
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]>
2026-09-26 19:07:48 -05:00

8.1 KiB
Raw Blame History

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.patch 419804f2fc8c8b178dafaa237961cc2df07fb3077f8f2d8f2e773b29b5d80dd7
    • delta-r1.patch b733b8940ab400458969428d3edc2339beaf6279dfdbc361de2dc3de793629c5
    • result pinned by build-manifest-r1.sha256 85a8a453d6130ad2181a2b51ac57352ce383b17aca900b1b7907f504788e86c8
    • revision note r1.md d3ba583fbf7fb3ab4c0a1c6c3e78684d2dd9ba9ee105aed9cc1207f513e6dc14
  • N13: approved at n13.patch 00868b2fcf7c806c212575fda0b3fb02205d8399d4473ca978e422624a12cc4d (scripts/test-foundation.sh 60f04822…abeb, scripts/test-discord.sh 2ad3be74…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, then delta-r1.patch, at 3a209eea: both apply cleanly, and sha256sum -c build-manifest-r1.sha256 gives 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, with node --test 107/107. verify skipped because HEAD has no queue.json.
  • The canonical .git holds only sample hooks and no mosaic-queue* file, and core.hooksPath is unset in every scope (rc 1). QUEUE.md, AGENTS.md, docs/TOOLS.md and DEFERRED.md are 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 specAllows oracle 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 showed required true 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 --issue when there are several, and keeps the previous round's issue unless --issue names another. validateRow now refuses review.issue: null. set piece and set gate are privileged only (applySet, the requirePriv under case "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. acquire calls release unguarded on both gate paths. One is the new gate-check catch, where const left = release(handle, io) is called inside the catch. The other is the older gate-present branch. release itself can throw: lstatOrNull and readOrNull rethrow anything but ENOENT, and so does io.unlink. If .git stops 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. withLock already 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. --issue on a later round overwrites review.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. unlock splits its result on newlines. store.unlock takes the first line for stdout and treats every other line as a warning. The result echoes the removed lock's bytes. parseRecord accepts 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 from 40a02d2b for both files, I planted a failing test in each suite's test directory and set NODE_TEST_CONTEXT=child-v8. Both suites exit 0, and each prints OK node --test … (summary missing).
  • Fix verified. With n13.patch applied 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 -u removed from node_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 grep finds no other node --test in scripts/test-*.sh. The rest are README lines and package.json test scripts, which don't run nested.

N13 notes (non-blocking):

  • N13-a. The check tests the canonical tree, not the patch. n13-check.sh copies $SRC/scripts/test-$suite.sh from the canonical checkout (SRC is four levels up from the script). It doesn't apply n13.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-*.txt paths.
  • N13-b. For Sage: the canonical tree already holds both candidates, uncommitted. scripts/test-foundation.sh and scripts/test-discord.sh are modified in the canonical working tree. Their git diff is byte-identical to n13.patch. The 20 A1 files are present there untracked and match build-manifest-r1.sha256 20/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.