Row 286 r3: fix new credential fixtures and record green CLEAR gate with killed mutants

This commit is contained in:
jason.woltje committed 2026-10-24 06:22:49 -05:00
1 parent b7d3949285
commit 02f1c2df63
10 files changed
+1298 -8

No files matched your search

+2
View File
@@ -5503,3 +5503,5 @@ claim. Receipts and limitations in agents/lena/work/queue-296/BUILD.md and run-r
2026-10-24T10:21Z | Beakley (88b97f65) | Row 217 round2 slot verified, sage-4042/4043 | Source 2d274a5b6: touched57/57, whole library142/142 business270/270 bus974/974 cli988/988 harness172/172 seat218/218, all zero fail/skip/cancel. M1-M5 killed, controls/restored controls green, product hashes restored after each; E4 RED stand-in observed. Only first-red was new runtime fixture invalid-authority, corrected and retained in receipts; no old test failed/edited. Local root/webui npm ci, short TMPDIR, timeout-k10; no canonical npm/rm or module link. Full evidence agents/beakley/work/queue-217/run-r2; Sage owns scripts landing gate and formal review.
- 2026-10-24 (rockerduck, row 286 / #1791, r3 before gate): transplanted Ludwig 45dca69f6..573fa0be0 onto b19ffa04f, preserved newer exports in sole index.mjs conflict; plain-text range-diff, patch IDs and reader/pin drift inventory in agents/rockerduck/work/queue-286/BUILD.md. UNTESTED by sage-4040: no setup or tests until CLEAR.
- 2026-10-24 (rockerduck, row 286 / #1791, r3 after sage-4054 CLEAR): own-worktree installs; library 140/140 and bus 963/963; M1 forced-refspec and M2 missing-inode-compare killed at semantic assertions, restored before final suites; all gate-output fixture searches zero. Four first-run reds only in new credential test; setup corrections and intermediate findings recorded in agents/rockerduck/work/queue-286/BUILD.md. No old test edited during gate; shell/CLI suites remain Sage landing gate.
+64
View File
@@ -458,3 +458,67 @@ The changed reader/mapping/survey interfaces add supporting scope and editor.use
- First push succeeded through the repository helper; remote ls-remote confirms 29e830cac8f9ad1cd7e449eefd6053c7c2b841ab on rockerduck/row286-r3. Ready-for-CLEAR sent to Sage as rockerduck-0002.
- git diff --check passed. Both changed test files compare byte-identically to Ludwig 573fa0be0; pre-existing sync test bodies compare byte-identically to b19ffa04f. These are static checks only.
- No setup, npm, tests or mutants run. Remain at the explicit CLEAR boundary.
## CLEAR gate (sage-4054, 2026-10-24)
Sage released the slot at 10:33:37Z for 4b8261f41. Dependencies installed only in this worktree:
- Root: npm ci --ignore-scripts --no-audit --no-fund -> 0 (128 packages).
- packages/webui: same command -> 0 (2 packages).
- Short TMPDIR created using export TMPDIR=$(mktemp -d /mnt/storage/scratch/tmp/XXXXXX).
- Commands: timeout -k 10 900 node --test packages/library/tests/*.test.mjs;
timeout -k 10 1800 node --test packages/bus/tests/*.test.mjs.
- No scripts/test-*.sh run by this seat: Sage runs every shell suite at landing; CLI counts from that landing gate (mos-1561).
- Queue commands are no longer wrapped in timeout (sage-4054); no lock edits.
First-run results: library 140/140; bus 959 passed, four failed, all in the NEW
packages/bus/tests/library-credential.test.mjs. No old-test red. New-test setup fixes,
placed under sage-4054 / mos-1272 without changing production policy:
1. T7/T9 grant-chief-only at original line 150: boss is definition pm, and grant raises
require chief-of-staff. Bind/claim the existing chief and let it raise its own grant;
boss retains the separately ruled fire role. No SQL staging for grants/revokes/fire.
2. T7 rehire at original line 215 and T8 two-chief at original line 234: Broker clones
its input. Explicitly reloadBusiness after changing each fixture organization.
3. Next T9 run reached runtime and exposed its app project's missing checkout root
(project-path). Give verbDoc an explicit scratch root and app-checkout path.
4. Next T9 assertion read credential before the initial timer published: command
construction only marks the start of the fetch. Wait for the completed sync log.
Also register runtime.close with t.after so assertion failure cannot retain its timer.
5. Reopen of the shared T9 store found the fixture runs still claimed (role-already-held).
Release those runs through role.release before closing/reopening the fixture broker.
Focused credential reruns exposed each newly reached setup path; final focused result
6/6. The intermediate fixture run with a failed assertion retained a timer; its own
180-second timeout process was terminated and the next run registered runtime cleanup.
No other seat/process or canonical state was changed.
Final complete suites after fixes and restored mutants:
- library: 140 tests, 140 pass, 0 fail/cancelled/skipped/todo; exit 0.
- bus: 963 tests, 963 pass, 0 fail/cancelled/skipped/todo; exit 0.
- Both production trees match pre-gate 4b8261f41 byte-for-byte (git diff --quiet).
- The pre-existing sync test declaration block still matches b19ffa04f byte-for-byte.
Mutants (sequential, restored in finally before final suites):
- M1 adds + only to syncCommand's push refspec. timeout -k 10 180 node --test,
pattern 'C2-03b argv|C2-03b T2', sync.test.mjs: exit 1, 2/2 semantic failures
at argv assertion line 331 and race result assertion line 365.
- M2 removes only askpass's inode comparison. Same timeout, pattern 'C2-03b T5 helper':
exit 1, swapped-file refusal assertion at lines 510/526 fails.
- A scratch Node reporter prints failed test names, assertion locations and counts only;
it excludes assertion values so the deliberately broken helper cannot print a fixture
token in diagnostics. Both mutants' output searches found zero matches.
Evidence: gate-library.txt and gate-bus.txt contain final full text output;
mutant-M1.txt and mutant-M2.txt contain mutant failure locations/counts. token-search.txt
records exact fixture-string and general-pattern match counts for every captured run.
Six exact fixture values were checked in memory; every count is zero. T1/T9 also cover
argv, mirror config, data-root files and runtime log non-disclosure as specified in Ludwig's
T11 map. No fixture values are printed by the search.
The static-output slip reported before CLEAR remains in the earlier operational record;
it is not represented as a clean source-inspection history. The gate-run outputs are clean.
Candidate manifest covers all nine changed packages paths, inherited Ludwig rulings,
this BUILD and gate receipts. Shared append-only BUILD-LOG/SESSIONS are excluded from
candidate hashes so unrelated later appends do not invalidate the review.
Scratch run directory retained for landing audit: /mnt/storage/scratch/tmp/FcfQ9q
@@ -0,0 +1,16 @@
7fab157be380502b726c4a84772bfb667850766062e4952b73f172f5ada363ed agents/ludwig/work/queue-286/BUILD.md
7ce8537c45ab0dc66a6a33c1f0db838506c96e4fe313dc197755aa7aa0dd41cb agents/rockerduck/work/queue-286/BUILD.md
e5026111e3c84f1294c80631fc5d5dad6dc77166209acdfd07c6ea8755469e19 agents/rockerduck/work/queue-286/gate-bus.txt
4e191637baa4d8683679fd6e84d81e29ec6fe64faf38b4b33f9b5965fce1dfcf agents/rockerduck/work/queue-286/gate-library.txt
50291819572752733a1c33e846e1e1e8d66e89b677a6a6d0cc7d2402e8fa82ea agents/rockerduck/work/queue-286/mutant-M1.txt
ade72e9641ac5ee97b1ceaa266d54b48d28d0d613f415a030547963664a04646 agents/rockerduck/work/queue-286/mutant-M2.txt
b3b9a19825a43f33942746bbaaa93670453d4f21b63005d915d9cf92523e9143 agents/rockerduck/work/queue-286/token-search.txt
b6c4c71e83d90a4415337cd5bad93200232ff3a74e0bdc303c1351c2f1a4aae4 packages/bus/src/broker.mjs
a93e322bd27fea2a5fe6a2f89aad04d9cf96b6cc2004dc1c663af5a46494fb09 packages/bus/src/runtime.mjs
44e62c044caf66358c4469cd1549aebadaa1bc22e681e4e2ce1c8e07dae649b4 packages/bus/tests/library-credential.test.mjs
d9c523d830c57df9fedf5cb42e6c74999fde529751e8a5eea95b3ae097d8548d packages/library/README.md
5c9b528fd69a2493f04933fc84f352b1101d276d69d9982806975def614fd740 packages/library/bin/askpass
978c7a404baeb52c472948a57a606c0881793c25ee85feef68b681f9ea15fc05 packages/library/src/index.mjs
0bea0f3553ecfca8bee81e545faf5142e5fa6521ea971fbd2d8a78932d644f2b packages/library/src/mirror.mjs
784af63a417b547b195ca835878daeba5b696b42a83a4c95de6728a0efa75e38 packages/library/src/sync.mjs
c8500795d80f56536f0ffd17bcad4f38778d4b06ec39030200c17f31c750ac94 packages/library/tests/sync.test.mjs
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,149 @@
✔ the same commit, repo path and mapping return the same index, and only mapped files are in it (38.910506ms)
✔ a different repo path, mapping or commit gets its own index (58.789692ms)
✔ the cache holds at most eight indexes and evicts the least recently used (78.224098ms)
✔ a failed read is not kept in the cache (15.140975ms)
✔ a missing or unchecked mapping is refused before any read (12.020832ms)
✔ a 3,000-file rebuild completes and its time is reported (2900.628078ms)
ℹ 3,000-file index rebuild: 2680 ms
✔ resolver step 1: a path from the repo root, with or without .md (1.1254ms)
✔ resolver step 2: the same path with vaultPrefix/ stripped (0.211505ms)
✔ resolver step 3: a path relative to the linking file, never above the repo root (0.200699ms)
✔ resolver step 4: a base name that matches exactly one indexed file (0.260396ms)
✔ a link into another of her repos resolves to nothing (0.191988ms)
✔ wikilink forms, embeds, and links skipped inside code (1.098741ms)
✔ only a body embed whose target has an extension other than .md, in any case, is an attachment (0.349473ms)
✔ the fixture mapping checks and comes back frozen (2.412937ms)
✔ C2-01c: a prefix inside or holding another entry's book refuses library-playground-other-universe (1.155505ms)
✔ C2-01c: a prefix equal to a book folder, or holding its own, refuses library-mapping-invalid (0.650366ms)
✔ C2-01c: universe-level prefixes lie outside every book, in a plain universe and in a hybrid with no books (0.710421ms)
✔ C2-01c: a draft takes kind, name and playground only, and comes back frozen with books [] (1.484212ms)
✔ C2-01d: supporting prefixes at book level, universe level, in a hybrid and in a draft, [] when absent (0.537029ms)
✔ C2-01d: each supporting prefix rule refuses with its code (1.971647ms)
✔ C2-01d: between the lists, a supporting prefix may equal its own playground, and a playground may hold its own supporting (0.392589ms)
✔ C2-01d: editor is optional, kept when given, and refuses anything but a plain name and email (5.280718ms)
✔ C2-01d: an accepted editor round-trips through a real git commit unchanged (15.73724ms)
✔ no playground prefix holds another, and no book folder holds another (0.934567ms)
✔ shape refusals: kind, remote, branch, unknown keys, types, manuscript, folder names (1.116891ms)
✔ C2-03a sage-2021: user is optional, kept when given, and must be a plain account name (0.777602ms)
✔ a hybrid universe is a shape the query code can take (1.4), with sources that must exist (1.069424ms)
✔ a caller-supplied fail receives the code, as business file loading will pass it (C2-04) (0.375805ms)
✔ scope comes from the path alone (design 1.2) (0.696744ms)
✔ C2-04 mirror: exact default path, bare without checkout or remote, and idempotent initialization (59.246676ms)
✔ C2-04 mirror: simultaneous creators publish one intact mirror and leave no staging paths (42.751841ms)
✔ C2-04 mirror: skipped publication accepts both coreutils statuses without removing the winner (137.796639ms)
✔ C2-04 mirror: preserve occupied directories and reject symlink ancestors and code overlaps (16.53077ms)
✔ C2-04 mirror: existing metadata accepts only bare Git plus state and the precreated lock (29.399708ms)
✔ C2-04 state: missing state is empty only while the served ref is absent (51.916373ms)
✔ C2-04 state: valid problems and sync metadata return no content and change no state bytes (46.274776ms)
✔ C2-04 state: strict keys, types, times, branch, commit and fixed R messages fail closed (131.367058ms)
✔ C2-04 state: symlink, hardlink, non-private state and missing lock refuse without replacement (37.826957ms)
✔ C2-04 file: served commit, not HEAD or a caller commit, owns the exact returned text (84.427946ms)
✔ C2-04 file: R1, R2 and R7 exclusions and never-synced mirrors cannot return file bodies (100.550125ms)
✔ C2-04 lock: a first-sync and fast-forward reader wait for a consistent pair across processes (258.847103ms)
✔ C2-04 lock: same-process waits, timeout code, callback expiry and throw release (5032.288443ms)
✔ C2-04 lock: owner death releases the kernel lock without replacing its file (54.703792ms)
✔ C2-04 lock: a missing flock binary becomes a handled refusal (50.127819ms)
✔ C2-04 lock: an unawaited scoped read drains before the lock is released (19.957011ms)
✔ the query reply cap equals the harness reply cap (1.19734ms)
✔ find is bound to its universe and refuses a call without one (53.893139ms)
✔ every result carries its scope, and playground appears only when asked for (32.313169ms)
✔ unmapped files never appear in any reply (27.837074ms)
✔ a hybrid sees its sources canon, minus exclusions, and no playground (30.347014ms)
✔ a hybrid gets a source file it can see, and not an excluded or foreign one (41.713814ms)
✔ get lists visible links both ways and drops a target another universe cannot see (41.538976ms)
✔ a long list pages by position, never cuts an item, and returns 50 per page (162.791386ms)
✔ a page stays under the reply cap when items are large (78.463045ms)
✔ a search line too long to fit alone comes back marked, with no excerpt, and the other hits still return (29.164591ms)
✔ a find item that cannot fit alone is refused, not cut (28.322729ms)
✔ get pages its lines, and the next line picks up where the page stopped (30.368574ms)
✔ get refuses a file whose front matter alone is over the cap, and a line alone is over the cap (28.128026ms)
✔ get pages the links of a hub note, every page carries the front matter, and the pages add up (869.902906ms)
✔ get rejects a bad links_from (35.196585ms)
✔ search returns scoped line hits, case-insensitively, and refuses empty text (28.459891ms)
✔ a manuscript call returns one chapter, at most 400 lines, and names its next line (46.946258ms)
✔ a manuscript call without a chapter returns the first chapter in path order and names the next (26.573024ms)
✔ a chapter name that matches two visible files is refused (24.016997ms)
✔ a hybrid reads a source chapter through its declared sources only (35.070966ms)
✔ universe info reports a hybrid sources, constraints and notes, and refuses an unknown universe (13.168062ms)
✔ an exclusion hides what it names from a hybrid and from nothing else (36.359286ms)
✔ PRD 1.14: a lookup that names a book leaves book-null files out (30.463487ms)
✔ PRD 1.14: library_manuscript never reads a book-null file (29.534997ms)
✔ PRD 1.14: a draft universe has no canon, so its lookups return files only with scope playground (29.89583ms)
✔ PRD 1.14: library_universe on a draft returns its kind, name and prefixes (14.363564ms)
✔ a hybrid gets a source playground file as null, while the source gets it with scope playground (37.6646ms)
✔ the fixture reads clean: every resolver step, appears_in and relationships wikilinks indexed (48.455238ms)
✔ R1: executables, symlinks, gitlinks, blobs over 1 MiB and non-UTF-8 text are not indexed (76.694953ms)
✔ R2: unmapped paths are reported and not indexed (26.809308ms)
✔ R3: front matter not fully parsed stays raw, with the line where parsing stopped (31.113448ms)
✔ front matter forms the reader accepts and refuses (0.475374ms)
✔ R4: a link to no file, to more than one, or into another repo is reported and not followed (29.384746ms)
✔ a block list link carries its item line, a scalar or flow link its key line, and problems follow (28.900438ms)
✔ an unresolved attachment embed gives no problem; a link or front matter value to one is R4; a note embed resolves (29.126382ms)
✔ an indexed Dr.Quinn.md resolves as a body link, a block list link and an embed (29.274318ms)
✔ R5: a canon file that refers into the playground is reported, and the link still goes by path (29.580541ms)
✔ R6: a canon file that refers into another universe is reported; a hybrid may refer into its sources (24.571442ms)
✔ R7: two paths that differ only in case are both left out (31.165932ms)
✔ the reader reads the commit, never the working tree, and refuses a bad commit id (28.951224ms)
✔ a bare mirror reads the same as the clone (46.972003ms)
✔ renderItems snapshot: fact (1.417516ms)
✔ renderItems snapshot: finding (0.276536ms)
✔ renderItems snapshot: correction (0.22018ms)
✔ renderItems snapshot: question (0.181125ms)
✔ renderItems snapshot: idea (0.204383ms)
✔ renderItems numbers several items and takes a parsed body as well as a string (1.006969ms)
✔ without options a path cite has no badge and is never marked changed (0.236544ms)
✔ renderItems snapshot: notice no-cited-answer (0.194799ms)
✔ renderItems snapshot: notice no-answer (0.230859ms)
✔ renderItems snapshot: notice turn-failed (0.2386ms)
✔ a body without the reply shape shows a fixed line and none of its text (0.636756ms)
✔ C2-01c: each level gives its universe, and its book or null (3.423205ms)
✔ C2-01c: prefixes come first: in a book that holds a prefix, a file outside it is canon and one under it playground (0.57979ms)
✔ C2-01c: a canon file linking into a draft gives R6, and into its own universe-level prefix gives R5 (50.419041ms)
✔ C2-01d: each supporting level gives its universe, and its book or null (0.8375ms)
✔ C2-01d: supporting comes before playground; a folder in both lists is supporting, one in the playground only stays playground (0.479654ms)
✔ C2-01d: only .md files are supporting; a .canvas or .base under a supporting prefix is unmapped (0.290969ms)
✔ C2-01d: a path passes at book level, universe level, in a draft and in a folder in both lists (2.074148ms)
✔ C2-01d: a path of exactly 1024 bytes passes, and 1025 bytes made of multi-byte characters refuses (0.982879ms)
✔ C2-01d: a path outside the universe's supporting folders refuses (0.71389ms)
✔ C2-01d: malformed paths refuse by class, in order (0.646566ms)
✔ C2-01d: a symlink or gitlink on the way, or at the path itself, refuses (0.31072ms)
✔ C2-01d: a name that differs from a tree name only in case or Unicode form refuses, at the file or any folder (1.011818ms)
✔ the survey prints folder names, counts, key sets and link-form counts, and never text (49.619419ms)
✔ folder names print DEL, C1 and bidi controls, U+061C among them, as escapes (26.757812ms)
✔ an embed of an attachment counts as an embed and as an attachment; a plain link to one does not (19.118043ms)
✔ with --mapping the survey adds scope, resolver step and problem counts (41.583182ms)
✔ C2-01d: with --mapping the survey counts supporting files (37.584205ms)
✔ survey exit codes: usage 4, bad mapping 3, unreadable repo 2 (15.886586ms)
✔ scripts/mosaic library survey reaches the survey (98.91682ms)
✔ C2-03a argv: the fixed sequence, one https allow, no other protocol key (2.475406ms)
✔ C2-03a argv: only an https URL with a plain host, no userinfo, and a plain user (0.920886ms)
✔ C2-03a helper: answers only the exact prompts for the configured host and user (dewey-0765) (40.63027ms)
✔ C2-03a first sync: served is the fetched tip, HEAD is served, the survey reads it, and the token stays in the slot (164.393615ms)
✔ C2-03a fast-forward: served moves, problems are rebuilt, and a repeat changes only lastFetch (242.672377ms)
✔ C2-03a Filbert N2: a read that took served before a sync still finds its objects after served moves (201.409814ms)
✔ C2-03a overlap: a reader during a sync sees the old pair or the new one, never a mix (182.181215ms)
✔ C2-03a diverged: a non-fast-forward keeps serving and holds until a human accepts the tip (414.515618ms)
✔ C2-03a accept starts the record over, so a changed branch gets a fresh state (174.335397ms)
✔ C2-03a fetch failure: a wrong token keeps serving and records the error, lastFetch unchanged (200.468866ms)
✔ C2-03a a failed first fetch records the error with nothing served (60.013342ms)
✔ C2-03a a 302 to another host fails the fetch and the other host sees nothing (63.037701ms)
✔ C2-03a the slot: missing or unsafe refuses before git, and sync never opens it (59.780442ms)
✔ C2-03a sage-2021: an entry with no user refuses library-remote-invalid and runs no git (31.991782ms)
✔ C2-03a one sync per mirror: an overlapping call refuses library-sync-busy (127.65035ms)
✔ C2-03b argv: a push sends one full commit to the branch, fast-forward only, with the fetch prefix (0.498418ms)
✔ C2-03b T1 push: a fast-forward lands with the seat's own user and file, and moves no local ref (123.563433ms)
✔ C2-03b T2 and T3: a moved tip reports the race after one fetch, and a second race refuses stale-base (201.045487ms)
✔ C2-03b race fetch: while a sync of the mirror runs, the race refuses library-sync-busy (217.586092ms)
✔ C2-03b T4: a dead remote, a hook refusal and a wrong token each refuse library-push-failed (150.972736ms)
✔ C2-03b push: a refused, missing or unsafe credential runs no git (91.830589ms)
✔ C2-03b T10 humanCredential: her login and a 0600 slot library-human, or library-human-missing (0.868836ms)
✔ C2-03b fetch credential: the state names the kind and user, a refusal runs no git, and a pre-286 state still reads (134.468925ms)
✔ C2-03b T5 helper: the named seat's user and file, never a link, 0644, another uid, or a swapped file (27.628362ms)
ℹ tests 140
ℹ suites 0
ℹ pass 140
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 6220.993116
@@ -0,0 +1,6 @@
FAIL C2-03b argv: a push sends one full commit to the branch, fast-forward only, with the fetch prefix ERR_TEST_FAILURE
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row286-r3/packages/library/tests/sync.test.mjs:331:10)
FAIL C2-03b T2 and T3: a moved tip reports the race after one fetch, and a second race refuses stale-base ERR_TEST_FAILURE
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row286-r3/packages/library/tests/sync.test.mjs:365:10)
SUMMARY {"tests":2,"failed":2,"passed":0,"cancelled":0,"skipped":0,"todo":0,"topLevel":2,"suites":0}
SUMMARY {"tests":2,"failed":2,"passed":0,"cancelled":0,"skipped":0,"todo":0,"topLevel":2,"suites":0}
@@ -0,0 +1,5 @@
FAIL C2-03b T5 helper: the named seat's user and file, never a link, 0644, another uid, or a swapped file ERR_TEST_FAILURE
at refused (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row286-r3/packages/library/tests/sync.test.mjs:510:40)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row286-r3/packages/library/tests/sync.test.mjs:526:3)
SUMMARY {"tests":1,"failed":1,"passed":0,"cancelled":0,"skipped":0,"todo":0,"topLevel":1,"suites":0}
SUMMARY {"tests":1,"failed":1,"passed":0,"cancelled":0,"skipped":0,"todo":0,"topLevel":1,"suites":0}
@@ -0,0 +1,12 @@
Fixture exact values checked: 6
M1.log: exact=0, pattern=0
M2.log: exact=0, pattern=0
bus-final.log: exact=0, pattern=0
bus.log: exact=0, pattern=0
credential-rerun.log: exact=0, pattern=0
credential-rerun2.log: exact=0, pattern=0
credential-rerun3.log: exact=0, pattern=0
credential-rerun4.log: exact=0, pattern=0
credential-t9.log: exact=0, pattern=0
library-final.log: exact=0, pattern=0
library.log: exact=0, pattern=0
+2
View File
@@ -1636,3 +1636,5 @@ are never rewritten or removed; corrections are new entries.
2026-10-24T10:21Z | Beakley (88b97f65) | Row217 #1718 round2 slot | All touched57 and six whole suites2764 pass, zero skips/cancels; M1-M5 killed/restored, E4 RED stand-in observed. First-new runtime fixture red recorded and corrected; no old-test change/failure. Evidence in agents/beakley/work/queue-217/run-r2. Verified for review on beakley/row217-r2; Sage landing scripts/review remain.
- 2026-10-24 — rockerduck (Codex, a403aa78-b550-4bab-a613-7ea3fd75ec79), row 286 C2-03b / #1791 r3: twelve-commit transplant and static drift evidence prepared; UNTESTED, awaiting Sage CLEAR after own-branch push; no npm/tests run.
- 2026-10-24 — rockerduck (Codex, a403aa78-b550-4bab-a613-7ea3fd75ec79), row 286 / #1791 r3 CLEAR gate: library 140/140, bus 963/963, both mutants killed/restored, gate-output fixture matches zero; new-test setup fixes only; candidate prepared for Boyd review and Sage landing.
+25 -8
View File
@@ -76,7 +76,7 @@ function world(t, options) {
// The business for the real paths. `boss` is launch.by: instance.fire is the launch.by role's verb and
// refuses its own name (organization-instance-referenced), so the fired chief is the one listed
// chief-of-staff instance, fired by boss. The grant targets project app; books is the library.
function verbDoc(url) {
function verbDoc(url, root) {
return {
id: 'acme', human: 'jason', arbiters: { technical: 'boss', delivery: 'boss' },
roles: {
@@ -89,7 +89,8 @@ function verbDoc(url) {
pm: { roleVersion: 2, credentials: [] },
coder: { roleVersion: 2, credentials: [] },
},
projects: { app: { remote: `${url}/acme/app` }, books: { ...mappingEntry(), user: 'books-bot' } },
// sage-4054 / mos-1272: runtime validates every code project's absolute checkout root.
projects: { app: { root: join(root, 'app-checkout'), remote: `${url}/acme/app` }, books: { ...mappingEntry(), user: 'books-bot' } },
launch: { by: 'boss', instances: ['chief', 'coder'] },
};
}
@@ -112,7 +113,7 @@ async function verbWorld(t, opts = {}) {
const dataRoot = opts.dataRoot ?? join(dir, 'data');
mkdirSync(dataRoot, { recursive: true, mode: 0o700 });
const storeRoot = opts.storeRoot ?? join(dir, 'secrets', 'agents');
const doc = opts.doc ?? verbDoc(gitea.url);
const doc = opts.doc ?? verbDoc(gitea.url, dir);
const store = new Store(dataRoot);
const references = {};
const { held } = giteaStart(store, storeRoot, { acme: doc }, references);
@@ -142,12 +143,15 @@ async function verbWorld(t, opts = {}) {
});
const boss = broker.bindLaunch({ business: 'acme', role: 'boss', run: 'boss-run', harness: 'pi', address: 'boss' });
broker.request(boss, { verb: 'role.claim' });
// sage-4054 / mos-1272: grant raises require the chief definition, independent of launch.by's fire authority.
const chief = broker.bindLaunch({ business: 'acme', role: 'chief', run: 'chief-run', harness: 'pi', address: 'chief' });
broker.request(chief, { verb: 'role.claim' });
const human = broker.bindHuman({ business: 'acme', human: 'jason', via: 'cli', outsideAgent: true });
const events = () => store.all(`SELECT body FROM events WHERE business='acme' AND ${GRANT_EVIDENCE} ORDER BY seq`).map((e) => JSON.parse(e.body));
const ended = (id) => events().findLast((e) => e.grantDecision === id && ['grant.applied', 'grant.failed'].includes(e.action));
const row = () => store.get("SELECT 1 FROM gitea_grants WHERE business='acme' AND agent='chief'");
const approveChief = async () => {
const d = await broker.request(boss, {
const d = await broker.request(chief, {
verb: 'decision.raise',
args: {
action: 'credential.mint', question: 'Grant chief Gitea?', options, recommendation: 'yes', blocking: false,
@@ -172,7 +176,12 @@ async function verbWorld(t, opts = {}) {
await broker.grantsIdle();
assert.equal(row(), undefined, 'the fire\'s step G deleted the row (row 281)');
};
return { gitea, doc, store, broker, storeRoot, row, approveChief, revoke, fire, close, choose: () => broker.libraryFetchCredential('acme') };
// sage-4054 / mos-1272: a second fixture broker on this store needs the previous runs released.
const release = () => {
broker.request(chief, { verb: 'role.release' });
broker.request(boss, { verb: 'role.release' });
};
return { gitea, doc, store, broker, storeRoot, row, approveChief, revoke, fire, close, release, choose: () => broker.libraryFetchCredential('acme') };
}
const REFUSED = { refused: 'library-fetch-no-grant', fix: LIBRARY_FETCH_FIX };
@@ -212,6 +221,8 @@ test('C2-03b T7 choice checks: delisted, a fire under way and held each refuse;
grant(delisted.store, 'chief');
assert.deepEqual(delisted.choose(), REFUSED, 'delisted with the row still there');
delisted.business.launch.instances.push('chief');
// sage-4054 / mos-1272: Broker clones input; publish the fixture's organization change.
delisted.broker.reloadBusiness('acme', delisted.business);
assert.deepEqual(delisted.choose(), { kind: 'chief', agent: 'chief', user: 'chief-bot' }, 'a rehire lists it again');
delisted.store.run("INSERT INTO events(id,at,business,kind,actor_role,actor_run,subject,body) VALUES('f1',?,?,'action.allowed','chief','run','chief',?)",
AT, 'acme', JSON.stringify({ action: 'fire.stopped' }));
@@ -231,8 +242,10 @@ test('C2-03b T8: a chief grant on another project ends the fallback, and two lis
grant(two.store, 'chief');
assert.deepEqual(two.choose(), { kind: 'chief', agent: 'chief', user: 'chief-bot' });
two.business.roles.second = { definition: 'chief-of-staff', ...role };
two.broker.reloadBusiness('acme', two.business); // sage-4054 / mos-1272: publish the fixture change
assert.deepEqual(two.choose(), REFUSED, 'two chief-of-staff entries, both listed: one chief only');
two.business.launch = { instances: ['coder'] };
two.broker.reloadBusiness('acme', two.business); // sage-4054 / mos-1272
assert.deepEqual(two.choose(), REFUSED, 'neither listed');
});
@@ -263,6 +276,7 @@ test('C2-03b T9 runtime: the chief\'s store file and user, then a real revoke th
writeFileSync(slot, SLOT_TOKEN + '\n', { mode: 0o600 });
const granted = await verbWorld(t, { dataRoot, storeRoot });
await granted.approveChief();
granted.release();
granted.close();
const gitea = granted.gitea;
const chiefFile = join(storeRoot, 'acme', 'chief', 'gitea');
@@ -275,12 +289,14 @@ test('C2-03b T9 runtime: the chief\'s store file and user, then a real revoke th
return write.call(this, chunk, ...rest);
};
t.after(() => { process.stderr.write = write; });
const start = () => startBroker({ dataRoot, businesses: { acme: verbDoc(gitea.url) }, organization: { dir: root, rolesDir, system: systemFor(root) },
const start = () => startBroker({ dataRoot, businesses: { acme: verbDoc(gitea.url, root) }, organization: { dir: root, rolesDir, system: systemFor(root) },
librarySync: { command, intervalMs: 50 } });
const untilAsync = async (fn) => { const end = Date.now() + 10000; while (!fn() && Date.now() < end) await sleep(10); };
let runtime = await start();
await untilAsync(() => calls.length >= 1);
t.after(async () => { await runtime.close(); }); // sage-4054 / mos-1272: close even on assertion failure
// sage-4054 / mos-1272: command construction precedes publication; wait for the completed sync log.
await untilAsync(() => lines.length >= 1);
const human = runtime.broker.bindHuman({ business: 'acme', human: 'jason', via: 'cli', outsideAgent: true });
await runtime.broker.request(human, { verb: 'library.sync', args: { project: 'books' } }).catch(e => e);
// webby-0151 R3: library.status names the kind and user of the last fetch, never the file or value.
@@ -294,6 +310,7 @@ test('C2-03b T9 runtime: the chief\'s store file and user, then a real revoke th
// Revoked through grants.revoke: the next start refuses before git, and the log names the fix.
const revoking = await verbWorld(t, { dataRoot, storeRoot, gitea });
await revoking.revoke();
revoking.release();
revoking.close();
chmodSync(slot, 0o000);
calls.length = 0; lines.length = 0;
@@ -310,7 +327,7 @@ test('C2-03b T9 runtime: the chief\'s store file and user, then a real revoke th
assert.deepEqual(JSON.parse(lines[0].slice('library: '.length)),
{ event: 'library-sync-held', business: 'acme', project: 'books', code: 'library-fetch-no-grant', fix: LIBRARY_FETCH_FIX });
for (const line of lines) assert.equal(tokens().some(tok => line.includes(tok)), false);
const mirror = library.mirrorPath({ business: verbDoc(gitea.url), project: 'books', dataRoot });
const mirror = library.mirrorPath({ business: verbDoc(gitea.url, root), project: 'books', dataRoot });
const state = await library.readSyncState(mirror, { branch: 'main' });
assert.equal(state.lastError.code, 'library-fetch-no-grant');
assert.equal(state.credential, null);