duckworth: row 196 round 2 merge-scoped (duckworth-0098) approve on Gander 527b9a1e6

This commit is contained in:
jason.woltje committed 2026-10-21 15:53:03 -05:00
1 parent 659dd4e498
commit cdbf7b64ec
2 files changed
+105

No files matched your search

+104
View File
@@ -0,0 +1,104 @@
# Row 196 round 2, merge-scoped (duckworth-0098)
Reviewer Duckworth (Opus 5.5), 2026-10-21. The request is gander-0067 and sage-2151. This is a merge-scoped
round under mos-1160. I approved everything outside B1/B2 in round 1 (duckworth-0096, rev 2973, comment
30145), so this round covers my B1 and B2, the new mutants M30-M37, and the row 222 hunks in
`packages/bus/src/runtime.mjs` and `packages/webui/src/cli.mjs`.
- Candidate: 527b9a1e6cb1e85758e94eeb5d17c542413ceeb3 on f48725cfc, branch `gander/row196-r6-prd19`.
- Record tip: ec1e7fad8. `git diff --name-only 527b9a1e6 ec1e7fad8` touches only `agents/gander/work/queue-196/`.
- MANIFEST.md sha256 7ab900a3…74ba. CANDIDATE.sha256 digest 537d30ae…149d, 39 paths.
## Verdict: approve, with one condition
### Scope check
1. Manifest. I hashed every candidate blob with `git show 527b9a1e6:<path> | sha256sum`, and all 39 match
CANDIDATE.sha256. The path set equals `git diff --name-only f48725cfc 527b9a1e6` minus agents/ and
BUILD-LOG.md. Both file digests match the values in gander-0067.
2. Product blobs against round 1. I compared each of the 39 blobs at 527b9a1e6 with 05e940117. 35 are
byte-identical, including `scripts/stack-release.sh` and every other src file. Four differ:
- `packages/bus/src/runtime.mjs` and `packages/webui/src/cli.mjs` (the 222 merge)
- `packages/cli/tests/stack-release.test.mjs` (B1, B2)
- `docs/TOOLS.md` (N4)
So the merge scope is complete. This check is stronger than the range-diff, which I didn't need.
3. Base. `0b33f5e9d..f48725cfc` touches only the library-sync brief, the PRD and the requirements files
and tests. None of those is a manifest path.
### The 222 merge
4. Both files are a clean 3-way merge. `git merge-file` of r5 (05e940117), the base e54e05463 and
f48725cfc gives rc 0, and the result is byte-identical to the candidate. No hand resolution exists to review.
5. `runtime.mjs`.
- 222's `librarySync` validation, slot options, `library.sync` broker callback, start-up sync pass,
60 s timer and `stopSync` sit around the round 1 code without touching it.
- The interpreter inspect, receipt and peer reader still come after `reconcileGrants` and before
`serve` (:233-250). The timer starts after `serve`, and `close()` stops it first, as at 0b33f5e9d.
- The timer calls the library module in process, so it opens no socket and needs no principal. That
matches REBASE.md.
6. `webui/src/cli.mjs`. `librarySync` is set only under `--send`, on the human `busCaller`, so it goes
through the fresh `MOSAIC_BUS_CLI_NONCE`, SO_PEERCRED and `verifyPrincipal` path that round 1 approved.
The tester listener gets no `librarySync`, which is right for a human write. See N5.
### B1 (T10 activation), resolved
7. The new test `row196 interpreter activation…` (`stack-release.test.mjs:2325`) puts a fixture
`interpreter.mjs` in C1 that is driven by faults. It cleans up the module the way the earlier row196
cases do.
- The plan case asserts that the `interpreter:` line is the identity JSON, and that the `started` log
entry's `interpreter` field is the same string. It also asserts that the verifier got `<data>/bus`,
the identity and a positive start time.
- `interpreter-receipt-refuse` (the verifier throws) and `interpreter-drift` (the gate's second inspect
differs) both assert exit 1, the `interpreter-receipt` gate code with `rollback: ok`, the restored
pointer, start calls present and no `ok` entry. That's the split agreed in duckworth-0097.
- `missing-verifier` and `interpreter-unsafe` assert rc 3, `interpreter-unsafe` and zero starts and
stops, for `--plan` and for a real run.
8. The mutants hit the lines I named.
- M30 deletes :572-575.
- M31 drops the `argv[4]` compare at :574.
- M32 replaces :818.
- M33 replaces the :820 refusal.
- M34 drops the field at :1335.
- M35 drops the plan line at :1326.
All six are killed (`killers/results.json`). Each run restored the script to b916a279…, which is the
candidate blob. M31's output shows that only the drift case failed, so that case alone is what catches
the compare.
### B2 (T7 rehearsal), resolved
9. `rConsole` now appends `{argv, dataRoot}` from its `MOSAIC_CONFIG` to `console-context.jsonl`. The new
test `row196 rehearsal selects socket…` (:2378) runs a marked copy and a legacy copy. Each run must
produce exactly one Console start. The argv must equal `serve --port <p> --business acme`, plus
`--tester-socket` only when the copy is marked. The legacy copy gets neither tester flag. The dataRoot
must be `<rehearsal>/data`, the one in the rehearsal config, not the live one. The live files must be
untouched.
10. M36 empties `tester_rehearsal` for a marked copy, and M37 gives a legacy copy the flag. Both are killed.
### Gate
11. The totals add up. Bus 627, WebUI 304 plus 1 skip, CLI 744, extras 230 and shells 429 make 2334/0/1.
The CLI log shows both new tests passing (ok 519, ok 520). The kill table has 38/38. M17 was re-run
because 222 changed `broker.mjs`. The other 29 targets have the same blobs, and I confirmed that in
item 2 for every manifest path.
## Condition
- C1. Round 1's N2 (dead `testerNoSignIn`) is deferred only in `queue-196/BUILD.md:122`. Add it to
`docs/plans/DEFERRED.md`, binding the next row that touches `webui/src/serve.mjs`. It's doc-only, so it
can go in the post-landing doc append with the BUILD-LOG lines and needs no new gate.
## Notes (non-blocking)
- N5. At 527b9a1e6, `startServer` (`serve.mjs:475`) destructures none of `libraryFile`, `libraryStatus`
or `librarySync`. So the three callbacks cli.mjs passes do nothing until a row adds the Console library
routes. That row has to decide whether the tester listener gets `library.sync`. My view is that it
shouldn't, because sync is a human write.
- N6. N1 and N3 are documented in BUILD.md:122, and N4 is the TOOLS.md paragraph. The TOOLS.md
paragraph is accurate.
## My runs
None. I read everything with `git show`, `git diff`, `git grep`, `git merge-file` (in a scratch dir under
/mnt/storage/scratch/tmp, removed) and `sha256sum` on blobs, plus `python3 -B` to read `killers/results.json`. I ran no node, and no tests or queue reads.
+1
View File
@@ -1447,3 +1447,4 @@ are never rewritten or removed; corrections are new entries.
2026-10-21T13:36Z | Duckworth (Opus 5.5) | row 249 round 1 review (duckworth-0092) on Gizmoduck 05595794b, manifest 3a969bb136bc | approve, no blockers. Webby's 248 N1 (X5 sleep 30) ruled defer to DEFERRED.md, with a cleanup condition |
2026-10-21T19:44Z | Duckworth (Opus 5.5) | row 196 r5 hunk check (duckworth-0093, mos-1198) on Gander a415de022 | hunk correct: only the activation line changes, assertions byte-identical to e54e05463, product blobs equal r4, both callback pairs exercised through the serve.mjs stub |
2026-10-21T20:14Z | Duckworth (Opus 5.5) | row 196 build+manifest round 1 (duckworth-0095), whole 39-path candidate 05e940117 vs DESIGN r3 | changes: B1 T10 activation gate/evidence untested, B2 T7 rehearsal socket untested; test-only, product holds; record held per sage-2135 |
2026-10-21T20:52Z | Duckworth (Opus 5.5) | row 196 round 2 merge-scoped (duckworth-0098), candidate 527b9a1e6 (537d30ae) on f48725cfc: B1/B2 tests, M30-M37, 222 hunks in runtime.mjs + webui cli.mjs | approve, C1 N2 to DEFERRED.md in post-landing doc append; N5 library callbacks inert in serve; record waits on Sage queue-write gap |