Test-only round for Filbert's changes request (comment 28639): three new staff-request tests, mutants N1, N2, N2b and n2f added (25 of 25 killed), chief-of-staff.md conflict with row 146 resolved keeping both bullets. Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
9.2 KiB
Row 140 (#1634) round 2: the pm asks the chief of staff for staff, and the chief hires and launches
Seat: Researcher. Reviewer: Filbert. Gate owner: Sage.
Brief: docs/plans/2026-10-15_q167-north-star-rows.md, the row 140 section (REQ-COS-1).
Round 1: ../build.md. Filbert asked for changes on #1634 (comment 28639). He found the code correct; the finding is test-only. This round adds the tests and the mutants he asked for, and rebases onto the landed rows 146 and 142.
Base and candidate
Base: 02ee7f640 (detached worktree /mnt/storage/scratch/researcher/q140r2). Canonical HEAD was c66c7fb71 at packet time; git diff --name-only 02ee7f640 HEAD -- packages roles scripts docs/TOOLS.md package.json is empty (the commits after 02ee7f640 touch docs and agents only).
row140.patch (this directory) is my diff on 02ee7f640: 11 files, +429 −5. It passes git apply --cached --check on 02ee7f640 and round-trips to the candidate tree 87633b89509c4a9fcc914492e5d5968772f5342f (temp GIT_INDEX_FILE, trees equal). candidate-manifest.sha256 lists the 11 files (sha256 of the manifest: 04a381e88eeee7be99ddd4a1911cc3f5a3211668a47e7da962bb29da26d84c43). Secrets and binary scan of the patch: nothing. Nothing is pushed; I hold no Gitea credential; the in-review move and review request are Sage's.
What changed since round 1
Round 1's patch was +354 −5 on dda7e31b0. Round 2's is +429 −5 on 02ee7f640. Per file, only packages/bus/tests/staff-request.test.mjs differs in size (198 to 273 added lines). The other ten files carry the same added lines as in round 1. No production code of mine changed.
Rebase
Rows 146 (277d1fa21) and 142 (02ee7f640) landed after dda7e31b0. Of my 11 files, three sit under paths they touched: packages/bus/src/broker.mjs and packages/bus/README.md (146) and roles/chief-of-staff.md (146). The first two applied with no conflict. One conflict, in roles/chief-of-staff.md: 146 put a bullet about messages from _bus where mine goes. I kept both bullets: 146's _bus bullet first ("A message from _bus is the bus telling you…"), then mine ("Answer a staff request. The pm role sends you a STAFF-REQUEST message…"). 146 had also replaced the stale "until the broker gives you a verb" sentence with the change_organization text, so the note I left for it in round 1 is closed.
Filbert's finding and the three new tests
N1 and N2 survived round 1's tests because every fixture gave an instance the same name as its role definition (instance pm with the pm definition, instance chief with the chief-of-staff definition). A check written against the instance name passed all seven tests. The broker judges both ends by role definition (b.roles[s.role]?.definition !== STAFF_FROM, b.roles[chief]?.definition !== STAFF_TO), so the tests now use names that differ from the definitions. setup() takes an arbiters option and returns staffEvents() (the action.allowed events whose operation is staff.request).
The file has 10 tests (was 7). New:
- The sender is judged by definition. Instance
lead, with thepmdefinition, sends and the chief receives it fromlead. Instancepm, with thecoderdefinition and pm authority, getsstaff-request-refused, and nostaff.requestevent is left. - The launcher is judged by definition. Launcher
boss(thechief-of-staffdefinition,launch.by: 'boss') receives the request. Launcherchiefwith thecoderdefinition givesno-chief-of-staff; no event and no message is left. - A refused staff request leaves no
staff.requestaction.allowedevent. Three refusals: no launcher (no-chief-of-staff), a coder sender (staff-request-refused), androles: [](invalid-request). The event count is 0 after each. This is Filbert's assertion 5.
Assertion 5 has no mutant target, and that is on purpose. The missing event is not produced by a line that can be deleted. The request runs in one transaction, so its action.allowed event rolls back when a later check refuses. Nothing in broker.mjs says "delete the event on refusal", so there is nothing to mutate; removing the transaction would be a design change, not a mutant. The assertion pins the behavior (a refused request writes nothing); no mutant targets it. Filbert asked for the assertion, not a mutant.
Mutants
mutants.sh <worktree> <outdir> is round 1's script with four mutants added after m21. Each edits broker.mjs exactly once (the dry run, MUTANT_DRY=1, found every edit once on the new base):
| Mutant | Edit | What it models |
|---|---|---|
N1 (n1-sender-by-name) |
if (s.role !== STAFF_FROM) fail('staff-request-refused'); |
the sender checked by instance name, not definition |
N2 (n2-launcher-by-name) |
if (!chief || chief !== 'chief') fail('no-chief-of-staff'); |
the launcher checked by instance name |
N2b (n2b-launcher-exists-only) |
if (!chief || !b.roles[chief]) fail('no-chief-of-staff'); |
any existing launcher accepted |
n2f (n2f-filbert-recipient) |
if (!b.roles[chief] || chief === 'coder') fail('no-chief-of-staff'); |
Filbert's own N2 text (sage-0430): the recipient check becomes "exists and is not named coder" |
Run 2026-10-15T23:56:41Z to 23:56:50Z on q140r2 (mutants-run.txt, mutants-started.txt, mutants-finished.txt; one .out, .rc and .patch per mutant in mutants/). The slot was Sage's "slot yours" (sage-0455); a busy check by exit status (/proc cwd links only) read CLEAR before and after. HEAD was 02ee7f640 and the candidate tree was 87633b89… before and after.
Three controls (staff-request, tools and bundle tests on the unmutated candidate) pass 10/10, 18/18 and 21/21. All 25 mutants fail their test file by a named assertion (rc=1 each, no timeout kills). The worktree was restored: no unstaged diff, git write-tree equals the candidate tree.
New mutants and what kills them:
| Mutant | Killed by | Round 1's seven tests |
|---|---|---|
N1 n1-sender-by-name |
the sender-by-definition test, and only that one | passed 7/7 (survived) |
N2 n2-launcher-by-name |
the launcher-by-definition test, and only that one | passed 7/7 (survived) |
N2b n2b-launcher-exists-only |
the launcher-by-definition test and "the request goes to the business launcher, and only when that is a chief of staff" | killed already by the second one |
n2f n2f-filbert-recipient |
the launcher-by-definition test, and only that one | passed 7/7 (survived) |
The round 1 column is from running round 1's seven-test file (control 7/7) against the same four edits on dda7e31b0, on 2026-10-15 at about 23:19Z to 23:21Z, as single test files in a scratch worktree (sage-0427). The n2f run overlapped the start of Rocko's slot by about 45 seconds; I reported that to Sage at the time. round1-tests-on-new-mutants/ holds their output (N1, N2 and n2f: 7/7 pass; N2b: 1 failure, the business-launcher test). The new tests also kill round 1's mutants more often than before: m1 fails 3 tests (was 1), m3 2, m15 3, m17 5.
Round 1's 21 mutants (m1 to m21) are unchanged and all still fail on the new base: m1 3 tests, m2 2, m3 2, m4 1, m5 1, m6 1, m7 to m10 1 each (the shape test), m11 2, m12 to m14 1 each, m15 3, m16 1, m17 5, m18 6 (tools.test), m19 1, m20 1, m21 1 (bundle.test). The launcher end-to-end test still has no mutant of its own, as in round 1.
Assertion 5 (a refused request leaves no staff.request event) has no mutant, per the section above; m1 and m3 fail that test only because they let a request through, not because they target the rollback.
Verification
Each test file singly (touched/, others/), on the candidate tree at 02ee7f640, 2026-10-15T23:43:52Z to 23:45:39Z, all rc=0:
- The four files this row changes:
staff-request.test.mjs10/10 (packages/bus/tests/),tools.test.mjs18/18,bundle.test.mjs21/21 (packages/harness/tests/),launcher.test.mjs18/18 (packages/cli/tests/). The launcher test uses the real bwrap runner and ran (it is skipped without one). - Every other test file in the bus, harness and cli packages: 61 files, rc=0 each (
suites/others/_summary.txt). Row 145's lesson: a same-blob test can break on a new base, so I ran all of them and not only the files the rebase touched.
The full gate was not rerun for this packet. Sage's rule is that the gate runs at landing. I ran the bus, harness and cli test files singly, as above; I did not run the whole suites in one process, the other packages' suites, or scripts/test-*.sh. Round 1's gate (22:59 to 23:03Z on dda7e31b0, all green) does not cover this candidate, because the base and the test file changed. No Docker gate ran, so there is no network to clean (docker network ls shows none of mine). No flake (#258, #261, #262, #263) recurred in any run above. After the mutants, nothing of mine is running (/proc cwd links under my scratch show only the shell).
Not in this packet
- The Console's send text and the STAFF-REQUEST body wording stay as in round 1 (the body is guidance, not enforcement).
- A live pm and chief exchanging a real request; the evidence is the in-process tests and the launcher test.
- Carried from row 132, unchanged by this row: the
change_organizationdescription says "replaces" while the broker merges per instance; a revision-only call is refused by the writer, not by the schema.