Unclaimed files left in the canonical checkout. Inventory: canonical-cleanup-inventory.md (commit-as-evidence groups). detect-secrets scan clean on 2026-11-02: hits are sha256 pins, git object ids, test sentinels already in tracked tests and unit-file lines.
4.3 KiB
Row 105 round 1 (#1599), Filbert: approve.
Candidate manifest SHA-256: cd6d5eb3e4093ac157f63d05cb639d243d76c6bde1a03e78efb8f29e191b6b44. Base: 0d71b9ddd. Packet: agents/researcher/work/queue-105/r1/. This answers request 28246.
I rebuilt the candidate in my own worktree at 0d71b9ddd and applied build.patch. All 5 manifest hashes match, git diff --check is clean, and the worktree shows only the 5 paths. None of the 5 paths changed from 0d71b9ddd to the current refactor head. With Sage's leave, I ran tests/review.test.mjs in packages/bus (8 pass, 0 fail) and tests/tools.test.mjs in packages/harness (11 pass, 0 fail). I ran no full suite and no queue-commit.sh.
What Sage asked me to check
held, routing and the delivery row agree. The case computes held from this.#holder(s.business, a.to) with h?.op === 'claim' ? h.holder_run : null. #reviewMessage makes its own #holder(s.business, to) call with the same query and the same op === 'claim' test, and records that run on the routed delivery. Strictly these are two calls, not one, but both run in the same synchronous request, and nothing between them writes role_claims, so they read the same row. The new test pins all three for both cases: reply held, event held, and the delivery's holder_run (reviewer-run held, null after release). I reran three mutants with the test names captured:
- M3-style (
held = h?.holder_run ?? null, a release counted as held): killed by the new test. - M4 (event records
held: null): killed by the existing event deep-equal ("names the latest pushed commit") and by the new test. helddropped from the reply: killed by the new test. The manifest verified again after each restore.
Release, then request, then claim. After role.release the latest role_claims row is a release, so held is null and the delivery is routed with holder_run: null. A later role.claim by reviewer-2 adds a second routed row for that message to reviewer-2, through the existing #routeWaiting. The test asserts both rows in order. Correct.
Existing reply fields unchanged. The return only appends held. request, message, commit and ref are computed as before, and the existing test still checks commit and ref and uses request and message. The event body gains only held, and the existing deep-equal was updated for exactly that key.
tools.mjs wording against the code. "The reply's held names the run holding the reviewer role, or is null when no reviewer is running" matches: it is the claiming run or null. "A null request waits until a reviewer launches" is close: the code waits for a run to claim the role, which is what a launched reviewer does. The instruction to tell whoever launches roles is the brief's text. The README row says the same, in more exact terms ("waits for a claim").
script-queue skip. The packet's skip of verify/render --check is outside this row's code, and Sage's canonical-root rerun covers it.
Scope
broker.mjs changes only inside the review.request case. tools.mjs changes only the request_review description. The README edit is the review.request row of the verb table. The brief says "the review paragraph only", and the README has no standalone review paragraph. The table row is the one place that describes this reply and event, so I take that as the right reading. The review loop paragraph at README:373-375 says "The review loop adds no event kind and no schema change", which still holds, since held is a body key and schema.sql checks only json_valid(body).
Notes (none blocking)
- N1. A revoked reviewer takes the same null branch as a release, since the latest row isn't a claim, but no test covers revoke. BUILD.md says so.
- N2. No assertion pins the reply's full key set. A deep-equal on the reply in the existing test would catch a later rename or dropped field.
- N3.
heldis a snapshot from routing time. It doesn't mean the run is still alive when the requester reads the reply. BUILD.md states this. A short clause in the README row ("when the request is routed") already says it. - N4. Each of the packet's mutant kills names only the file, not the test case. My reruns above name the cases for M3, M4 and the reply mutant.
The gate still needs Sage's suite rerun, and the decision 109 notices to Mos before and after. The bus side goes live only at a bus restart with Mos's go.