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.
5.2 KiB
Filbert review, row 149 round 2: changes.
Candidate: manifest a325a32568a6a2635837455795b0965f1126f31fc25c4048e56e132263aeffcb, Dewey's build.patch applied to ac55e84fe (origin/refactor). In a fresh worktree all 21 hashes check. The patch's added and removed lines are the same as round 1's, so only context moved. I didn't post a round 1 verdict, so this round covers the whole row, not only the 5 drifted paths. Lines below are at the candidate tree.
Changes
- merge-gate can't land in the run that raised the decision, and merge-gate.md says it can (roles/merge-gate.md:16-20).
land_workexists only when the broker'slandHeldis true at launch (packages/cli/src/launcher.mjs:262, packages/harness/src/tools.mjs:134). The git socket is bound only then too (packages/cli/README.md:432-434), because merge-gate holds neither git.push.working nor review.verdict. The runner reads tools.json once, at start (packages/harness/src/runner.mjs:322).- In the raising run,
landHeldwas false at launch. When cto resolves, the approval comes in as a DECISION message to that same run (packages/bus/src/broker.mjs:1597-1612), and that run has noland_work. The bundle's "Landing:" prompt line (packages/harness/src/bundle.mjs:118) is missing too. So line 16's "Once the decision is resolved ..., callland_work" can't be done. - Row 137 meant it this way: "row 136 lets a later run of the same instance use it" (brief docs/plans/2026-10-15_q167-rows-r3.md:328-331, blob
606f7e0905). A second run of merge-gate, in the same thread, has to start before anything lands. No contract says who starts it. merge-gate can't message anyone: its RESULT reply to the DECISION message is refused, per your probe. cto.md and chief-of-staff.md say nothing about relaunching it. As shipped, an approved merge sits unused until a person notices. - Fix:
- Say the two-run flow in merge-gate.md:
land_workappears only in a run launched after the approval, in the thread that raised it. In the raising run, the approval arrives without the tool. - Name who starts the landing run in that role's contract, or record it in BUILD.md's Follow-ups with its cost, the way follow-up 1 does for message.send.
- Add a test that pins the path. In packages/bus/tests/workflow-roles.test.mjs,
b.landHeld({ business: 'demo', role: 'merge-gate', thread: null })should be false before cto resolves, true after, and false once the approval is used. - roles/merge-gate.md is test-read (packages/business/tests/workflow-roles.test.mjs:59, 93), so this isn't doc-only under decision 137.
- Say the two-run flow in merge-gate.md:
Minor, fix in the same round
- The hard-wait list in pm.md:53-56 and chief-of-staff.md:52-55 leaves out one case the broker treats as a hard wait.
#hardWaitis GATED plusrole.revokeaimed at an END_PROTECTED instance, which today isassistant(broker.mjs:139, 516-519). A citedrole.revokeof the assistant goes to the human (broker.mjs:1466-1469). The text says "every hard wait goes to the human" and then lists only the eight GATED_ONLY actions. Keep the eight-action sentence, since the test pins it to GATED_ONLY at workflow-roles.test.mjs:112-114. Add a sentence for ending the assistant's run.
Checked and correct
- Brief: every "What ships" bullet and every listed test (q167-rows-r3.md:162-216).
- security-reviewer: read, grep, find, ls;
review.verdictwithin role only; no crossRole; no credentials. - merge-gate: crossRole
git.merge.protectedonly; empty withinRole; no write tools. - The proactive line is inside Authority in all 13 contracts.
- The domain enum in tools.mjs is technical and delivery, with no default sent.
- pm and chief-of-staff carry the REQ-DEC-2 text, and their old "for the human" wording is gone.
- security-reviewer: read, grep, find, ls;
raise_decisionforwardsdomain. The broker defaults it to delivery and refuses anything else with invalid-domain (broker.mjs:1461-1462). The arbitrated route matches the new tool text and the contract text (broker.mjs:1466-1469).- Row 133's refusal works on the shipped lists. merge-gate's receiveFrom includes cto.
checkMessaging(route, raiser)runs before anything is stored (broker.mjs:1473). The bus test drops cto and gets decision-route-refused with 0 decisions. - Naming either new role as an arbiter is refused because both declare messaging lists (packages/business/src/business.mjs:167-168). The business test pins that.
- security-reviewer's REVIEW-RESULT reaches the coder through
review.verdict, with no message.send (bus test lines 86-99).fetch_reviewis offered only with a checkout (tools.mjs:151). Your follow-up 2 covers a reviewer that has no way to read a ref. - The rebase onto
ac55e84fe. Row 143's Duties bullets in assistant, chief-of-staff, pm and cto don't conflict with this row's Authority paragraphs. In tools.mjs onlyraise_decisionchanged;MESSAGE_CLASSESkeeps BLOCK. - READMEs: the packages/business section and the packages/harness paragraph match the code.
Not run by me
I ran no tests, mutants or gate. Finding 1 changes merge-gate.md and adds a test, so I'll run the touched files singly in round 3 with a slot. Your singles (r2/singles.log, 37 files, 337 tests) and round 1's mutants and gate are your receipts, not mine.
Verdict: changes, on 1. Item 2 is small and can go in the same round.