Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3586955286 | ||
|
|
a54a17f3d8 | ||
|
|
0cdead66cd | ||
|
|
1b6158ce26 | ||
|
|
081ff6b128 | ||
|
|
be86adbff2 | ||
|
|
d163afc47f | ||
|
|
e54e054632 | ||
|
|
6096b051b1 | ||
|
|
9a8c8860d3 | ||
|
|
6195a00f8d |
@@ -5177,3 +5177,5 @@ Before: managed project/thread verbs had no Console conversation area. After: fi
|
||||
2026-10-21T01:28:05Z | Darkwing | row 232 #1734 installer I1 build, round 1 in review | Before: stack-release.sh managed only user units (systemctl --user), and stack-copy.sh had no bundle copy. After: --units external (adopt, activate, rollback --to, status, confirm, revert, gate --since, AWAITING-UNITS, stale-start, external-pm, --plan --expect-from) and stack-copy check --units external, copy --bundle FILE SHA, wrapper ID --create; user mode byte-identical to the base by test. First build 0af0c73c6 on 00d4cc1f6; rebased onto row 200 (cb5fdb064) as a0ffabc3f on darkwing/row232-r1; --sso refused under external (D9), row 200 config_checks run under external (D10). Gate on Sage's slot (sage-1618): cli 561/0, every scripts/test-*.sh green; 17/17 mutants killed. Results commit 84f1a91e6 (pushed, seat branch only). Manifest 7a3b4ea1 (9 paths), queue revs 2595-2596, request comment 29825, reviewer Filbert. Packet agents/darkwing/work/queue-232/BUILD.md.
|
||||
2026-10-21T04:50:44Z | Darkwing | row 233 #1735 installer I3 build, round 1 in review | Before: root had no upgrade driver for root-owned units and no host run sheet; stack-release.sh had no rehearse --backup last and no external plan refusals. After: scripts/stack-upgrade.sh upgrade and rollback (r6 A1-A5, A2f, R1-R4) with 20 tests, docs/guides/host-run-sheet.md, TOOLS.md lines, and on Sage's rulings stack-release.sh --backup last, BACKUP_STORE and the --plan refusals open-activation and migrate-required (3 tests). Base e65a3ab4d (row 232's landing). Gate on Sage's slot (sage-1704) on d99166ade: cli 616/0, every scripts/test-*.sh green, 1201/0 summed by awk; m1-m8 8/8 killed. Correction: the process sweep after the gate found an orphaned sleep 60 from the lock test's flock holder (N1); 08db6ac3f fixes it test only, Sage ruled the gate stands (sage-1707), rerun c0 20/0 and m1 killed with 0 left (sage-1708). Tip 1a1dc80ca (pushed, seat branch only). Manifest 464ce9eb (7 paths), queue revs 2644 and 2647, request comment 29901, reviewer Filbert. Packet agents/darkwing/work/queue-233/BUILD.md.
|
||||
2026-10-21T06:37:41Z | Darkwing | row 240 #1746 installer I4 build, round 1 in review | Before: root had no host check for the bwrap AppArmor profile, its pins or a boot unit, and stack-upgrade.sh exited 1 args-failed when the args move after A5 failed, while exit 1 means the old copy runs. After: scripts/case1-hostcheck.sh (seven items, --check, --enforce, --upstream), scripts/case1-pins.sh, mosaic-hostcheck.service and 16 tests; the args move failure exits 5 args-failed, documented in TOOLS.md and run sheet section 6 and tested; run sheet section 3 puts the pinned npm on PATH and names the bin/claude.exe --claude path; sections 8 and 10 have precheck lines. Verification: slot run r1 on 47ec9fe2f failed at the singles (the new N1 test's after hook threw ENOENT after the fixture cleanup removed the root); b45852daa drops the hook; r2 on b45852daa green: singles 16/0 and 21/0, c0 plus M1-M8 8/8 killed, cli 639/0, scripts 585/0. Candidate darkwing/row240-r3 ad1b23ab2 on c771a36f4, manifest 573ece95 (9 paths), revs 2694 and 2695, comment 29943.
|
||||
2026-10-21T09:00Z | Herb | row 215 C2-04 implementation started | Before: business files reject library entries and root consumers assume code projects; the organization writer can change all project mappings. Plan: approved manifest 2522025af on C2-01 a2c72ac95, Filbert reply to herb-0056, scope sage-1848/1852/1860. Focused slot sage-1869 observed expected red mapping and M9 cases, then 14/0 green for new T1/T2 cases, no skips; clear herb-0062 with empty test/fixture process scan. After that clear, T3/T4 tests and host-only mirror/bus implementation continue under sage-1874, unrun while Sage holds the slot. Full singles, suites and implementation review remain pending. No source commit, push or live change.
|
||||
2026-10-21T13:29Z | Herb | row 215 C2-04 source verified for candidate review | Before: business code assumed every project had a root and organization writes could replace project mappings. After: library mappings load without agent checkouts or publish grants, project mappings are protected before and after serialization, host-only bare mirrors share a bounded publication lock with sync, and library.file/library.status are human-only async bus reads. Base f8276c5eb preserves all nine landed overlaps. Granted sage-2008 whole singles: 16 files, 451/0, no skips or cancellations, ended 13:27:27.279728Z; all source hashes unchanged, process scan empty, no own-path drift through 8a04f4aa4. Full landing gate and implementation review remain pending; no HTTP, sync writer or live change.
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
# Row 250 build notes (Gizmoduck)
|
||||
|
||||
Vikunja #450, Mos ruling mos-1182 item 3. Brief: docs/plans/2026-10-21_k12-cohort-events.md. Reviewer
|
||||
Filbert, gate owner Sage. Branch gizmoduck/row250 from origin/refactor 3b0aef995. Line numbers below are on
|
||||
this branch unless a commit is named.
|
||||
|
||||
## Step 1
|
||||
|
||||
cbba6ff07 changes only the K12 assertion (packages/conversation/tests/cohort.test.mjs:292 on 3b0aef995).
|
||||
On failure it prints the shim's answer, with `ok` and `unavailable`, and `h.ctrl.evidence.releases`.
|
||||
|
||||
## Step 2: the cause
|
||||
|
||||
K12 reads the shim after the controller has started to release it.
|
||||
|
||||
- The force stop sets the binding `stopped` (packages/conversation/src/controller.mjs:1615). Then it pauses at
|
||||
`scope-release` (:1623) and calls `#releaseScope` (:1624).
|
||||
- `#releaseScope` calls `releaseCohort` (:1639). That sends `hello`, then `release`
|
||||
(packages/conversation/src/cohort.mjs:261-265).
|
||||
- The shim answers `release` and exits 10 ms later. It unlinks its socket first (shim.mjs:165-176). systemd
|
||||
then collects the empty scope, `engine` included.
|
||||
- K12's `forceStop` helper returns once it sees `stopped` (cohort.test.mjs:148, polling every 10 ms). The
|
||||
test then reads `engine/cgroup.freeze` (:281 on 3b0aef995) and asks the shim for `events` (:291).
|
||||
|
||||
Nothing in K12 orders those reads before the release. Unloaded, the test usually sends its `events` request
|
||||
within the 10 ms before the shim exits, so it passes. Under load the release wins. `shimRequest` then
|
||||
returns `{ ok: false, unavailable: "the shim socket is gone" }` (cohort.mjs:46), or "unreachable" or
|
||||
"closed the connection" (:62-63), and `ev.populated` is undefined. Both recorded failures fit this
|
||||
pattern:
|
||||
|
||||
- Row 197 proof 4, pair1-b: K12 failed in 339 ms on `undefined !== 0` at :292. 339 ms is far below the
|
||||
3 s `shimRequest` timeout (cohort.mjs:56), so the request didn't time out. The `cgroup.freeze` read at
|
||||
:281 passed, so the scope still existed then.
|
||||
- BUILD-LOG.md:4092, row 56's gate: "`populated` undefined with load around 12".
|
||||
|
||||
Row 50 (a9cc522a0, #1536) added the release after a proven stop. K12 is older. Its comment still says
|
||||
"the shim holds the scope", and that stopped being true in row 50. E1 (cohort.test.mjs:923-925) already
|
||||
holds `scope-release` so it can read the shim while the shim still answers. K12 never got the hold. No
|
||||
other test reads the shim after a proven stop and expects an answer. R1 expects the shim gone, R3 is an
|
||||
uncertain stop, and K15 reads before its stop.
|
||||
|
||||
The cgroup read itself has no race. The kill's `waitFor` (shim.mjs:117-126) had already read `populated 0`
|
||||
for the stop to be proven. The read is the shim's call to `events()` (shim.mjs:83-96), and it reads one
|
||||
kernel file. So the brief's allowance for a bounded retry doesn't apply, and there is none.
|
||||
|
||||
The fix goes in the test's setup, which the brief allows ("Use the shim, the cohort controller or the
|
||||
test's setup and teardown, whichever the evidence points to"). The controller's release is correct and
|
||||
specified (README "Scope release", R1). Delaying it for a reader would change row 50's behavior.
|
||||
|
||||
## Step 2: the change
|
||||
|
||||
packages/conversation/tests/cohort.test.mjs, K12:
|
||||
|
||||
- It runs with `gate()`, holds `scope-release` before the stop, and waits until the hold is reached. Then it
|
||||
does every read that needs the scope: `cgroup.freeze`, `events` and `members`.
|
||||
- After the reads it lets the release go and asserts one entry, `["force-stop", "released"]`. This is new
|
||||
coverage: K12 now also shows the forking cohort's scope released.
|
||||
- The assertions are unchanged. `populated` must be 0 and the member list must be empty. The step 1 message
|
||||
stays.
|
||||
|
||||
packages/conversation/src/shim.mjs:167-168, `release` (:167 on 3b0aef995). It answered a failed `events()` with "the engine
|
||||
cgroup is not empty", so it reported unavailable as not empty. The refusal was already safe, but the reason
|
||||
was false. Now an `events()` answer that isn't `ok` is returned as it is, with the read's own reason. Only
|
||||
`populated` 1 gives "not empty". Nothing else matched that string (grep of packages/).
|
||||
|
||||
## Tests
|
||||
|
||||
- K12 as above.
|
||||
- R13, the brief's new case, placed after R3. After a proven stop, with `scope-release` held, the test makes
|
||||
`engine/cgroup.events` mode 000. Then:
|
||||
- `events` returns `ok: false`, has no `populated`, and the reason is "engine/cgroup.events unreadable
|
||||
(EACCES)".
|
||||
- On release, the controller records one entry `["force-stop", "unavailable", <that reason>]`.
|
||||
- The unit stays active, and the shim still answers `hello`.
|
||||
|
||||
Then `close()` reuses the stop's release, so there is still one entry. The `finally` closes the
|
||||
controller again (a second close is a no-op), restores mode 444, the kernel's mode for cgroup.events,
|
||||
and releases the scope. On
|
||||
3b0aef995's shim.mjs, R13 fails on the reason, because it reads "the engine cgroup is not empty".
|
||||
- K15 already covers a stop, as opposed to a release, with `events` unavailable: the shim gone, the file
|
||||
mode 000, or `engine` missing, each ending `uncertain` with its reason.
|
||||
|
||||
## File added beyond the brief
|
||||
|
||||
packages/conversation/README.md:599 listed "R1–R3, R5–R12" for cohort.test.mjs. With R13 it now reads
|
||||
"R1–R3, R5–R13". The brief's files don't include the README. Sage added it to this row in sage-2082.
|
||||
|
||||
## Runs
|
||||
|
||||
None yet. They need Sage's slot. Sage's sage-2082 says the run is on the pushed candidate in a clean
|
||||
worktree, and that it adds the control-board suite whole, so it counts as the gate run.
|
||||
|
||||
## Round 2
|
||||
|
||||
Filbert's C1 (#1755 comment 30125): R13 never closed its in-process controller, so the controller's
|
||||
socket server (controller.mjs:548) stayed open, and `reap` only kills units and engines. Only `close()`
|
||||
closes it (:1789). R13 now calls `h.ctrl.close()` after its checks and asserts one release entry, as R2
|
||||
does. Its `finally` also closes the controller, for a failure partway through. The second close is safe:
|
||||
`server` is null by then (:1791), and `#releaseScope` returns the cached release (:1634-1648). Branch
|
||||
gizmoduck/row250-r2, on e9cfd92f8.
|
||||
@@ -0,0 +1,399 @@
|
||||
# Row 215 build record
|
||||
|
||||
Owner: Herb. Reviewer: Filbert. Claim: herb-215-start, rev 2753.
|
||||
Brief: docs/plans/2026-10-20_case2-rows.md, C2-04, pin
|
||||
16847e94ae1768881711318fe81cbb5e6c66b971. Design: Gosalyn r11,
|
||||
sections 1.1, 1.3, 2.1, M4, M9 and 7.2.
|
||||
|
||||
Base: a2c72ac952df94ecab7e391d5042f49b7f88b816, row 212's reviewed
|
||||
candidate, under Q177. Branch: herb/row215. Rebuild on the combined 212+197
|
||||
landing when Sage names it. Do not replay or revert landed changes.
|
||||
|
||||
## Scope rulings (sage-1848)
|
||||
|
||||
1. Add packages/bus/src/runtime.mjs for library adapter injection and the
|
||||
library skip in protectedRoots. The skip has its own consumer test. Change
|
||||
nothing else there.
|
||||
2. Add packages/library/src/mirror.mjs, named mirror rather than store. It
|
||||
creates a bare mirror without a remote, reads at the served commit and
|
||||
reads sync state. Export one state filename constant, and export this
|
||||
module through packages/library/src/index.mjs. Row 222 imports the constant.
|
||||
3. Add packages/bus/src/server.mjs only to await library.file and
|
||||
library.status, with socket tests proving their replies are results, not {}.
|
||||
4. HTTP exposure is deferred. Row 225 owns the library.status route;
|
||||
C2-11b owns library pages. Leave serve.mjs alone. webui/src/cli.mjs gets
|
||||
only callback wiring next to the project-file callbacks on both listeners.
|
||||
5. Reuse existing refusal codes where possible.
|
||||
6. Build on a2c72ac95 until Sage supplies the 212 landing SHA.
|
||||
|
||||
Additional ruling, sage-1852: library-state-invalid is approved for malformed,
|
||||
unsafe or mismatched state, including a missing file while the served ref
|
||||
exists. The version-1 shared contract below is approved. Row 222 also owns
|
||||
runtime.mjs for its sync and timer wiring, recorded in that row's manifest.
|
||||
|
||||
Additional rulings, sage-1860, after Filbert's CHANGES on 6a508804f:
|
||||
|
||||
- B1 adds packages/cli/src/config.mjs and cli/tests/trackers-boot.test.mjs.
|
||||
trackerFor skips library entries. A real bus boot with tracker.baseUrl and
|
||||
a library entry succeeds and gets no tracker from that entry.
|
||||
- B2 refuses a role publish grant naming a library project in the loader.
|
||||
- B3 readers use the sync lock. mirror.mjs exports withLibraryLock, with a
|
||||
5000 ms wait bound and library-sync-busy on timeout. Sync locks only the
|
||||
served-ref move and state publication, never the fetch.
|
||||
- N3, git-socket doPush/recordPush accepting a library ID, is a later row.
|
||||
Sage records it in DEFERRED.md when 215 lands. No fix here.
|
||||
|
||||
## Shared contract with row 222
|
||||
|
||||
Agreed in herb-0048, megavolt-0081/0082 and sage-1852. This section is the
|
||||
contract Filbert reviews and Megavolt cites for Dewey. It is not a sync writer.
|
||||
|
||||
Module: packages/library/src/mirror.mjs. Export
|
||||
`SYNC_STATE_FILE = 'mosaic-library-sync.json'`. The full path is
|
||||
`join(mirror, SYNC_STATE_FILE)`, inside the bare repository. Only sync.mjs
|
||||
writes it, using a sibling temp file, fsync, rename, and directory fsync.
|
||||
|
||||
Version 1 has exactly these keys:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 1,
|
||||
"branch": "main",
|
||||
"served": null,
|
||||
"lastFetch": null,
|
||||
"lastError": null,
|
||||
"diverged": null,
|
||||
"problems": []
|
||||
}
|
||||
```
|
||||
|
||||
- branch is the configured mapping branch and must match the reader's branch.
|
||||
- served is null or a full lowercase 40-hex commit ID. refs/heads/served is
|
||||
authority. The state value must equal that ref, which must name a commit.
|
||||
- lastFetch is null or a canonical ISO UTC timestamp.
|
||||
- lastError is null or exactly {code, at}. code matches [a-z-]{1,64}; at is
|
||||
canonical ISO UTC. It never holds stderr, prose or a credential value.
|
||||
- diverged is null or exactly {commit, at}, with the same commit/time rules.
|
||||
- problems uses C2-01's exact {code, path, message, line?}. code is R1-R7,
|
||||
message is that code's fixed RULES text, line is a positive safe integer
|
||||
when present. No file body or arbitrary message is accepted.
|
||||
- An absent file and absent served ref return the empty object above with
|
||||
the configured branch. An absent file with an existing served ref refuses.
|
||||
- Unknown keys, bad types, unsafe filesystem metadata, invalid JSON and a
|
||||
mismatch refuse library-state-invalid. Reads use a bounded regular owned
|
||||
private file without following links. The read never repairs state.
|
||||
- refs/remotes/library/<branch> is not duplicated in this file. Row 222 may
|
||||
read it when it needs the fetched tip.
|
||||
|
||||
Exports consumed by row 222:
|
||||
|
||||
| Export | Contract |
|
||||
| --- | --- |
|
||||
| mirrorPath({business, project, dataRoot}) | Require a library entry; return projectRepo's checked path |
|
||||
| ensureMirror(context) | Promise of the mirror path; race-safe idempotent bare init; no remote or fetch |
|
||||
| servedCommit(mirror) | Promise of full commit ID or null; refs/heads/served only |
|
||||
| readSyncState(mirror, {branch}) | Promise of checked version-1 state; compare with served ref |
|
||||
| withLibraryLock(mirror, operation) | Await the same exclusive lock as readers, then await operation({readSyncState}); always release |
|
||||
|
||||
The lock is a stable private regular file, mosaic-library-sync.lock inside
|
||||
the mirror. It is never unlinked. A kernel flock is held by the caller's
|
||||
file descriptor. Acquisition waits at most 5000 ms and refuses
|
||||
library-sync-busy on timeout. Unsafe lock metadata refuses library-state-invalid.
|
||||
|
||||
There is no fs.flock API. The exact protocol is: open the stable file with
|
||||
O_NOFOLLOW, check regular/private/owned/single-link metadata, pass its fd as
|
||||
child FD 3 to `flock --exclusive --wait 5 --conflict-exit-code 75 3` using
|
||||
asynchronous spawn, await
|
||||
that child's exit 0, then run the callback while the parent still holds its
|
||||
original descriptor. Both descriptors share the open file description, so
|
||||
the lock survives acquisition-child exit. Finally close the parent's fd.
|
||||
Process death also closes it. No holder child stays alive in the callback,
|
||||
no stale file is deleted, and unrelated operation children inherit only 0-2.
|
||||
Acquisition never uses spawnSync: the bus must serve other calls while a
|
||||
library reader waits (megavolt-0087).
|
||||
|
||||
A scratch-only probe on node v26.8.1 at 2026-10-21T08:34:00Z confirmed this:
|
||||
acquisition child exited 0; a second flock -n returned 1 while the parent fd
|
||||
stayed open; after closeSync it returned 0. The probe removed its own root.
|
||||
This was a design probe, not a package test, suite, Docker command or proof.
|
||||
|
||||
readSyncState takes that lock around reading the served ref and state file.
|
||||
The callback-scoped readSyncState({branch}) supplied by withLibraryLock reads
|
||||
under the already-held lock and does not reacquire it. The helper awaits
|
||||
asynchronous callbacks and releases in finally. A callback-scoped reader
|
||||
used after its callback ends refuses; it cannot escape its lock lifetime.
|
||||
|
||||
Row 222 fetches without this lock, then calls withLibraryLock across the
|
||||
served-ref move and atomic state write. Its tests hold publication between
|
||||
those steps and prove a concurrent reader waits, then sees the new consistent
|
||||
pair, including first sync. Row 215 tests that publication shape and timeout.
|
||||
A file read releases the lock after snapshotting a consistent served SHA,
|
||||
then reads that immutable commit. Row 222's separate outer sync lock spans
|
||||
fetch to prevent two sync operations interleaving (megavolt-0086).
|
||||
|
||||
Host adapter exports for this row:
|
||||
|
||||
- libraryStatus(context): return {project, ...state}, with no repository path
|
||||
or content. Do not fetch or rebuild on this read.
|
||||
- readLibraryFile({...context, path}): read a mapped, readable file at the
|
||||
served commit, returning {project, path, commit, content}. No caller-picked
|
||||
commit, working-tree fallback, fetch or write. C2-01's R1/R2/R7 exclusions
|
||||
apply. A never-synced mirror refuses library-commit for a file read.
|
||||
|
||||
Row 222 owns syncCommand, sync, writeSyncState, its outer sync lock, the timer
|
||||
and state publication. Row 215 owns the shared publication/read lock per
|
||||
sage-1860. Sync rebuilds problems with existing readLibrary({repo, commit,
|
||||
mapping}). It does not need a second rebuild function from this row.
|
||||
|
||||
## Root consumer audit and reviewer notes
|
||||
|
||||
On a2c72ac95, ran exactly the sage-1860 audit:
|
||||
`git grep -n 'entry\.root\|\.root)' -- 'packages/*/src/*.mjs'`.
|
||||
It has 14 hits. runtime.mjs:95, business/cli.mjs:61,72,78,118,
|
||||
instance-settings.mjs:142-143, resolve.mjs:44, cli/config.mjs:62-63 and
|
||||
project/paths.mjs:42 all get the library guard in this row. business.mjs:233
|
||||
and :242 are code-project validation after the library dispatch, not an
|
||||
unguarded consumer. queue.mjs:1144 compares queue genesis roots and never
|
||||
iterates business.projects; it is safe and unchanged. A second search for
|
||||
projectFilePath/business.projects/b.projects found no additional root reader.
|
||||
ensureCheckouts destructures root rather than spelling .root; its guard and
|
||||
the launcher's filter remain in T1. Bare projectFilePath/loadProject remain
|
||||
strict and unchanged.
|
||||
|
||||
Filbert N1 is handled at the existing owned paths.mjs boundary: projectRepo
|
||||
defaults to record-project use and refuses a library entry with project-invalid.
|
||||
Only mirrorPath's internal call opts into allowLibrary. Thus ordinary human
|
||||
and tester project init cannot occupy an uninitialized library mirror path.
|
||||
No record API or bus argument exposes that internal option.
|
||||
|
||||
Filbert N2: ensureMirror failure refuses bus boot. No socket becomes ready.
|
||||
The runtime closes resources it opened, following its existing failure path.
|
||||
A T4 test uses an unsafe/pre-existing mirror and proves the refusal, rather
|
||||
than serving a half-configured library adapter.
|
||||
|
||||
## Verification record
|
||||
|
||||
Planning stage. No product code, package test, suite, image build, live operation
|
||||
or push for row 215 has happened. Product implementation awaits Filbert's
|
||||
manifest approval. Sage owns suite and full-gate grants. Row 197's proof
|
||||
commit is separate and is not part of this row's changes.
|
||||
|
||||
## Implementation ledger
|
||||
|
||||
Plan: agents/herb/work/queue-215/MANIFEST.md at 2522025af, approved by
|
||||
Filbert in the reply to herb-0056. Execution is inline by Herb under the
|
||||
executing-plans and test-driven-development skills. No agent delegation.
|
||||
|
||||
Pre-flight: T1's validated mapping feeds T2's protected document and T3's
|
||||
mirror context; T3's lock/state helpers feed T4's injected host adapter.
|
||||
The shared contract is pinned above, with no interface conflict found.
|
||||
|
||||
Sage-1867 overrides COMMON's singles allowance: every test and executable
|
||||
probe needs an explicit slot grant. No further probe/test has run since
|
||||
that reminder. Read-only inspection and test authoring continue while the
|
||||
slot is held. The first red execution is pending; product code is unchanged.
|
||||
|
||||
Filbert's approved-manifest build notes: ensureMirror creates the lock in
|
||||
its staged directory before publication; a missing lock in an existing
|
||||
mirror refuses library-state-invalid. The top-level metadata allowlist
|
||||
permits only normal bare Git entries plus the state and stable lock files.
|
||||
Tests cover an unknown entry. The host needs /usr/bin/flock; ENOENT yields
|
||||
a handled library-state-invalid refusal, never an unhandled child error.
|
||||
Lock acquisition uses /usr/bin/flock directly and asynchronous spawn.
|
||||
|
||||
T1: consumer and loader regression tests authored, not run. T2: direct M9
|
||||
write and serialization regression tests authored, not run. No completion
|
||||
or passing claim is made for either task.
|
||||
|
||||
Update, sage-1869 focused slot, 2026-10-21T08:47:48Z to 08:51:07Z:
|
||||
the busy check was CLEAR before the first test. T1's mapping regression
|
||||
failed 0/1 on unsupported kind as expected, then passed 2/0 with the publish
|
||||
refusal included. Other focused greens: business CLI 1/0, resolver 1/0,
|
||||
instance settings 1/0, seat checkout 1/0, project paths 1/0, sandboxed launcher
|
||||
1/0, and trackers-boot whole 2/0. T2's direct writer case failed 0/1 on the
|
||||
missing refusal, then its whole new file passed 4/0. Green total 14/0 with
|
||||
no skips or cancellations. Logs and counts: granted-t1/. The final /proc
|
||||
scan found no test process or fixture cwd/argv reference; its private root
|
||||
was removed. Clear sent as herb-0062. Existing files' other cases have not
|
||||
been run yet, so T1/T2's full-file acceptance is still pending.
|
||||
|
||||
Sage-1874 directs continued authoring and implementation while the landing
|
||||
gate/proof holds the slot. T3/T4 tests were written first. Their initial
|
||||
red runs cannot execute during that hold; implementation proceeds under
|
||||
that owner direction, with no claim of a witnessed red or green for T3/T4.
|
||||
Their baseline red and candidate checks need a later explicit grant.
|
||||
|
||||
Implementation ruling: initialization uses GNU /usr/bin/mv --no-clobber
|
||||
--no-target-directory for its bounded staging rename, rather than Node's
|
||||
renameSync, which could replace an empty directory made by a competing
|
||||
actor. This preserves pre-existing directories and needs no new package on
|
||||
the Linux/coreutils bus host. The host also needs /usr/bin/flock. Neither
|
||||
command has been executed for T3/T4 yet. Publication errors fail closed.
|
||||
Sync-state reads are capped at 8 MiB, including a checked extra byte; an
|
||||
oversized or concurrently changed file refuses library-state-invalid.
|
||||
|
||||
T5 static dependency audit found two partial pinned-copy fixtures that copy
|
||||
business/src but not its newly imported library mapping validator:
|
||||
cli/tests/stack-release.test.mjs:1772 and stack-release-fixture.mjs:309 on
|
||||
the base. Each now includes packages/library/src in the existing copy list.
|
||||
This changes fixture closure only, no assertion or timeout. The complete
|
||||
stack-release file and each test file importing that shared fixture require
|
||||
a later granted single-file run. They are outside the four-file T3/T4 slot.
|
||||
|
||||
Sage-1879 places the four-file T3/T4 focused run after their 212+197 proof,
|
||||
before Gizmoduck, and requires their explicit clear before starting. No run
|
||||
has occurred after herb-0062. Row 197's N7 base-image-tag finding is left to
|
||||
Sage's DEFERRED entry; no row 197 source change is made here.
|
||||
|
||||
|
||||
Focused T3/T4 grant sage-1882, 2026-10-21 09:13-09:18Z: busy check
|
||||
CLEAR. Final whole-file results: mirror 16/0, bus library 6/0, WebUI
|
||||
library-cli 1/0, project-runtime 3/0, all with zero skips/cancellations.
|
||||
Syntax checks passed for the four files and five changed host modules.
|
||||
Logs, all intermediate failures, counts and empty /proc cleanup scan are
|
||||
in granted-t34/. Baseline a2c72ac95: three focused bus cases 0/3
|
||||
(unknown-verb), CLI 0/1 (missing callbacks). Mirror baseline 0/1 is an
|
||||
import refusal for the new module, not a witnessed behavioral red.
|
||||
An initial whole baseline bus attempt left a runtime after its expected
|
||||
failure; its exact runner was stopped, no process remained, and the
|
||||
baseline was narrowed to the three bounded broker/socket cases.
|
||||
Candidate fixture setup errors and a mock-child timeout were corrected
|
||||
before the final whole-file passes. No suite or Docker/image/proof ran.
|
||||
|
||||
Filbert's 09:09 publication note: no dependence on mv -n's skipped-rename
|
||||
exit status across coreutils versions. Save staging dev/ino before mv;
|
||||
only its disappearance plus the same dev/ino at the mirror proves a win.
|
||||
A remaining original staging inode means a loss, requiring a valid winner.
|
||||
Only that owned original staging inode is removed. Numeric no-clobber
|
||||
statuses 0 and 1, including a diagnostic, are tested with a competing
|
||||
winner. Spawn errors, signals/timeouts and inconsistent outcomes refuse.
|
||||
Coreutils must provide atomic --no-clobber --no-target-directory semantics;
|
||||
it need not use any particular skipped-rename status convention.
|
||||
|
||||
|
||||
Landing update: prepared herb/row215-on212 on fefd54e13 (includes row 212
|
||||
landing ee7b2f137), without history replay or stash. Only BUILD-LOG.md and
|
||||
cli/tests/stack-release.test.mjs overlap the a2c72ac95-to-landing change
|
||||
set. BUILD-LOG preserves all landed entries and appends the existing Herb
|
||||
entry. stack-release preserves the landing plus only the library/src copy
|
||||
list addition. No test has run on this landing yet. All further execution
|
||||
requires a Sage grant (supersedes the original COMMON singles rule).
|
||||
|
||||
|
||||
Sage-1979 early singles on fefd54e13, stopped after file10 per sage-1983:
|
||||
- packages/bus/tests/library.test.mjs: 6/0
|
||||
- packages/bus/tests/project-runtime.test.mjs: 3/0
|
||||
- packages/business/tests/business.test.mjs: 18/0
|
||||
- packages/business/tests/cli.test.mjs: 10/0
|
||||
- packages/business/tests/instance-settings.test.mjs: 12/0
|
||||
- packages/business/tests/library-projects-protected.test.mjs: 4/0
|
||||
- packages/business/tests/resolve.test.mjs: 11/0
|
||||
- packages/cli/tests/launcher.test.mjs: 30/0
|
||||
- packages/cli/tests/stack-release-external.test.mjs: 25/0
|
||||
- packages/cli/tests/stack-release.test.mjs: 196/0
|
||||
|
||||
Total315/0, zero skips/cancellations. This is an early read only, not gate
|
||||
evidence for a merged candidate. The sequential driver was paused during
|
||||
file10 so it could not start file11, then terminated after file10 exited0.
|
||||
No file11 log exists. Results/logs are in granted-singles/. Later landed
|
||||
overlaps require a new branch and all16 singles again after their merge.
|
||||
|
||||
|
||||
Current merge preparation per sage-1983/1987: new branch
|
||||
herb/row215-on-f827 on f8276c5eb3ecb0aad353ee65e3dd8f7faac5dd87.
|
||||
Nine landed overlaps are recorded in current-MERGE.json and the exact
|
||||
candidate deltas against the landing are in current-merge-only.patch.
|
||||
Two textual conflicts were resolved manually: Broker keeps hostKeys and
|
||||
adds library; business.mjs keeps CREATIVE_DEFINITIONS and adds checkMapping.
|
||||
The other seven merges preserve the landing plus the original C2-04 edits.
|
||||
All other product/test paths match the early215 tree byte for byte. The
|
||||
landing's BUILD-LOG is preserved and the existing Herb entry is appended.
|
||||
No history replay, stash, force push, branch deletion or source commit.
|
||||
No test/probe/syntax check ran on the merged tree after the slot was cleared.
|
||||
All16 whole singles need a new Sage grant before candidate commit/review.
|
||||
The10 old-base315/0 results are early reads only, never merged gate evidence.
|
||||
|
||||
|
||||
## Source candidate and sage-2008 receipts
|
||||
|
||||
Source commit: e333af4dc7af3a9d3789c8c0db26a0df8bdddfee, on
|
||||
f8276c5eb3ecb0aad353ee65e3dd8f7faac5dd87. SOURCE.json records all30
|
||||
changed source/phase-log paths with blob SHA256 and Git mode. The next
|
||||
commit contains only this packet. No product change follows the tests.
|
||||
|
||||
Sage-2008: start13:15:15.548943Z; end13:27:27.279728Z, 2026-10-21.
|
||||
Each of the16 TEST-FILES.txt files ran whole, sequentially. All451 passed,
|
||||
with0 failed/skipped/cancelled. Per-file outputs are in granted-2008/;
|
||||
EVIDENCE.json records their counts, Node durations and log hashes.
|
||||
|
||||
| File | Pass/fail |
|
||||
| --- | ---: |
|
||||
| packages/bus/tests/library.test.mjs | 6/0 |
|
||||
| packages/bus/tests/project-runtime.test.mjs | 3/0 |
|
||||
| packages/business/tests/business.test.mjs | 19/0 |
|
||||
| packages/business/tests/cli.test.mjs | 10/0 |
|
||||
| packages/business/tests/instance-settings.test.mjs | 13/0 |
|
||||
| packages/business/tests/library-projects-protected.test.mjs | 4/0 |
|
||||
| packages/business/tests/resolve.test.mjs | 11/0 |
|
||||
| packages/cli/tests/launcher.test.mjs | 31/0 |
|
||||
| packages/cli/tests/stack-release-external.test.mjs | 25/0 |
|
||||
| packages/cli/tests/stack-release.test.mjs | 196/0 |
|
||||
| packages/cli/tests/stack-upgrade.test.mjs | 21/0 |
|
||||
| packages/cli/tests/trackers-boot.test.mjs | 2/0 |
|
||||
| packages/library/tests/mirror.test.mjs | 16/0 |
|
||||
| packages/project/tests/project.test.mjs | 15/0 |
|
||||
| packages/seat/tests/checkout.test.mjs | 78/0 |
|
||||
| packages/webui/tests/library-cli.test.mjs | 1/0 |
|
||||
|
||||
All29 product/test hashes equal their pre-run values. The final /proc cwd
|
||||
and argv scan was empty; the private test root was removed. Clear sent
|
||||
as herb-0082 at13:28:38Z. No further runs occurred. No image, Docker,
|
||||
lane, proof or full suite was part of this grant.
|
||||
|
||||
Before commit, checked f8276c5eb..8a04f4aa4 on every215 source path and
|
||||
all16 test paths: no overlap. Row248's grant-executor test is outside them.
|
||||
The current root-consumer grep still returns14 sites, all classified by
|
||||
the earlier audit: business code roots after dispatch, guarded library
|
||||
skips at consumers, and queue's unrelated genesis-root invariant.
|
||||
|
||||
Sage-2016 authorizes the source commit, packet receipts and seat-only push,
|
||||
then Filbert's candidate review. The landing gate stays with Sage. Earlier
|
||||
focused and old-base receipts are archived in granted-t1/, granted-t34/
|
||||
and granted-singles/, with their limits kept above. Full package/shell
|
||||
landing checks and implementation approval remain pending. No HTTP route,
|
||||
remote fetch, sync writer, timer or live operation was added.
|
||||
|
||||
Raw Node error logs retain their original space-only lines. Packet whitespace
|
||||
checks exclude *.log so the recorded output bytes stay unchanged; source and
|
||||
other packet files pass the ordinary diff check.
|
||||
|
||||
## Merge-scoped round 2 after rows 249 and 197 (sage-2054)
|
||||
|
||||
Row197 landed as a36523713 after proof6 passed 8/8 gates. Row249's
|
||||
broker fix is also in this base. Source a6101e21c596e2972ab5a7e3087736075899505e, single parent a3652371338e60187d4e95cee4a0f30f3c8a8f06,
|
||||
is on the new herb/row215-on197 branch. The old branch stays untouched.
|
||||
No force push, branch deletion or stash was used. The merge was clean.
|
||||
|
||||
Only broker.mjs and stack-release.test.mjs changed upstream among the30
|
||||
source/phase-log paths. Both retain every landed hunk. The broker keeps
|
||||
row249's installed flag and hostLineLeft handling. The stack-release test
|
||||
keeps row197's leasePort import, after hook and closed-port lease helper;
|
||||
215 adds only its library fixture copy. The other28 blobs and all modes
|
||||
match the prior source. All30 paths have exactly the same -U0 added and
|
||||
removed lines as f8276c5eb..e333af4dc. BUILD-LOG.md is append-only.
|
||||
|
||||
Stable patch-id, old and new: d191e7e9586cd3b7c18310daacdf0c1fdbc8be01.
|
||||
r2-range-diff.txt reports only the commit message changed (!); its patch
|
||||
is unchanged.
|
||||
r2-MERGE.json records every path; r2-merge-only.patch contains both merged
|
||||
source diffs against the new base. SOURCE.json names the new source.
|
||||
|
||||
Filbert approved round1 in comment30071, rev2897. This round requests
|
||||
merge-only review. The earlier451/0 receipts belong to the prior base;
|
||||
no test, probe, syntax check, Docker command or lane ran in this round.
|
||||
Merged-tree evidence remains pending Sage's explicit clear.
|
||||
r2-TEST-FILES.txt proposes all16 original whole singles plus all66
|
||||
bus test files whose local import closure reaches broker.mjs, deduplicated
|
||||
to80 whole files. This includes shared fixture and runtime imports.
|
||||
Sage's slot and row196 landing gate come first. The full landing gate
|
||||
remains Sage's. No library behavior, assertion or timeout changed.
|
||||
@@ -0,0 +1,261 @@
|
||||
{
|
||||
"grant": "sage-2008",
|
||||
"sourceCommit": "e333af4dc7af3a9d3789c8c0db26a0df8bdddfee",
|
||||
"base": "f8276c5eb3ecb0aad353ee65e3dd8f7faac5dd87",
|
||||
"start": "2026-10-21T13:15:15.548778+00:00",
|
||||
"end": "2026-10-21T13:27:27.279728+00:00",
|
||||
"summary": {
|
||||
"tests": 451,
|
||||
"pass": 451,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"file": "packages/bus/tests/library.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 6,
|
||||
"pass": 6,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "01-packages_bus_tests_library.test.mjs.log",
|
||||
"sha256": "c19016583abc936534f41bde26eb39e095496eda944622142b1d18ffd5018bc0",
|
||||
"nodeDurationMs": 359.869493
|
||||
},
|
||||
{
|
||||
"file": "packages/bus/tests/project-runtime.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 3,
|
||||
"pass": 3,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "02-packages_bus_tests_project-runtime.test.mjs.log",
|
||||
"sha256": "f123231042d1562fee6dad3d885ac587967e0287f63603c861d04c1907363530",
|
||||
"nodeDurationMs": 312.717335
|
||||
},
|
||||
{
|
||||
"file": "packages/business/tests/business.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 19,
|
||||
"pass": 19,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "03-packages_business_tests_business.test.mjs.log",
|
||||
"sha256": "ae990ebccf7f21b9b32fd9c25fdd637873251c078e17dd95471b82b548322980",
|
||||
"nodeDurationMs": 199.91256
|
||||
},
|
||||
{
|
||||
"file": "packages/business/tests/cli.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 10,
|
||||
"pass": 10,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "04-packages_business_tests_cli.test.mjs.log",
|
||||
"sha256": "28512dc38e2bce04294048a2f1c7dc7cf0c322028f874d1d35aa83b87570ea54",
|
||||
"nodeDurationMs": 2381.258516
|
||||
},
|
||||
{
|
||||
"file": "packages/business/tests/instance-settings.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 13,
|
||||
"pass": 13,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "05-packages_business_tests_instance-settings.test.mjs.log",
|
||||
"sha256": "146623624012da1399fb4ee3de4c0e13df1af28caae81f4870315a67ac368f8f",
|
||||
"nodeDurationMs": 608.08011
|
||||
},
|
||||
{
|
||||
"file": "packages/business/tests/library-projects-protected.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 4,
|
||||
"pass": 4,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "06-packages_business_tests_library-projects-protected.test.mjs.log",
|
||||
"sha256": "675ae18523218ab70a4addee039f41df6ae08ee414f20527f975a2004dde65b2",
|
||||
"nodeDurationMs": 118.54831
|
||||
},
|
||||
{
|
||||
"file": "packages/business/tests/resolve.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 11,
|
||||
"pass": 11,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "07-packages_business_tests_resolve.test.mjs.log",
|
||||
"sha256": "6557938cb8e6d79617c0ea911a6e0ad7303cf5a4f9dd5a5631c70d093e6b06fe",
|
||||
"nodeDurationMs": 94.022587
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/launcher.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 31,
|
||||
"pass": 31,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "08-packages_cli_tests_launcher.test.mjs.log",
|
||||
"sha256": "c3404f1931595914d469cb00a951a5e1648f7792733c86bddbfa099552e5791c",
|
||||
"nodeDurationMs": 24989.261794
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release-external.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 25,
|
||||
"pass": 25,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "09-packages_cli_tests_stack-release-external.test.mjs.log",
|
||||
"sha256": "55224b6204d4d05a4cb669fb2845aa4168ab868223c3f341ab026032c47458b4",
|
||||
"nodeDurationMs": 96332.465778
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 196,
|
||||
"pass": 196,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "10-packages_cli_tests_stack-release.test.mjs.log",
|
||||
"sha256": "3f7430ce1f28482a5b66fc0e7db76969298f0dd32c3793e242bc10110dc44e6e",
|
||||
"nodeDurationMs": 533493.817869
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-upgrade.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 21,
|
||||
"pass": 21,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "11-packages_cli_tests_stack-upgrade.test.mjs.log",
|
||||
"sha256": "d18a3eff64b39a5128ab7e842721748b214dc3037ecc9d2c93c58f023859d695",
|
||||
"nodeDurationMs": 60456.446459
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/trackers-boot.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 2,
|
||||
"pass": 2,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "12-packages_cli_tests_trackers-boot.test.mjs.log",
|
||||
"sha256": "22e56455a6a56c98b02f942ed3d38504e4f8486343235c4035c88b967625bce5",
|
||||
"nodeDurationMs": 502.723687
|
||||
},
|
||||
{
|
||||
"file": "packages/library/tests/mirror.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 16,
|
||||
"pass": 16,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "13-packages_library_tests_mirror.test.mjs.log",
|
||||
"sha256": "def30105a3d561118e360535d9d3129226361f2e7902f316e47c74f65f1c0e47",
|
||||
"nodeDurationMs": 5963.543966
|
||||
},
|
||||
{
|
||||
"file": "packages/project/tests/project.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 15,
|
||||
"pass": 15,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "14-packages_project_tests_project.test.mjs.log",
|
||||
"sha256": "e63ab0d23ab24aa1f1f2c1ea8017e8541f415dcb20dff697a37bb7a6368e174d",
|
||||
"nodeDurationMs": 355.86586
|
||||
},
|
||||
{
|
||||
"file": "packages/seat/tests/checkout.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 78,
|
||||
"pass": 78,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "15-packages_seat_tests_checkout.test.mjs.log",
|
||||
"sha256": "c9e7168f589047b8176ec4ee8d2f03adb9fb68f692b363ba6d0036f670811ede",
|
||||
"nodeDurationMs": 4880.907448
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/tests/library-cli.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 1,
|
||||
"pass": 1,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "16-packages_webui_tests_library-cli.test.mjs.log",
|
||||
"sha256": "1ca5b92bc4f2de9ef6aa7156cdea62742fb9ddf054ebfb56a9548431e0cfec0d",
|
||||
"nodeDurationMs": 191.536271
|
||||
}
|
||||
],
|
||||
"cleanup": {
|
||||
"processes": [],
|
||||
"removed": "/mnt/storage/scratch/gt-j5nm6iqn",
|
||||
"sourceHashesUnchanged": 29
|
||||
},
|
||||
"drift": {
|
||||
"base": "f8276c5eb",
|
||||
"tip": "8a04f4aa4aba493eb89e92aa9e0c34084be7058e",
|
||||
"overlap": []
|
||||
},
|
||||
"earlierRuns": {
|
||||
"granted-t1": "focused T1/T2 red/green on a2c72ac95",
|
||||
"granted-t34": "focused T3/T4 with baseline import refusal and corrected fixture errors recorded",
|
||||
"granted-singles": "old fefd54e13 early315/0, not merged gate evidence"
|
||||
},
|
||||
"mergeRound": {
|
||||
"sourceCommit": "a6101e21c596e2972ab5a7e3087736075899505e",
|
||||
"base": "a3652371338e60187d4e95cee4a0f30f3c8a8f06",
|
||||
"status": "not-run; awaiting Sage clear",
|
||||
"priorReceipts": "sage-2008 receipts apply to e333af4dc on f8276c5eb only"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
# C2-04 library business entry implementation plan
|
||||
|
||||
> Execution: Herb implements in this session using the executing-plans skill.
|
||||
> Filbert approves this manifest before any product implementation.
|
||||
|
||||
**Goal:** Load a library mapping without giving an agent a checkout, protect
|
||||
all project mappings from organization writes, and expose human-only bus
|
||||
reads of the bare mirror's served commit and sync status.
|
||||
|
||||
**Architecture:** C2-01 checks mappings and reads commits. Business consumers
|
||||
skip library entries. A host-only mirror module owns local mirror reads and
|
||||
initialization. runtime.mjs injects that module into the broker, preserving
|
||||
the broker's sandbox import closure. Sync and HTTP routes belong to later rows.
|
||||
|
||||
**Tech stack:** Existing Node ESM, node:test and bounded local Git helpers.
|
||||
No dependencies. node_modules remains the plain canonical symlink.
|
||||
|
||||
**Spec:** Pinned C2-04 brief; Gosalyn's approved design 1.1, 1.3, 2.1,
|
||||
M4/M9 and 7.2; BUILD.md's sage-1848/1852/1860 scope and shared-state contract.
|
||||
|
||||
## Constraints and review focus
|
||||
|
||||
- Base a2c72ac95; rebase only onto Sage's named 212 landing on a new branch.
|
||||
- Existing code-project entries retain root/repo/remote behavior. Library
|
||||
entries have no root or repo override and use C2-01 checkMapping.
|
||||
- Preserve the broker's pinned imports. No library import in broker.mjs and
|
||||
no new runner mount. Do not edit serve.mjs or add an HTTP route.
|
||||
- No fetch, remote config, credential read, timer, sync writer, bus write or
|
||||
live operation. All tests use made-up content and local repositories.
|
||||
- All test/probe runs require Sage's grant (sage-1867), including singles.
|
||||
Stop and report two failures in one gate. Do not push without authorization.
|
||||
|
||||
Review focus, with owning tasks below: library-first iteration must not
|
||||
break a later code project (T1); serialized documents cannot bypass M9
|
||||
(T2); racing initialization must not replace another mirror (T3); stale or
|
||||
unsafe state must not leak content (T3); async socket replies must preserve
|
||||
the result and human-only admission (T4).
|
||||
|
||||
## Paths and evidence from the base
|
||||
|
||||
| Product path | Allowed change |
|
||||
| --- | --- |
|
||||
| packages/business/src/business.mjs | Dispatch kind:library to checkMapping before code-root validation (:228-244) |
|
||||
| packages/business/src/organization.mjs | Compare canonical projects in write before publication (:177 onward) |
|
||||
| packages/business/src/cli.mjs | Skip library roots in validate, resolve --project and credential exclusion roots (:60-61, :71-79, :118) |
|
||||
| packages/business/src/resolve.mjs | Skip library entries while matching a project file (:44) |
|
||||
| packages/business/src/instance-settings.mjs | Skip library before projectFilePath (:142), nothing else |
|
||||
| packages/seat/src/checkout.mjs | Skip library entries in ensureCheckouts (:315-327) |
|
||||
| packages/cli/src/launcher.mjs | Pass only code entries to ensureCheckouts (:354) |
|
||||
| packages/cli/src/config.mjs | Skip library entries in trackerFor's root loop (:61-63), per sage-1860 |
|
||||
| packages/project/src/paths.mjs | Skip library entries in overlap loop (:41-44); default record use refuses library, mirrorPath internally opts into allowLibrary |
|
||||
| packages/library/src/mirror.mjs | New bare init, checked state and served-commit file read module |
|
||||
| packages/library/src/index.mjs | Export mirror module interface and SYNC_STATE_FILE |
|
||||
| packages/bus/src/broker.mjs | New injected library adapter, human-only admission and two async verbs |
|
||||
| packages/bus/src/runtime.mjs | Library adapter wiring, mirror initialization and protectedRoots skip only |
|
||||
| packages/bus/src/server.mjs | Await the two library verbs only |
|
||||
| packages/webui/src/cli.mjs | Two library read callbacks beside project callbacks on main and tester listener; no routes |
|
||||
|
||||
packages/business/src/project.mjs need not change: callers skip a library
|
||||
before projectFilePath or loadProject. Do not weaken their code-root checks.
|
||||
scripts/stack-copy.sh already copies packages/library/src and needs no edit.
|
||||
|
||||
Test paths to modify: business/tests/business.test.mjs, cli.test.mjs,
|
||||
resolve.test.mjs, instance-settings.test.mjs; seat/tests/checkout.test.mjs;
|
||||
cli/tests/launcher.test.mjs, trackers-boot.test.mjs; project/tests/project.test.mjs;
|
||||
bus/tests/project-runtime.test.mjs. All paths are under packages/.
|
||||
|
||||
T5 dependency-audit addition: cli/tests/stack-release.test.mjs and its
|
||||
stack-release-fixture.mjs helper copy packages/library/src alongside
|
||||
business/src, whose validator now imports the mapping checker. No assertions
|
||||
or timeouts change. Whole-file dependent singles require a later Sage slot.
|
||||
|
||||
New tests: packages/business/tests/library-projects-protected.test.mjs;
|
||||
packages/library/tests/mirror.test.mjs; packages/bus/tests/library.test.mjs;
|
||||
packages/webui/tests/library-cli.test.mjs. Reuse existing made-up fixtures.
|
||||
If a new fixture is needed, define it within the corresponding new test file.
|
||||
No unrelated test assertion or timeout changes.
|
||||
|
||||
Record paths: agents/herb/work/queue-215/{MANIFEST.md,BUILD.md}, later source
|
||||
manifest and test receipts there; one append-only BUILD-LOG.md phase for this
|
||||
row when implementation begins. Sage owns docs/SESSIONS.md.
|
||||
|
||||
## T1. Mapping and consumer skips
|
||||
|
||||
- [ ] Add failing business tests: accept a frozen library mapping without a
|
||||
root, retain mixed/only-library documents, and propagate C2-01's mapping
|
||||
and playground refusal codes. A role publish naming a library project
|
||||
refuses at load, even with an otherwise valid fork identity and remote.
|
||||
Existing code validation remains unchanged.
|
||||
- [ ] Add a separate regression for each consumer: CLI validate and its
|
||||
credential exclusion roots; CLI resolve --project books has no project
|
||||
layer; resolveInstance finds a later real project; instance settings still
|
||||
writes an unrelated setting; ensureCheckouts returns no library checkout;
|
||||
launcher creates no books workspace clone; projectRepo skips a library
|
||||
while still rejecting overlap with a real code root. Put books first.
|
||||
- [ ] Add the real bus boot regression in cli/tests/trackers-boot.test.mjs:
|
||||
tracker.baseUrl is set and books is a library entry; boot succeeds, books
|
||||
produces no tracker, and a later real tracker project still works.
|
||||
- [ ] projectRepo(context, {allowLibrary = false} = {}) refuses a library
|
||||
entry by default with project-invalid. Only mirrorPath opts in. Test that
|
||||
ordinary human and tester record initialization leave no directory at the
|
||||
future mirror path; no public verb can supply allowLibrary.
|
||||
- [ ] Add runtime's protectedRoots consumer regression in T4's real runtime
|
||||
fixture. A valid credential outside code/data roots still loads with a
|
||||
library entry, and existing credential protections still refuse unsafe files.
|
||||
- [ ] Run each changed test singly, confirm the new cases fail for the
|
||||
intended root assumption, then implement only the table's guards and
|
||||
checkMapping dispatch. Re-run the same files singly.
|
||||
|
||||
CLI validate reports a library entry as library, without an absent-project
|
||||
warning. CLI resolve --project books resolves without loading a project file,
|
||||
as the design's skip requires. It does not fabricate project vars or a root.
|
||||
|
||||
## T2. M9 at the organization writer
|
||||
|
||||
- [ ] In the new business test file, call organizationWriter.write directly
|
||||
with a changed playground prefix and, separately, a changed hybrid entry.
|
||||
Both refuse organization-projects-protected. Snapshot business bytes and
|
||||
changes.jsonl before each call; assert both remain identical afterward.
|
||||
- [ ] Cover addition, deletion and changes to code projects too, since M9
|
||||
protects all projects. Reordered object keys are allowed; array changes
|
||||
are changes. An ordinary non-project write still succeeds and logs.
|
||||
- [ ] Add a serialization regression so a proposed object's serialized
|
||||
projects cannot differ from those checked before publication.
|
||||
- [ ] Run the file singly to see the missing refusal, compare canonical
|
||||
projects against old disk JSON and the document that actually lands,
|
||||
before any publication/receipt, then re-run it singly.
|
||||
|
||||
## T3. Bare mirror, served file and read-only state
|
||||
|
||||
- [ ] Add failing tests for mirrorPath and ensureMirror: exact projectRepo
|
||||
default, no checkout/remote, retained no-links/overlap protections,
|
||||
idempotence, simultaneous creators and preservation of a pre-existing
|
||||
non-mirror directory or unsafe Git metadata.
|
||||
- [ ] Add failing state tests for BUILD.md's full version-1 contract: missing
|
||||
state/ref, valid state, malformed JSON, unknown keys/types, branch mismatch,
|
||||
invalid times/IDs/problem shape, symlink/hardlink/non-private file and
|
||||
missing or mismatched served ref. Assert reads change no bytes.
|
||||
- [ ] Add shared-lock tests: withLibraryLock(mirror, operation) waits at most
|
||||
5000 ms, refuses library-sync-busy on timeout and releases after a throw.
|
||||
A reader arriving between the publisher's served move and state write
|
||||
waits, then reads the consistent pair. Cover first sync and fast-forward
|
||||
in independent processes, same-process independent acquisitions and
|
||||
release after owner death. A callback-scoped reader expires on release.
|
||||
- [ ] Implement the lock by async spawn of flock on the parent's inherited
|
||||
fd 3, as pinned in BUILD.md. Await acquisition-child exit before calling
|
||||
operation. Never spawnSync during acquisition, which could freeze the bus
|
||||
for 5 s. A parallel ordinary bus read remains responsive while a library
|
||||
read waits. Only the publication/read lock is shared; fetch is outside it.
|
||||
- [ ] Add served-read tests against local fixtures containing spaces,
|
||||
capitals, a .canvas and unmapped top-level note. Seed a served ref and state
|
||||
without fetching. A newer unrelated HEAD does not change the returned
|
||||
file. R1/R2/R7 exclusions, traversal, a missing path, a caller commit and a
|
||||
never-synced mirror refuse. Status contains no fixture body marker.
|
||||
- [ ] Implement mirror.mjs and index exports using the shared contract.
|
||||
Initialization stages into an owned private sibling directory and renames
|
||||
atomically; a losing creator validates the winner and removes only its own
|
||||
staging directory. Git uses existing bounded safe helpers, no remote.
|
||||
- [ ] Run mirror.test.mjs singly, red then green. Re-run C2-01 reader.test.mjs
|
||||
singly if a reader assumption changes. Do not change C2-01 reader rules.
|
||||
|
||||
mirror.mjs validates a bare mirror's metadata before Git reads it, including
|
||||
no remote/include/indirection. It does not apply inspectGit's working-tree
|
||||
.git assumption to a bare repository. Failures reuse library-git or the
|
||||
approved library-state-invalid code. State reads are bounded and private.
|
||||
|
||||
## T4. Human-only bus reads and deferred Console callbacks
|
||||
|
||||
- [ ] Add broker tests for library.file and library.status using injected
|
||||
adapters. Each agent session refuses human-required before adapter access,
|
||||
including bad arguments and an absent adapter. A reader or tester does not
|
||||
gain a human capability. Human calls validate keys, then use checked
|
||||
library context. Secret checking and bounded refusal evidence remain.
|
||||
- [ ] Add real startBroker/socket tests for both verbs. Seed only local
|
||||
fixture mirror data. Assert result shape/content and an actual status
|
||||
field, not merely successful transport or {}. Cover never-synced status
|
||||
and runtime's protectedRoots skip. Keep the pinned import-closure test.
|
||||
- [ ] Inject a separate library adapter via runtime, initialize only library
|
||||
mirrors, add the two async request paths, and include them in server's
|
||||
awaited list. Do not import library or fs into broker.
|
||||
- [ ] Unsafe or pre-existing non-mirror initialization refuses bus boot,
|
||||
closes opened resources and never publishes a ready socket. Add that
|
||||
runtime regression in library.test.mjs.
|
||||
- [ ] Wire main and tester Console callbacks beside project-file callbacks.
|
||||
No HTTP route is shipped. The new CLI test captures the startServer
|
||||
options with a test-only module loader and calls the supplied callbacks
|
||||
against a fixture bus, checking the verb and transport identity. No
|
||||
product test seam, UI page, endpoint or serve.mjs change is needed.
|
||||
- [ ] Run library.test.mjs, project-runtime.test.mjs and library-cli.test.mjs
|
||||
individually, red then green. Human admission may use the existing
|
||||
fixture authentication seam; do not forge or bypass a live identity.
|
||||
|
||||
## T5. Review packet and Sage's gate
|
||||
|
||||
- [ ] Search packages/*/tests and scripts/test-*.sh for each changed source
|
||||
path, imports and 64-hex pins. Record the resulting test-file list and run
|
||||
each changed/touched test singly. Stop and report a scope error.
|
||||
- [ ] Self-review the diff against this manifest and all acceptance cases.
|
||||
Record results, commands, skips, source hashes and remaining limits in
|
||||
BUILD.md. Request Sage's slot for the required business, seat, cli, project,
|
||||
bus and webui suites and every scripts/test-*.sh. Do not run them ungranted.
|
||||
- [ ] After applicable tests are green, make the source commit, build the
|
||||
candidate manifest from the authorized pushed tip, and move the row with
|
||||
scripts/mosaic. Sage posts token-requiring requests; Filbert reviews the
|
||||
candidate. Push only when authorized. No merge or live change by Herb.
|
||||
|
||||
## Self-review
|
||||
|
||||
Every brief acceptance item is in T1-T4. Added host support paths match
|
||||
sage-1848/1860. BUILD.md records the complete 14-hit root audit. State shape
|
||||
and authority match sage-1852; the shared read/publication lock follows
|
||||
sage-1860 and Megavolt's agreement. Fetch, timers, outer sync serialization
|
||||
and HTTP stay with their later rows.
|
||||
This is a plan only; no product edits or test execution precede approval.
|
||||
|
||||
|
||||
Landing update: prepared herb/row215-on212 on fefd54e13 (includes row 212
|
||||
landing ee7b2f137), without history replay or stash. Only BUILD-LOG.md and
|
||||
cli/tests/stack-release.test.mjs overlap the a2c72ac95-to-landing change
|
||||
set. BUILD-LOG preserves all landed entries and appends the existing Herb
|
||||
entry. stack-release preserves the landing plus only the library/src copy
|
||||
list addition. No test has run on this landing yet. All further execution
|
||||
requires a Sage grant (supersedes the original COMMON singles rule).
|
||||
|
||||
|
||||
Current merge preparation per sage-1983/1987: new branch
|
||||
herb/row215-on-f827 on f8276c5eb3ecb0aad353ee65e3dd8f7faac5dd87.
|
||||
Nine landed overlaps are recorded in current-MERGE.json and the exact
|
||||
candidate deltas against the landing are in current-merge-only.patch.
|
||||
Two textual conflicts were resolved manually: Broker keeps hostKeys and
|
||||
adds library; business.mjs keeps CREATIVE_DEFINITIONS and adds checkMapping.
|
||||
The other seven merges preserve the landing plus the original C2-04 edits.
|
||||
All other product/test paths match the early215 tree byte for byte. The
|
||||
landing's BUILD-LOG is preserved and the existing Herb entry is appended.
|
||||
No history replay, stash, force push, branch deletion or source commit.
|
||||
No test/probe/syntax check ran on the merged tree after the slot was cleared.
|
||||
All16 whole singles need a new Sage grant before candidate commit/review.
|
||||
The10 old-base315/0 results are early reads only, never merged gate evidence.
|
||||
|
||||
|
||||
Candidate status: source commit e333af4dc7af3a9d3789c8c0db26a0df8bdddfee. The16 whole
|
||||
singles passed451/0 under sage-2008 with zero skips/cancellations; raw
|
||||
outputs and merge receipts are in this packet, indexed by EVIDENCE.json
|
||||
and SOURCE.json. Sage keeps the landing gate. Filbert's implementation
|
||||
review and that gate remain pending. Prior315/0 on fefd54e13 is early
|
||||
read evidence only. Sage-2016 authorizes the seat-only source/packet push.
|
||||
@@ -0,0 +1,157 @@
|
||||
{
|
||||
"sourceCommit": "a6101e21c596e2972ab5a7e3087736075899505e",
|
||||
"base": "a3652371338e60187d4e95cee4a0f30f3c8a8f06",
|
||||
"paths": [
|
||||
{
|
||||
"path": "BUILD-LOG.md",
|
||||
"sha256": "b7c8f906f2db095dfe02d29b4064836af83ae877a87b38c09466b8c9a327e019",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/bus/src/broker.mjs",
|
||||
"sha256": "762234259d72db87aff510751fe14003099759ae37bc8eaf14f1ea1de61d2005",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/bus/src/runtime.mjs",
|
||||
"sha256": "c759e665514a5bcad40536bc9f979837187fe6523462b3c0a0687182885c3ac6",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/bus/src/server.mjs",
|
||||
"sha256": "207c7a76752c753ef7380f18f9ce1a4f23e8fa35142973b6358aaf0c45f44899",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/bus/tests/library.test.mjs",
|
||||
"sha256": "58d839709e005571b398a11abda5a50f542bab0e37bd97b72f43cde926434301",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/business/src/business.mjs",
|
||||
"sha256": "5fd3fee664d3e70153d988b4c1a42406f888a31b3927fa52375e66619d8cec59",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/business/src/cli.mjs",
|
||||
"sha256": "31cfe9090900169416e1207dc6db865b046439273917e9de442add4159c89eb3",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/business/src/instance-settings.mjs",
|
||||
"sha256": "3873411688d927336a909d0299acddeba92a653102c660d276471f5a0f6eebd3",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/business/src/organization.mjs",
|
||||
"sha256": "eaa650499d2d078552a2c0e5b13a6126e0aca02f73160032a7325b3f5aa90964",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/business/src/resolve.mjs",
|
||||
"sha256": "712183465fee099606223d84423afc54e3386a0c8e468c68d5ac39c1e676d109",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/business/tests/business.test.mjs",
|
||||
"sha256": "910f924d90b6f9b18c1f36d97cebd0b7a0a15a080b73530c4fb847bfd435fb3f",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/business/tests/cli.test.mjs",
|
||||
"sha256": "d54ba2338bcdfec22764030cf3ec9e3464ab275b15321d6d1b039169ea37fd85",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/business/tests/instance-settings.test.mjs",
|
||||
"sha256": "072e25c5237e1be4294c7a4a95daa2ab593832786013e1283b19725c330647c1",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/business/tests/library-projects-protected.test.mjs",
|
||||
"sha256": "cfc726ec7bf73c1dc9fc6395cba85e374b7a006bac45bd8c47c969550557147f",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/business/tests/resolve.test.mjs",
|
||||
"sha256": "c74af44a83ee918196e2c1016b62786e757c0ae774c9b1613280d3fbbf3ffb22",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/cli/src/config.mjs",
|
||||
"sha256": "ab7b9f452123b6f7e98f4f59cbb3cc4483fd296e4af5522412410ee53d1b20e0",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/cli/src/launcher.mjs",
|
||||
"sha256": "d8a870d8eb8254adfd576688696705359fefbf517b40e5d7482500bf27941022",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/cli/tests/launcher.test.mjs",
|
||||
"sha256": "99234f247e8414120d2fd214efd590e9d573eca86180d7b775cb506ac1c12c78",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/cli/tests/stack-release-fixture.mjs",
|
||||
"sha256": "86a3c15446d4c119206097c754cd15f5bef7b7e93c9f16e9d8696ec8c475eea9",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/cli/tests/stack-release.test.mjs",
|
||||
"sha256": "46cc95a6e75a89b907cdd5e9bd03853e1d1f75f1ced81084d968c5476466822e",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/cli/tests/trackers-boot.test.mjs",
|
||||
"sha256": "c90493e45bfa09bf0b01600aaf04d6ecd79d939357beacc1a9cd65f958bb7c22",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/library/src/index.mjs",
|
||||
"sha256": "ecda99dea46390b81fffa6f414d56a13737233e01d883b82cd186e0e21b6c4d1",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/library/src/mirror.mjs",
|
||||
"sha256": "75ce08fba0956c846f2ca9ab1b565974657925f94ac952c720e7308783946480",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/library/tests/mirror.test.mjs",
|
||||
"sha256": "e96473be70ece8c8232ce5325822244b593f273371b74b4126920654cde9d72c",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/project/src/paths.mjs",
|
||||
"sha256": "bd9debcf3f9bb92560e74f220a0b108dfe24154bc6d1fb03c5ec414356d451f9",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/project/tests/project.test.mjs",
|
||||
"sha256": "0ebe1862ce70f26c4a6a44304182327f9a6944d16cc87f674fbb1d32e08ac602",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/seat/src/checkout.mjs",
|
||||
"sha256": "859201bd192522e51c33b86ef45f73487b27cdfc48ea7e4e09870e26d056048a",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/seat/tests/checkout.test.mjs",
|
||||
"sha256": "663040d7c737aba6403e6397bacf1325b558cc14df3e5677f0a28f9499c45127",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/webui/src/cli.mjs",
|
||||
"sha256": "e98fd2fe4e621d5b4fa1ed95c4d4585469e7ab7a11dd379dc541dddb1b1a1f02",
|
||||
"mode": "100644"
|
||||
},
|
||||
{
|
||||
"path": "packages/webui/tests/library-cli.test.mjs",
|
||||
"sha256": "1983912b76f01f8e6d0c564e3bbcd763c0b2c44044988b192ef827446f98556c",
|
||||
"mode": "100644"
|
||||
}
|
||||
],
|
||||
"priorSourceCommit": "e333af4dc7af3a9d3789c8c0db26a0df8bdddfee"
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
packages/bus/tests/library.test.mjs
|
||||
packages/bus/tests/project-runtime.test.mjs
|
||||
packages/business/tests/business.test.mjs
|
||||
packages/business/tests/cli.test.mjs
|
||||
packages/business/tests/instance-settings.test.mjs
|
||||
packages/business/tests/library-projects-protected.test.mjs
|
||||
packages/business/tests/resolve.test.mjs
|
||||
packages/cli/tests/launcher.test.mjs
|
||||
packages/cli/tests/stack-release-external.test.mjs
|
||||
packages/cli/tests/stack-release.test.mjs
|
||||
packages/cli/tests/stack-upgrade.test.mjs
|
||||
packages/cli/tests/trackers-boot.test.mjs
|
||||
packages/library/tests/mirror.test.mjs
|
||||
packages/project/tests/project.test.mjs
|
||||
packages/seat/tests/checkout.test.mjs
|
||||
packages/webui/tests/library-cli.test.mjs
|
||||
@@ -0,0 +1,229 @@
|
||||
{
|
||||
"base": "fefd54e13",
|
||||
"landing": "f8276c5eb3ecb0aad353ee65e3dd8f7faac5dd87",
|
||||
"overlaps": [
|
||||
"packages/bus/src/broker.mjs",
|
||||
"packages/bus/src/runtime.mjs",
|
||||
"packages/business/src/business.mjs",
|
||||
"packages/business/src/instance-settings.mjs",
|
||||
"packages/business/tests/business.test.mjs",
|
||||
"packages/business/tests/instance-settings.test.mjs",
|
||||
"packages/cli/src/launcher.mjs",
|
||||
"packages/cli/tests/launcher.test.mjs",
|
||||
"packages/library/src/index.mjs"
|
||||
],
|
||||
"initialConflicts": [
|
||||
"packages/bus/src/broker.mjs",
|
||||
"packages/business/src/business.mjs"
|
||||
],
|
||||
"remainingConflicts": [],
|
||||
"resolutions": {
|
||||
"packages/bus/src/broker.mjs": "retain landed hostKeys constructor parameter and add library parameter",
|
||||
"packages/business/src/business.mjs": "retain landed CREATIVE_DEFINITIONS import and add checkMapping import"
|
||||
},
|
||||
"sourcePaths": [
|
||||
{
|
||||
"path": "packages/bus/src/broker.mjs",
|
||||
"merged": true,
|
||||
"sameAsEarlyTree": false,
|
||||
"earlySha256": "dca11dd58561bf3f399d18d7521aefa93f43e0ee3de9c532c1da073ce5a17466",
|
||||
"sha256": "925b3dd6744565349ec421a58b3374ce3d21181e6c2d3d32ffb99c79271b9450"
|
||||
},
|
||||
{
|
||||
"path": "packages/bus/src/runtime.mjs",
|
||||
"merged": true,
|
||||
"sameAsEarlyTree": false,
|
||||
"earlySha256": "6f69e9fb838cf1d8ee60d1b7090395193d3dbfdc6492a401a4b72c356c371ca9",
|
||||
"sha256": "c759e665514a5bcad40536bc9f979837187fe6523462b3c0a0687182885c3ac6"
|
||||
},
|
||||
{
|
||||
"path": "packages/bus/src/server.mjs",
|
||||
"merged": false,
|
||||
"sameAsEarlyTree": true,
|
||||
"earlySha256": "207c7a76752c753ef7380f18f9ce1a4f23e8fa35142973b6358aaf0c45f44899",
|
||||
"sha256": "207c7a76752c753ef7380f18f9ce1a4f23e8fa35142973b6358aaf0c45f44899"
|
||||
},
|
||||
{
|
||||
"path": "packages/bus/tests/library.test.mjs",
|
||||
"merged": false,
|
||||
"sameAsEarlyTree": true,
|
||||
"earlySha256": "58d839709e005571b398a11abda5a50f542bab0e37bd97b72f43cde926434301",
|
||||
"sha256": "58d839709e005571b398a11abda5a50f542bab0e37bd97b72f43cde926434301"
|
||||
},
|
||||
{
|
||||
"path": "packages/business/src/business.mjs",
|
||||
"merged": true,
|
||||
"sameAsEarlyTree": false,
|
||||
"earlySha256": "e132f92211cd35f951e85ff5e90471a2316755cb35ad7eabf516e780ce6c13ad",
|
||||
"sha256": "5fd3fee664d3e70153d988b4c1a42406f888a31b3927fa52375e66619d8cec59"
|
||||
},
|
||||
{
|
||||
"path": "packages/business/src/cli.mjs",
|
||||
"merged": false,
|
||||
"sameAsEarlyTree": true,
|
||||
"earlySha256": "31cfe9090900169416e1207dc6db865b046439273917e9de442add4159c89eb3",
|
||||
"sha256": "31cfe9090900169416e1207dc6db865b046439273917e9de442add4159c89eb3"
|
||||
},
|
||||
{
|
||||
"path": "packages/business/src/instance-settings.mjs",
|
||||
"merged": true,
|
||||
"sameAsEarlyTree": false,
|
||||
"earlySha256": "04d61c1ec89a5d67da75aede46c3a8e2197aadd63b11bef8e4fc37d90e8862cf",
|
||||
"sha256": "3873411688d927336a909d0299acddeba92a653102c660d276471f5a0f6eebd3"
|
||||
},
|
||||
{
|
||||
"path": "packages/business/src/organization.mjs",
|
||||
"merged": false,
|
||||
"sameAsEarlyTree": true,
|
||||
"earlySha256": "eaa650499d2d078552a2c0e5b13a6126e0aca02f73160032a7325b3f5aa90964",
|
||||
"sha256": "eaa650499d2d078552a2c0e5b13a6126e0aca02f73160032a7325b3f5aa90964"
|
||||
},
|
||||
{
|
||||
"path": "packages/business/src/resolve.mjs",
|
||||
"merged": false,
|
||||
"sameAsEarlyTree": true,
|
||||
"earlySha256": "712183465fee099606223d84423afc54e3386a0c8e468c68d5ac39c1e676d109",
|
||||
"sha256": "712183465fee099606223d84423afc54e3386a0c8e468c68d5ac39c1e676d109"
|
||||
},
|
||||
{
|
||||
"path": "packages/business/tests/business.test.mjs",
|
||||
"merged": true,
|
||||
"sameAsEarlyTree": false,
|
||||
"earlySha256": "55aafd3f0eea816d5f42283b7b74323dd32a698d7b95dd9cc54529dbf7b16058",
|
||||
"sha256": "910f924d90b6f9b18c1f36d97cebd0b7a0a15a080b73530c4fb847bfd435fb3f"
|
||||
},
|
||||
{
|
||||
"path": "packages/business/tests/cli.test.mjs",
|
||||
"merged": false,
|
||||
"sameAsEarlyTree": true,
|
||||
"earlySha256": "d54ba2338bcdfec22764030cf3ec9e3464ab275b15321d6d1b039169ea37fd85",
|
||||
"sha256": "d54ba2338bcdfec22764030cf3ec9e3464ab275b15321d6d1b039169ea37fd85"
|
||||
},
|
||||
{
|
||||
"path": "packages/business/tests/instance-settings.test.mjs",
|
||||
"merged": true,
|
||||
"sameAsEarlyTree": false,
|
||||
"earlySha256": "c0959f3af3df653bbf469471d3bbe3f28bc4478cba8ba57910af7f09498c4c3f",
|
||||
"sha256": "072e25c5237e1be4294c7a4a95daa2ab593832786013e1283b19725c330647c1"
|
||||
},
|
||||
{
|
||||
"path": "packages/business/tests/library-projects-protected.test.mjs",
|
||||
"merged": false,
|
||||
"sameAsEarlyTree": true,
|
||||
"earlySha256": "cfc726ec7bf73c1dc9fc6395cba85e374b7a006bac45bd8c47c969550557147f",
|
||||
"sha256": "cfc726ec7bf73c1dc9fc6395cba85e374b7a006bac45bd8c47c969550557147f"
|
||||
},
|
||||
{
|
||||
"path": "packages/business/tests/resolve.test.mjs",
|
||||
"merged": false,
|
||||
"sameAsEarlyTree": true,
|
||||
"earlySha256": "c74af44a83ee918196e2c1016b62786e757c0ae774c9b1613280d3fbbf3ffb22",
|
||||
"sha256": "c74af44a83ee918196e2c1016b62786e757c0ae774c9b1613280d3fbbf3ffb22"
|
||||
},
|
||||
{
|
||||
"path": "packages/cli/src/config.mjs",
|
||||
"merged": false,
|
||||
"sameAsEarlyTree": true,
|
||||
"earlySha256": "ab7b9f452123b6f7e98f4f59cbb3cc4483fd296e4af5522412410ee53d1b20e0",
|
||||
"sha256": "ab7b9f452123b6f7e98f4f59cbb3cc4483fd296e4af5522412410ee53d1b20e0"
|
||||
},
|
||||
{
|
||||
"path": "packages/cli/src/launcher.mjs",
|
||||
"merged": true,
|
||||
"sameAsEarlyTree": false,
|
||||
"earlySha256": "2272232dbe6c362eddb23ad903987fd4b8e0ca1eb94dbe93b66b3e785e7d0712",
|
||||
"sha256": "d8a870d8eb8254adfd576688696705359fefbf517b40e5d7482500bf27941022"
|
||||
},
|
||||
{
|
||||
"path": "packages/cli/tests/launcher.test.mjs",
|
||||
"merged": true,
|
||||
"sameAsEarlyTree": false,
|
||||
"earlySha256": "38fb51c15764333642d75db7fb358d611e448049cf894b24686ea6cf2cf169c4",
|
||||
"sha256": "99234f247e8414120d2fd214efd590e9d573eca86180d7b775cb506ac1c12c78"
|
||||
},
|
||||
{
|
||||
"path": "packages/cli/tests/stack-release-fixture.mjs",
|
||||
"merged": false,
|
||||
"sameAsEarlyTree": true,
|
||||
"earlySha256": "86a3c15446d4c119206097c754cd15f5bef7b7e93c9f16e9d8696ec8c475eea9",
|
||||
"sha256": "86a3c15446d4c119206097c754cd15f5bef7b7e93c9f16e9d8696ec8c475eea9"
|
||||
},
|
||||
{
|
||||
"path": "packages/cli/tests/stack-release.test.mjs",
|
||||
"merged": false,
|
||||
"sameAsEarlyTree": true,
|
||||
"earlySha256": "aa63fadca8b3a51e7af1ff7560fd2645f3ef56bf4e5625b2d5a5f6946db40996",
|
||||
"sha256": "aa63fadca8b3a51e7af1ff7560fd2645f3ef56bf4e5625b2d5a5f6946db40996"
|
||||
},
|
||||
{
|
||||
"path": "packages/cli/tests/trackers-boot.test.mjs",
|
||||
"merged": false,
|
||||
"sameAsEarlyTree": true,
|
||||
"earlySha256": "c90493e45bfa09bf0b01600aaf04d6ecd79d939357beacc1a9cd65f958bb7c22",
|
||||
"sha256": "c90493e45bfa09bf0b01600aaf04d6ecd79d939357beacc1a9cd65f958bb7c22"
|
||||
},
|
||||
{
|
||||
"path": "packages/library/src/index.mjs",
|
||||
"merged": true,
|
||||
"sameAsEarlyTree": false,
|
||||
"earlySha256": "b80e6c27daf908a0e71fcc1e5e8c91d05e857790bd77d92e06ff086ab3623306",
|
||||
"sha256": "ecda99dea46390b81fffa6f414d56a13737233e01d883b82cd186e0e21b6c4d1"
|
||||
},
|
||||
{
|
||||
"path": "packages/library/src/mirror.mjs",
|
||||
"merged": false,
|
||||
"sameAsEarlyTree": true,
|
||||
"earlySha256": "75ce08fba0956c846f2ca9ab1b565974657925f94ac952c720e7308783946480",
|
||||
"sha256": "75ce08fba0956c846f2ca9ab1b565974657925f94ac952c720e7308783946480"
|
||||
},
|
||||
{
|
||||
"path": "packages/library/tests/mirror.test.mjs",
|
||||
"merged": false,
|
||||
"sameAsEarlyTree": true,
|
||||
"earlySha256": "e96473be70ece8c8232ce5325822244b593f273371b74b4126920654cde9d72c",
|
||||
"sha256": "e96473be70ece8c8232ce5325822244b593f273371b74b4126920654cde9d72c"
|
||||
},
|
||||
{
|
||||
"path": "packages/project/src/paths.mjs",
|
||||
"merged": false,
|
||||
"sameAsEarlyTree": true,
|
||||
"earlySha256": "bd9debcf3f9bb92560e74f220a0b108dfe24154bc6d1fb03c5ec414356d451f9",
|
||||
"sha256": "bd9debcf3f9bb92560e74f220a0b108dfe24154bc6d1fb03c5ec414356d451f9"
|
||||
},
|
||||
{
|
||||
"path": "packages/project/tests/project.test.mjs",
|
||||
"merged": false,
|
||||
"sameAsEarlyTree": true,
|
||||
"earlySha256": "0ebe1862ce70f26c4a6a44304182327f9a6944d16cc87f674fbb1d32e08ac602",
|
||||
"sha256": "0ebe1862ce70f26c4a6a44304182327f9a6944d16cc87f674fbb1d32e08ac602"
|
||||
},
|
||||
{
|
||||
"path": "packages/seat/src/checkout.mjs",
|
||||
"merged": false,
|
||||
"sameAsEarlyTree": true,
|
||||
"earlySha256": "859201bd192522e51c33b86ef45f73487b27cdfc48ea7e4e09870e26d056048a",
|
||||
"sha256": "859201bd192522e51c33b86ef45f73487b27cdfc48ea7e4e09870e26d056048a"
|
||||
},
|
||||
{
|
||||
"path": "packages/seat/tests/checkout.test.mjs",
|
||||
"merged": false,
|
||||
"sameAsEarlyTree": true,
|
||||
"earlySha256": "663040d7c737aba6403e6397bacf1325b558cc14df3e5677f0a28f9499c45127",
|
||||
"sha256": "663040d7c737aba6403e6397bacf1325b558cc14df3e5677f0a28f9499c45127"
|
||||
},
|
||||
{
|
||||
"path": "packages/webui/src/cli.mjs",
|
||||
"merged": false,
|
||||
"sameAsEarlyTree": true,
|
||||
"earlySha256": "e98fd2fe4e621d5b4fa1ed95c4d4585469e7ab7a11dd379dc541dddb1b1a1f02",
|
||||
"sha256": "e98fd2fe4e621d5b4fa1ed95c4d4585469e7ab7a11dd379dc541dddb1b1a1f02"
|
||||
},
|
||||
{
|
||||
"path": "packages/webui/tests/library-cli.test.mjs",
|
||||
"merged": false,
|
||||
"sameAsEarlyTree": true,
|
||||
"earlySha256": "1983912b76f01f8e6d0c564e3bbcd763c0b2c44044988b192ef827446f98556c",
|
||||
"sha256": "1983912b76f01f8e6d0c564e3bbcd763c0b2c44044988b192ef827446f98556c"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
diff --git a/packages/bus/src/broker.mjs b/packages/bus/src/broker.mjs
|
||||
index 3baa709f9..512d57519 100644
|
||||
--- a/packages/bus/src/broker.mjs
|
||||
+++ b/packages/bus/src/broker.mjs
|
||||
@@ -90,0 +91 @@ export const PROJECT_FILE_VERBS = Object.freeze(['project.files', 'project.file'
|
||||
+export const LIBRARY_VERBS = Object.freeze(['library.file', 'library.status']);
|
||||
@@ -281,0 +283 @@ export class Broker {
|
||||
+ #library;
|
||||
@@ -297 +299 @@ export class Broker {
|
||||
- constructor({ store, businesses, secretCheck = () => {}, credentialStatus = () => [], organization = null, project = null, usage = null, limits = null, harnessOn = null, credentialVerbs = null, hostGrant = null, hostKeys = null }) {
|
||||
+ constructor({ store, businesses, secretCheck = () => {}, credentialStatus = () => [], organization = null, project = null, library = null, usage = null, limits = null, harnessOn = null, credentialVerbs = null, hostGrant = null, hostKeys = null }) {
|
||||
@@ -308,0 +311 @@ export class Broker {
|
||||
+ this.#library = library;
|
||||
@@ -2189,0 +2193,2 @@ export class Broker {
|
||||
+ if (LIBRARY_VERBS.includes(request.verb))
|
||||
+ return this.#requestLibrary(s, { verb: request.verb, args: structuredClone(args) });
|
||||
@@ -2438,0 +2444,20 @@ export class Broker {
|
||||
+ // C2-04 M4: only a verified human reads library text or status. Host Git
|
||||
+ // functions stay injected, preserving this module's sandbox import closure.
|
||||
+ async #requestLibrary(s, request) {
|
||||
+ const { verb, args } = request;
|
||||
+ try {
|
||||
+ this.#human(s);
|
||||
+ const fields = verb === 'library.file' ? ['project', 'path'] : ['project'];
|
||||
+ keys(args, fields, fields);
|
||||
+ if (!this.#library?.readFile || !this.#library?.status) fail('project-not-configured');
|
||||
+ const context = { business: this.#business(s.business), project: args.project };
|
||||
+ const result = verb === 'library.file'
|
||||
+ ? await this.#library.readFile({ ...context, path: args.path })
|
||||
+ : await this.#library.status(context);
|
||||
+ this.#secretCheck(result);
|
||||
+ return result;
|
||||
+ } catch (error) {
|
||||
+ const Failure = this.#library?.LibraryError;
|
||||
+ throw this.#refused(s, Failure && error instanceof Failure ? new BusError(error.code) : error, request);
|
||||
+ }
|
||||
+ }
|
||||
diff --git a/packages/bus/src/runtime.mjs b/packages/bus/src/runtime.mjs
|
||||
index f81f956f2..e265ff5d1 100644
|
||||
--- a/packages/bus/src/runtime.mjs
|
||||
+++ b/packages/bus/src/runtime.mjs
|
||||
@@ -5,0 +6 @@ import * as projectModule from '../../project/src/index.mjs';
|
||||
+import * as libraryModule from '../../library/src/index.mjs';
|
||||
@@ -95 +96 @@ export async function startBroker({
|
||||
- ...Object.values(businesses).flatMap((b) => Object.values(b.projects ?? {}).map((p) => p.root)),
|
||||
+ ...Object.values(businesses).flatMap((b) => Object.values(b.projects ?? {}).filter(p => p.kind !== 'library').map((p) => p.root)),
|
||||
@@ -130,0 +132,5 @@ export async function startBroker({
|
||||
+ // C2-04: mirrors are host state, never session checkouts. An unsafe
|
||||
+ // existing mirror refuses startup before a socket can become ready.
|
||||
+ for (const business of Object.values(businesses))
|
||||
+ for (const [project, entry] of Object.entries(business.projects ?? {}))
|
||||
+ if (entry.kind === 'library') await libraryModule.ensureMirror({ business, project, dataRoot });
|
||||
@@ -138,0 +145,5 @@ export async function startBroker({
|
||||
+ library: {
|
||||
+ readFile: context => libraryModule.readLibraryFile({ ...context, dataRoot }),
|
||||
+ status: context => libraryModule.libraryStatus({ ...context, dataRoot }),
|
||||
+ LibraryError: libraryModule.LibraryError,
|
||||
+ },
|
||||
diff --git a/packages/business/src/business.mjs b/packages/business/src/business.mjs
|
||||
index d08a4f52e..e8337ea2b 100644
|
||||
--- a/packages/business/src/business.mjs
|
||||
+++ b/packages/business/src/business.mjs
|
||||
@@ -12,0 +13 @@ import { checkPlugins } from "../../plugins/src/kinds.mjs";
|
||||
+import { checkMapping } from "../../library/src/mapping.mjs";
|
||||
@@ -241,0 +243,4 @@ export function validateBusinessDocument(document, file, { rolesDir }) {
|
||||
+ if (entry.kind === 'library') {
|
||||
+ projects[id] = checkMapping(entry, `${file} projects.${id}`, { fail: (code, message) => refuse(`${code}: ${message}`) });
|
||||
+ continue;
|
||||
+ }
|
||||
@@ -257,0 +263 @@ export function validateBusinessDocument(document, file, { rolesDir }) {
|
||||
+ if (projects[project].kind === 'library') refuse(`${file} roles.${instance}.publish names library project ${project}; library repositories cannot be published by agents`);
|
||||
diff --git a/packages/business/src/instance-settings.mjs b/packages/business/src/instance-settings.mjs
|
||||
index ff3a6d9d3..50cc36edc 100644
|
||||
--- a/packages/business/src/instance-settings.mjs
|
||||
+++ b/packages/business/src/instance-settings.mjs
|
||||
@@ -149,0 +150 @@ export function instanceSettings({ dir, rolesDir, system, levels = () => null })
|
||||
+ if (entry.kind === 'library') continue;
|
||||
diff --git a/packages/business/tests/business.test.mjs b/packages/business/tests/business.test.mjs
|
||||
index b64659fa1..0f214a005 100644
|
||||
--- a/packages/business/tests/business.test.mjs
|
||||
+++ b/packages/business/tests/business.test.mjs
|
||||
@@ -10,0 +11,30 @@ import { launchDoc, businessDoc, REPO, REPO_ROLES, rolesCopy, tmp, writeJson } f
|
||||
+test('C2-04: library mappings load without roots, remain frozen, and retain mapping refusals', async t => {
|
||||
+ const { mappingEntry } = await import('../../library/tests/helpers.mjs');
|
||||
+ const { rmSync } = await import('node:fs');
|
||||
+ const root = tmp(); t.after(() => rmSync(root, { recursive: true, force: true }));
|
||||
+ const doc = businessDoc(root), file = join(root, 'businesses/acme.json');
|
||||
+ doc.projects = { books: mappingEntry(), ...doc.projects };
|
||||
+ const loaded = validateBusinessDocument(doc, file, { rolesDir: REPO_ROLES });
|
||||
+ const { checkMapping } = await import('../../library/src/mapping.mjs');
|
||||
+ assert.deepEqual(loaded.projects.books, checkMapping(mappingEntry()));
|
||||
+ assert.equal(loaded.projects.books.root, undefined);
|
||||
+ assert.ok(Object.isFrozen(loaded.projects.books.universes.harbor.books));
|
||||
+ const only = structuredClone(doc); delete only.projects.stack;
|
||||
+ assert.deepEqual(Object.keys(validateBusinessDocument(only, file, { rolesDir: REPO_ROLES }).projects), ['books']);
|
||||
+ doc.projects.books.universes.harbor.playground = ['Elsewhere/Playground/'];
|
||||
+ refuses(() => validateBusinessDocument(doc, file, { rolesDir: REPO_ROLES }), /library-playground-outside-book/);
|
||||
+ doc.projects.books = { ...mappingEntry(), root: '/forbidden' };
|
||||
+ refuses(() => validateBusinessDocument(doc, file, { rolesDir: REPO_ROLES }), /library-mapping-invalid/);
|
||||
+});
|
||||
+
|
||||
+test('C2-04: an otherwise valid publish grant cannot name a library repo', async t => {
|
||||
+ const { mappingEntry } = await import('../../library/tests/helpers.mjs');
|
||||
+ const { rmSync } = await import('node:fs');
|
||||
+ const root = tmp(); t.after(() => rmSync(root, { recursive: true, force: true }));
|
||||
+ const doc = businessDoc(root);
|
||||
+ doc.projects.books = { ...mappingEntry(), remote: 'https://git.example/writer/books' };
|
||||
+ doc.roles.coder.identity = { name: 'Coder', email: '[email protected]', gitea: { url: 'https://git.example', user: 'acme-coder' } };
|
||||
+ doc.roles.coder.publish = ['books'];
|
||||
+ refuses(() => validateBusinessDocument(doc, join(root, 'businesses/acme.json'), { rolesDir: REPO_ROLES }), /publish.*library/);
|
||||
+});
|
||||
+
|
||||
diff --git a/packages/business/tests/instance-settings.test.mjs b/packages/business/tests/instance-settings.test.mjs
|
||||
index 6b19f9e89..a6c8fe665 100644
|
||||
--- a/packages/business/tests/instance-settings.test.mjs
|
||||
+++ b/packages/business/tests/instance-settings.test.mjs
|
||||
@@ -22,0 +23,10 @@ const LEVELS = { pi: ["off", "minimal", "low", "medium", "high", "xhigh", "max"]
|
||||
+test('C2-04: instance settings skip a library while checking a later code project', async () => {
|
||||
+ const { mappingEntry } = await import('../../library/tests/helpers.mjs');
|
||||
+ const f = fixture(doc => { doc.projects = { books: mappingEntry(), ...doc.projects }; });
|
||||
+ writeJson(projectFilePath(f.doc.projects.stack.root), { projectVersion: 1, id: 'stack', vars: { 'tracker.project': 3 } });
|
||||
+ const before = f.settings.read('acme');
|
||||
+ f.settings.set('acme', { revision: before.revision, instance: 'gate-215', op: 'add', definition: 'merge-gate' }, 'jason');
|
||||
+ assert.deepEqual(JSON.parse(readFileSync(f.file, 'utf8')).projects.books, mappingEntry());
|
||||
+ assert.ok(f.settings.read('acme').instances['gate-215']);
|
||||
+});
|
||||
+
|
||||
diff --git a/packages/cli/src/launcher.mjs b/packages/cli/src/launcher.mjs
|
||||
index 604cef203..c721ee9e8 100644
|
||||
--- a/packages/cli/src/launcher.mjs
|
||||
+++ b/packages/cli/src/launcher.mjs
|
||||
@@ -354 +354 @@ export function createLauncher({
|
||||
- checkouts = await ensureCheckouts({ workspace, projects: b.projects, env });
|
||||
+ checkouts = await ensureCheckouts({ workspace, projects: Object.fromEntries(Object.entries(b.projects).filter(([, entry]) => entry.kind !== 'library')), env });
|
||||
diff --git a/packages/cli/tests/launcher.test.mjs b/packages/cli/tests/launcher.test.mjs
|
||||
index 3b663ba94..4636df3de 100644
|
||||
--- a/packages/cli/tests/launcher.test.mjs
|
||||
+++ b/packages/cli/tests/launcher.test.mjs
|
||||
@@ -32,0 +33,10 @@ const skip = sandboxProblem() ?? false;
|
||||
+test('C2-04: launcher workspace clones code but never the library', { skip, timeout: 30000 }, async t => {
|
||||
+ const { mappingEntry } = await import('../../library/tests/helpers.mjs');
|
||||
+ const f = await setup(t, doc => { doc.projects = { books: mappingEntry(), ...doc.projects }; return doc; });
|
||||
+ await f.launcher.launchPm();
|
||||
+ const workspace = workspaceDir(f.f.dataRoot, 'acme', 'chief');
|
||||
+ assert.equal(existsSync(join(workspace, 'stack', '.git')), true);
|
||||
+ assert.equal(existsSync(join(workspace, 'books')), false);
|
||||
+ assert.equal(await f.close(), 0);
|
||||
+});
|
||||
+
|
||||
diff --git a/packages/library/src/index.mjs b/packages/library/src/index.mjs
|
||||
index f64d77860..53ce5cb43 100644
|
||||
--- a/packages/library/src/index.mjs
|
||||
+++ b/packages/library/src/index.mjs
|
||||
@@ -8,0 +9 @@ export { survey, formatSurvey, surveyMain } from './survey.mjs';
|
||||
+export { SYNC_STATE_FILE, mirrorPath, ensureMirror, withLibraryLock, servedCommit, readSyncState, libraryStatus, readLibraryFile } from './mirror.mjs';
|
||||
@@ -0,0 +1,14 @@
|
||||
✔ C2-04 M4: both verbs reject every agent before arguments or adapter access (30.144386ms)
|
||||
✔ C2-04 bus: human reads validate keys and return adapter results without path leakage (11.434614ms)
|
||||
✔ C2-04 socket: each async library verb resolves its result rather than serializing {} (17.684117ms)
|
||||
✔ C2-04 runtime: protectedRoots skips library but retains real code-root credential protection (45.253455ms)
|
||||
✔ C2-04 runtime: unsafe existing mirror refuses boot and never publishes a socket (23.246812ms)
|
||||
✔ C2-04 runtime: real library adapters reach the socket and lock waits leave other bus reads responsive (107.052077ms)
|
||||
ℹ tests 6
|
||||
ℹ suites 0
|
||||
ℹ pass 6
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 359.869493
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
✔ Broker keeps the sandbox client import closure: only the listed imports, no lazy project import (2.265255ms)
|
||||
✔ without a trusted project adapter all three async paths refuse project-not-configured (57.448982ms)
|
||||
✔ real startBroker injects the project adapter for socket reads and bound-author record writes (102.784823ms)
|
||||
ℹ tests 3
|
||||
ℹ suites 0
|
||||
ℹ pass 3
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 312.717335
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
✔ C2-04: library mappings load without roots, remain frozen, and retain mapping refusals (12.852402ms)
|
||||
✔ C2-04: an otherwise valid publish grant cannot name a library repo (2.693014ms)
|
||||
✔ config directory and file path follow MOSAIC_CONFIG (0.229245ms)
|
||||
✔ the fixture business validates and comes back frozen (1.006969ms)
|
||||
✔ two instances may share a definition (0.94271ms)
|
||||
✔ top-level refusals (3.474817ms)
|
||||
✔ arbiters and projects (5.543282ms)
|
||||
✔ role instances (2.7386ms)
|
||||
✔ Vikunja bots (6.181044ms)
|
||||
✔ a role without Vikunja takes no tracker block (5.900981ms)
|
||||
✔ credential references match the definition's services (3.012597ms)
|
||||
✔ launch (8.561546ms)
|
||||
✔ REQ-THREAD-2 REQ-LAUNCH-1 launch.threadIdleSeconds: absent is the default, a positive integer is used, anything else refuses (6.420869ms)
|
||||
✔ loadBusiness: file checks (2.241353ms)
|
||||
✔ loadBusiness: not a regular file (46.573969ms)
|
||||
✔ loading writes nothing (2.802338ms)
|
||||
✔ names that are Object.prototype properties don't count as declared (3.291238ms)
|
||||
✔ the shipped example refuses as written and validates once filled in (1.195924ms)
|
||||
✔ persona vars: agent layer, creative definition only, both or neither (9.0736ms)
|
||||
ℹ tests 19
|
||||
ℹ suites 0
|
||||
ℹ pass 19
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 199.91256
|
||||
@@ -0,0 +1,18 @@
|
||||
✔ C2-04: business validate and resolve skip a library before code projects and credential checks (235.663956ms)
|
||||
✔ usage errors exit 4 (325.805811ms)
|
||||
✔ validate: a good business exits 0 and prints instance digests (69.331646ms)
|
||||
✔ validate: project files (344.919464ms)
|
||||
✔ validate: missing files and a broken system config (252.779029ms)
|
||||
✔ validate: credential reference problems exit 2 and name each one (66.663076ms)
|
||||
✔ validate: a token file inside the repository is refused (78.714732ms)
|
||||
✔ validate: role definitions come from MOSAIC_ROLES_DIR (201.487424ms)
|
||||
✔ resolve: prints one instance's record (281.684478ms)
|
||||
✔ resolve: refusals (454.610462ms)
|
||||
ℹ tests 10
|
||||
ℹ suites 0
|
||||
ℹ pass 10
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 2381.258516
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
✔ C2-04: instance settings skip a library while checking a later code project (32.527878ms)
|
||||
✔ row 165 read lists each instance and the definitions add accepts (3.218296ms)
|
||||
✔ row 165 add: two instances join, validate exits 0, the log names the human, and the bus restart is reported (93.702292ms)
|
||||
✔ row 165 change: definition, vars and launch membership log before and after; only a definition change asks for a restart (99.793939ms)
|
||||
✔ row 165 refuses each validation failure and leaves the file's bytes alone (33.820979ms)
|
||||
✔ row 165 refuses an added instance whose definition declares credentials, and says why (5.999086ms)
|
||||
✔ row 165 refuses a definition change to or from one that declares credentials (6.767714ms)
|
||||
✔ row 165 a vars or launch change on an instance with its binding succeeds and keeps the binding (89.83786ms)
|
||||
✔ row 165 refuses an END_PROTECTED definition and every change to a protected instance (9.793219ms)
|
||||
✔ row 165 refuses while a project file doesn't resolve, as validate would (15.487298ms)
|
||||
✔ row 165 refuses a stale revision and leaves the file's bytes alone (10.871014ms)
|
||||
✔ row 65 an instance write refuses harness-off, thinking-unsupported, an unknown model and a partial fallback (38.02395ms)
|
||||
✔ row 213 a creative instance is the human's: add, vars and definition changes, persona digest only (90.045141ms)
|
||||
ℹ tests 13
|
||||
ℹ suites 0
|
||||
ℹ pass 13
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 608.08011
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
✔ C2-04 M9: changed playground and hybrid entries leave business and changes.jsonl byte-identical (23.242034ms)
|
||||
✔ C2-04 M9: code projects, additions, deletions and array changes are protected too (15.756145ms)
|
||||
✔ C2-04 M9: canonical key order is allowed and a non-project setter still records its change (17.060499ms)
|
||||
✔ C2-04 M9: a serialization hook cannot change projects after the canonical comparison (9.833495ms)
|
||||
ℹ tests 4
|
||||
ℹ suites 0
|
||||
ℹ pass 4
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 118.54831
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
✔ C2-04: a library first in projects does not hide a later project layer (9.584516ms)
|
||||
✔ systemVars flattens the validated config (1.063324ms)
|
||||
✔ precedence: system, business, project, project role, agent (2.001802ms)
|
||||
✔ limits narrow the definition and never widen it (2.563505ms)
|
||||
✔ role.launch stays within-role only for the instance the launch block names (5.04696ms)
|
||||
✔ limits.authority without role.launch leaves the launcher with no launch block (2.106162ms)
|
||||
✔ limits.authority narrows cross-role actions too (1.098761ms)
|
||||
✔ classify (1.065895ms)
|
||||
✔ the record carries what the broker and launcher need (0.966677ms)
|
||||
✔ digest: key order doesn't matter, any value change does (7.43546ms)
|
||||
✔ refusals (2.150825ms)
|
||||
ℹ tests 11
|
||||
ℹ suites 0
|
||||
ℹ pass 11
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 94.022587
|
||||
@@ -0,0 +1,54 @@
|
||||
✔ C2-04: launcher workspace clones code but never the library (1298.398732ms)
|
||||
✔ bus start --pm: the launcher instance (the chief of staff) runs under its own PID namespace, registered, with a manifest (1264.618734ms)
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"r4accc4841d41","instance":"chief","turn":"81814ac7-9330-484a-95f8-cc2f80a9aeef","source":"@none","code":"baseline-unknown"}
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"r0719029c31b1","instance":"coder","turn":"fd2dfc33-9ab6-4d4d-9eef-ba46b6d7a510","source":"@none","code":"baseline-unknown"}
|
||||
✔ the chief of staff launches a coder through its launch tool; the coder answers; refusals name their code (657.713119ms)
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"r4b37f983290f","instance":"chief","turn":"6c8768d3-4742-4ae2-87c6-4653182c8520","source":"@none","code":"baseline-unknown"}
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"r7bc8dc8db66c","instance":"pm","turn":"4b196787-1bf9-4702-82d2-397c84ab1e3c","source":"@none","code":"baseline-unknown"}
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"r4b37f983290f","instance":"chief","turn":"1c6ec26d-97da-43b6-8cd8-91994e6c7c7b","source":"@none","code":"baseline-unknown"}
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"r7bc8dc8db66c","instance":"pm","turn":"a12fdeb9-e25d-45a4-bd25-e048621a3557","source":"@none","code":"baseline-unknown"}
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"r7bc8dc8db66c","instance":"pm","turn":"ad419687-0675-48a8-9932-90b2da5333ef","source":"@none","code":"baseline-unknown"}
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"r4b37f983290f","instance":"chief","turn":"0d54926f-f5b8-4dbb-b38a-8ea23fdd5cb5","source":"@none","code":"baseline-unknown"}
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"r7bc8dc8db66c","instance":"pm","turn":"6891e20c-472e-4e67-815e-88728024acf4","source":"@none","code":"baseline-unknown"}
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"r4b37f983290f","instance":"chief","turn":"9ac6fe37-9044-4f54-bae0-826a6c84c15b","source":"@none","code":"baseline-unknown"}
|
||||
✔ a launched pm's request_staff reaches the chief of staff; no other session has the tool and the launch limits still hold (1202.248105ms)
|
||||
✔ each launch makes sure the workspace has a clone of the project: cloned, fast-forwarded, or fetched and logged (3926.301471ms)
|
||||
✔ a role the broker says holds a merge decision gets land_work, its prompt line, its landing and the git socket; without it, none (593.731622ms)
|
||||
✔ REQ-LAUNCH-1 the tick starts a listed merge decision holder once, with land_work, the Landing line and its landing turn; an unlisted holder starts nothing (755.589469ms)
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"rf7ecf1ef2b65","instance":"coder","turn":"744cb116-e163-4b18-831e-556df7e7bfd9","source":"@none","code":"baseline-unknown"}
|
||||
✔ a holder running since before the resolution is stopped once the broker releases it, land-relaunch, and the next tick starts it: landing turn first, then the message that waited (739.551352ms)
|
||||
✔ a landing run that ended isn't started again for its decision, a spent decision starts nothing, and a new decision starts the holder (564.790867ms)
|
||||
✔ after a restart, the new host's first tick starts a holder whose decision is still held (883.94802ms)
|
||||
✔ a refused landing start is logged once per code with its decision, isn't a start, and the next tick with room starts the holder (595.491854ms)
|
||||
✔ a project clone that can't be made refuses checkout-failed, from --chief and from a session, with no run and no clone left (250.651304ms)
|
||||
✔ a runner that stops at once ends its launch with the runner's reason (336.620423ms)
|
||||
✔ a Claude Code launch with no session credential refuses before it starts (172.971844ms)
|
||||
✔ a pi launch needs no session credential: pi logs in through its own ENV_ALLOW variables (287.021469ms)
|
||||
usage: {"event":"plugin-refused","kind":"harness","name":"down","code":"missing","message":"/home/jwoltje/.t3/worktrees/mosaic-stack/herb-row215-on-f827/packages/plugins/harness/down is missing","kept":[]}
|
||||
plugins: {"event":"plugin-refused","kind":"harness","name":"down","code":"missing","message":"/home/jwoltje/.t3/worktrees/mosaic-stack/herb-row215-on-f827/packages/plugins/harness/down is missing","kept":[]}
|
||||
✔ row 65 a failed primary preflight launches the fallback on a fixture harness module, recording the route and the reason (327.373038ms)
|
||||
✔ a runner killed from the host ends its launch as killed, not failed (381.927989ms)
|
||||
✔ a missing or failing bwrap refuses sandbox-unavailable before anything starts; there is no unconfined fallback (198.778768ms)
|
||||
✔ row 64 a role skill that isn't enabled refuses skill-not-enabled, and one that isn't a plain directory skill-refused, before anything starts (184.44803ms)
|
||||
✔ row 213 a creative instance's persona is read from <configDir>/personas: off its digest the launch fails with the mismatch as its reason (239.197527ms)
|
||||
✔ row 64 on Claude Code a role skill that isn't enabled refuses the same way, before anything starts (230.64829ms)
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"r800039251a09","instance":"chief","turn":"f2e6a1ad-767e-4316-be90-6194b840e2ef","source":"@none","code":"baseline-unknown"}
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"rfeeb081c2983","instance":"coder","turn":"1abdb906-521d-4100-897b-f5eba12663cf","source":"@none","code":"baseline-unknown"}
|
||||
✔ a real Claude Code coder's shell can't read a stand-in secret or anything else its sandbox doesn't hold (1612.164523ms)
|
||||
✔ a host that died hard leaves its sessions to the next host, which kills them and ends their runs so the role can be launched again (909.716449ms)
|
||||
✔ a host that died hard leaves its sessions to the next host, which finds one already exited (23) and ends their runs so the role can be launched again (3844.434582ms)
|
||||
✔ bus start --no-launch leaves an earlier host's live session alone: no signal, no end, sessions.json as it was (224.265713ms)
|
||||
✔ bus start --no-launch refuses every launch: the PM launch and a session's request, each logged, nothing spawned (193.925449ms)
|
||||
✔ bus start --no-launch starts no thread tick; the same host with launches runs it (1181.783938ms)
|
||||
✔ a malformed sessions.json refuses the host start with exit 3 and stays as it was (166.842635ms)
|
||||
✔ an over-long launch request is refused at once, not at the 10 s idle timeout (171.101521ms)
|
||||
✔ a launch client that never closes its side doesn't hold the host's close (170.266667ms)
|
||||
✔ a runner that ignores SIGTERM is killed when the host closes (1305.753454ms)
|
||||
ℹ tests 31
|
||||
ℹ suites 0
|
||||
ℹ pass 31
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 24989.261794
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
✔ row 232: confirm, revert, gate, --to and --expect-from need --units external; the user-only flags are usage under it (1129.148785ms)
|
||||
✔ row 232: pm-on and activate --pm-after-harness refuse external-pm (1112.631619ms)
|
||||
✔ row 232: units-running (N4) refuses while a unit is active and leaves the store, the log and TAKEN; failed counts as down (2301.278572ms)
|
||||
✔ row 232: activate stages: the pointer stays, AWAITING-UNITS names TO, a backup of the stopped store, no directory in the set, no --user, no journal (2229.906955ms)
|
||||
✔ row 232: A3 order: capture-failed and marker-failed refuse with exit 3 and leave no marker or FAILED (1913.7476ms)
|
||||
✔ row 232: confirm and revert refuse open-activation with no marker, two, the wrong copy, or one the log holds closed; refusals name no activation (3892.845676ms)
|
||||
✔ row 232: confirm polls: bus status good after 3 s fails with --timeout 1, writes FAILED and leaves the rest; FAILED then refuses activation-failed (3703.021367ms)
|
||||
✔ row 232: confirm polls to a pass with --timeout 10: the pointer, an ok line that reads as the started run, no marker (6350.955178ms)
|
||||
✔ row 232: stale-start: @1792540799 fails a start floor of 1792540800 with stale-start (3365.187863ms)
|
||||
✔ row 232: stale-start is a gate code: an enter time that turns to @1792540800 after 2 s passes with --timeout 10 (4713.287991ms)
|
||||
✔ row 232: gate (N2, A2f): --since 1792540800 passes @1792540800 and fails @1792540799; it writes nothing (3014.18649ms)
|
||||
✔ row 232: the external PM check reads launches list: one live run of launch.by since the start passes (7715.019003ms)
|
||||
✔ row 232: revert puts the wrapper back and leaves the store when nothing migrated (1540.240269ms)
|
||||
✔ row 232: confirm --rollback refuses rollback-mismatch, and logs rollback-failed with exit 2 when OLD fails its gate (3838.859298ms)
|
||||
✔ row 232: confirm --rollback after a --restore swap logs rollbackCode not-attempted; rollback --restore finds an external backup (4385.316411ms)
|
||||
✔ row 232: sequence 1: activate, confirm times out, revert, confirm --rollback --cause A5: gate-failed rollback ok (5668.17255ms)
|
||||
✔ row 232: sequence 2: activate --migrate, the wrapper install fails, revert restores TAKEN, confirm --rollback --cause A3 (3356.512703ms)
|
||||
✔ row 232: sequence 3: activate, root's A4 fails, revert, confirm --rollback --cause A4: failed code units-start (3090.998502ms)
|
||||
✔ row 232: sequence 4: a capture failure leaves nothing open, then A2f's gate OLD writes nothing (2006.820211ms)
|
||||
✔ row 232: sequence 5: a confirm of the wrong copy is refused, and revert and confirm --rollback still close the activation (3716.790879ms)
|
||||
✔ row 232: sequence 6: a revert that fails leaves the activation open, and the next --plan refuses interrupted-run (2084.865556ms)
|
||||
✔ row 232: sequence 7: adopt, two confirmed activates, rollback --to the previous copy, confirmed, logs op rollback (8859.407093ms)
|
||||
✔ row 232: sequence 8: a migration that writes and fails: revert restores the backup byte for byte, confirm --rollback --cause A3 (4066.89509ms)
|
||||
✔ row 232: user mode: every systemctl call carries --user, and activate, rollback and check make the base's calls (8472.325246ms)
|
||||
✔ row 232: user mode: a default activate --plan prints the base's bytes (2725.266801ms)
|
||||
ℹ tests 25
|
||||
ℹ suites 0
|
||||
ℹ pass 25
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 96332.465778
|
||||
+227
@@ -0,0 +1,227 @@
|
||||
✔ T1 adopt writes the pointer from the units once; a failing check refuses check-failed (1604.406515ms)
|
||||
✔ T2 activate installs exactly the pointer's pm, claude and Console flags (2285.234425ms)
|
||||
▶ T3 a hand-edited unit refuses unit-flags-drift, names the difference and changes nothing
|
||||
✔ pm (1074.84155ms)
|
||||
✔ claude (1048.597035ms)
|
||||
✔ console (1069.472197ms)
|
||||
✔ T3 a hand-edited unit refuses unit-flags-drift, names the difference and changes nothing (3193.872973ms)
|
||||
▶ T4 each item 3 refusal changes nothing and logs one line with its code
|
||||
✔ copy-missing (970.101799ms)
|
||||
✔ copy-unreachable (976.867501ms)
|
||||
✔ copy-schema-unknown (942.411453ms)
|
||||
✔ already-active (966.01391ms)
|
||||
✔ instance-busy (another business active) (1033.865857ms)
|
||||
✔ instance-busy (this business activating) (989.106934ms)
|
||||
✔ drop-in-override (1051.252734ms)
|
||||
✔ no-pointer (535.256184ms)
|
||||
✔ T4 each item 3 refusal changes nothing and logs one line with its code (7466.71817ms)
|
||||
✔ T5 an activate with no migration stops the Console then the bus, installs, starts the bus then the Console (2298.616234ms)
|
||||
✔ T6 a migration without --migrate rolls back with migration-needs-flag (2085.91559ms)
|
||||
✔ T7 --migrate takes the backup before the migration runs (2415.592569ms)
|
||||
✔ T8 a failed migration restores the backup and keeps the store it replaced (2571.261148ms)
|
||||
✔ T9 a store outside the target's chain rolls back with store-newer (2405.058696ms)
|
||||
▶ T10 each gate check failing alone rolls back and puts every file back
|
||||
✔ units-inactive (5907.690999ms)
|
||||
✔ bus-status (6093.058453ms)
|
||||
✔ healthz (6393.330472ms)
|
||||
✔ copy-check (5442.480521ms)
|
||||
✔ pm-launch-unconfirmed (5607.705975ms)
|
||||
✔ T10 each gate check failing alone rolls back and puts every file back (29445.44482ms)
|
||||
▶ T10b the PM check needs exactly one launched line for a live run of this start
|
||||
✔ no launched line (5534.978468ms)
|
||||
✔ two lines (5372.975087ms)
|
||||
✔ a changed word (5420.826895ms)
|
||||
✔ run not in launches list (5601.520776ms)
|
||||
✔ run started before the start (5448.208485ms)
|
||||
✔ a human launch with no journal line (5346.70067ms)
|
||||
✔ run for another business (5684.948726ms)
|
||||
✔ run not live (5860.307931ms)
|
||||
✔ one well-formed line and a live run pass (2078.4402ms)
|
||||
✔ T10b the PM check needs exactly one launched line for a live run of this start (46350.52861ms)
|
||||
✔ T11 a rollback whose gate fails too: rollback-failed, exit 2, both units stopped, no retry (7145.208417ms)
|
||||
✔ T12 rollback takes the previous copy from the log (3164.021139ms)
|
||||
✔ T13 a rollback across a migration needs --restore, then restores and goes live (3796.056873ms)
|
||||
✔ T14 events written after the backup need --events N with the right N (4384.802883ms)
|
||||
✔ T14b a rollback --restore whose gate fails stops both units and skips item 6 (5813.087127ms)
|
||||
✔ T14c a rollback without --restore whose gate fails runs item 6 (6237.609182ms)
|
||||
✔ T15 --plan names the migration and the restore and changes nothing (2849.139286ms)
|
||||
✔ T26 --plan lists the commits an activate adds, after the migration lines (1481.868533ms)
|
||||
✔ T27 --plan names each migration step, or says the steps cannot be read (1173.748951ms)
|
||||
✔ T25 --plan refuses copies-unrelated when neither copy is an ancestor of the other (569.344968ms)
|
||||
▶ T23 --plan reads the store without changing a file, stopped or held
|
||||
✔ stopped store (721.626407ms)
|
||||
✔ held store (690.820461ms)
|
||||
✔ T23 --plan reads the store without changing a file, stopped or held (1413.175682ms)
|
||||
✔ T24 business-mismatch and capture-failed refuse with exit 3; a short id is a usage error (1463.46361ms)
|
||||
✔ T16 status prints the pointer, the log, the check, bus status and drift, and writes nothing (910.07629ms)
|
||||
✔ T19 a started line with no final line: status shows it and every changing verb refuses (1271.59212ms)
|
||||
✔ T20 a held run lock refuses run-locked without a log line; status and --plan still run (1515.929929ms)
|
||||
✔ T21 a bus unit with no MOSAIC_CLAUDE_BIN: adopt and activate refuse no-claude-pin (1789.2511ms)
|
||||
▶ T22 the stopped store read: a -wal or -shm refuses store-unclean and is left alone; a clean read adds no file
|
||||
✔ bus.sqlite-wal (1954.988144ms)
|
||||
✔ bus.sqlite-shm (2042.456191ms)
|
||||
✔ clean (2209.768749ms)
|
||||
✔ T22 the stopped store read: a -wal or -shm refuses store-unclean and is left alone; a clean read adds no file (6208.13226ms)
|
||||
▶ T28 a unit path, drop-in directory or drop-in file that cannot be read, or a relative unit path, refuses drop-in-override before any stop
|
||||
✔ unit path (938.058563ms)
|
||||
✔ drop-in directory (934.896589ms)
|
||||
✔ drop-in file (958.129787ms)
|
||||
✔ relative unit path (943.563721ms)
|
||||
✔ T28 a unit path, drop-in directory or drop-in file that cannot be read, or a relative unit path, refuses drop-in-override before any stop (3775.662901ms)
|
||||
▶ T29 a bus that stops during the held-store read: --plan says so, rollback --restore refuses restore-mismatch
|
||||
✔ --plan (932.393863ms)
|
||||
✔ rollback --restore (2879.958858ms)
|
||||
✔ T29 a bus that stops during the held-store read: --plan says so, rollback --restore refuses restore-mismatch (3812.923223ms)
|
||||
✔ T30 a copy check that agrees on another copy fails the gate with copy-check and rolls back (6646.085499ms)
|
||||
▶ T31 a quoted or escaped Environment= or ExecStart= is unreadable: refusals by name, nothing read from /a
|
||||
✔ Environment double quotes (1976.227811ms)
|
||||
✔ Environment single quotes (2063.211816ms)
|
||||
✔ Environment backslash (2038.183771ms)
|
||||
✔ ExecStart quotes (1984.451614ms)
|
||||
✔ Console ExecStart quotes (1980.466835ms)
|
||||
✔ T31 a quoted or escaped Environment= or ExecStart= is unreadable: refusals by name, nothing read from /a (10043.710809ms)
|
||||
▶ T32 item 1: --pm-after-harness refuses a target without harness or a file that sets it, and passes without the PM
|
||||
✔ usage: not with --pm, and only for activate (721.955423ms)
|
||||
✔ pm-after-harness-target (1015.757752ms)
|
||||
✔ pm-after-harness-set (1371.242025ms)
|
||||
✔ a pointer without pm (841.537689ms)
|
||||
✔ phase 1 installs without --pm, skips pm_launched and writes the pending pointer (1915.010297ms)
|
||||
✔ T32 item 1: --pm-after-harness refuses a target without harness or a file that sets it, and passes without the PM (5866.555622ms)
|
||||
▶ T33 item 2: read_pointer takes pmPending only as true beside pm false; a pending pointer refuses activate and shows in status
|
||||
✔ read_pointer (1570.154285ms)
|
||||
✔ pm-pending, already-adopted and the status line (3037.065347ms)
|
||||
✔ T33 item 2: read_pointer takes pmPending only as true beside pm false; a pending pointer refuses activate and shows in status (4607.778248ms)
|
||||
▶ T34 item 3: pm-on refuses before any stop, passes with the PM, or puts the phase-1 bus back
|
||||
✔ not-pending (719.010856ms)
|
||||
✔ harness-unset (2272.485716ms)
|
||||
✔ a launched line passes: the bus alone restarts with --pm (3276.598137ms)
|
||||
✔ a failed pm_launched puts the phase-1 unit back: exit 1, still pending (6693.543553ms)
|
||||
✔ a failed phase-1 gate too: pm-on-down, exit 2, both units stopped (8141.636634ms)
|
||||
✔ T34 item 3: pm-on refuses before any stop, passes with the PM, or puts the phase-1 bus back (21104.286659ms)
|
||||
▶ T35 item 4: rollback from pending installs --pm; a plug-in kind the target lacks refuses by name
|
||||
✔ rollback from pending gates pm_launched on the old copy (3372.092831ms)
|
||||
✔ after the harness set, rollback refuses until harness is gone (5046.857905ms)
|
||||
✔ activate names every kind the target lacks (1244.308621ms)
|
||||
✔ T35 item 4: rollback from pending installs --pm; a plug-in kind the target lacks refuses by name (9663.997607ms)
|
||||
✔ T36 --plan shows the pending state and lists the row 169 refusals it can see (3695.067003ms)
|
||||
✔ T37 tester-port activate writes pointer and unit, replaces the port, and supported re-pin and rollback keep it (6897.072525ms)
|
||||
✔ T38 tester-port rollback to unsupported target drops flag in plan, steps, unit and pointer (3812.546819ms)
|
||||
✔ T39 tester-port explicit unsupported target reads target copy and refuses before stopping either unit (904.276249ms)
|
||||
✔ T40 tester-port invalid values refuse exit 4 before stopping, including tunnel and main ports (819.160889ms)
|
||||
✔ T41 tester-port inherited activate to unsupported target drops it and retains drift refusal and failed-run recovery (8462.827367ms)
|
||||
✔ T42 tester-port pm-on preserves pointer Console flags (3200.83272ms)
|
||||
▶ T43 row 180 item 1: runs in one second get distinct activation ids, rollback sets and post-attempt stores
|
||||
✔ activate then pm-on on the same copy (3520.417628ms)
|
||||
✔ two restores: an old-form id and a suffixed one, each with its own post-attempt store (6507.524064ms)
|
||||
✔ adopt takes the next free id too (703.050442ms)
|
||||
✔ all ten names taken: capture-failed before anything stops, and the log line names no activation (956.29941ms)
|
||||
✔ --restore takes an id with or without -1 to -9 and nothing else (971.565868ms)
|
||||
✔ T43 row 180 item 1: runs in one second get distinct activation ids, rollback sets and post-attempt stores (12659.952034ms)
|
||||
▶ T44 row 180 item 2: --plan lists tester-port-invalid and tester-port-target with its other refusals
|
||||
✔ a bad tester port (1970.260005ms)
|
||||
✔ without --plan a bad port is usage before any pointer read (650.605696ms)
|
||||
✔ a target Console without --tester-port (1005.8136ms)
|
||||
✔ T44 row 180 item 2: --plan lists tester-port-invalid and tester-port-target with its other refusals (3627.354723ms)
|
||||
▶ T45 row 181 items 2 and 3: the restore guard counts events and every COUNTED table
|
||||
✔ both modes count events and each listed table, and a table the store lacks counts 0 (817.850391ms)
|
||||
✔ one instance_names row and no event refuses before any stop; --events 1 restores (4258.491111ms)
|
||||
✔ one usage_records row and no event refuses before any stop; --events 1 restores (4200.77682ms)
|
||||
✔ a listed table that cannot be read refuses restore-mismatch before any stop (2308.610496ms)
|
||||
✔ the in-run recount counts the listed tables too (3113.596786ms)
|
||||
✔ T45 row 181 items 2 and 3: the restore guard counts events and every COUNTED table (14700.29833ms)
|
||||
✔ T46 row 181 item 4: every table in the bus schema is in exactly one of four lists (3.037176ms)
|
||||
✔ T47 row 185 test 1: a same-schema activate leaves a whole backup and the log line names it (1868.973993ms)
|
||||
✔ T48 row 185 test 2: a gate failure on a same-schema activate rolls back without a restore (5804.760552ms)
|
||||
▶ T49 row 185 test 3: a same-schema rollback --restore restores, or refuses rows written after STAMP
|
||||
✔ no rows after STAMP: restores and goes live (3320.288695ms)
|
||||
✔ one instance_names row after STAMP refuses post-backup-events; --events 1 restores (3651.108762ms)
|
||||
✔ T49 row 185 test 3: a same-schema rollback --restore restores, or refuses rows written after STAMP (6972.06843ms)
|
||||
✔ T50 row 185 test 4: activate --plan prints the backup line and writes nothing (2352.202566ms)
|
||||
✔ T51 row 185 test 5: an activate with no store file takes no backup (2180.71818ms)
|
||||
▶ T52 row 186: the activate plan's backup line says what the run will do
|
||||
✔ same schema (2482.119077ms)
|
||||
✔ same schema with --migrate (2194.383877ms)
|
||||
✔ in chain with --migrate (2161.378827ms)
|
||||
✔ in chain without --migrate (1945.096692ms)
|
||||
✔ outside the chain (1933.991036ms)
|
||||
✔ outside the chain with --migrate (1982.219098ms)
|
||||
✔ T52 row 186: the activate plan's backup line says what the run will do (12700.35568ms)
|
||||
✔ T178 proxy proof header and path survive re-pin and rollback unchanged in the pointer and unit (3084.56264ms)
|
||||
✔ T178 proxy proof pair survives a tester-port replacement as well (1871.352274ms)
|
||||
▶ T53 row 187: activate sets, carries and drops the proof pair
|
||||
✔ tests 1 and 9: the pair goes after the preview flags, before --send and the kept --tester-port, as the unit renders it; a new pair replaces it (5957.458612ms)
|
||||
✔ tests 2 and 3: an activate of the live copy writes the pair; a later activate and a rollback carry it (4748.919152ms)
|
||||
✔ test 2: only a pair change may name the live copy; the log keeps from and to, and rollback still goes to the earlier copy (6348.550383ms)
|
||||
✔ test 2: a live-copy activate says only the Console flags change, and backs up the stopped store before it installs (3766.45236ms)
|
||||
✔ test 3: pm-on keeps the pair (2959.180793ms)
|
||||
✔ test 4: --no-proof drops the pair from the pointer and the unit and says so; with no pair it says so and passes (5233.036939ms)
|
||||
✔ test 5: each refusal exits 3 before anything stops (3649.68534ms)
|
||||
✔ tests 5 and 9: --plan lists every proof refusal with the others and writes nothing (836.025341ms)
|
||||
✔ test 6: usage errors (773.25631ms)
|
||||
✔ test 7: a rollback to a copy without proof support drops the pair and says so (3311.183201ms)
|
||||
✔ test 7: an activate to a copy without proof support refuses proof-target without --no-proof and passes with it (3616.1202ms)
|
||||
✔ T53 row 187: activate sets, carries and drops the proof pair (41201.876404ms)
|
||||
▶ T54 row 188: a carried pair gets the proof file checks, and a proof file inside the repository refuses
|
||||
✔ test 1: an activate that carries the pair refuses after chmod 644, in the plan and the run, before anything stops (2194.421439ms)
|
||||
✔ test 1: an activate that carries the pair refuses after a symlink to a mode-600 file, in the plan and the run, before anything stops (2189.529552ms)
|
||||
✔ test 1: an activate that carries the pair refuses after removal, in the plan and the run, before anything stops (2243.035352ms)
|
||||
✔ test 2: a rollback that carries the pair refuses after chmod 644, in the plan and the run, before anything stops (2336.000835ms)
|
||||
✔ test 3: a proof file inside the repository refuses, in the plan and the run, before anything stops (1105.046097ms)
|
||||
✔ test 4: a path outside the repository through a directory symlink into it refuses on its realpath (1150.666433ms)
|
||||
✔ T54 row 188: a carried pair gets the proof file checks, and a proof file inside the repository refuses (11219.876632ms)
|
||||
▶ T55 row 189: activate --no-send drops --send, and rollback and pm-on carry it off
|
||||
✔ test 1: a live-copy --no-send drops --send from the pointer and the unit, keeps the rest in order, logs the step and backs up the stopped store (2274.3857ms)
|
||||
✔ test 2: a plain live-copy activate still refuses already-active, and so does --no-send once --send is gone (3110.763383ms)
|
||||
✔ test 3: --plan prints one send: line in each case, with the live-copy note on a same-copy run (4485.563548ms)
|
||||
✔ test 4: after --no-send, a rollback to the earlier copy leaves --send out of the pointer and the unit (3260.741012ms)
|
||||
✔ test 4: pm-on after --no-send keeps --send off (3151.996202ms)
|
||||
✔ test 5: --no-send on rollback, pm-on, status, adopt or rehearse is a usage error (654.253174ms)
|
||||
✔ test 6: with both a pair and --send in the pointer, --no-send and --no-proof each drop what they name and keep the rest (9881.189087ms)
|
||||
✔ T55 row 189: activate --no-send drops --send, and rollback and pm-on carry it off (26820.278319ms)
|
||||
▶ T57 row 200: activate --sso, its refusals before any stop, and the rollback to a Console without --sso
|
||||
✔ item 1: --sso drops the preview set and the pair, puts --sso before --send and the tester port, and the plan names what it drops and carries (3703.052075ms)
|
||||
✔ item 1: --sso may re-pin the live copy once; later activates carry it; --no-send still drops --send (8819.731338ms)
|
||||
✔ item 1: --sso with a pair or --no-proof, or on any verb but activate, is a usage error (692.195455ms)
|
||||
✔ item 2: a target without --sso, a missing or bad console.sso, and each slot problem refuse before any stop (5662.393194ms)
|
||||
✔ item 3: a config whose console key the target loader refuses stops an activate or a rollback before any stop, naming the first step (4284.150525ms)
|
||||
✔ item 3: a rollback from --sso to a Console without it takes the flags from the set of the activation onto the copy, past a same-copy re-pin (sage-1389) (11448.283647ms)
|
||||
✔ item 3: a rollback set that is missing, fails its sums, holds no argv or already ran --sso refuses sso-rollback-flags (4548.577973ms)
|
||||
✔ round 2 (webby-0028 N1): run through a symlinked repository path, a slot or a proof file inside the repository still refuses (2401.295904ms)
|
||||
✔ round 2 (webby-0028 N2): a config.json that does not parse stops the run before anything is read or stopped (2172.272961ms)
|
||||
✔ round 3 (sage-1556): a named instance turns --sso on with its own config, slot and Console unit, and rolls back from its own set (4291.803296ms)
|
||||
✔ row 238 (#1744): on a named instance the sso-config first step names --instance NAME in both commands (1134.427878ms)
|
||||
✔ T57 row 200: activate --sso, its refusals before any stop, and the rollback to a Console without --sso (49160.357454ms)
|
||||
✔ R1 rehearse passes on the same schema; the scratch root holds its files and the live files stay byte-identical (3480.635997ms)
|
||||
✔ R2 rehearse runs the migration checks when the schema differs; the live store stays at 3g (3538.664935ms)
|
||||
✔ R3 a failing migration gives REHEARSAL_FAIL migrate and starts nothing (352.394887ms)
|
||||
✔ R4 a host that does not start, does not answer status, reports another pid, launches anyway, makes a launches directory or keeps its lock each fails by name (22497.071985ms)
|
||||
✔ R5 a host that ignores SIGTERM gets SIGKILL and FAIL host-stopped (4425.852712ms)
|
||||
✔ R6 a Console that does not answer /healthz gives REHEARSAL_FAIL healthz (5628.652507ms)
|
||||
✔ R7 a host on another copy fails copy-match (5626.942239ms)
|
||||
✔ R8 a scratch port in use or reserved refuses, and the rehearsal takes no other port (483.876429ms)
|
||||
✔ R9 mos-0963: a role reference left outside placeholders/, or left on an env variable, fails credential-ref-live before the host starts (737.183647ms)
|
||||
✔ R10 mos-0962: a scratch business that still sets a tracker fails tracker-configured (336.641991ms)
|
||||
✔ R11 mos-0961: a scratch config on the live data root or on any root but the scratch one, or a sessions.json naming a running pid, refuses by name (1329.146892ms)
|
||||
✔ R12 mos-0962: a notifier config with a binding fails notify-off (322.530573ms)
|
||||
✔ R13 the pre-checks: an old copy, a backup that fails its sums, a missing backup or pointer, and usage (467.892209ms)
|
||||
✔ R14 a host that writes the live config, the live business file or the backup fails the end check by name (9332.612807ms)
|
||||
✔ R15 a rehearsal stopped by TERM, INT or HUP fails signal and still stops the host and Console and runs the end checks (9980.867141ms)
|
||||
✔ row 233: --backup last takes the newest backup the log records; a later line with backup null does not hide it, and the store line names it (3438.884089ms)
|
||||
✔ row 233: --backup last with no backup in the log, or no log, exits 3 with no-backup and makes no rehearsal directory (190.873827ms)
|
||||
✔ row 233: --backup last refuses a newest backup that is not an activation id, with exit 1 (117.903969ms)
|
||||
▶ T56 row 190: named instances side by side on one unit directory, $BIN and set of stand-ins
|
||||
✔ T-I3 each instance renders its own config, session env and Description, and nothing of another (1497.847969ms)
|
||||
✔ T-I4 a Console port another installed Console takes refuses port-claimed, and a named instance keeps off the default ports (1995.198242ms)
|
||||
✔ T-I6 alpha's activate and rollback reach nothing of beta's (3765.448219ms)
|
||||
✔ T-I6 swapped: beta's reach nothing of alpha's (3738.069466ms)
|
||||
✔ T-I7 MOSAIC_CONFIG naming alpha's config with no flag refuses instance-root-mismatch and changes nothing (672.561735ms)
|
||||
✔ T-I9 another instance's bus active refuses nothing; one of this instance's does (5819.537565ms)
|
||||
✔ T56 row 190: named instances side by side on one unit directory, $BIN and set of stand-ins (17490.000329ms)
|
||||
ℹ tests 196
|
||||
ℹ suites 0
|
||||
ℹ pass 196
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 533493.817869
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
✔ row 233: sequence 1: confirm fails healthz, the driver reverts, renders the old copy and confirm --rollback --cause A5 passes: exit 1 (6210.373434ms)
|
||||
✔ row 233: sequence 2: activate --migrate fails at the wrapper, revert restores the store, confirm --rollback --cause A3: exit 1 (3236.556603ms)
|
||||
✔ row 233: sequence 3: root's render of the new copy fails, the driver rolls back with --cause A4, and holds the lock to the end: exit 1 (3088.506825ms)
|
||||
✔ row 233: sequence 4: a capture failure is exit 3 from the stage, and A2f restarts the old units and gates them: exit 1 (2296.722984ms)
|
||||
✔ row 233: N1: a bus that outlives A2's timeout keeps its old start, so A2f's gate fails stale-start: exit 2, both units stopped (7977.855045ms)
|
||||
✔ row 233: sequence 5: confirm of the wrong copy is refused, and the driver rolls back with --cause A5: exit 1 (3484.271196ms)
|
||||
✔ row 233: sequence 6: a revert that fails stops both units at exit 2, and the next run refuses at its --plan with nothing stopped (2709.834241ms)
|
||||
✔ row 233: sequence 7: two upgrades and a rollback --to the previous copy with --restore, the args file following each confirm (7481.097653ms)
|
||||
✔ row 240: I3 N1: a failed args move after A5 exits 5 args-failed, the new copy live and confirmed and both args files kept (2791.714439ms)
|
||||
✔ row 233: sequence 8: a migration that writes and fails: the driver reverts to the backup byte for byte, --cause A3: exit 1 (3155.287145ms)
|
||||
✔ row 233: a second run while the lock is held refuses upgrade-running with one log line and no call (659.849042ms)
|
||||
✔ row 233: A1 refuses open-activation on any AWAITING-UNITS file, through the stack's user's --plan, with nothing stopped (1064.03698ms)
|
||||
✔ row 233: a target that migrates refuses migrate-required without --migrate, with nothing stopped (1067.011634ms)
|
||||
✔ row 233: the rehearsal runs after the plan and before A2; a failed one refuses rehearsal-failed with nothing stopped (1099.022074ms)
|
||||
✔ row 233: the rehearsal's BACKUP_STORE line goes to the step log after a match, a malformed one as none, the rest of its output never (2918.095196ms)
|
||||
✔ row 233: a real rehearsal with no backup in the log refuses no-backup, and goes on only with --no-rehearsal, which logs the skip (3400.448853ms)
|
||||
✔ row 233: a real rehearsal after an upgrade names the log's newest backup; --no-rehearsal with a backup refuses rehearsal-required (3795.598553ms)
|
||||
✔ row 233: the args file must be the running user's, with no group or other write, one --copy, and the copy the units run (839.804685ms)
|
||||
✔ row 233: hostcheck (row 240): a nonzero --check or a missing file refuses profile-drift before the plan (962.315692ms)
|
||||
✔ row 233: the checkout must be at --sha (head-mismatch), and a commit the clone can't fast-forward to refuses fetch-failed (936.914531ms)
|
||||
✔ row 233: usage exits 4 before any log or lock (685.887579ms)
|
||||
ℹ tests 21
|
||||
ℹ suites 0
|
||||
ℹ pass 21
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 60456.446459
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
✔ C2-04: a library-only business with tracker.baseUrl boots without a project tracker (143.257728ms)
|
||||
task.close {} answered: invalid-request; fake saw 18 requests, first GET /info 200, GET /projects/1 200, GET /projects/1/views 200
|
||||
task.close on a missing task answered: task-not-found; it made GET /tasks/999 404
|
||||
✔ bootConfig trackers reach the S3 adapter in the real broker child, which goes ready against a fake Vikunja (274.054339ms)
|
||||
ℹ tests 2
|
||||
ℹ suites 0
|
||||
ℹ pass 2
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 502.723687
|
||||
@@ -0,0 +1,24 @@
|
||||
✔ C2-04 mirror: exact default path, bare without checkout or remote, and idempotent initialization (35.180686ms)
|
||||
✔ C2-04 mirror: simultaneous creators publish one intact mirror and leave no staging paths (28.575775ms)
|
||||
✔ C2-04 mirror: skipped publication accepts both coreutils statuses without removing the winner (100.935123ms)
|
||||
✔ C2-04 mirror: preserve occupied directories and reject symlink ancestors and code overlaps (11.206477ms)
|
||||
✔ C2-04 mirror: existing metadata accepts only bare Git plus state and the precreated lock (20.077192ms)
|
||||
✔ C2-04 state: missing state is empty only while the served ref is absent (32.816347ms)
|
||||
✔ C2-04 state: valid problems and sync metadata return no content and change no state bytes (34.864084ms)
|
||||
✔ C2-04 state: strict keys, types, times, branch, commit and fixed R messages fail closed (97.291867ms)
|
||||
✔ C2-04 state: symlink, hardlink, non-private state and missing lock refuse without replacement (29.030379ms)
|
||||
✔ C2-04 file: served commit, not HEAD or a caller commit, owns the exact returned text (71.409306ms)
|
||||
✔ C2-04 file: R1, R2 and R7 exclusions and never-synced mirrors cannot return file bodies (78.061049ms)
|
||||
✔ C2-04 lock: a first-sync and fast-forward reader wait for a consistent pair across processes (230.30816ms)
|
||||
✔ C2-04 lock: same-process waits, timeout code, callback expiry and throw release (5027.25259ms)
|
||||
✔ C2-04 lock: owner death releases the kernel lock without replacing its file (52.471475ms)
|
||||
✔ C2-04 lock: a missing flock binary becomes a handled refusal (44.850141ms)
|
||||
✔ C2-04 lock: an unawaited scoped read drains before the lock is released (19.645975ms)
|
||||
ℹ tests 16
|
||||
ℹ suites 0
|
||||
ℹ pass 16
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 5963.543966
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
✔ C2-04: record APIs refuse a library before creating a repository (2.136303ms)
|
||||
✔ init creates a checked versioned layout, valid templates and human-authored local history (25.282114ms)
|
||||
✔ init honors repo, refuses a non-empty directory and an undeclared project without touching files (13.067957ms)
|
||||
✔ check reports every bad record, filename mismatch and unknown top-level path (11.851979ms)
|
||||
✔ one writer commits validated docs, requirements and decisions with the bound agent author (66.653ms)
|
||||
✔ writer refuses spec paths, bad schemas, mismatched IDs and invalid actor metadata before changing history (14.848593ms)
|
||||
✔ writer refuses human pending edits and remotes instead of absorbing or contacting them (18.544136ms)
|
||||
✔ links, repo/code overlap, identity mismatch and a busy writer refuse safely (17.705717ms)
|
||||
✔ schemas remain package-owned and reject invalid nested data and dates (0.249795ms)
|
||||
✔ git commit failure restores only the attempted record and leaves human history unchanged (36.217826ms)
|
||||
✔ git hooks and ambient git identity cannot alter the record writer or execute outside actions (25.483658ms)
|
||||
✔ project-local schemas cannot weaken checks; invalid UTF-8 and linked git directories refuse (14.206204ms)
|
||||
✔ schema constraints and layout omissions are reported independently (12.868115ms)
|
||||
✔ unsupported schema keywords, malformed contexts, ignored local config and nonempty markers refuse (18.523225ms)
|
||||
✔ a linked git directory is refused before a writer lock can touch its target (30.574055ms)
|
||||
ℹ tests 15
|
||||
ℹ suites 0
|
||||
ℹ pass 15
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 355.86586
|
||||
@@ -0,0 +1,91 @@
|
||||
✔ C2-04: ensureCheckouts skips a library before a real clone and leaves no books path (22.355495ms)
|
||||
✔ a first launch clones the root at its branch, with the root's path as origin (23.522928ms)
|
||||
✔ the clone is not at its place until git clone has finished (19.304369ms)
|
||||
✔ a later launch fast-forwards a clean clone after a commit to the root, then finds it current (56.365259ms)
|
||||
✔ a clone ahead of the root keeps its commits and counts as current (35.573942ms)
|
||||
▶ a dirty clone and one on another branch are fetched, and nothing but refs/remotes moves
|
||||
✔ a modified file (41.519272ms)
|
||||
✔ an untracked file (42.31579ms)
|
||||
✔ a staged file (42.328417ms)
|
||||
✔ another branch (40.470049ms)
|
||||
✔ a detached HEAD (40.702516ms)
|
||||
✔ a dirty clone and one on another branch are fetched, and nothing but refs/remotes moves (208.344457ms)
|
||||
✔ a diverged clone gets the fetch into refs/remotes and is kept, not-fast-forward (42.026437ms)
|
||||
▶ a clone kept before the branch check, or for a failed status, gets no fetch
|
||||
✔ not-a-clone (22.404264ms)
|
||||
✔ hooks-present (23.073574ms)
|
||||
✔ submodule (30.027272ms)
|
||||
✔ config-changed (26.84014ms)
|
||||
✔ root-unreadable (27.464656ms)
|
||||
✔ root-detached (32.242501ms)
|
||||
✔ status-failed, on the root's branch and clean (35.760734ms)
|
||||
✔ status-failed, dirty (35.340017ms)
|
||||
✔ a clone kept before the branch check, or for a failed status, gets no fetch (234.251087ms)
|
||||
✔ a dirty clone whose fetch fails is kept, fetch-failed, exactly as it was (37.035833ms)
|
||||
✔ every git call the host makes, for a new clone and an existing one, carries maintenance.auto=false and gc.auto=0 (44.392371ms)
|
||||
✔ a clone with loose objects enough for gc --auto gets no maintenance or gc from the fetch and the merge (71.033894ms)
|
||||
▶ a clone with user.name or user.email in its config is kept, and git runs nothing in it
|
||||
✔ user.name (25.544784ms)
|
||||
✔ user.email (25.14754ms)
|
||||
✔ a clone with user.name or user.email in its config is kept, and git runs nothing in it (51.146879ms)
|
||||
✔ a commit git can't read after the fast-forward is null (45.746486ms)
|
||||
✔ a new clone whose commit can't be read refuses the launch and leaves nothing behind (18.576825ms)
|
||||
▶ a clone the session rigged is kept, and git runs nothing and writes nothing outside it
|
||||
✔ core.fsmonitor (33.120199ms)
|
||||
✔ core.hooksPath (33.027016ms)
|
||||
✔ a hook file (30.549575ms)
|
||||
✔ include.path (33.355749ms)
|
||||
✔ includeIf (33.915275ms)
|
||||
✔ a filter driver (34.236367ms)
|
||||
✔ origin moved (34.552998ms)
|
||||
✔ a second origin url (33.217597ms)
|
||||
✔ the origin url twice, both the root (34.870837ms)
|
||||
✔ an ext:: origin (33.6526ms)
|
||||
✔ a branch tracking another remote (33.582081ms)
|
||||
✔ a branch merging a tag (33.08648ms)
|
||||
✔ a fetch line onto local branches (34.366694ms)
|
||||
✔ no origin (33.938644ms)
|
||||
✔ a config file over the size cap (31.285987ms)
|
||||
✔ config a symlink to /dev/zero (31.094858ms)
|
||||
✔ the clone a symlink to the bait (32.754738ms)
|
||||
✔ the clone a file (31.24085ms)
|
||||
✔ the clone a plain directory (30.973366ms)
|
||||
✔ .git a gitdir: file (31.404094ms)
|
||||
✔ .git a symlink (30.769522ms)
|
||||
✔ .git/logs a symlink (30.883317ms)
|
||||
✔ .git/refs/heads a symlink (31.770074ms)
|
||||
✔ .git/objects a symlink (30.840803ms)
|
||||
✔ a reflog hard-linked to a file outside (30.322982ms)
|
||||
✔ HEAD a fifo (31.496048ms)
|
||||
✔ a commondir file (30.352537ms)
|
||||
✔ an alternates file (30.782307ms)
|
||||
✔ a gitlink staged, no .gitmodules (43.468245ms)
|
||||
✔ a gitlink and .gitmodules staged (44.893483ms)
|
||||
✔ a gitlink to a repository with its own gitlink (51.849481ms)
|
||||
✔ a gitlink and .gitmodules committed (47.718755ms)
|
||||
✔ a gitlink and submodule.active in config (44.861481ms)
|
||||
✔ a .git/modules with no gitlink (33.279554ms)
|
||||
✔ a clone the session rigged is kept, and git runs nothing and writes nothing outside it (1175.645437ms)
|
||||
▶ a root that can't be cloned refuses with the project id and leaves nothing behind
|
||||
✔ missing (10.161685ms)
|
||||
✔ not a repository (9.929001ms)
|
||||
✔ a plain directory inside another repository (14.613067ms)
|
||||
✔ unreadable (9.85915ms)
|
||||
✔ on no branch (11.8808ms)
|
||||
✔ missing an object (15.129485ms)
|
||||
✔ a root that can't be cloned refuses with the project id and leaves nothing behind (72.336456ms)
|
||||
✔ a clone whose root is on no branch, or gone, is kept and named (28.236024ms)
|
||||
✔ no credential or forge remote of the root reaches a clone (47.533999ms)
|
||||
✔ every project in the business file gets its own clone at its own branch (36.497038ms)
|
||||
✔ a clone past its time gets SIGTERM and refuses the launch, with nothing left in the workspace (513.397369ms)
|
||||
✔ a clone that ignores SIGTERM gets SIGKILL once the grace period is over (1018.126958ms)
|
||||
✔ a timeout signals git's process group, so a process git started dies with it (515.579592ms)
|
||||
✔ once a signalled git has closed, its group gets SIGKILL, so a process that ignored SIGTERM dies too (515.62296ms)
|
||||
ℹ tests 78
|
||||
ℹ suites 0
|
||||
ℹ pass 78
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 4880.907448
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
✔ C2-04 CLI: both listener callback pairs dispatch library verbs with their own transport (109.519835ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 1
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 191.536271
|
||||
@@ -0,0 +1 @@
|
||||
{"processes": [], "removed": "/mnt/storage/scratch/gt-j5nm6iqn", "sourceHashesUnchanged": 29}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"base": "f8276c5eb",
|
||||
"tip": "8a04f4aa4aba493eb89e92aa9e0c34084be7058e",
|
||||
"overlap": []
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
2026-10-21T13:27:27.279728+00:00
|
||||
@@ -0,0 +1,194 @@
|
||||
[
|
||||
{
|
||||
"file": "packages/bus/tests/library.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 6,
|
||||
"pass": 6,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "01-packages_bus_tests_library.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/bus/tests/project-runtime.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 3,
|
||||
"pass": 3,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "02-packages_bus_tests_project-runtime.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/business/tests/business.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 19,
|
||||
"pass": 19,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "03-packages_business_tests_business.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/business/tests/cli.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 10,
|
||||
"pass": 10,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "04-packages_business_tests_cli.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/business/tests/instance-settings.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 13,
|
||||
"pass": 13,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "05-packages_business_tests_instance-settings.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/business/tests/library-projects-protected.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 4,
|
||||
"pass": 4,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "06-packages_business_tests_library-projects-protected.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/business/tests/resolve.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 11,
|
||||
"pass": 11,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "07-packages_business_tests_resolve.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/launcher.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 31,
|
||||
"pass": 31,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "08-packages_cli_tests_launcher.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release-external.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 25,
|
||||
"pass": 25,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "09-packages_cli_tests_stack-release-external.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 196,
|
||||
"pass": 196,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "10-packages_cli_tests_stack-release.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-upgrade.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 21,
|
||||
"pass": 21,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "11-packages_cli_tests_stack-upgrade.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/trackers-boot.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 2,
|
||||
"pass": 2,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "12-packages_cli_tests_trackers-boot.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/library/tests/mirror.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 16,
|
||||
"pass": 16,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "13-packages_library_tests_mirror.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/project/tests/project.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 15,
|
||||
"pass": 15,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "14-packages_project_tests_project.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/seat/tests/checkout.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 78,
|
||||
"pass": 78,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "15-packages_seat_tests_checkout.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/tests/library-cli.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 1,
|
||||
"pass": 1,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "16-packages_webui_tests_library-cli.test.mjs.log"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1 @@
|
||||
/mnt/storage/scratch/gt-j5nm6iqn
|
||||
@@ -0,0 +1 @@
|
||||
2026-10-21T13:15:15.548778+00:00
|
||||
@@ -0,0 +1 @@
|
||||
{"tests": 451, "pass": 451, "fail": 0, "cancelled": 0, "skipped": 0}
|
||||
@@ -0,0 +1,14 @@
|
||||
✔ C2-04 M4: both verbs reject every agent before arguments or adapter access (31.111616ms)
|
||||
✔ C2-04 bus: human reads validate keys and return adapter results without path leakage (12.907709ms)
|
||||
✔ C2-04 socket: each async library verb resolves its result rather than serializing {} (14.631614ms)
|
||||
✔ C2-04 runtime: protectedRoots skips library but retains real code-root credential protection (42.32493ms)
|
||||
✔ C2-04 runtime: unsafe existing mirror refuses boot and never publishes a socket (20.701022ms)
|
||||
✔ C2-04 runtime: real library adapters reach the socket and lock waits leave other bus reads responsive (82.322654ms)
|
||||
ℹ tests 6
|
||||
ℹ suites 0
|
||||
ℹ pass 6
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 342.882774
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
✔ Broker keeps the sandbox client import closure: only the listed imports, no lazy project import (1.629219ms)
|
||||
✔ without a trusted project adapter all three async paths refuse project-not-configured (43.976856ms)
|
||||
✔ real startBroker injects the project adapter for socket reads and bound-author record writes (68.038516ms)
|
||||
ℹ tests 3
|
||||
ℹ suites 0
|
||||
ℹ pass 3
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 209.393305
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
✔ C2-04: library mappings load without roots, remain frozen, and retain mapping refusals (9.717487ms)
|
||||
✔ C2-04: an otherwise valid publish grant cannot name a library repo (1.932435ms)
|
||||
✔ config directory and file path follow MOSAIC_CONFIG (0.219374ms)
|
||||
✔ the fixture business validates and comes back frozen (0.988926ms)
|
||||
✔ two instances may share a definition (0.940973ms)
|
||||
✔ top-level refusals (3.202519ms)
|
||||
✔ arbiters and projects (4.893652ms)
|
||||
✔ role instances (2.749701ms)
|
||||
✔ Vikunja bots (5.88131ms)
|
||||
✔ a role without Vikunja takes no tracker block (4.097438ms)
|
||||
✔ credential references match the definition's services (2.14689ms)
|
||||
✔ launch (7.492201ms)
|
||||
✔ REQ-THREAD-2 REQ-LAUNCH-1 launch.threadIdleSeconds: absent is the default, a positive integer is used, anything else refuses (4.633228ms)
|
||||
✔ loadBusiness: file checks (1.761847ms)
|
||||
✔ loadBusiness: not a regular file (36.320112ms)
|
||||
✔ loading writes nothing (1.117059ms)
|
||||
✔ names that are Object.prototype properties don't count as declared (2.898886ms)
|
||||
✔ the shipped example refuses as written and validates once filled in (0.943369ms)
|
||||
ℹ tests 18
|
||||
ℹ suites 0
|
||||
ℹ pass 18
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 152.091247
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
✔ C2-04: business validate and resolve skip a library before code projects and credential checks (219.31729ms)
|
||||
✔ usage errors exit 4 (321.939555ms)
|
||||
✔ validate: a good business exits 0 and prints instance digests (76.14497ms)
|
||||
✔ validate: project files (353.409636ms)
|
||||
✔ validate: missing files and a broken system config (238.885921ms)
|
||||
✔ validate: credential reference problems exit 2 and name each one (72.187146ms)
|
||||
✔ validate: a token file inside the repository is refused (66.603163ms)
|
||||
✔ validate: role definitions come from MOSAIC_ROLES_DIR (212.341091ms)
|
||||
✔ resolve: prints one instance's record (340.865306ms)
|
||||
✔ resolve: refusals (526.732262ms)
|
||||
ℹ tests 10
|
||||
ℹ suites 0
|
||||
ℹ pass 10
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 2493.367293
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
✔ C2-04: instance settings skip a library while checking a later code project (33.384562ms)
|
||||
✔ row 165 read lists each instance and the definitions add accepts (2.667885ms)
|
||||
✔ row 165 add: two instances join, validate exits 0, the log names the human, and the bus restart is reported (87.186598ms)
|
||||
✔ row 165 change: definition, vars and launch membership log before and after; only a definition change asks for a restart (92.493768ms)
|
||||
✔ row 165 refuses each validation failure and leaves the file's bytes alone (29.566007ms)
|
||||
✔ row 165 refuses an added instance whose definition declares credentials, and says why (3.207564ms)
|
||||
✔ row 165 refuses a definition change to or from one that declares credentials (4.215516ms)
|
||||
✔ row 165 a vars or launch change on an instance with its binding succeeds and keeps the binding (72.107052ms)
|
||||
✔ row 165 refuses an END_PROTECTED definition and every change to a protected instance (7.281711ms)
|
||||
✔ row 165 refuses while a project file doesn't resolve, as validate would (13.645202ms)
|
||||
✔ row 165 refuses a stale revision and leaves the file's bytes alone (10.119096ms)
|
||||
✔ row 65 an instance write refuses harness-off, thinking-unsupported, an unknown model and a partial fallback (29.171515ms)
|
||||
ℹ tests 12
|
||||
ℹ suites 0
|
||||
ℹ pass 12
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 450.444507
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
✔ C2-04 M9: changed playground and hybrid entries leave business and changes.jsonl byte-identical (20.276877ms)
|
||||
✔ C2-04 M9: code projects, additions, deletions and array changes are protected too (16.209877ms)
|
||||
✔ C2-04 M9: canonical key order is allowed and a non-project setter still records its change (13.103686ms)
|
||||
✔ C2-04 M9: a serialization hook cannot change projects after the canonical comparison (12.598611ms)
|
||||
ℹ tests 4
|
||||
ℹ suites 0
|
||||
ℹ pass 4
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 112.92317
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
✔ C2-04: a library first in projects does not hide a later project layer (6.304379ms)
|
||||
✔ systemVars flattens the validated config (0.828852ms)
|
||||
✔ precedence: system, business, project, project role, agent (1.532829ms)
|
||||
✔ limits narrow the definition and never widen it (2.353655ms)
|
||||
✔ role.launch stays within-role only for the instance the launch block names (4.439921ms)
|
||||
✔ limits.authority without role.launch leaves the launcher with no launch block (1.815884ms)
|
||||
✔ limits.authority narrows cross-role actions too (0.827532ms)
|
||||
✔ classify (0.829892ms)
|
||||
✔ the record carries what the broker and launcher need (0.755977ms)
|
||||
✔ digest: key order doesn't matter, any value change does (5.452ms)
|
||||
✔ refusals (1.724971ms)
|
||||
ℹ tests 11
|
||||
ℹ suites 0
|
||||
ℹ pass 11
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 79.941483
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
✔ C2-04: launcher workspace clones code but never the library (1262.341325ms)
|
||||
✔ bus start --pm: the launcher instance (the chief of staff) runs under its own PID namespace, registered, with a manifest (1237.473965ms)
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"r4414332d2ef5","instance":"chief","turn":"382a782c-719a-48e8-a249-ec24caf5ad1e","source":"@none","code":"baseline-unknown"}
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"reaca93954ae7","instance":"coder","turn":"70bcac05-fbc1-41b2-85cb-725c15884a94","source":"@none","code":"baseline-unknown"}
|
||||
✔ the chief of staff launches a coder through its launch tool; the coder answers; refusals name their code (579.516254ms)
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"rb21267233555","instance":"chief","turn":"c228faeb-6e3c-4453-ba9b-b9a27b9790af","source":"@none","code":"baseline-unknown"}
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"r1fc01260daa7","instance":"pm","turn":"a5d09ce0-4208-4eb4-8178-6e06a1792ab9","source":"@none","code":"baseline-unknown"}
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"rb21267233555","instance":"chief","turn":"25722023-5270-4c50-a8a0-7c3645d08bd7","source":"@none","code":"baseline-unknown"}
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"r1fc01260daa7","instance":"pm","turn":"f4a76756-4300-4cdf-a64b-542fc075c137","source":"@none","code":"baseline-unknown"}
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"r1fc01260daa7","instance":"pm","turn":"99ea9441-ce4e-4aab-a56c-614a30c9f0da","source":"@none","code":"baseline-unknown"}
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"rb21267233555","instance":"chief","turn":"d85fa6e4-7557-4adf-b1f6-5e76455a1e51","source":"@none","code":"baseline-unknown"}
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"r1fc01260daa7","instance":"pm","turn":"87f4bf91-2ef2-4fe7-8e99-09fc8b14887e","source":"@none","code":"baseline-unknown"}
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"rb21267233555","instance":"chief","turn":"6db9d009-2cb9-41ba-a07e-da13d92b8182","source":"@none","code":"baseline-unknown"}
|
||||
✔ a launched pm's request_staff reaches the chief of staff; no other session has the tool and the launch limits still hold (917.244851ms)
|
||||
✔ each launch makes sure the workspace has a clone of the project: cloned, fast-forwarded, or fetched and logged (3692.977114ms)
|
||||
✔ a role the broker says holds a merge decision gets land_work, its prompt line, its landing and the git socket; without it, none (439.559581ms)
|
||||
✔ REQ-LAUNCH-1 the tick starts a listed merge decision holder once, with land_work, the Landing line and its landing turn; an unlisted holder starts nothing (324.77099ms)
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"rd33ea739f0c8","instance":"coder","turn":"434622cc-98ff-44b4-99c9-58a8c92f32af","source":"@none","code":"baseline-unknown"}
|
||||
✔ a holder running since before the resolution is stopped once the broker releases it, land-relaunch, and the next tick starts it: landing turn first, then the message that waited (502.385034ms)
|
||||
✔ a landing run that ended isn't started again for its decision, a spent decision starts nothing, and a new decision starts the holder (453.667705ms)
|
||||
✔ after a restart, the new host's first tick starts a holder whose decision is still held (654.880099ms)
|
||||
✔ a refused landing start is logged once per code with its decision, isn't a start, and the next tick with room starts the holder (498.662638ms)
|
||||
✔ a project clone that can't be made refuses checkout-failed, from --chief and from a session, with no run and no clone left (208.782448ms)
|
||||
✔ a runner that stops at once ends its launch with the runner's reason (261.153743ms)
|
||||
✔ a Claude Code launch with no session credential refuses before it starts (143.737058ms)
|
||||
✔ a pi launch needs no session credential: pi logs in through its own ENV_ALLOW variables (239.874115ms)
|
||||
usage: {"event":"plugin-refused","kind":"harness","name":"down","code":"missing","message":"/home/jwoltje/.t3/worktrees/mosaic-stack/herb-row215-on212/packages/plugins/harness/down is missing","kept":[]}
|
||||
plugins: {"event":"plugin-refused","kind":"harness","name":"down","code":"missing","message":"/home/jwoltje/.t3/worktrees/mosaic-stack/herb-row215-on212/packages/plugins/harness/down is missing","kept":[]}
|
||||
✔ row 65 a failed primary preflight launches the fallback on a fixture harness module, recording the route and the reason (281.577833ms)
|
||||
✔ a runner killed from the host ends its launch as killed, not failed (297.263791ms)
|
||||
✔ a missing or failing bwrap refuses sandbox-unavailable before anything starts; there is no unconfined fallback (151.327191ms)
|
||||
✔ row 64 a role skill that isn't enabled refuses skill-not-enabled, and one that isn't a plain directory skill-refused, before anything starts (151.537445ms)
|
||||
✔ row 64 on Claude Code a role skill that isn't enabled refuses the same way, before anything starts (166.552674ms)
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"rc42c73baf400","instance":"chief","turn":"e62acc78-0ddd-4cd3-bb90-c828cf5dc76e","source":"@none","code":"baseline-unknown"}
|
||||
usage: {"event":"usage-unknown","business":"acme","run":"r9fac1139247f","instance":"coder","turn":"e634dd74-b64a-4c8d-8e8d-90244a1070d4","source":"@none","code":"baseline-unknown"}
|
||||
✔ a real Claude Code coder's shell can't read a stand-in secret or anything else its sandbox doesn't hold (1685.572916ms)
|
||||
✔ a host that died hard leaves its sessions to the next host, which kills them and ends their runs so the role can be launched again (791.200293ms)
|
||||
✔ a host that died hard leaves its sessions to the next host, which finds one already exited (23) and ends their runs so the role can be launched again (3731.707174ms)
|
||||
✔ bus start --no-launch leaves an earlier host's live session alone: no signal, no end, sessions.json as it was (196.993732ms)
|
||||
✔ bus start --no-launch refuses every launch: the PM launch and a session's request, each logged, nothing spawned (159.584006ms)
|
||||
✔ bus start --no-launch starts no thread tick; the same host with launches runs it (1086.093241ms)
|
||||
✔ a malformed sessions.json refuses the host start with exit 3 and stays as it was (132.916552ms)
|
||||
✔ an over-long launch request is refused at once, not at the 10 s idle timeout (143.651083ms)
|
||||
✔ a launch client that never closes its side doesn't hold the host's close (144.715063ms)
|
||||
✔ a runner that ignores SIGTERM is killed when the host closes (1275.914847ms)
|
||||
ℹ tests 30
|
||||
ℹ suites 0
|
||||
ℹ pass 30
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 21918.233853
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
✔ row 232: confirm, revert, gate, --to and --expect-from need --units external; the user-only flags are usage under it (832.842347ms)
|
||||
✔ row 232: pm-on and activate --pm-after-harness refuse external-pm (934.889182ms)
|
||||
✔ row 232: units-running (N4) refuses while a unit is active and leaves the store, the log and TAKEN; failed counts as down (2121.604528ms)
|
||||
✔ row 232: activate stages: the pointer stays, AWAITING-UNITS names TO, a backup of the stopped store, no directory in the set, no --user, no journal (1777.227274ms)
|
||||
✔ row 232: A3 order: capture-failed and marker-failed refuse with exit 3 and leave no marker or FAILED (1712.692045ms)
|
||||
✔ row 232: confirm and revert refuse open-activation with no marker, two, the wrong copy, or one the log holds closed; refusals name no activation (3642.165244ms)
|
||||
✔ row 232: confirm polls: bus status good after 3 s fails with --timeout 1, writes FAILED and leaves the rest; FAILED then refuses activation-failed (3522.196896ms)
|
||||
✔ row 232: confirm polls to a pass with --timeout 10: the pointer, an ok line that reads as the started run, no marker (5641.501857ms)
|
||||
✔ row 232: stale-start: @1792540799 fails a start floor of 1792540800 with stale-start (3076.294408ms)
|
||||
✔ row 232: stale-start is a gate code: an enter time that turns to @1792540800 after 2 s passes with --timeout 10 (4471.752137ms)
|
||||
✔ row 232: gate (N2, A2f): --since 1792540800 passes @1792540800 and fails @1792540799; it writes nothing (2692.190142ms)
|
||||
✔ row 232: the external PM check reads launches list: one live run of launch.by since the start passes (9781.807961ms)
|
||||
✔ row 232: revert puts the wrapper back and leaves the store when nothing migrated (1409.775029ms)
|
||||
✔ row 232: confirm --rollback refuses rollback-mismatch, and logs rollback-failed with exit 2 when OLD fails its gate (3556.739549ms)
|
||||
✔ row 232: confirm --rollback after a --restore swap logs rollbackCode not-attempted; rollback --restore finds an external backup (3258.873111ms)
|
||||
✔ row 232: sequence 1: activate, confirm times out, revert, confirm --rollback --cause A5: gate-failed rollback ok (4878.560819ms)
|
||||
✔ row 232: sequence 2: activate --migrate, the wrapper install fails, revert restores TAKEN, confirm --rollback --cause A3 (3203.155908ms)
|
||||
✔ row 232: sequence 3: activate, root's A4 fails, revert, confirm --rollback --cause A4: failed code units-start (2844.170694ms)
|
||||
✔ row 232: sequence 4: a capture failure leaves nothing open, then A2f's gate OLD writes nothing (1940.493148ms)
|
||||
✔ row 232: sequence 5: a confirm of the wrong copy is refused, and revert and confirm --rollback still close the activation (3423.561744ms)
|
||||
✔ row 232: sequence 6: a revert that fails leaves the activation open, and the next --plan refuses interrupted-run (1732.106092ms)
|
||||
✔ row 232: sequence 7: adopt, two confirmed activates, rollback --to the previous copy, confirmed, logs op rollback (8298.40004ms)
|
||||
✔ row 232: sequence 8: a migration that writes and fails: revert restores the backup byte for byte, confirm --rollback --cause A3 (3658.849346ms)
|
||||
✔ row 232: user mode: every systemctl call carries --user, and activate, rollback and check make the base's calls (7450.661653ms)
|
||||
✔ row 232: user mode: a default activate --plan prints the base's bytes (2572.062595ms)
|
||||
ℹ tests 25
|
||||
ℹ suites 0
|
||||
ℹ pass 25
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 89317.249955
|
||||
+227
@@ -0,0 +1,227 @@
|
||||
✔ T1 adopt writes the pointer from the units once; a failing check refuses check-failed (1372.806902ms)
|
||||
✔ T2 activate installs exactly the pointer's pm, claude and Console flags (2175.278069ms)
|
||||
▶ T3 a hand-edited unit refuses unit-flags-drift, names the difference and changes nothing
|
||||
✔ pm (940.434448ms)
|
||||
✔ claude (905.331444ms)
|
||||
✔ console (953.801488ms)
|
||||
✔ T3 a hand-edited unit refuses unit-flags-drift, names the difference and changes nothing (2800.414725ms)
|
||||
▶ T4 each item 3 refusal changes nothing and logs one line with its code
|
||||
✔ copy-missing (828.258816ms)
|
||||
✔ copy-unreachable (750.040135ms)
|
||||
✔ copy-schema-unknown (804.784952ms)
|
||||
✔ already-active (767.83377ms)
|
||||
✔ instance-busy (another business active) (836.742584ms)
|
||||
✔ instance-busy (this business activating) (824.181046ms)
|
||||
✔ drop-in-override (819.802212ms)
|
||||
✔ no-pointer (432.597537ms)
|
||||
✔ T4 each item 3 refusal changes nothing and logs one line with its code (6065.707472ms)
|
||||
✔ T5 an activate with no migration stops the Console then the bus, installs, starts the bus then the Console (1974.205406ms)
|
||||
✔ T6 a migration without --migrate rolls back with migration-needs-flag (1689.71261ms)
|
||||
✔ T7 --migrate takes the backup before the migration runs (1874.080499ms)
|
||||
✔ T8 a failed migration restores the backup and keeps the store it replaced (1879.088438ms)
|
||||
✔ T9 a store outside the target's chain rolls back with store-newer (1695.743767ms)
|
||||
▶ T10 each gate check failing alone rolls back and puts every file back
|
||||
✔ units-inactive (5145.320966ms)
|
||||
✔ bus-status (5504.739824ms)
|
||||
✔ healthz (4630.494167ms)
|
||||
✔ copy-check (4953.814776ms)
|
||||
✔ pm-launch-unconfirmed (5175.714883ms)
|
||||
✔ T10 each gate check failing alone rolls back and puts every file back (25411.164743ms)
|
||||
▶ T10b the PM check needs exactly one launched line for a live run of this start
|
||||
✔ no launched line (5309.620588ms)
|
||||
✔ two lines (5271.450965ms)
|
||||
✔ a changed word (5207.189363ms)
|
||||
✔ run not in launches list (5249.94294ms)
|
||||
✔ run started before the start (5297.104798ms)
|
||||
✔ a human launch with no journal line (5012.384828ms)
|
||||
✔ run for another business (5255.258408ms)
|
||||
✔ run not live (5155.194619ms)
|
||||
✔ one well-formed line and a live run pass (1936.667118ms)
|
||||
✔ T10b the PM check needs exactly one launched line for a live run of this start (43696.539474ms)
|
||||
✔ T11 a rollback whose gate fails too: rollback-failed, exit 2, both units stopped, no retry (9445.48752ms)
|
||||
✔ T12 rollback takes the previous copy from the log (3164.86878ms)
|
||||
✔ T13 a rollback across a migration needs --restore, then restores and goes live (3832.433037ms)
|
||||
✔ T14 events written after the backup need --events N with the right N (4300.182861ms)
|
||||
✔ T14b a rollback --restore whose gate fails stops both units and skips item 6 (5706.078353ms)
|
||||
✔ T14c a rollback without --restore whose gate fails runs item 6 (7364.684709ms)
|
||||
✔ T15 --plan names the migration and the restore and changes nothing (2976.558ms)
|
||||
✔ T26 --plan lists the commits an activate adds, after the migration lines (1448.921448ms)
|
||||
✔ T27 --plan names each migration step, or says the steps cannot be read (1074.961775ms)
|
||||
✔ T25 --plan refuses copies-unrelated when neither copy is an ancestor of the other (504.611631ms)
|
||||
▶ T23 --plan reads the store without changing a file, stopped or held
|
||||
✔ stopped store (612.654192ms)
|
||||
✔ held store (615.45405ms)
|
||||
✔ T23 --plan reads the store without changing a file, stopped or held (1228.613968ms)
|
||||
✔ T24 business-mismatch and capture-failed refuse with exit 3; a short id is a usage error (1504.453363ms)
|
||||
✔ T16 status prints the pointer, the log, the check, bus status and drift, and writes nothing (969.540282ms)
|
||||
✔ T19 a started line with no final line: status shows it and every changing verb refuses (1272.112268ms)
|
||||
✔ T20 a held run lock refuses run-locked without a log line; status and --plan still run (1363.537596ms)
|
||||
✔ T21 a bus unit with no MOSAIC_CLAUDE_BIN: adopt and activate refuse no-claude-pin (1516.277233ms)
|
||||
▶ T22 the stopped store read: a -wal or -shm refuses store-unclean and is left alone; a clean read adds no file
|
||||
✔ bus.sqlite-wal (1776.498328ms)
|
||||
✔ bus.sqlite-shm (1805.948894ms)
|
||||
✔ clean (1860.970301ms)
|
||||
✔ T22 the stopped store read: a -wal or -shm refuses store-unclean and is left alone; a clean read adds no file (5444.145497ms)
|
||||
▶ T28 a unit path, drop-in directory or drop-in file that cannot be read, or a relative unit path, refuses drop-in-override before any stop
|
||||
✔ unit path (838.2428ms)
|
||||
✔ drop-in directory (770.669306ms)
|
||||
✔ drop-in file (787.861386ms)
|
||||
✔ relative unit path (799.918614ms)
|
||||
✔ T28 a unit path, drop-in directory or drop-in file that cannot be read, or a relative unit path, refuses drop-in-override before any stop (3197.49908ms)
|
||||
▶ T29 a bus that stops during the held-store read: --plan says so, rollback --restore refuses restore-mismatch
|
||||
✔ --plan (842.842612ms)
|
||||
✔ rollback --restore (2383.664939ms)
|
||||
✔ T29 a bus that stops during the held-store read: --plan says so, rollback --restore refuses restore-mismatch (3227.016275ms)
|
||||
✔ T30 a copy check that agrees on another copy fails the gate with copy-check and rolls back (4822.028878ms)
|
||||
▶ T31 a quoted or escaped Environment= or ExecStart= is unreadable: refusals by name, nothing read from /a
|
||||
✔ Environment double quotes (1747.115914ms)
|
||||
✔ Environment single quotes (1747.871141ms)
|
||||
✔ Environment backslash (1718.42505ms)
|
||||
✔ ExecStart quotes (1733.916441ms)
|
||||
✔ Console ExecStart quotes (1805.192313ms)
|
||||
✔ T31 a quoted or escaped Environment= or ExecStart= is unreadable: refusals by name, nothing read from /a (8753.514814ms)
|
||||
▶ T32 item 1: --pm-after-harness refuses a target without harness or a file that sets it, and passes without the PM
|
||||
✔ usage: not with --pm, and only for activate (630.81989ms)
|
||||
✔ pm-after-harness-target (949.989597ms)
|
||||
✔ pm-after-harness-set (1400.026643ms)
|
||||
✔ a pointer without pm (849.389257ms)
|
||||
✔ phase 1 installs without --pm, skips pm_launched and writes the pending pointer (2037.948918ms)
|
||||
✔ T32 item 1: --pm-after-harness refuses a target without harness or a file that sets it, and passes without the PM (5869.092521ms)
|
||||
▶ T33 item 2: read_pointer takes pmPending only as true beside pm false; a pending pointer refuses activate and shows in status
|
||||
✔ read_pointer (1646.25297ms)
|
||||
✔ pm-pending, already-adopted and the status line (2899.447167ms)
|
||||
✔ T33 item 2: read_pointer takes pmPending only as true beside pm false; a pending pointer refuses activate and shows in status (4546.229216ms)
|
||||
▶ T34 item 3: pm-on refuses before any stop, passes with the PM, or puts the phase-1 bus back
|
||||
✔ not-pending (781.816005ms)
|
||||
✔ harness-unset (2528.770078ms)
|
||||
✔ a launched line passes: the bus alone restarts with --pm (3635.97518ms)
|
||||
✔ a failed pm_launched puts the phase-1 unit back: exit 1, still pending (6129.763508ms)
|
||||
✔ a failed phase-1 gate too: pm-on-down, exit 2, both units stopped (10681.440065ms)
|
||||
✔ T34 item 3: pm-on refuses before any stop, passes with the PM, or puts the phase-1 bus back (23758.959718ms)
|
||||
▶ T35 item 4: rollback from pending installs --pm; a plug-in kind the target lacks refuses by name
|
||||
✔ rollback from pending gates pm_launched on the old copy (3432.493856ms)
|
||||
✔ after the harness set, rollback refuses until harness is gone (4814.40527ms)
|
||||
✔ activate names every kind the target lacks (1278.267995ms)
|
||||
✔ T35 item 4: rollback from pending installs --pm; a plug-in kind the target lacks refuses by name (9525.935986ms)
|
||||
✔ T36 --plan shows the pending state and lists the row 169 refusals it can see (3442.637109ms)
|
||||
✔ T37 tester-port activate writes pointer and unit, replaces the port, and supported re-pin and rollback keep it (6713.755862ms)
|
||||
✔ T38 tester-port rollback to unsupported target drops flag in plan, steps, unit and pointer (3556.909655ms)
|
||||
✔ T39 tester-port explicit unsupported target reads target copy and refuses before stopping either unit (816.518752ms)
|
||||
✔ T40 tester-port invalid values refuse exit 4 before stopping, including tunnel and main ports (798.151327ms)
|
||||
✔ T41 tester-port inherited activate to unsupported target drops it and retains drift refusal and failed-run recovery (8335.191178ms)
|
||||
✔ T42 tester-port pm-on preserves pointer Console flags (3045.995877ms)
|
||||
▶ T43 row 180 item 1: runs in one second get distinct activation ids, rollback sets and post-attempt stores
|
||||
✔ activate then pm-on on the same copy (3077.866023ms)
|
||||
✔ two restores: an old-form id and a suffixed one, each with its own post-attempt store (6478.022663ms)
|
||||
✔ adopt takes the next free id too (676.463788ms)
|
||||
✔ all ten names taken: capture-failed before anything stops, and the log line names no activation (927.509173ms)
|
||||
✔ --restore takes an id with or without -1 to -9 and nothing else (1026.017549ms)
|
||||
✔ T43 row 180 item 1: runs in one second get distinct activation ids, rollback sets and post-attempt stores (12186.978758ms)
|
||||
▶ T44 row 180 item 2: --plan lists tester-port-invalid and tester-port-target with its other refusals
|
||||
✔ a bad tester port (2101.036117ms)
|
||||
✔ without --plan a bad port is usage before any pointer read (417.577025ms)
|
||||
✔ a target Console without --tester-port (1050.997021ms)
|
||||
✔ T44 row 180 item 2: --plan lists tester-port-invalid and tester-port-target with its other refusals (3570.568101ms)
|
||||
▶ T45 row 181 items 2 and 3: the restore guard counts events and every COUNTED table
|
||||
✔ both modes count events and each listed table, and a table the store lacks counts 0 (819.811738ms)
|
||||
✔ one instance_names row and no event refuses before any stop; --events 1 restores (4281.220981ms)
|
||||
✔ one usage_records row and no event refuses before any stop; --events 1 restores (4339.553222ms)
|
||||
✔ a listed table that cannot be read refuses restore-mismatch before any stop (3011.194623ms)
|
||||
✔ the in-run recount counts the listed tables too (3456.814799ms)
|
||||
✔ T45 row 181 items 2 and 3: the restore guard counts events and every COUNTED table (15910.111456ms)
|
||||
✔ T46 row 181 item 4: every table in the bus schema is in exactly one of four lists (2.96277ms)
|
||||
✔ T47 row 185 test 1: a same-schema activate leaves a whole backup and the log line names it (1839.922479ms)
|
||||
✔ T48 row 185 test 2: a gate failure on a same-schema activate rolls back without a restore (5782.007105ms)
|
||||
▶ T49 row 185 test 3: a same-schema rollback --restore restores, or refuses rows written after STAMP
|
||||
✔ no rows after STAMP: restores and goes live (3276.614244ms)
|
||||
✔ one instance_names row after STAMP refuses post-backup-events; --events 1 restores (3603.193575ms)
|
||||
✔ T49 row 185 test 3: a same-schema rollback --restore restores, or refuses rows written after STAMP (6880.328466ms)
|
||||
✔ T50 row 185 test 4: activate --plan prints the backup line and writes nothing (2392.362463ms)
|
||||
✔ T51 row 185 test 5: an activate with no store file takes no backup (2055.74343ms)
|
||||
▶ T52 row 186: the activate plan's backup line says what the run will do
|
||||
✔ same schema (2076.652498ms)
|
||||
✔ same schema with --migrate (2103.728264ms)
|
||||
✔ in chain with --migrate (2343.740358ms)
|
||||
✔ in chain without --migrate (2172.44891ms)
|
||||
✔ outside the chain (2018.610199ms)
|
||||
✔ outside the chain with --migrate (2286.782735ms)
|
||||
✔ T52 row 186: the activate plan's backup line says what the run will do (13003.221353ms)
|
||||
✔ T178 proxy proof header and path survive re-pin and rollback unchanged in the pointer and unit (3428.609169ms)
|
||||
✔ T178 proxy proof pair survives a tester-port replacement as well (2005.665148ms)
|
||||
▶ T53 row 187: activate sets, carries and drops the proof pair
|
||||
✔ tests 1 and 9: the pair goes after the preview flags, before --send and the kept --tester-port, as the unit renders it; a new pair replaces it (5369.617405ms)
|
||||
✔ tests 2 and 3: an activate of the live copy writes the pair; a later activate and a rollback carry it (4877.926077ms)
|
||||
✔ test 2: only a pair change may name the live copy; the log keeps from and to, and rollback still goes to the earlier copy (6411.791056ms)
|
||||
✔ test 2: a live-copy activate says only the Console flags change, and backs up the stopped store before it installs (3823.440479ms)
|
||||
✔ test 3: pm-on keeps the pair (2929.528358ms)
|
||||
✔ test 4: --no-proof drops the pair from the pointer and the unit and says so; with no pair it says so and passes (6134.571168ms)
|
||||
✔ test 5: each refusal exits 3 before anything stops (4080.818538ms)
|
||||
✔ tests 5 and 9: --plan lists every proof refusal with the others and writes nothing (921.495619ms)
|
||||
✔ test 6: usage errors (791.940368ms)
|
||||
✔ test 7: a rollback to a copy without proof support drops the pair and says so (3569.742095ms)
|
||||
✔ test 7: an activate to a copy without proof support refuses proof-target without --no-proof and passes with it (4102.029003ms)
|
||||
✔ T53 row 187: activate sets, carries and drops the proof pair (43015.196531ms)
|
||||
▶ T54 row 188: a carried pair gets the proof file checks, and a proof file inside the repository refuses
|
||||
✔ test 1: an activate that carries the pair refuses after chmod 644, in the plan and the run, before anything stops (2443.927487ms)
|
||||
✔ test 1: an activate that carries the pair refuses after a symlink to a mode-600 file, in the plan and the run, before anything stops (2451.543098ms)
|
||||
✔ test 1: an activate that carries the pair refuses after removal, in the plan and the run, before anything stops (2371.886229ms)
|
||||
✔ test 2: a rollback that carries the pair refuses after chmod 644, in the plan and the run, before anything stops (2440.808004ms)
|
||||
✔ test 3: a proof file inside the repository refuses, in the plan and the run, before anything stops (1028.022624ms)
|
||||
✔ test 4: a path outside the repository through a directory symlink into it refuses on its realpath (1092.396277ms)
|
||||
✔ T54 row 188: a carried pair gets the proof file checks, and a proof file inside the repository refuses (11829.775747ms)
|
||||
▶ T55 row 189: activate --no-send drops --send, and rollback and pm-on carry it off
|
||||
✔ test 1: a live-copy --no-send drops --send from the pointer and the unit, keeps the rest in order, logs the step and backs up the stopped store (2297.315751ms)
|
||||
✔ test 2: a plain live-copy activate still refuses already-active, and so does --no-send once --send is gone (3372.219555ms)
|
||||
✔ test 3: --plan prints one send: line in each case, with the live-copy note on a same-copy run (4822.032599ms)
|
||||
✔ test 4: after --no-send, a rollback to the earlier copy leaves --send out of the pointer and the unit (3681.502406ms)
|
||||
✔ test 4: pm-on after --no-send keeps --send off (3384.224907ms)
|
||||
✔ test 5: --no-send on rollback, pm-on, status, adopt or rehearse is a usage error (646.332677ms)
|
||||
✔ test 6: with both a pair and --send in the pointer, --no-send and --no-proof each drop what they name and keep the rest (10576.556687ms)
|
||||
✔ T55 row 189: activate --no-send drops --send, and rollback and pm-on carry it off (28781.800109ms)
|
||||
▶ T57 row 200: activate --sso, its refusals before any stop, and the rollback to a Console without --sso
|
||||
✔ item 1: --sso drops the preview set and the pair, puts --sso before --send and the tester port, and the plan names what it drops and carries (3731.038851ms)
|
||||
✔ item 1: --sso may re-pin the live copy once; later activates carry it; --no-send still drops --send (9441.965146ms)
|
||||
✔ item 1: --sso with a pair or --no-proof, or on any verb but activate, is a usage error (804.681755ms)
|
||||
✔ item 2: a target without --sso, a missing or bad console.sso, and each slot problem refuse before any stop (6340.571003ms)
|
||||
✔ item 3: a config whose console key the target loader refuses stops an activate or a rollback before any stop, naming the first step (4474.330517ms)
|
||||
✔ item 3: a rollback from --sso to a Console without it takes the flags from the set of the activation onto the copy, past a same-copy re-pin (sage-1389) (11258.382547ms)
|
||||
✔ item 3: a rollback set that is missing, fails its sums, holds no argv or already ran --sso refuses sso-rollback-flags (4811.481384ms)
|
||||
✔ round 2 (webby-0028 N1): run through a symlinked repository path, a slot or a proof file inside the repository still refuses (2548.588058ms)
|
||||
✔ round 2 (webby-0028 N2): a config.json that does not parse stops the run before anything is read or stopped (2148.082108ms)
|
||||
✔ round 3 (sage-1556): a named instance turns --sso on with its own config, slot and Console unit, and rolls back from its own set (4427.346674ms)
|
||||
✔ row 238 (#1744): on a named instance the sso-config first step names --instance NAME in both commands (1072.216503ms)
|
||||
✔ T57 row 200: activate --sso, its refusals before any stop, and the rollback to a Console without --sso (51060.894572ms)
|
||||
✔ R1 rehearse passes on the same schema; the scratch root holds its files and the live files stay byte-identical (3501.665564ms)
|
||||
✔ R2 rehearse runs the migration checks when the schema differs; the live store stays at 3g (2615.765886ms)
|
||||
✔ R3 a failing migration gives REHEARSAL_FAIL migrate and starts nothing (406.432761ms)
|
||||
✔ R4 a host that does not start, does not answer status, reports another pid, launches anyway, makes a launches directory or keeps its lock each fails by name (23643.921414ms)
|
||||
✔ R5 a host that ignores SIGTERM gets SIGKILL and FAIL host-stopped (4522.753011ms)
|
||||
✔ R6 a Console that does not answer /healthz gives REHEARSAL_FAIL healthz (5695.642056ms)
|
||||
✔ R7 a host on another copy fails copy-match (5707.109175ms)
|
||||
✔ R8 a scratch port in use or reserved refuses, and the rehearsal takes no other port (564.078959ms)
|
||||
✔ R9 mos-0963: a role reference left outside placeholders/, or left on an env variable, fails credential-ref-live before the host starts (739.463019ms)
|
||||
✔ R10 mos-0962: a scratch business that still sets a tracker fails tracker-configured (356.527698ms)
|
||||
✔ R11 mos-0961: a scratch config on the live data root or on any root but the scratch one, or a sessions.json naming a running pid, refuses by name (1415.617777ms)
|
||||
✔ R12 mos-0962: a notifier config with a binding fails notify-off (346.615997ms)
|
||||
✔ R13 the pre-checks: an old copy, a backup that fails its sums, a missing backup or pointer, and usage (495.179039ms)
|
||||
✔ R14 a host that writes the live config, the live business file or the backup fails the end check by name (10325.286968ms)
|
||||
✔ R15 a rehearsal stopped by TERM, INT or HUP fails signal and still stops the host and Console and runs the end checks (9991.220342ms)
|
||||
✔ row 233: --backup last takes the newest backup the log records; a later line with backup null does not hide it, and the store line names it (3454.052038ms)
|
||||
✔ row 233: --backup last with no backup in the log, or no log, exits 3 with no-backup and makes no rehearsal directory (203.934243ms)
|
||||
✔ row 233: --backup last refuses a newest backup that is not an activation id, with exit 1 (127.433768ms)
|
||||
▶ T56 row 190: named instances side by side on one unit directory, $BIN and set of stand-ins
|
||||
✔ T-I3 each instance renders its own config, session env and Description, and nothing of another (1595.173571ms)
|
||||
✔ T-I4 a Console port another installed Console takes refuses port-claimed, and a named instance keeps off the default ports (1992.011586ms)
|
||||
✔ T-I6 alpha's activate and rollback reach nothing of beta's (3927.69359ms)
|
||||
✔ T-I6 swapped: beta's reach nothing of alpha's (4046.222781ms)
|
||||
✔ T-I7 MOSAIC_CONFIG naming alpha's config with no flag refuses instance-root-mismatch and changes nothing (707.673985ms)
|
||||
✔ T-I9 another instance's bus active refuses nothing; one of this instance's does (6093.674502ms)
|
||||
✔ T56 row 190: named instances side by side on one unit directory, $BIN and set of stand-ins (18364.096442ms)
|
||||
ℹ tests 196
|
||||
ℹ suites 0
|
||||
ℹ pass 196
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 530980.947325
|
||||
@@ -0,0 +1 @@
|
||||
{"processes": [], "removed": "/mnt/storage/scratch/gt-t2e8hpyu", "trees": ["/home/jwoltje/.t3/worktrees/mosaic-stack/herb-row215-on212", "/home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197-r8"]}
|
||||
@@ -0,0 +1 @@
|
||||
{"pid": 765123, "reason": "sage-1983 stop after file10; do not start file11"}
|
||||
@@ -0,0 +1,122 @@
|
||||
[
|
||||
{
|
||||
"file": "packages/bus/tests/library.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 6,
|
||||
"pass": 6,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "01-packages_bus_tests_library.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/bus/tests/project-runtime.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 3,
|
||||
"pass": 3,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "02-packages_bus_tests_project-runtime.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/business/tests/business.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 18,
|
||||
"pass": 18,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "03-packages_business_tests_business.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/business/tests/cli.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 10,
|
||||
"pass": 10,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "04-packages_business_tests_cli.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/business/tests/instance-settings.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 12,
|
||||
"pass": 12,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "05-packages_business_tests_instance-settings.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/business/tests/library-projects-protected.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 4,
|
||||
"pass": 4,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "06-packages_business_tests_library-projects-protected.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/business/tests/resolve.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 11,
|
||||
"pass": 11,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "07-packages_business_tests_resolve.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/launcher.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 30,
|
||||
"pass": 30,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "08-packages_cli_tests_launcher.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release-external.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 25,
|
||||
"pass": 25,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "09-packages_cli_tests_stack-release-external.test.mjs.log"
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"rc": 0,
|
||||
"counts": {
|
||||
"tests": 196,
|
||||
"pass": 196,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"log": "10-packages_cli_tests_stack-release.test.mjs.log"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1 @@
|
||||
/mnt/storage/scratch/gt-t2e8hpyu
|
||||
@@ -0,0 +1 @@
|
||||
2026-10-21T11:56:56.177608+00:00
|
||||
@@ -0,0 +1,10 @@
|
||||
✔ C2-04: library mappings load without roots, remain frozen, and retain mapping refusals (9.004507ms)
|
||||
✔ C2-04: an otherwise valid publish grant cannot name a library repo (1.807264ms)
|
||||
ℹ tests 2
|
||||
ℹ suites 0
|
||||
ℹ pass 2
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 67.488189
|
||||
@@ -0,0 +1,23 @@
|
||||
✖ C2-04: library mappings load without roots, remain frozen, and retain mapping refusals (5.192384ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 0
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 54.487487
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/business.test.mjs:11:1
|
||||
✖ C2-04: library mappings load without roots, remain frozen, and retain mapping refusals (5.192384ms)
|
||||
Error [BusinessError]: unsupported /mnt/storage/scratch/gt-PvGtsQ/mosaic-business-4vAhxB/businesses/acme.json projects.books key: "kind"
|
||||
at refuse (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/business/src/errors.mjs:12:9)
|
||||
at rejectUnknownKeys (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/business/src/util.mjs:17:33)
|
||||
at validateBusinessDocument (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/business/src/business.mjs:232:5)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/business/tests/business.test.mjs:17:18)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||
exitCode: 2
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
✔ C2-04: ensureCheckouts skips a library before a real clone and leaves no books path (24.411494ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 1
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 72.211367
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"at": "2026-10-21T08:51:07Z",
|
||||
"tempRoot": "/mnt/storage/scratch/gt-PvGtsQ",
|
||||
"fixtureCwdOrArgv": [],
|
||||
"testProcesses": [],
|
||||
"excluded": "current scan process and its ancestors",
|
||||
"tempRootRemoved": true
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
✔ C2-04: business validate and resolve skip a library before code projects and credential checks (206.597157ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 1
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 260.97412
|
||||
@@ -0,0 +1,9 @@
|
||||
✔ C2-04: instance settings skip a library while checking a later code project (22.656666ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 1
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 79.494698
|
||||
@@ -0,0 +1,9 @@
|
||||
✔ C2-04: launcher workspace clones code but never the library (1241.43402ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 1
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 1338.915726
|
||||
@@ -0,0 +1,12 @@
|
||||
✔ C2-04 M9: changed playground and hybrid entries leave business and changes.jsonl byte-identical (21.916712ms)
|
||||
✔ C2-04 M9: code projects, additions, deletions and array changes are protected too (17.081275ms)
|
||||
✔ C2-04 M9: canonical key order is allowed and a non-project setter still records its change (14.304068ms)
|
||||
✔ C2-04 M9: a serialization hook cannot change projects after the canonical comparison (9.595281ms)
|
||||
ℹ tests 4
|
||||
ℹ suites 0
|
||||
ℹ pass 4
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 116.250811
|
||||
@@ -0,0 +1,28 @@
|
||||
✖ C2-04 M9: changed playground and hybrid entries leave business and changes.jsonl byte-identical (21.728048ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 0
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 71.097427
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/library-projects-protected.test.mjs:35:1
|
||||
✖ C2-04 M9: changed playground and hybrid entries leave business and changes.jsonl byte-identical (21.728048ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||
at protectedWrite (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/business/tests/library-projects-protected.test.mjs:29:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/business/tests/library-projects-protected.test.mjs:37:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
expected: { code: 'organization-projects-protected' },
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
✔ C2-04: record APIs refuse a library before creating a repository (3.426617ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 1
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 61.266328
|
||||
@@ -0,0 +1,9 @@
|
||||
✔ C2-04: a library first in projects does not hide a later project layer (6.517821ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 1
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 62.270511
|
||||
@@ -0,0 +1,90 @@
|
||||
[
|
||||
{
|
||||
"file": "business-green.log",
|
||||
"tests": 2,
|
||||
"pass": 2,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
{
|
||||
"file": "business-red.log",
|
||||
"tests": 1,
|
||||
"pass": 0,
|
||||
"fail": 1,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
{
|
||||
"file": "checkout-green.log",
|
||||
"tests": 1,
|
||||
"pass": 1,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
{
|
||||
"file": "cli-green.log",
|
||||
"tests": 1,
|
||||
"pass": 1,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
{
|
||||
"file": "instance-settings-green.log",
|
||||
"tests": 1,
|
||||
"pass": 1,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
{
|
||||
"file": "launcher-green.log",
|
||||
"tests": 1,
|
||||
"pass": 1,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
{
|
||||
"file": "m9-green.log",
|
||||
"tests": 4,
|
||||
"pass": 4,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
{
|
||||
"file": "m9-red.log",
|
||||
"tests": 1,
|
||||
"pass": 0,
|
||||
"fail": 1,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
{
|
||||
"file": "project-green.log",
|
||||
"tests": 1,
|
||||
"pass": 1,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
{
|
||||
"file": "resolve-green.log",
|
||||
"tests": 1,
|
||||
"pass": 1,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
{
|
||||
"file": "trackers-boot-green.log",
|
||||
"tests": 2,
|
||||
"pass": 2,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1 @@
|
||||
2026-10-21T08:48:14Z
|
||||
@@ -0,0 +1 @@
|
||||
/mnt/storage/scratch/gt-PvGtsQ
|
||||
@@ -0,0 +1,12 @@
|
||||
✔ C2-04: a library-only business with tracker.baseUrl boots without a project tracker (132.133246ms)
|
||||
task.close {} answered: invalid-request; fake saw 18 requests, first GET /info 200, GET /projects/1 200, GET /projects/1/views 200
|
||||
task.close on a missing task answered: task-not-found; it made GET /tasks/999 404
|
||||
✔ bootConfig trackers reach the S3 adapter in the real broker child, which goes ready against a fake Vikunja (261.808635ms)
|
||||
ℹ tests 2
|
||||
ℹ suites 0
|
||||
ℹ pass 2
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 480.083569
|
||||
@@ -0,0 +1 @@
|
||||
{"processes": [], "removed": "/mnt/storage/scratch/gt-iwfcrf5s"}
|
||||
@@ -0,0 +1 @@
|
||||
["packages/library/tests/mirror.test.mjs", "packages/bus/tests/library.test.mjs", "packages/webui/tests/library-cli.test.mjs", "packages/bus/tests/project-runtime.test.mjs"]
|
||||
@@ -0,0 +1,31 @@
|
||||
✖ C2-04 CLI: both listener callback pairs dispatch library verbs with their own transport (140.263767ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 0
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 244.49705
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/webui/tests/library-cli.test.mjs:10:1
|
||||
✖ C2-04 CLI: both listener callback pairs dispatch library verbs with their own transport (140.263767ms)
|
||||
AssertionError [ERR_ASSERTION]: refused: missing library callbacks
|
||||
|
||||
|
||||
2 !== 0
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/webui/tests/library-cli.test.mjs:27:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 2,
|
||||
expected: 0,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
✖ C2-04 CLI: both listener callback pairs dispatch library verbs with their own transport (31.496523ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 0
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 122.065824
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/webui/tests/library-cli.test.mjs:10:1
|
||||
✖ C2-04 CLI: both listener callback pairs dispatch library verbs with their own transport (31.496523ms)
|
||||
AssertionError [ERR_ASSERTION]: file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/webui/src/bus.mjs:1
|
||||
import {appendFileSync} from 'node:fs';export class BusReadError extends Error{};export const busCaller=o=>async(verb,args)=>{appendFileSync("/mnt/storage/scratch/gt-iwfcrf5s/library-cli-1eUPUX/calls.jsonl",JSON.stringify({verb,args,cli:o.cli??"/mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/human-cli.mjs"})+'
|
||||
^
|
||||
|
||||
SyntaxError: Invalid or unexpected token
|
||||
at compileSourceTextModule (node:internal/modules/esm/utils:355:16)
|
||||
at ModuleLoader.moduleStrategy (node:internal/modules/esm/translators:93:18)
|
||||
at #translate (node:internal/modules/esm/loader:441:20)
|
||||
at afterLoad (node:internal/modules/esm/loader:509:29)
|
||||
at ModuleLoader.loadAndTranslate (node:internal/modules/esm/loader:514:12)
|
||||
at #getOrCreateModuleJobAfterResolve (node:internal/modules/esm/loader:567:36)
|
||||
at afterResolve (node:internal/modules/esm/loader:614:52)
|
||||
at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:620:12)
|
||||
at ModuleJob.syncLink (node:internal/modules/esm/module_job:277:33)
|
||||
at ModuleJob.link (node:internal/modules/esm/module_job:389:17)
|
||||
|
||||
Node.js v26.8.1
|
||||
|
||||
|
||||
1 !== 0
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/webui/tests/library-cli.test.mjs:27:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 1,
|
||||
expected: 0,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
✔ C2-04 CLI: both listener callback pairs dispatch library verbs with their own transport (110.620217ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 1
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 194.067409
|
||||
@@ -0,0 +1,9 @@
|
||||
✔ C2-04 CLI: both listener callback pairs dispatch library verbs with their own transport (107.138425ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 1
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 193.527058
|
||||
@@ -0,0 +1,71 @@
|
||||
✖ C2-04 M4: both verbs reject every agent before arguments or adapter access (14.387463ms)
|
||||
✖ C2-04 bus: human reads validate keys and return adapter results without path leakage (8.808227ms)
|
||||
✖ C2-04 socket: each async library verb resolves its result rather than serializing {} (15.107055ms)
|
||||
ℹ tests 3
|
||||
ℹ suites 0
|
||||
ℹ pass 0
|
||||
ℹ fail 3
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 125.805576
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/bus/tests/library.test.mjs:28:1
|
||||
✖ C2-04 M4: both verbs reject every agent before arguments or adapter access (14.387463ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
Comparison {
|
||||
+ code: 'unknown-verb'
|
||||
- code: 'human-required'
|
||||
}
|
||||
|
||||
at async TestContext.<anonymous> (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/tests/library.test.mjs:32:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: Error: unknown-verb
|
||||
at fail (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:145:9)
|
||||
at #dispatch (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:3098:9)
|
||||
at file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:1810:38
|
||||
at Store.transaction (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/store.mjs:263:22)
|
||||
at Broker.request (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:1801:26)
|
||||
at file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/tests/library.test.mjs:24:78
|
||||
at async waitForActual (node:assert:615:5)
|
||||
at async strict.rejects (node:assert:738:25)
|
||||
at async TestContext.<anonymous> (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/tests/library.test.mjs:32:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7),
|
||||
expected: { code: 'human-required' },
|
||||
operator: 'rejects',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/bus/tests/library.test.mjs:45:1
|
||||
✖ C2-04 bus: human reads validate keys and return adapter results without path leakage (8.808227ms)
|
||||
Error: unknown-verb
|
||||
at fail (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:145:9)
|
||||
at #dispatch (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:3098:9)
|
||||
at file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:1810:38
|
||||
at Store.transaction (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/store.mjs:263:22)
|
||||
at Broker.request (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:1801:26)
|
||||
at file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/tests/library.test.mjs:24:78
|
||||
at async TestContext.<anonymous> (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/tests/library.test.mjs:49:17)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
code: 'unknown-verb'
|
||||
}
|
||||
|
||||
test at packages/bus/tests/library.test.mjs:56:1
|
||||
✖ C2-04 socket: each async library verb resolves its result rather than serializing {} (15.107055ms)
|
||||
Error: unknown-verb
|
||||
at Socket.<anonymous> (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/client.mjs:42:17)
|
||||
at Socket.emit (node:events:514:20)
|
||||
at addChunk (node:internal/streams/readable:575:12)
|
||||
at readableAddChunkPushByteMode (node:internal/streams/readable:526:3)
|
||||
at Readable.push (node:internal/streams/readable:406:5)
|
||||
at Pipe.onStreamRead (node:internal/stream_base_commons:189:23) {
|
||||
code: 'unknown-verb'
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
✖ C2-04 M4: both verbs reject every agent before arguments or adapter access (16.66162ms)
|
||||
✖ C2-04 bus: human reads validate keys and return adapter results without path leakage (9.880605ms)
|
||||
✖ C2-04 socket: each async library verb resolves its result rather than serializing {} (17.417761ms)
|
||||
✖ C2-04 runtime: protectedRoots skips library but retains real code-root credential protection (27.11473ms)
|
||||
✖ C2-04 runtime: unsafe existing mirror refuses boot and never publishes a socket (21.990752ms)
|
||||
✖ C2-04 runtime: real library adapters reach the socket and lock waits leave other bus reads responsive (21.295513ms)
|
||||
|
||||
Interrupted while running:
|
||||
|
||||
⚠ packages/bus/tests/library.test.mjs (packages/bus/tests/library.test.mjs:1:1)
|
||||
✖ packages/bus/tests/library.test.mjs (34335.85978ms)
|
||||
ℹ tests 7
|
||||
ℹ suites 0
|
||||
ℹ pass 0
|
||||
ℹ fail 6
|
||||
ℹ cancelled 1
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 34341.308382
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/bus/tests/library.test.mjs:28:1
|
||||
✖ C2-04 M4: both verbs reject every agent before arguments or adapter access (16.66162ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
Comparison {
|
||||
+ code: 'unknown-verb'
|
||||
- code: 'human-required'
|
||||
}
|
||||
|
||||
at async TestContext.<anonymous> (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/tests/library.test.mjs:32:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: Error: unknown-verb
|
||||
at fail (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:145:9)
|
||||
at #dispatch (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:3098:9)
|
||||
at file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:1810:38
|
||||
at Store.transaction (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/store.mjs:263:22)
|
||||
at Broker.request (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:1801:26)
|
||||
at file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/tests/library.test.mjs:24:78
|
||||
at async waitForActual (node:assert:615:5)
|
||||
at async strict.rejects (node:assert:738:25)
|
||||
at async TestContext.<anonymous> (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/tests/library.test.mjs:32:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7),
|
||||
expected: { code: 'human-required' },
|
||||
operator: 'rejects',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/bus/tests/library.test.mjs:45:1
|
||||
✖ C2-04 bus: human reads validate keys and return adapter results without path leakage (9.880605ms)
|
||||
Error: unknown-verb
|
||||
at fail (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:145:9)
|
||||
at #dispatch (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:3098:9)
|
||||
at file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:1810:38
|
||||
at Store.transaction (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/store.mjs:263:22)
|
||||
at Broker.request (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:1801:26)
|
||||
at file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/tests/library.test.mjs:24:78
|
||||
at async TestContext.<anonymous> (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/tests/library.test.mjs:49:17)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
code: 'unknown-verb'
|
||||
}
|
||||
|
||||
test at packages/bus/tests/library.test.mjs:56:1
|
||||
✖ C2-04 socket: each async library verb resolves its result rather than serializing {} (17.417761ms)
|
||||
Error: unknown-verb
|
||||
at Socket.<anonymous> (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/client.mjs:42:17)
|
||||
at Socket.emit (node:events:514:20)
|
||||
at addChunk (node:internal/streams/readable:575:12)
|
||||
at readableAddChunkPushByteMode (node:internal/streams/readable:526:3)
|
||||
at Readable.push (node:internal/streams/readable:406:5)
|
||||
at Pipe.onStreamRead (node:internal/stream_base_commons:189:23) {
|
||||
code: 'unknown-verb'
|
||||
}
|
||||
|
||||
test at packages/bus/tests/library.test.mjs:67:1
|
||||
✖ C2-04 runtime: protectedRoots skips library but retains real code-root credential protection (27.11473ms)
|
||||
TypeError: library.mirrorPath is not a function
|
||||
at TestContext.<anonymous> (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/tests/library.test.mjs:74:26)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
|
||||
|
||||
test at packages/bus/tests/library.test.mjs:81:1
|
||||
✖ C2-04 runtime: unsafe existing mirror refuses boot and never publishes a socket (21.990752ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected rejection.
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async TestContext.<anonymous> (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/tests/library.test.mjs:87:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
expected: { code: 'library-git' },
|
||||
operator: 'rejects',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/bus/tests/library.test.mjs:92:1
|
||||
✖ C2-04 runtime: real library adapters reach the socket and lock waits leave other bus reads responsive (21.295513ms)
|
||||
Error: unknown-verb
|
||||
at Socket.<anonymous> (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/client.mjs:42:17)
|
||||
at Socket.emit (node:events:514:20)
|
||||
at addChunk (node:internal/streams/readable:575:12)
|
||||
at readableAddChunkPushByteMode (node:internal/streams/readable:526:3)
|
||||
at Readable.push (node:internal/streams/readable:406:5)
|
||||
at Pipe.onStreamRead (node:internal/stream_base_commons:189:23) {
|
||||
code: 'unknown-verb'
|
||||
}
|
||||
|
||||
test at packages/bus/tests/library.test.mjs:1:1
|
||||
✖ packages/bus/tests/library.test.mjs (34335.85978ms)
|
||||
'Promise resolution is still pending but the event loop has already resolved'
|
||||
@@ -0,0 +1,126 @@
|
||||
✖ C2-04 M4: both verbs reject every agent before arguments or adapter access (24.976387ms)
|
||||
✖ C2-04 bus: human reads validate keys and return adapter results without path leakage (7.097425ms)
|
||||
✖ C2-04 socket: each async library verb resolves its result rather than serializing {} (6.894431ms)
|
||||
✖ C2-04 runtime: protectedRoots skips library but retains real code-root credential protection (34.318499ms)
|
||||
✖ C2-04 runtime: unsafe existing mirror refuses boot and never publishes a socket (21.188728ms)
|
||||
✖ C2-04 runtime: real library adapters reach the socket and lock waits leave other bus reads responsive (11.406264ms)
|
||||
ℹ tests 6
|
||||
ℹ suites 0
|
||||
ℹ pass 0
|
||||
ℹ fail 6
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 197.495962
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/bus/tests/library.test.mjs:28:1
|
||||
✖ C2-04 M4: both verbs reject every agent before arguments or adapter access (24.976387ms)
|
||||
Error: invalid-business
|
||||
at fail (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:145:9)
|
||||
at new Broker (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:322:9)
|
||||
at world (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/tests/library.test.mjs:20:18)
|
||||
at TestContext.<anonymous> (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/tests/library.test.mjs:30:13)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
code: 'invalid-business'
|
||||
}
|
||||
|
||||
test at packages/bus/tests/library.test.mjs:45:1
|
||||
✖ C2-04 bus: human reads validate keys and return adapter results without path leakage (7.097425ms)
|
||||
Error: invalid-business
|
||||
at fail (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:145:9)
|
||||
at new Broker (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:322:9)
|
||||
at world (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/tests/library.test.mjs:20:18)
|
||||
at TestContext.<anonymous> (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/tests/library.test.mjs:47:13)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||
code: 'invalid-business'
|
||||
}
|
||||
|
||||
test at packages/bus/tests/library.test.mjs:56:1
|
||||
✖ C2-04 socket: each async library verb resolves its result rather than serializing {} (6.894431ms)
|
||||
Error: invalid-business
|
||||
at fail (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:145:9)
|
||||
at new Broker (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:322:9)
|
||||
at world (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/tests/library.test.mjs:20:18)
|
||||
at TestContext.<anonymous> (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/tests/library.test.mjs:57:13)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
code: 'invalid-business'
|
||||
}
|
||||
|
||||
test at packages/bus/tests/library.test.mjs:67:1
|
||||
✖ C2-04 runtime: protectedRoots skips library but retains real code-root credential protection (34.318499ms)
|
||||
Error: credential-format
|
||||
at deny (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/credentials.mjs:10:9)
|
||||
at #format (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/credentials.mjs:232:28)
|
||||
at #read (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/credentials.mjs:222:37)
|
||||
at new Credentials (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/credentials.mjs:145:35)
|
||||
at startBroker (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/runtime.mjs:108:19)
|
||||
at TestContext.<anonymous> (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/tests/library.test.mjs:72:25)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19) {
|
||||
code: 'credential-format'
|
||||
}
|
||||
|
||||
test at packages/bus/tests/library.test.mjs:81:1
|
||||
✖ C2-04 runtime: unsafe existing mirror refuses boot and never publishes a socket (21.188728ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
Comparison {
|
||||
+ code: 'invalid-business'
|
||||
- code: 'library-git'
|
||||
}
|
||||
|
||||
at async TestContext.<anonymous> (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/tests/library.test.mjs:86:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: Error: invalid-business
|
||||
at fail (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:145:9)
|
||||
at new Broker (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/broker.mjs:322:9)
|
||||
at startBroker (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/runtime.mjs:126:20)
|
||||
at async waitForActual (node:assert:615:5)
|
||||
at async strict.rejects (node:assert:738:25)
|
||||
at async TestContext.<anonymous> (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/tests/library.test.mjs:86:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7),
|
||||
expected: { code: 'library-git' },
|
||||
operator: 'rejects',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/bus/tests/library.test.mjs:91:1
|
||||
✖ C2-04 runtime: real library adapters reach the socket and lock waits leave other bus reads responsive (11.406264ms)
|
||||
Error: ENOENT: no such file or directory, lstat '/mnt/storage/scratch/gt-iwfcrf5s/library-m65UFF/data'
|
||||
at lstatSync (node:fs:2138:25)
|
||||
at new Store (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/store.mjs:137:22)
|
||||
at startBroker (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/src/runtime.mjs:99:13)
|
||||
at TestContext.<anonymous> (file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/bus/tests/library.test.mjs:94:25)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
errno: -2,
|
||||
code: 'ENOENT',
|
||||
syscall: 'lstat',
|
||||
path: '/mnt/storage/scratch/gt-iwfcrf5s/library-m65UFF/data'
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
✔ C2-04 M4: both verbs reject every agent before arguments or adapter access (28.309128ms)
|
||||
✔ C2-04 bus: human reads validate keys and return adapter results without path leakage (11.198339ms)
|
||||
✔ C2-04 socket: each async library verb resolves its result rather than serializing {} (14.717312ms)
|
||||
✔ C2-04 runtime: protectedRoots skips library but retains real code-root credential protection (42.066656ms)
|
||||
✔ C2-04 runtime: unsafe existing mirror refuses boot and never publishes a socket (23.773967ms)
|
||||
✔ C2-04 runtime: real library adapters reach the socket and lock waits leave other bus reads responsive (89.925539ms)
|
||||
ℹ tests 6
|
||||
ℹ suites 0
|
||||
ℹ pass 6
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 301.460553
|
||||
@@ -0,0 +1,63 @@
|
||||
✔ C2-04 M4: both verbs reject every agent before arguments or adapter access (27.706148ms)
|
||||
✔ C2-04 bus: human reads validate keys and return adapter results without path leakage (10.128912ms)
|
||||
✖ C2-04 socket: each async library verb resolves its result rather than serializing {} (14.255977ms)
|
||||
✖ C2-04 runtime: protectedRoots skips library but retains real code-root credential protection (20.969978ms)
|
||||
✔ C2-04 runtime: unsafe existing mirror refuses boot and never publishes a socket (19.148653ms)
|
||||
✖ C2-04 runtime: real library adapters reach the socket and lock waits leave other bus reads responsive (10.834076ms)
|
||||
ℹ tests 6
|
||||
ℹ suites 0
|
||||
ℹ pass 3
|
||||
ℹ fail 3
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 192.486443
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/bus/tests/library.test.mjs:56:1
|
||||
✖ C2-04 socket: each async library verb resolves its result rather than serializing {} (14.255977ms)
|
||||
Error: unauthenticated
|
||||
at Socket.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/bus/src/client.mjs:42:17)
|
||||
at Socket.emit (node:events:514:20)
|
||||
at addChunk (node:internal/streams/readable:575:12)
|
||||
at readableAddChunkPushByteMode (node:internal/streams/readable:526:3)
|
||||
at Readable.push (node:internal/streams/readable:406:5)
|
||||
at Pipe.onStreamRead (node:internal/stream_base_commons:189:23) {
|
||||
code: 'unauthenticated'
|
||||
}
|
||||
|
||||
test at packages/bus/tests/library.test.mjs:67:1
|
||||
✖ C2-04 runtime: protectedRoots skips library but retains real code-root credential protection (20.969978ms)
|
||||
Error: credential-format
|
||||
at deny (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/bus/src/credentials.mjs:10:9)
|
||||
at #format (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/bus/src/credentials.mjs:232:28)
|
||||
at #read (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/bus/src/credentials.mjs:222:37)
|
||||
at new Credentials (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/bus/src/credentials.mjs:145:35)
|
||||
at startBroker (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/bus/src/runtime.mjs:109:19)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/bus/tests/library.test.mjs:72:25)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19) {
|
||||
code: 'credential-format'
|
||||
}
|
||||
|
||||
test at packages/bus/tests/library.test.mjs:91:1
|
||||
✖ C2-04 runtime: real library adapters reach the socket and lock waits leave other bus reads responsive (10.834076ms)
|
||||
Error: ENOENT: no such file or directory, lstat '/mnt/storage/scratch/gt-iwfcrf5s/library-rRi0EP/data'
|
||||
at lstatSync (node:fs:2138:25)
|
||||
at new Store (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/bus/src/store.mjs:137:22)
|
||||
at startBroker (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/bus/src/runtime.mjs:100:13)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/bus/tests/library.test.mjs:94:25)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5) {
|
||||
errno: -2,
|
||||
code: 'ENOENT',
|
||||
syscall: 'lstat',
|
||||
path: '/mnt/storage/scratch/gt-iwfcrf5s/library-rRi0EP/data'
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
✔ C2-04 M4: both verbs reject every agent before arguments or adapter access (29.476748ms)
|
||||
✔ C2-04 bus: human reads validate keys and return adapter results without path leakage (11.765761ms)
|
||||
✔ C2-04 socket: each async library verb resolves its result rather than serializing {} (15.523467ms)
|
||||
✔ C2-04 runtime: protectedRoots skips library but retains real code-root credential protection (41.028545ms)
|
||||
✔ C2-04 runtime: unsafe existing mirror refuses boot and never publishes a socket (20.174444ms)
|
||||
✔ C2-04 runtime: real library adapters reach the socket and lock waits leave other bus reads responsive (89.276012ms)
|
||||
ℹ tests 6
|
||||
ℹ suites 0
|
||||
ℹ pass 6
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 314.116154
|
||||
@@ -0,0 +1,35 @@
|
||||
node:internal/modules/esm/resolve:272
|
||||
throw new ERR_MODULE_NOT_FOUND(
|
||||
^
|
||||
|
||||
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/mnt/storage/scratch/gt-iwfcrf5s/base/packages/library/src/mirror.mjs' imported from /mnt/storage/scratch/gt-iwfcrf5s/base/packages/library/tests/mirror.test.mjs
|
||||
at finalizeResolution (node:internal/modules/esm/resolve:272:11)
|
||||
at moduleResolve (node:internal/modules/esm/resolve:879:10)
|
||||
at defaultResolve (node:internal/modules/esm/resolve:1006:11)
|
||||
at #cachedDefaultResolve (node:internal/modules/esm/loader:708:20)
|
||||
at #resolveAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:728:38)
|
||||
at ModuleLoader.resolveSync (node:internal/modules/esm/loader:766:56)
|
||||
at #resolve (node:internal/modules/esm/loader:690:17)
|
||||
at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:610:35)
|
||||
at ModuleJob.syncLink (node:internal/modules/esm/module_job:277:33)
|
||||
at ModuleJob.link (node:internal/modules/esm/module_job:389:17) {
|
||||
code: 'ERR_MODULE_NOT_FOUND',
|
||||
url: 'file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/library/src/mirror.mjs'
|
||||
}
|
||||
|
||||
Node.js v26.8.1
|
||||
✖ packages/library/tests/mirror.test.mjs (35.196517ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 0
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 41.636181
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/library/tests/mirror.test.mjs:1:1
|
||||
✖ packages/library/tests/mirror.test.mjs (35.196517ms)
|
||||
'test failed'
|
||||
@@ -0,0 +1,35 @@
|
||||
node:internal/modules/esm/resolve:272
|
||||
throw new ERR_MODULE_NOT_FOUND(
|
||||
^
|
||||
|
||||
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/mnt/storage/scratch/gt-iwfcrf5s/base/packages/library/src/mirror.mjs' imported from /mnt/storage/scratch/gt-iwfcrf5s/base/packages/library/tests/mirror.test.mjs
|
||||
at finalizeResolution (node:internal/modules/esm/resolve:272:11)
|
||||
at moduleResolve (node:internal/modules/esm/resolve:879:10)
|
||||
at defaultResolve (node:internal/modules/esm/resolve:1006:11)
|
||||
at #cachedDefaultResolve (node:internal/modules/esm/loader:708:20)
|
||||
at #resolveAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:728:38)
|
||||
at ModuleLoader.resolveSync (node:internal/modules/esm/loader:766:56)
|
||||
at #resolve (node:internal/modules/esm/loader:690:17)
|
||||
at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:610:35)
|
||||
at ModuleJob.syncLink (node:internal/modules/esm/module_job:277:33)
|
||||
at ModuleJob.link (node:internal/modules/esm/module_job:389:17) {
|
||||
code: 'ERR_MODULE_NOT_FOUND',
|
||||
url: 'file:///mnt/storage/scratch/gt-iwfcrf5s/base/packages/library/src/mirror.mjs'
|
||||
}
|
||||
|
||||
Node.js v26.8.1
|
||||
✖ packages/library/tests/mirror.test.mjs (29.912154ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 0
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 35.532092
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/library/tests/mirror.test.mjs:1:1
|
||||
✖ packages/library/tests/mirror.test.mjs (29.912154ms)
|
||||
'test failed'
|
||||
@@ -0,0 +1,24 @@
|
||||
✔ C2-04 mirror: exact default path, bare without checkout or remote, and idempotent initialization (38.226069ms)
|
||||
✔ C2-04 mirror: simultaneous creators publish one intact mirror and leave no staging paths (28.230282ms)
|
||||
✔ C2-04 mirror: skipped publication accepts both coreutils statuses without removing the winner (102.534821ms)
|
||||
✔ C2-04 mirror: preserve occupied directories and reject symlink ancestors and code overlaps (13.3233ms)
|
||||
✔ C2-04 mirror: existing metadata accepts only bare Git plus state and the precreated lock (21.415494ms)
|
||||
✔ C2-04 state: missing state is empty only while the served ref is absent (35.194627ms)
|
||||
✔ C2-04 state: valid problems and sync metadata return no content and change no state bytes (37.132264ms)
|
||||
✔ C2-04 state: strict keys, types, times, branch, commit and fixed R messages fail closed (99.673047ms)
|
||||
✔ C2-04 state: symlink, hardlink, non-private state and missing lock refuse without replacement (28.715976ms)
|
||||
✔ C2-04 file: served commit, not HEAD or a caller commit, owns the exact returned text (71.638861ms)
|
||||
✔ C2-04 file: R1, R2 and R7 exclusions and never-synced mirrors cannot return file bodies (78.457144ms)
|
||||
✔ C2-04 lock: a first-sync and fast-forward reader wait for a consistent pair across processes (228.356974ms)
|
||||
✔ C2-04 lock: same-process waits, timeout code, callback expiry and throw release (5027.769608ms)
|
||||
✔ C2-04 lock: owner death releases the kernel lock without replacing its file (52.875238ms)
|
||||
✔ C2-04 lock: a missing flock binary becomes a handled refusal (49.021765ms)
|
||||
✔ C2-04 lock: an unawaited scoped read drains before the lock is released (20.779739ms)
|
||||
ℹ tests 16
|
||||
ℹ suites 0
|
||||
ℹ pass 16
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 5980.465131
|
||||
@@ -0,0 +1,30 @@
|
||||
✔ C2-04 mirror: exact default path, bare without checkout or remote, and idempotent initialization (42.294098ms)
|
||||
✔ C2-04 mirror: simultaneous creators publish one intact mirror and leave no staging paths (29.430204ms)
|
||||
✖ C2-04 mirror: skipped publication accepts both coreutils statuses without removing the winner (15050.820834ms)
|
||||
✔ C2-04 mirror: preserve occupied directories and reject symlink ancestors and code overlaps (13.507402ms)
|
||||
✔ C2-04 mirror: existing metadata accepts only bare Git plus state and the precreated lock (19.93202ms)
|
||||
✔ C2-04 state: missing state is empty only while the served ref is absent (33.088494ms)
|
||||
✔ C2-04 state: valid problems and sync metadata return no content and change no state bytes (34.798253ms)
|
||||
✔ C2-04 state: strict keys, types, times, branch, commit and fixed R messages fail closed (96.144919ms)
|
||||
✔ C2-04 state: symlink, hardlink, non-private state and missing lock refuse without replacement (28.529103ms)
|
||||
✔ C2-04 file: served commit, not HEAD or a caller commit, owns the exact returned text (71.331837ms)
|
||||
✔ C2-04 file: R1, R2 and R7 exclusions and never-synced mirrors cannot return file bodies (80.081788ms)
|
||||
✔ C2-04 lock: a first-sync and fast-forward reader wait for a consistent pair across processes (232.208946ms)
|
||||
✔ C2-04 lock: same-process waits, timeout code, callback expiry and throw release (5028.099129ms)
|
||||
✔ C2-04 lock: owner death releases the kernel lock without replacing its file (55.474555ms)
|
||||
✔ C2-04 lock: a missing flock binary becomes a handled refusal (51.152959ms)
|
||||
✔ C2-04 lock: an unawaited scoped read drains before the lock is released (21.006119ms)
|
||||
ℹ tests 16
|
||||
ℹ suites 0
|
||||
ℹ pass 15
|
||||
ℹ fail 0
|
||||
ℹ cancelled 1
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 20945.326932
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/library/tests/mirror.test.mjs:53:1
|
||||
✖ C2-04 mirror: skipped publication accepts both coreutils statuses without removing the winner (15050.820834ms)
|
||||
'test timed out after 15000ms'
|
||||
@@ -0,0 +1,23 @@
|
||||
✔ C2-04 mirror: exact default path, bare without checkout or remote, and idempotent initialization (37.162857ms)
|
||||
✔ C2-04 mirror: simultaneous creators publish one intact mirror and leave no staging paths (28.538429ms)
|
||||
✔ C2-04 mirror: preserve occupied directories and reject symlink ancestors and code overlaps (10.987669ms)
|
||||
✔ C2-04 mirror: existing metadata accepts only bare Git plus state and the precreated lock (20.080027ms)
|
||||
✔ C2-04 state: missing state is empty only while the served ref is absent (33.757482ms)
|
||||
✔ C2-04 state: valid problems and sync metadata return no content and change no state bytes (35.501927ms)
|
||||
✔ C2-04 state: strict keys, types, times, branch, commit and fixed R messages fail closed (96.276094ms)
|
||||
✔ C2-04 state: symlink, hardlink, non-private state and missing lock refuse without replacement (28.464199ms)
|
||||
✔ C2-04 file: served commit, not HEAD or a caller commit, owns the exact returned text (72.087911ms)
|
||||
✔ C2-04 file: R1, R2 and R7 exclusions and never-synced mirrors cannot return file bodies (78.120774ms)
|
||||
✔ C2-04 lock: a first-sync and fast-forward reader wait for a consistent pair across processes (230.905584ms)
|
||||
✔ C2-04 lock: same-process waits, timeout code, callback expiry and throw release (5029.743303ms)
|
||||
✔ C2-04 lock: owner death releases the kernel lock without replacing its file (51.842651ms)
|
||||
✔ C2-04 lock: a missing flock binary becomes a handled refusal (48.619585ms)
|
||||
✔ C2-04 lock: an unawaited scoped read drains before the lock is released (19.747384ms)
|
||||
ℹ tests 15
|
||||
ℹ suites 0
|
||||
ℹ pass 15
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 5872.380072
|
||||
@@ -0,0 +1,51 @@
|
||||
✔ C2-04 mirror: exact default path, bare without checkout or remote, and idempotent initialization (35.114121ms)
|
||||
✔ C2-04 mirror: simultaneous creators publish one intact mirror and leave no staging paths (28.344028ms)
|
||||
✖ C2-04 mirror: preserve occupied directories and reject symlink ancestors and code overlaps (11.29287ms)
|
||||
✔ C2-04 mirror: existing metadata accepts only bare Git plus state and the precreated lock (21.069667ms)
|
||||
✔ C2-04 state: missing state is empty only while the served ref is absent (33.576129ms)
|
||||
✔ C2-04 state: valid problems and sync metadata return no content and change no state bytes (36.355449ms)
|
||||
✔ C2-04 state: strict keys, types, times, branch, commit and fixed R messages fail closed (98.678405ms)
|
||||
✔ C2-04 state: symlink, hardlink, non-private state and missing lock refuse without replacement (28.476513ms)
|
||||
✔ C2-04 file: served commit, not HEAD or a caller commit, owns the exact returned text (72.613881ms)
|
||||
✔ C2-04 file: R1, R2 and R7 exclusions and never-synced mirrors cannot return file bodies (78.072657ms)
|
||||
✔ C2-04 lock: a first-sync and fast-forward reader wait for a consistent pair across processes (230.109966ms)
|
||||
✔ C2-04 lock: same-process waits, timeout code, callback expiry and throw release (5027.239374ms)
|
||||
✔ C2-04 lock: owner death releases the kernel lock without replacing its file (53.970224ms)
|
||||
✔ C2-04 lock: a missing flock binary becomes a handled refusal (45.088532ms)
|
||||
✔ C2-04 lock: an unawaited scoped read drains before the lock is released (19.793614ms)
|
||||
ℹ tests 15
|
||||
ℹ suites 0
|
||||
ℹ pass 14
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 5869.613351
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/library/tests/mirror.test.mjs:53:1
|
||||
✖ C2-04 mirror: preserve occupied directories and reject symlink ancestors and code overlaps (11.29287ms)
|
||||
AssertionError [ERR_ASSERTION]: The input did not match the regular expression /overlap/. Input:
|
||||
|
||||
'Error: project-path: unsafe mirror path'
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/library/tests/mirror.test.mjs:64:10)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: Error: project-path: unsafe mirror path
|
||||
at Module.mirrorPath (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/library/src/mirror.mjs:40:25)
|
||||
at file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/library/tests/mirror.test.mjs:64:27
|
||||
at getActual (node:assert:580:5)
|
||||
at strict.throws (node:assert:728:24)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/library/tests/mirror.test.mjs:64:10)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7),
|
||||
expected: /overlap/,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
✖ C2-04 mirror: skipped publication accepts both coreutils statuses without removing the winner (56.393634ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 0
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 102.30317
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/library/tests/mirror.test.mjs:53:1
|
||||
✖ C2-04 mirror: skipped publication accepts both coreutils statuses without removing the winner (56.393634ms)
|
||||
Error: {"code":1,"stderr":"file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/library/src/mirror.mjs:18\nconst fail = (code, message = code) => { throw new LibraryError(code, message); };\n ^\n\nLibraryError: library-git: expected a private owned bare mirror\n at fail (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/library/src/mirror.mjs:18:48)\n at ownedRoot (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/library/src/mirror.mjs:49:13)\n at inspectMirrorUnchecked (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/library/src/mirror.mjs:57:3)\n at inspectMirror (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/library/src/mirror.mjs:94:15)\n at ensureMirror (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/library/src/mirror.mjs:128:11)\n at process.processTicksAndRejections (node:internal/process/task_queues:104:5)\n at async file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/[eval1]:7:149 {\n code: 'library-git'\n}\n\nNode.js v26.8.1\n"}
|
||||
at file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/library/tests/mirror.test.mjs:65:108
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/herb-row197/packages/library/tests/mirror.test.mjs:65:22)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3)
|
||||
@@ -0,0 +1,11 @@
|
||||
✔ Broker keeps the sandbox client import closure: only the listed imports, no lazy project import (1.794155ms)
|
||||
✔ without a trusted project adapter all three async paths refuse project-not-configured (39.865453ms)
|
||||
✔ real startBroker injects the project adapter for socket reads and bound-author record writes (65.643553ms)
|
||||
ℹ tests 3
|
||||
ℹ suites 0
|
||||
ℹ pass 3
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 197.45826
|
||||
@@ -0,0 +1,11 @@
|
||||
✔ Broker keeps the sandbox client import closure: only the listed imports, no lazy project import (1.418597ms)
|
||||
✔ without a trusted project adapter all three async paths refuse project-not-configured (34.510685ms)
|
||||
✔ real startBroker injects the project adapter for socket reads and bound-author record writes (59.944824ms)
|
||||
ℹ tests 3
|
||||
ℹ suites 0
|
||||
ℹ pass 3
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 183.05447
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"mirror.test-final-r2.log": {
|
||||
"tests": 16,
|
||||
"pass": 16,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"library.test-final.log": {
|
||||
"tests": 6,
|
||||
"pass": 6,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"library-cli.test-final.log": {
|
||||
"tests": 1,
|
||||
"pass": 1,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"project-runtime.test-final.log": {
|
||||
"tests": 3,
|
||||
"pass": 3,
|
||||
"fail": 0,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"library.test-baseline-focused.log": {
|
||||
"tests": 3,
|
||||
"pass": 0,
|
||||
"fail": 3,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"library-cli.test-baseline-r2.log": {
|
||||
"tests": 1,
|
||||
"pass": 0,
|
||||
"fail": 1,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"mirror.test-baseline-r2.log": {
|
||||
"tests": 1,
|
||||
"pass": 0,
|
||||
"fail": 1,
|
||||
"cancelled": 0,
|
||||
"skipped": 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/mnt/storage/scratch/gt-iwfcrf5s
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"base": "a2c72ac95",
|
||||
"landing": "fefd54e13",
|
||||
"overlaps": [
|
||||
"BUILD-LOG.md",
|
||||
"packages/cli/tests/stack-release.test.mjs"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
{
|
||||
"oldBase": "f8276c5eb3ecb0aad353ee65e3dd8f7faac5dd87",
|
||||
"oldSource": "e333af4dc7af3a9d3789c8c0db26a0df8bdddfee",
|
||||
"newBase": "a3652371338e60187d4e95cee4a0f30f3c8a8f06",
|
||||
"paths": [
|
||||
{
|
||||
"path": "BUILD-LOG.md",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/bus/src/broker.mjs",
|
||||
"upstreamChanged": true,
|
||||
"matchesPriorBlob": false,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/bus/src/runtime.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/bus/src/server.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/bus/tests/library.test.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/business/src/business.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/business/src/cli.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/business/src/instance-settings.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/business/src/organization.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/business/src/resolve.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/business/tests/business.test.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/business/tests/cli.test.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/business/tests/instance-settings.test.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/business/tests/library-projects-protected.test.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/business/tests/resolve.test.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/cli/src/config.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/cli/src/launcher.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/cli/tests/launcher.test.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/cli/tests/stack-release-fixture.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/cli/tests/stack-release.test.mjs",
|
||||
"upstreamChanged": true,
|
||||
"matchesPriorBlob": false,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/cli/tests/trackers-boot.test.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/library/src/index.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/library/src/mirror.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/library/tests/mirror.test.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/project/src/paths.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/project/tests/project.test.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/seat/src/checkout.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/seat/tests/checkout.test.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/webui/src/cli.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
},
|
||||
{
|
||||
"path": "packages/webui/tests/library-cli.test.mjs",
|
||||
"upstreamChanged": false,
|
||||
"matchesPriorBlob": true,
|
||||
"changeLinesIdentical": true
|
||||
}
|
||||
],
|
||||
"newSource": "a6101e21c596e2972ab5a7e3087736075899505e",
|
||||
"stablePatchId": "d191e7e9586cd3b7c18310daacdf0c1fdbc8be01"
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
packages/bus/tests/library.test.mjs
|
||||
packages/bus/tests/project-runtime.test.mjs
|
||||
packages/business/tests/business.test.mjs
|
||||
packages/business/tests/cli.test.mjs
|
||||
packages/business/tests/instance-settings.test.mjs
|
||||
packages/business/tests/library-projects-protected.test.mjs
|
||||
packages/business/tests/resolve.test.mjs
|
||||
packages/cli/tests/launcher.test.mjs
|
||||
packages/cli/tests/stack-release-external.test.mjs
|
||||
packages/cli/tests/stack-release.test.mjs
|
||||
packages/cli/tests/stack-upgrade.test.mjs
|
||||
packages/cli/tests/trackers-boot.test.mjs
|
||||
packages/library/tests/mirror.test.mjs
|
||||
packages/project/tests/project.test.mjs
|
||||
packages/seat/tests/checkout.test.mjs
|
||||
packages/webui/tests/library-cli.test.mjs
|
||||
packages/bus/tests/agents.test.mjs
|
||||
packages/bus/tests/approval-binding.test.mjs
|
||||
packages/bus/tests/broker.test.mjs
|
||||
packages/bus/tests/business.test.mjs
|
||||
packages/bus/tests/channel-proof.test.mjs
|
||||
packages/bus/tests/chief-of-staff.test.mjs
|
||||
packages/bus/tests/comment-cursors.test.mjs
|
||||
packages/bus/tests/creative.test.mjs
|
||||
packages/bus/tests/credential-claim.test.mjs
|
||||
packages/bus/tests/credential-status.test.mjs
|
||||
packages/bus/tests/credential-store.test.mjs
|
||||
packages/bus/tests/credential-verbs.test.mjs
|
||||
packages/bus/tests/credentials.test.mjs
|
||||
packages/bus/tests/csuite-messaging.test.mjs
|
||||
packages/bus/tests/daily-quota-runtime.test.mjs
|
||||
packages/bus/tests/decision-close.test.mjs
|
||||
packages/bus/tests/decision-route.test.mjs
|
||||
packages/bus/tests/decisions.test.mjs
|
||||
packages/bus/tests/end-launch.test.mjs
|
||||
packages/bus/tests/grant-enroll.test.mjs
|
||||
packages/bus/tests/grant-executor.test.mjs
|
||||
packages/bus/tests/grant-host.test.mjs
|
||||
packages/bus/tests/grant-migration.test.mjs
|
||||
packages/bus/tests/hard-waits.test.mjs
|
||||
packages/bus/tests/host-run.test.mjs
|
||||
packages/bus/tests/human.test.mjs
|
||||
packages/bus/tests/instances-verb.test.mjs
|
||||
packages/bus/tests/land.test.mjs
|
||||
packages/bus/tests/launch-notice.test.mjs
|
||||
packages/bus/tests/limit-stop.test.mjs
|
||||
packages/bus/tests/limits-runtime.test.mjs
|
||||
packages/bus/tests/limits.test.mjs
|
||||
packages/bus/tests/message-citation.test.mjs
|
||||
packages/bus/tests/messages.test.mjs
|
||||
packages/bus/tests/messaging.test.mjs
|
||||
packages/bus/tests/names.test.mjs
|
||||
packages/bus/tests/plugins-verb.test.mjs
|
||||
packages/bus/tests/process.test.mjs
|
||||
packages/bus/tests/project-await.test.mjs
|
||||
packages/bus/tests/project-files.test.mjs
|
||||
packages/bus/tests/publish.test.mjs
|
||||
packages/bus/tests/replies.test.mjs
|
||||
packages/bus/tests/requirements.test.mjs
|
||||
packages/bus/tests/review.test.mjs
|
||||
packages/bus/tests/routes-verb.test.mjs
|
||||
packages/bus/tests/single-use.test.mjs
|
||||
packages/bus/tests/spec-review.test.mjs
|
||||
packages/bus/tests/spec-socket.test.mjs
|
||||
packages/bus/tests/spec.test.mjs
|
||||
packages/bus/tests/staff-request.test.mjs
|
||||
packages/bus/tests/state.test.mjs
|
||||
packages/bus/tests/task-page.test.mjs
|
||||
packages/bus/tests/task-read.test.mjs
|
||||
packages/bus/tests/tasks.test.mjs
|
||||
packages/bus/tests/tester-threads.test.mjs
|
||||
packages/bus/tests/tester-writes.test.mjs
|
||||
packages/bus/tests/tester.test.mjs
|
||||
packages/bus/tests/thread-migration.test.mjs
|
||||
packages/bus/tests/threads.test.mjs
|
||||
packages/bus/tests/transport.test.mjs
|
||||
packages/bus/tests/usage-broker.test.mjs
|
||||
packages/bus/tests/usage-runtime.test.mjs
|
||||
packages/bus/tests/web.test.mjs
|
||||
packages/bus/tests/workflow-roles.test.mjs
|
||||
@@ -0,0 +1,86 @@
|
||||
diff --git a/packages/bus/src/broker.mjs b/packages/bus/src/broker.mjs
|
||||
index 135a1699a..f0eb4ae65 100644
|
||||
--- a/packages/bus/src/broker.mjs
|
||||
+++ b/packages/bus/src/broker.mjs
|
||||
@@ -88,6 +88,7 @@ export const TASK_PAGE_MAX = 200;
|
||||
// Row 148 (#1642): the human-only verbs behind the Console's document editor. The save is the one
|
||||
// request allowed past the ordinary 64 KiB envelope (server.mjs and client.mjs), up to its content cap.
|
||||
export const PROJECT_FILE_VERBS = Object.freeze(['project.files', 'project.file', 'project.file.save']);
|
||||
+export const LIBRARY_VERBS = Object.freeze(['library.file', 'library.status']);
|
||||
export const PROJECT_SAVE_VERB = 'project.file.save';
|
||||
export const PROJECT_SAVE_REQUEST_MAX = 1024 * 1024 + 64 * 1024;
|
||||
export const WEB_VERBS =Object.freeze(['web.search', 'web.fetch']);
|
||||
@@ -279,6 +280,7 @@ export class Broker {
|
||||
#organization;
|
||||
#credentialVerbs;
|
||||
#project;
|
||||
+ #library;
|
||||
#usage;
|
||||
#limits;
|
||||
#harnessOn;
|
||||
@@ -294,7 +296,7 @@ export class Broker {
|
||||
#stops = new Map();
|
||||
#clock = 0;
|
||||
// credentialStatus is the runtime's metadata-only Credentials.status(); the broker never gets use().
|
||||
- constructor({ store, businesses, secretCheck = () => {}, credentialStatus = () => [], organization = null, project = null, usage = null, limits = null, harnessOn = null, credentialVerbs = null, hostGrant = null, hostKeys = null }) {
|
||||
+ constructor({ store, businesses, secretCheck = () => {}, credentialStatus = () => [], organization = null, project = null, library = null, usage = null, limits = null, harnessOn = null, credentialVerbs = null, hostGrant = null, hostKeys = null }) {
|
||||
if (!object(businesses) || !Object.keys(businesses).length) fail('invalid-business');
|
||||
this.#businesses = structuredClone(businesses);
|
||||
this.#store = store;
|
||||
@@ -306,6 +308,7 @@ export class Broker {
|
||||
this.#hostGrant = hostGrant;
|
||||
this.#hostKeys = hostKeys;
|
||||
this.#project = project;
|
||||
+ this.#library = library;
|
||||
this.#usage = usage;
|
||||
this.#limits = limits;
|
||||
// Row 65: harnessOn(business, name) is true when the organization file's plugins.harness switches
|
||||
@@ -2192,6 +2195,8 @@ export class Broker {
|
||||
return this.#requestProject(s, { verb: request.verb, args: structuredClone(args) });
|
||||
if (PROJECT_FILE_VERBS.includes(request.verb))
|
||||
return this.#requestProjectFile(s, { verb: request.verb, args: structuredClone(args) });
|
||||
+ if (LIBRARY_VERBS.includes(request.verb))
|
||||
+ return this.#requestLibrary(s, { verb: request.verb, args: structuredClone(args) });
|
||||
if (CREDENTIAL_VERBS.includes(request.verb)) return this.#requestCredential(s, request.verb, structuredClone(args));
|
||||
if (["limits", "limits.set", "organization.set", "organization.revision", "plugins", "plugins.set", "instances", "instances.set", "routes", "routes.set"].includes(request.verb)) {
|
||||
// Row 123 (#1617, REQ-COS-1, REQ-LIMIT-1): organization.set is limits.set for a role whose
|
||||
@@ -2441,6 +2446,26 @@ export class Broker {
|
||||
throw this.#refused(s, ProjectFailure && e instanceof ProjectFailure ? new BusError(e.code) : e, request);
|
||||
}
|
||||
}
|
||||
+ // C2-04 M4: only a verified human reads library text or status. Host Git
|
||||
+ // functions stay injected, preserving this module's sandbox import closure.
|
||||
+ async #requestLibrary(s, request) {
|
||||
+ const { verb, args } = request;
|
||||
+ try {
|
||||
+ this.#human(s);
|
||||
+ const fields = verb === 'library.file' ? ['project', 'path'] : ['project'];
|
||||
+ keys(args, fields, fields);
|
||||
+ if (!this.#library?.readFile || !this.#library?.status) fail('project-not-configured');
|
||||
+ const context = { business: this.#business(s.business), project: args.project };
|
||||
+ const result = verb === 'library.file'
|
||||
+ ? await this.#library.readFile({ ...context, path: args.path })
|
||||
+ : await this.#library.status(context);
|
||||
+ this.#secretCheck(result);
|
||||
+ return result;
|
||||
+ } catch (error) {
|
||||
+ const Failure = this.#library?.LibraryError;
|
||||
+ throw this.#refused(s, Failure && error instanceof Failure ? new BusError(error.code) : error, request);
|
||||
+ }
|
||||
+ }
|
||||
// The eight task verbs reach the trusted S3 handler here. It runs outside any transaction, gets the
|
||||
// cap to authorize and record through authorize() and recordTask(); refusals are recorded as in request().
|
||||
async requestTask(cap, request, handler) {
|
||||
diff --git a/packages/cli/tests/stack-release.test.mjs b/packages/cli/tests/stack-release.test.mjs
|
||||
index 7398247ce..0e316fd74 100644
|
||||
--- a/packages/cli/tests/stack-release.test.mjs
|
||||
+++ b/packages/cli/tests/stack-release.test.mjs
|
||||
@@ -1779,7 +1779,7 @@ export class Store {
|
||||
const RCOPIES=join(base,'rcopies');mkdirSync(RCOPIES);
|
||||
for(const [id,v,froms] of [[B,'3g',['3f']],[C,'3h',['3f','3g']],[A,'3g',['3f']],[C1,'3g',['3f']]]){
|
||||
const d=join(RCOPIES,id);
|
||||
- for(const p of ['scripts/mosaic','scripts/mosaic-config.mjs','packages/cli/src/config.mjs','packages/cli/src/errors.mjs','packages/bus/src/business.mjs','packages/plugins/src/kinds.mjs','packages/business/src','roles'])cpSync(join(repo,p),join(d,p),{recursive:true});
|
||||
+ for(const p of ['scripts/mosaic','scripts/mosaic-config.mjs','packages/cli/src/config.mjs','packages/cli/src/errors.mjs','packages/bus/src/business.mjs','packages/plugins/src/kinds.mjs','packages/business/src','packages/library/src','roles'])cpSync(join(repo,p),join(d,p),{recursive:true});
|
||||
if(id===C1)writeFileSync(join(d,'scripts','mosaic'),`#!/usr/bin/env bash\nexec node "${join(RCOPIES,B,'packages','cli','src','cli.mjs')}" "$@"\n`,{mode:0o755});
|
||||
for(const [f,text] of [['packages/cli/src/cli.mjs',id===A?'// fixture host from before row 163\nprocess.exit(1);\n':script(rHost)],['packages/webui/src/cli.mjs',script(rConsole)],['packages/bus/src/store.mjs',rStore(v,froms)],['packages/bus/src/migrate-schema.mjs',script(rMigrate)],['packages/bus/src/broker.mjs','export class BusError extends Error { constructor(code) { super(code); this.code = code; } }\n']]){mkdirSync(dirname(join(d,f)),{recursive:true});writeFileSync(join(d,f),text)}
|
||||
execFileSync('chmod',['-R','a-w',d]);
|
||||
@@ -0,0 +1,10 @@
|
||||
1: e333af4dc ! 1: a6101e21c feat: add human-only library projects and served reads
|
||||
@@ Metadata
|
||||
Author: Herb <[email protected]>
|
||||
|
||||
## Commit message ##
|
||||
- feat: add human-only library projects and served reads
|
||||
+ feat: carry reviewed C2-04 library entry onto row 197 landing
|
||||
|
||||
## BUILD-LOG.md ##
|
||||
@@ BUILD-LOG.md: Before: managed project/thread verbs had no Console conversation area. After: fi
|
||||
@@ -0,0 +1,128 @@
|
||||
# Row 243: too-open mode refusal tests set their mode with chmod
|
||||
|
||||
Brief: `docs/plans/2026-10-21_gate-env-rows.md` § "The startup token refusal test sets its file mode"
|
||||
(Sage, sage-1909). Reviewer Webby. Lands after row 197 (mos-1162). Design notes written before 197
|
||||
lands, read at `origin/refactor` 01e1fe512. Recheck the line cites against 197's landing before code
|
||||
starts.
|
||||
|
||||
## The defect
|
||||
|
||||
`writeFileSync(file, data, { mode })` and `mkdirSync(dir, { mode })` apply the process umask to the
|
||||
mode. A test that creates a "too open" file this way and expects a refusal passes under `umask 022`
|
||||
(0644 stays 0644) and fails under `umask 077` (0644 becomes 0600, and the source accepts it).
|
||||
|
||||
Row 197 r6 (df0c59608) runs each gate step under `umask 022` (`gate-lane.mjs:46`), so the lane no
|
||||
longer hits this. Row 243 still makes the tests independent of the umask, as the brief asks.
|
||||
|
||||
## Sweep
|
||||
|
||||
Method: every source-side mode check in `packages/*/src` and `scripts/` (grep for `mode & 0o...`), then
|
||||
the tests that reach each check's refusal branch, deciding whether the too-open object gets its mode at
|
||||
creation or from an explicit chmod. Also a scan of every `writeFileSync`/`mkdirSync`/`openSync` in
|
||||
`packages/*/tests` with a group or other bit in its mode (50 hits, 41 without a following chmod), and a
|
||||
grep of the refusal messages for objects created with no mode or by a shell-out. Read at
|
||||
`origin/refactor` with `git show` and `git grep`; nothing run.
|
||||
|
||||
Affected refusal tests, all three verified by reading the test (the fourth file, an accept test, follows the table):
|
||||
|
||||
| Creation | Test | Source check | Expected refusal |
|
||||
|---|---|---|---|
|
||||
| `packages/bus/tests/process.test.mjs:76` `writeFileSync(file, secret, { mode: 0o644 })` | startup token refusal returns safe code... | `bus/src/credentials.mjs:205` (must be 0600) | `credential-file`, exit 2 (:83-84) |
|
||||
| `packages/webui/tests/proof-cli.test.mjs:28` `writeFileSync(file, value, { mode })`, mode 0o644 from the `mode` case at :27 | proof startup refuses partial flags... | `webui/src/serve.mjs:234` (0600 or 0400) | status 2 (:38) |
|
||||
| `packages/webui/tests/sso.test.mjs:360` `writeFileSync(.../secrets/mosaic-stack/a, ..., { mode: 0o644 })` | 11: the CLI refuses --sso... | `webui/src/sso.mjs:45` (no group or other bits) | status 2 and the "no group or other permission bits" line (:361-363); the chmod to 0600 at :364 comes after |
|
||||
|
||||
Fix for each: keep the write, then `chmodSync(<path>, 0o644)` right after it. For `proof-cli.test.mjs`
|
||||
the chmod goes inside the case map after the write, with the case's own mode, so the 0o600 cases are set
|
||||
explicitly too.
|
||||
|
||||
Not affected (each sets the mode with a chmod or a chmodding helper before the code under test reads it):
|
||||
bus credentials.test :52, credential-store.test :55-61; business access.test :225-226, business.test
|
||||
:159/161/174, credentials.test :60, cli.test :151, helpers `writeJson`/`tokenFile`; cli cli.test :176,
|
||||
notifier.test :318/:321, stack-release.test :1220/1239/1294/1313/1552, stack-upgrade.test :426-430,
|
||||
case2-unit.test :340/:510/:635; control-board discord.test :79; discord binding.test :106/118/140/277,
|
||||
notify.test :76, setspark.test :110, git.test :138/:360, offline-check.test :21; mosaic safety.test :80;
|
||||
queue review.test :214/:228; ledger gitea-helper-raw.test :113; webui service.test :797, sso.test :310;
|
||||
bus host-tools.test :182/:266. The 0o644/0o755 adapter and fake-binary writes (launcher, thread-launch,
|
||||
session, sandbox, checkout, commit, etc.) aren't read by a mode check, or are only checked for the exec
|
||||
bit, which 0700 keeps. `host-tools.test.mjs:205`, `:271` and the confDir at `:77` expect acceptance and
|
||||
only need "not group-writable".
|
||||
|
||||
Mode checks with no refusal test at all (not this row; listed for the record): `bus/src/store.mjs:121`,
|
||||
`bus/src/host-run.mjs:71`, `business/src/organization.mjs:28/45/109/141`,
|
||||
`conversation/src/controller.mjs:299`, `mosaic/src/materialize-fixture.mjs:16`,
|
||||
`mosaic/src/refresh-fixture.mjs:64`, `seat/src/session.mjs:72`, `scripts/git-credential-mosaic.mjs:49`,
|
||||
and the mode branch of `scripts/stack-release.sh:1952`.
|
||||
|
||||
Fourth file, folded in by Sage (sage-1918): `packages/cli/tests/stack-instances.test.mjs:84` and `:89`
|
||||
assert 0644 on the config and `instance.json`. `scripts/mosaic-config.mjs:337` creates them with
|
||||
`openSync(file, "wx", 0o644)` and no chmod, so under `umask 077` they come out 0600 and the test fails.
|
||||
This is an accept test of a source mode, not a refusal test.
|
||||
|
||||
| Creation | Test | Source | Ruling |
|
||||
|---|---|---|---|
|
||||
| `scripts/mosaic-config.mjs:337` via `bootstrap()` (`stack-instances.test.mjs:41`, a `spawnSync` of `scripts/bootstrap.sh`) | the `--instance` create test, :79-89 | `createExclusive` passes 0o644 and the umask narrows it | test-only (sage-1918) |
|
||||
|
||||
- No change to `mosaic-config.mjs`. Letting the operator's umask narrow the config is the source's
|
||||
choice; a chmod to 0644 would make the config wider than that umask. No row asks for it.
|
||||
- `bootstrap()` runs its child under an explicit `umask 022`, the pattern from `gate-lane.mjs:46`:
|
||||
`run("/bin/bash", ["-c", 'umask 022; exec "$@"', "bash", BOOTSTRAP, ...args], homeEnv(home))`. Every
|
||||
`bootstrap()` call goes through it (:79, :99, :102, :119, :127, :136, :140, :152, :165, :169), so the
|
||||
0644 assertions still prove the mode the source asks for, whatever the gate's umask.
|
||||
- New assertion: a `bootstrap --instance` run under `umask 077` makes the config and `instance.json`
|
||||
0600. That pins that the source honors the umask, so a later chmod "fix" fails a test. The directories
|
||||
stay 0700 in both runs (they're created with `mode: 0o700`, which 077 can't narrow).
|
||||
- The `config()` helper (:42) has no mode assertion and stays as it is.
|
||||
|
||||
Tests outside `packages/*/tests`: the five `scripts/foundation/*.test.mjs` files have no open-mode
|
||||
write. `cli.test.mjs:144/148` chmods to 0o000 and 0o600, which doesn't depend on the umask. The
|
||||
`agents/*/work` probe tests are review evidence, not gate steps (`discoverSteps` doesn't run them), so
|
||||
they're out of scope.
|
||||
|
||||
## Tests
|
||||
|
||||
- Each of the four files runs whole twice, once under `umask 022` and once under `umask 077`
|
||||
(`bash -c 'umask 077; node --test <file>'`). Both pass. The brief requires this for process.test.mjs;
|
||||
Sage extended it to all four (sage-1918).
|
||||
- Proof that the change matters: before the change, the same four files under `umask 077` fail on the
|
||||
named assertions. I record that run too, on the slot, so the 077 pass after the change is meaningful.
|
||||
- Order (mos-1162): this lands after 197 r6, so r6's proof ran on the unchanged test.
|
||||
|
||||
## Files (expected)
|
||||
|
||||
`packages/bus/tests/process.test.mjs`, `packages/webui/tests/proof-cli.test.mjs`,
|
||||
`packages/webui/tests/sso.test.mjs`, `packages/cli/tests/stack-instances.test.mjs`. Test-only. No
|
||||
source change.
|
||||
|
||||
## Build (sage-2056: start on row 197's landing a36523713)
|
||||
|
||||
Branch `morgana/row243`, one commit on a36523713. Cites rechecked there: all hold except proof-cli's
|
||||
write, which is now `proof-cli.test.mjs:30` (was :28).
|
||||
|
||||
- `bus/tests/process.test.mjs`: imports `chmodSync`; `chmodSync(file, 0o644)` after the write at :76.
|
||||
- `webui/tests/proof-cli.test.mjs:30`: `chmodSync(file, mode)` after the write, with each case's own
|
||||
mode, so the 0o600 cases are set explicitly too.
|
||||
- `webui/tests/sso.test.mjs:360`: `chmodSync(..., 0o644)` after the write, before the `--sso` start
|
||||
that must refuse.
|
||||
- `cli/tests/stack-instances.test.mjs`: `underUmask(mask, home, args)` runs `scripts/bootstrap.sh`
|
||||
through `/bin/bash -c 'umask <mask>; exec "$@"'`; `bootstrap()` is `underUmask("022", ...)`. New
|
||||
subtest in T-I1: under umask 077 the config dir and root are 0700, and the config and `instance.json`
|
||||
are 0600.
|
||||
- Hash pins: no test or script names any of the four files (a grep for the basenames; positive control
|
||||
`stack-release.test` found in two files). `stack-release.test.mjs:2122` mentions
|
||||
`stack-instances.test.mjs` only in a comment.
|
||||
|
||||
Tests: on Sage's slot (sage-2062, plan approved in sage-2059), 18:55Z. My busy check read CLEAR before
|
||||
and after. Each file ran whole with `node --test --test-concurrency=2` from its package, under
|
||||
`bash -c 'umask <mask>; exec ...'`, with TMPDIR from `mktemp -d /mnt/storage/scratch/tmp/g243XXXX`.
|
||||
Script `/mnt/storage/scratch/morgana-r243/slot243.sh`, logs in `logs/` next to it.
|
||||
|
||||
| Tree | umask | process | proof-cli | sso | stack-instances |
|
||||
|---|---|---|---|---|---|
|
||||
| base a36523713 | 077 | 7/1 | 2/1 | 27/1 | 21/2 |
|
||||
| candidate 137bda3af | 022 | 8/0 | 3/0 | 28/0 | 24/0 |
|
||||
| candidate 137bda3af | 077 | 8/0 | 3/0 | 28/0 | 24/0 |
|
||||
|
||||
(pass/fail.) The base fails are the predicted ones: "startup token refusal returns safe code...",
|
||||
"proof startup refuses partial flags...", "11: the CLI refuses --sso...", and in stack-instances the
|
||||
0644 subtest "alpha and beta get a 0700 config dir..." plus its parent T-I1 (so 2). stack-instances has
|
||||
one more test on the candidate (the umask 077 subtest). No unpredicted failure.
|
||||
@@ -1419,4 +1419,15 @@ are never rewritten or removed; corrections are new entries.
|
||||
2026-10-21T06:47:54Z | researcher | row 228 (#1729) round 3 in review (rev 2702; start rev 2700) | rebase of r2 onto the 234 landing c771a36f4 as researcher/row228-r3 cf18c42b9 (one commit, pushed) with Webby's round 2 N1 (:711 and :718); manifest 82cf98c6 (3 files); slot sage-1796: session.test 13 + host.test 42 = 55/0, manifest OK before and after, busy228.sh copy named in the clear; r2 94/0 and M1 killed stand (seat blobs unchanged); request attempt left in requesting state (lock held by sage-238-review-2b when the outcome rev was written, exit 3; transport said failed pre-send, no token), Sage resolves and posts as jarvis; packet agents/researcher/work/queue-228/r3
|
||||
2026-10-21T07:29:23Z | researcher | row 228 (#1729) landed as 86249ac55 (pushed 07:25Z by Sage) | patch-id b6ffe31feb0d matches my r3 candidate cf18c42b9 (checked here against origin/refactor); Sage combined gate with 238: seat 165/0, cli 640/0, scripts 585/0; queue note rev 2725, done rev 2727, #1729 closed comment 29966 (sage-1824); q228r2 worktree removed, branches researcher/row228, -r2 and -r3 stay on origin and locally; packets agents/researcher/work/queue-228 r1 r2 r3 uncommitted
|
||||
2026-10-21T15:19:14Z | Sage (Opus 5.5, 1ef1e4f8) | MVP push 10-21 afternoon: rows 249, 197 proof 3/4, 222 singles, 66 r4d, queue-commit | 249 landed 9de5a57ab (+7b9737953 DEFERRED N1, #1751 closed, Vikunja 445 c442); 197 proof 3 rc=1 on a driver defect, Herb's fix a5b636750 to Webby, proof 4 set up in sage-r197p4; 222 singles 34/34 and 5 mutants killed (sage-2028); 66 round 4 in review (82c830779, c30083/30084); queue revs 2642-2904 committed 0636721e6
|
||||
2026-10-21T15:20:10Z | Dewey (Opus 5.5, 84fb346c) | row 66 r4 review (sage-2036, sage/row66-r4d 82c830779, manifest 6cfd812da4ca) | APPROVE 30085, rev 2905; rebase only, code lines identical to r3 (-U0 patch-id b3e9e076e5f1), four shared files clean; no tests run; dewey-0768 Sage
|
||||
2026-10-21T15:20:58Z | Filbert (Opus 5.5, 048f3c63) | row 66 r4 review (sage-2037, sage/row66-r4d 82c830779, manifest 6cfd812da4ca) | APPROVE 30086, rev 2906; static, no tests; rebase only, row 66 +/- lines identical to r3 next to rows 212/213/232/245; N1 code-only patch-id d67275ac4251 (508bb684eade includes BUILD.md), N2 BUILD.md cap-sentence wording; packet-only notes
|
||||
2026-10-21T18:55:21Z | Filbert (Opus 5.5, 048f3c63) | row 215 r2 merge-scoped review (herb-0093, mos-1160, herb/row215-on197 dde3445ab, manifest 40d9722a) | APPROVE 30103, rev 2924; static, no tests; patch-id d191e7e9586c same as r1, 28/30 blobs+modes = e333af4dc, broker.mjs and stack-release.test.mjs = clean merge-file onto a36523713; r1 N1-N4 carry, suite gate Sage's
|
||||
2026-10-21T19:06:16Z | Sage (Opus 5.5, 1ef1e4f8) | row 66 landing, #435/J2 brief, 196 r2/215/243/250/251 gate coordination (mos-1186, mos-1193, mos-1195, mos-1197) | row 66 LANDED 2c38325ec + DEFERRED 3b0aef995, #1559 closed; 640aa03f2 brief pushed; REQ-WEB-2 wording to Mos (sage-2067); 196 r2 stop 2 ruled (sage-2072); 215 gate on slot (Herb); #1754 for 243; 250 Gizmoduck/Filbert, 251 Darkwing/Dewey
|
||||
2026-10-21T19:20:16Z | Darkwing (Opus 5.5, 7525c8e4) | row 251 T27 ssh-add lifetime (sage-2075, sage-2084, Vikunja #453, Gitea #1756) | darkwing/row251 68f2dfd4b pushed (e5e4b2e5a step 1, c19b4167e -t 2 + 3.5 s sleep, host-run.mjs unchanged); in-review r1 rev 2944, request 30121 resolved rev 2947, manifest c7497de3; Dewey woken darkwing-0111; slot asked darkwing-0110, nothing run
|
||||
2026-10-21T19:23:11Z | Dewey (Opus 5.5, 84fb346c) | row 251 r1 static review (darkwing-0111), 68f2dfd4b, digest c7497de3 | no blocking findings; OpenSSH 10.5p1 citations checked at V_10_5_P1; comment 30126 on #1756; verdict to be recorded on r2 with part A results; no tests run
|
||||
2026-10-21T19:23:48Z | Filbert (Opus 5.5, 048f3c63) | row 250 r1 static review (gizmoduck-0146, sage-2091, gizmoduck/row250 e9cfd92f8, manifest 14ff20b6) | CHANGES 30125, rev 2950; static, no tests; C1 R13 never calls h.ctrl.close() so the controller server (controller.mjs:548) stays open and cohort.test.mjs is expected not to exit; fix await h.ctrl.close() before h.c.close(); cause trace, step 1, no loosening, R13 coverage, no pins, no drift all hold
|
||||
2026-10-21T19:28:22Z | Filbert (Opus 5.5, 048f3c63) | row 250 r2 static review (gizmoduck-0148, gizmoduck/row250-r2 c1a858975, manifest eca0b8e2) | APPROVE 30130, rev 2957; static, no tests; C1 fixed: R13 closes its controller after the checks (cached release, one entry) and again in finally (no-op); no drift, no findings; gate run Sage's
|
||||
2026-10-21T19:31:02Z | Herb (gpt-6.1-sol, f6cf4287) | row 215 C2-04 landed as e54e05463 (#1716 closed c30133, queue done rev 2955) | Filbert round 2 APPROVE c30103/rev 2924; candidate dde3445ab on a36523713 preserves rows 249 and 197. Granted sage-2071: business 209/0, seat 166/0, cli 729/0, project 41/0, bus 604/0, webui 300/0 with one environment editor-build skip; all ten scripts/test-*.sh 585/0; total 2634/0 in 926.796 s, ended 19:20:47Z, leftover process sweep 0, temp root and owned network removed. Sage accepted receipts and landed after 6096b051b (sage-2097); no further 215 work.
|
||||
2026-10-21T19:34:18Z | Sage (Opus 5.5, 1ef1e4f8) | row 215 landing, 196 r3 grant withdrawn for the base change and r4 granted, 250/222/244/251 slot order | 215 LANDED e54e05463 (patch-id 2f68188b6c9d = a36523713..dde3445ab, tree = merge-tree; herb-0095 2634/0, webui esbuild skip ruled env); #1716 closed c30133, done rev 2955, Vikunja 416 c471. sage-2092 withdrawn (r3 conflicted with 215), sage-2096 to Gander r4 f8a59e6aa, mutant kills kept by blob sha. 250 r2 request c30131 (rev 2958), Filbert APPROVE 2957. 244 issue #1757 (rev 2959). 222 r2 c9aa9c2ee accepted; gate scope per the row. Order: Gander, Gizmoduck, Megavolt, Morgana, Darkwing.
|
||||
2026-10-21T19:46:12Z | Dewey (Opus 5.5, 84fb346c) | row 222 r1 static review (megavolt-0095), c9aa9c2ee, manifest c2121b55 | APPROVE, comment 30138 on #1723, queue rev 2966; rulings: createObject=rename accepted, 5 s human timeout deferred with STATUS codes in the follow-up, credential.helper reset argv-only accepted; notes N1-N5; no tests run
|
||||
2026-10-21T19:49:37Z | Sage (Opus 5.5, 1ef1e4f8) | row 250 landing, row 196 r5 grant (mos-1198) and resume (mos-1200), F27 row 253 | 250 LANDED 1b6158ce2 (patch-id 29786caa, Filbert rev 2957, Gizmoduck slot green), #1755 closed c30139, Vikunja 450; 196 r5 91e3696ef hunk checked by Duckworth, webui 304/0; my queue add tripped Gander's busy check, not a stop (mos-1200), resume on 05e940117; row 253 #1758 brief 0cdead66c
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
# Brief: case2-unit.sh and case1-accept.sh move to --tester-socket (F27)
|
||||
|
||||
Sage, 2026-10-21, for Mos's ruling mos-1198 item 4. Owner Gander, reviewer Duckworth, gate owner Sage.
|
||||
Chained directly after row 196: it starts on row 196's landing and rebases onto it. Until this row lands, no
|
||||
Case 1 or Case 2 host (.53, .54) takes a stack copy that carries row 196.
|
||||
|
||||
## Why
|
||||
|
||||
Row 196 retires the Console's `--tester-port`. `packages/webui/src/cli.mjs:30` refuses it with
|
||||
"--tester-port retired; activate explicitly with --tester-socket". Two root scripts still produce or require
|
||||
the old flag, so a unit they render won't start on a copy that carries 196:
|
||||
|
||||
- `scripts/case2-unit.sh` takes `--tester-port N` for the factory profile (:163, :193-194, :204) and renders
|
||||
`cli.mjs serve $FLAGS` into the Console unit's ExecStart (:356).
|
||||
- `scripts/case1-accept.sh` reads `--tester-port` from the saved installer args (:65), refuses args that
|
||||
lack it (:88), and checks the tester port in P10 tester-port-squat (:430, :432).
|
||||
|
||||
Gander's static audit on row 196 r5 lists every caller and test: `agents/gander/work/queue-196/r5/
|
||||
TESTER-PORT-AUDIT.md` and `tester-port-occurrences.json` at 91e3696ef.
|
||||
|
||||
## What this row does
|
||||
|
||||
1. `case2-unit.sh`: the factory profile takes `--tester-socket` and renders it into the Console ExecStart.
|
||||
`--tester-port` is refused with stack-release.sh's migration wording (`scripts/stack-release.sh:808`,
|
||||
"retires tester TCP; use --tester-socket"), naming this script in place of the target copy. The
|
||||
library profile still refuses any tester flag.
|
||||
2. The socket path must work under the unit's hardening (ProtectHome, PrivateTmp, ReadWritePaths, :340-343).
|
||||
Use the path row 196 derives (`<dataRoot>/console/tester.sock`) and the parent checks stack-release.sh
|
||||
makes (:815). Say in DESIGN.md how the rendered unit reaches it.
|
||||
3. `case1-accept.sh`: accept the socket form in the saved args, and refuse args that carry `--tester-port`
|
||||
with the same wording. P10 checks what the socket form needs in place of a port squat check. Say what
|
||||
it checks and what each outcome line reads.
|
||||
4. Tests: `packages/cli/tests/case2-unit.test.mjs` and `case1-accept.test.mjs` move their fixtures to the
|
||||
socket form, and each gains a refusal test for `--tester-port`. Fakes only, as they use now.
|
||||
5. Leave the deliberate legacy paths alone: `scripts/webui-service.sh`, `scripts/stack-release.sh`,
|
||||
`scripts/instance.sh`, their tests, `stack-release-fixture.mjs`, `case1-hostcheck.test.mjs` and the
|
||||
negative calls in `tester-cli.test.mjs`. If one of them needs a change, stop and ask.
|
||||
|
||||
## Static check
|
||||
|
||||
The check covers scripts as well as tests (mos-1198 item 4). After this row, `git grep -n -- --tester-port
|
||||
scripts packages` returns only the legacy paths in step 5 and the refusals this row adds. BUILD.md lists
|
||||
each remaining hit and why it stays.
|
||||
|
||||
## Boundaries
|
||||
|
||||
- No test touches `~/.mosaic-dev`, `~/.config/mosaic-dev`, the live units, a slot file, .53 or .54.
|
||||
- This row doesn't run case1-accept.sh or case2-unit.sh on a host. That is a window with Jason.
|
||||
|
||||
## Gate
|
||||
|
||||
Duckworth approves DESIGN.md, then the manifest. On Sage's slot: the cli suite whole, the webui suite whole,
|
||||
and every `scripts/test-*.sh`, green. The mutants named in DESIGN.md are killed, at least one per refusal.
|
||||
The static check above holds on the candidate.
|
||||
+12
-8
@@ -33,7 +33,7 @@ Gaps found while working go to `docs/plans/DEFERRED.md`, not here.
|
||||
|
||||
<!-- mosaic-queue:begin -->
|
||||
|
||||
Generated from `docs/plans/queue.json` revision 2904 by `queue render`. Do not edit between the markers; change the queue with `scripts/mosaic queue`.
|
||||
Generated from `docs/plans/queue.json` revision 2967 by `queue render`. Do not edit between the markers; change the queue with `scripts/mosaic queue`.
|
||||
|
||||
| # | Piece | Owner | Issues | State | After | Gate | Brief | Note |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
@@ -78,7 +78,7 @@ Generated from `docs/plans/queue.json` revision 2904 by `queue render`. Do not e
|
||||
| 39 | Slice 1 S4: the mosaic CLI, inbox, decide, tasks, agents, trail | rocko; reviewers darkwing, filbert | #1521 | done | 37 done | filbert approves on #1521, darkwing approves the packages/discord change and the broker host; cli tests, test-discord, every test-*.sh green (sage) | `docs/plans/2026-10-04_slice-1.md` § Slice 1 S4: the `mosaic` CLI (inbox, decide, tasks, agents, trail) | Follow-ups from round 1 (sage): (a) one host that boots every business, since writer.lock allows one broker per dataRoot while the unit is per business; accepted for slice 1 with one business. (b) the queue's PATH_RE refuses '@' in manifest paths, so the S4 unit template was renamed to mosaic-bus.service.in; packages/discord/systemd/[email protected] would hit the same refusal in any future candidate manifest. |
|
||||
| 40 | Slice 1 S5: WebUI inbox, tasks, agents and trails; CHAT-03 Gate E | dewey; reviewers darkwing, filbert | #1522 | done | 39 done | darkwing and filbert approve on #1522; webui, conversation, control-board and every test-*.sh green; row 5 Gate E is Jason's (sage) | `docs/plans/2026-10-04_slice-1.md` § Slice 1 S5: WebUI (inbox, tasks, agents and trails; CHAT-03 Gate E) | — |
|
||||
| 41 | Slice 1 S6: meta-harness and launching; the PM moves off T3 | filbert; reviewers darkwing | #1523 | done | 34 done, 36 done, 38 done | darkwing approves on #1523; harness and seat tests, every test-*.sh; recorded PM launch of a coder (sage) | `docs/plans/2026-10-04_slice-1.md` § Slice 1 S6: meta-harness and launching (the PM moves off T3) | — |
|
||||
| 42 | Slice 1 S7: acceptance, five pieces in a row | sage | #1524 | in-progress | 40 done, 41 done | Jason, from the five trails: only gated decisions reached him, every step left a trail (jason) | `docs/plans/2026-10-04_slice-1.md` § Slice 1 S7: acceptance, five pieces in a row | — |
|
||||
| 42 | Slice 1 S7: acceptance, five pieces in a row | sage | #1524 | in-progress | 40 done, 41 done | Jason, from the five trails: only gated decisions reached him, every step left a trail (jason) | `docs/plans/2026-10-04_slice-1.md` § Slice 1 S7: acceptance, five pieces in a row | mos-1184 (2026-10-21T16:58Z): pieces 1-5 are Jason's requests to pm through the Console or mosaic talk pm, a route Q194 suspends until Jason says the Stack is operational. The pieces are paused, the 10-23 23:59Z date is dropped and no new date is set. mos-1148's C1/C2 rules wait with them. The 10-24 window goes ahead without the pieces (sage-1622). |
|
||||
| 43 | S2b: gated approvals are single-use (authorize records consumption) | rocko; reviewers darkwing | #1525 | done | 37 done | darkwing approves on #1525; Sage's integration gate (sage) | `docs/plans/2026-10-05_s2b-single-use-approvals.md` § S2b: gated approvals are single-use (authorize records consumption) | 2026-10-05: S2 is in the tree at 38828a2c. Rocko's README edit (ae643fba, decision 62 human-proof note) is an uncommitted change on packages/bus/README.md and belongs in this row's candidate. |
|
||||
| 44 | S2c: a within-role message cites a decision without consuming it | rocko; reviewers darkwing | #1526 | done | 43 done | darkwing approves on #1526; Sage's integration gate (sage) | `docs/plans/2026-10-05_s2c-message-decision-citation.md` § S2c: a within-role message cites a decision without consuming it | — |
|
||||
| 45 | S4 follow-up: notifier retry limit, journal types and the round 2 test gaps | rocko; reviewers darkwing, filbert | #1527 | done | — | filbert and darkwing approve on #1527; every node package suite and every test-*.sh green on Sage's gate rerun (sage) | `docs/plans/2026-10-09_s4-follow-up-and-cohort.md` § S4 follow-up: notifier retry limit, journal types and the round 2 test gaps | lead decision 72; follows row 39 (2f5303c1) |
|
||||
@@ -102,7 +102,7 @@ Generated from `docs/plans/queue.json` revision 2904 by `queue render`. Do not e
|
||||
| 63 | Multi-project verbs: task verbs across the tree | darkwing; reviewers dewey, filbert | #1556 | done | 62 done | dewey and filbert approve on the issue naming the candidate manifest; tasks, harness and every scripts/test-*.sh green on Sage's gate rerun (sage) | `docs/plans/2026-10-11_multi-project-sync.md` § Multi-project verbs: task verbs across the tree (row B) | lands before row 90 (decision 125): both share packages/tasks/README.md and tests/verbs.test.mjs, so row 90 rebases after this lands |
|
||||
| 64 | Managed sessions get their role's skills on both harnesses | sage; reviewers darkwing, filbert | #1557 | done | 65 done | darkwing and filbert approve on #1557 naming the candidate manifest; business, harness, cli and every test-*.sh green on Sage's gate rerun; Sage's landing session on each harness shows the role's skills (sage) | `docs/plans/2026-10-11_managed-session-config.md` § Managed sessions get their role's skills on both harnesses | Landed (mos-0863/0864): 9f0039711 = c6d7d538f (range-diff =, patch-id 7e1948e2f2e9), F1 doc 6b6567b8b, packet ebfc23c43; gate-land GATE_PASSED 2384/0 on 6b6567b8b. D2 on #1557 comment 29228: claude-code coder rc13bcd555652 replied with its 4 skills, pi coder r3455505dd5da launch only (no pi credential on host, to Mos); both manifests list the 4 coder skills, sha256 = landed files. D3 window step 46de60893, D4 #1672 row 174. |
|
||||
| 65 | Model routing table: sessions resolve harness, model and thinking from one table | sage; reviewers darkwing, dewey | #1558 | done | 49 done, 131 done | Mos clears the routing table's public/ diff (decision 123, mos-0840) before in-review; darkwing and dewey approve on #1558; plugins, bus, business, harness, seat, cli, webui, test-*.sh green on Sage's rerun; landing session shows module, route, counted model, thinking; report names the mos-0840 view (sage) | `docs/plans/2026-10-11_managed-session-config.md` § Model routing table: sessions resolve harness, model and thinking from one table | Decision 94 hold ended (cutover live 17:21Z); restarted under decision 111 and Mos sage-0091. |
|
||||
| 66 | Managed sessions run the unslop check on both harnesses | sage; reviewers dewey, filbert | #1559 | in-review, round 4, request posted | 64 done | dewey and filbert approve on #1559 naming the candidate manifest; unslop, harness, cli and every test-*.sh green on Sage's gate rerun; Sage's landing session on each harness shows the notice, the correction and the counts (sage) | `docs/plans/2026-10-11_managed-session-config.md` § Managed sessions run the unslop check on both harnesses | Drift: row 245 (6d5545d44) changed docs/TOOLS.md, which is in this manifest. r4c must take 245's TOOLS.md hunks before its gate and new manifest; the approved TOOLS.md blob is now stale (sage-1992 sweep). |
|
||||
| 66 | Managed sessions run the unslop check on both harnesses | sage; reviewers dewey, filbert | #1559 | done | 64 done | dewey and filbert approve on #1559 naming the candidate manifest; unslop, harness, cli and every test-*.sh green on Sage's gate rerun; Sage's landing session on each harness shows the notice, the correction and the counts (sage) | `docs/plans/2026-10-11_managed-session-config.md` § Managed sessions run the unslop check on both harnesses | Landed 2c38325ec (mos-1186) = r5 7ffb640ac on a36523713: range-diff = but one hunk header, code patch-id d67275ac4251 on all bases; whole 215df5455e46, 24 paths equal. N1/N2 corrected in BUILD.md. Gate r4d green (cli 682/0 rerun), harness 149/0 on r5. Sessions on scratch root: claude-code r4ab24630d323 note+notice, checked 2 flagged 1 notices 1; pi r1dd94171bede launch only (#383). Live checks Vikunja #454. |
|
||||
| 67 | Decisions read follow-up: seen-then-resolve, list-before-503 and full-row tests | filbert; reviewers darkwing, dewey | #1560 | done | — | darkwing and dewey approve on #1560 naming the candidate manifest; bus, webui and every scripts/test-*.sh green on Sage's gate rerun (sage) | `docs/plans/2026-10-11_decisions-read-follow-up.md` § Decisions read follow-up: seen-then-resolve, list-before-503 and full-row tests | — |
|
||||
| 68 | Bus host runs an explicit Claude Code binary | sage; reviewers dewey, filbert | #1561 | done | — | Filbert and Dewey approve; cli, seat, harness suites and every scripts/test-*.sh green on Sage's gate rerun; unit reinstalled and opus probe through MOSAIC_CLAUDE_BIN (sage) | `docs/plans/2026-10-11_bus-claude-binary.md` § Bus host runs an explicit Claude Code binary | — |
|
||||
| 69 | Terminal app follow-up: narrow-terminal guard test, hidden-box way out and width tests | darkwing; reviewers dewey, filbert | #1562 | done | 55 done | dewey and filbert approve on the issue naming the candidate manifest; cli and queue node suites plus every scripts/test-*.sh green on Sage's gate rerun (sage) | `docs/plans/2026-10-11_terminal-app-follow-up.md` § Terminal app follow-up: narrow-terminal guard test, hidden-box way out and width tests | Sage accepts the two shortened texts in round 1 (hidden box way out, status line), both forced by the 40x10 frame. Follow-up at landing: when help is cut to fit, draw() points at mosaic inbox --json though help has no whole text; open it as its own row (build.md Found, not fixed) |
|
||||
@@ -233,7 +233,7 @@ Generated from `docs/plans/queue.json` revision 2904 by `queue render`. Do not e
|
||||
| 194 | agent lifecycle from the Console and the CLI (create, launch, terminate, regenerate, delete) with a per-agent hire/fire veto (MVP T1.5, Vikunja #414/#415) | honker; reviewers webby | #1692 | in-progress | — | Webby approves DESIGN.md then the manifest; bus, cli, business and webui suites and every scripts/test-*.sh green on Sage's gate; the mutants killed (sage) | `docs/plans/2026-10-20_agent-lifecycle.md` § Brief: agent lifecycle from the Console and the CLI, with a per-agent hire/fire veto | sage-1610 (honker-0049): a human add takes tracker {bot, botId}, required for a vikunja definition, refused otherwise, checked by checkBot and bot uniqueness; CLI and API only. Delete accepts a tracker bot when all credentials are store refs, and its result names the bot for removal by hand in Vikunja. No Vikunja account is created (Q188 untouched). Mutants: drop the requirement, refuse the bot on delete, skip checkBot on add. |
|
||||
| 195 | row 195: the Case 1 install on 10.1.1.53 as mosaic under /srv/mosaic, reusing C2-13's scripts by input under row 190's canon (Q181, Q182/Q183, Q185; ops-01 root steps under #423 step 1) | darkwing; reviewers duckworth | #1693 | done | 190 done, 226 done, 233 done | Duckworth approves DESIGN.md then the manifest; cli suite and every scripts/test-*.sh green on Sage's gate; the mutants killed (sage) | `docs/plans/2026-10-20_hub-own-uid.md` § Brief: the Case 1 install on 10.1.1.53 (row 195) | LANDED b65014647 (pushed 361ba2387 tip). Patch-id 656e43ff25de = 4ced5e63d..37171f65b; verify-commit ok, 5 paths. Combined gate with 213 on 38b83ea5c+paths 09:45:52-09:57:52Z: business 200/0 bus 542/0 harness 140/0 cli 663/0, all 10 scripts green, L1 killed. N1-N3 to DEFERRED next; follow-up darkwing/row195-n1 1e3c4767c. |
|
||||
| 196 | the human boundary across uids and humans: Console, tester listener, broker.sock and the path-bound human proof (P19 333, before federation R3, mos-0989) | gander; reviewers duckworth | #1694 | in-progress | — | Duckworth approves DESIGN.md then the manifest; bus, webui and cli suites and every scripts/test-*.sh green on Sage's gate; the mutants killed (sage) | `docs/plans/2026-10-20_human-boundary.md` § Brief: the human boundary across uids and humans (P19 333) | — |
|
||||
| 197 | a second gate lane: two full gates at once on dragon-lin, design first (mos-0977 item 6) | herb; reviewers webby | #1695 | in-review, round 6, request posted | — | Webby approves DESIGN.md then the manifest; cli suite and every scripts/test-*.sh green on Sage's gate, singly and in the two-lane proof (sage) | `docs/plans/2026-10-20_second-gate-lane.md` § Brief: a second gate lane, two full gates at once on dragon-lin | r7 APPROVED (webby-0074 rev 2822). r7 proof sage-1973 11:50-11:51Z STOPPED at solo-a pkg-cli (#1695 c30044): gate-lane-image.test.mjs:93 and :103 call docker via PATH, which in a lane is the guard shim; composeFixture env drops MOSAIC_GATE_DOCKER_RECORD, shim exits 2. business 200/0, bus 596/0, cli 197/2. r8 Herb: test-only fix + run under a lane-shaped PATH. N10 still open. |
|
||||
| 197 | a second gate lane: two full gates at once on dragon-lin, design first (mos-0977 item 6) | herb; reviewers webby | #1695 | done | — | Webby approves DESIGN.md then the manifest; cli suite and every scripts/test-*.sh green on Sage's gate, singly and in the two-lane proof (sage) | `docs/plans/2026-10-20_second-gate-lane.md` § Brief: a second gate lane, two full gates at once on dragon-lin | Landed a36523713 on refactor (base 5afff5490, pushed 18:40Z): Herb's c45ddeb6b cherry-picked. Range-diff = (only the cherry-pick line), patch-id 79c46b98c685 equals c45ddeb6b and candidate A d2de56bd2; 37 paths equal, marker test absent (mos-1174 check). Proof 6 PROOF_PASSED 18:40:06Z, sage-r197p6: 8 waves 26/26 steps, cb A 124 B 125, probe ok, no event or cleanup errors, final CLEAR/CLEAR. Webby approved r8 (rev 2867). |
|
||||
| 198 | retire the control board writer on 7331 (unauthenticated loopback writer, Q175; mos-1008) | bushroot; reviewers webby | #1696 | in-progress | 192 done, 197 done | Webby approves INVENTORY.md then the manifest; control-board, webui and cli suites and every scripts/test-*.sh green on Sage's gate; the mutants killed (sage) | `docs/plans/2026-10-20_retire-control-board.md` § Brief: retire the control board writer on 7331 | Order with row 197 (Sage, mos-1040 N1): 197 lands first. Row 198 rebases onto 197's landing before its manifest review; shared tests are packages/webui/tests/serve.test.mjs:100 and preview.test.mjs:208. |
|
||||
| 199 | MVP T1 item 6: a credential store per agent, own git identity, pushes to a remote (G11, G13; mos-0974) | megavolt; reviewers duckworth | #1697 | done | — | Duckworth approves DESIGN.md; Mos rules on the authority model; Duckworth approves the manifest; bus, business, cli and tasks suites and every scripts/test-*.sh green on Sage's gate; the mutants killed (sage) | `docs/plans/2026-10-20_agent-credentials.md` § Brief: a credential store per agent, own git identity, pushes to a remote | Landed cb5fdb064 on refactor (base 76134dfde), pushed. Patch-id 828fa21a matches git diff 00d4cc1f6..86963d281 on the 37 manifest paths; docs/TOOLS.md 3-way with row 200, hunk unchanged. Manifest 35f900fd, Duckworth approve r1 29779. Gate on 9e1085816+patch: packages 2735/0, scripts 429/0; landed blobs equal the gate tree. |
|
||||
| 200 | stack-release.sh activate --sso for the Q175 phase 2 window (row 192 F3; chained on 192) | launchpad; reviewers webby | #1698 | done | — | Webby approves the manifest; cli suite and every scripts/test-*.sh green on Sage's gate; the mutants killed (sage) | `docs/plans/2026-10-20_stack-release-sso.md` § Brief: stack-release.sh activates a Console with --sso (Q175 phase 2 prerequisite) | Landed 9e1085816 on refactor (base 722136772), pushed. Patch-id 7ebfa6a5 matches git diff 00d4cc1f6..9df40878f on the 3 manifest paths. Manifest b3ead55c, Webby approve r3 29772. Gate on 9df40878f: packages 2675/0, scripts 429/0. Mutants 13/14, M12 ruled equivalent (sage-1446). |
|
||||
@@ -251,14 +251,14 @@ Generated from `docs/plans/queue.json` revision 2904 by `queue render`. Do not e
|
||||
| 212 | Case 2 C2-01 packages/library: mapping, scope, reader, resolver, R-rules, renderItems, survey | gosalyn; reviewers webby | #1713 | done | — | Webby approves the manifest. The library tests and the cli suite are green on Sage's gate, along with every `scripts/test-*.sh`. (sage) | `docs/plans/2026-10-20_case2-rows.md` § C2-01 packages/library: mapping, scope, reader, resolver, R-rules, renderItems, survey | Landed ee7b2f137 (pushed 09:13Z) on f6c70f944, alone per mos-1162: the 21 manifest paths from a2c72ac95. Patch-id ea84d3e35470 equals the candidate's; blobs and modes match; verify-commit ok (21 paths). No 212 path changed after c771a36f4. Gate: Sage's landing gate 08:51-09:03Z on 4ced5e63d plus 212's and 197's paths, GATE_PASSED, node 981/0, selftests 429/0. Gosalyn r3 slot 451/0, test-queue 28/0. Row 197 waits for r6 (lane proof stopped, sage-1881). |
|
||||
| 213 | Case 2 C2-08 creative roles, persona file and block, M1, M2, M6, M10, prompt passed by file | morgana; reviewers webby | #1714 | done | — | Webby approves the manifest. The business, bus and harness suites, `scripts/test-config.sh` and every `scripts/test-*.sh` are green on Sage's gate, and the `models` mutant is killed. (sage) | `docs/plans/2026-10-20_case2-rows.md` § C2-08 creative roles, persona file and block, M1, M2, M6, M10, prompt passed by file | LANDED 361ba2387 (39 paths incl. 4 packet files). Patch-id f313e69b6f7e = c771a36f4..2b3e67e36; verify-commit ok, 35 manifest paths. Same combined gate as 195: business 200/0 bus 542/0 harness 140/0 cli 663/0, test-config 31/0 and all 10 scripts green, models mutant L1 killed. Webby N2 is row 235 acceptance (mos-1163). |
|
||||
| 214 | Case 2 C2-11a editor wikilink node, after measuring whether [[ round-trips | rocko; reviewers filbert | #1715 | briefed | — | Filbert approves the manifest. The webui suite is green on Sage's gate, along with every `scripts/test-*.sh`. (sage) | `docs/plans/2026-10-20_case2-rows.md` § C2-11a editor wikilink node, after measuring whether [[ round-trips | — |
|
||||
| 215 | Case 2 C2-04 the library entry in the business file, consumer skips, M9, mirror, library.file and library.status | herb; reviewers filbert | #1716 | in-review, round 1, request posted | — | Filbert approves the manifest. The business, seat, cli, project, bus and webui suites are green on Sage's gate, along with every `scripts/test-*.sh`. (sage) | `docs/plans/2026-10-20_case2-rows.md` § C2-04 the library entry in the business file, consumer skips, M9, mirror, library.file and library.status | Sage 15:01Z drift sweep after 249 landed 9de5a57ab (+7b9737953): manifest 8d5695d7 shares packages/bus/src/broker.mjs with 249, merge-tree was clean. Order stays 197 then 215 (sage-2029, sage-2030): after 197 lands Herb rebases 215 on that tip for a merge-scoped round with Filbert (broker.mjs from 249, stack-release.test.mjs from 197), then Sage's full landing gate. Rows 13, 66, 197, 202 have no overlap. |
|
||||
| 215 | Case 2 C2-04 the library entry in the business file, consumer skips, M9, mirror, library.file and library.status | herb; reviewers filbert | #1716 | done | — | Filbert approves the manifest. The business, seat, cli, project, bus and webui suites are green on Sage's gate, along with every `scripts/test-*.sh`. (sage) | `docs/plans/2026-10-20_case2-rows.md` § C2-04 the library entry in the business file, consumer skips, M9, mirror, library.file and library.status | LANDED e54e05463 on 6096b051b (sage-2094). Patch-id 2f68188b6c9d equals a36523713..dde3445ab; 118 paths, blobs and modes equal; tree 5b1613245 equals merge-tree. No path overlap with rows 66/243; no hash pins either way. Gate: Filbert APPROVE rev 2924; herb-0095 grant sage-2071 2634 pass 0 fail, 1 webui skip (editor rebuild needs esbuild 0.28.2, env, not a 215 path), accepted. |
|
||||
| 216 | Case 2 C2-05a lookup index and queries | researcher; reviewers filbert | #1717 | briefed | — | Filbert approves the manifest. The library suite is green on Sage's gate, along with every `scripts/test-*.sh`. (sage) | `docs/plans/2026-10-20_case2-rows.md` § C2-05a lookup index and queries | — |
|
||||
| 217 | Case 2 C2-06 the cited-reply guard, the page store and the three notices | launchpad; reviewers webby | #1718 | briefed | — | Webby approves the manifest. The library, bus and harness suites are green on Sage's gate, along with every `scripts/test-*.sh`. (sage) | `docs/plans/2026-10-20_case2-rows.md` § C2-06 the cited-reply guard, the page store and the three notices | — |
|
||||
| 218 | Case 2 C2-12 the setup sheet for Melanie and the survey run sheet | sage; reviewers webby | #1719 | done | — | Doc only. Webby approves it against C2-01's real flags. Before landing, grep `packages/*/tests` and `scripts/test-*.sh` to confirm no test reads either file. (sage) | `docs/plans/2026-10-20_case2-rows.md` § C2-12 the setup sheet for Melanie and the survey run sheet | LANDED f8276c5eb (pushed, on Darkwing sessions b65f3a0e8). Webby APPROVE r1-r3 (revs 2848, 2856, 2860; r3 candidate 1a38baf5af2a = 89ba79d94). Patch-id 18ba1e40ad29 seat 5c6f73ed7..89ba79d94 equals landed b65f3a0e8..f8276c5eb; three blobs equal 89ba79d94. Gate: doc only, 0 test readers (control 3). Melanie handover waits on C2-06 and Jason (#419). |
|
||||
| 219 | Case 2 C2-09a one thread per creative instance | rocko; reviewers dewey | #1720 | briefed | — | Dewey approves the manifest. The bus, cli and webui suites are green on Sage's gate, along with every `scripts/test-*.sh`. Watch for hash pins on `bus.js` and `broker.mjs` (`packages/bus/tests/channel-proof.test.mjs` pins a webui file). (sage) | `docs/plans/2026-10-20_case2-rows.md` § C2-09a one thread per creative instance | — |
|
||||
| 220 | Case 2 C2-10a no raw session view (M7) and no raw Discord engine (M8) | researcher; reviewers filbert | #1721 | briefed | — | Filbert approves the manifest. The conversation and discord suites and `scripts/test-discord.sh` are green on Sage's gate, along with every `scripts/test-*.sh`. No test reaches a Discord server. (sage) | `docs/plans/2026-10-20_case2-rows.md` § C2-10a no raw session view (M7) and no raw Discord engine (M8) | — |
|
||||
| 221 | Case 2 C2-20 Bean and Chet persona import, with a count-only dry run | gosalyn; reviewers webby | #1722 | done | — | Webby approves the manifest. The test file runs green on its own and the cli suite is green on Sage's gate, along with every `scripts/test-*.sh`. (sage) | `docs/plans/2026-10-20_case2-rows.md` § C2-20 Bean and Chet persona import, with a count-only dry run | LANDED 300766450, pushed. Cand 8f403d0d4, manifest 20f05e3a6ad5, 22 paths, verify-commit ok, patch-id dfbb754c6fb4 equals 62ddc96cc..8f403d0d4. Gate 11:07:50-11:19Z on b1fece6f0: test file alone 11/0, harness 140/0, cli 677/0, all scripts green. Brief Gate met: webby-0073 approve, test file alone, cli, scripts. No live run in the Gate; the import itself waits on Jason. N1 N2 N4 go to C2-20b, N3 to DEFERRED. |
|
||||
| 222 | Case 2 C2-03a fetch-only sync | megavolt; reviewers dewey | #1723 | in-progress | — | Dewey approves the manifest. The library and bus suites are green on Sage's gate, along with every `scripts/test-*.sh`, and the mutant is killed. A search of the test run's output for the fixture token finds nothing. (sage) | `docs/plans/2026-10-20_case2-rows.md` § C2-03a fetch-only sync | sage-2024 on megavolt-0089: core.createObject=rename in the fetch argv is accepted as a brief departure, since C2-04 inspectMirror refuses nlink 2. Dewey checks it. The askpass env keys, export SAFE in project/src/git.mjs, bus/tests/library-sync.test.mjs and the SURVEY-RUN user line are accepted. The 5 s client timeout residual goes in BUILD.md and Dewey rules fix or defer. Slot after 197 proof 3 and the 249 gate. |
|
||||
| 222 | Case 2 C2-03a fetch-only sync | megavolt; reviewers dewey | #1723 | in-review, round 1, request posted | — | Dewey approves the manifest. The library and bus suites are green on Sage's gate, along with every `scripts/test-*.sh`, and the mutant is killed. A search of the test run's output for the fixture token finds nothing. (sage) | `docs/plans/2026-10-20_case2-rows.md` § C2-03a fetch-only sync | sage-2024 on megavolt-0089: core.createObject=rename in the fetch argv is accepted as a brief departure, since C2-04 inspectMirror refuses nlink 2. Dewey checks it. The askpass env keys, export SAFE in project/src/git.mjs, bus/tests/library-sync.test.mjs and the SURVEY-RUN user line are accepted. The 5 s client timeout residual goes in BUILD.md and Dewey rules fix or defer. Slot after 197 proof 3 and the 249 gate. |
|
||||
| 223 | Case 2 C2-07 runner retry on a guard refusal, and the runner's notices | researcher; reviewers filbert | #1724 | briefed | — | Filbert approves the manifest. The harness suite is green on Sage's gate, along with every `scripts/test-*.sh`. (sage) | `docs/plans/2026-10-20_case2-rows.md` § C2-07 runner retry on a guard refusal, and the runner's notices | — |
|
||||
| 224 | Case 2 C2-05b broker lookup verbs and typed tools | rocko; reviewers dewey | #1725 | briefed | — | Dewey approves the manifest. The bus and harness suites are green on Sage's gate, along with every `scripts/test-*.sh`. (sage) | `docs/plans/2026-10-20_case2-rows.md` § C2-05b broker lookup verbs and typed tools | — |
|
||||
| 225 | Case 2 C2-10b Console chat: cited items and the status line | researcher; reviewers dewey | #1726 | briefed | — | Dewey approves the manifest. The webui suite is green on Sage's gate, along with every `scripts/test-*.sh`. Grep for hash pins on `bus.js` and `serve.mjs` before in-review. (sage) | `docs/plans/2026-10-20_case2-rows.md` § C2-10b Console chat: cited items and the status line | — |
|
||||
@@ -279,13 +279,17 @@ Generated from `docs/plans/queue.json` revision 2904 by `queue render`. Do not e
|
||||
| 240 | Installer I4: hostcheck, the bwrap profile check, pins and boot unit, from r6 B2 (MVP, Q187, Vikunja #432; split from I3) | darkwing; reviewers filbert | #1746 | done | 233 done | Filbert approves the manifest. The test file, the cli suite and every scripts/test-*.sh are green on Sage's gate, with the mutants killed. (sage) (sage) | `docs/plans/2026-10-20_installer-rows.md` § I4 hostcheck: the bwrap profile check, pins and boot unit | Landed c515273db (pushed 06:57Z) on da3051ccc: the 9 manifest paths from ad1b23ab2. Patch-id 48e376efe8a4 equals the candidate's; modes and blobs match; verify-commit ok (9 paths). Sage's gate on 060a17b54 plus the 9 paths, 06:45:05Z to 06:56:21Z: cli 639/0, all ten scripts/test-*.sh 585/0. Darkwing's r2: singles 37/0, M1-M8 8/8. Filbert N1 and N2 in DEFERRED (da3051ccc); N3 by design. |
|
||||
| 241 | Row 237 follow-up: one decision lands once, a two-ticket broker land test and three mutants on the landing guards (megavolt-0069, sage-1651, P19 441) | megavolt; reviewers duckworth | #1747 | done | 237 done | Duckworth approves the manifest. The bus, seat and cli suites and every scripts/test-*.sh are green on Sage's gate, and the three mutants are killed. (sage) (sage) | `docs/plans/2026-10-20_agent-credentials.md` § Brief: row 237 follow-up, one decision lands once, with tests at the broker | Landed 5d4a61776 on refactor, pushed (base e65a3ab4d). Blobs from 3e3ed303e on 2 paths; patch-id a1649f80 equals git diff f5753c0e8..3e3ed303e on those paths; ls-tree modes equal; manifest e8266864 verifies on the landed files. Sage slot on bbf3b1ee8: M1-M3 killed; gate 15 packages 2797/0, 10 script suites 429/0. Duckworth approve 29870 rev 2628. |
|
||||
| 242 | Row 237 follow-up N1: a retry after publish-timeout pushes once; hold the decision or kill and wait for the push, a slow-push retry test and a mutant (duckworth-0069, P19 440) | megavolt; reviewers duckworth | #1748 | done | 237 done | Duckworth approves the manifest. The bus and cli suites and every scripts/test-*.sh are green on Sage's gate, and the mutant is killed. (sage) (sage) | `docs/plans/2026-10-20_agent-credentials.md` § Brief: row 237 follow-up N1, a retry after publish-timeout pushes once | Landed 5fb736b92 on refactor, pushed (base 96bac588f). Blobs from 635c10924 on 3 paths; patch-id ceb741ee equals git diff 8fede5fc6..635c10924 on those paths; ls-tree modes equal; manifest 1fbfab6c verifies on the landed files. Megavolt M1/M2 killed on Sage's slot; Sage gate 15 packages 2826/0, 10 script suites 429/0. Duckworth approve 29889 rev 2639. |
|
||||
| 243 | process.test.mjs startup token refusal sets its file mode (chmod), umask sweep of packages/*/tests | morgana; reviewers webby | — | briefed | 197 done | Webby approves the manifest. The test file passes whole under umask 022 and under umask 077 on Sage's slot. (sage) | `docs/plans/2026-10-21_gate-env-rows.md` § The startup token refusal test sets its file mode | mos-1162: lands after 197 r6, whose proof runs on the unchanged test. |
|
||||
| 244 | Gate runs use a fixture PI_AUTH_FILE (DEFERRED 059577886, Webby N4) | morgana; reviewers webby | — | briefed | 197 done | Webby approves the manifest. The new test and every touched file are green on Sage's slot, along with test-task.sh and test-release.sh. (sage) | `docs/plans/2026-10-21_gate-env-rows.md` § Gate runs use a fixture pi auth file | — |
|
||||
| 243 | process.test.mjs startup token refusal sets its file mode (chmod), umask sweep of packages/*/tests | morgana; reviewers webby | #1754 | done | 197 done | Webby approves the manifest. The test file passes whole under umask 022 and under umask 077 on Sage's slot. (sage) | `docs/plans/2026-10-21_gate-env-rows.md` § The startup token refusal test sets its file mode | LANDED 6096b051b on 9a8c8860d, pushed. Patch-id f9d687dd1d41 equals a36523713..6581f750e; 5 paths, blobs and modes equal the candidate; no drift on those paths since a36523713. Gate: Webby r1 APPROVE rev 2939 (c30111); slot singles (morgana-0041): candidate 4 files whole green at umask 022 and 077, base 077 red only on the predicted tests. |
|
||||
| 244 | Gate runs use a fixture PI_AUTH_FILE (DEFERRED 059577886, Webby N4) | morgana; reviewers webby | #1757 | briefed | 197 done | Webby approves the manifest. The new test and every touched file are green on Sage's slot, along with test-task.sh and test-release.sh. (sage) | `docs/plans/2026-10-21_gate-env-rows.md` § Gate runs use a fixture pi auth file | — |
|
||||
| 245 | row 195 follow-up: Duckworth's N1-N3 on scripts/case1-accept.sh (root never runs an unchecked --node; the header lists what root runs; F6 refuses .. after the claude pin dir) | darkwing; reviewers duckworth | #1693; closes none | done | — | Duckworth approves the manifest. The cli suite and every scripts/test-*.sh are green on Sage's gate, and a mutant for each of N1 and N3 is killed. (sage) | `docs/plans/2026-10-20_hub-own-uid.md` § Row 195 follow-up: Duckworth's N1-N3 on the Case 1 acceptance script | LANDED 6d5545d44 on 856c1826b, pushed. Patch-id 36a621ac3966 equals 62ddc96cc..ef8b4439e. Gate: Duckworth r1 APPROVE rev 2849; N1 mutants 13-15 and N3 mutant 16 killed (sage-1961, darkwing-0107); Sage gate 12:24-12:35Z: case1-accept alone 23/0, cli 681/0, scripts/test-*.sh 429/0. Lands before row 246 as the brief asks. #1693 stays open for 246. |
|
||||
| 246 | row 195 window: the Case 1 acceptance run on 10.1.1.53 (carries row 195's done condition; needs a Jason or Mos go) | darkwing; reviewers duckworth | #1693 | queued | 226 done, 245 done | The window's acceptance run passes on .53, Duckworth reads its output, and Mos confirms. (sage) | `docs/plans/2026-10-20_hub-own-uid.md` § Row 195 window: the Case 1 acceptance run on 10.1.1.53 | — |
|
||||
| 247 | Case 2 C2-20b persona import follow-up: printed keys, the dry run fence check and the mkdir race | gosalyn; reviewers webby | #1749 | done | 221 done | Webby approves the manifest. The test file runs green on its own, and the three mutants are killed on Sage's slot. The cli suite and every scripts/test-*.sh are green on Sage's gate. (sage) | `docs/plans/2026-10-20_case2-rows.md` § C2-20b persona import follow-up: printed keys, the dry run fence check and the mkdir race | LANDED 856c1826b on f8276c5eb, pushed. Patch-id 373ab2cc4c50 equals 6d43618a3's. Gate: Webby r1 APPROVE rev 2852; test file alone 14/0 and M1-M4 killed (sage-1971); Sage gate 12:10-12:21Z: file 14/0, cli 680/0, scripts/test-*.sh 429/0. M1/M2 at :248 not :237 (gosalyn-0111). |
|
||||
| 248 | row 235 follow-up: the grant-executor hold-add and hold-remove stubs stop when their test dir is gone (found by the 197 r8 proof) | sage; reviewers webby | #1750 | done | — | Webby approves the commit. On Sage's gate the whole grant-executor.test.mjs passes three times with no stub left, the bus suite is green, and a mutant that drops the dir check leaves a stub. (sage) | `docs/plans/2026-10-20_host-credentials.md` § Machine grant row b follow-up: the held stubs end with their test | LANDED 8a04f4aa4 on refactor, pushed. Temp-index landing of candidate 4d99c178b's one path onto bc579f7a8. No drift on the path since 540239b6b. Patch-id 84974d6b08d6 matches the candidate's. Gate per the brief: Webby APPROVE r1 rev 2883, Sage's gate 13:05-13:07Z (file 3x 37/0 no stub, bus 596/0, mutant left 2). |
|
||||
| 249 | row 235 follow-up: the grant undo records hostLineLeft when install never returned, since the remote add can outlive an abort or timeout (mos-1166) | gizmoduck; reviewers duckworth | #1751 | done | — | Duckworth approves the manifest. On Sage's gate the bus suite and the whole touched test files are green, and a mutant that drops the new catch branch is killed. (sage) | `docs/plans/2026-10-20_host-credentials.md` § Machine grant row b follow-up: the undo can't prove the remote add has ended | LANDED 9de5a57ab on refactor, pushed with 7b9737953 (DEFERRED N1). Range-diff: 8a04f4aa4..05595794b vs 8ca064158..9de5a57ab, same 3 paths, patch-id 99551b122e66 on both. Gate sage-2026 14:53Z: grant-executor whole 39/0, bus 598/0, no stub left, C1 (drop :1025) killed by G8 and both G23. Duckworth approve c30070. |
|
||||
| 250 | K12 (cohort.test.mjs) reads cgroup.events after cgroup.kill under load: print the shim's reason, then fix the cause at the source (Vikunja #450) | gizmoduck; reviewers filbert | #1755 | done | 197 done | reviewer approves the manifest; conversation and control-board suites whole on Sage's slot (sage) | `docs/plans/2026-10-21_k12-cohort-events.md` § Brief: K12 reads cgroup.events after cgroup.kill under load | LANDED 1b6158ce2 on refactor 19:42Z: candidate c1a858975 on 3b0aef995, manifest eca0b8e2, Filbert APPROVE rev 2957 (#1755 c30130). patch-id 29786caa = candidate; blob diff empty; tree 59f1e4781 = merge-tree. Gate on Sage slot sage-2109 (gizmoduck-0150): P1/P2/M1 as predicted, conversation whole 3x 183/183 plus concurrent pair, control-board 124/124. No drift on paths since base. |
|
||||
| 251 | T27 (host-run.test.mjs:453) lists no identities right after ssh-add -t 1: print timing and agent state, then fix the cause at the source (Vikunja #453) | darkwing; reviewers dewey | #1756 | in-review, round 1, request posted | 197 done | reviewer approves the manifest; bus suite whole on Sage's slot (sage) | `docs/plans/2026-10-21_t27-ssh-add-lifetime.md` § Brief: T27 lists no identities right after ssh-add -t 1 | mos-1185 item 2. If proof 6 fails outside 197's paths in a pair wave, this and row 250 go ahead of 197 (item 4). |
|
||||
| 252 | Console inbox Approve and Deny for grant requests (#435, J2) | gander; reviewers webby | — | briefed | — | Webby approves DESIGN.md then manifest; webui, bus, cli suites and every test-*.sh green on Sage's gate; DESIGN mutants killed; REQ-WEB-2 PRD amendment landed first (sage) | `docs/plans/2026-10-21_console-inbox-approve.md` § Gate | mos-1193. Chained on row 196's candidate (Q177): design starts now on Gander's row 196 build; code rebases onto 196's landing. Vikunja #435. |
|
||||
| 253 | F27: case2-unit.sh and case1-accept.sh move to --tester-socket and refuse --tester-port with stack-release's migration wording; no .53/.54 copy with 196 until this lands (mos-1198 item 4) | gander; reviewers duckworth | #1758 | queued | 196 done | reviewer approves DESIGN.md then the manifest; cli and webui suites whole and every scripts/test-*.sh on Sage's slot; mutants per DESIGN.md; static check covers scripts and tests (sage) | `docs/plans/2026-10-21_tester-socket-scripts.md` § Brief: case2-unit.sh and case1-accept.sh move to --tester-socket (F27) | — |
|
||||
|
||||
<!-- mosaic-queue:end -->
|
||||
|
||||
|
||||
+2087
-39
File diff suppressed because one or more lines are too long
@@ -88,6 +88,7 @@ export const TASK_PAGE_MAX = 200;
|
||||
// Row 148 (#1642): the human-only verbs behind the Console's document editor. The save is the one
|
||||
// request allowed past the ordinary 64 KiB envelope (server.mjs and client.mjs), up to its content cap.
|
||||
export const PROJECT_FILE_VERBS = Object.freeze(['project.files', 'project.file', 'project.file.save']);
|
||||
export const LIBRARY_VERBS = Object.freeze(['library.file', 'library.status']);
|
||||
export const PROJECT_SAVE_VERB = 'project.file.save';
|
||||
export const PROJECT_SAVE_REQUEST_MAX = 1024 * 1024 + 64 * 1024;
|
||||
export const WEB_VERBS =Object.freeze(['web.search', 'web.fetch']);
|
||||
@@ -279,6 +280,7 @@ export class Broker {
|
||||
#organization;
|
||||
#credentialVerbs;
|
||||
#project;
|
||||
#library;
|
||||
#usage;
|
||||
#limits;
|
||||
#harnessOn;
|
||||
@@ -294,7 +296,7 @@ export class Broker {
|
||||
#stops = new Map();
|
||||
#clock = 0;
|
||||
// credentialStatus is the runtime's metadata-only Credentials.status(); the broker never gets use().
|
||||
constructor({ store, businesses, secretCheck = () => {}, credentialStatus = () => [], organization = null, project = null, usage = null, limits = null, harnessOn = null, credentialVerbs = null, hostGrant = null, hostKeys = null }) {
|
||||
constructor({ store, businesses, secretCheck = () => {}, credentialStatus = () => [], organization = null, project = null, library = null, usage = null, limits = null, harnessOn = null, credentialVerbs = null, hostGrant = null, hostKeys = null }) {
|
||||
if (!object(businesses) || !Object.keys(businesses).length) fail('invalid-business');
|
||||
this.#businesses = structuredClone(businesses);
|
||||
this.#store = store;
|
||||
@@ -306,6 +308,7 @@ export class Broker {
|
||||
this.#hostGrant = hostGrant;
|
||||
this.#hostKeys = hostKeys;
|
||||
this.#project = project;
|
||||
this.#library = library;
|
||||
this.#usage = usage;
|
||||
this.#limits = limits;
|
||||
// Row 65: harnessOn(business, name) is true when the organization file's plugins.harness switches
|
||||
@@ -2192,6 +2195,8 @@ export class Broker {
|
||||
return this.#requestProject(s, { verb: request.verb, args: structuredClone(args) });
|
||||
if (PROJECT_FILE_VERBS.includes(request.verb))
|
||||
return this.#requestProjectFile(s, { verb: request.verb, args: structuredClone(args) });
|
||||
if (LIBRARY_VERBS.includes(request.verb))
|
||||
return this.#requestLibrary(s, { verb: request.verb, args: structuredClone(args) });
|
||||
if (CREDENTIAL_VERBS.includes(request.verb)) return this.#requestCredential(s, request.verb, structuredClone(args));
|
||||
if (["limits", "limits.set", "organization.set", "organization.revision", "plugins", "plugins.set", "instances", "instances.set", "routes", "routes.set"].includes(request.verb)) {
|
||||
// Row 123 (#1617, REQ-COS-1, REQ-LIMIT-1): organization.set is limits.set for a role whose
|
||||
@@ -2441,6 +2446,26 @@ export class Broker {
|
||||
throw this.#refused(s, ProjectFailure && e instanceof ProjectFailure ? new BusError(e.code) : e, request);
|
||||
}
|
||||
}
|
||||
// C2-04 M4: only a verified human reads library text or status. Host Git
|
||||
// functions stay injected, preserving this module's sandbox import closure.
|
||||
async #requestLibrary(s, request) {
|
||||
const { verb, args } = request;
|
||||
try {
|
||||
this.#human(s);
|
||||
const fields = verb === 'library.file' ? ['project', 'path'] : ['project'];
|
||||
keys(args, fields, fields);
|
||||
if (!this.#library?.readFile || !this.#library?.status) fail('project-not-configured');
|
||||
const context = { business: this.#business(s.business), project: args.project };
|
||||
const result = verb === 'library.file'
|
||||
? await this.#library.readFile({ ...context, path: args.path })
|
||||
: await this.#library.status(context);
|
||||
this.#secretCheck(result);
|
||||
return result;
|
||||
} catch (error) {
|
||||
const Failure = this.#library?.LibraryError;
|
||||
throw this.#refused(s, Failure && error instanceof Failure ? new BusError(error.code) : error, request);
|
||||
}
|
||||
}
|
||||
// The eight task verbs reach the trusted S3 handler here. It runs outside any transaction, gets the
|
||||
// cap to authorize and record through authorize() and recordTask(); refusals are recorded as in request().
|
||||
async requestTask(cap, request, handler) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { join } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { Store } from './store.mjs';
|
||||
import * as projectModule from '../../project/src/index.mjs';
|
||||
import * as libraryModule from '../../library/src/index.mjs';
|
||||
import { Broker, BusError } from './broker.mjs';
|
||||
import { Credentials } from './credentials.mjs';
|
||||
import { serve } from './server.mjs';
|
||||
@@ -92,7 +93,7 @@ export async function startBroker({
|
||||
const protectedRoots = [
|
||||
fileURLToPath(new URL('../../../', import.meta.url)),
|
||||
...repoRoots,
|
||||
...Object.values(businesses).flatMap((b) => Object.values(b.projects ?? {}).map((p) => p.root)),
|
||||
...Object.values(businesses).flatMap((b) => Object.values(b.projects ?? {}).filter(p => p.kind !== 'library').map((p) => p.root)),
|
||||
];
|
||||
// Row 199 (#1697, design D1): the per-agent store is <configDir>/secrets/agents.
|
||||
const storeRoot = organization ? join(organization.dir, 'secrets', 'agents') : null;
|
||||
@@ -128,6 +129,11 @@ export async function startBroker({
|
||||
const withTokens = (id, result) => ({ ...result, tokens: limits.report(id) });
|
||||
// Row 210 (#1707, design D7 step 6) and row 234 (#1740, r6 E2): the run dir and the host enrollment half.
|
||||
const runRoot = organization ? join(organization.dir, 'secrets', 'run') : null;
|
||||
// C2-04: mirrors are host state, never session checkouts. An unsafe
|
||||
// existing mirror refuses startup before a socket can become ready.
|
||||
for (const business of Object.values(businesses))
|
||||
for (const [project, entry] of Object.entries(business.projects ?? {}))
|
||||
if (entry.kind === 'library') await libraryModule.ensureMirror({ business, project, dataRoot });
|
||||
const broker = new Broker({
|
||||
hostGrant: runRoot ? hostGrant({ configDir: organization.dir, runRoot }) : null,
|
||||
// Row 235 (#1741, r6 X4, X5): the grant executor's claim, register and issue, never use().
|
||||
@@ -136,6 +142,11 @@ export async function startBroker({
|
||||
limits,
|
||||
store,
|
||||
businesses,
|
||||
library: {
|
||||
readFile: context => libraryModule.readLibraryFile({ ...context, dataRoot }),
|
||||
status: context => libraryModule.libraryStatus({ ...context, dataRoot }),
|
||||
LibraryError: libraryModule.LibraryError,
|
||||
},
|
||||
project: {
|
||||
readSpec: context => projectModule.readSpec({ ...context, dataRoot }),
|
||||
writeRecord: context => projectModule.writeRecord({ ...context, dataRoot }),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createServer } from 'node:net';
|
||||
import { lstatSync, chmodSync, unlinkSync } from 'node:fs';
|
||||
import { BusError, TASK_VERBS, WEB_VERBS, HOST_VERBS, HOSTS_VERBS, PROJECT_FILE_VERBS, PROJECT_SAVE_VERB, PROJECT_SAVE_REQUEST_MAX } from './broker.mjs';
|
||||
import { BusError, TASK_VERBS, WEB_VERBS, HOST_VERBS, HOSTS_VERBS, PROJECT_FILE_VERBS, LIBRARY_VERBS, PROJECT_SAVE_VERB, PROJECT_SAVE_REQUEST_MAX } from './broker.mjs';
|
||||
const LIMIT = 65536;
|
||||
// Row 148: a document save may carry up to 1 MiB of text. Only a request that names that verb near
|
||||
// its start (the proof object comes first) may pass LIMIT; the parsed verb is checked again below.
|
||||
@@ -122,7 +122,7 @@ export async function serve({ broker, path, authenticateHuman = null, authentica
|
||||
}
|
||||
// Row138: only project Git effects need an await; preserve every other sync path below.
|
||||
if (r.verb === 'usage.begin' || r.verb === 'usage.end' ||
|
||||
r.verb === 'spec.read' || r.verb === 'record.write' || PROJECT_FILE_VERBS.includes(r.verb) ||
|
||||
r.verb === 'spec.read' || r.verb === 'record.write' || PROJECT_FILE_VERBS.includes(r.verb) || LIBRARY_VERBS.includes(r.verb) ||
|
||||
// Row 234 (#1740): a grant raise awaits its keyscan, and hosts.check its ssh.
|
||||
HOSTS_VERBS.includes(r.verb) ||
|
||||
(r.verb === 'decision.raise' && (Object.hasOwn(r.args ?? {}, 'spec_path') || Object.hasOwn(r.args ?? {}, 'spec_commit') ||
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
// C2-04 M4 and real async transport, with made-up local library data.
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
import { Store } from '../src/store.mjs';
|
||||
import { Broker } from '../src/broker.mjs';
|
||||
import { serve } from '../src/server.mjs';
|
||||
import { Client } from '../src/client.mjs';
|
||||
import { startBroker } from '../src/runtime.mjs';
|
||||
import { mappingEntry, repo, git, BASE, MARKER } from '../../library/tests/helpers.mjs';
|
||||
import * as library from '../../library/src/index.mjs';
|
||||
|
||||
function world(t, adapter = {}) {
|
||||
const root = mkdtempSync(join(tmpdir(), 'bus-library-')), store = new Store(root);
|
||||
t.after(() => { store.close(); rmSync(root, { recursive: true, force: true }); });
|
||||
const business = { id: 'acme', human: 'jason', vars: { 'bus.tester': true },
|
||||
projects: { books: mappingEntry() }, arbiters: { technical: 'coder', delivery: 'coder' }, roles: { coder: { authority: { withinRole: [], crossRole: [] } } } };
|
||||
const broker = new Broker({ store, businesses: { acme: business }, library: adapter });
|
||||
const human = broker.bindHuman({ business: 'acme', human: 'jason', via: 'cli', outsideAgent: true });
|
||||
const agent = broker.bindLaunch({ business: 'acme', role: 'coder', run: 'library-agent', harness: 'pi' });
|
||||
const reader = broker.bindReader({ business: 'acme' }), tester = broker.bindTester({ business: 'acme' });
|
||||
const call = (cap, verb, args = {}) => Promise.resolve().then(() => broker.request(cap, { verb, args }));
|
||||
return { root, store, broker, business, human, agent, reader, tester, call };
|
||||
}
|
||||
|
||||
test('C2-04 M4: both verbs reject every agent before arguments or adapter access', async t => {
|
||||
let touched = 0;
|
||||
const f = world(t, { readFile: () => { touched++; }, status: () => { touched++; } });
|
||||
for (const verb of ['library.file', 'library.status']) {
|
||||
await assert.rejects(f.call(f.agent, verb, { unknown: true }), { code: 'human-required' });
|
||||
await assert.rejects(f.call(f.tester, verb, { unknown: true }), { code: 'human-required' });
|
||||
await assert.rejects(f.call(f.reader, verb, { unknown: true }), { code: 'read-only' });
|
||||
}
|
||||
assert.equal(touched, 0);
|
||||
const refusals = f.store.all("SELECT body FROM events WHERE kind='action.refused'").map(row => JSON.parse(row.body));
|
||||
assert.equal(refusals.length, 6);
|
||||
assert.equal(JSON.stringify(refusals).includes('unknown'), false);
|
||||
const absent = world(t, null);
|
||||
for (const verb of ['library.file', 'library.status'])
|
||||
await assert.rejects(absent.call(absent.agent, verb, {}), { code: 'human-required' });
|
||||
});
|
||||
|
||||
test('C2-04 bus: human reads validate keys and return adapter results without path leakage', async t => {
|
||||
const seen = [];
|
||||
const f = world(t, { readFile: async args => { seen.push(args); return { project: 'books', path: 'Book One/A.md', commit: 'a'.repeat(40), content: '# Made up\n' }; },
|
||||
status: async args => { seen.push(args); return { project: 'books', served: null, problems: [] }; }, LibraryError: library.LibraryError });
|
||||
assert.equal((await f.call(f.human, 'library.file', { project: 'books', path: 'Book One/A.md' })).content, '# Made up\n');
|
||||
assert.equal((await f.call(f.human, 'library.status', { project: 'books' })).served, null);
|
||||
assert.equal(seen[0].business.id, 'acme'); assert.equal(seen[1].project, 'books');
|
||||
for (const [verb, args] of [['library.file', { project: 'books' }], ['library.file', { project: 'books', path: 'Book One/A.md', commit: 'a'.repeat(40) }], ['library.status', { project: 'books', extra: 1 }]])
|
||||
await assert.rejects(f.call(f.human, verb, args), { code: 'invalid-request' });
|
||||
});
|
||||
|
||||
test('C2-04 socket: each async library verb resolves its result rather than serializing {}', async t => {
|
||||
const f = world(t, { readFile: async () => ({ project: 'books', path: 'Book One/A.md', commit: 'a'.repeat(40), content: '# Fixture\n' }),
|
||||
status: async () => ({ project: 'books', served: null, problems: [] }), LibraryError: library.LibraryError });
|
||||
const path = join(f.root, 'bus.sock');
|
||||
const server = await serve({ broker: f.broker, path, authenticateHuman: () => f.broker.bindHuman({ business: 'acme', human: 'jason', via: 'cli', outsideAgent: true }) });
|
||||
t.after(() => server.close());
|
||||
const human = new Client({ path, human: { fixture: true } });
|
||||
assert.deepEqual(await human.call('library.status', { project: 'books' }), { project: 'books', served: null, problems: [] });
|
||||
assert.equal((await human.call('library.file', { project: 'books', path: 'Book One/A.md' })).content, '# Fixture\n');
|
||||
});
|
||||
|
||||
test('C2-04 runtime: protectedRoots skips library but retains real code-root credential protection', async t => {
|
||||
const f = repo(t), dataRoot = join(f.root, 'data'), token = join(f.root, 'fixture-token');
|
||||
mkdirSync(dataRoot, { mode: 0o700 }); writeFileSync(token, 'made-up-fixture-token-123456', { mode: 0o600 });
|
||||
const business = { id: 'acme', human: 'jason', projects: { books: mappingEntry(), stack: { root: f.repo } },
|
||||
arbiters: { technical: 'coder', delivery: 'coder' }, roles: { coder: { authority: { withinRole: [], crossRole: [] }, credentials: { gitea: { file: token, rotateBy: '2099-01-01' } } } } };
|
||||
const runtime = await startBroker({ dataRoot, businesses: { acme: business } });
|
||||
await runtime.close();
|
||||
const mirror = library.mirrorPath({ business, project: 'books', dataRoot });
|
||||
assert.equal(git(mirror, 'rev-parse', '--is-bare-repository'), 'true');
|
||||
const bad = join(f.repo, 'credential'); writeFileSync(bad, 'made-up-fixture-token-123456', { mode: 0o600 });
|
||||
business.roles.coder.credentials.gitea.file = bad;
|
||||
await assert.rejects(startBroker({ dataRoot, businesses: { acme: business } }));
|
||||
});
|
||||
|
||||
test('C2-04 runtime: unsafe existing mirror refuses boot and never publishes a socket', async t => {
|
||||
const f = repo(t), dataRoot = join(f.root, 'data');
|
||||
mkdirSync(dataRoot, { mode: 0o700 });
|
||||
const business = { id: 'acme', human: 'jason', projects: { books: mappingEntry() }, arbiters: { technical: 'coder', delivery: 'coder' }, roles: { coder: { authority: { withinRole: [], crossRole: [] } } } };
|
||||
const mirror = join(dataRoot, 'projects/acme/books'); mkdirSync(mirror, { recursive: true });
|
||||
writeFileSync(join(mirror, 'keep'), 'made-up note');
|
||||
await assert.rejects(startBroker({ dataRoot, businesses: { acme: business } }), { code: 'library-git' });
|
||||
assert.equal(existsSync(join(dataRoot, 'bus.sock')), false);
|
||||
assert.equal(readFileSync(join(mirror, 'keep'), 'utf8'), 'made-up note');
|
||||
});
|
||||
|
||||
test('C2-04 runtime: real library adapters reach the socket and lock waits leave other bus reads responsive', { timeout: 15000 }, async t => {
|
||||
const f = repo(t), dataRoot = join(f.root, 'data');
|
||||
mkdirSync(dataRoot, { mode: 0o700 });
|
||||
const business = { id: 'acme', human: 'jason', projects: { books: mappingEntry() }, arbiters: { technical: 'coder', delivery: 'coder' }, roles: { coder: { authority: { withinRole: [], crossRole: [] } } } };
|
||||
const runtime = await startBroker({ dataRoot, businesses: { acme: business } });
|
||||
t.after(() => runtime.close());
|
||||
const cap = runtime.broker.bindHuman({ business: 'acme', human: 'jason', via: 'cli', outsideAgent: true });
|
||||
const path = join(f.root, 'human-fixture.sock');
|
||||
const server = await serve({ broker: runtime.broker, path, authenticateHuman: () => runtime.broker.bindHuman({ business: 'acme', human: 'jason', via: 'cli', outsideAgent: true }) }); t.after(() => server.close());
|
||||
const human = new Client({ path, human: { fixture: true } });
|
||||
assert.equal((await human.call('library.status', { project: 'books' })).served, null);
|
||||
const mirror = library.mirrorPath({ business, project: 'books', dataRoot });
|
||||
git(f.repo, '-c', 'protocol.file.allow=always', 'push', '-q', mirror, 'HEAD:refs/heads/served');
|
||||
writeFileSync(join(mirror, library.SYNC_STATE_FILE), JSON.stringify({ version: 1, branch: 'main', served: f.commit,
|
||||
lastFetch: null, lastError: null, diverged: null, problems: [] }), { mode: 0o600 });
|
||||
const file = await human.call('library.file', { project: 'books', path: 'Book One/Characters/Tomas.md' });
|
||||
assert.equal(file.content, BASE['Book One/Characters/Tomas.md']);
|
||||
assert.equal(file.commit, f.commit);
|
||||
let release, done = false;
|
||||
const hold = library.withLibraryLock(mirror, () => new Promise(r => { release = r; }));
|
||||
const deadline = Date.now() + 5000;
|
||||
while (!release && Date.now() < deadline) await new Promise(r => setTimeout(r, 5));
|
||||
assert.equal(typeof release, 'function');
|
||||
t.after(async () => { release(); await hold; });
|
||||
const pending = human.call('library.status', { project: 'books' }).then(result => { done = true; return result; });
|
||||
const ordinary = await Promise.race([human.call('agents'), new Promise((_, reject) => {
|
||||
const timer = setTimeout(() => reject(Error('ordinary bus read blocked by lock acquisition')), 1000); timer.unref();
|
||||
})]);
|
||||
assert.ok(ordinary && typeof ordinary === 'object'); assert.equal(done, false);
|
||||
release(); await hold;
|
||||
assert.equal((await pending).served, f.commit);
|
||||
});
|
||||
@@ -1,7 +1,7 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { fork } from 'node:child_process';
|
||||
import { mkdtempSync, rmSync, existsSync, writeFileSync, mkdirSync, readFileSync } from 'node:fs';
|
||||
import { mkdtempSync, rmSync, existsSync, writeFileSync, mkdirSync, readFileSync, chmodSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
import { once } from 'node:events';
|
||||
@@ -74,6 +74,8 @@ test('startup token refusal returns safe code without value or partial listening
|
||||
const secret = 'fixture-token-never-in-db-948723';
|
||||
const file = join(root, 'secret');
|
||||
writeFileSync(file, secret, { mode: 0o644 });
|
||||
// writeFileSync applies the umask; chmod sets the too-open mode under any umask (row 243).
|
||||
chmodSync(file, 0o644);
|
||||
const config = structuredClone(businesses);
|
||||
config.demo.roles.cto.credentials = { gitea: { file, rotateBy: '2099-01-01' } };
|
||||
const { child, logs } = launch(t);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user