Files
stack/agents/darkwing/work/queue-110/r2/build.md
T
jason.woltjeandClaude Opus 5.5 9f1563ec16 work: row 110 round 2 packet, the role-cap envelope case (#1604)
Folds Filbert's N1 per Sage's comment 28355: the envelope test sends a
role cap with a tester proof. The narrowing mutant at server.mjs:50
survives the full bus suite on round 1 and is killed on round 2. Full
gate passed with the real bwrap tester case running.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 20:28:46 -05:00

4.5 KiB

Row 110 (#1604) round 2: one more envelope case

Sage asked for changes in comment 28355 (rev 1093) and folded Filbert's note N1 into this round. Round 1 is agents/darkwing/work/queue-110/r1/. Everything in it still holds except the one test file below.

BASE: badfa52b9d, unchanged. Since BASE, the branch has changed only packet files, docs/SESSIONS.md, docs/plans/QUEUE.md and docs/plans/queue.json. No manifest path moved. Candidate: build.patch against BASE. candidate-manifest.sha256 lists the same 19 files as round 1. I applied the patch to a fresh git archive badfa52b9 export and every digest matched.

What changed

One file, packages/bus/tests/tester.test.mjs, in the test "an envelope carries exactly one of cap, human and tester; no tester authenticator refuses". The envelope loop gains a role cap beside the reader cap. r1-to-r2.diff is the whole change between the two candidates' applied trees:

   const cap = b.bindReader({ business: 'demo' });
-  for (const r of [{ tester: p, cap }, { tester: p, human: p }, { tester: p, human: p, cap }])
+  const role = b.bindLaunch({ business: 'demo', role: 'pm', run: 'pm-run', harness: 'pi' });
+  for (const r of [{ tester: p, cap }, { tester: p, cap: role }, { tester: p, human: p }, { tester: p, human: p, cap }])

The manifest line for that file goes from 39c225c5... to 167aa918.... The other 18 lines match round 1 byte for byte.

The narrowing mutant

mutant-n1.py in this packet. It narrows the conflict check at packages/bus/src/server.mjs:50 so a cap counts only when it is the envelope's sole credential or is a reader cap (broker.identity gives role null and no human). With the mutant, a role cap sent with a tester proof passes the envelope, and the request runs as the tester. The script swaps that one line, runs the whole bus suite (node --test tests/*.test.mjs in packages/bus), and puts server.mjs back from its .orig copy. Both runs report restored=True.

Candidate Bus suite under the mutant Result
round 1 (01:21:34Z) 147 pass, 0 fail survived
round 2 (01:21:50Z) 146 pass, 1 fail killed

On round 1 it survives every bus test, which is the gap Sage named. On round 2 the only failure is the envelope test. The new tuple gets { ok: true, result: [] } where the test expects { ok: false, error: 'invalid-envelope' } (mutant-n1-r2.log, the assertion at tester.test.mjs:337). The reader-cap tuple still refuses under the mutant, so the failure comes from the role-cap case.

The assertion message is Object.keys(r).join('+'), so both cap tuples print tester+cap. Sage's scope said nothing else changes, so I left the label alone. The actual value in the log shows which tuple failed.

Gate

gate.sh in this packet, run on the round-2 candidate with the slot from Sage, 01:22:27-01:27:55Z, on BASE badfa52b9 with DOCKER_HOST unset and docker 29.7.2. It runs every package's node suite and every scripts/test-*.sh. GATE_PASSED, exit 0. gate-run.log has the summary, and gate/ has one log per step. The worktree still matched the manifest after the run.

Step Passed Failed
bus 147 0
business 67 0
cli 184 0
control-board 124 0
conversation 182 0
discord 178 0
harness 80 0
ledger 78 0
mosaic 69 0
queue 156 0
runs 43 0
seat 120 (0 skipped) 0
tasks 92 0
webui 108 0
scripts auth 15, conductor 17, config 24, discord 66, extension-package 18, foundation 44, queue 28 (node 156), release 14, task 98 0

The counts match round 1. Bus stays at 147 because the new case sits inside an existing test.

The real bwrap tester case ran and passed. It did not skip. From gate/pkg-seat.log:77:

✔ a confined session that runs tester-cli.mjs is refused as tester, and the same shim outside the sandbox binds (262.780721ms)

Neither the review.test.mjs:123 flake (#261) nor the release active.json flake (#258) came back. The release step made wt_default at 01:27:13Z with no containers, and I removed it after the run.

Mutants from round 1

I didn't rerun the 96 round-1 mutants. The only change adds one more assertion to an existing test. A test with an extra assertion fails on everything it failed on before, so this round can only kill more mutants, never fewer. Two of them, s00 and s01, touch server.mjs:50, and round 1 killed both. Round 1's mutants-run.log (94 killed, b44 and b45 equivalent) ran on the round-1 candidate.