Compare commits

..
Author SHA1 Message Date
jason.woltje c8f2bc7233 launchpad: row 255 design, M1 conditions from mos-1666 item 3 in section 1 and P1 2026-10-24 23:38:15 -05:00
jason.woltje 9f60021a00 launchpad: row 255 design, R2 marked rejected per sage-4401 (R1 chosen, M2 dropped) 2026-10-24 23:31:22 -05:00
jason.woltje e29d8ec909 launchpad: row 255 design, bundled Pocket ID for users with no OIDC provider (Q203, #1760, sage-4363) 2026-10-24 23:16:36 -05:00
jason.woltje 78b69e1e68 docs: Vikunja 633 (P7 proxy startup refreshes) and 634 (row 284 N1) per mos-1647. DEFERRED entries, BUILD-LOG line, filing receipt. 2026-10-24 19:18:35 -05:00
jason.woltje 48b89db33b docs: row 284 landed ce0b6ed41 (#1789). BUILD-LOG and SESSIONS lines, DEFERRED Webby N1 (library read path). 2026-10-24 19:15:48 -05:00
jason.woltje 7c8dc20335 queue: revs 4065-4072. Row 284 round 2: Della reopen 4065, in-review 4066, request outcome 4067 (Della's); Sage request posted c31653 (4068-4069); Webby approve c31654 (4070, Webby's). Row 284 landed ce0b6ed41: note 4071, done 4072. 2026-10-24 19:15:41 -05:00
jason.woltje ce0b6ed411 row284: record row329 landed-base rebase pending CLEAR 2026-10-24 18:40:35 -05:00
jason.woltje 97cb9a7630 row284: record import-list passes and nine killed mutants 2026-10-24 18:40:23 -05:00
jason.woltje e908f7ffee row284: record stale queue brief pin and exact import example 2026-10-24 18:40:23 -05:00
jason.woltje 92df71a982 row284: record landed-base rebase and import-derived run plan 2026-10-24 18:40:23 -05:00
jason.woltje 0abec5d2e8 row284: cover absent supporting prefix directly (unrun) 2026-10-24 18:40:23 -05:00
jason.woltje 20996ecd66 row284: supporting lookup scope and served blob IDs (unrun) 2026-10-24 18:40:22 -05:00
jason.woltje 78b932feb6 row284: migrate playground get tests under mos-1330 (unrun) 2026-10-24 18:40:22 -05:00
66 changed files with 1925 additions and 2634 deletions

No files matched your search

+2 -11
View File
@@ -5583,14 +5583,5 @@ claim. Receipts and limitations in agents/lena/work/queue-296/BUILD.md and run-r
2026-10-24 — Magica row329 R2 (#1827): B1 ASCII-only management key fix verified with complete-tree refusals and positive auth control; package66/66,30bus readers261/261,49CLI readers726/726,config55/55, no required skip/failure. N1 corrects R1 bus total to1019; N3 stale-lock guidance and N4 34-code inventory corrected. Two over-selected file runs are recorded separately, with no F7 inference; cause unknown/Vikunja625. Old502 test/helper files byte-identical, slot returned to Sage. Evidence agents/magica/work/queue-329/BUILD.md.
2026-10-24T23:37:46Z | Sage | Row 329 (#1827, P1 pinned model proxy, Magica) LANDED 61ebf2c34, pushed 23:31:27Z 10-24. Before: refactor at 669cdf42c. After: Magica's 4 commits (94cde633e, c65fb34ee, d1f6f2b19, 61ebf2c34) cherry-picked onto 669cdf42c, diff vs the gated tree limited to drift paths, range-diff in scratch. Gate: one unchanged full landing gate in /mnt/storage/scratch/sage-r329l/wt (gate.sh 8b4978887 c8a9bcf94), started 23:08:12Z at load 14.35, GATE GREEN 23:29:14Z at load 8.67, no rerun, no test or timeout edit (mos-1634). Host note: two Codex workers cleaned T3 worktrees from about 23:14Z (mos-1639, Vikunja 632). Approvals: Dewey r2 c31643 rev 4047, Boyd r2 c31642 rev 4048. #1827 comment 31650, closed. Vikunja 237 comment 1109 (stays open for P2-P7); C4 P10 red filed as Vikunja 631. Queue: note rev 4063, done rev 4064, committed b24d917ec. DEFERRED: N2 and R2-N1 bound to row 331, N1 bound to P7. Overlap: row 284 (packages/bus/src/broker.mjs) and row 157 (scripts/mosaic-config.mjs) rebase onto 61ebf2c34 before their gates.
## 2026-10-24 — row332 P3 proxy harness configuration: investigation/test placement
Fethry at c8a9bcf94, per Sage sage-4292 and mos-1616 pi-route amendment. Before: every managed session receives instance-wide provider credentials; harnesses have no transient per-session proxy context; pi preflight checks only its binary. Intended after: proxy-mode isolation, Claude proxy env, pi private run-local route config using environment references only, credential preflight, and business proxy account settings. Design/test plan: agents/fethry/work/queue-332/BUILD.md. Initial tests placed before production changes. No tests run: Sage CLEAR is required and has not arrived. No success/acceptance claim, live change, or dependency landing. Existing proxy issue number requested from Sage; not yet received.
## 2026-10-24 — row332 crash stop, documentation-only checkpoint
Fethry stopped under Mos mos-1630/Jason's T3 crash instruction. No production implementation, tests, probes, mutants or acceptance runs occurred; Sage CLEAR never arrived. Explicit route metadata per sage-4293 is recorded in agents/fethry/work/queue-332/BUILD.md; full state and resumption boundaries are in HANDOFF.md there. Safe crash checkpoint commits documentation/historical plain-text import manifest only; four unrun tests and the import-audit script remain uncommitted. No long jobs restarted, protected branch changes, merges, live changes or further thread messages.
2026-10-24 — Fethry row332 P3 UNRUN implementation checkpoint: optional proxy route per sage-4325 (default Anthropic), transient preflight/bundle/spawn context and serialization split, pi private model file/provider credential requirement. Existing initial RED evidence precedes source changes; only specifically authorized old fixtures updated. GPT wire API value PENDING until separate offline CLEAR/evidence; P2 seam remains injected context, no real proxy/auth access. Not GREEN, not accepted or landed. Details agents/fethry/work/queue-332/BUILD.md.
2026-10-24 — Fethry row332 P3 checkpoint ef0939e35: required explicit route restored per sage-4293/4328; openai-responses chosen by Sage sage-4331 as reasoning-based tie-break, not evidence-decided (both offline shapes passed). Rehashed pinned8.0.42 single active-tool isolated GLM turn confirms thinking/tool_stream survive to stand-in;bundle7/7,proxy-harness5/5,no skips. Real Codex auth proof remains row209 phaseA step7. P2 landing/rebase,mutants,reviews and full gate still pending; no landing claim. Plain evidence/limitations in agents/fethry/work/queue-332/BUILD.md.
2026-10-25T00:15:48Z | Sage | Row 284 (#1789, C2-05c library.get scope, Della) LANDED ce0b6ed41, pushed 00:09:52Z 10-25. Before: refactor at 9e2689dff (row 329 landing docs). After: fast-forward to Della's 7 rebased commits 78b932feb..ce0b6ed41; 8 paths, manifest-r4 de505cfd matches the landed tree. Gate: one unchanged full landing gate in /mnt/storage/scratch/sage-r284l/wt (the 329 gate.sh with D and the compose project renamed), started 23:51:19Z at load 1.62, GATE GREEN 00:09:04Z at load 5.20, no rerun, no test or timeout edit. Counts: bus 1020/0, business 283/0, cli 999 pass 1 allowed skip (FED R7), harness 177/0, library 156/0, seat 218/0, webui 458/0, every scripts/test-*.sh rc 0; queue 34 and task 87/93 skips are the standing ones. Della's whole-file runs on ce0b6ed41: library-lookups 12/0, library-tools 5/0, query 34/0. Approval: Webby round 2 delta c31654 rev 4070 (round 1 rev 4062). Overlap sweep: rows 13, 157, 309, gyro/row310 and fethry/row332-p1 clean. #1789 comment 31655, closed. No Vikunja task for the row. Queue: note rev 4071, done rev 4072, committed 7c8dc2033. DEFERRED: Webby N1 (whole-tree listing per get) bound to the next library read-path row; N2 needs nothing; N3 is this gate.
2026-10-25T00:18:35Z | Sage | Follow-up tasks for mos-1647 item 3 (Q109): Vikunja 633 (P7 cutover, CLIProxyAPI 8.0.42 startup Grok-npm and antigravity version refreshes, from row 332 isolated runs) and 634 (row 284 Webby N1, library get lists the whole tree). DEFERRED gains the 633 entry and the 634 number for row 284 N1. Filing script and receipt in agents/sage/work/vikunja-setup/.
+934
View File
@@ -0,0 +1,934 @@
# Row284 C2-05c — supporting scope and served-tree blob (#1789)
Owner Della; reviewer Dewey; gate Sage. Build start sage-3658/3660 (10-23).
Branch della/row284. Original prerequisite base Honker28346bad7ea3;
merge fc05bcbc3 carries22423816cf28 and2164f3fbc25a intact. Only conflict was
CLI thread-launch's added footer tests: retained both full test bodies and
assertions. No prerequisite code copied. Every prerequisite needs its own
review/mutants/landing under mos1351; rebase after283 lands.
## Execution status
UNTESTED. No Node, node--check, test or mutant run before Sage CLEAR. First
own commit is the authorized old-test migration; the implementation follows.
Sage authorizes an immediate untested push. No queue write or shared-log edit.
224 stays first;284 is critical to Bubba288. T4 for224 is not a CLEAR yet.
## Binding readings
Brief C2-05c at94c33a43c:1737-1789, Q226, sage2918 and mos1330 item3.
get defaults canon; explicit playground/supporting opt-in; mismatch null.
Sort full outgoing/incoming lists supporting, playground, canon before paging,
keep cross-scope links and universe filter. Manuscript stays canon/playground.
No all/array scope, write tool, guard, mapping or creative-name-count change.
## mos-1330 old-test migration (separate commit)
All paths below are packages/library/tests/query.test.mjs. Baseline file at
fc05bcbc3 matches216's file. Source assertions retained; negative calls receive
explicit scope too, so universe isolation cannot pass on default-scope denial.
Call/assertion 348 -> 348:
```js
// OLD
const rin = await get(s, { universe: 'idea', path: 'Drafts/New World/Characters/Rin.md' });
// NEW
const rin = await get(s, { universe: 'idea', path: 'Drafts/New World/Characters/Rin.md', scope: 'playground' });
```
Call/assertion 350 -> 350:
```js
// OLD
assert.equal(await get(s, { universe: 'harbor', path: 'Drafts/New World/Characters/Rin.md' }), null);
// NEW
assert.equal(await get(s, { universe: 'harbor', path: 'Drafts/New World/Characters/Rin.md', scope: 'playground' }), null);
```
Call/assertion 366 -> 366:
```js
// OLD
assert.equal(await get(src(ref, mapping(WITH_BLEND)), { universe: 'blend', path }), null);
// NEW
assert.equal(await get(src(ref, mapping(WITH_BLEND)), { universe: 'blend', path, scope: 'playground' }), null);
```
Call/assertion 367 -> 367:
```js
// OLD
const own = await get(src(ref), { universe: 'harbor', path });
// NEW
const own = await get(src(ref), { universe: 'harbor', path, scope: 'playground' });
```
Assertion 349 retained, OLD == NEW:
```js
assert.equal(rin.scope, 'playground');
```
Assertion 368 retained, OLD == NEW:
```js
assert.equal(own.scope, 'playground');
```
The null assertions at350 and366 are the complete OLD/NEW expressions above:
expectation remains null. Added one separate no-scope playground-get -> null
behavior test. It is unrun and expected to expose old get behavior until the
new scope implementation lands. This migration is authorized by mos1330 under
mos1272; no check removed or weakened. Dewey checks this list in manifest review.
## 283 surface and blob choice
Inspected actual46bad7ea3: optional editor.user is present. reader's parsed
file records and index entries still discard tree oid. In owned query.mjs use
the existing bounded listTree(repo, servedCommit) to obtain exact path oid,
not HEAD and not a user-supplied revision expression. No reader/index edit.
Tradeoff: one additional bounded tree listing per get; latency unmeasured.
Recheck after rebasing to283's actual landing.
## Intended owned paths
query.mjs; broker.mjs lookup branch; tools.mjs lookup schemas/descriptions;
library query.test.mjs/query-fixture.mjs; bus library-lookups.test.mjs;
harness library-tools.test.mjs; this BUILD.md. Other files are prerequisites.
## Gate
Dewey manifest approval, whole library/bus/harness suites and every
scripts/test-*.sh on Sage gate. Before review grep all package tests for enum
pins and canon/playground pairs. Keep shared logs out; send receipts to Sage.
No test or mutant evidence claimed. Manifest/digest follows complete code.
## Implementation head (UNTESTED, sage-3658)
- query scope accepts supporting for find/search/get. get defaults canon,
mismatch null. Manuscript passes a separate two-value scope allowlist.
- get returns blob from listTree(source.repo,index.commit) after scope/universe
filtering. The same index.commit supplies the text; source HEAD is irrelevant.
- Full outgoing and incoming link lists are stably sorted by supporting,
playground,canon before combining/paging. All visible cross-scope links stay;
universe/hybrid visibility still applies. Scope metadata isn't added to links.
- Broker only adds optional scope to library.get's strict fields. No new verbs.
- Typed scope expands find/search/get only; manuscript retains its own two-value
enum. Names/M3 counts remain the row224 six/eight, no write tools added.
- New tests: book/universe/draft supporting find/search/get; defaults/mismatch;
absent supporting prefix; source HEAD advances but each scope's blob equals
served:path; 300 outgoing plus300 incoming links ordered across bounded pages,
retaining cross-scope links and dropping other-universe links; hybrid source
stays canon-only; no all/array scope; manuscript rejects supporting; broker
scope/blob forwarding; typed enums and unchanged names. All unrun.
## Additional old assertion pin (brief Gate)
harness/tests/library-tools.test.mjs:49 at23816cf28 (line49, unchanged in this head):
OLD find scope enum ['canon','playground']; NEW ['canon','playground','supporting'].
This is the exact scope-enum pin the brief directs updating. Existing six/eight
name snapshots and TYPES equality assertion are unchanged. The new manuscript
pin intentionally remains ['canon','playground']. No other two-scope test pin
was found by rg over packages/*/tests at this build's prerequisite merge.
## Proposed mutation evidence (reviewer confirms final set)
All unrun. Require assertion failures with whole-file runs and pristine restore:
M1 remove supporting from query SCOPES -> supporting lookup cases.
M2 drop get's requested-scope comparison -> default/mismatch null cases.
M3 use source HEAD for blob lookup -> served-tree/advanced-HEAD equality case.
M4 remove link rank sort -> multi-page outgoing/incoming expected order.
M5 restrict links to requested scope -> cross-scope link counts/order case.
M6 drop sees() from visible/link filtering -> second-universe/hybrid cases.
M7 allow supporting in manuscript validator -> manuscript refusal case.
M8 omit get scope from broker fields -> real broker supporting get case.
M9 widen typed manuscript enum -> typed-scope separation case.
## Inspection and pending gate
No production imports change in broker/tools, so no new sandbox closure file
or mount. query.mjs is host library code and adds existing reader.listTree;
no new package/export/copy-path file. rg found the one old find scope pin plus
the intentional new manuscript two-scope pin. Whole library/bus/harness and
shell gates remain required. CLI integration/merge context is prerequisite224/
219, not this row's source delta; any changed gate expectation goes to Sage.
Node checks, tests, mutants and elapsed-time evidence remain absent pending
CLEAR. The first test-migration commit and this implementation are distinct.
Sage sweep receipt: Della row284 builds on28346bad7ea3 plus intact224 merge;
mos1330 old-test migration separate, supporting scope/blob implementation and
fixtures authored, completely UNTESTED. No shared-log/queue write or live action.
## Current assertion anchors after implementation imports
The separate migration commit0ed4fbab9 retains its complete OLD/NEW text
above. Adding only the fs/path imports in the implementation shifts anchors:
query.test.mjs:130: `const blendCh2 = await get(src(ref, mapping(WITH_BLEND)), { universe: 'blend', path: 'Book One/Chapters/Chapter 02.md' });`
query.test.mjs:350: `const rin = await get(s, { universe: 'idea', path: 'Drafts/New World/Characters/Rin.md', scope: 'playground' });`
query.test.mjs:351: `assert.equal(rin.scope, 'playground');`
query.test.mjs:352: `assert.equal(await get(s, { universe: 'harbor', path: 'Drafts/New World/Characters/Rin.md', scope: 'playground' }), null);`
query.test.mjs:368: `assert.equal(await get(src(ref, mapping(WITH_BLEND)), { universe: 'blend', path, scope: 'playground' }), null);`
query.test.mjs:369: `const own = await get(src(ref), { universe: 'harbor', path, scope: 'playground' });`
query.test.mjs:370: `assert.equal(own.scope, 'playground');`
No result/null assertion changed; scope arguments carry the explicit opt-in.
## Dewey dewey-0941 static review — round2
Static scope fc05bcbc3..47db04eba CLEAN; not a final verdict or test evidence.
M1-M9 accepted as the final set. Optional M10 not added to this gate.
N2 taken: keep the existing canon-path supporting-scope mismatch assertion,
and ADD get(Book One/Support/Notes/Helper.md,scope:supporting) -> null under
the default mapping with no supporting prefix. The supporting-positive test
already returns this same path under withSupporting, so the added probe
pins the missing-prefix case directly. No assertion removed or weakened;
mos1330's separate migration commit and its retained assertions unchanged.
N1 proposed DEFERRED/follow-up for Sage: retain each tree oid in reader/index
entries so get can return blob without cat-file/whole ls-tree -r -l per page.
Current get's result is pinned correctly, but per-page cost grows with the
library. No performance measurement yet. This optimization needs reader/index
ownership and separate acceptance/performance evidence; do not silently expand
284's manifest or change its served-snapshot contract for it.
No Node, tests, mutants or syntax checks run in this round; hold still applies.
## sage-4281 — rebase onto landed 224/283, 2026-10-24
New worktree /mnt/storage/scratch/della-row284-r2, branch della/row284-r2,
base refactor 95d4991d20a4ef291c824d37c886eaeaa9be7062. Cherry-picked only
284-owned 0ed4fbab9, 47db04eba, 5d587a552. Range-diff: all three equal, no
conflicts. The separate mos-1330 migration remains its own commit. No 216,
224 or 283 prerequisite commits copied. Old della/row284 remains unchanged.
mos-1584 fixture check: new tests add no businessDoc() with a library. The
harness role() uses landed 224's gitea reference for bean; the library-enabled
CLI chief fixture fix is also upstream. New broker test uses the direct
Broker fixture (no businessDoc/bootConfig), not a new validated organization.
No new made-up credential values are introduced in this row; existing short
fixture references are reused, so no new credential reaches 24 characters.
No credential values were inspected or printed. No fixture edit necessary.
No Node, npm, syntax check, service, test, mutant or install run in this worktree.
No canonical node_modules link. Dependency installation remains a separately
cleared local npm ci if needed; tests wait for Sage CLEAR. For future runs use
shell mktemp -d /mnt/storage/scratch/tmp/XXXXXX and per-child absolute nice 19.
Shared logs unchanged; Sage owns landing receipts.
## Import-derived whole-file run plan (mos-1612)
Walked relative static import/re-export edges and literal dynamic imports
transitively, from each packages/*/tests/**/*.test.mjs to changed query.mjs,
broker.mjs, tools.mjs or query-fixture.mjs. This follows source import edges,
not textual mentions. Example CLI/thread-launch -> Broker; CLI/helpers ->
Broker; webui/serve -> webui/bus -> Broker; harness/bundle -> tools.
Evidence generator and per-test import chains are in
/mnt/storage/scratch/della-row284-r2-evidence/import-run-list.py and .json.
The import-derived set has 260 files; union with the brief's whole library,
bus and harness suites adds files that use subprocesses/source reads instead
of direct imports. Excluded case1-accept.test.mjs by sage-4281. Any dynamic
nonliteral loading or external shell gate is not claimed covered by import
tracing; mandatory package suites and Sage's full script gate remain required.
First focused whole files: library/query.test.mjs; bus/library-lookups.test.mjs;
harness/library-tools.test.mjs. Then the full import-derived/mandatory union
below, each file whole (duplicates need not repeat without a change). This
is a proposed run list for Sage's CLEAR, not authorization to run now.
M1-M9 retain Dewey's agreed specification above; no mutant executed.
Whole-file union:
```text
packages/bus/tests/access-revoke.test.mjs
packages/bus/tests/account-migration.test.mjs
packages/bus/tests/address.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/citation-availability.test.mjs
packages/bus/tests/citation-guard.test.mjs
packages/bus/tests/citation-runtime.test.mjs
packages/bus/tests/comment-cursors.test.mjs
packages/bus/tests/comment-migration.test.mjs
packages/bus/tests/console-decide.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/fire-revokes-grants.test.mjs
packages/bus/tests/gitea-grant-docker.test.mjs
packages/bus/tests/gitea-grant.test.mjs
packages/bus/tests/gitea-migration.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/grant-scope-runtime.test.mjs
packages/bus/tests/grant-scope.test.mjs
packages/bus/tests/hard-waits.test.mjs
packages/bus/tests/host-run.test.mjs
packages/bus/tests/host-tools.test.mjs
packages/bus/tests/human.test.mjs
packages/bus/tests/instances-verb.test.mjs
packages/bus/tests/interpreter.test.mjs
packages/bus/tests/land.test.mjs
packages/bus/tests/launch-notice.test.mjs
packages/bus/tests/launcher-released.test.mjs
packages/bus/tests/library-credential.test.mjs
packages/bus/tests/library-lookups.test.mjs
packages/bus/tests/library-sync.test.mjs
packages/bus/tests/library.test.mjs
packages/bus/tests/lifecycle-revoke.test.mjs
packages/bus/tests/lifecycle-verbs.test.mjs
packages/bus/tests/limit-checks.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/message-filter.test.mjs
packages/bus/tests/messages.test.mjs
packages/bus/tests/messaging.test.mjs
packages/bus/tests/name-migration.test.mjs
packages/bus/tests/names.test.mjs
packages/bus/tests/peer-transport.test.mjs
packages/bus/tests/peercred.test.mjs
packages/bus/tests/plugins-verb.test.mjs
packages/bus/tests/principal.test.mjs
packages/bus/tests/process.test.mjs
packages/bus/tests/processing-runtime.test.mjs
packages/bus/tests/processing-timeout.test.mjs
packages/bus/tests/processing-web.test.mjs
packages/bus/tests/processing.test.mjs
packages/bus/tests/project-await.test.mjs
packages/bus/tests/project-files.test.mjs
packages/bus/tests/project-runtime.test.mjs
packages/bus/tests/publish.test.mjs
packages/bus/tests/reload.test.mjs
packages/bus/tests/replies.test.mjs
packages/bus/tests/requirements.test.mjs
packages/bus/tests/review.test.mjs
packages/bus/tests/revoke-window.test.mjs
packages/bus/tests/room-check.test.mjs
packages/bus/tests/rooms.test.mjs
packages/bus/tests/routes-verb.test.mjs
packages/bus/tests/schema.test.mjs
packages/bus/tests/session-clear.test.mjs
packages/bus/tests/session-compactions.test.mjs
packages/bus/tests/sessions.test.mjs
packages/bus/tests/single-use.test.mjs
packages/bus/tests/spec-migration.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/store.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-claims.test.mjs
packages/bus/tests/thread-migration.test.mjs
packages/bus/tests/thread-shares.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-migration.test.mjs
packages/bus/tests/usage-runtime.test.mjs
packages/bus/tests/usage.test.mjs
packages/bus/tests/user-principal.test.mjs
packages/bus/tests/viewer.test.mjs
packages/bus/tests/web.test.mjs
packages/bus/tests/workflow-roles.test.mjs
packages/business/tests/case1-business-file.test.mjs
packages/business/tests/launch-settings.test.mjs
packages/cli/tests/access-boot.test.mjs
packages/cli/tests/access.test.mjs
packages/cli/tests/app.test.mjs
packages/cli/tests/boot-status.test.mjs
packages/cli/tests/case1-hostcheck.test.mjs
packages/cli/tests/case2-install.test.mjs
packages/cli/tests/case2-persona-import.test.mjs
packages/cli/tests/case2-unit.test.mjs
packages/cli/tests/channel-cli.test.mjs
packages/cli/tests/channel-recovery.test.mjs
packages/cli/tests/cli.test.mjs
packages/cli/tests/compactions-launch.test.mjs
packages/cli/tests/config.test.mjs
packages/cli/tests/credentials.test.mjs
packages/cli/tests/federation-acceptance.test.mjs
packages/cli/tests/follow.test.mjs
packages/cli/tests/git-socket.test.mjs
packages/cli/tests/grants-scope.test.mjs
packages/cli/tests/grants.test.mjs
packages/cli/tests/host.test.mjs
packages/cli/tests/hosts.test.mjs
packages/cli/tests/idle-stop-race.test.mjs
packages/cli/tests/instances.test.mjs
packages/cli/tests/launch-account.test.mjs
packages/cli/tests/launch-limit-checks.test.mjs
packages/cli/tests/launch-limits.test.mjs
packages/cli/tests/launch-routes.test.mjs
packages/cli/tests/launcher.test.mjs
packages/cli/tests/lifecycle.test.mjs
packages/cli/tests/limits-tokens.test.mjs
packages/cli/tests/limits.test.mjs
packages/cli/tests/mark-read.test.mjs
packages/cli/tests/names.test.mjs
packages/cli/tests/notifier.test.mjs
packages/cli/tests/optional-tracker.test.mjs
packages/cli/tests/other-tree.test.mjs
packages/cli/tests/processing-cli.test.mjs
packages/cli/tests/project-name-repo.test.mjs
packages/cli/tests/project.test.mjs
packages/cli/tests/publish-socket.test.mjs
packages/cli/tests/reply-limits.test.mjs
packages/cli/tests/revoke-window.test.mjs
packages/cli/tests/session-clear.test.mjs
packages/cli/tests/session-cli.test.mjs
packages/cli/tests/session-launch.test.mjs
packages/cli/tests/stack-copy.test.mjs
packages/cli/tests/stack-instances.test.mjs
packages/cli/tests/tester-http.test.mjs
packages/cli/tests/tester-reads.test.mjs
packages/cli/tests/tester-threads.test.mjs
packages/cli/tests/tester.test.mjs
packages/cli/tests/thread-cli.test.mjs
packages/cli/tests/thread-launch.test.mjs
packages/cli/tests/thread-revoke.test.mjs
packages/cli/tests/trackers-boot.test.mjs
packages/cli/tests/transport.test.mjs
packages/cli/tests/usage.test.mjs
packages/cli/tests/verbs.test.mjs
packages/harness/tests/bundle.test.mjs
packages/harness/tests/citation-runner.test.mjs
packages/harness/tests/claude-gate.test.mjs
packages/harness/tests/claude-session.test.mjs
packages/harness/tests/creative.test.mjs
packages/harness/tests/gate.test.mjs
packages/harness/tests/git-tools.test.mjs
packages/harness/tests/library-tools.test.mjs
packages/harness/tests/mcp-server.test.mjs
packages/harness/tests/pi-session.test.mjs
packages/harness/tests/raise-domain.test.mjs
packages/harness/tests/runner.test.mjs
packages/harness/tests/skills.test.mjs
packages/harness/tests/spec-tools.test.mjs
packages/harness/tests/tools.test.mjs
packages/library/tests/guard.test.mjs
packages/library/tests/index-build.test.mjs
packages/library/tests/links.test.mjs
packages/library/tests/mapping.test.mjs
packages/library/tests/mirror.test.mjs
packages/library/tests/query.test.mjs
packages/library/tests/reader.test.mjs
packages/library/tests/render.test.mjs
packages/library/tests/scope.test.mjs
packages/library/tests/supporting.test.mjs
packages/library/tests/survey.test.mjs
packages/library/tests/sync.test.mjs
packages/processing-control/tests/task.test.mjs
packages/seat/tests/sandbox.test.mjs
packages/seat/tests/session.test.mjs
packages/tasks/tests/adapter.test.mjs
packages/tasks/tests/comment-restart.test.mjs
packages/tasks/tests/fields.test.mjs
packages/tasks/tests/processing.test.mjs
packages/tasks/tests/shapes.test.mjs
packages/tasks/tests/startup.test.mjs
packages/tasks/tests/sync.test.mjs
packages/tasks/tests/tree.test.mjs
packages/tasks/tests/verbs.test.mjs
packages/webui/tests/agents-browser.test.mjs
packages/webui/tests/agents.test.mjs
packages/webui/tests/assistant.test.mjs
packages/webui/tests/board-held.test.mjs
packages/webui/tests/browser-edge.test.mjs
packages/webui/tests/browser.test.mjs
packages/webui/tests/bus-browser.test.mjs
packages/webui/tests/bus.test.mjs
packages/webui/tests/channel-chat.test.mjs
packages/webui/tests/chat-browser.test.mjs
packages/webui/tests/chat-instances.test.mjs
packages/webui/tests/chat-replies-browser.test.mjs
packages/webui/tests/chat-sessions-access.test.mjs
packages/webui/tests/chat.test.mjs
packages/webui/tests/conversation.test.mjs
packages/webui/tests/decide-browser.test.mjs
packages/webui/tests/decide-sso.test.mjs
packages/webui/tests/decision-http.test.mjs
packages/webui/tests/discord.test.mjs
packages/webui/tests/docs-browser.test.mjs
packages/webui/tests/editor-browser.test.mjs
packages/webui/tests/editor.test.mjs
packages/webui/tests/granted-user.test.mjs
packages/webui/tests/history-return-flow.test.mjs
packages/webui/tests/instances-browser.test.mjs
packages/webui/tests/instances.test.mjs
packages/webui/tests/library-cli.test.mjs
packages/webui/tests/library-routes.test.mjs
packages/webui/tests/library-status.test.mjs
packages/webui/tests/limits-browser.test.mjs
packages/webui/tests/limits-route.test.mjs
packages/webui/tests/messages.test.mjs
packages/webui/tests/pinned-copy.test.mjs
packages/webui/tests/preview.test.mjs
packages/webui/tests/processing-browser.test.mjs
packages/webui/tests/processing.test.mjs
packages/webui/tests/project-file.test.mjs
packages/webui/tests/project-name-repo.test.mjs
packages/webui/tests/proof-cli.test.mjs
packages/webui/tests/proof.test.mjs
packages/webui/tests/reads.test.mjs
packages/webui/tests/relaunch.test.mjs
packages/webui/tests/return-flow.test.mjs
packages/webui/tests/room-browser.test.mjs
packages/webui/tests/room-http.test.mjs
packages/webui/tests/routes-browser.test.mjs
packages/webui/tests/routes.test.mjs
packages/webui/tests/send-browser.test.mjs
packages/webui/tests/send.test.mjs
packages/webui/tests/serve.test.mjs
packages/webui/tests/settings-form.test.mjs
packages/webui/tests/settings-write.test.mjs
packages/webui/tests/shell.test.mjs
packages/webui/tests/sso-browser.test.mjs
packages/webui/tests/sso.test.mjs
packages/webui/tests/tester-browser.test.mjs
packages/webui/tests/tester-cli.test.mjs
packages/webui/tests/tester-listener.test.mjs
packages/webui/tests/tester-socket.test.mjs
packages/webui/tests/thread-claims-browser.test.mjs
packages/webui/tests/thread-claims.test.mjs
packages/webui/tests/thread-sharing.test.mjs
packages/webui/tests/usage-browser.test.mjs
packages/webui/tests/usage.test.mjs
packages/webui/tests/user-option-swap.test.mjs
packages/webui/tests/views.test.mjs
```
Queue next on 2026-10-24 names row284 but reports the whole brief differs
from its queue pin and asks the lead to re-pin. Sage-4281 names 5e8a720b and
says the section is unchanged; awaiting lead resolution of the queue pin
before the start move. No queue policy refusal is bypassed.
## sage-4289 lane B — completed verification, 2026-10-24
Current reviewer is Webby under mos-1614 / sage-4284, replacing Dewey.
Dewey's earlier static readings and agreed M1-M9 remain historical evidence.
Row284 claimed in-progress rev4038, op della-284-start-1 after lead re-pin.
Candidate tested: 2f1a6bd93e5fc602c46ee5f770d19adecde5fc11. No code,
fixture or assertion change during verification. Local npm ci used the exact
lockfile, ignore-scripts/no-audit/no-fund, rc0,128 packages; no canonical
node_modules link. Installer receipt and log are in the evidence directory.
Run list sent in full to Sage before starting (della-0058); source is the
import walk documented above, union mandatory package suites,279 whole files.
Three targeted files first, then M1-M9 with byte-exact restore after each,
then remaining276 whole files. Already-passed unchanged targeted files are
not repeated. Every Node invocation used fresh shell gXXX TMPDIR,29 bytes,
absolute nice19 set in the child before exec, timeout -k10 (900-second cap,
shortened automatically near23:45Z hardstop). All timeout nice observations
were19. Normal run total1067.962s; mutant total19.485s. Completed22:34Z.
| Package | Whole files | Pass | Fail | Skip |
| --- | ---: | ---: | ---: | ---: |
| bus | 114 | 1012 | 0 | 0 |
| business | 2 | 25 | 0 | 0 |
| cli | 58 | 610 | 0 | 1 |
| harness | 15 | 177 | 0 | 0 |
| library | 12 | 156 | 0 | 0 |
| processing-control | 1 | 7 | 0 | 0 |
| seat | 2 | 23 | 0 | 0 |
| tasks | 9 | 95 | 0 | 0 |
| webui | 66 | 396 | 0 | 0 |
Totals:279 whole files,2501 passed,0 failed,1 skipped,0 cancelled.
Sole skip: packages/cli/tests/federation-acceptance.test.mjs,
FED R7 scratch two-instance acceptance, directs running
scripts/test-federation-acceptance.sh. That acceptance was not exercised;
Sage's full shell landing gate is separate. case1-accept.test.mjs excluded
as ordered. No unlisted run or extra mutant. Targeted counts: query34/34,
broker12/12,typed tools5/5,zero skips.
M1-M9 all killed with exit1, no syntax/setup failures. M1 and M8 are expected
behavior errors when a required capability is removed; the others fail
assertions/refusal checks. Killing named tests are recorded below. Each
restored original bytes in finally; git diff --stat and status --porcelain
empty after every mutant and again after all normal runs, before receipts.
No extra post-restore test rerun.
| Mutant | Killing behavior oracle | Restored |
| --- | --- | --- |
| M1 | supporting find/search/get | byte-exact, clean |
| M2 | get without scope returns null | byte-exact, clean |
| M3 | each get blob equals its served tree object | byte-exact, clean |
| M4 | full outgoing and incoming links stay in scope order | byte-exact, clean |
| M5 | full outgoing and incoming links stay in scope order | byte-exact, clean |
| M6 | full outgoing and incoming links stay in scope order | byte-exact, clean |
| M7 | manuscript still refuses supporting | byte-exact, clean |
| M8 | broker forwards supporting scope | byte-exact, clean |
| M9 | scope schemas expand only find/search/get | byte-exact, clean |
Post-run sweep: current OS user's executable names node/nodejs/chromium/
chrome, matching cwd or argv paths under this worktree or any run TMPDIR.
Checked289 unique roots;0 matching live processes. No signals sent, no
other seat's process inspected beyond process identity/path matching.
No full argv, environment or credential values printed. Slot returned to
Sage in della-0059 at22:34Z. No further tests.
Evidence: /mnt/storage/scratch/della-row284-r2-evidence/run-4289 contains
install receipt, exact commands, stdout/stderr per whole-file run, mutant
edits/restores, summaries and hashed logs. The following plain-text ledger
freezes commands and results; raw logs remain available for reviewer checks.
Each normal test path below was run whole; hashes are SHA256 of raw logs.
```text
{"label":"target-query","command":["timeout","-k","10","900","node","--test","packages/library/tests/query.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gUgw","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":2.889,"mutant":false,"tests":34,"pass":34,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"dc2575e2c597b099c94b7cf254b0cb4d009a0ddb14c0cbd572f93e5ad15f8f72"}
{"label":"target-broker","command":["timeout","-k","10","900","node","--test","packages/bus/tests/library-lookups.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gDd2","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.431,"mutant":false,"tests":12,"pass":12,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"6729e92f2241a2c2d0b725cb9c6ed4fe4d8b50352fd179cf30f905182eac9160"}
{"label":"target-tools","command":["timeout","-k","10","900","node","--test","packages/harness/tests/library-tools.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gmPG","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.169,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"532de351eef39478011d7f84b3b506711c3bafc71676716f623fa29573fc4dec"}
{"label":"M1","command":["timeout","-k","10","900","node","--test","packages/library/tests/query.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gIGt","start_nice":19,"observed_timeout_nice":19,"exit":1,"seconds":2.683,"mutant":true,"tests":34,"pass":30,"fail":4,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"ec36434e918ee16c7639ec0ec4259be66e0381e2684bac7c6ee5755756bded78"}
{"label":"M2","command":["timeout","-k","10","900","node","--test","packages/library/tests/query.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/geid","start_nice":19,"observed_timeout_nice":19,"exit":1,"seconds":2.587,"mutant":true,"tests":34,"pass":31,"fail":3,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"e08eadfd606fc685faed21edb06b1d7d00fd11e7942051fddc0b48b83c6bef90"}
{"label":"M3","command":["timeout","-k","10","900","node","--test","packages/library/tests/query.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gs4j","start_nice":19,"observed_timeout_nice":19,"exit":1,"seconds":2.538,"mutant":true,"tests":34,"pass":33,"fail":1,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"8abb79847deb7a05940c7b48d5407dde6baaf394fef31334f6ac266d65b3c02f"}
{"label":"M4","command":["timeout","-k","10","900","node","--test","packages/library/tests/query.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gvmZ","start_nice":19,"observed_timeout_nice":19,"exit":1,"seconds":2.674,"mutant":true,"tests":34,"pass":33,"fail":1,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"8b8386b876fb85e12335be27216dc5c6a8d5c311c03db0bf49ffbe0639a8693c"}
{"label":"M5","command":["timeout","-k","10","900","node","--test","packages/library/tests/query.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gG6o","start_nice":19,"observed_timeout_nice":19,"exit":1,"seconds":2.633,"mutant":true,"tests":34,"pass":32,"fail":2,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"08ff976a29e42f593dce3262e596e75c43da2ae2e3dfe48945989fe98c3061cf"}
{"label":"M6","command":["timeout","-k","10","900","node","--test","packages/library/tests/query.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gWpu","start_nice":19,"observed_timeout_nice":19,"exit":1,"seconds":2.347,"mutant":true,"tests":34,"pass":23,"fail":11,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"4cd149d0f74e402d2294c2d9ef05aac440ec4c3dc379acad7b9624b7402528bb"}
{"label":"M7","command":["timeout","-k","10","900","node","--test","packages/library/tests/query.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g65B","start_nice":19,"observed_timeout_nice":19,"exit":1,"seconds":2.403,"mutant":true,"tests":34,"pass":33,"fail":1,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"541100f0937dd2e592ed9bee7c48f27ae4e13634d3c0dcf53fc3e8b2f632a000"}
{"label":"M8","command":["timeout","-k","10","900","node","--test","packages/bus/tests/library-lookups.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gtX5","start_nice":19,"observed_timeout_nice":19,"exit":1,"seconds":1.421,"mutant":true,"tests":12,"pass":11,"fail":1,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"2adc93e5aaa663621caa9fd762faded3a975f62de918d7c46a1b5b0469001955"}
{"label":"M9","command":["timeout","-k","10","900","node","--test","packages/harness/tests/library-tools.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gMtM","start_nice":19,"observed_timeout_nice":19,"exit":1,"seconds":0.199,"mutant":true,"tests":5,"pass":4,"fail":1,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"da8c8c2094732b36526dc803e567d4bce18ff964bf70ff406e1981bb7dd313de"}
{"label":"import-001","command":["timeout","-k","10","900","node","--test","packages/bus/tests/access-revoke.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gGcs","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.728,"mutant":false,"tests":10,"pass":10,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"ee78177b9385025df0b0ce154e9f92f3d84a01920da94eb2b95df7aee533721a"}
{"label":"import-002","command":["timeout","-k","10","900","node","--test","packages/bus/tests/account-migration.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/giJX","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.456,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"04456ac702b53d59e127eb7ae2d9828b79acbbcc99c8845cc226e88e4569ffb2"}
{"label":"import-003","command":["timeout","-k","10","900","node","--test","packages/bus/tests/address.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gLUL","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.102,"mutant":false,"tests":15,"pass":15,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"c4ff31db588ac88b6492416d3850b123492e29dbd7c6b2aa283dd736e6caa8cc"}
{"label":"import-004","command":["timeout","-k","10","900","node","--test","packages/bus/tests/agents.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gDuh","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.493,"mutant":false,"tests":11,"pass":11,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"424001894b865c63405976f7facc9a9c93c2ac018b6c97f17ebf87001d071d52"}
{"label":"import-005","command":["timeout","-k","10","900","node","--test","packages/bus/tests/approval-binding.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gsfL","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.305,"mutant":false,"tests":6,"pass":6,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"f8029477d12d0acbd774ec6fa82d9af47ae93c575e0ada16c31130248280431d"}
{"label":"import-006","command":["timeout","-k","10","900","node","--test","packages/bus/tests/broker.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gwdO","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.532,"mutant":false,"tests":16,"pass":16,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"b02528f749bc8367149451f2118cf612f7d46ee6269ad05d9a894d6ef893b727"}
{"label":"import-007","command":["timeout","-k","10","900","node","--test","packages/bus/tests/business.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gX5H","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.102,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"3246c77a5431fda5ee0ef798b9850ee8bf05297c7afa272fc88d148582dc14d8"}
{"label":"import-008","command":["timeout","-k","10","900","node","--test","packages/bus/tests/channel-proof.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g0t2","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.644,"mutant":false,"tests":2,"pass":2,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"d3dc7af8bd80c5cd391a42468cec38fa2cdf4d7bb8d758e84094a255cf2e8626"}
{"label":"import-009","command":["timeout","-k","10","900","node","--test","packages/bus/tests/chief-of-staff.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gAXk","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":2.744,"mutant":false,"tests":42,"pass":42,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"6e355388daee3b3cfe0251abd3f1f1fc56744e26354b8489d8113e4cb4033847"}
{"label":"import-010","command":["timeout","-k","10","900","node","--test","packages/bus/tests/citation-availability.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gNQV","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":5.391,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"fe32f9423c7317c53d0946d6422fb4ea58bcbb0795730b80cba7b5daae47b8ef"}
{"label":"import-011","command":["timeout","-k","10","900","node","--test","packages/bus/tests/citation-guard.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gilj","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.258,"mutant":false,"tests":13,"pass":13,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"1f6c35c535a407a121ec4ee9bb4e9acdc12b5e16e3f8ccf75bcb94a66511b820"}
{"label":"import-012","command":["timeout","-k","10","900","node","--test","packages/bus/tests/citation-runtime.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gjTW","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.331,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"9cb0ab5a64b667f563c827239c242ee77475acb8744e515d8472d839d7190e2e"}
{"label":"import-013","command":["timeout","-k","10","900","node","--test","packages/bus/tests/comment-cursors.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gQvO","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.162,"mutant":false,"tests":2,"pass":2,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"898a7bcc0f68f8a54748a9da6c75b702738b07230a48ff4f939206b1c2dccfdf"}
{"label":"import-014","command":["timeout","-k","10","900","node","--test","packages/bus/tests/comment-migration.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g4nL","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.609,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"ade667dca625e36750417b46f3156be89ec5d40fff78511722c3fa671f3bcd25"}
{"label":"import-015","command":["timeout","-k","10","900","node","--test","packages/bus/tests/console-decide.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/girM","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.893,"mutant":false,"tests":12,"pass":12,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"11a0ac7147f0164542442a9fc6e9224e5d36305cd3e999fc03733e289dfc8f4e"}
{"label":"import-016","command":["timeout","-k","10","900","node","--test","packages/bus/tests/creative.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gXAL","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.447,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"13b107465c7ddecb4fba573b58d4ff42f8807221d1956325b2a0e54eec4581d2"}
{"label":"import-017","command":["timeout","-k","10","900","node","--test","packages/bus/tests/credential-claim.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g8Cy","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.157,"mutant":false,"tests":8,"pass":8,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"a66956b56367cb240de84571fc79e4297bf4bf49c06ce92ac3dd9c5d155b26a5"}
{"label":"import-018","command":["timeout","-k","10","900","node","--test","packages/bus/tests/credential-status.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gEDT","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.401,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"8812b6b0962c7b15e437a9c9b5741d502ab81001d9e17c9b5b14729db8f6033d"}
{"label":"import-019","command":["timeout","-k","10","900","node","--test","packages/bus/tests/credential-store.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gPQx","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.158,"mutant":false,"tests":12,"pass":12,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"2ead3ac9725024e493121f7aaa8e7cf71a35616ffd57c901d3f425ac50b4a8b7"}
{"label":"import-020","command":["timeout","-k","10","900","node","--test","packages/bus/tests/credential-verbs.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g1Wz","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.328,"mutant":false,"tests":2,"pass":2,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"bf447a8e6566816992f48a92e6821441ec1acd86960251aeee4b03b6e4b6dee3"}
{"label":"import-021","command":["timeout","-k","10","900","node","--test","packages/bus/tests/credentials.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/grcF","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.105,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"f3f807e470c8ec40f6c1aea188308a1ca183c8f0e98a0eaea996c96577ab471a"}
{"label":"import-022","command":["timeout","-k","10","900","node","--test","packages/bus/tests/csuite-messaging.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gFHk","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.779,"mutant":false,"tests":16,"pass":16,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"1034823ca51c040db2f0bb18416c67761580ed55df0e60636883bc217878afd5"}
{"label":"import-023","command":["timeout","-k","10","900","node","--test","packages/bus/tests/daily-quota-runtime.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gl0H","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.401,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"95472c3d6b012d38f3db4c790fdd48b710535beee03274c0ea44a2cbd97ed095"}
{"label":"import-024","command":["timeout","-k","10","900","node","--test","packages/bus/tests/decision-close.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g2Iz","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.34,"mutant":false,"tests":8,"pass":8,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"5c855717b19f203797db5b4f2789dd8f8df7d49cbdfee62ae0ffa220e4ed1a4a"}
{"label":"import-025","command":["timeout","-k","10","900","node","--test","packages/bus/tests/decision-route.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gDI5","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.286,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"485577231e6e797c256db8a832d98aca4bf856e47459e0c30a1940598c60b8aa"}
{"label":"import-026","command":["timeout","-k","10","900","node","--test","packages/bus/tests/decisions.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/geqP","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.474,"mutant":false,"tests":7,"pass":7,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"aa887a5b2b30390fab4906cbd2f6ffa4ec37cc9e794478b18e7cd47eb354063b"}
{"label":"import-027","command":["timeout","-k","10","900","node","--test","packages/bus/tests/end-launch.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g5u4","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.414,"mutant":false,"tests":7,"pass":7,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"e3aced744c09beda07405cba691c54a8c8dca973b7718285f67612cbfdad4ac1"}
{"label":"import-028","command":["timeout","-k","10","900","node","--test","packages/bus/tests/fire-revokes-grants.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gD7b","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":4.034,"mutant":false,"tests":24,"pass":24,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"0e79b5a7c00f0701c84b76f3e9fd73f1bac2c9343594039df1e8a667e42d6ea4"}
{"label":"import-029","command":["timeout","-k","10","900","node","--test","packages/bus/tests/gitea-grant-docker.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gcCX","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":25.371,"mutant":false,"tests":2,"pass":2,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"5720e4fc3d58350dc4192c7ceb5dff76aba9bf1aff1ac917e016e7295380b325"}
{"label":"import-030","command":["timeout","-k","10","900","node","--test","packages/bus/tests/gitea-grant.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gIPd","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":12.386,"mutant":false,"tests":66,"pass":66,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"142962fbea6f3602701e4bcc5e0248cb06b98a2fad8bfafb92143a593e535ee6"}
{"label":"import-031","command":["timeout","-k","10","900","node","--test","packages/bus/tests/gitea-migration.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gPFr","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.443,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"2a3d38fa696805a193460d33bfec2461778463b7087e368b738700c583ad23c3"}
{"label":"import-032","command":["timeout","-k","10","900","node","--test","packages/bus/tests/grant-enroll.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gAeL","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.838,"mutant":false,"tests":24,"pass":24,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"fc5d1d86af5c0689eb5a92d94ee1dc7a0143299523fc010d4a119c34b30ff768"}
{"label":"import-033","command":["timeout","-k","10","900","node","--test","packages/bus/tests/grant-executor.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gEJ1","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":22.682,"mutant":false,"tests":42,"pass":42,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"97a66205b109952a7704ff9d5d63efbb0277922a0bf1510a677284f9ccbc9831"}
{"label":"import-034","command":["timeout","-k","10","900","node","--test","packages/bus/tests/grant-host.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gYeV","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.433,"mutant":false,"tests":10,"pass":10,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"0ab7ed5613f9c353c5e6f786ceffc6112c4f851debb799cf60ff73ae2f2bf65d"}
{"label":"import-035","command":["timeout","-k","10","900","node","--test","packages/bus/tests/grant-migration.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gcHz","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.495,"mutant":false,"tests":6,"pass":6,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"690a9c67e3426b8f6dc94c34f1b34ae5e502c0f8fb9ce67c5beab7cf5122557e"}
{"label":"import-036","command":["timeout","-k","10","900","node","--test","packages/bus/tests/grant-scope-runtime.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gVjH","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.228,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"c013731042ef37735fe6648ec299831b127d3ddb351c613d95efd4bc610d6ff2"}
{"label":"import-037","command":["timeout","-k","10","900","node","--test","packages/bus/tests/grant-scope.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gwvw","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.35,"mutant":false,"tests":14,"pass":14,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"1b48fba6570d0dcef4666725bde8b8c8f95e75eb8abb517d15b226a6ae5b0ea4"}
{"label":"import-038","command":["timeout","-k","10","900","node","--test","packages/bus/tests/hard-waits.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gM7r","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.464,"mutant":false,"tests":13,"pass":13,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"41d7bdf1b5276a7205b6b3e61ff4ac2f7982d60f5f190c3475e75c1ff4cebefd"}
{"label":"import-039","command":["timeout","-k","10","900","node","--test","packages/bus/tests/host-run.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gfCB","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":15.268,"mutant":false,"tests":26,"pass":26,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"7f5c5ab5e5f654c1826e84369739616606de89763879d96ffaa9cc196db05d72"}
{"label":"import-040","command":["timeout","-k","10","900","node","--test","packages/bus/tests/host-tools.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gbtM","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":4.726,"mutant":false,"tests":6,"pass":6,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"dfd0a799f300925eb291c8047adc0f9359bf05927f0b1c129c6b420fcf0bfcc0"}
{"label":"import-041","command":["timeout","-k","10","900","node","--test","packages/bus/tests/human.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gnLK","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.102,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"09791081c562afc5c9fa6da5b6df4e37935797147fc6d4c3f4cd8be2dd3d56ae"}
{"label":"import-042","command":["timeout","-k","10","900","node","--test","packages/bus/tests/instances-verb.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g46h","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.305,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"d41d14dd33492e34f21452550fed8d0ca0d3b1847cca0fb86c53ad13f8cb4fb7"}
{"label":"import-043","command":["timeout","-k","10","900","node","--test","packages/bus/tests/interpreter.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gTjS","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.178,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"c3be5eace9c994767d451fcd0d99ddfff2a647a8f7e74f21306c95ac503c229c"}
{"label":"import-044","command":["timeout","-k","10","900","node","--test","packages/bus/tests/land.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gOEa","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.156,"mutant":false,"tests":18,"pass":18,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"b59e6b60f597b4b1d02d4ced63344dbcb820946148a11a4ddd8e29ac422ef0f8"}
{"label":"import-045","command":["timeout","-k","10","900","node","--test","packages/bus/tests/launch-notice.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gv3V","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.543,"mutant":false,"tests":8,"pass":8,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"4979af0184d2b8fe0cfc7048da37828e2f58a8bb433b589399be4d8a7798371d"}
{"label":"import-046","command":["timeout","-k","10","900","node","--test","packages/bus/tests/launcher-released.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gEQl","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.365,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"9e4890aeaa7e21398fb140c469c606cb8a5cec2b564826232ade66f171fed937"}
{"label":"import-047","command":["timeout","-k","10","900","node","--test","packages/bus/tests/library-credential.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gJlk","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":3.11,"mutant":false,"tests":6,"pass":6,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"ca7c89d815a3bc281b406089a04dbaf94d04927c0b6b0ae840cae34cd8e858f5"}
{"label":"import-049","command":["timeout","-k","10","900","node","--test","packages/bus/tests/library-sync.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/geyX","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":7.525,"mutant":false,"tests":6,"pass":6,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"835bea6e1730fb67ab7d7ef02701ace657b0b3a839d300713ca16d0a32713828"}
{"label":"import-050","command":["timeout","-k","10","900","node","--test","packages/bus/tests/library.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gejb","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.736,"mutant":false,"tests":6,"pass":6,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"70633e1f2e5662e511239ada1bb47e1dc197b79e2c9ecf005308b270f713a41c"}
{"label":"import-051","command":["timeout","-k","10","900","node","--test","packages/bus/tests/lifecycle-revoke.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gA7g","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.815,"mutant":false,"tests":8,"pass":8,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"190fd253cefb4d669245531043a93225d37ae66ba694635a3e8bffd86c9e4264"}
{"label":"import-052","command":["timeout","-k","10","900","node","--test","packages/bus/tests/lifecycle-verbs.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gYLp","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.62,"mutant":false,"tests":13,"pass":13,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"071bed270aff7f251d954b557e090230ee6e224535938b85b93e8f885d3fb944"}
{"label":"import-053","command":["timeout","-k","10","900","node","--test","packages/bus/tests/limit-checks.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gt3p","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.347,"mutant":false,"tests":16,"pass":16,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"cb634a9e2819a161ec128a250586e4086591696309f00c9e6a62d7c54c6b9382"}
{"label":"import-054","command":["timeout","-k","10","900","node","--test","packages/bus/tests/limit-stop.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g1Vs","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.362,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"93504cdb3c5a9e5295bd72b8224ec69c43bbd344529a97538376c5a09e47328e"}
{"label":"import-055","command":["timeout","-k","10","900","node","--test","packages/bus/tests/limits-runtime.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/giXl","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.454,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"a18ac489d4eaa62e0bdb40444d70722379b0f4dc172f28e71f8600307ce7c3b6"}
{"label":"import-056","command":["timeout","-k","10","900","node","--test","packages/bus/tests/limits.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gZog","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.424,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"072dfdd9f45f609d52910d3619d4253bd05b54ec36e1a8599db17e17b472e99a"}
{"label":"import-057","command":["timeout","-k","10","900","node","--test","packages/bus/tests/message-citation.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gCEq","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.244,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"d53489b437b4adc8ac10bc52d0f1e6557b6fd187786008a6ad13a264207be034"}
{"label":"import-058","command":["timeout","-k","10","900","node","--test","packages/bus/tests/message-filter.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gsfe","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.58,"mutant":false,"tests":6,"pass":6,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"6038a839d1b12b29d8cdbc0ea341ae22197e19444be5743ca327cb188cd1af59"}
{"label":"import-059","command":["timeout","-k","10","900","node","--test","packages/bus/tests/messages.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gkz2","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.501,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"e507905469453069f469a1366bd4cbd446c6b7e2e8ba5234c3d0bee83d1172ba"}
{"label":"import-060","command":["timeout","-k","10","900","node","--test","packages/bus/tests/messaging.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gPZR","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.502,"mutant":false,"tests":13,"pass":13,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"434390031617151891ecb63a788da353c0d43051a4ea60db2e5727b149c9de4e"}
{"label":"import-061","command":["timeout","-k","10","900","node","--test","packages/bus/tests/name-migration.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gsLH","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.192,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"1979f0b1dd32162d42acace08a4b4306249e1096f5bbadb47038681af6b375d5"}
{"label":"import-062","command":["timeout","-k","10","900","node","--test","packages/bus/tests/names.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/grPm","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.313,"mutant":false,"tests":7,"pass":7,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"1d35ce65a08ec74388a7a65af8bfb7a87d341fab5795360fd553e65aa10d4999"}
{"label":"import-063","command":["timeout","-k","10","900","node","--test","packages/bus/tests/peer-transport.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g2ja","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.194,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"579cce4a4581e991e6cad80666cd40bfb10d1346699f1233a44dab5d17ee1583"}
{"label":"import-064","command":["timeout","-k","10","900","node","--test","packages/bus/tests/peercred.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g35b","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.499,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"c6d9c4a534f8aab5c73e6920346674eb243a19439eaaa09436ff4c2bc9b68fd7"}
{"label":"import-065","command":["timeout","-k","10","900","node","--test","packages/bus/tests/plugins-verb.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gGrj","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.331,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"4677c69292a7fe1961239e40ecd5848b1e9355e6d9326f1c935dd077605cc36b"}
{"label":"import-066","command":["timeout","-k","10","900","node","--test","packages/bus/tests/principal.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g5U9","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.102,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"efac2a82f133ae63ba26543832b6704df573f345c7699b48b928d4329467f03e"}
{"label":"import-067","command":["timeout","-k","10","900","node","--test","packages/bus/tests/process.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/go8U","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.448,"mutant":false,"tests":8,"pass":8,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"e26c9f5eb045dd7f651f453875fc1daac5dafa5f2060a69c3edcf37c79433e24"}
{"label":"import-068","command":["timeout","-k","10","900","node","--test","packages/bus/tests/processing-runtime.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gmrO","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.392,"mutant":false,"tests":2,"pass":2,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"624f60b78329dbf8db5b5ce17e9f218148f7e417a46bcace45666b10193ea4c4"}
{"label":"import-069","command":["timeout","-k","10","900","node","--test","packages/bus/tests/processing-timeout.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gt14","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.263,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"30a4c425941c5732bb0afa09ff8cf2229f11ec6031c7cd3ae26932cf55dc2552"}
{"label":"import-070","command":["timeout","-k","10","900","node","--test","packages/bus/tests/processing-web.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gWj9","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.126,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"dbe9bc036efc99fc38b2dea8824cb7a64fc39e49fcd3a1ef07c60298b0d8e69f"}
{"label":"import-071","command":["timeout","-k","10","900","node","--test","packages/bus/tests/processing.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gP4m","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.381,"mutant":false,"tests":14,"pass":14,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"d2204029f1dbc5836a759b43d421f2790ca32b97a1cc1fc6cb3f098fa4d7ab5d"}
{"label":"import-072","command":["timeout","-k","10","900","node","--test","packages/bus/tests/project-await.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/grrE","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.177,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"55cb0e215ff4f1e3265322c3336b3861d37fc3ba3cac53a31aa3dcc9ee0cab46"}
{"label":"import-073","command":["timeout","-k","10","900","node","--test","packages/bus/tests/project-files.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gZZ4","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.894,"mutant":false,"tests":8,"pass":8,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"b3395652052ccd06de8df2a1ce1aaac185dab50e854fb712a33aef8319d17fdc"}
{"label":"import-074","command":["timeout","-k","10","900","node","--test","packages/bus/tests/project-runtime.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gYyK","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.404,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"b139c3c9cea5fc9bd86ac64f33c4af23f568bee13f9271fef40a07d76ed51cf2"}
{"label":"import-075","command":["timeout","-k","10","900","node","--test","packages/bus/tests/publish.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gUl2","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.831,"mutant":false,"tests":13,"pass":13,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"0adf717babd8ac6229a115e1c796071fd68c1524f140d4596c9f1ee8c528b69f"}
{"label":"import-076","command":["timeout","-k","10","900","node","--test","packages/bus/tests/reload.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gZPr","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.003,"mutant":false,"tests":10,"pass":10,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"2ce6a9bd3ea3eeccf1689e1b6335b72bba2d440ae27feeec3dc727567fa140ff"}
{"label":"import-077","command":["timeout","-k","10","900","node","--test","packages/bus/tests/replies.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gbjz","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.374,"mutant":false,"tests":7,"pass":7,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"6db5c1588c83f2df4be469f06857569df7f4cfc47c18b15a8f9e741d4d739c4f"}
{"label":"import-078","command":["timeout","-k","10","900","node","--test","packages/bus/tests/requirements.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g1jX","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.192,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"32b876110fc8a35246f6ab16343dae9ea6da42ef556a99e1e5356e077474a96f"}
{"label":"import-079","command":["timeout","-k","10","900","node","--test","packages/bus/tests/review.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gVJz","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.427,"mutant":false,"tests":8,"pass":8,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"333b7d84cf72b95ba2cdb1d3824bcb8043623c5f0810c68ed22738210977c297"}
{"label":"import-080","command":["timeout","-k","10","900","node","--test","packages/bus/tests/revoke-window.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gRZs","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.305,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"7e759b3330537c0c566b55b2c405adc6f5f48c3b229c4450d938aaec3280fc09"}
{"label":"import-081","command":["timeout","-k","10","900","node","--test","packages/bus/tests/room-check.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gzW9","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.225,"mutant":false,"tests":2,"pass":2,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"300f1ea96ccfa38c9405ef163e531cfeec3c7eb8f46986f077669ca95b8f72f3"}
{"label":"import-082","command":["timeout","-k","10","900","node","--test","packages/bus/tests/rooms.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gEx0","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.033,"mutant":false,"tests":18,"pass":18,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"fbcac36a4495da1def5dd650d8aea5758bf25d3e7473148a2b8961bb97b57239"}
{"label":"import-083","command":["timeout","-k","10","900","node","--test","packages/bus/tests/routes-verb.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g0LO","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.292,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"4fef276b76a79518faa03b81d119962ab8880af3010fa33ead93f393dca89f02"}
{"label":"import-084","command":["timeout","-k","10","900","node","--test","packages/bus/tests/schema.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gZFQ","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.169,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"e71271414564fa851dbf25a155b44dcf481770c7f3d4dafe5ce44a09c49526b1"}
{"label":"import-085","command":["timeout","-k","10","900","node","--test","packages/bus/tests/session-clear.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gfrg","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.773,"mutant":false,"tests":19,"pass":19,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"c8097880d5e9a396fb907bc1f35f342821971b545fea7f1e4ddcb2b9f2fb322a"}
{"label":"import-086","command":["timeout","-k","10","900","node","--test","packages/bus/tests/session-compactions.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gfRL","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.179,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"0a2f0ef4d7f6588e2aaeb5a5d8e200650ae573c4468640130140eb83430261b3"}
{"label":"import-087","command":["timeout","-k","10","900","node","--test","packages/bus/tests/sessions.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gaNb","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.654,"mutant":false,"tests":7,"pass":7,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"11f26dc0d082b49ce7839d22aca75067dcc2f978d6c319da3d2800adcc0a9ffc"}
{"label":"import-088","command":["timeout","-k","10","900","node","--test","packages/bus/tests/single-use.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gSe3","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.416,"mutant":false,"tests":12,"pass":12,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"7a0e2e7a4a6ab79b85462ad1a39955c5402dab8a9236534c857cef88d08ecc87"}
{"label":"import-089","command":["timeout","-k","10","900","node","--test","packages/bus/tests/spec-migration.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gPmw","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.215,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"b9831356a0d65a037796a66764dcf7dcc267d8512e70087b364cbe390a8c85dc"}
{"label":"import-090","command":["timeout","-k","10","900","node","--test","packages/bus/tests/spec-review.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gqKv","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":2.034,"mutant":false,"tests":12,"pass":12,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"8a70a550b2b056c35f2e85bdd4a155bf7d02332d89596aeed40e16bec765221c"}
{"label":"import-091","command":["timeout","-k","10","900","node","--test","packages/bus/tests/spec-socket.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gY6G","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.787,"mutant":false,"tests":6,"pass":6,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"d58670526310fa5106ab9b3d724d817910283b76cfa8bd79278b0428e42b73c3"}
{"label":"import-092","command":["timeout","-k","10","900","node","--test","packages/bus/tests/spec.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gnTM","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.538,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"d04ac45ad25906322cbbd50b703c316c4eeefad1d40f901eeaf2c34224fc5958"}
{"label":"import-093","command":["timeout","-k","10","900","node","--test","packages/bus/tests/staff-request.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g07B","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.544,"mutant":false,"tests":10,"pass":10,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"e0e379d2e0871ecbbae9a5e92ee7217342dc31cf69c80373aeef72f78ea27fd9"}
{"label":"import-094","command":["timeout","-k","10","900","node","--test","packages/bus/tests/state.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gx6m","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.289,"mutant":false,"tests":8,"pass":8,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"63ac32064c6220c89204a8c34f13ce45ebb76f65a6e10e4173608740e1b54887"}
{"label":"import-095","command":["timeout","-k","10","900","node","--test","packages/bus/tests/store.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g5mj","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.286,"mutant":false,"tests":7,"pass":7,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"329377b361787f86ffb5bda9210559d3d073e8ed9cfacc43e341156de63af707"}
{"label":"import-096","command":["timeout","-k","10","900","node","--test","packages/bus/tests/task-page.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gErK","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.203,"mutant":false,"tests":6,"pass":6,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"0e48322586d18073df7d9efbc0700b7f9e2e45a7a61eb32ffa13ab9d9695de54"}
{"label":"import-097","command":["timeout","-k","10","900","node","--test","packages/bus/tests/task-read.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g7B0","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.237,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"3aa73723d9410d5c6851352f6b3d9c0f671f9b008b8a2355021488f2a071c22b"}
{"label":"import-098","command":["timeout","-k","10","900","node","--test","packages/bus/tests/tasks.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gqcQ","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.037,"mutant":false,"tests":9,"pass":9,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"60e43ca791f0ee0e5a91c0a112ad0d971f38d28e18d6feb7a2d33132aec934fe"}
{"label":"import-099","command":["timeout","-k","10","900","node","--test","packages/bus/tests/tester-threads.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gbPX","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.486,"mutant":false,"tests":15,"pass":15,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"101fcf483990278f3a997ed1cff44b6191b1766147083ddf21341a4480eb602b"}
{"label":"import-100","command":["timeout","-k","10","900","node","--test","packages/bus/tests/tester-writes.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gMT4","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.609,"mutant":false,"tests":8,"pass":8,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"d5618314574cf7e64ac877e29787712f5fd68903228e6e1001c37cdd9b54a9e4"}
{"label":"import-101","command":["timeout","-k","10","900","node","--test","packages/bus/tests/tester.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gl5m","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":2.337,"mutant":false,"tests":14,"pass":14,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"c44885e9d43e6ed5969af2f87ecc17fe00e1f1895435d86f5ddbe399c945642e"}
{"label":"import-102","command":["timeout","-k","10","900","node","--test","packages/bus/tests/thread-claims.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gmfF","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.354,"mutant":false,"tests":6,"pass":6,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"bd053d20e52d1859ea6ed13f316e7ed27dac3ba3a8f1be5b3b7adef2fa15e356"}
{"label":"import-103","command":["timeout","-k","10","900","node","--test","packages/bus/tests/thread-migration.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gUt3","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.513,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"ee94081c476ab12b1c1b73eb2efb6138c22deee6dda92aa015fd2b2cc4cc405e"}
{"label":"import-104","command":["timeout","-k","10","900","node","--test","packages/bus/tests/thread-shares.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g6KY","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.966,"mutant":false,"tests":16,"pass":16,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"e2c37691510cc5acfecfcd6d5be612b701fa72a06c544c265b027a381eb577ae"}
{"label":"import-105","command":["timeout","-k","10","900","node","--test","packages/bus/tests/threads.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gqdT","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.848,"mutant":false,"tests":20,"pass":20,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"0e25845dfd5e6c68c206ef19b6ab74b5e00d01cf2ce6cd8843b7f0abe4229d60"}
{"label":"import-106","command":["timeout","-k","10","900","node","--test","packages/bus/tests/transport.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gG0Z","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.355,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"177ad5f143bb47dc7d65ef89785b19170ed7f5a25d1dd78079c73367b7d34bb5"}
{"label":"import-107","command":["timeout","-k","10","900","node","--test","packages/bus/tests/usage-broker.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gYVM","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.179,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"91d3b9ff3e854f2afb6d635a0994a4b2d1af482804067c2e6f78930babf25378"}
{"label":"import-108","command":["timeout","-k","10","900","node","--test","packages/bus/tests/usage-migration.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gJIX","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.232,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"35dae9048409bf16982b1554b0d3bf53de51293c012b428cfa95e3876c353d1b"}
{"label":"import-109","command":["timeout","-k","10","900","node","--test","packages/bus/tests/usage-runtime.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gzcI","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.3,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"1b260c414d98caf272852cc1c6a0928a79f84b05baad356f954fabb8befed9f4"}
{"label":"import-110","command":["timeout","-k","10","900","node","--test","packages/bus/tests/usage.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g9hD","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.341,"mutant":false,"tests":15,"pass":15,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"4b7a7719685b54f0bafcd0d6ca0eff8da3c35e8c438b69fb63826120c444646d"}
{"label":"import-111","command":["timeout","-k","10","900","node","--test","packages/bus/tests/user-principal.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gCyo","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.843,"mutant":false,"tests":24,"pass":24,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"7e5d8e391b6d683905f7654276e74e56cd2e0bb3019d8882fb51f5e96e8bb4e2"}
{"label":"import-112","command":["timeout","-k","10","900","node","--test","packages/bus/tests/viewer.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gckq","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.495,"mutant":false,"tests":7,"pass":7,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"0088c69c83ad21b0c09c5b74986f7d1b5609f6155d40d6230cb755914506b209"}
{"label":"import-113","command":["timeout","-k","10","900","node","--test","packages/bus/tests/web.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gr8J","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.209,"mutant":false,"tests":19,"pass":19,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"81db5367857555ba39abf0d45a2b4837a60c796109af4039b43f3dceaaf9a3e4"}
{"label":"import-114","command":["timeout","-k","10","900","node","--test","packages/bus/tests/workflow-roles.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gObE","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.265,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"4a3d911233067a9623aacbe0f856296e7c80d616d1099a30a9ce253506791bb2"}
{"label":"import-115","command":["timeout","-k","10","900","node","--test","packages/business/tests/case1-business-file.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gKGR","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.839,"mutant":false,"tests":7,"pass":7,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"2dd7e08774e88449fc90beffa7a1097772a4b04906e62548cd34b31f1cf541b3"}
{"label":"import-116","command":["timeout","-k","10","900","node","--test","packages/business/tests/launch-settings.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gaiJ","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.451,"mutant":false,"tests":18,"pass":18,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"849eeebfaaf47c96f22db45752fb5f00143663fb4ed0aa2d22d74f8af9ea3905"}
{"label":"import-117","command":["timeout","-k","10","900","node","--test","packages/cli/tests/access-boot.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gU7B","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.64,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"1698f3f93b14d11b330e559f19a580edae78b4182042df0e7da1cc9d4cbb53be"}
{"label":"import-118","command":["timeout","-k","10","900","node","--test","packages/cli/tests/access.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gHaW","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":7.364,"mutant":false,"tests":34,"pass":34,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"e42f5491e4db8370ad6f6c2f09a8008c9559ecd572f0985f766f0ca11b1d7b60"}
{"label":"import-119","command":["timeout","-k","10","900","node","--test","packages/cli/tests/app.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gmHw","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":16.086,"mutant":false,"tests":30,"pass":30,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"d65043a7cf3a1d67b99bb47de8efa029c44b90b9fcc0cc7cb8d8ed54403bba81"}
{"label":"import-120","command":["timeout","-k","10","900","node","--test","packages/cli/tests/boot-status.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gYv3","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.916,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"f6753a454d658737099bb6da76219aeb3c6e92bce76b78c53f2d9dae29f5d777"}
{"label":"import-121","command":["timeout","-k","10","900","node","--test","packages/cli/tests/case1-hostcheck.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gvaK","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":3.735,"mutant":false,"tests":19,"pass":19,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"aeb1e23bf951d5859d7adb54fe8f3c6464ba4bf368e9316dce8e5142e097565c"}
{"label":"import-122","command":["timeout","-k","10","900","node","--test","packages/cli/tests/case2-install.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gLWb","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":11.37,"mutant":false,"tests":27,"pass":27,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"06166332e80fd57cd9ae5e5ef2f167260adb413cd6c799b9c1834255cbf3ed63"}
{"label":"import-123","command":["timeout","-k","10","900","node","--test","packages/cli/tests/case2-persona-import.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g955","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":3.606,"mutant":false,"tests":14,"pass":14,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"6005b321161cba438dc94ee6f58a05a05919e099da0d5b43b16b0438214b128e"}
{"label":"import-124","command":["timeout","-k","10","900","node","--test","packages/cli/tests/case2-unit.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gPC5","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":104.569,"mutant":false,"tests":47,"pass":47,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"b9c64e1eea4e389dfc10b9e1ddf88e47d903c7abb1f175b0f73b0a6adf5e8a3b"}
{"label":"import-125","command":["timeout","-k","10","900","node","--test","packages/cli/tests/channel-cli.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gCxf","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.604,"mutant":false,"tests":2,"pass":2,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"69ae3003d282a5f998613498ca1a696b684a9e4c03f5b006409d1fb15402c3c6"}
{"label":"import-126","command":["timeout","-k","10","900","node","--test","packages/cli/tests/channel-recovery.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gy7b","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":7.039,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"0df2d0dce24f2c7e9e70c1db3da115d848ee778a3b77c30f50db5fa5b70b15a8"}
{"label":"import-127","command":["timeout","-k","10","900","node","--test","packages/cli/tests/cli.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g4YA","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.986,"mutant":false,"tests":12,"pass":12,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"9e9f75b810bdce44a7e288a0f03572a824642a0e615c3912113d8882fba57f20"}
{"label":"import-128","command":["timeout","-k","10","900","node","--test","packages/cli/tests/compactions-launch.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gH0o","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":18.141,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"7ab789f5de01f4d9fb2c2933fc906d657bb3c867ebb7e8545b4ae8b2f07e348b"}
{"label":"import-129","command":["timeout","-k","10","900","node","--test","packages/cli/tests/config.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gvdv","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.989,"mutant":false,"tests":7,"pass":7,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"46976c51d867431031baeb7dfb03518e111f88327f99f24fafa727c987037710"}
{"label":"import-130","command":["timeout","-k","10","900","node","--test","packages/cli/tests/credentials.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gW4m","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.558,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"1633748b05e927193646fd8eaeb9cc64092553734a972a33ac9b26baee4390e1"}
{"label":"import-131","command":["timeout","-k","10","900","node","--test","packages/cli/tests/federation-acceptance.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gEeW","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.281,"mutant":false,"tests":1,"pass":0,"fail":0,"cancelled":0,"skipped":1,"todo":0,"log_sha256":"76dec3f040a21cad59757b69487247ebb3b6a8b27b015f0615585b3be477942a"}
{"label":"import-132","command":["timeout","-k","10","900","node","--test","packages/cli/tests/follow.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gxPz","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.084,"mutant":false,"tests":6,"pass":6,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"db3463b8998634a487878c02c81b31eb196077dc45ac102de56f6f06a7bd26ee"}
{"label":"import-133","command":["timeout","-k","10","900","node","--test","packages/cli/tests/git-socket.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gcHM","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":27.936,"mutant":false,"tests":24,"pass":24,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"c1a6247751b05dcaad81d9a42e93c923200f2971ef17622924d00a07c8292735"}
{"label":"import-134","command":["timeout","-k","10","900","node","--test","packages/cli/tests/grants-scope.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gRr9","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.298,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"2f9222ce2ac41443cb24c69bffea46fd96c53af469670f642dcc2319d162ffc5"}
{"label":"import-135","command":["timeout","-k","10","900","node","--test","packages/cli/tests/grants.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gbr2","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.418,"mutant":false,"tests":6,"pass":6,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"018fba785221ec997b369739f1fa39ff927f7144b6276f071338a64ba331e555"}
{"label":"import-136","command":["timeout","-k","10","900","node","--test","packages/cli/tests/host.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gIQc","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":20.522,"mutant":false,"tests":43,"pass":43,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"98d2bb8ac91e143fd16fb02b29d877b2df4397a1d8857687707d0bfebb3459be"}
{"label":"import-137","command":["timeout","-k","10","900","node","--test","packages/cli/tests/hosts.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gB9t","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.5,"mutant":false,"tests":8,"pass":8,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"376d8a698c39bc25b9e43ee63f762718ab2d2d2dbfab36da61971e3982f98353"}
{"label":"import-138","command":["timeout","-k","10","900","node","--test","packages/cli/tests/idle-stop-race.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gt4N","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":2.246,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"4ee49db59177a6cedcc98642ad2b4215e1489c8720e3ab27c88a1d3513b4384f"}
{"label":"import-139","command":["timeout","-k","10","900","node","--test","packages/cli/tests/instances.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/ga2n","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":4.158,"mutant":false,"tests":15,"pass":15,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"125780e39af442913bf056f71a57b663c954d8eb5a96fb245db8063237ccb1e1"}
{"label":"import-140","command":["timeout","-k","10","900","node","--test","packages/cli/tests/launch-account.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gEgp","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.427,"mutant":false,"tests":7,"pass":7,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"1a2de9540358023f6acb51ab8cdfe0f56e21331cca06ecef672fe7e9b1e0b43a"}
{"label":"import-141","command":["timeout","-k","10","900","node","--test","packages/cli/tests/launch-limit-checks.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gxqf","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.398,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"027fb83eb3ef68f01fde4e1a272faf569516372f194e3e8404973756f9ffb974"}
{"label":"import-142","command":["timeout","-k","10","900","node","--test","packages/cli/tests/launch-limits.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g5N5","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.255,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"a3c26a3f092d8e7dd96fe1addfcd77b89d726d027e9f988340a1442823644c3c"}
{"label":"import-143","command":["timeout","-k","10","900","node","--test","packages/cli/tests/launch-routes.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gMhQ","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.514,"mutant":false,"tests":9,"pass":9,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"ba0335e2efd7de694b51ca89b427ffb06b652f6d9757df1997f9c1c7703ac74a"}
{"label":"import-144","command":["timeout","-k","10","900","node","--test","packages/cli/tests/launcher.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gqhv","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":45.769,"mutant":false,"tests":34,"pass":34,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"5e5374884901f29432961198070f3ede2f87fcc41a818423c3cb90c919dfd7d0"}
{"label":"import-145","command":["timeout","-k","10","900","node","--test","packages/cli/tests/lifecycle.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g76b","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":16.885,"mutant":false,"tests":24,"pass":24,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"37c3dcc1555bc527fe0f853c1a08bae993bd541143c3b6f7edc360c0c3c26d8d"}
{"label":"import-146","command":["timeout","-k","10","900","node","--test","packages/cli/tests/limits-tokens.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g7dV","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.224,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"6dae4cd3607f44b07df6a5e6764276a2ef152b892f050340d6defd14a83b731e"}
{"label":"import-147","command":["timeout","-k","10","900","node","--test","packages/cli/tests/limits.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gLVw","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.442,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"efe051216bb6347423f556f8951c6b6c4adf9c266d8fde6fedfbebb3e678c17f"}
{"label":"import-148","command":["timeout","-k","10","900","node","--test","packages/cli/tests/mark-read.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gVQ4","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.266,"mutant":false,"tests":6,"pass":6,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"b90e024010c9a6fbded17306d01b78b2f5748167f9dd4fee20bc5775ef72de81"}
{"label":"import-149","command":["timeout","-k","10","900","node","--test","packages/cli/tests/names.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gJL7","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.297,"mutant":false,"tests":2,"pass":2,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"b8d4005cb4e0f1acbe89bc6427b952459b2b876f54c1ed031a558789b535e87e"}
{"label":"import-150","command":["timeout","-k","10","900","node","--test","packages/cli/tests/notifier.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gSos","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.033,"mutant":false,"tests":27,"pass":27,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"c7156a9c99f99c3b51da2c73b728349f348dac6a0b0530bda96212a848014f7c"}
{"label":"import-151","command":["timeout","-k","10","900","node","--test","packages/cli/tests/optional-tracker.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/ggn7","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.413,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"d09457d3034c683bc98639f04d83d5348815571d46d5c30cbe055aed5ceef3a7"}
{"label":"import-152","command":["timeout","-k","10","900","node","--test","packages/cli/tests/other-tree.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gclm","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.3,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"aa7be88cd823a44c8743159006f1d9b61072ebaa04935339d4a875d0997f903e"}
{"label":"import-153","command":["timeout","-k","10","900","node","--test","packages/cli/tests/processing-cli.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gvyI","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.367,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"55d67187192edfd5c929713af6a8f40025259429f36a444eb886fd26013a3135"}
{"label":"import-154","command":["timeout","-k","10","900","node","--test","packages/cli/tests/project-name-repo.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g3qR","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.431,"mutant":false,"tests":2,"pass":2,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"9e8364d68d732dbcb9e518ff8dc1cb957d0d254c0a3821711df20e34f6427f07"}
{"label":"import-155","command":["timeout","-k","10","900","node","--test","packages/cli/tests/project.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gJK9","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.908,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"7014e206c70053c2eaeb89fa59b38781802e65d2982fee3855772dd9721285a6"}
{"label":"import-156","command":["timeout","-k","10","900","node","--test","packages/cli/tests/publish-socket.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gQ5m","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":11.807,"mutant":false,"tests":9,"pass":9,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"e20a380f9e0e0070d2598bd3ae85679f70f59c92e6f8cf1c7c840a0975c253b7"}
{"label":"import-157","command":["timeout","-k","10","900","node","--test","packages/cli/tests/reply-limits.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gR4L","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.167,"mutant":false,"tests":2,"pass":2,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"9339298bbd5ebfb0e033d2b992c69f62c168e124e741bfc0de500c35b8ffc092"}
{"label":"import-158","command":["timeout","-k","10","900","node","--test","packages/cli/tests/revoke-window.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gHpa","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.868,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"774c1211e7dadeab526d34d50b143c1141ee9f85e3799b644734eeb78c8e9b6f"}
{"label":"import-159","command":["timeout","-k","10","900","node","--test","packages/cli/tests/session-clear.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gd9q","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":13.609,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"a47caf45da848c1bf1a8456eb89c213df981229dc0765362573ec82e6701b11c"}
{"label":"import-160","command":["timeout","-k","10","900","node","--test","packages/cli/tests/session-cli.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gXLB","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.323,"mutant":false,"tests":14,"pass":14,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"3d260701a0c4afd1d21effb5ca1db6cdb47803281bde2536853926f56a236955"}
{"label":"import-161","command":["timeout","-k","10","900","node","--test","packages/cli/tests/session-launch.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gPoX","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":12.34,"mutant":false,"tests":8,"pass":8,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"9d077d5e2956b1f40de6abba79ebed6504cc61a3821754526a032231e8697271"}
{"label":"import-162","command":["timeout","-k","10","900","node","--test","packages/cli/tests/stack-copy.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gb3j","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":32.255,"mutant":false,"tests":18,"pass":18,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"a31fda44310b53fcbfbfb5ca037db8bf9209a0235ed951a911358c61c5f4d13b"}
{"label":"import-163","command":["timeout","-k","10","900","node","--test","packages/cli/tests/stack-instances.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gVU0","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":5.223,"mutant":false,"tests":24,"pass":24,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"baf388164839b10a5ea8c3e019d6b5095d7951657ee638784701848b69a160cd"}
{"label":"import-164","command":["timeout","-k","10","900","node","--test","packages/cli/tests/tester-http.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/geku","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.28,"mutant":false,"tests":2,"pass":2,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"d06f4abf2476d898d85533318fee23bdfe3fdc6012c40e809ae4f21e1d6e74bb"}
{"label":"import-165","command":["timeout","-k","10","900","node","--test","packages/cli/tests/tester-reads.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g7PM","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":5.141,"mutant":false,"tests":6,"pass":6,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"2f293f7b23b679733870b5d5d2f666570b56fa1335d5b94590046447433225c8"}
{"label":"import-166","command":["timeout","-k","10","900","node","--test","packages/cli/tests/tester-threads.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gAdD","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":12.373,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"6505ae90432cfcf6c2b74ed4c22ebe6ee1b26055b41f3fdada4e40c54e1124f9"}
{"label":"import-167","command":["timeout","-k","10","900","node","--test","packages/cli/tests/tester.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gx0E","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.628,"mutant":false,"tests":11,"pass":11,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"abadf2326205ea5ba1e617fd174018995de824d1552f308815e2bc9c3f71e4bc"}
{"label":"import-168","command":["timeout","-k","10","900","node","--test","packages/cli/tests/thread-cli.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gbFa","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":5.076,"mutant":false,"tests":11,"pass":11,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"fc7f5fadded9b52bcebcf80af32a54bfcb85c2a58608e261d839e8c91d473ce4"}
{"label":"import-169","command":["timeout","-k","10","900","node","--test","packages/cli/tests/thread-launch.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gQNn","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":36.824,"mutant":false,"tests":15,"pass":15,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"f4052bf907e300dae2a7d44f3e8b370849e879abf1de9f84e0c74138f41f2640"}
{"label":"import-170","command":["timeout","-k","10","900","node","--test","packages/cli/tests/thread-revoke.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gNtT","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.273,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"2f66b678922916e9856a6ade3a4524c420d981f39548a6687df77cb95c660d40"}
{"label":"import-171","command":["timeout","-k","10","900","node","--test","packages/cli/tests/trackers-boot.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/giDk","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.097,"mutant":false,"tests":2,"pass":2,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"dbb78cab0545fe2d18089c4510092562aa5bc16cdc3f1f95784719d8e2dda241"}
{"label":"import-172","command":["timeout","-k","10","900","node","--test","packages/cli/tests/transport.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g6h3","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":2.447,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"7b7a41c111670e869d5156d3714a33c7a4e7a675893cff4767c505b658ac0dc8"}
{"label":"import-173","command":["timeout","-k","10","900","node","--test","packages/cli/tests/usage.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gERb","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.44,"mutant":false,"tests":2,"pass":2,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"d39ae2e64f3e78a0d4bd7fc8d4c6f8f087ac80f0ba47d5dbd199d627d826e86f"}
{"label":"import-174","command":["timeout","-k","10","900","node","--test","packages/cli/tests/verbs.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gaL4","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":3.562,"mutant":false,"tests":9,"pass":9,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"6eafbcea30d6c03a2f8dd925ca6b801fb7f2a8475f3b70715ad8a5060f47f0f0"}
{"label":"import-175","command":["timeout","-k","10","900","node","--test","packages/harness/tests/bundle.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g8v2","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.276,"mutant":false,"tests":22,"pass":22,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"232cba86e5cf956c07e7ac3bce916899fd288db2ef252bf33041c54fa29f6e1b"}
{"label":"import-176","command":["timeout","-k","10","900","node","--test","packages/harness/tests/citation-runner.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g6h4","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":6.327,"mutant":false,"tests":21,"pass":21,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"ef0a3e5f582524e0f03a3a39b518356af2d180cefcaa64439c828dbfc9ab0555"}
{"label":"import-177","command":["timeout","-k","10","900","node","--test","packages/harness/tests/claude-gate.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gmnt","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.62,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"2b7867d549382bd5943f9f828f7132743abd724b9d6a26f7e7647e5deac1086c"}
{"label":"import-178","command":["timeout","-k","10","900","node","--test","packages/harness/tests/claude-session.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gWex","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":8.983,"mutant":false,"tests":10,"pass":10,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"e97d2c71fb63346d736d85b37e1bae38708041a7e09b15cc5d64f44d5f87e592"}
{"label":"import-179","command":["timeout","-k","10","900","node","--test","packages/harness/tests/creative.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g7fD","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.349,"mutant":false,"tests":7,"pass":7,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"0a08749c464113ccbc5207cc63ad3cb33ccd7d7af3ebdcb614106f14a38fa8af"}
{"label":"import-180","command":["timeout","-k","10","900","node","--test","packages/harness/tests/gate.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gLqE","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.177,"mutant":false,"tests":12,"pass":12,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"8d3cf0837ecb7d8c5be2a02c67fbe1fb1fbf0a7d75b8e79029a6a3530870353f"}
{"label":"import-181","command":["timeout","-k","10","900","node","--test","packages/harness/tests/git-tools.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gcPM","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":2.824,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"170299b738f35a5cbce8336dbf37ddd340045c9f12b0d86716dc9764ce692656"}
{"label":"import-183","command":["timeout","-k","10","900","node","--test","packages/harness/tests/mcp-server.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gruQ","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.352,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"fcbb8ff07441b7458fad73e8f0d2e8c81a37a184244403c46f0db51bcb579d6c"}
{"label":"import-184","command":["timeout","-k","10","900","node","--test","packages/harness/tests/pi-session.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gQR8","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":7.664,"mutant":false,"tests":10,"pass":10,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"21ef864f6c0608e398001beed596c711eaa16df9830be6e9948d23adaf7ae19b"}
{"label":"import-185","command":["timeout","-k","10","900","node","--test","packages/harness/tests/raise-domain.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gkno","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.289,"mutant":false,"tests":2,"pass":2,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"258b03d95708255aaf9c53af130e80349d3fb7a15c412f5e99a552d38d273cf4"}
{"label":"import-186","command":["timeout","-k","10","900","node","--test","packages/harness/tests/runner.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gHpN","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":14.264,"mutant":false,"tests":40,"pass":40,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"6b2ed91f2cc0af529b15da7dd1ca38fc4f9024b8838f1ae948bb9fb61f52b1d4"}
{"label":"import-187","command":["timeout","-k","10","900","node","--test","packages/harness/tests/skills.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/ge6l","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.322,"mutant":false,"tests":10,"pass":10,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"a5eb44bb14feab35f8afff44467dd1ab4b6ccd95f0c20e99bd8165e02ab11e94"}
{"label":"import-188","command":["timeout","-k","10","900","node","--test","packages/harness/tests/spec-tools.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gqeF","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.392,"mutant":false,"tests":2,"pass":2,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"25bef2391ffce43b2ad8c6159fb801bf371064b48998f5212b45043b78a65ab4"}
{"label":"import-189","command":["timeout","-k","10","900","node","--test","packages/harness/tests/tools.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gh6I","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.254,"mutant":false,"tests":23,"pass":23,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"032cd4df77581f65cc3d1e3487b542cc2568e40461f34cf345c9e3ccf224d2c0"}
{"label":"import-190","command":["timeout","-k","10","900","node","--test","packages/library/tests/guard.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gX5T","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.7,"mutant":false,"tests":11,"pass":11,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"c5c5e1daabdcbc4830da5472dc584f3095874effa6ed00a5d752ef5a792f433a"}
{"label":"import-191","command":["timeout","-k","10","900","node","--test","packages/library/tests/index-build.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gDCo","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":4.794,"mutant":false,"tests":6,"pass":6,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"6122712a2a10cd4fc7ad0f29e7581dc27e6d1e5daddb92dc3b9831ccd26c06b5"}
{"label":"import-192","command":["timeout","-k","10","900","node","--test","packages/library/tests/links.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gNyj","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.128,"mutant":false,"tests":7,"pass":7,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"933818b92437600be0591b784675887f9240915167a6218d9bd5546737c0de1d"}
{"label":"import-193","command":["timeout","-k","10","900","node","--test","packages/library/tests/mapping.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gBnG","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.16,"mutant":false,"tests":16,"pass":16,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"b97b350865814827ad8998f9a24ea1f65749b882dd10531eb79052268769f9d0"}
{"label":"import-194","command":["timeout","-k","10","900","node","--test","packages/library/tests/mirror.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gfP9","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":6.763,"mutant":false,"tests":16,"pass":16,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"ba91652dd7daa182d771e5f8d093769fa009494d0f4080fd697a423b8c8aff4c"}
{"label":"import-196","command":["timeout","-k","10","900","node","--test","packages/library/tests/reader.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gvmz","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.028,"mutant":false,"tests":14,"pass":14,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"5b335d4472ccc9aead596840a67909ccf96270c7ccf88e4ad2141eb5953de74c"}
{"label":"import-197","command":["timeout","-k","10","900","node","--test","packages/library/tests/render.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gfUA","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.211,"mutant":false,"tests":9,"pass":9,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"f95a831fa8ef95d90f50861d7ebf05fdedc4d3d68d1ea3dec1e17e9392befab9"}
{"label":"import-198","command":["timeout","-k","10","900","node","--test","packages/library/tests/scope.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gxAY","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.368,"mutant":false,"tests":6,"pass":6,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"3935e31b852d0be272395f8d2af9816e8b8ee3bf75a088be39559e413d58fd1e"}
{"label":"import-199","command":["timeout","-k","10","900","node","--test","packages/library/tests/supporting.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gT0U","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.25,"mutant":false,"tests":6,"pass":6,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"cfd46a3aaa0167b3adda75bb69095f6328de4cfd43bdb26ae4952e6867c6bf81"}
{"label":"import-200","command":["timeout","-k","10","900","node","--test","packages/library/tests/survey.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gQVP","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.764,"mutant":false,"tests":7,"pass":7,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"a20f9ea4cd570def995d73d389f0610621f0198499e60c8f27ada2e952b22bb8"}
{"label":"import-201","command":["timeout","-k","10","900","node","--test","packages/library/tests/sync.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gGSr","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":6.838,"mutant":false,"tests":24,"pass":24,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"683e7b2ec581c2d72a6a3edc68913a7092a49c3ac5c15fe9dfa3062fc3d59fe9"}
{"label":"import-202","command":["timeout","-k","10","900","node","--test","packages/processing-control/tests/task.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gAOM","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.776,"mutant":false,"tests":7,"pass":7,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"a9c5e79fa8bddcd222359c6b5fb5634ad170ad56babfe3971f22d8f1fbcaceb9"}
{"label":"import-203","command":["timeout","-k","10","900","node","--test","packages/seat/tests/sandbox.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gcfc","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":7.076,"mutant":false,"tests":10,"pass":10,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"9d9e237b00482d14c1173fcdf2ba0770d87c2e77e0a2d7f8b3631531d1fa5da2"}
{"label":"import-204","command":["timeout","-k","10","900","node","--test","packages/seat/tests/session.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gpBq","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.478,"mutant":false,"tests":13,"pass":13,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"2ffb0ee5961f4611d6afde99fd99270dee783b7abde51c9038ee2087dc426c22"}
{"label":"import-205","command":["timeout","-k","10","900","node","--test","packages/tasks/tests/adapter.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/guN4","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.512,"mutant":false,"tests":8,"pass":8,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"b0441401e2ab0e9593e6d55cca661366e7ee8b51850ac934bfca23de45d2a35a"}
{"label":"import-206","command":["timeout","-k","10","900","node","--test","packages/tasks/tests/comment-restart.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gyAw","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.45,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"599ad621c9d89dc1f200ad0e87eb1573e5ae7bfcc6ff9cddb9048855a9f8613f"}
{"label":"import-207","command":["timeout","-k","10","900","node","--test","packages/tasks/tests/fields.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gOij","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.617,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"2d83b920f5f716537a69555f6bead6b99be1b3c64751305ec8de1a71cadeb56f"}
{"label":"import-208","command":["timeout","-k","10","900","node","--test","packages/tasks/tests/processing.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g72u","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.32,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"5d740844a654055345b9e7c69ed4d2a247cd932ad2a5a6fcf329c7801cbd0ad7"}
{"label":"import-209","command":["timeout","-k","10","900","node","--test","packages/tasks/tests/shapes.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gJAm","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.518,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"3811bcc866161d152d9460cb8bfef2faa9cd3e533de96f1b3f014403dd7fb51e"}
{"label":"import-210","command":["timeout","-k","10","900","node","--test","packages/tasks/tests/startup.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gGTN","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.541,"mutant":false,"tests":9,"pass":9,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"b2c08b276e60a676346a7a7a96423939fc50fece24e84f7d31a141414ae9c65e"}
{"label":"import-211","command":["timeout","-k","10","900","node","--test","packages/tasks/tests/sync.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gccq","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.994,"mutant":false,"tests":11,"pass":11,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"7521b57b037d5dfd35e4e7f8b3e0f772e6f09e9a7f218eaa55a95b40798fb3cb"}
{"label":"import-212","command":["timeout","-k","10","900","node","--test","packages/tasks/tests/tree.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gKai","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.129,"mutant":false,"tests":19,"pass":19,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"035eba7993242c2797c236e2c7f5d41f9248d872984cbfd785bb596bd323721f"}
{"label":"import-213","command":["timeout","-k","10","900","node","--test","packages/tasks/tests/verbs.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gcgn","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.767,"mutant":false,"tests":31,"pass":31,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"27cd7e0bb4607ec39ededdc89e4afcb363698eee6dd31ddd5d5a6b2cbabd847b"}
{"label":"import-214","command":["timeout","-k","10","900","node","--test","packages/webui/tests/agents-browser.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gtNR","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":17.433,"mutant":false,"tests":2,"pass":2,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"e2c213130dbf80c125011ba8d45c016bfb347ebe1d21f1c64d1756e0db82d6f9"}
{"label":"import-215","command":["timeout","-k","10","900","node","--test","packages/webui/tests/agents.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gQRO","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.233,"mutant":false,"tests":9,"pass":9,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"c94baa2f42b463dee93e00cf1f3b1e60b287f109debf3a5a5133a8363b992d3a"}
{"label":"import-216","command":["timeout","-k","10","900","node","--test","packages/webui/tests/assistant.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gCyc","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.233,"mutant":false,"tests":6,"pass":6,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"1a32bdca8137c6aff24e9eee5c19dcadfef1e3a5f0aab5a45c600cf39c29e56e"}
{"label":"import-217","command":["timeout","-k","10","900","node","--test","packages/webui/tests/board-held.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gPDU","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":10.78,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"fb532481a6401e7097d1b7fd8c858885988e37529779c7e989885dd0de21f7e9"}
{"label":"import-218","command":["timeout","-k","10","900","node","--test","packages/webui/tests/browser-edge.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gw0B","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.748,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"f23507b59a89ff056564e71cda5e73b275ebc4de3130956b9cf69615af5aebe0"}
{"label":"import-219","command":["timeout","-k","10","900","node","--test","packages/webui/tests/browser.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gZfS","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":2.398,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"08f605ea6cfe1ec7b0f9d1a951a359e2e0106892dc56567152ed569548bff757"}
{"label":"import-220","command":["timeout","-k","10","900","node","--test","packages/webui/tests/bus-browser.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gjO2","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":3.795,"mutant":false,"tests":2,"pass":2,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"c03e5eaab52ea76d3b5ac1ccfbae6c25a2fab9f592aa45cd29bc6e22f3f45c3f"}
{"label":"import-221","command":["timeout","-k","10","900","node","--test","packages/webui/tests/bus.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g766","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":4.937,"mutant":false,"tests":10,"pass":10,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"703208aaab3751971784b6266b335c54f41048735650e92f40b6e8bd37ea9a6a"}
{"label":"import-222","command":["timeout","-k","10","900","node","--test","packages/webui/tests/channel-chat.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gyou","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.526,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"9dd425b57cb427c25265f7e1b4266cc9d9d09892d2de5ddf4c916635b66515c1"}
{"label":"import-223","command":["timeout","-k","10","900","node","--test","packages/webui/tests/chat-browser.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g5ri","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":40.593,"mutant":false,"tests":19,"pass":19,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"4a751781c8e1b9c4e1bbe9e1767d5d897c3cbb09ac4db39ea25d13c276e947cd"}
{"label":"import-224","command":["timeout","-k","10","900","node","--test","packages/webui/tests/chat-instances.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gypj","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.248,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"c43f61b93bbf092d23c0bfe9c6e85b76e4ded17b18d973c4a37832764df71f72"}
{"label":"import-225","command":["timeout","-k","10","900","node","--test","packages/webui/tests/chat-replies-browser.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gDNY","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":8.751,"mutant":false,"tests":11,"pass":11,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"f919fe31839c0bc40d4860c4f4412480a1016267c00b292fead32b36098031d5"}
{"label":"import-226","command":["timeout","-k","10","900","node","--test","packages/webui/tests/chat-sessions-access.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g9LK","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":4.741,"mutant":false,"tests":7,"pass":7,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"a4c4116cfd2a752d7efd2897430a9b2b052b6acf868c1ca8ce26b81ba9585812"}
{"label":"import-227","command":["timeout","-k","10","900","node","--test","packages/webui/tests/chat.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/go2w","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.849,"mutant":false,"tests":30,"pass":30,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"77d6c675d0a4534e84f4b2ce4eddf2135908dc5014469e74b87b6fdd3f63c130"}
{"label":"import-228","command":["timeout","-k","10","900","node","--test","packages/webui/tests/conversation.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/ga85","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":4.852,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"35d962e50a5a143e4dd8b816414c3044096d8907e807f50ca72eef81df9531ee"}
{"label":"import-229","command":["timeout","-k","10","900","node","--test","packages/webui/tests/decide-browser.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gd1n","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":12.017,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"559586deeaa79f7f28185318bf29e7ea28b4536c60bddbfdcdd337850104820a"}
{"label":"import-230","command":["timeout","-k","10","900","node","--test","packages/webui/tests/decide-sso.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gTYk","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.998,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"f277b7937f563610c111f75d55917ba1a6474b0cbf7edcc417f66ca1db9e77a8"}
{"label":"import-231","command":["timeout","-k","10","900","node","--test","packages/webui/tests/decision-http.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gesP","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.149,"mutant":false,"tests":9,"pass":9,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"1ae4314867f3da3d96bb8bd99bb9e4bb120610e4b4f76f266a4394d2c4cdac3d"}
{"label":"import-232","command":["timeout","-k","10","900","node","--test","packages/webui/tests/discord.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gROh","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.126,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"d1da3a8a99ae68e4e2c704b993c9f4fac1502f60dc21502abadad75584e212f1"}
{"label":"import-233","command":["timeout","-k","10","900","node","--test","packages/webui/tests/docs-browser.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gZtM","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.892,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"b126c48278cbe8276b5a1459b14cf00d1047ec686a80a82dfe509169e4d8aa7c"}
{"label":"import-234","command":["timeout","-k","10","900","node","--test","packages/webui/tests/editor-browser.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gJnO","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":23.444,"mutant":false,"tests":16,"pass":16,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"1053f032713f4a82d05003347cb02c6db54f6c554d3d549608615e3dcc835c83"}
{"label":"import-235","command":["timeout","-k","10","900","node","--test","packages/webui/tests/editor.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gLje","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":6.017,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"a1b78738684b0e0049cc5731f55b67cc21d83c0bd117a20ee094efcefbc926b9"}
{"label":"import-236","command":["timeout","-k","10","900","node","--test","packages/webui/tests/granted-user.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gH8T","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":6.001,"mutant":false,"tests":19,"pass":19,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"7e778058c0b4dfc5a44b1c95d146e3628f1401f18e5ca68d0eb5a2af2357fe16"}
{"label":"import-237","command":["timeout","-k","10","900","node","--test","packages/webui/tests/history-return-flow.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gOZs","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":56.725,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"1e74c166baa23c019edac72a0ce2735e7804112369ef6f6d12b4b30e0ed1a7a1"}
{"label":"import-238","command":["timeout","-k","10","900","node","--test","packages/webui/tests/instances-browser.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/goix","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":3.608,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"20da30c92fc5b9149e84cd2547aceac366f5509e8efbeb346b700d6f8cacc18b"}
{"label":"import-239","command":["timeout","-k","10","900","node","--test","packages/webui/tests/instances.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gr2y","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.265,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"0b0782580df886f98f4428ad6f94d33fa2d37d89c58d12c152964b26786d48fe"}
{"label":"import-240","command":["timeout","-k","10","900","node","--test","packages/webui/tests/library-cli.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gGV8","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.868,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"1e3617d918b4d7474e1acf9b5ad32732305aa86f8ad3044d488aac21f551cb4e"}
{"label":"import-241","command":["timeout","-k","10","900","node","--test","packages/webui/tests/library-routes.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gWxL","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.532,"mutant":false,"tests":13,"pass":13,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"d9729aef19f819e8190e6fdc9dbb1d7c4061f2311598f3785678cc81fbaea30e"}
{"label":"import-242","command":["timeout","-k","10","900","node","--test","packages/webui/tests/library-status.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gurC","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.265,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"99e68ba123769f5df8b60d9d12546d113f9f1f18f27b26a82738f4ac670fc18f"}
{"label":"import-243","command":["timeout","-k","10","900","node","--test","packages/webui/tests/limits-browser.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gq0e","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":4.598,"mutant":false,"tests":2,"pass":2,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"4d3b961b33557106779e969bdfb9aa959e01462a521d5368d9e7e560a4bab19b"}
{"label":"import-244","command":["timeout","-k","10","900","node","--test","packages/webui/tests/limits-route.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gK8P","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.561,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"2283f78868a29c6ebf37b0aaabc2fdfd84d0a381b3fd046d27902adf2710bfae"}
{"label":"import-245","command":["timeout","-k","10","900","node","--test","packages/webui/tests/messages.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gaaW","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":6.474,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"c2e137bf0cc8d12832a07cdb1f70f95dd3cc8ce34a500e6b0479f9d94bf4b300"}
{"label":"import-246","command":["timeout","-k","10","900","node","--test","packages/webui/tests/pinned-copy.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gG1M","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":7.925,"mutant":false,"tests":10,"pass":10,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"ebeca41fa26f042b9e877ddc3315254a60f98b947fb3eb9ccf098c4d455117b4"}
{"label":"import-247","command":["timeout","-k","10","900","node","--test","packages/webui/tests/preview.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gHU1","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.186,"mutant":false,"tests":11,"pass":11,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"4f0064f793bb36dbdf294fe77d67530afc0aea22f01b847aa1d00c3844469119"}
{"label":"import-248","command":["timeout","-k","10","900","node","--test","packages/webui/tests/processing-browser.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gkgO","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":8.863,"mutant":false,"tests":9,"pass":9,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"816a885bb9c45578982d7e43326cb77215e8cb29f557aa06e0efc39a26297e05"}
{"label":"import-249","command":["timeout","-k","10","900","node","--test","packages/webui/tests/processing.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gMEO","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.36,"mutant":false,"tests":6,"pass":6,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"d0d8b5325152e1919b5838bfd1b83c4551b52d69c60f07d0921eb95af6391222"}
{"label":"import-250","command":["timeout","-k","10","900","node","--test","packages/webui/tests/project-file.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g0K1","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.316,"mutant":false,"tests":10,"pass":10,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"52754ce30568e4d818370c3558342ab23d1292a67f692c1ded6a4d4b4121a029"}
{"label":"import-251","command":["timeout","-k","10","900","node","--test","packages/webui/tests/project-name-repo.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gRNU","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.132,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"324df0e70027674e99303723c75b02402d6ae43aefc73192e6c723644952fe98"}
{"label":"import-252","command":["timeout","-k","10","900","node","--test","packages/webui/tests/proof-cli.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gUya","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":2.557,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"9d0379c0dac670ea3b54331afee0d9da9c4c76a9c62315bd7cdf33458708b9b1"}
{"label":"import-253","command":["timeout","-k","10","900","node","--test","packages/webui/tests/proof.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gw3P","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.23,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"4b564ec494d8631518bd5e0a9dafce3492cc3655e90a82f12bc994fb0f48f017"}
{"label":"import-254","command":["timeout","-k","10","900","node","--test","packages/webui/tests/reads.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gDRG","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":2.251,"mutant":false,"tests":11,"pass":11,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"acd0a107da0270ad86ea4e75d1af8089f2541e1aa1c1613c10c35f47fcc38dea"}
{"label":"import-255","command":["timeout","-k","10","900","node","--test","packages/webui/tests/relaunch.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gDNA","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.062,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"b717bc82d68a804092878b6f68c73d970519d5dde6d9170a5cc3f417cd108c66"}
{"label":"import-256","command":["timeout","-k","10","900","node","--test","packages/webui/tests/return-flow.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/go3N","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":21.066,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"61fa95c4b8c802668f2b144954e8785c1a5d6e5f8d511646c61ae51abfcf899c"}
{"label":"import-257","command":["timeout","-k","10","900","node","--test","packages/webui/tests/room-browser.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/geyH","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":8.015,"mutant":false,"tests":9,"pass":9,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"65cd71916ae9b8b6a8d47a0175d5cca96ed6c3d93d65ea334338cc651c3529e7"}
{"label":"import-258","command":["timeout","-k","10","900","node","--test","packages/webui/tests/room-http.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gfgT","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.284,"mutant":false,"tests":7,"pass":7,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"32d8f63c7cbf6a67265e3ebb08eeda185061a94d2674c9e79da3e5ec9348ffaa"}
{"label":"import-259","command":["timeout","-k","10","900","node","--test","packages/webui/tests/routes-browser.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gqwx","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":2.226,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"915d721ef9ebb84e963f021957955ce02a7603a048fde2ba61bd7f87e70137ae"}
{"label":"import-260","command":["timeout","-k","10","900","node","--test","packages/webui/tests/routes.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gULI","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.499,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"f5cb0cbb1428122e4a826ebf11a304123af5e33696dc7c3c6e9a40105a7f59b5"}
{"label":"import-261","command":["timeout","-k","10","900","node","--test","packages/webui/tests/send-browser.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gV7T","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":14.209,"mutant":false,"tests":2,"pass":2,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"b76ab6c25710827dc2e6c7231b3aa82259cce1a88174a33f83a45c251ff4e8cf"}
{"label":"import-262","command":["timeout","-k","10","900","node","--test","packages/webui/tests/send.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gbPv","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.077,"mutant":false,"tests":13,"pass":13,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"51a759891344d96c63d9d554c0b0a0cb541acca3d3d139170805723a90f83201"}
{"label":"import-263","command":["timeout","-k","10","900","node","--test","packages/webui/tests/serve.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g9AU","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.835,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"38c0c60b3b161bcd2cc3642f551fafd755e7ff57aa3a1f9cfc4329f0333ade9d"}
{"label":"import-264","command":["timeout","-k","10","900","node","--test","packages/webui/tests/settings-form.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gp5I","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":5.17,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"305e2081fd87ffad6bae81ef0ea0a7732f9208a0fcd6ea73c8604de13af86210"}
{"label":"import-265","command":["timeout","-k","10","900","node","--test","packages/webui/tests/settings-write.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gQmT","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.2,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"604a5dfa84401b569a004ca35182684d0aefda4da8a34c833953c15d8047c238"}
{"label":"import-266","command":["timeout","-k","10","900","node","--test","packages/webui/tests/shell.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/goIy","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":8.597,"mutant":false,"tests":5,"pass":5,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"aa8226cc8ad92136f875f3a976de37dfc1b0ab30a3c24f2861c34fcd6355d002"}
{"label":"import-267","command":["timeout","-k","10","900","node","--test","packages/webui/tests/sso-browser.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gxVE","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":8.875,"mutant":false,"tests":2,"pass":2,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"37b3e8ed9a38b6a66600fee9386b5a414d6179a8630349c6f695075c1fb29806"}
{"label":"import-268","command":["timeout","-k","10","900","node","--test","packages/webui/tests/sso.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gsiS","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":8.274,"mutant":false,"tests":28,"pass":28,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"2f286ac4644f8789c2ede5261362f4c57bcf02b84671e9b6c2f5c2994368bfbe"}
{"label":"import-269","command":["timeout","-k","10","900","node","--test","packages/webui/tests/tester-browser.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g7am","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":4.164,"mutant":false,"tests":2,"pass":2,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"92727a4aee749943dc100d1b843f848ef75bbeeda29d693217882c71368c4d42"}
{"label":"import-270","command":["timeout","-k","10","900","node","--test","packages/webui/tests/tester-cli.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gz1T","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":11.668,"mutant":false,"tests":2,"pass":2,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"1c952ee8767467b1d1d4306e566b9b0f863d68215d30ae8ed3ab46d75ef46e8a"}
{"label":"import-271","command":["timeout","-k","10","900","node","--test","packages/webui/tests/tester-listener.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g99a","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":2.294,"mutant":false,"tests":11,"pass":11,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"b07648c44f522c5fa789c03634f248f63e8d312e9b93b7edd90d7951145d5419"}
{"label":"import-272","command":["timeout","-k","10","900","node","--test","packages/webui/tests/tester-socket.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gbnC","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.19,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"61704160b72bcd47d1e4166371e3ff65b148b7ef02b785f9427ef133d5ecdfb6"}
{"label":"import-273","command":["timeout","-k","10","900","node","--test","packages/webui/tests/thread-claims-browser.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gGv0","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":5.008,"mutant":false,"tests":6,"pass":6,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"9d3d03d3fc2a108a5e1da2c8e153db2a21bc1e08b207698e9c8eb242dff9905a"}
{"label":"import-274","command":["timeout","-k","10","900","node","--test","packages/webui/tests/thread-claims.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g09J","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.423,"mutant":false,"tests":4,"pass":4,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"2b031497a6d9d4b18d215d28bc04de28fe26a800c5a7d54af8052aab35eee3be"}
{"label":"import-275","command":["timeout","-k","10","900","node","--test","packages/webui/tests/thread-sharing.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gmhU","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":3.736,"mutant":false,"tests":7,"pass":7,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"9f7b307edc31c95fac9ce71f39ea02466a40a6d80c70d9db91f433a07e19adb7"}
{"label":"import-276","command":["timeout","-k","10","900","node","--test","packages/webui/tests/usage-browser.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/g1rW","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":1.032,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"819697b7c5cb3918c007b9fe57dd3f101c79afb9b5656905e5e1e1b0bc82de9f"}
{"label":"import-277","command":["timeout","-k","10","900","node","--test","packages/webui/tests/usage.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gHnS","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.238,"mutant":false,"tests":2,"pass":2,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"555da950dacca5dc85db7172b50aaef5e50e726c6e30bb66c770c0c38d58ab76"}
{"label":"import-278","command":["timeout","-k","10","900","node","--test","packages/webui/tests/user-option-swap.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gx24","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":0.38,"mutant":false,"tests":1,"pass":1,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"20bcc3985f5808a2d7f8daa02c5438fbac81c5163c117fde07bea3f46e8fa5b3"}
{"label":"import-279","command":["timeout","-k","10","900","node","--test","packages/webui/tests/views.test.mjs"],"TMPDIR":"/mnt/storage/scratch/tmp/gHJv","start_nice":19,"observed_timeout_nice":19,"exit":0,"seconds":5.483,"mutant":false,"tests":3,"pass":3,"fail":0,"cancelled":0,"skipped":0,"todo":0,"log_sha256":"dd69767c233e8eaeeb85ddaaf274380bbb6df73ec6cc7aaaadc6336053e4ddd8"}
```
Exact mutant edits (temporary only, all restored):
```text
{"mutant":"M1","edits":[["const SCOPES = Object.freeze(['canon', 'playground', 'supporting']);","const SCOPES = Object.freeze(['canon', 'playground']);"]],"path":"packages/library/src/query.mjs","oracle":"supporting find/search/get","killed":true,"restored_clean":true}
{"mutant":"M2","edits":[["file.scope !== requestedScope || ",""]],"path":"packages/library/src/query.mjs","oracle":"get without scope returns null","killed":true,"restored_clean":true}
{"mutant":"M3","edits":[["import { listTree } from './reader.mjs';","import { listTree, headCommit } from './reader.mjs';"],["listTree(source.repo, index.commit)","listTree(source.repo, await headCommit(source.repo))"]],"path":"packages/library/src/query.mjs","oracle":"each get blob equals its served tree object","killed":true,"restored_clean":true}
{"mutant":"M4","edits":[["}).sort((a, b) => SCOPE_RANK[index.files.get(a.path).scope] - SCOPE_RANK[index.files.get(b.path).scope]);","});"]],"path":"packages/library/src/query.mjs","oracle":"full outgoing and incoming links stay in scope order","killed":true,"restored_clean":true}
{"mutant":"M5","edits":[["return other !== undefined && sees(index.mapping, universe, other);","return other !== undefined && other.scope === requestedScope && sees(index.mapping, universe, other);"]],"path":"packages/library/src/query.mjs","oracle":"full outgoing and incoming links stay in scope order","killed":true,"restored_clean":true}
{"mutant":"M6","edits":[["file.scope === scope && sees(index.mapping, universe, file)","file.scope === scope"],["other !== undefined && sees(index.mapping, universe, other)","other !== undefined"]],"path":"packages/library/src/query.mjs","oracle":"full outgoing and incoming links stay in scope order","killed":true,"restored_clean":true}
{"mutant":"M7","edits":[["scopeArg(scope, MANUSCRIPT_SCOPES)","scopeArg(scope, SCOPES)"]],"path":"packages/library/src/query.mjs","oracle":"manuscript still refuses supporting","killed":true,"restored_clean":true}
{"mutant":"M8","edits":[["'library.get': { method: 'get', fields: ['universe', 'path', 'scope', 'from', 'links_from']","'library.get': { method: 'get', fields: ['universe', 'path', 'from', 'links_from']"]],"path":"packages/bus/src/broker.mjs","oracle":"broker forwards supporting scope","killed":true,"restored_clean":true}
{"mutant":"M9","edits":[["const manuscriptScope = str(\"canon by default; playground is opt-in\", { enum: [\"canon\", \"playground\"] });","const manuscriptScope = str(\"canon by default; playground is opt-in\", { enum: [\"canon\", \"playground\", \"supporting\"] });"]],"path":"packages/harness/src/tools.mjs","oracle":"scope schemas expand only find/search/get","killed":true,"restored_clean":true}
```
Sweep summary:
```text
{
"root_count": 289,
"matches": []
}
```
## sage-4310 — row329 landed-base rebase, 2026-10-24
Branch della/row284-r4 rebased the six commits in 95d4991d2..315e9c84f
onto origin/refactor 9e2689dffb24c9881724b67db982bc87d527157f. Old branch
della/row284-r2 and its crash handoff remain unchanged. No conflict hunks
occurred: Git replayed all six commits automatically; range-diff marks all
six patches equal. Thus no manual conflict resolution was required.
Inspected broker.mjs against the new base: the sole row284 delta adds scope
to library.get fields. Row329 proxy verbs and all other base broker code
are retained unchanged. No optimization or review-note behavior change added.
The new eight-path seal is stored outside Git in
/mnt/storage/scratch/della-row284-r2-evidence/manifest-r4.txt with sibling
manifest-r4.blobs.txt and range-diff-r4.txt. Base, final candidate tip and
manifest digest are in seal-r4.txt beside them (avoids a self-referential
BUILD hash). Prior test/mutant results above apply to the prior base only;
no test, mutant, Node, syntax check, dependency install or queue command
was run for this rebase. Explicit sage-4310 authorizes this untested push.
Worker runs and Sage landing gate wait for CLEAR after Webby delta review.
-299
View File
@@ -1,299 +0,0 @@
# Row 332 — P3 harness config from the model proxy
## Assignment and boundaries
2026-10-24: Fethry, thread 65673bd9-3bfa-412b-85d5-9b364187d8b6, branch fethry/row332, baseline c8a9bcf94. Sage assignment sage-4292; accepted brief plus full pi-routes amendment c8a9bcf94 (mos-1616). Gladstone first review, Dewey landing review; landing waits for P1/329 and P2/331, rebase on both and Sage's gate. No tests before Sage's CLEAR. No live proxy, host credential directories, real proxy data, management key, cutover, policy edits, or Codex harness changes.
Queue next in canonical checkout returned `nothing` during assignment. Starting row with op fethry-332-start met Sage's queue update lock; retry through the queue only. Root npm ci --ignore-scripts --no-audit --no-fund completed in this worktree (128 packages); no canonical node_modules use.
## Design note (line numbers at c8a9bcf94)
- packages/seat/src/session.mjs:242-247 defines ENV_ALLOW; keep it unchanged. sessionEnv:256-262 gains optional proxy context and drops CLAUDE_CODE_OAUTH_TOKEN, every passed ANTHROPIC_* variable, OPENAI_API_KEY, OPENROUTER_API_KEY and ZAI_API_KEY before adding harness env. Non-proxy results retain current behavior exactly.
- packages/plugins/harness/claude-code/index.mjs:56-67 preflight accepts the session proxy credential; env:119-126 sets ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN from that context.
- packages/plugins/harness/pi/index.mjs:33-36 preflight requires its own provider credential or proxy key, never a Claude OAuth token. env:63-70 sets only the session's proxy key as ANTHROPIC_API_KEY and selects the generated provider. Fresh run-local home/.pi/agent/models.json is private (0600; parent directories 0700). Every apiKey is the literal reference $ANTHROPIC_API_KEY; recursively forbid values beginning with !. Nothing stores the key in models.json or a manifest.
- packages/harness/src/bundle.mjs:313 buildBundle accepts transient proxy context; :379 harness.env call needs it plus run location and launch.models. Context must never be added to session metadata, source digests, or manifest. The run-local file regenerates on each launch.
- packages/cli/src/launcher.mjs:391,400 preflight, :412 account checks, :529 bundle creation and :592 child env must agree on the same session credential. Coordinate its acquisition with P2; build/test now against the specified { baseUrl, key } stand-in, not a management client or a key-store implementation.
Exact business setting keys remain launch.models.<selection>.provider, launch.models.<selection>.model, launch.account.name and launch.account.credential (launch.mjs:12-24,81-89). Provider already accepts proxy. Proposed account credential sentinel is the literal proxy (add alongside existing uppercase environment-set syntax), with launch.account.name a human-readable id such as proxy. No new fields. Existing provider anthropic selects the Anthropic route, zai selects GLM, and proxy selects the stack-owned GPT route; send this interpretation to Sage before implementation because the brief doesn't specify route encoding for provider proxy.
## Build-time API choice and pinned binary
P1's committed magica/row329 has CLIProxyAPI 8.0.42 in packages/model-proxy/PIN. Use that commit's fetchPinned({dataRoot:<fresh temporary root>}) implementation, copied from Git objects to this seat's temp tooling directory with its relative dependencies and PIN, until P1 lands. Never inspect another seat's worktree/scratch. It fetches only pinned GitHub release assets and checks archive, executable and panel hashes. No production instance config is needed and nothing under a real dataRoot/proxy is read.
After CLEAR, try actual pinned pi requests with both openai-responses and openai-completions through that binary under unshare -rn, against stand-in upstreams with made-up credentials under 24 characters. Record version, API path, safe request fields, response status and turn result. Choose one shape once from those results and hard-code it; no runtime fallback. Real Codex OAuth cannot be simulated as a real authenticated turn: first real Codex turn remains row209 phase A step7. Distinguish the offline compatibility evidence from that deferred real-auth proof.
The separate offline GLM acceptance script (outside scripts/test-*.sh) uses pinned pi and proxy, checks the upstream sees the model id from /v1/models, and records whether thinkingFormat/zaiToolStream-derived fields survive translation. All configs/auth placeholders belong to its fresh temp root.
## Implementation and test sequence
1. Add tests first for env isolation, Claude proxy env and preflight, pi credential refusal and each generated route/file invariant, and business account acceptance. Do not run until CLEAR; first new-test red is reported afterward, old-test red or second red is reported before changing anything.
2. Implement harness/bundle/env handling against P2's transient interface. Add launcher boundary integration once its exact P2 acquisition seam is agreed. Keep secrets out of session.json and bundle manifests.
3. With CLEAR, run the offline API-shape probe and GLM turn, then whole touched test files. Before each whole-file run report the list derived by parsing imports and traversing local dependencies; include harness plug-in dynamic loading explicitly. packages/cli/tests/case1-accept.test.mjs remains excluded without Mos approval.
4. Kill named mutants; restore production source and verify. Record exact output and nice. Use a fresh shell mktemp -d /mnt/storage/scratch/tmp/XXXXXX TMPDIR for each run, absolute nice 19, and timeout -k 10 for each scripts/test-*.sh. No hidden skips; Sage owns the package/script landing gate.
5. After dependency landings, rebase, complete review and gate stages, update queue only through its CLI, and append session/build receipts. Push only fethry/* when ready for authorized review; no force-push or attribution trailers.
Planned tests:
- Each forbidden environment variable is absent in proxy mode; all existing allowed env is identical without a proxy; two launches receive distinct own keys and no other agent's key.
- Claude env has exactly the supplied proxy base URL/auth token; proxy credential satisfies preflight without host upstream credentials.
- pi refuses no-session-credential for no key or Claude OAuth alone, accepts an own provider key and a proxy key.
- models.json covers Anthropic anthropic-messages at root URL, GLM openai-completions at /v1, and a stack-owned GPT provider at /v1 with the chosen API; routes use configured model ids.
- Every apiKey is $ANTHROPIC_API_KEY; no key value occurs in file; recursively no value starts with !; mode 0600 and private parents; next launch uses changed port/models/key reference with no stale content.
- Business accepts provider proxy and account credential proxy while preserving existing valid and invalid account behavior.
- Launcher/bundle integration keeps context transient and passes only the launch's own key.
- Every new refusal code gets a separate test.
- Offline GLM pinned-pi turn and z.ai compat observation; both GPT API-shape requests recorded with limitations.
Named gate mutants:
1. Proxy mode still passes CLAUDE_CODE_OAUTH_TOKEN (original brief).
2. models.json receives the key value instead of $ANTHROPIC_API_KEY (amendment).
No tests have run. API-shape choice is pending evidence, not claimed.
## Progress 22:27Z
Placed initial RED tests (not executed): packages/seat/tests/proxy-session-env.test.mjs and packages/plugins/tests/proxy-harness.test.mjs. These exercise real sessionEnv and loader-loaded harness exports. Production source remains untouched pending the first authorized RED run. Removed no assertions and ran no tests. Correct baseline bundle harness.env line is 376 (not 379 in the initial design note).
Sage reporting attempts fethry-0001 (including same-key retry) and fethry-0002 all returned `T3 GET /api/orchestration/threads/<sage> timed out after 30s`. Delivery is unconfirmed. Queue move retry also met a Sage queue update lock (sage-333-reviewers-1024a); no bypass.
Additional test-first placement: packages/business/tests/proxy-launch.test.mjs covers existing proxy model acceptance, proposed proxy account credential literal, preserved environment account forms, and rejection of mixed/literal credential strings. Pending Sage's route/account interpretation and CLEAR; no production edits or tests run.
## Import audit and queue status
The non-evaluating import audit uses Node vm.SourceTextModule.dependencySpecifiers, not a text-path grep, plus explicit computed-import edges from the plug-in loader to both harness modules. Source: import-run-list.mjs; output: IMPORT-RUN-LIST.txt (211 entries, including the explicitly EXCLUDED case1-accept file). This is a candidate impact list for the planned source changes, not an executed test list. Before a whole-file run, report the actual authorized subset to Sage. Parsing executes no repository modules and runs no tests. The first audit invocation had a path-depth setup error (ENOENT); corrected the audit's own repository root and regenerated successfully.
At 22:28:19Z the canonical start operation returned `queue: only the owner (sage) may start row 332`. Per assignment, wait at least two minutes before repeating this same op. No queue state was edited manually.
## Design correction after D9 re-read
The initial route-encoding proposal (provider proxy for GPT only) is not sufficient: design D9 explicitly defines provider proxy as any model through the instance proxy. Do not implement the earlier proposal. Two viable encodings need resolving before route-dependent tests/production: exact model-id lookup in pinned pi's provider catalogs (no new business fields, but refuses proxy-only aliases/unknown models), or explicit route metadata in launch.models (additive schema, needs Sage to confirm it is within the approved brief). Recommend exact catalog membership if all intended configured model ids are in pinned pi; otherwise ask Sage to define/approve an explicit route field. Never guess by model prefix or silently choose a wire API. Independent env/preflight tests already placed remain valid.
Reporting recovered: fethry-0004 was accepted by t3_send_message at approximately 22:29:51Z. It delivered the D9 route correction, route-encoding/P2-seam question, import-manifest location and no-tests status to Sage. Earlier failed-message deliveries remain unconfirmed.
22:32:18Z: The start retry issued at 22:30:40Z (over two minutes after first owner refusal) also exited 2: `queue: only the owner (sage) may start row 332`. This is an ownership boundary; row was not started and no code/test execution proceeds through it. Sage's assignment must take effect before the same op can succeed. The full design report fethry-0005 again timed out; fethry-0004 is the confirmed delivered report. git diff --check passed; no test, probe, commit or push has run.
## Route ruling accepted — sage-4293, 22:37Z
Sage settled explicit metadata, superseding both initial encoding proposals and the catalog proposal. Exact new setting: launch.models.<selection>.route; permitted values anthropic, glm, codex, required only when provider is proxy. Nonproxy entries still allow provider/model only. Missing route refuses proxy-route-missing; present unknown/nonstring route refuses proxy-route-unknown. Both get independent code assertions; each valid value gets a test using a proxy-only model id absent from any catalog. The GPT route's generated pi provider will be mosaic-proxy-codex, never openai-codex. Its wire API remains a build-time choice after the pinned-binary probe. P2 passes only {baseUrl,key}; no route belongs to that seam.
A key persistence hazard found during source inspection: launcher.mjs:571 writes bundle.env as session.harnessEnv. Adding the key to harness.env must not retain this behavior for credentials. P3 will keep generated key env transient for spawnSession and omit those credential values from serialized harnessEnv. runner.mjs:390 already inherits the spawn environment before applying nonsecret harnessEnv. Test the on-disk session/bundle boundary, not only models.json.
The old launch-settings.test.mjs already uses provider proxy fixtures without route. Update those fixtures to explicit anthropic routes before any full-file run; preserve their existing authorization assertions. This is the new approved validation shape, not permission to loosen tests. No tests have run and no production edits exist.
Additional test-first placement after route ruling: packages/harness/tests/proxy-bundle.test.mjs exercises real buildBundle with explicit provider proxy entries and proxy-only model ids, three generated providers, run-local file mode, environment references, recursive no-! values, no key in bundle files/manifest, fresh model/port/key on next launch. The exact GPT API assertion must be added from the authorized pinned-binary probe before this test file's first run; it deliberately makes no unverified wire-shape claim now. No skip is introduced.
Canonical queue show returned owner sage and after=331 at 22:40Z; it also warned `view unknown` for the rendered table. No repair or queue bypass attempted; wait for Sage's announced batch. Queue metadata identifies shared proxy Gitea issue #1830.
## STOPPED — mos-1630, 2026-10-24T22:48Z
Jason's relayed crash instruction supersedes active work: no long-job restart, commit/push safe documentation only, handoff in this worktree, no other thread messages, then stop. See HANDOFF.md for complete state, next steps, uncommitted tests/audit script, and reruns needed. No tests or probes ever ran; no production implementation exists. Latest design is explicit launch.models route metadata per sage-4293; earlier catalog/GPT-only proposals are superseded. The original 211-entry import manifest predates the fourth new test file and is historical, not run authorization. Full inline resends still hit T3 timeouts. Crash commit will exclude every unrun test and the audit script.
## Resumed — sage-4298, 2026-10-24T23:12Z
Resume authorized; crash-stop state above is historical. Sage accepts route spellings, refusal codes, mosaic-proxy-codex and launch.account.credential=proxy. Added third named mutant: **proxy key serialized into session.json**. Added an unrun real-launcher integration test in packages/cli/tests/launcher.test.mjs: a stand-in `{baseUrl,key}` enters via proposed createLauncher proxy option; real harness generation, session writer and runner must pass the key transiently while disk session/bundle files omit it. Adapter alone is fake. This catches restoring harnessEnv:bundle.env without credential separation. Existing test assertions are unchanged.
Regenerated IMPORT-RUN-LIST.txt with the non-evaluating import audit (static module dependencies plus explicit computed harness-loader edges). It now includes proxy-bundle.test.mjs; case1-accept remains explicitly EXCLUDED (mos-1612). Full manifest, touched tests and all three named mutants delivered inline to Sage using t3_code t3_thread_send, clientRequestId fethry-row332-resume-report-001, delivery steered. No unresolved route question remains. GPT API selection awaits CLEAR and pinned-binary evidence. Production implementation remains held for required first RED; tests/probes/fetches remain held for CLEAR. git diff --check clean.
Canonical queue next fethry started without timeout; no start retry until Sage confirms after-none write. Initial local-worktree queue invocation refused because queue requires canonical checkout; rerouted to canonical as required, no state bypass.
## Queue start retry — sage-4301, 2026-10-24T23:15Z
Sage reports after=none at rev4057. Retried canonical `scripts/mosaic queue move 332 in-progress --op fethry-332-start --by fethry` without a timeout. Awaiting its result; no duplicate command or manual queue edit. Lane B remains held and all tests/probes/fetches remain forbidden until CLEAR. Static review of test fixtures confirms launcher test uses the existing real-harness fake-adapter setup; initial RED remains unrun.
Start result: `ok fethry-332-start rev 4059 row 332 briefed→in-progress` (exit0). No tests/probes/fetches run.
## P1 rebase and pre-run reader stop — sage-4312/4313
Rebased onto 9e2689dff; current documentation checkpoint efe3e4697. Saved/restored all uncommitted notes/tests with named stash (retained for recovery). BUILD-LOG.md and SESSIONS.md append conflicts preserve both upstream and row332 entries. No production edits or force-push. git diff --check clean.
CLEAR received in sage-4313, conditional on pre-step reader check. STOP condition found before any test/probe/fetch: packages/cli/tests/launcher.test.mjs imports ./helpers.mjs, whose line10 imports BusError/Broker from ../../bus/src/broker.mjs (P1-changed path). The P3 test also starts the real broker through startHost. Report delivered to Sage as fethry-resume-0003, clientRequestId fethry-row332-p1-reader-stop. Await specific reader-chain authorization. No runs, counts or mutant outcomes exist. Mutant execution requires implementation reaching GREEN first; baseline RED will not be claimed as mutant evidence.
## First execution — sage-4316/4319, lane B, 2026-10-24
Reader chain authorized by sage-4316. Every run below used fresh shell `mktemp -d /mnt/storage/scratch/tmp/gXXX`, absolute nice19 (recorded), timeout -k10 (180s new files/300s whole launcher). No probes/fetches/mutants or case1-accept run. Logs are plain text in red/ beside this note.
| File | UTC start/end | pass/fail/skip | Classification |
| --- | --- | --- | --- |
| business proxy-launch | 23:41:37/23:41:37 | 2/4/0 | Expected missing route validation/account support |
| harness proxy-bundle | 23:41:42/23:41:42 | 0/5/0 | Fixture ERROR: assignment to frozen resolved.vars, not feature RED |
| plugins proxy-harness | 23:41:44/23:41:44 | 0/5/0 | Fixture ERROR: missing createLoader options, not feature RED |
| seat proxy-session-env | 23:41:50/23:41:50 | 1/1/0 | Expected instance OAuth leak |
| cli launcher (whole) | 23:41:55/23:42:25 | 34/1/0 | New P3 route rejected; all34 old tests pass |
Per sage-4319, fixed only the two new-file fixtures and committed b285e581e `fixture fix, untested` before rerunning. resolvedFor uses its mutation callback; createLoader receives {log(){}}. Existing launcher assertions were not changed.
| Corrected file | UTC start/end | pass/fail/skip | Classification |
| --- | --- | --- | --- |
| harness proxy-bundle | 23:42:41/23:42:41 | 0/5/0 | Another fixture ERROR: pm selects a/z/g absent from fixture launch.models; not valid feature RED |
| plugins proxy-harness | 23:42:41/23:42:41 | 1/4/0 | Valid feature REDs: missing Claude proxy URL/key and preflight; pi missing-credential refusals absent. Acceptance test already passes because existing pi preflight only checks binary; not proof of proxy credential behavior |
Stopped after exactly one authorized corrected run each. No edits/reruns after second harness fixture error; report to Sage before changes. Proposed follow-up: preserve valid fixture business routing, then overlay a test-local resolved vars object for buildBundle, or supply a coherent model table in callback. GPT API assertion still awaits authorized evidence and must precede a GREEN claim.
Stash created before rebase: 69ad35ec79805a0303ede4454f8d6815ddfa7bb3. Shared refs/stash must not be used again; entry remains untouched for Sage to clear. Future checkpoints use branch WIP commits.
Own-worktree node/chromium process sweep at23:42:57Z found only six tool-service processes predating tests (started23:12:08–23:12:10Z), no test node/chromium leftovers. Preserved tool services. No process killed. Lane B returned; mutants deferred until RED→fix→GREEN and later CLEAR with tip.
## Corrected bundle first valid RED — sage-4320
Only proxy-bundle.test.mjs edited: resolve a valid existing fixture business first, then copy resolved and vars locally, overlay harness/model, and assert selection exists in the supplied declared models table. Frozen original is untouched. Commit56701f715 `fixture fix, untested`, directly atop b285e581e, before execution.
Exactly one whole proxy-bundle run at23:44:40Z (start/end), fresh gXXX TMPDIR, nice19, timeout-k10/180s: 5tests,0pass,5fail,0skip,exit1. All five now reach real buildBundle and fail ENOENT on the required run/home/.pi/agent/models.json: missing production generation, valid feature RED rather than fixture errors. Earlier frozen-vars and unknown-model errors remain separately recorded. Log red/harness-corrected-2.txt. No production edits, further runs, mutants, probes or fetches. Lane B free.
Rebase made original origin/fethry/row332 diverge from local; publish current history on fethry/row332-p1 without force, preserving original remote checkpoint. Shared stash69ad35ec79805a0303ede4454f8d6815ddfa7bb3 remains untouched. Remaining uncommitted business/seat tests, launcher addition and audit source are not included in this two-fixture checkpoint.
## P3 implementation checkpoint — sage-4323/4325, UNRUN
Scope correction: sage-4322's P1 meant P3; no P1 code changed. Source edits authorized by sage-4323; all runs remain held. This is an implementation checkpoint, not GREEN or acceptance. Executing the established plan inline; user lane restrictions supersede skill test-run/commit defaults for this checkpoint.
Latest route ruling sage-4325 supersedes sage-4293/4298 and all earlier route-required notes: omitted proxy route means Anthropic and preserves the stored provider/model shape. Explicit anthropic/glm/codex routes remain accepted; unknown/present-invalid route refuses proxy-route-unknown. proxy-route-missing is withdrawn, not implemented. Other providers keep provider/model-only schema. Own business test updated for default; new bundle test exercises default generation without changing existing explicit-route assertions. launch-settings.test.mjs remains byte-unchanged.
Implementation in six production files:
- business launch validates optional proxy route, preserves omission, accepts account credential literal proxy.
- seat sessionEnv leaves ENV_ALLOW unchanged and filters provider variables only with proxy context.
- Claude accepts proxy credential preflight and returns proxy base/auth env; pi requires own provider key or proxy key, never Claude OAuth.
- bundle carries transient proxy/models to harness calls and propagates proxyRoute separately from primary/fallback route; no context in manifest.
- pi groups declared routes into run-local private models.json, references only $ANTHROPIC_API_KEY, refuses executable-looking model ids/key collisions, exclusive create and0700 parents/0600 file. No host auth reads. Generated file digest included in bundle manifest. Models use pi's documented default sizes/costs and reasoning support, with explicit z.ai compat for GLM; no catalog membership inference.
- launcher accepts the specified context stand-in or a per-agent factory, copies only baseUrl/key, carries it through repeated preflight checks and final bundle/spawn. Factory receives business/instance; P2 owns acquisition and may be called twice due to existing launch recheck. No P2 store/client calls invented. Provider credential variables split out at actual session.json serialization and delivered only through spawn env. Account proxy source validates against the supplied context, not host upstream variables.
### Old-test changes authorized by sage-4325 (baseline1e47b0919)
P3 item4 (rows brief pi preflight bullet, lines250-252) mandates refusal without proxy/own credential:
- plugins/tests/harness.test.mjs:102 before `assert.equal(pi.preflight({ env: {} }), null)`; after asserts `.code === no-session-credential`. Other assertions unchanged.
- cli/tests/launcher.test.mjs prepare():84 before only fake Claude OAuth; after additionally supplies ZAI_API_KEY=fx332-pi only when chief primary/fallback names pi. Other tests' assertions unchanged; Claude-only preparation does not receive it.
- cli/tests/launcher.test.mjs old no-credential pi test (sage reference697): before deletes OAuth then expects launch/pi and launch-log event; after also deletes newly supplied fake ZAI key, expects no-session-credential refusal, refused log code and no registered session. Test renamed to reflect mandated behavior. Existing no-session-credential Claude test unchanged.
No other old test was changed. Static review found these conflicts before execution and authorization preceded edits. No old-test RED occurred; baseline whole launcher had34 old passes.
### GPT wire API: PENDING
Single build-time value PROXY_CODEX_API=null in pi/index.mjs. A declared codex route refuses generation with a plain pending-evidence error until that value is settled; no guessed wire API, environment switch or runtime fallback. Consequently existing all-three-route bundle tests are not expected GREEN yet. P2 integration, full tests, pinned evidence, mutants and reviews remain pending.
Planned separate 4c evidence run (outside scripts/test-*.sh), requiring its own lane B CLEAR:
1. Use landed P1 fetchPinned only under a fresh owned temp root for the exact PIN (8.0.42). Fetch is a separately approved preparation, not part of offline networking. Verify hashes via P1; never use host installation or another seat's scratch.
2. Run the pinned proxy and local stand-in upstream inside unshare -rn with loopback enabled, empty private HOME/auth dir and a sanitized environment. No real auth file or network. All fake credentials under24 chars. Private test-only proxy config points only at the stand-in.
3. Generate two private probe-only pi model configs, one openai-responses and one openai-completions, both baseUrl=the isolated proxy/v1. Run pinned pi turns and record safe path/body shape fields, statuses, stream result and upstream observations, omitting auth/header values. These probe configs do not select the production constant.
4. Separately run the GLM completions turn under the same isolation and record whether thinkingFormat=zai/zaiToolStream-derived fields survive proxy translation.
5. If the offline stand-in cannot distinguish the two GPT shapes for the Codex-login route, report inconclusive evidence to Sage for Mos; do not select a value. A compatibility route cannot be reported as a real Codex-auth turn. First real Codex turn remains row209 phaseA step7.
No tests, probes, binary invocation or fetch ran during implementation. Import audit below is source parsing only, never repository evaluation. New run list includes the old harness.test.mjs touched under ruling; case1-accept remains EXCLUDED. Shared stash already cleared by Sage after1e47b0919 confirmation; no further stash operation used.
## Six whole files on a5330386c — sage-4326 lane B
Each ran exactly once, in requested order, no edits between runs and no reruns. Fresh shell gXXX TMPDIR per file; every log records nice19; timeout-k10/180s (launcher300s). No mutants/probes/fetches or extra impact files. Logs green-attempt/*.txt.
| File | pass/fail/skip | exit | UTC start/end |
| --- | --- | --- | --- |
| business | 6/0/0 | 0 | 23:57:06Z/23:57:06Z |
| seat | 2/0/0 | 0 | 23:57:06Z/23:57:06Z |
| proxy-harness | 5/0/0 | 0 | 23:57:06Z/23:57:06Z |
| harness | 9/0/0 | 0 | 23:57:12Z/23:57:12Z |
| proxy-bundle | 1/5/0 | 1 | 23:57:12Z/23:57:12Z |
| launcher | 34/1/0 | 1 | 23:57:12Z/23:57:42Z |
Expected-PENDING failures (each shared declared table includes codex), all stop before assertions with `Error: proxy GPT API is PENDING build-time evidence`:
- P3 Anthropic route uses messages at proxy root and the declared model id
- P3 GLM route uses completions at proxy /v1 with explicit z.ai compatibility
- P3 GPT route selects a stack-owned provider instead of pi Codex OAuth
- P3 models file is private, references the one session key, and stores no executable values or keys
- P3 every launch regenerates proxy port, declared models and own key without caching
The omitted-route-only bundle case passed. Five pending failures do not establish the remaining route/file assertions; no claim of GREEN.
Real old-test RED: `row 65 a failed primary preflight launches the fallback on a fixture harness module, recording the route and the reason` (launcher.test.mjs:714). First expected operation `await launcher.launchPm()` throws before the result assertions: `PM launch refused: no-session-credential (fallback fixture: pi needs its own provider key or a session proxy key (primary down: fixture preflight fails))`. Fixture harness re-exports real pi; prepare() recognized literal pi primary/fallback only, so it did not supply the needed own key. Reported to Sage as fethry-resume-0012 before any edit; no fix or rerun authorized/performed. P3 serialization test and all other launcher tests passed.
After all runs finished, changed only harness.test.mjs:100 title per sage-4326 to `row 65 pi preflight refuses missing credentials, and its version is the package pin`; assertion unchanged, no rerun for title. Sweep after end23:57:42Z found the same six pre-existing tool services (2699602,2699605,2700525,2700526,2700531,2700931), no test node/chromium leftovers; no process killed. Lane B free. No other source/test fixes in this follow-up.
## Fixture correction authorized — sage-4327
Old-test list addition: launcher.test.mjs row65 fallback test (line714 at e9fc105ac), before: no own pi credential before setup; after: this test alone sets given.f.env.ZAI_API_KEY=fx332-pi immediately before setup. All assertions unchanged; prepare() condition unchanged. Reason: P3 item4 requires pi own/proxy credential; this fixture inherits pi preflight. Prior real RED and first thrown error preserved above.
New proxy-bundle tests now supply explicit per-test declared tables: Anthropic only, omitted/default only, GLM only, GPT only; privacy/regeneration use Anthropic+GLM and retain every key/mode/no-executable assertion applicable to those routes. Regeneration additionally checks changed GLM endpoint/model. Added expected refusal test for declared Codex with pending build-time API; no production source changes. Only GPT generation test should remain expected-PENDING. Fixture fixes committed untested before exactly two authorized whole-file runs.
### Two-file fixture verification — sage-4327
Fixture checkpoint f1e8cda07, no source change. Exactly one run each, no edits between runs or reruns. nice19, fresh gXXX TMPDIR per file, timeout-k10/180s bundle and300s launcher. Logs fixture-r3/*.txt.
- proxy-bundle23:59:16Z:7tests,6pass,1fail,0skip,exit1. Sole expected-PENDING failure: `P3 GPT route selects a stack-owned provider instead of pi Codex OAuth`, error `proxy GPT API is PENDING build-time evidence`. All other route/privacy/regeneration cases and explicit pending-refusal case pass.
- launcher23:59:16–23:59:45Z:35tests,35pass,0fail,0skip,exit0. Row65 fallback assertions unchanged and now pass; P3 transient serialization case passes.
No failure other than expected GPT generation; GPT wire evidence, P2 integration/rebase, mutants and reviews still pending. Sweep shows only same six pre-existing node/chrome tool services, no test leftovers. Lane B free after23:59:45Z. No probes/fetches/mutants or extra tests run.
## Route-required correction — sage-4328 restores sage-4293
sage-4325 default-Anthropic ruling withdrawn. Explicit route required again: missing proxy-route-missing, present invalid proxy-route-unknown, distinct own tests. Removed generation/session-model defaults; bundle omitted-route test now asserts missing-route code. Active plug-in documentation corrected. No catalog/prefix inference.
Old-test list (baseline1da28a7bd): launch-settings.test.mjs41,154,161,188,198 object fixtures before provider:proxy/model only; after identical objects plus route:anthropic. Line45 before assignment models.opus.provider=proxy; after adds models.opus.route=anthropic. Every assertion byte-unchanged; no assertion relaxed. Authority/reason sage-4293 restored by sage-4328: D9 proxy is any upstream route and omission cannot select Anthropic silently.
Pre-run git-grep audit scoped 'packages/*/tests/*', saved route-required/proxy-fixture-grep.txt:16 model/assignment lines in four files. Positive controls matched launch-settings41 literal,45 assignment and intentional missing inputs proxy-launch14/proxy-bundle47. Broader quoted-proxy literal audit saved proxy-literal-grep.txt, manually reviewed for multiline entries. Remaining route omissions only intentional refusal cases (proxy-launch14,proxy-bundle47); unknown-route test uses route variable. All six old fixtures explicit; launcher155 and remaining bundle model literals explicit. Other broad hits are account sentinels, CLI argv or filesystem strings, not model table entries. Findings sent inline as fethry-resume-0015 BEFORE any tests. No other missing-route positive fixture found.
Committed untested per instruction; four whole-file runs follow under lane B CLEAR, no reruns or extra files. GPT offline run and P1 fetch remain unstarted and require separate explicit go.
### Required-route four-file verification — sage-4328
Tested9563fbc8b, exactly once per whole file in authorized order. No edits between runs, no reruns/extra tests. Each fresh gXXX TMPDIR,nice19,timeout-k10/180s (launcher300s). Plain logs route-required/*.txt.
| File | pass/fail/skip | exit | UTC start/end (2026-10-25) |
| --- | --- | --- | --- |
| proxy-launch | 6/0/0 | 0 | 00:01:47Z/00:01:47Z |
| launch-settings | 18/0/0 | 0 | 00:01:55Z/00:01:56Z |
| proxy-bundle | 6/1/0 | 1 | 00:01:56Z/00:01:56Z |
| launcher | 35/0/0 | 0 | 00:01:56Z/00:02:27Z |
Only failure: `P3 GPT route selects a stack-owned provider instead of pi Codex OAuth`, expected-PENDING error before assertions: proxy GPT API is PENDING build-time evidence. No other failures; missing-route and unknown-route separate-code tests pass; six old launch-settings fixture metadata changes preserve all assertions. All35 launcher tests pass.
Sweep after00:02:27Z: only same six pre-existing tool services; no test node/chromium leftovers and no process killed. Lane B free. GPT wire-shape evidence and P1 fetch NOT started; each still needs Sage explicit go/CLEAR. No mutants.
## GPT offline attempt1 and static diagnosis — sage-4329/4330
One authorized landed-P1 fetchPinned invocation succeeded, exact PIN8.0.42 executable SHA74661f8cf949977870231359e8bf4344e07946766a673c08fa25a3e5f72fc95e, panel1.26.7 SHA8c9c6b7d3fb311e6aad5d06e1993e53a2d28389e640448a1bc6304ed20b057b5. Fresh owned root named in evidence/root.txt, no alternate binary/new fetch. Fetch entry required nice19, end log observed16 due host renice; disclosed before continuing. Static-inspection invocation then failed entry nice guard before any binary read/launch; no turn. Main isolated attempt1 setPriority19 explicitly, but static binary tag scan again observed host renice16; subsequent child starts explicitly set19.
Attempt1 unshare-rn showed interfaces[lo], empty private HOME/auth and sanitized env. Proxy booted version8.0.42 commitbc064340, built2026-10-24T14:21:38Z. GET/v1/models response200 with modelIds[], script refused `stand-in routes absent from proxy catalog`; zero GPT-responses/GPT-completions/GLM pi turns ran, so zero compatibility evidence. Cleanup remainingManagedChildren0. No rerun under that CLEAR; reported0018. Raw sanitized receipt evidence/offline.txt preserved.
Startup network finding for P7/unit, plain text from isolated proxy log:
`failed to fetch latest Grok CLI version from npm, keeping fallback/cached version error=npm registry request failed: Get https://registry.npmjs.org/@xai-official/grok/latest: dial tcp [2606:4700::6810:122]:443: connect: network is unreachable`.
The namespace blocked external egress. Panel auto-update was disabled; this separate Grok version check still attempted startup egress. No real auth or host proxy touched.
### Static cause recorded BEFORE attempt2 (sage-4330)
No executable/probe invocation for diagnosis. Read the hash-pinned bundled management.html's config reader/serializer and P1 initialConfig in packages/model-proxy/src/settings.mjs. P1 produces nested server/management/access/oauth/observability/routing but adds no upstream provider config. Bundled panel Ip explicitly reads `api-keys.openai-compatibility`; zee reads e['api-keys'][provider]; Fp rejects groups without array group.keys; Np reads group name/base-url/keys/models; xv serializes a group with name,base-url,keys; hv serializes each key as api-key. Therefore the version8 payload is ROOT `api-keys: { openai-compatibility: [{name,base-url,keys:[{api-key}],models:[{name}]}] }`, distinct from the client allowlist under access.api-keys. Source excerpts/character offsets in evidence/bundled-panel-shape.txt; no header/auth values in receipts. This is actual pinned bundled UI reader/writer source, not a guessed provider nesting or an external/unpinned example.
Cause of first setup failure: my test used providers.openai-compatibility with api-key-entries, neither the root key nor the group-key field expected by that pinned writer. Initial readiness also stopped at first200 instead of waiting for required models; fixed to30s bound,1s intervals, model count logged per poll. Under sage-4330 one further isolated attempt only: reuse fetched binary and re-hash with P1 verifyInstall before launch; separate attempt2 test roots; actual pi turns each once, retry disabled in pi settings; API constant remains PENDING. Record/restore niceness for own descendants when host policy changes it. No actual turn has yet run as of this pre-attempt note.
## Offline attempt2 evidence — sage-4330, API STILL PENDING
Static diagnosis above preceded this one extra attempt. No new fetch. P1 verifyInstall recomputed existing executable/panel hashes before use and matched PIN8.0.42/panel1.26.7. unshare-rn verified only lo, empty private HOME/auth, sanitized env. Test config uses bundled writer's root api-keys.openai-compatibility/groups.keys shape. Readiness poll1 not-ready/modelCount0; poll2 status200/modelCount2; proxy lists gpt-fixture and glm-fixture. No setup failure on attempt2.
A transparent loopback HTTP tap captures pi's method/path and a whitelist of body shape fields; forwards original body bytes to pinned proxy; no header/auth values recorded. Upstream stand-in receives proxy output. Both remain inside network namespace. Each actual pi invocation once,50s timeout-k10; retry.enabled=false and provider.maxRetries=0 in private pi settings. Proxy has request-retry0. Outer isolation240s timeout-k10; no reruns. All three turn exits0 and marker P332_OFFLINE_OK observed:
| Turn | Pi request to proxy through transparent tap | Proxy response | Stand-in upstream observation |
| --- | --- | --- | --- |
| GPT responses | POST/v1/responses, modelgpt-fixture,streamtrue,reasoning={effort:low,summary:auto} |200,response.completed event, marker |POST/v1/chat/completions,reasoning_effort=low,max_tokens=16384,streamtrue |
| GPT completions | POST/v1/chat/completions, modelgpt-fixture,roles[developer,user],reasoning_effort=low,max_completion_tokens=16384 |200,completion stream marker |POST/v1/chat/completions,roles[developer,user],reasoning_effort=low,max_tokens=16384 |
| GLM completions | POST/v1/chat/completions,modelglm-fixture,thinking={type:enabled,clear_thinking:false},reasoning_effort=low,max_completion_tokens=16384 |200,completion stream marker |POST/v1/chat/completions,same thinking object and reasoning_effort retained,max_tokens=16384 |
GLM compatibility finding: thinkingFormat=zai-generated thinking.type=enabled/clear_thinking=false survives proxy translation, as does reasoning_effort=low. zaiToolStream-derived tool_stream was NOT emitted, because this turn disabled tools; its survival is NOT proven. Static pinned pi source node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js:612-618 sets params.tool_stream=true only with active tools and compat.zaiToolStream. No tool-call stream was exercised. This limitation is reported, not silently interpreted as pass or drop.
Both GPT shapes pass on the stand-in openai-compatibility credential route. This does not distinguish them for the Codex-login route; no Codex OAuth/auth file exists in this experiment. Evidence is INCONCLUSIVE for the production GPT choice. PROXY_CODEX_API remains null/PENDING; no source or API selection changed. Sage rules or takes to Mos per plan item5; first real Codex-auth turn stays row209 phaseA step7.
Niceness: attempt2 entry/emitted turn values19, explicit setPriority at entry/child start and100ms restore over owned descendants. Host policy temporarily changed processes to16 eight times; corrections restored19, disclosed here. Initial fetch end16 and failed inspection guard are retained separately, not represented as clean19 throughout. Full safe request/response receipts in evidence/offline-attempt2.txt; no auth/header value recorded. Process cleanup reports remainingManagedChildren0. Sweep over worktree and owned evidence root found same six pre-existing tool services only, no proxy/pi/timeout/chromium test leftovers. Lane B free. No mutants or other test files run.
## API choice and active-tool follow-up — sage-4331
Sage's ruling: PROXY_CODEX_API=openai-responses. The evidence does not separate the two shapes: both pass through pinned8.0.42. This is a tie broken on reasoning; it is NOT an evidence-decided pick. Sage's reason: Codex upstream speaks Responses natively and Responses carries pi's reasoning summary field, while completions drops that field; expected fewer translations/lost fields on the real route. This reasoning is a lead decision, not a claim of an authenticated Codex experiment. Row209 phaseA step7 verifies first real Codex turn; change the single constant if it fails there, with no runtime fallback/env switch. Earlier PENDING logs/notes remain historical evidence.
Set constant/remove pending refusal; GPT route test asserts openai-responses on mosaic-proxy-codex. Replaced temporary pending-refusal test with generated single-provider/responses/key-reference assertions per ruling. No other production change. Active plug-in docs updated.
Evidence script adds glm-tool mode: one GLM turn only, same pinned verified binary and isolated setup, distinct attempt3-tool root, active built-in read tool but stand-in still returns text only. Capture tool_stream and tool names before/after proxy, never header/auth values. No actual tool execution is demanded by stand-in, so this checks wire-field survival, not arbitrary tool-call semantics. Rehash before launch, no fetch,30s catalog readiness with counts,50s timeout-k10 for one turn,own descendants restored nice19. Commit untested before cleared run; then proxy-bundle and proxy-harness each whole once. No other runs/mutants.
### sage-4331 single active-tool GLM turn and two-file results
Tested ef0939e35. No fetch. P1 verifyInstall rehashed existing binary/panel and matched both PIN hashes before use. One isolated glm-tool run, unshare-rn interfaces[lo],empty private HOME/auth,sanitized env. Readiness poll1 not-ready/count0;poll2 status200/count2. One pi invocation with one active builtin read tool,exit0,markerP332_OFFLINE_OK; no rerun. Outer timeout-k10/140s,inner120s,pi50s;nice19 explicitly at entry/child starts and guard restores observed16→19 three times. No production API chosen by script.
Plain request/response evidence (full safe receipt evidence/glm-tool.txt):
- pi POST/v1/chat/completions modelglm-fixture,streamtrue,tools=[read],tool_stream=true,thinking={type:enabled,clear_thinking:false},reasoning_effort=low,max_completion_tokens=16384.
- pinned proxy200 completion stream,marker.
- stand-in receives POST/v1/chat/completions,tools=[read],tool_stream=true and same thinking/reasoning_effort fields;max_tokens=16384. Thus zaiToolStream-derived tool_stream survives this proxy route. No tool invocation or tool-call delta sequence was requested by the stand-in; this proves field survival with active tool, not every tool-call streaming semantic.
Then exactly once each whole file, fresh gXXX TMPDIR,nice19,timeout-k10/180s:
- packages/harness/tests/proxy-bundle.test.mjs00:14:20Z:7pass,0fail,0skip,exit0.
- packages/plugins/tests/proxy-harness.test.mjs00:14:20Z:5pass,0fail,0skip,exit0.
No failures, no extra runs/mutants. Cleanup managed children0. Own-worktree/evidence-root sweep found only same six pre-existing tool services,no proxy/pi/test/timeout/chromium leftovers. Lane B free. P3 now waits for P2/row331 landing before rebase,mutants,Gladstone review and further gates; no landing/merge requested or performed.
-51
View File
@@ -1,51 +0,0 @@
# STOPPED — row 332 (P3), T3 crash handoff
Stopped on 2026-10-24 under Mos mos-1630, relaying Jason's instruction: do not restart long jobs; commit/push safe work, leave a handoff, then stop. No further thread messages, tests, probes, queue operations, or implementation will run in this session.
## Branch and completed work
- Worktree: /home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332
- Branch: fethry/row332, based on refactor c8a9bcf94. No implementation commits, rebases, merges or production source edits.
- Read P3 brief, rules, full pi amendment, gate template, design and named source files. Detailed notes in BUILD.md beside this handoff.
- Root npm ci --ignore-scripts --no-audit --no-fund completed in this worktree only (128 packages). No canonical node_modules used.
- Initial test files written before implementation; none executed. Sage has not sent CLEAR. No proxy fetch, binary probe, offline turn, mutant, or suite has run.
- No real proxy, management key, host auth directory or live instance was accessed. No production service was started/stopped.
- Canonical queue next returned nothing during the assignment. Queue start op fethry-332-start refused on locks, then owner sage, including a retry after two minutes. Latest completed queue show still had owner sage, state briefed, after 331; it also warned that the rendered table was unknown. Did not repair or bypass it. Sage sage-4293 says an assign/after=none batch is running. Queue metadata identifies shared Gitea issue #1830.
## Latest accepted design
Sage sage-4293 supersedes all earlier route proposals: explicit route metadata, never catalog membership or model-prefix inference. Selected spelling: launch.models.<selection>.route = anthropic | glm | codex, required only with provider proxy. Missing route: proxy-route-missing; unknown/nonstring route: proxy-route-unknown. Other providers keep provider/model-only entries. Proposed launch.account.credential literal proxy; existing name/credential field names retained. GPT generated provider: mosaic-proxy-codex, never openai-codex. GPT wire API is still undecided pending the authorized pinned-binary requests. P2's seam stays exactly { baseUrl, key }.
Important implementation finding: launcher.mjs:571 serializes bundle.env into session.harnessEnv. Harness env will contain the session key in proxy mode, so credentials must instead reach spawnSession through transient environment variables and be omitted from serialized harnessEnv. runner.mjs:390 already inherits the spawn environment. Preserve ENV_ALLOW; filter instance provider variables in proxy mode only.
## Uncommitted work, intentionally left for the next session
These are unrun, incomplete tests/audit code, excluded from the documentation-only crash commit:
- packages/business/tests/proxy-launch.test.mjs — explicit routes and refusal codes, proxy account credential, existing nonproxy/account behavior.
- packages/plugins/tests/proxy-harness.test.mjs — Claude env/preflight, own-key isolation, pi preflight and OAuth-only refusal.
- packages/seat/tests/proxy-session-env.test.mjs — instance credential filtering and unchanged nonproxy env.
- packages/harness/tests/proxy-bundle.test.mjs — real bundle generation, all three providers, key reference/no-key/no-! invariants, file modes and launch freshness. Exact GPT API assertion deliberately pending probe evidence; add before its first run.
- agents/fethry/work/queue-332/import-run-list.mjs — non-evaluating static import audit using vm.SourceTextModule plus explicit computed loader edges. It ran successfully after correcting its own root-depth setup error. It is not a test runner.
IMPORT-RUN-LIST.txt is a historical 211-entry candidate impact list, generated before proxy-bundle.test.mjs was added. It includes case1-accept as explicitly EXCLUDED (mos-1612). Regenerate the list after resuming and report the actual authorized run list inline before any whole-file run. Do not treat the historical manifest as a current run authorization.
## Reporting status
T3 reporting repeatedly failed during GET with a 30-second timeout. fethry-0004 was confirmed delivered. Some later short numeric keys returned reused:true unexpectedly; do not rely on them as delivery evidence. A row-scoped detailed design resend and the inline 211-line import manifest also timed out, including the manifest's same-key retry. Sage may not have those messages. This handoff and BUILD.md are being pushed so they can be read with git show; no new thread message is sent under mos-1630.
## Next session, after restart authorization
1. Read this handoff/BUILD.md and recover queue state from canonical checkout. Wait for owner fethry and no after, then retry the same start op. Never bypass a refusal.
2. Recover Sage's slot status. Still NO tests or probes until Sage sends CLEAR. No job needs restarting merely to preserve current state.
3. Review the four uncommitted test files. Add the pinned-proxy API probe and exact GPT assertion before the first relevant run. Initial RED has not happened; production implementation must follow the authorized first RED.
4. Rebuild the import-derived run list and send it inline or in a reviewed pushed commit before runs. case1-accept remains off without Mos approval. Existing launch-settings.test.mjs proxy fixtures need explicit route metadata with their authorization assertions preserved; no old-test red has occurred.
5. Use P1's committed fetchPinned code under an owned fresh temporary root (8.0.42 at the inspected magica/row329 revision), never live proxy assets or another seat's scratch. After CLEAR, try pi's responses and completions requests under unshare -rn against stand-in upstream, record evidence, choose one GPT API at build time. Separately prove offline GLM and record z.ai compat survival. Real Codex auth proof remains row209 phase A step7.
6. Implement transient P2 context, model validation/route propagation, harness config, preflight, spawn env/serialization separation and tests. Named mutants: OAuth token leak; literal key in models.json. No policy or real credentials involved.
7. Land only after 329 and 331 land, rebasing on both, Gladstone first review, Dewey landing review and Sage's required gate. No force-push or merge authority is added by the crash instruction.
All future tests use a fresh shell-created short TMPDIR, absolute nice 19, and timeout -k 10 for scripts/test-*.sh. First new-test red is reportable afterward; old-test red or a second red goes to Sage before changes/reruns. No test outcomes are claimed here.
## Crash commit
Only documentation and the historical plain-text import manifest are committed. The final STOPPED reply records the exact pushed commit. The uncommitted files above remain deliberately available in this worktree because they have never run and test-slot authorization has not arrived.
@@ -1,213 +0,0 @@
packages/bus/tests/access-revoke.test.mjs
packages/bus/tests/broker.test.mjs
packages/bus/tests/channel-proof.test.mjs
packages/bus/tests/chief-of-staff.test.mjs
packages/bus/tests/citation-guard.test.mjs
packages/bus/tests/citation-runtime.test.mjs
packages/bus/tests/creative.test.mjs
packages/bus/tests/credential-verbs.test.mjs
packages/bus/tests/grant-scope-runtime.test.mjs
packages/bus/tests/host-run.test.mjs
packages/bus/tests/land.test.mjs
packages/bus/tests/library-credential.test.mjs
packages/bus/tests/library-lookups.test.mjs
packages/bus/tests/library-sync.test.mjs
packages/bus/tests/library.test.mjs
packages/bus/tests/lifecycle-revoke.test.mjs
packages/bus/tests/limit-checks.test.mjs
packages/bus/tests/messages.test.mjs
packages/bus/tests/processing-runtime.test.mjs
packages/bus/tests/project-runtime.test.mjs
packages/bus/tests/reload.test.mjs
packages/bus/tests/tasks.test.mjs
packages/bus/tests/tester-writes.test.mjs
packages/bus/tests/tester.test.mjs
packages/bus/tests/usage-runtime.test.mjs
packages/bus/tests/usage.test.mjs
packages/bus/tests/workflow-roles.test.mjs
packages/business/tests/access-levels.test.mjs
packages/business/tests/access.test.mjs
packages/business/tests/agent-identity.test.mjs
packages/business/tests/assistant.test.mjs
packages/business/tests/business.test.mjs
packages/business/tests/case1-business-file.test.mjs
packages/business/tests/chief-library-credentials.test.mjs
packages/business/tests/chief-of-staff.test.mjs
packages/business/tests/cli.test.mjs
packages/business/tests/credentials.test.mjs
packages/business/tests/csuite.test.mjs
packages/business/tests/grant-scope.test.mjs
packages/business/tests/hard-waits.test.mjs
packages/business/tests/hosts.test.mjs
packages/business/tests/instance-credential-transitions.test.mjs
packages/business/tests/instance-settings.test.mjs
packages/business/tests/launch-settings.test.mjs
packages/business/tests/library-projects-protected.test.mjs
packages/business/tests/library-seats.test.mjs
packages/business/tests/lifecycle-settings.test.mjs
packages/business/tests/optional-tracker.test.mjs
packages/business/tests/plugin-settings.test.mjs
packages/business/tests/project-repo.test.mjs
packages/business/tests/project.test.mjs
packages/business/tests/proxy-launch.test.mjs
packages/business/tests/record-grants.test.mjs
packages/business/tests/reply-limits.test.mjs
packages/business/tests/resolve.test.mjs
packages/business/tests/role.test.mjs
packages/business/tests/token-limit-settings.test.mjs
packages/business/tests/vars.test.mjs
packages/business/tests/workflow-roles.test.mjs
packages/cli/tests/access-boot.test.mjs
packages/cli/tests/access.test.mjs
packages/cli/tests/app.test.mjs
packages/cli/tests/boot-status.test.mjs
EXCLUDED (mos-1612) packages/cli/tests/case1-accept.test.mjs
packages/cli/tests/case1-hostcheck.test.mjs
packages/cli/tests/case2-install.test.mjs
packages/cli/tests/case2-persona-import.test.mjs
packages/cli/tests/case2-unit.test.mjs
packages/cli/tests/channel-cli.test.mjs
packages/cli/tests/channel-recovery.test.mjs
packages/cli/tests/cli.test.mjs
packages/cli/tests/compactions-launch.test.mjs
packages/cli/tests/config.test.mjs
packages/cli/tests/credentials.test.mjs
packages/cli/tests/federation-acceptance.test.mjs
packages/cli/tests/follow.test.mjs
packages/cli/tests/git-socket.test.mjs
packages/cli/tests/grants-scope.test.mjs
packages/cli/tests/grants.test.mjs
packages/cli/tests/host.test.mjs
packages/cli/tests/hosts.test.mjs
packages/cli/tests/idle-stop-race.test.mjs
packages/cli/tests/instances.test.mjs
packages/cli/tests/launch-account.test.mjs
packages/cli/tests/launch-limit-checks.test.mjs
packages/cli/tests/launch-limits.test.mjs
packages/cli/tests/launch-routes.test.mjs
packages/cli/tests/launcher.test.mjs
packages/cli/tests/lifecycle.test.mjs
packages/cli/tests/limits-tokens.test.mjs
packages/cli/tests/limits.test.mjs
packages/cli/tests/mark-read.test.mjs
packages/cli/tests/model-proxy.test.mjs
packages/cli/tests/names.test.mjs
packages/cli/tests/notifier.test.mjs
packages/cli/tests/optional-tracker.test.mjs
packages/cli/tests/other-tree.test.mjs
packages/cli/tests/processing-cli.test.mjs
packages/cli/tests/project-name-repo.test.mjs
packages/cli/tests/project.test.mjs
packages/cli/tests/publish-socket.test.mjs
packages/cli/tests/reply-limits.test.mjs
packages/cli/tests/revoke-window.test.mjs
packages/cli/tests/session-clear.test.mjs
packages/cli/tests/session-cli.test.mjs
packages/cli/tests/session-launch.test.mjs
packages/cli/tests/stack-copy.test.mjs
packages/cli/tests/stack-instances.test.mjs
packages/cli/tests/tester-reads.test.mjs
packages/cli/tests/tester-threads.test.mjs
packages/cli/tests/tester.test.mjs
packages/cli/tests/thread-cli.test.mjs
packages/cli/tests/thread-launch.test.mjs
packages/cli/tests/thread-revoke.test.mjs
packages/cli/tests/trackers-boot.test.mjs
packages/cli/tests/transport.test.mjs
packages/cli/tests/usage.test.mjs
packages/cli/tests/verbs.test.mjs
packages/control-board/tests/creative-hidden.test.mjs
packages/control-board/tests/discord.test.mjs
packages/control-board/tests/serve.test.mjs
packages/conversation/tests/flows.test.mjs
packages/harness/tests/bundle.test.mjs
packages/harness/tests/claude-gate.test.mjs
packages/harness/tests/claude-session.test.mjs
packages/harness/tests/creative.test.mjs
packages/harness/tests/gate.test.mjs
packages/harness/tests/git-tools.test.mjs
packages/harness/tests/library-tools.test.mjs
packages/harness/tests/mcp-server.test.mjs
packages/harness/tests/pi-session.test.mjs
packages/harness/tests/proxy-bundle.test.mjs
packages/harness/tests/raise-domain.test.mjs
packages/harness/tests/runner.test.mjs
packages/harness/tests/skills.test.mjs
packages/harness/tests/spec-tools.test.mjs
packages/harness/tests/tools.test.mjs
packages/plugins/tests/channel.test.mjs
packages/plugins/tests/harness-compactions.test.mjs
packages/plugins/tests/harness.test.mjs
packages/plugins/tests/loader.test.mjs
packages/plugins/tests/proxy-harness.test.mjs
packages/plugins/tests/searxng.test.mjs
packages/processing-control/tests/task.test.mjs
packages/seat/tests/compactions-budget.test.mjs
packages/seat/tests/compactions-ledger.test.mjs
packages/seat/tests/compactions.test.mjs
packages/seat/tests/proxy-session-env.test.mjs
packages/seat/tests/sandbox.test.mjs
packages/seat/tests/session-workspace.test.mjs
packages/seat/tests/session.test.mjs
packages/tasks/tests/fields.test.mjs
packages/webui/tests/agents-browser.test.mjs
packages/webui/tests/agents.test.mjs
packages/webui/tests/assistant.test.mjs
packages/webui/tests/board-held.test.mjs
packages/webui/tests/browser-edge.test.mjs
packages/webui/tests/browser.test.mjs
packages/webui/tests/bus-browser.test.mjs
packages/webui/tests/bus.test.mjs
packages/webui/tests/channel-chat.test.mjs
packages/webui/tests/chat-browser.test.mjs
packages/webui/tests/chat-instances.test.mjs
packages/webui/tests/chat-replies-browser.test.mjs
packages/webui/tests/chat.test.mjs
packages/webui/tests/conversation.test.mjs
packages/webui/tests/decide-browser.test.mjs
packages/webui/tests/decide-sso.test.mjs
packages/webui/tests/discord.test.mjs
packages/webui/tests/docs-browser.test.mjs
packages/webui/tests/editor-browser.test.mjs
packages/webui/tests/editor.test.mjs
packages/webui/tests/granted-user.test.mjs
packages/webui/tests/history-return-flow.test.mjs
packages/webui/tests/instances-browser.test.mjs
packages/webui/tests/instances.test.mjs
packages/webui/tests/library-cli.test.mjs
packages/webui/tests/library-routes.test.mjs
packages/webui/tests/limits-browser.test.mjs
packages/webui/tests/limits-route.test.mjs
packages/webui/tests/messages.test.mjs
packages/webui/tests/pinned-copy.test.mjs
packages/webui/tests/preview.test.mjs
packages/webui/tests/processing-browser.test.mjs
packages/webui/tests/processing.test.mjs
packages/webui/tests/project-file.test.mjs
packages/webui/tests/proof-cli.test.mjs
packages/webui/tests/proof.test.mjs
packages/webui/tests/reads.test.mjs
packages/webui/tests/relaunch.test.mjs
packages/webui/tests/return-flow.test.mjs
packages/webui/tests/room-browser.test.mjs
packages/webui/tests/room-http.test.mjs
packages/webui/tests/routes-browser.test.mjs
packages/webui/tests/routes.test.mjs
packages/webui/tests/send-browser.test.mjs
packages/webui/tests/send.test.mjs
packages/webui/tests/serve.test.mjs
packages/webui/tests/settings-form.test.mjs
packages/webui/tests/settings-write.test.mjs
packages/webui/tests/shell.test.mjs
packages/webui/tests/sso-browser.test.mjs
packages/webui/tests/sso.test.mjs
packages/webui/tests/tester-browser.test.mjs
packages/webui/tests/tester-cli.test.mjs
packages/webui/tests/tester-listener.test.mjs
packages/webui/tests/thread-claims-browser.test.mjs
packages/webui/tests/thread-claims.test.mjs
packages/webui/tests/thread-sharing.test.mjs
packages/webui/tests/usage-browser.test.mjs
packages/webui/tests/usage.test.mjs
packages/webui/tests/user-option-swap.test.mjs
packages/webui/tests/views.test.mjs
@@ -1,19 +0,0 @@
00:14:20Z
nice=19
✔ P3 Anthropic route uses messages at proxy root and the declared model id (12.070131ms)
✔ P3 omitted route refuses proxy-route-missing before model config generation (2.197623ms)
✔ P3 GLM route uses completions at proxy /v1 with explicit z.ai compatibility (3.390562ms)
✔ P3 GPT route selects a stack-owned provider instead of pi Codex OAuth (4.240948ms)
✔ P3 a declared Codex route generates only the single build-time responses provider (3.37448ms)
✔ P3 models file is private, references the one session key, and stores no executable values or keys (3.305299ms)
✔ P3 every launch regenerates proxy port, declared models and own key without caching (6.287121ms)
ℹ tests 7
ℹ suites 0
ℹ pass 7
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 128.759611
exit=0
00:14:20Z
@@ -1,17 +0,0 @@
00:14:20Z
nice=19
✔ P3 Claude env receives the session proxy URL and key, without another agent or host credential (3.096286ms)
✔ P3 Claude preflight accepts a proxy key without a host provider credential (1.305258ms)
✔ P3 pi refuses no-session-credential with no provider key (1.23137ms)
✔ P3 pi refuses no-session-credential with only a Claude OAuth token (3.659409ms)
✔ P3 pi accepts its own provider key or a session proxy key (0.590987ms)
ℹ tests 5
ℹ suites 0
ℹ pass 5
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 68.648537
exit=0
00:14:20Z
@@ -1,17 +0,0 @@
Ip=e=> @ char 1054606:
Ip=e=>{let t={raw:Dc(e)?e:{}};if(!Dc(e))return t;let n=t=>t.split(`.`).reduce((e,t)=>Dc(e)?e[t]:void 0,e);t.debug=wp(n(`observability.logs.debug`)),t.requestLog=wp(n(`observability.logs.request-log`)),t.loggingToFile=wp(n(`observability.logs.logging-to-file`));let r=n(`observability.logs.logs-max-total-size-mb`);typeof r==`number`&&(t.logsMaxTotalSizeMb=r);let i=n(`requests.proxy-url`);typeof i==`string`&&(t.proxyUrl=i);let a=n(`routing.retry.request-retry`);typeof a==`number`&&(t.requestRetry=a),t.wsAuth=wp(n(`oauth.providers.aistudio.ws-auth`))??!0,t.forceModelPrefix=wp(n(`routing.force-model-prefix`));let o=n(`routing.strategy`);typeof o==`string`&&(t.routingStrategy=o);let s=n(`access.api-keys`);return t.apiKeys=Array.isArray(s)?s.filter(e=>typeof e==`string`):[],t.quotaExceeded={antigravityCredits:wp(n(`oauth.providers.antigravity.antigravity-credits`))??!1},t.providerGroups=Dc(e[`api-keys`])?e[`api-keys`]:{},t.geminiApiKeys=Fp(n(`api-keys.gemini`)),t.interactionsApiKeys=Fp(n(`api-keys.interactions`)),t.codexApiKeys=Fp(n(`api-keys.codex`)),t.metaApiKeys=Fp(n(`api-keys.meta`)),t.xaiApiKeys=Fp(n(`api-keys.xai`)),t.claudeApiKeys=Fp(n(`api-keys.claude`)),t.vertexApiKeys=Fp(n(`api-keys.vertex`)),t.openaiCompatibility=Fp(n(`api-keys.openai-compatibility`),!0),t.oauthExcludedModels=Pp(n(`oauth.excluded-models`)),t},Lp={async getConfig(){return Ip(await W.get(`/config`))},updateRequestLog:e=>W.put(`/config/observability/logs/request-log`,e)},Rp=0,zp=null,Bp=null,Vp=()=>Bp!==null&&Date.now()-Bp.timestamp<3e4,Hp=Tc((e,t)=>({config:null,fetchConfig:async(t=!1)=>{if(!t&&Bp&&Vp())return Bp.data;if(zp)return zp.promise;let n=Rp+=1;try{let t=Lp.getConfig();zp={id:n,promise:t};let r
Fp=(e,t= @ char 1054198:
Fp=(e,t=!1)=>Array.isArray(e)?e.flatMap((n,r)=>{if(!Dc(n)||!Array.isArray(n.keys))return[];if(t){let t=Np(n,r);return t?[{...t,source:{groupIndex:r,group:n,groups:e}}]:[]}return n.keys.flatMap((t,i)=>{if(!Dc(t))return[];let a={...n};delete a.keys,delete a.name,Object.entries(t).forEach(([e,t])=>{t!==null&&(a[e]=t)});let o=Mp(a);return o?[{...o,source:{groupIndex:r,keyIndex:i,group:n,groups:e}}]:[]})}):[],Ip=e=>{let t={raw:Dc(e)?e:{}};if(!Dc(e))return t;let n=t=>t.split(`.`).reduce((e,t)=>Dc(e)?e[t]:void 0,e);t.debug=wp(n(`observability.logs.debug`)),t.requestLog=wp(n(`observability.logs.reques
Np=(e,t)=> @ char 1053331:
Np=(e,t)=>{if(!Dc(e))return null;let n=e.name,r=e[`base-url`];if(!n||!r)return null;let i=Array.isArray(e.keys)?e.keys.map((e,t)=>{let n=Ap(e);return n?{...n,sourceIndex:t}:null}).filter(Boolean):[],a=Ep(e.headers),o=Tp(e.models),s=e.priority,c={name:String(n),baseUrl:String(r),apiKeyEntries:i,...jp(e)},l=wp(e[`support-prompt-cache-key`]);l!==void 0&&(c.supportPromptCacheKey=l);let u=wp(e.disabled);u!==void 0&&(c.disabled=u);let d=wp(e[`disable-cooling`]);d!==void 0&&(c.disableCooling=d);let f=Op(e.prefix);f&&(c.prefix=f),a&&(c.headers=a),o.length&&(c.models=o),s!==void 0&&(c.priority=Number(s));let p=kp(e[`auth-index`]);return p&&(c.authIndex=p),t!==void 0&&(c.sourceIndex=t),c},Pp=e=>{if(!Dc(e))return;let t=e;if(!Dc(t))return;let n={};return Object.entries(t).forEach(([e,t])=>{let r=String(e||``).trim();if(!r)return;let i=Dp(t);n[r.toLow
xv=e=> @ char 1129493:
xv=e=>{let t={name:e.name,"base-url":e.baseUrl,...gv(e),keys:Array.isArray(e.apiKeyEntries)?e.apiKeyEntries.map(e=>hv(e)):[]};e.prefix?.trim()&&(t.prefix=e.prefix.trim()),e.disabled!==void 0&&(t.disabled=e.disabled),e.supportPromptCacheKey!==void 0&&(t[`support-prompt-cache-key`]=e.supportPromptCacheKey);let n=pv(e.headers);n&&(t.headers=n);let r=mv(e.models,!0);return r&&r.length&&(t.models=r),e.priority!==void 0&&(t.priority=e.priority),e.disableCooling!==void 0&&(t[`disable-cooling`]=e.disableCooling),t},Sv=(e,t)=>{if(e===t)return!0;if(Array.isArray(e)&&Array.isArray(t))return e.length===t.length&&e.every((e,n)=>Sv(e,t[n]));if(Dc(e)&&Dc(t)){let n=Object.keys(e).filter(t=>e[t]!==void 0);re
hv=e=> @ char 1126395:
hv=e=>{let t={"api-key":e.apiKey};return e.proxyUrl&&(t[`proxy-url`]=e.proxyUrl),e.weight!==void 0&&(t.weight=e.weight),t},gv=(e,t=!0)=>{let n={};return e.requestRetry!==void 0&&(n[`request-retry`]=e.requestRetry),t&&e.r
zee=(e,t)=> @ char 1130380:
zee=(e,t)=>{if(!Dc(e)||!Dc(e[`api-keys`]))return[];let n=e[`api-keys`][t];if(n===void 0)return[];if(!Array.isArray(n)||!n.every(e=>Dc(e)&&Array.isArray(e.keys)))throw Cv();return n},wv=async e=>{let t=cv(),n=Nm.getState(),r=await W.get(`/config`);t();let i=Nm.getState();if(n.apiBase!==i.apiBase||n.managementKey!==i.managementKey||n.isAuthenticated!==i.isAuthenticated)throw Cv();return zee(r,e)},Tv
@@ -1,11 +0,0 @@
file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/agents/fethry/work/queue-332/proxy-evidence.mjs:9
if (getPriority(0) !== 19) throw Error('nice19 required');
^
Error: nice19 required
at file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/agents/fethry/work/queue-332/proxy-evidence.mjs:9:34
at ModuleJob.run (node:internal/modules/esm/module_job:569:25)
at async node:internal/modules/esm/loader:650:26
at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:101:5)
Node.js v26.8.1
@@ -1 +0,0 @@
{"phase":"fetch","version":"8.0.42","binarySha256":"74661f8cf949977870231359e8bf4344e07946766a673c08fa25a3e5f72fc95e","panelVersion":"1.26.7","panelSha256":"8c9c6b7d3fb311e6aad5d06e1993e53a2d28389e640448a1bc6304ed20b057b5","nice":16,"verified":true}
@@ -1,8 +0,0 @@
{"phase":"isolation","interfaces":["lo"],"enteredNice":19,"nice":19,"version":"8.0.42","binarySha256":"74661f8cf949977870231359e8bf4344e07946766a673c08fa25a3e5f72fc95e","panelSha256":"8c9c6b7d3fb311e6aad5d06e1993e53a2d28389e640448a1bc6304ed20b057b5","reverified":true}
{"phase":"readiness","poll":1,"status":"not-ready","modelCount":0}
{"phase":"readiness","poll":2,"status":200,"modelCount":2}
{"phase":"catalog","modelIds":["gpt-fixture","glm-fixture"]}
{"phase":"turn","name":"glm-completions-tool","api":"openai-completions","exit":0,"signal":null,"marker":true,"piRequests":[{"method":"POST","path":"/v1/chat/completions","keys":["max_completion_tokens","messages","model","reasoning_effort","store","stream","stream_options","thinking","tool_stream","tools"],"model":"glm-fixture","stream":true,"roles":["developer","user"],"inputTypes":"undefined","thinking":{"type":"enabled","clear_thinking":false},"reasoning_effort":"low","tool_stream":true,"toolNames":["read"],"stream_options":{"include_usage":true},"max_completion_tokens":16384}],"proxyResponses":[{"request":0,"status":200,"events":[],"marker":true}],"upstreamRequests":[{"method":"POST","path":"/v1/chat/completions","keys":["max_tokens","messages","model","reasoning_effort","store","stream","stream_options","thinking","tool_stream","tools"],"model":"glm-fixture","stream":true,"roles":["developer","user"],"inputTypes":"undefined","thinking":{"type":"enabled","clear_thinking":false},"reasoning_effort":"low","tool_stream":true,"toolNames":["read"],"stream_options":{"include_usage":true},"max_tokens":16384}],"nice":19}
{"phase":"conclusion","limitation":"Stand-in openai-compatibility credential only; no Codex OAuth credential or real-auth turn. This script never selects the production API."}
{"phase":"nice-corrections","restoredTo":19,"observedBeforeRestore":{"16":3}}
{"phase":"cleanup","remainingManagedChildren":0}
@@ -1,10 +0,0 @@
{"phase":"isolation","interfaces":["lo"],"enteredNice":19,"nice":19,"version":"8.0.42","binarySha256":"74661f8cf949977870231359e8bf4344e07946766a673c08fa25a3e5f72fc95e","panelSha256":"8c9c6b7d3fb311e6aad5d06e1993e53a2d28389e640448a1bc6304ed20b057b5","reverified":true}
{"phase":"readiness","poll":1,"status":"not-ready","modelCount":0}
{"phase":"readiness","poll":2,"status":200,"modelCount":2}
{"phase":"catalog","modelIds":["gpt-fixture","glm-fixture"]}
{"phase":"turn","name":"gpt-responses","api":"openai-responses","exit":0,"signal":null,"marker":true,"piRequests":[{"method":"POST","path":"/v1/responses","keys":["include","input","max_output_tokens","model","prompt_cache_key","reasoning","store","stream"],"model":"gpt-fixture","stream":true,"inputTypes":[null,null],"reasoning":{"effort":"low","summary":"auto"}}],"proxyResponses":[{"request":0,"status":200,"events":["response.created","response.in_progress","response.output_item.added","response.content_part.added","response.output_text.delta","response.output_text.done","response.content_part.done","response.output_item.done","response.completed"],"marker":true}],"upstreamRequests":[{"method":"POST","path":"/v1/chat/completions","keys":["max_tokens","messages","model","reasoning_effort","stream","stream_options"],"model":"gpt-fixture","stream":true,"roles":["user","user"],"inputTypes":"undefined","reasoning_effort":"low","stream_options":{"include_usage":true},"max_tokens":16384}],"nice":19}
{"phase":"turn","name":"gpt-completions","api":"openai-completions","exit":0,"signal":null,"marker":true,"piRequests":[{"method":"POST","path":"/v1/chat/completions","keys":["max_completion_tokens","messages","model","reasoning_effort","store","stream","stream_options"],"model":"gpt-fixture","stream":true,"roles":["developer","user"],"inputTypes":"undefined","reasoning_effort":"low","stream_options":{"include_usage":true},"max_completion_tokens":16384}],"proxyResponses":[{"request":1,"status":200,"events":[],"marker":true}],"upstreamRequests":[{"method":"POST","path":"/v1/chat/completions","keys":["max_tokens","messages","model","reasoning_effort","store","stream","stream_options"],"model":"gpt-fixture","stream":true,"roles":["developer","user"],"inputTypes":"undefined","reasoning_effort":"low","stream_options":{"include_usage":true},"max_tokens":16384}],"nice":19}
{"phase":"turn","name":"glm-completions","api":"openai-completions","exit":0,"signal":null,"marker":true,"piRequests":[{"method":"POST","path":"/v1/chat/completions","keys":["max_completion_tokens","messages","model","reasoning_effort","store","stream","stream_options","thinking"],"model":"glm-fixture","stream":true,"roles":["developer","user"],"inputTypes":"undefined","thinking":{"type":"enabled","clear_thinking":false},"reasoning_effort":"low","stream_options":{"include_usage":true},"max_completion_tokens":16384}],"proxyResponses":[{"request":2,"status":200,"events":[],"marker":true}],"upstreamRequests":[{"method":"POST","path":"/v1/chat/completions","keys":["max_tokens","messages","model","reasoning_effort","store","stream","stream_options","thinking"],"model":"glm-fixture","stream":true,"roles":["developer","user"],"inputTypes":"undefined","thinking":{"type":"enabled","clear_thinking":false},"reasoning_effort":"low","stream_options":{"include_usage":true},"max_tokens":16384}],"nice":19}
{"phase":"conclusion","limitation":"Stand-in openai-compatibility credential only; no Codex OAuth credential or real-auth turn. API value remains PENDING."}
{"phase":"nice-corrections","restoredTo":19,"observedBeforeRestore":{"16":8}}
{"phase":"cleanup","remainingManagedChildren":0}
@@ -1,4 +0,0 @@
{"phase":"isolation","interfaces":["lo"],"enteredNice":19,"nice":16,"version":"8.0.42","configTags":["ntptr; X0 []string } \"*struct { F uintptr; X0 net.Conn } Models yaml:\"models\" json:\"models\" \"*config.DisableImageGene","ubscriptionCommand $*struct { F uintptr; R *api.Server } APIKey yaml:\"api-key\" json:\"api-key\" $EffectiveSignInWithChat","on:\\\"type\\\"\" } '*struct { F uintptr; X0 *bufio.Reader } BaseURL yaml:\"base-url\" json:\"base-url\" '*config.CodexWebSearch","ise-management\" json:\"advertise-management\" OpenAICompatibility7yaml:\"openai-compatibility\" json:\"openai-compatibility\" K*struct { "]}
{"phase":"catalog","modelIds":[]}
{"phase":"error","message":"stand-in routes absent from proxy catalog","proxyDiagnostic":"CLIProxyAPI Version: 8.0.42, Commit: bc064340, BuiltAt: 2026-10-24T14:21:38Z\n[2026-10-24 19:07:27] [--------] [info ] [main.go:641] CLIProxyAPI Version: 8.0.42, Commit: bc064340, BuiltAt: 2026-10-24T14:21:38Z\n[2026-10-24 19:07:27] [--------] [info ] [main.go:752] Local model mode: using embedded catalogs unless an explicit catalog source is configured\n[2026-10-24 19:07:27] [--------] [info ] [antigravity_version.go:71] periodic antigravity version refresh started (interval=3h0m0s)\n[2026-10-24 19:07:27] [--------] [info ] [service_lifecycle.go:103] core auth auto-refresh started (interval=15m0s)\n[2026-10-24 19:07:27] [--------] [info ] [server_management.go:22] management routes registered after secret key configuration\n[2026-10-24 19:07:27] [--------] [warn ] [xai_version.go:96] failed to fetch latest Grok CLI version from npm, keeping fallback/cached version error=npm registry request failed: Get \"https://registry.npmjs.org/@xai-official/grok/latest\": dial tcp [2606:4700::6810:122]:443: connect: network is unreachable\n[2026-10-24 19:07:27] [--------] [info ] [xai_version.go:79] periodic Grok CLI version refresh started (interval=3h0m0s)\n[2026-10-24 19:07:27] [b7852b37] [info ] [gin_logger.go:113] 200 | 0s | 127.0.0.1 | GET \"/v1/models\"\n"}
{"phase":"cleanup","remainingManagedChildren":0}
@@ -1 +0,0 @@
/mnt/storage/scratch/tmp/g2Ta
@@ -1,63 +0,0 @@
23:59:16Z
nice=19
✔ C2-04: launcher workspace clones code but never the library (1450.400805ms)
✔ P3 proxy key reaches the spawned runner but never session.json or the bundle (1347.117393ms)
✔ bus start --pm: the launcher instance (the chief of staff) runs under its own PID namespace, registered, with a manifest (1362.533548ms)
usage: {"event":"usage-unknown","business":"acme","run":"r5c4bfddc2d03","instance":"chief","turn":"2ce6282a-5e4f-4276-851e-3d8dd2d53a7a","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"rf9b4b14789bc","instance":"coder","turn":"d7a0db99-cce3-417f-8e7d-9910641f0860","source":"@none","code":"baseline-unknown"}
✔ the chief of staff launches a coder through its launch tool; the coder answers; refusals name their code (842.489432ms)
usage: {"event":"usage-unknown","business":"acme","run":"rd5fa76df3fb0","instance":"chief","turn":"f739ef1e-c01f-401f-9a89-cf45bc15b976","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"r2c414ea1d43f","instance":"pm","turn":"8852a197-c1be-4108-a3af-34dad0232264","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"rd5fa76df3fb0","instance":"chief","turn":"6ccde05e-202a-43af-8556-43481f552676","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"rd5fa76df3fb0","instance":"chief","turn":"4a8f168b-8676-4b54-9404-174a2a703fcf","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"r2c414ea1d43f","instance":"pm","turn":"67ee96fd-1338-48aa-a4fc-edbb7e0aef0e","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"r2c414ea1d43f","instance":"pm","turn":"ead68527-7bf4-49a1-8fd7-0107b9c6dfdf","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"rd5fa76df3fb0","instance":"chief","turn":"c1cc3a5e-1afe-4994-aea4-a3ea811a8f30","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"r2c414ea1d43f","instance":"pm","turn":"e60723f6-187d-4b55-bd81-66189ae014c0","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"rd5fa76df3fb0","instance":"chief","turn":"1b7721ee-a337-4623-9fcc-1e05277336ce","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 (1152.112093ms)
✔ each launch makes sure the workspace has a clone of the project: cloned, fast-forwarded, or fetched and logged (4210.704487ms)
✔ a role the broker says holds a merge decision gets land_work, its prompt line, its landing and the git socket; without it, none (713.043698ms)
✔ 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 (456.475273ms)
usage: {"event":"usage-unknown","business":"acme","run":"r0e259f41ad4d","instance":"coder","turn":"52bb41d8-5eb6-4c72-9c5c-0b8abf8eae42","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 (838.095383ms)
✔ a landing run that ended isn't started again for its decision, a spent decision starts nothing, and a new decision starts the holder (721.283915ms)
✔ after a restart, the new host's first tick starts a holder whose decision is still held (963.365086ms)
✔ 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 (708.305295ms)
✔ a project clone that can't be made refuses checkout-failed, from --chief and from a session, with no run and no clone left (300.51414ms)
✔ a runner that stops at once ends its launch with the runner's reason (380.448961ms)
✔ a Claude Code launch with no session credential refuses before it starts (206.153531ms)
✔ a pi launch with no own credential refuses no-session-credential (207.22057ms)
usage: {"event":"plugin-refused","kind":"harness","name":"down","code":"missing","message":"/home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/harness/down is missing","kept":[]}
plugins: {"event":"plugin-refused","kind":"harness","name":"down","code":"missing","message":"/home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/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 (398.352887ms)
✔ a runner killed from the host ends its launch as killed, not failed (418.567314ms)
✔ a missing or failing bwrap refuses sandbox-unavailable before anything starts; there is no unconfined fallback (211.208923ms)
✔ 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 (215.670064ms)
✔ row 213 a creative instance's persona is read from <configDir>/personas: off its digest the launch fails with the mismatch as its reason (321.498853ms)
✔ row 64 on Claude Code a role skill that isn't enabled refuses the same way, before anything starts (208.543617ms)
usage: {"event":"usage-unknown","business":"acme","run":"r1f065863b517","instance":"chief","turn":"2c19dcc1-343e-4c12-93e3-4cd6dd65c4d9","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"reae1621f7ddf","instance":"coder","turn":"03cc3667-aab3-4f55-9e57-bf637e1be0dc","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 (1566.080686ms)
✔ 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 (1164.65123ms)
✔ 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 (4189.297007ms)
✔ bus start --no-launch leaves an earlier host's live session alone: no signal, no end, sessions.json as it was (258.381919ms)
✔ bus start --no-launch refuses every launch: the PM launch and a session's request, each logged, nothing spawned (219.378242ms)
✔ bus start --no-launch starts no thread tick; the same host with launches runs it (1236.400078ms)
✔ a malformed sessions.json refuses the host start with exit 3 and stays as it was (198.129142ms)
✔ an over-long launch request is refused at once, not at the 10 s idle timeout (200.659094ms)
✔ a launch client that never closes its side doesn't hold the host's close (211.221353ms)
✔ a runner that ignores SIGTERM is killed when the host closes (1398.582123ms)
✔ kill switch refuses chief and hire before launch work and a clear permits a later request (373.807885ms)
✔ kill switch stops an actual managed namespace and records the halt reason without rewriting its bundle (372.1022ms)
✔ a launch waiting across halt and resume cannot use its stale admission (236.835216ms)
ℹ tests 35
ℹ suites 0
ℹ pass 35
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 29398.149477
exit=0
23:59:45Z
@@ -1,35 +0,0 @@
23:59:16Z
nice=19
✔ P3 Anthropic route uses messages at proxy root and the declared model id (9.965114ms)
✔ P3 omitted route generates the Anthropic provider at proxy root (3.050792ms)
✔ P3 GLM route uses completions at proxy /v1 with explicit z.ai compatibility (2.833686ms)
✖ P3 GPT route selects a stack-owned provider instead of pi Codex OAuth (2.980797ms)
✔ P3 a declared Codex route refuses generation while the build-time API is PENDING (4.028363ms)
✔ P3 models file is private, references the one session key, and stores no executable values or keys (3.814909ms)
✔ P3 every launch regenerates proxy port, declared models and own key without caching (7.841047ms)
ℹ tests 7
ℹ suites 0
ℹ pass 6
ℹ fail 1
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 117.036157
✖ failing tests:
test at packages/harness/tests/proxy-bundle.test.mjs:68:1
✖ P3 GPT route selects a stack-owned provider instead of pi Codex OAuth (2.980797ms)
Error: proxy GPT API is PENDING build-time evidence
at Module.bundle (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/harness/pi/index.mjs:78:62)
at buildBundle (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/src/bundle.mjs:354:23)
at build (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:20:18)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:69: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)
exit=1
23:59:16Z
@@ -1,18 +0,0 @@
23:57:06Z
nice=19
✔ P3 proxy model validation preserves each explicit wire route and the proxy model id (1.161459ms)
✔ P3 a proxy model without route preserves its stored shape for the default Anthropic route (0.134804ms)
✔ P3 an unknown proxy route refuses proxy-route-unknown (0.823069ms)
✔ P3 nonproxy models retain their provider/model-only shape and reject route metadata (0.170037ms)
✔ P3 launch.account accepts the proxy credential source without naming host variables (0.132947ms)
✔ P3 existing environment-set accounts retain their validated representation (0.200363ms)
ℹ tests 6
ℹ suites 0
ℹ pass 6
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 52.197696
exit=0
23:57:06Z
@@ -1,21 +0,0 @@
23:57:12Z
nice=19
✔ row 65 both harness modules load through the loader with every export the kind names (7.907431ms)
✔ row 65 each module answers for its own harness: adapter, levels, account, web, turn end and session files (0.745524ms)
✔ row 65 claude-code preflight: a missing credential, then a missing or relative binary, each refuse with their code (3.501824ms)
✔ row 65 claude-code version asks MOSAIC_CLAUDE_BIN when set, else claude on PATH, else null (3.715209ms)
✔ row 65 pi preflight passes with the repository's pi, and its version is the package pin (0.570287ms)
✔ row 65 env passes the thinking level to both adapters, and claude-code's bundle writes its hook and MCP files (1.263458ms)
✔ row 65 a route's thinking reaches pi as --thinking and claude as --effort, through each module's env and adapter (14.961799ms)
✔ row 65 no core source outside packages/plugins names a harness, apart from the listed exceptions (14.014352ms)
✔ row 65 the grep's pattern catches a quoted name and a regex alternation, and not a word in prose (0.144087ms)
ℹ tests 9
ℹ suites 0
ℹ pass 9
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 95.780618
exit=0
23:57:12Z
@@ -1,74 +0,0 @@
23:57:12Z
nice=19
✔ C2-04: launcher workspace clones code but never the library (1409.48354ms)
✔ P3 proxy key reaches the spawned runner but never session.json or the bundle (1360.002763ms)
✔ bus start --pm: the launcher instance (the chief of staff) runs under its own PID namespace, registered, with a manifest (1355.188394ms)
usage: {"event":"usage-unknown","business":"acme","run":"r77c2d6253086","instance":"chief","turn":"492fcf7a-ee92-4637-b1ee-de6d29c5f536","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"r0caee85973df","instance":"coder","turn":"a8f6e869-e911-4e61-8913-9bcb8c84bca5","source":"@none","code":"baseline-unknown"}
✔ the chief of staff launches a coder through its launch tool; the coder answers; refusals name their code (844.874148ms)
usage: {"event":"usage-unknown","business":"acme","run":"rdd1124f17d39","instance":"chief","turn":"99cbfb5d-a0b1-4de7-b94b-855285416cea","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"r3ee360b6ea6f","instance":"pm","turn":"3299c709-0616-4d80-878e-589213b2833a","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"rdd1124f17d39","instance":"chief","turn":"aaef40d5-2c04-4a58-8019-3a9fed2740d3","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"rdd1124f17d39","instance":"chief","turn":"f7697cc5-383e-41e4-8f48-ca8032cb501f","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"r3ee360b6ea6f","instance":"pm","turn":"b6f5d1de-a58e-40de-9d2c-9e79472bc8f5","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"r3ee360b6ea6f","instance":"pm","turn":"7a8278f1-c934-418d-a62a-34528048a50c","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"rdd1124f17d39","instance":"chief","turn":"c8f0554c-b415-4b2c-aa8e-8eebf3253c12","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"r3ee360b6ea6f","instance":"pm","turn":"d5084f6b-43d9-48b4-ada8-14c78f9a6472","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"rdd1124f17d39","instance":"chief","turn":"2b8f60d0-5e87-4823-a4c8-e7a13fdffae2","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 (1499.426496ms)
✔ each launch makes sure the workspace has a clone of the project: cloned, fast-forwarded, or fetched and logged (4214.335578ms)
✔ a role the broker says holds a merge decision gets land_work, its prompt line, its landing and the git socket; without it, none (731.541713ms)
✔ 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 (452.219971ms)
usage: {"event":"usage-unknown","business":"acme","run":"r8dca21c7af83","instance":"coder","turn":"b0a65410-42a5-495d-a881-d7828ea5dc69","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 (859.92414ms)
✔ a landing run that ended isn't started again for its decision, a spent decision starts nothing, and a new decision starts the holder (813.442124ms)
✔ after a restart, the new host's first tick starts a holder whose decision is still held (1026.204746ms)
✔ 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 (698.000891ms)
✔ a project clone that can't be made refuses checkout-failed, from --chief and from a session, with no run and no clone left (333.63354ms)
✔ a runner that stops at once ends its launch with the runner's reason (392.682058ms)
✔ a Claude Code launch with no session credential refuses before it starts (219.352153ms)
✔ a pi launch with no own credential refuses no-session-credential (202.834512ms)
usage: {"event":"plugin-refused","kind":"harness","name":"down","code":"missing","message":"/home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/harness/down is missing","kept":[]}
plugins: {"event":"plugin-refused","kind":"harness","name":"down","code":"missing","message":"/home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/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 (214.464488ms)
✔ a runner killed from the host ends its launch as killed, not failed (437.720138ms)
✔ a missing or failing bwrap refuses sandbox-unavailable before anything starts; there is no unconfined fallback (240.940882ms)
✔ 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 (220.344629ms)
✔ row 213 a creative instance's persona is read from <configDir>/personas: off its digest the launch fails with the mismatch as its reason (288.705681ms)
✔ row 64 on Claude Code a role skill that isn't enabled refuses the same way, before anything starts (211.010194ms)
usage: {"event":"usage-unknown","business":"acme","run":"r31e317a9ff60","instance":"chief","turn":"bf22f39d-2bf0-48ec-849b-bf8665a262af","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"rcb1b05afaad6","instance":"coder","turn":"40f65cf7-8938-4265-949a-c816ef7084cd","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 (1532.310766ms)
✔ 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 (1163.295788ms)
✔ 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 (4129.096956ms)
✔ bus start --no-launch leaves an earlier host's live session alone: no signal, no end, sessions.json as it was (253.012747ms)
✔ bus start --no-launch refuses every launch: the PM launch and a session's request, each logged, nothing spawned (210.12322ms)
✔ bus start --no-launch starts no thread tick; the same host with launches runs it (1206.988059ms)
✔ a malformed sessions.json refuses the host start with exit 3 and stays as it was (200.617792ms)
✔ an over-long launch request is refused at once, not at the 10 s idle timeout (208.31407ms)
✔ a launch client that never closes its side doesn't hold the host's close (210.5977ms)
✔ a runner that ignores SIGTERM is killed when the host closes (1396.242105ms)
✔ kill switch refuses chief and hire before launch work and a clear permits a later request (356.328128ms)
✔ kill switch stops an actual managed namespace and records the halt reason without rewriting its bundle (411.659934ms)
✔ a launch waiting across halt and resume cannot use its stale admission (248.122427ms)
ℹ tests 35
ℹ suites 0
ℹ pass 34
ℹ fail 1
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 29678.41987
✖ failing tests:
test at packages/cli/tests/launcher.test.mjs:714:1
✖ row 65 a failed primary preflight launches the fallback on a fixture harness module, recording the route and the reason (214.464488ms)
Error [CliError]: PM launch refused: no-session-credential (fallback fixture: pi needs its own provider key or a session proxy key (primary down: fixture preflight fails))
at file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/cli/src/launcher.mjs:1189:23
at process.processTicksAndRejections (node:internal/process/task_queues:104:5) {
exitCode: 3,
code: 'no-session-credential'
}
exit=1
23:57:42Z
@@ -1,88 +0,0 @@
23:57:12Z
nice=19
✖ P3 Anthropic route uses messages at proxy root and the declared model id (8.82863ms)
✔ P3 omitted route generates the Anthropic provider at proxy root (3.493006ms)
✖ P3 GLM route uses completions at proxy /v1 with explicit z.ai compatibility (2.169226ms)
✖ P3 GPT route selects a stack-owned provider instead of pi Codex OAuth (2.321456ms)
✖ P3 models file is private, references the one session key, and stores no executable values or keys (2.285532ms)
✖ P3 every launch regenerates proxy port, declared models and own key without caching (2.062519ms)
ℹ tests 6
ℹ suites 0
ℹ pass 1
ℹ fail 5
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 94.962091
✖ failing tests:
test at packages/harness/tests/proxy-bundle.test.mjs:35:1
✖ P3 Anthropic route uses messages at proxy root and the declared model id (8.82863ms)
Error: proxy GPT API is PENDING build-time evidence
at Module.bundle (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/harness/pi/index.mjs:78:62)
at buildBundle (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/src/bundle.mjs:354:23)
at build (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:20:18)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:36: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)
test at packages/harness/tests/proxy-bundle.test.mjs:57:1
✖ P3 GLM route uses completions at proxy /v1 with explicit z.ai compatibility (2.169226ms)
Error: proxy GPT API is PENDING build-time evidence
at Module.bundle (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/harness/pi/index.mjs:78:62)
at buildBundle (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/src/bundle.mjs:354:23)
at build (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:20:18)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:58: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)
test at packages/harness/tests/proxy-bundle.test.mjs:68:1
✖ P3 GPT route selects a stack-owned provider instead of pi Codex OAuth (2.321456ms)
Error: proxy GPT API is PENDING build-time evidence
at Module.bundle (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/harness/pi/index.mjs:78:62)
at buildBundle (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/src/bundle.mjs:354:23)
at build (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:20:18)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:69: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)
test at packages/harness/tests/proxy-bundle.test.mjs:79:1
✖ P3 models file is private, references the one session key, and stores no executable values or keys (2.285532ms)
Error: proxy GPT API is PENDING build-time evidence
at Module.bundle (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/harness/pi/index.mjs:78:62)
at buildBundle (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/src/bundle.mjs:354:23)
at build (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:20:18)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:81: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)
test at packages/harness/tests/proxy-bundle.test.mjs:94:1
✖ P3 every launch regenerates proxy port, declared models and own key without caching (2.062519ms)
Error: proxy GPT API is PENDING build-time evidence
at Module.bundle (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/harness/pi/index.mjs:78:62)
at buildBundle (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/src/bundle.mjs:354:23)
at build (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:20:18)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:95:17)
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)
exit=1
23:57:12Z
@@ -1,17 +0,0 @@
23:57:06Z
nice=19
✔ P3 Claude env receives the session proxy URL and key, without another agent or host credential (2.459573ms)
✔ P3 Claude preflight accepts a proxy key without a host provider credential (1.019636ms)
✔ P3 pi refuses no-session-credential with no provider key (0.965529ms)
✔ P3 pi refuses no-session-credential with only a Claude OAuth token (0.264623ms)
✔ P3 pi accepts its own provider key or a session proxy key (0.345262ms)
ℹ tests 5
ℹ suites 0
ℹ pass 5
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 56.359357
exit=0
23:57:06Z
@@ -1,14 +0,0 @@
23:57:06Z
nice=19
✔ P3 proxy sessionEnv removes every instance provider credential without widening ENV_ALLOW (0.976855ms)
✔ P3 no proxy retains the full existing allowlist and run environment (0.214793ms)
ℹ tests 2
ℹ suites 0
ℹ pass 2
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 47.349955
exit=0
23:57:06Z
@@ -1,42 +0,0 @@
// Parse static imports without evaluating any repository module. This is an audit tool, not a test runner.
// Usage: node --experimental-vm-modules agents/fethry/work/queue-332/import-run-list.mjs
import { readdirSync, readFileSync } from 'node:fs';
import { dirname, join, relative, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { SourceTextModule } from 'node:vm';
const root = resolve(dirname(fileURLToPath(import.meta.url)), '../../../..');
const files = [];
function walk(dir) {
for (const entry of readdirSync(dir, { withFileTypes: true })) {
if (['node_modules', '.git', 'dist'].includes(entry.name)) continue;
const path = join(dir, entry.name);
if (entry.isDirectory()) walk(path);
else if (entry.isFile() && path.endsWith('.mjs')) files.push(path);
}
}
for (const dir of ['packages', 'scripts', 'adapters']) walk(join(root, dir));
const graph = new Map();
for (const file of files) {
const module = new SourceTextModule(readFileSync(file, 'utf8'), { identifier: file });
graph.set(file, module.dependencySpecifiers.filter(spec => spec.startsWith('.')).map(spec => resolve(dirname(file), spec)));
}
// The loader imports the configured harness via a computed path. Explicit runtime import edges:
const loader = join(root, 'packages/plugins/src/loader.mjs');
graph.get(loader).push(...['claude-code', 'pi'].map(name => join(root, 'packages/plugins/harness', name, 'index.mjs')));
const changed = new Set([
'packages/seat/src/session.mjs', 'packages/business/src/launch.mjs',
'packages/plugins/harness/claude-code/index.mjs', 'packages/plugins/harness/pi/index.mjs',
'packages/harness/src/bundle.mjs', 'packages/cli/src/launcher.mjs',
].map(file => join(root, file)));
function affected(file, seen = new Set()) {
if (changed.has(file)) return true;
if (seen.has(file)) return false;
seen.add(file);
return (graph.get(file) ?? []).some(dep => affected(dep, seen));
}
const excluded = 'packages/cli/tests/case1-accept.test.mjs';
for (const file of files.filter(file => file.endsWith('.test.mjs')).sort()) {
if (!affected(file)) continue;
const path = relative(root, file);
console.log(`${path === excluded ? 'EXCLUDED (mos-1612) ' : ''}${path}`);
}
@@ -1,211 +0,0 @@
// Row332 evidence. The only network-capable phase is the single authorized fetch.
// offline runs in unshare -rn; a transparent local tap records pi payload shapes
// without retaining headers, then pipes bytes unchanged to the pinned proxy.
import { mkdirSync, readFileSync, readlinkSync, writeFileSync } from 'node:fs';
import { dirname, join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { getPriority, setPriority, networkInterfaces } from 'node:os';
import { spawn } from 'node:child_process';
import { once } from 'node:events';
import http from 'node:http';
import { fetchPinned } from '../../../../packages/model-proxy/src/fetch.mjs';
import { PIN } from '../../../../packages/model-proxy/src/common.mjs';
import { initialConfig, verifyInstall } from '../../../../packages/model-proxy/src/settings.mjs';
const root = process.env.P3_EVIDENCE_ROOT;
if (!root || !root.startsWith('/mnt/storage/scratch/') || resolve(root) !== root) throw Error('owned evidence root required');
const enteredNice = getPriority(0);
setPriority(0, 19);
const repo = resolve(dirname(fileURLToPath(import.meta.url)), '../../../..');
const mode = process.argv[2];
const fakeKeys = ['fx332-client', 'fx332-upstream', 'fx332-manage'];
function redact(value) {
let text = String(value);
for (const key of fakeKeys) text = text.split(key).join('[redacted]');
return text;
}
const emit = (value) => console.log(redact(JSON.stringify(value)));
if (mode === 'fetch') {
const dataRoot = join(root, 'data');
mkdirSync(dataRoot, { mode: 0o700 });
const installed = await fetchPinned({ dataRoot, pin: PIN });
writeFileSync(join(root, 'installed.json'), JSON.stringify(installed) + '\n', { mode: 0o600, flag: 'wx' });
emit({ phase: 'fetch', version: PIN.version, binarySha256: PIN.binary.sha256,
panelVersion: PIN.panel.version, panelSha256: PIN.panel.sha256, enteredNice, nice: getPriority(0), verified: true });
} else if (mode === 'offline' || mode === 'glm-tool') {
const withTool = mode === 'glm-tool';
if (readlinkSync('/proc/self/ns/net') === process.env.P3_HOST_NET_NS) throw Error('network namespace was not isolated');
if (Object.keys(networkInterfaces()).some(name => name !== 'lo')) throw Error('loopback-only namespace required');
// Re-hash the already fetched assets; this function performs no network I/O.
const installed = verifyInstall(join(root, 'data'), PIN);
const attemptRoot = join(root, withTool ? 'attempt3-tool' : 'attempt2');
mkdirSync(attemptRoot, { mode: 0o700 });
setPriority(0, 19);
emit({ phase: 'isolation', interfaces: Object.keys(networkInterfaces()), enteredNice, nice: getPriority(0), version: PIN.version,
binarySha256: PIN.binary.sha256, panelSha256: PIN.panel.sha256, reverified: true });
const requests = [], responses = [], upstreamRequests = [], children = new Set();
const managed = (args, options = {}) => {
setPriority(0, 19);
const child = spawn('/usr/bin/timeout', ['-k', '10', ...args], { env: {
PATH: '/usr/bin:/bin', HOME: join(root, 'home'), TMPDIR: process.env.TMPDIR,
LANG: 'C.UTF-8', ...options.env,
}, cwd: root, stdio: ['ignore', 'pipe', 'pipe'] });
children.add(child);
setPriority(child.pid, 19);
child.once('close', () => children.delete(child));
return child;
};
const summary = body => ({ keys: Object.keys(body).sort(), model: body.model, stream: body.stream,
roles: Array.isArray(body.messages) ? body.messages.map(message => message.role) : undefined,
inputTypes: Array.isArray(body.input) ? body.input.map(item => item.type) : typeof body.input,
...(Object.hasOwn(body, 'reasoning') ? { reasoning: body.reasoning } : {}),
...(Object.hasOwn(body, 'thinking') ? { thinking: body.thinking } : {}),
...(Object.hasOwn(body, 'reasoning_effort') ? { reasoning_effort: body.reasoning_effort } : {}),
...(Object.hasOwn(body, 'enable_thinking') ? { enable_thinking: body.enable_thinking } : {}),
...(Object.hasOwn(body, 'tool_stream') ? { tool_stream: body.tool_stream } : {}),
...(Array.isArray(body.tools) ? { toolNames: body.tools.map(tool => tool.function?.name) } : {}),
...(Object.hasOwn(body, 'stream_options') ? { stream_options: body.stream_options } : {}),
...(Object.hasOwn(body, 'max_tokens') ? { max_tokens: body.max_tokens } : {}),
...(Object.hasOwn(body, 'max_completion_tokens') ? { max_completion_tokens: body.max_completion_tokens } : {}) });
const payload = async req => { let text = ''; for await (const part of req) text += part; return JSON.parse(text || '{}'); };
const listen = async server => { await new Promise((ok, no) => { server.once('error', no); server.listen(0, '127.0.0.1', ok); }); return server.address().port; };
const marker = 'P332_OFFLINE_OK';
const upstream = http.createServer(async (req, res) => {
const body = await payload(req);
upstreamRequests.push({ method: req.method, path: req.url, ...summary(body) });
const item = { id: 'msg_fixture', type: 'message', role: 'assistant', status: 'completed', content: [{ type: 'output_text', text: marker, annotations: [] }] };
if (req.url.endsWith('/chat/completions')) {
res.writeHead(200, { 'Content-Type': 'text/event-stream' });
const chunk = (delta, finish_reason = null) => res.write(`data: ${JSON.stringify({ id: 'chat_fixture', object: 'chat.completion.chunk', created: 1, model: body.model, choices: [{ index: 0, delta, finish_reason }] })}\n\n`);
chunk({ role: 'assistant', content: marker }); chunk({}, 'stop');
res.write(`data: ${JSON.stringify({ id: 'chat_fixture', object: 'chat.completion.chunk', created: 1, model: body.model, choices: [], usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 } })}\n\n`);
res.end('data: [DONE]\n\n');
} else if (req.url.endsWith('/responses')) {
res.writeHead(200, { 'Content-Type': 'text/event-stream' });
const event = (type, more) => res.write(`event: ${type}\ndata: ${JSON.stringify({ type, ...more })}\n\n`);
const response = { id: 'resp_fixture', object: 'response', model: body.model, status: 'in_progress', output: [] };
event('response.created', { response });
event('response.output_item.added', { output_index: 0, item: { ...item, status: 'in_progress', content: [] } });
event('response.content_part.added', { item_id: item.id, output_index: 0, content_index: 0, part: { type: 'output_text', text: '', annotations: [] } });
event('response.output_text.delta', { item_id: item.id, output_index: 0, content_index: 0, delta: marker });
event('response.output_text.done', { item_id: item.id, output_index: 0, content_index: 0, text: marker });
event('response.output_item.done', { output_index: 0, item });
event('response.completed', { response: { ...response, status: 'completed', output: [item], usage: { input_tokens: 1, output_tokens: 1, total_tokens: 2 } } });
res.end();
} else { res.writeHead(404); res.end('{"error":"stand-in path refused"}'); }
});
let proxy, tap;
let proxyText = '';
const corrections = {};
const restoreNice = pid => {
try {
const priority = getPriority(pid);
if (priority !== 19) { corrections[priority] = (corrections[priority] ?? 0) + 1; setPriority(pid, 19); }
const descendants = readFileSync(`/proc/${pid}/task/${pid}/children`, 'utf8').trim().split(/\s+/).filter(Boolean);
for (const child of descendants) restoreNice(Number(child));
} catch {}
};
const keepNice = setInterval(() => restoreNice(process.pid), 100);
keepNice.unref();
try {
const upstreamPort = await listen(upstream);
const reservation = http.createServer(); const proxyPort = await listen(reservation);
await new Promise(ok => reservation.close(ok));
if (proxyPort === 8317 || upstreamPort === 8317) throw Error('reserved host-proxy port excluded');
const dataRoot = join(attemptRoot, 'offline');
mkdirSync(dataRoot, { mode: 0o700 });
mkdirSync(join(dataRoot, 'proxy'), { mode: 0o700 });
mkdirSync(join(dataRoot, 'proxy', 'auth'), { mode: 0o700 });
const config = initialConfig({ dataRoot, port: proxyPort, key: fakeKeys[2], sentinel: fakeKeys[0] });
config.management['disable-control-panel'] = true;
config.observability.logs['logging-to-file'] = false;
// Bundled panel1.26.7: Ip reads api-keys.openai-compatibility;
// Fp/Np require group.keys; xv/hv serialize keys:[{"api-key":...}].
config['api-keys'] = { 'openai-compatibility': [{ name: 'p332-standin', 'base-url': `http://127.0.0.1:${upstreamPort}/v1`,
keys: [{ 'api-key': fakeKeys[1] }], models: [{ name: 'gpt-fixture' }, { name: 'glm-fixture' }] }] };
const configFile = join(dataRoot, 'config.yaml');
writeFileSync(configFile, JSON.stringify(config, null, 2) + '\n', { mode: 0o600, flag: 'wx' });
proxy = managed(['200', installed.binary, '-config', configFile, '-local-model'], { env: { MANAGEMENT_STATIC_PATH: dirname(installed.panel) } });
proxy.stdout.on('data', bytes => { proxyText += bytes; });
proxy.stderr.on('data', bytes => { proxyText += bytes; });
let catalog, ids = [];
const readinessDeadline = Date.now() + 30000;
for (let poll = 1; Date.now() < readinessDeadline; poll++) {
if (proxy.exitCode !== null) throw Error('proxy exited before readiness');
try {
const result = await fetch(`http://127.0.0.1:${proxyPort}/v1/models`, { headers: { Authorization: `Bearer ${fakeKeys[0]}` }, signal: AbortSignal.timeout(1000) });
catalog = result.ok ? await result.json() : null;
ids = (catalog?.data ?? []).map(model => model.id);
emit({ phase: 'readiness', poll, status: result.status, modelCount: ids.length });
if (['gpt-fixture', 'glm-fixture'].every(id => ids.includes(id))) break;
} catch { emit({ phase: 'readiness', poll, status: 'not-ready', modelCount: 0 }); }
await new Promise(ok => setTimeout(ok, 1000));
}
if (!catalog) throw Error('proxy readiness failed');
emit({ phase: 'catalog', modelIds: ids });
if (!['gpt-fixture', 'glm-fixture'].every(id => ids.includes(id))) throw Error('stand-in routes absent from proxy catalog');
tap = http.createServer(async (req, res) => {
let raw = ''; for await (const part of req) raw += part;
const body = JSON.parse(raw || '{}');
const index = requests.push({ method: req.method, path: req.url, ...summary(body) }) - 1;
const outgoing = http.request({ hostname: '127.0.0.1', port: proxyPort, method: req.method, path: req.url,
headers: { ...req.headers, host: `127.0.0.1:${proxyPort}` } }, incoming => {
const chunks = [];
res.writeHead(incoming.statusCode, incoming.headers);
incoming.on('data', bytes => { chunks.push(bytes); res.write(bytes); });
incoming.on('end', () => {
const text = Buffer.concat(chunks).toString();
const events = text.split('\n').filter(line => line.startsWith('event: ')).map(line => line.slice(7));
responses.push({ request: index, status: incoming.statusCode, events, marker: text.includes(marker),
...(incoming.statusCode >= 400 ? { errorBody: redact(text).slice(0, 800) } : {}) });
res.end();
});
});
outgoing.on('error', () => { res.writeHead(502); res.end(); });
// Preserve exact body bytes and never log a header value.
outgoing.end(raw);
});
const tapPort = await listen(tap);
if (tapPort === 8317) throw Error('reserved host-proxy port excluded');
const scenarios = [
['gpt-responses', 'openai-responses', 'gpt-fixture', null],
['gpt-completions', 'openai-completions', 'gpt-fixture', null],
['glm-completions', 'openai-completions', 'glm-fixture', { thinkingFormat: 'zai', zaiToolStream: true }],
];
for (const [name, api, model, compat] of (withTool ? scenarios.filter(([name]) => name === 'glm-completions') : scenarios)) {
const turnHome = join(attemptRoot, name, 'home');
const agentDir = join(turnHome, '.pi', 'agent');
mkdirSync(agentDir, { recursive: true, mode: 0o700 });
const models = { providers: { 'p332-probe': { baseUrl: `http://127.0.0.1:${tapPort}/v1`, api,
apiKey: '$ANTHROPIC_API_KEY', ...(compat ? { compat } : {}), models: [{ id: model, reasoning: true }] } } };
writeFileSync(join(agentDir, 'models.json'), JSON.stringify(models) + '\n', { mode: 0o600, flag: 'wx' });
writeFileSync(join(agentDir, 'settings.json'), JSON.stringify({ retry: { enabled: false, maxRetries: 0, provider: { maxRetries: 0 } } }) + '\n', { mode: 0o600, flag: 'wx' });
const reqStart = requests.length, upstreamStart = upstreamRequests.length, responseStart = responses.length;
const pi = managed(['50', '/usr/bin/node', join(repo, 'node_modules/@earendil-works/pi-coding-agent/dist/cli.js'),
'--no-extensions', '--no-skills', '--no-prompt-templates', '--no-themes', '--no-context-files', '--no-session',
...(withTool ? ['--tools', 'read'] : ['--no-tools']),
'--provider', 'p332-probe', '--model', model, '--thinking', 'low', '-p', 'Reply P332_OFFLINE_OK only.'],
{ env: { HOME: turnHome, PI_CODING_AGENT_DIR: agentDir, ANTHROPIC_API_KEY: fakeKeys[0] } });
let stdout = '', stderr = '';
pi.stdout.on('data', bytes => { stdout += bytes; });
pi.stderr.on('data', bytes => { stderr += bytes; });
const [exit, signal] = await once(pi, 'close');
emit({ phase: 'turn', name: withTool ? `${name}-tool` : name, api, exit, signal, marker: stdout.includes(marker),
piRequests: requests.slice(reqStart), proxyResponses: responses.slice(responseStart), upstreamRequests: upstreamRequests.slice(upstreamStart),
...(exit !== 0 ? { stderr: redact(stderr).slice(0, 1200), stdout: redact(stdout).slice(0, 1200) } : {}), nice: getPriority(0) });
}
emit({ phase: 'conclusion', limitation: 'Stand-in openai-compatibility credential only; no Codex OAuth credential or real-auth turn. This script never selects the production API.' });
emit({ phase: 'nice-corrections', restoredTo: 19, observedBeforeRestore: corrections });
} catch (error) {
emit({ phase: 'error', message: error.message, proxyDiagnostic: redact(proxyText).slice(-3000) });
process.exitCode = 1;
} finally {
clearInterval(keepNice);
for (const child of [...children]) child.kill('SIGTERM');
for (const child of [...children]) {
await Promise.race([once(child, 'close'), new Promise(ok => setTimeout(ok, 1200))]);
if (child.exitCode === null) child.kill('SIGKILL');
}
for (const server of [tap, upstream].filter(Boolean)) { server.closeAllConnections(); await new Promise(ok => server.close(ok)); }
emit({ phase: 'cleanup', remainingManagedChildren: children.size });
}
} else { throw Error('fetch, offline or glm-tool phase required'); }
@@ -1,104 +0,0 @@
23:41:37Z
nice=19
✖ P3 proxy model validation preserves each explicit wire route and the proxy model id (0.843397ms)
✖ P3 a proxy model without route refuses proxy-route-missing (0.621133ms)
✖ P3 an unknown proxy route refuses proxy-route-unknown (1.448927ms)
✔ P3 nonproxy models retain their provider/model-only shape and reject route metadata (0.541212ms)
✖ P3 launch.account accepts the proxy credential source without naming host variables (0.159973ms)
✔ P3 existing environment-set accounts retain their validated representation (0.209852ms)
ℹ tests 6
ℹ suites 0
ℹ pass 2
ℹ fail 4
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 58.617716
✖ failing tests:
test at packages/business/tests/proxy-launch.test.mjs:6:1
✖ P3 proxy model validation preserves each explicit wire route and the proxy model id (0.843397ms)
Error [BusinessError]: unsupported launch.models.selected key: "route"
at refuse (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/errors.mjs:12:9)
at rejectUnknownKeys (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/util.mjs:17:33)
at file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/launch.mjs:18:5
at Array.map (<anonymous>)
at checkModels (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/launch.mjs:15:51)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/tests/proxy-launch.test.mjs:9:22)
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) {
exitCode: 2
}
test at packages/business/tests/proxy-launch.test.mjs:13:1
✖ P3 a proxy model without route refuses proxy-route-missing (0.621133ms)
AssertionError [ERR_ASSERTION]: Missing expected exception.
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/tests/proxy-launch.test.mjs:14:10)
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) {
generatedMessage: false,
code: 'ERR_ASSERTION',
actual: undefined,
expected: { code: 'proxy-route-missing' },
operator: 'throws',
diff: 'simple'
}
test at packages/business/tests/proxy-launch.test.mjs:19:1
✖ P3 an unknown proxy route refuses proxy-route-unknown (1.448927ms)
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
+ actual - expected
+ Comparison {}
- Comparison {
- code: 'proxy-route-unknown'
- }
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/tests/proxy-launch.test.mjs:21:12)
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) {
generatedMessage: true,
code: 'ERR_ASSERTION',
actual: BusinessError: unsupported launch.models.selected key: "route"
at refuse (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/errors.mjs:12:9)
at rejectUnknownKeys (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/util.mjs:17:33)
at file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/launch.mjs:18:5
at Array.map (<anonymous>)
at checkModels (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/launch.mjs:15:51)
at assert.throws.code (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/tests/proxy-launch.test.mjs:21:25)
at getActual (node:assert:580:5)
at strict.throws (node:assert:728:24)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/tests/proxy-launch.test.mjs:21:12)
at Test.runInAsyncScope (node:async_hooks:226:14),
expected: { code: 'proxy-route-unknown' },
operator: 'throws',
diff: 'simple'
}
test at packages/business/tests/proxy-launch.test.mjs:34:1
✖ P3 launch.account accepts the proxy credential source without naming host variables (0.159973ms)
Error [BusinessError]: launch.account.credential must name environment variables, joined with "+"
at refuse (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/errors.mjs:12:9)
at checkAccount (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/launch.mjs:86:5)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/tests/proxy-launch.test.mjs:35:20)
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) {
exitCode: 2
}
exit=1
23:41:37Z
@@ -1,107 +0,0 @@
23:44:40Z
nice=19
✖ P3 Anthropic route uses messages at proxy root and the declared model id (10.834783ms)
✖ P3 GLM route uses completions at proxy /v1 with explicit z.ai compatibility (3.078049ms)
✖ P3 GPT route selects a stack-owned provider instead of pi Codex OAuth (2.606176ms)
✖ P3 models file is private, references the one session key, and stores no executable values or keys (2.917109ms)
✖ P3 every launch regenerates proxy port, declared models and own key without caching (2.778195ms)
ℹ tests 5
ℹ suites 0
ℹ pass 0
ℹ fail 5
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 117.630612
✖ failing tests:
test at packages/harness/tests/proxy-bundle.test.mjs:35:1
✖ P3 Anthropic route uses messages at proxy root and the declared model id (10.834783ms)
Error: ENOENT: no such file or directory, open '/mnt/storage/scratch/tmp/gxWP/p332-ddGpq6/run/home/.pi/agent/models.json'
at readFileSync (node:fs:621:20)
at build (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:28:43)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:36: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) {
errno: -2,
code: 'ENOENT',
syscall: 'open',
path: '/mnt/storage/scratch/tmp/gxWP/p332-ddGpq6/run/home/.pi/agent/models.json'
}
test at packages/harness/tests/proxy-bundle.test.mjs:45:1
✖ P3 GLM route uses completions at proxy /v1 with explicit z.ai compatibility (3.078049ms)
Error: ENOENT: no such file or directory, open '/mnt/storage/scratch/tmp/gxWP/p332-7vqUkh/run/home/.pi/agent/models.json'
at readFileSync (node:fs:621:20)
at build (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:28:43)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:46: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) {
errno: -2,
code: 'ENOENT',
syscall: 'open',
path: '/mnt/storage/scratch/tmp/gxWP/p332-7vqUkh/run/home/.pi/agent/models.json'
}
test at packages/harness/tests/proxy-bundle.test.mjs:56:1
✖ P3 GPT route selects a stack-owned provider instead of pi Codex OAuth (2.606176ms)
Error: ENOENT: no such file or directory, open '/mnt/storage/scratch/tmp/gxWP/p332-xqR4OI/run/home/.pi/agent/models.json'
at readFileSync (node:fs:621:20)
at build (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:28:43)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.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) {
errno: -2,
code: 'ENOENT',
syscall: 'open',
path: '/mnt/storage/scratch/tmp/gxWP/p332-xqR4OI/run/home/.pi/agent/models.json'
}
test at packages/harness/tests/proxy-bundle.test.mjs:67:1
✖ P3 models file is private, references the one session key, and stores no executable values or keys (2.917109ms)
Error: ENOENT: no such file or directory, open '/mnt/storage/scratch/tmp/gxWP/p332-jAVWvp/run/home/.pi/agent/models.json'
at readFileSync (node:fs:621:20)
at build (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:28:43)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:69: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) {
errno: -2,
code: 'ENOENT',
syscall: 'open',
path: '/mnt/storage/scratch/tmp/gxWP/p332-jAVWvp/run/home/.pi/agent/models.json'
}
test at packages/harness/tests/proxy-bundle.test.mjs:82:1
✖ P3 every launch regenerates proxy port, declared models and own key without caching (2.778195ms)
Error: ENOENT: no such file or directory, open '/mnt/storage/scratch/tmp/gxWP/p332-yUgdwP/run/home/.pi/agent/models.json'
at readFileSync (node:fs:621:20)
at build (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:28:43)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:83:17)
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: 'open',
path: '/mnt/storage/scratch/tmp/gxWP/p332-yUgdwP/run/home/.pi/agent/models.json'
}
exit=1
23:44:40Z
@@ -1,99 +0,0 @@
23:42:41Z
nice=19
✖ P3 Anthropic route uses messages at proxy root and the declared model id (6.017482ms)
✖ P3 GLM route uses completions at proxy /v1 with explicit z.ai compatibility (1.65735ms)
✖ P3 GPT route selects a stack-owned provider instead of pi Codex OAuth (1.23753ms)
✖ P3 models file is private, references the one session key, and stores no executable values or keys (1.202284ms)
✖ P3 every launch regenerates proxy port, declared models and own key without caching (1.210998ms)
ℹ tests 5
ℹ suites 0
ℹ pass 0
ℹ fail 5
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 88.02888
✖ failing tests:
test at packages/harness/tests/proxy-bundle.test.mjs:35:1
✖ P3 Anthropic route uses messages at proxy root and the declared model id (6.017482ms)
Error [BusinessError]: /mnt/storage/scratch/tmp/gQE5/mosaic-harness-biz-FaxPH3/businesses/acme.json launch: instance pm selects unknown model a
at refuse (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/errors.mjs:12:9)
at checkLaunch (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/business.mjs:204:125)
at validateBusinessDocument (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/business.mjs:310:57)
at resolvedFor (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/helpers.mjs:46:20)
at build (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:17:20)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:36: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) {
exitCode: 2
}
test at packages/harness/tests/proxy-bundle.test.mjs:45:1
✖ P3 GLM route uses completions at proxy /v1 with explicit z.ai compatibility (1.65735ms)
Error [BusinessError]: /mnt/storage/scratch/tmp/gQE5/mosaic-harness-biz-rtXOnL/businesses/acme.json launch: instance pm selects unknown model z
at refuse (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/errors.mjs:12:9)
at checkLaunch (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/business.mjs:204:125)
at validateBusinessDocument (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/business.mjs:310:57)
at resolvedFor (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/helpers.mjs:46:20)
at build (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:17:20)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:46: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) {
exitCode: 2
}
test at packages/harness/tests/proxy-bundle.test.mjs:56:1
✖ P3 GPT route selects a stack-owned provider instead of pi Codex OAuth (1.23753ms)
Error [BusinessError]: /mnt/storage/scratch/tmp/gQE5/mosaic-harness-biz-IGXaeo/businesses/acme.json launch: instance pm selects unknown model g
at refuse (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/errors.mjs:12:9)
at checkLaunch (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/business.mjs:204:125)
at validateBusinessDocument (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/business.mjs:310:57)
at resolvedFor (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/helpers.mjs:46:20)
at build (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:17:20)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.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) {
exitCode: 2
}
test at packages/harness/tests/proxy-bundle.test.mjs:67:1
✖ P3 models file is private, references the one session key, and stores no executable values or keys (1.202284ms)
Error [BusinessError]: /mnt/storage/scratch/tmp/gQE5/mosaic-harness-biz-z5VTgc/businesses/acme.json launch: instance pm selects unknown model a
at refuse (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/errors.mjs:12:9)
at checkLaunch (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/business.mjs:204:125)
at validateBusinessDocument (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/business.mjs:310:57)
at resolvedFor (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/helpers.mjs:46:20)
at build (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:17:20)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:69: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) {
exitCode: 2
}
test at packages/harness/tests/proxy-bundle.test.mjs:82:1
✖ P3 every launch regenerates proxy port, declared models and own key without caching (1.210998ms)
Error [BusinessError]: /mnt/storage/scratch/tmp/gQE5/mosaic-harness-biz-83xrrf/businesses/acme.json launch: instance pm selects unknown model a
at refuse (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/errors.mjs:12:9)
at checkLaunch (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/business.mjs:204:125)
at validateBusinessDocument (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/business/src/business.mjs:310:57)
at resolvedFor (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/helpers.mjs:46:20)
at build (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:17:20)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:83:17)
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) {
exitCode: 2
}
exit=1
23:42:41Z
@@ -1,77 +0,0 @@
23:41:42Z
nice=19
✖ P3 Anthropic route uses messages at proxy root and the declared model id (8.181278ms)
✖ P3 GLM route uses completions at proxy /v1 with explicit z.ai compatibility (1.652506ms)
✖ P3 GPT route selects a stack-owned provider instead of pi Codex OAuth (1.297337ms)
✖ P3 models file is private, references the one session key, and stores no executable values or keys (1.318875ms)
✖ P3 every launch regenerates proxy port, declared models and own key without caching (1.353193ms)
ℹ tests 5
ℹ suites 0
ℹ pass 0
ℹ fail 5
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 104.116628
✖ failing tests:
test at packages/harness/tests/proxy-bundle.test.mjs:34:1
✖ P3 Anthropic route uses messages at proxy root and the declared model id (8.181278ms)
TypeError: Cannot assign to read only property 'vars' of object '#<Object>'
at build (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:18:17)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:35: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)
test at packages/harness/tests/proxy-bundle.test.mjs:44:1
✖ P3 GLM route uses completions at proxy /v1 with explicit z.ai compatibility (1.652506ms)
TypeError: Cannot assign to read only property 'vars' of object '#<Object>'
at build (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:18:17)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:45: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)
test at packages/harness/tests/proxy-bundle.test.mjs:55:1
✖ P3 GPT route selects a stack-owned provider instead of pi Codex OAuth (1.297337ms)
TypeError: Cannot assign to read only property 'vars' of object '#<Object>'
at build (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:18:17)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:56: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)
test at packages/harness/tests/proxy-bundle.test.mjs:66:1
✖ P3 models file is private, references the one session key, and stores no executable values or keys (1.318875ms)
TypeError: Cannot assign to read only property 'vars' of object '#<Object>'
at build (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:18:17)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:68: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)
test at packages/harness/tests/proxy-bundle.test.mjs:81:1
✖ P3 every launch regenerates proxy port, declared models and own key without caching (1.353193ms)
TypeError: Cannot assign to read only property 'vars' of object '#<Object>'
at build (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:18:17)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:82:17)
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)
exit=1
23:41:42Z
@@ -1,78 +0,0 @@
23:41:55Z
nice=19
✔ C2-04: launcher workspace clones code but never the library (1499.521161ms)
✖ P3 proxy key reaches the spawned runner but never session.json or the bundle (40.623657ms)
✔ bus start --pm: the launcher instance (the chief of staff) runs under its own PID namespace, registered, with a manifest (1361.267044ms)
usage: {"event":"usage-unknown","business":"acme","run":"r61b9e08ebd95","instance":"chief","turn":"a017a278-0466-41ec-b7d4-d05d7bb2b4e8","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"r786eccbac72a","instance":"coder","turn":"5f857a62-f7e6-4662-a745-852935445baf","source":"@none","code":"baseline-unknown"}
✔ the chief of staff launches a coder through its launch tool; the coder answers; refusals name their code (853.066ms)
usage: {"event":"usage-unknown","business":"acme","run":"raa425c1d9f99","instance":"chief","turn":"94eec92a-4189-4188-abf0-c0dd27eb3f7a","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"r91d263cb44fe","instance":"pm","turn":"b3030547-e499-4465-ba6f-387ca92e7b2e","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"raa425c1d9f99","instance":"chief","turn":"2bb5f36b-953e-4f27-8368-d3cb77b0e68d","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"r91d263cb44fe","instance":"pm","turn":"f393963d-90db-4cc3-ada0-9749bbe898e9","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"r91d263cb44fe","instance":"pm","turn":"0fca073a-da7d-4cf2-953f-d590f37c6a9c","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"raa425c1d9f99","instance":"chief","turn":"9afffc56-5aca-4ac9-a8e9-ef50b859e54e","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"r91d263cb44fe","instance":"pm","turn":"555642ca-00ee-4665-89ab-e68eee143f82","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"raa425c1d9f99","instance":"chief","turn":"1dad33fc-cbe9-404b-8752-3b68753ab199","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 (1303.262398ms)
✔ each launch makes sure the workspace has a clone of the project: cloned, fast-forwarded, or fetched and logged (4218.830472ms)
✔ a role the broker says holds a merge decision gets land_work, its prompt line, its landing and the git socket; without it, none (747.37249ms)
✔ 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 (463.557222ms)
usage: {"event":"usage-unknown","business":"acme","run":"r18be47008dae","instance":"coder","turn":"52cd9cf6-57bd-41bf-96c0-fedd9ff9c092","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 (763.066104ms)
✔ a landing run that ended isn't started again for its decision, a spent decision starts nothing, and a new decision starts the holder (706.701053ms)
✔ after a restart, the new host's first tick starts a holder whose decision is still held (956.687674ms)
✔ 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 (721.85447ms)
✔ a project clone that can't be made refuses checkout-failed, from --chief and from a session, with no run and no clone left (395.757947ms)
✔ a runner that stops at once ends its launch with the runner's reason (463.349261ms)
✔ a Claude Code launch with no session credential refuses before it starts (235.420433ms)
✔ a pi launch needs no session credential: pi logs in through its own ENV_ALLOW variables (443.687348ms)
usage: {"event":"plugin-refused","kind":"harness","name":"down","code":"missing","message":"/home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/harness/down is missing","kept":[]}
plugins: {"event":"plugin-refused","kind":"harness","name":"down","code":"missing","message":"/home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/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 (477.875324ms)
✔ a runner killed from the host ends its launch as killed, not failed (491.276085ms)
✔ a missing or failing bwrap refuses sandbox-unavailable before anything starts; there is no unconfined fallback (257.904073ms)
✔ 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 (271.706852ms)
✔ row 213 a creative instance's persona is read from <configDir>/personas: off its digest the launch fails with the mismatch as its reason (374.032091ms)
✔ row 64 on Claude Code a role skill that isn't enabled refuses the same way, before anything starts (266.897065ms)
usage: {"event":"usage-unknown","business":"acme","run":"r505be704086e","instance":"chief","turn":"d3144fd2-644c-4bf1-95b5-5914f45dd040","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"r505be704086e","instance":"chief","turn":"c61a5cf2-9714-4e2a-a335-a48d0d1dc430","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"r96a1ff87bc5e","instance":"coder","turn":"bc58500e-35cc-47b5-b849-a56aa0438ace","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 (1866.534461ms)
✔ 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 (1438.787679ms)
✔ 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 (4207.748283ms)
✔ bus start --no-launch leaves an earlier host's live session alone: no signal, no end, sessions.json as it was (275.473348ms)
✔ bus start --no-launch refuses every launch: the PM launch and a session's request, each logged, nothing spawned (235.254265ms)
✔ bus start --no-launch starts no thread tick; the same host with launches runs it (1246.476055ms)
✔ a malformed sessions.json refuses the host start with exit 3 and stays as it was (188.603222ms)
✔ an over-long launch request is refused at once, not at the 10 s idle timeout (194.710702ms)
✔ a launch client that never closes its side doesn't hold the host's close (204.602445ms)
✔ a runner that ignores SIGTERM is killed when the host closes (1400.602264ms)
✔ kill switch refuses chief and hire before launch work and a clear permits a later request (396.558108ms)
✔ kill switch stops an actual managed namespace and records the halt reason without rewriting its bundle (362.427202ms)
✔ a launch waiting across halt and resume cannot use its stale admission (218.641499ms)
ℹ tests 35
ℹ suites 0
ℹ pass 34
ℹ fail 1
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 29700.689398
✖ failing tests:
test at packages/cli/tests/launcher.test.mjs:150:1
✖ P3 proxy key reaches the spawned runner but never session.json or the bundle (40.623657ms)
Error [CliError]: unsupported /mnt/storage/scratch/tmp/gmDV/mosaic-launch-PVUXgr/config/businesses/acme.json launch.models.claude-opus-5-5 key: "route"
at business (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/cli/src/config.mjs:45:47)
at bootConfig (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/cli/src/config.mjs:126:10)
at setup (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/cli/tests/launcher.test.mjs:99:16)
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
at async TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/cli/tests/launcher.test.mjs:156:34)
at async Test.run (node:internal/test_runner/test:1409:7)
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
exitCode: 3
}
exit=1
23:42:25Z
@@ -1,98 +0,0 @@
23:42:41Z
nice=19
✖ P3 Claude env receives the session proxy URL and key, without another agent or host credential (3.24785ms)
✖ P3 Claude preflight accepts a proxy key without a host provider credential (1.57681ms)
✖ P3 pi refuses no-session-credential with no provider key (1.085777ms)
✖ P3 pi refuses no-session-credential with only a Claude OAuth token (0.464216ms)
✔ P3 pi accepts its own provider key or a session proxy key (0.351842ms)
ℹ tests 5
ℹ suites 0
ℹ pass 1
ℹ fail 4
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 71.435137
✖ failing tests:
test at packages/plugins/tests/proxy-harness.test.mjs:24:1
✖ P3 Claude env receives the session proxy URL and key, without another agent or host credential (3.24785ms)
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
+ actual - expected
+ undefined
- 'http://127.0.0.1:12345'
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/tests/proxy-harness.test.mjs:30:12)
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: undefined,
expected: 'http://127.0.0.1:12345',
operator: 'strictEqual',
diff: 'simple'
}
test at packages/plugins/tests/proxy-harness.test.mjs:39:1
✖ P3 Claude preflight accepts a proxy key without a host provider credential (1.57681ms)
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
+ actual - expected
+ {
+ code: 'no-session-credential',
+ message: "the bus host has none of CLAUDE_CODE_OAUTH_TOKEN, ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN with ANTHROPIC_BASE_URL; the bus unit's EnvironmentFile sets one when the bus starts"
+ }
- null
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/tests/proxy-harness.test.mjs:44:10)
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: { code: 'no-session-credential', message: "the bus host has none of CLAUDE_CODE_OAUTH_TOKEN, ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN with ANTHROPIC_BASE_URL; the bus unit's EnvironmentFile sets one when the bus starts" },
expected: null,
operator: 'strictEqual',
diff: 'simple'
}
test at packages/plugins/tests/proxy-harness.test.mjs:49:1
✖ P3 pi refuses no-session-credential with no provider key (1.085777ms)
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
+ actual - expected
+ undefined
- 'no-session-credential'
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/tests/proxy-harness.test.mjs:51:10)
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: undefined,
expected: 'no-session-credential',
operator: 'strictEqual',
diff: 'simple'
}
test at packages/plugins/tests/proxy-harness.test.mjs:54:1
✖ P3 pi refuses no-session-credential with only a Claude OAuth token (0.464216ms)
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
+ actual - expected
+ undefined
- 'no-session-credential'
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/tests/proxy-harness.test.mjs:56:10)
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: undefined,
expected: 'no-session-credential',
operator: 'strictEqual',
diff: 'simple'
}
exit=1
23:42:41Z
@@ -1,82 +0,0 @@
23:41:44Z
nice=19
✖ P3 Claude env receives the session proxy URL and key, without another agent or host credential (0.739622ms)
✖ P3 Claude preflight accepts a proxy key without a host provider credential (0.187719ms)
✖ P3 pi refuses no-session-credential with no provider key (0.161237ms)
✖ P3 pi refuses no-session-credential with only a Claude OAuth token (0.154227ms)
✖ P3 pi accepts its own provider key or a session proxy key (0.168061ms)
ℹ tests 5
ℹ suites 0
ℹ pass 0
ℹ fail 5
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 52.551274
✖ failing tests:
test at packages/plugins/tests/proxy-harness.test.mjs:24:1
✖ P3 Claude env receives the session proxy URL and key, without another agent or host credential (0.739622ms)
TypeError: Cannot destructure property 'log' of 'undefined' as it is undefined.
at createLoader (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/src/loader.mjs:88:32)
at harness (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/tests/proxy-harness.test.mjs:11:18)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/tests/proxy-harness.test.mjs:25:24)
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)
test at packages/plugins/tests/proxy-harness.test.mjs:39:1
✖ P3 Claude preflight accepts a proxy key without a host provider credential (0.187719ms)
TypeError: Cannot destructure property 'log' of 'undefined' as it is undefined.
at createLoader (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/src/loader.mjs:88:32)
at harness (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/tests/proxy-harness.test.mjs:11:18)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/tests/proxy-harness.test.mjs:40:24)
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)
test at packages/plugins/tests/proxy-harness.test.mjs:49:1
✖ P3 pi refuses no-session-credential with no provider key (0.161237ms)
TypeError: Cannot destructure property 'log' of 'undefined' as it is undefined.
at createLoader (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/src/loader.mjs:88:32)
at harness (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/tests/proxy-harness.test.mjs:11:18)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/tests/proxy-harness.test.mjs:50:20)
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)
test at packages/plugins/tests/proxy-harness.test.mjs:54:1
✖ P3 pi refuses no-session-credential with only a Claude OAuth token (0.154227ms)
TypeError: Cannot destructure property 'log' of 'undefined' as it is undefined.
at createLoader (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/src/loader.mjs:88:32)
at harness (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/tests/proxy-harness.test.mjs:11:18)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/tests/proxy-harness.test.mjs:55:20)
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)
test at packages/plugins/tests/proxy-harness.test.mjs:59:1
✖ P3 pi accepts its own provider key or a session proxy key (0.168061ms)
TypeError: Cannot destructure property 'log' of 'undefined' as it is undefined.
at createLoader (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/src/loader.mjs:88:32)
at harness (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/tests/proxy-harness.test.mjs:11:18)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/tests/proxy-harness.test.mjs:60:20)
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)
exit=1
23:41:44Z
-35
View File
@@ -1,35 +0,0 @@
23:41:50Z
nice=19
✖ P3 proxy sessionEnv removes every instance provider credential without widening ENV_ALLOW (1.019646ms)
✔ P3 no proxy retains the full existing allowlist and run environment (0.564867ms)
ℹ tests 2
ℹ suites 0
ℹ pass 1
ℹ fail 1
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 46.658896
✖ failing tests:
test at packages/seat/tests/proxy-session-env.test.mjs:16:1
✖ P3 proxy sessionEnv removes every instance provider credential without widening ENV_ALLOW (1.019646ms)
AssertionError [ERR_ASSERTION]: CLAUDE_CODE_OAUTH_TOKEN
true !== false
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/seat/tests/proxy-session-env.test.mjs:19:40)
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: true,
expected: false,
operator: 'strictEqual',
diff: 'simple'
}
exit=1
23:41:50Z
@@ -1,30 +0,0 @@
00:01:55Z
nice=19
✔ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (22.211777ms)
✔ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (0.666965ms)
✔ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (19.091287ms)
✔ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (15.98515ms)
✔ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (4.713343ms)
✔ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (20.35829ms)
✔ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (2.568186ms)
✔ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (9.763289ms)
✔ Q169 assistants: vars and definition change and log the actor; tracker null leaves no tracker (16.756637ms)
✔ Q169 assistants: refuses other instances, other definitions, holder and credentials, empty entries, a tracker the definition has no credential for and a stale revision (19.737439ms)
✔ Q169 assistants: a definition with a vikunja credential takes a tracker change and refuses its removal or a used bot (12.898928ms)
✔ row 65 routes lists every instance with harness, model, thinking and fallback, the switched-on harnesses, the model keys and each harness's levels (2.552837ms)
✔ row 65 setRoutes saves a harness, model, thinking and whole fallback, reads each back from the file, logs the actor, and a null fallback clears all three (16.235475ms)
✔ row 65 setRoutes refuses a partial fallback, a switched-off harness, a level the harness doesn't apply, an unloaded module, an unknown model or instance, a malformed route, no change and a stale revision, with the file unchanged (20.272464ms)
✔ row 65 a file with harness vars and no plugins.harness loads and its views read; a model change still saves, and a route change refuses harness-off (10.564122ms)
✔ B7 kept instance: the models keys it names and the instances key are the human's (26.878317ms)
✔ B7 kept instance: its route is the human's (10.786018ms)
✔ M10 creative instance: models keys it names, the instances key and its route are the human's (35.64373ms)
ℹ tests 18
ℹ suites 0
ℹ pass 18
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 331.736961
exit=0
00:01:56Z
@@ -1,62 +0,0 @@
00:01:56Z
nice=19
✔ C2-04: launcher workspace clones code but never the library (1457.042303ms)
✔ P3 proxy key reaches the spawned runner but never session.json or the bundle (1365.062806ms)
✔ bus start --pm: the launcher instance (the chief of staff) runs under its own PID namespace, registered, with a manifest (1374.325436ms)
usage: {"event":"usage-unknown","business":"acme","run":"ra78486da0ed8","instance":"chief","turn":"9402e726-ac22-4423-aea9-cf7dcc35c134","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"r49e89e37520e","instance":"coder","turn":"6bf40609-ae81-49b3-96d0-de2d5811b135","source":"@none","code":"baseline-unknown"}
✔ the chief of staff launches a coder through its launch tool; the coder answers; refusals name their code (836.256914ms)
usage: {"event":"usage-unknown","business":"acme","run":"rf8408ce6a5b4","instance":"chief","turn":"e773abb1-268c-4404-a5da-81acd979905f","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"r42524dd77612","instance":"pm","turn":"58e2bf95-0793-4495-bcdc-b27aa651caa1","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"rf8408ce6a5b4","instance":"chief","turn":"cb53fe60-e24f-4760-b284-d3b1d3620050","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"r42524dd77612","instance":"pm","turn":"7460fc5d-aea2-4343-98a5-00d063c730c5","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"r42524dd77612","instance":"pm","turn":"1ee4cbc7-90b7-4275-b3ac-4cbbd0394912","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"rf8408ce6a5b4","instance":"chief","turn":"1573dcc7-1d85-4783-b8c9-1a25c6ff71ac","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"r42524dd77612","instance":"pm","turn":"bcb2aa05-7af5-4d9e-b085-c631754554ae","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"rf8408ce6a5b4","instance":"chief","turn":"9c77b01a-8f82-4d76-8e86-3eccdf5c05bc","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 (1399.028095ms)
✔ each launch makes sure the workspace has a clone of the project: cloned, fast-forwarded, or fetched and logged (4193.990785ms)
✔ a role the broker says holds a merge decision gets land_work, its prompt line, its landing and the git socket; without it, none (707.949813ms)
✔ 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 (438.968553ms)
usage: {"event":"usage-unknown","business":"acme","run":"r33b3a0a89f29","instance":"coder","turn":"54d42057-6aeb-4460-bbbb-11bb7d96f6a0","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 (784.946481ms)
✔ a landing run that ended isn't started again for its decision, a spent decision starts nothing, and a new decision starts the holder (733.626616ms)
✔ after a restart, the new host's first tick starts a holder whose decision is still held (1104.180428ms)
✔ 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 (766.099638ms)
✔ a project clone that can't be made refuses checkout-failed, from --chief and from a session, with no run and no clone left (314.836965ms)
✔ a runner that stops at once ends its launch with the runner's reason (380.228742ms)
✔ a Claude Code launch with no session credential refuses before it starts (206.698491ms)
✔ a pi launch with no own credential refuses no-session-credential (194.63649ms)
usage: {"event":"plugin-refused","kind":"harness","name":"down","code":"missing","message":"/home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/harness/down is missing","kept":[]}
plugins: {"event":"plugin-refused","kind":"harness","name":"down","code":"missing","message":"/home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/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 (395.760187ms)
✔ a runner killed from the host ends its launch as killed, not failed (404.215037ms)
✔ a missing or failing bwrap refuses sandbox-unavailable before anything starts; there is no unconfined fallback (204.482756ms)
✔ 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 (223.681469ms)
✔ row 213 a creative instance's persona is read from <configDir>/personas: off its digest the launch fails with the mismatch as its reason (294.218836ms)
✔ row 64 on Claude Code a role skill that isn't enabled refuses the same way, before anything starts (216.464613ms)
usage: {"event":"usage-unknown","business":"acme","run":"r4b699771c38c","instance":"chief","turn":"77969cf2-7fc8-41ff-8d52-7569e054b6f8","source":"@none","code":"baseline-unknown"}
usage: {"event":"usage-unknown","business":"acme","run":"r6e6168e49a89","instance":"coder","turn":"e6dfb039-1843-41b7-8111-7992cfddac3d","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 (2155.647443ms)
✔ 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 (1620.990125ms)
✔ 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 (4336.758535ms)
✔ bus start --no-launch leaves an earlier host's live session alone: no signal, no end, sessions.json as it was (279.143242ms)
✔ bus start --no-launch refuses every launch: the PM launch and a session's request, each logged, nothing spawned (229.339371ms)
✔ bus start --no-launch starts no thread tick; the same host with launches runs it (1236.511266ms)
✔ a malformed sessions.json refuses the host start with exit 3 and stays as it was (212.151607ms)
✔ an over-long launch request is refused at once, not at the 10 s idle timeout (201.563393ms)
✔ a launch client that never closes its side doesn't hold the host's close (203.041695ms)
✔ a runner that ignores SIGTERM is killed when the host closes (1399.240682ms)
✔ kill switch refuses chief and hire before launch work and a clear permits a later request (362.776444ms)
✔ kill switch stops an actual managed namespace and records the halt reason without rewriting its bundle (400.610758ms)
✔ a launch waiting across halt and resume cannot use its stale admission (221.918115ms)
ℹ tests 35
ℹ suites 0
ℹ pass 35
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 30999.3545
exit=0
00:02:27Z
@@ -1,35 +0,0 @@
00:01:56Z
nice=19
✔ P3 Anthropic route uses messages at proxy root and the declared model id (11.574291ms)
✔ P3 omitted route refuses proxy-route-missing before model config generation (2.072933ms)
✔ P3 GLM route uses completions at proxy /v1 with explicit z.ai compatibility (2.699568ms)
✖ P3 GPT route selects a stack-owned provider instead of pi Codex OAuth (2.510206ms)
✔ P3 a declared Codex route refuses generation while the build-time API is PENDING (2.334352ms)
✔ P3 models file is private, references the one session key, and stores no executable values or keys (3.084202ms)
✔ P3 every launch regenerates proxy port, declared models and own key without caching (5.343868ms)
ℹ tests 7
ℹ suites 0
ℹ pass 6
ℹ fail 1
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 108.561079
✖ failing tests:
test at packages/harness/tests/proxy-bundle.test.mjs:62:1
✖ P3 GPT route selects a stack-owned provider instead of pi Codex OAuth (2.510206ms)
Error: proxy GPT API is PENDING build-time evidence
at Module.bundle (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/plugins/harness/pi/index.mjs:78:62)
at buildBundle (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/src/bundle.mjs:359:23)
at build (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:20:18)
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/fethry-row332/packages/harness/tests/proxy-bundle.test.mjs:63: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)
exit=1
00:01:56Z
@@ -1,16 +0,0 @@
packages/business/tests/launch-settings.test.mjs:41: assert.throws(()=>migrateLaunch(old,{...mapping,families:{opus:'missing',sonnet:'sonnet'}},f.file,{rolesDir:f.rolesDir}));assert.throws(()=>migrateLaunch(old,{...mapping,families:{opus:'opus',sonnet:'opus'}},f.file,{rolesDir:f.rolesDir}),/ambiguous/);assert.throws(()=>migrateLaunch(old,{...mapping,models:{...mapping.models,proxy:{provider:'proxy',route:'anthropic',model:'claude-opus-5-5'}},instances:{pm:'proxy'}},f.file,{rolesDir:f.rolesDir}),/ambiguous/);const onlyOpus=structuredClone(old);onlyOpus.launch.max={opus:4};assert.throws(()=>migrateLaunch(onlyOpus,mapping,f.file,{rolesDir:f.rolesDir}),/unknown or ambiguous/);const allOpus=structuredClone(old);for(const r of Object.values(allOpus.roles))r.vars.model='claude-opus-5-5';assert.throws(()=>migrateLaunch(allOpus,{...mapping,families:{opus:'opus',sonnet:'opus'}},f.file,{rolesDir:f.rolesDir}),/ambiguous/);assert.equal(readFileSync(f.file,'utf8'),bytes);assert.equal(statSync(f.file).mtimeMs,mtime);
packages/business/tests/launch-settings.test.mjs:45: const result=settings.set('acme',{revision:view.revision,limits:{total:0},instances:{coder:'opus'}},'jason');assert.equal(result.limits.total,0);assert.equal(result.instances.coder.modelKey,'opus');const models=structuredClone(result.models);models.opus.provider='proxy';models.opus.route='anthropic';const updated=settings.set('acme',{revision:result.revision,models},'jason');assert.equal(updated.instances.pm.provider,'proxy');assert.throws(()=>settings.set('acme',{revision:result.revision,instances:{coder:'ghost'}},'jason'));assert.throws(()=>settings.set('acme',{revision:result.revision,roles:{}},'jason'));
packages/business/tests/launch-settings.test.mjs:154: const moved={...models,[key]:{provider:'proxy',route:'anthropic',model:'claude-sonnet-5-5'}};
packages/business/tests/launch-settings.test.mjs:161: ({revision}=settings.set('acme',{revision,models:{...models,spare:{provider:'proxy',route:'anthropic',model:'claude-opus-5-5'}}},chief));
packages/business/tests/launch-settings.test.mjs:188: const sonnet={...models,sonnet:{provider:'proxy',route:'anthropic',model:'claude-sonnet-5-5'}};
packages/business/tests/launch-settings.test.mjs:198: ({revision}=settings.set('acme',{revision,models:{...models,opus:{provider:'proxy',route:'anthropic',model:'claude-opus-5-5'}}},chief));
packages/business/tests/proxy-launch.test.mjs:8: const models = { selected: { provider: 'proxy', model: 'proxy-only-id', route } };
packages/business/tests/proxy-launch.test.mjs:14: assert.throws(() => checkModels({ selected: { provider: 'proxy', model: 'proxy-only-id' } }), {
packages/business/tests/proxy-launch.test.mjs:21: assert.throws(() => checkModels({ selected: { provider: 'proxy', model: 'proxy-only-id', route } }), {
packages/cli/tests/launcher.test.mjs:155: doc.launch.models['claude-opus-5-5'] = { provider: 'proxy', model: 'claude-fixture', route: 'anthropic' };
packages/harness/tests/proxy-bundle.test.mjs:10: a: { provider: 'proxy', model: 'claude-fixture', route: 'anthropic' },
packages/harness/tests/proxy-bundle.test.mjs:11: z: { provider: 'proxy', model: 'glm-fixture', route: 'glm' },
packages/harness/tests/proxy-bundle.test.mjs:12: g: { provider: 'proxy', model: 'gpt-fixture', route: 'codex' },
packages/harness/tests/proxy-bundle.test.mjs:47: a: { provider: 'proxy', model: 'claude-fixture' },
packages/harness/tests/proxy-bundle.test.mjs:97: a: { provider: 'proxy', model: 'changed-model-id', route: 'anthropic' },
packages/harness/tests/proxy-bundle.test.mjs:98: z: { provider: 'proxy', model: 'changed-glm-id', route: 'glm' },
@@ -1,18 +0,0 @@
00:01:47Z
nice=19
✔ P3 proxy model validation preserves each explicit wire route and the proxy model id (1.21495ms)
✔ P3 a proxy model without route refuses proxy-route-missing (0.356994ms)
✔ P3 an unknown proxy route refuses proxy-route-unknown (0.767073ms)
✔ P3 nonproxy models retain their provider/model-only shape and reject route metadata (0.17626ms)
✔ P3 launch.account accepts the proxy credential source without naming host variables (0.179844ms)
✔ P3 existing environment-set accounts retain their validated representation (0.312195ms)
ℹ tests 6
ℹ suites 0
ℹ pass 6
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 57.913873
exit=0
00:01:47Z
@@ -1,31 +0,0 @@
packages/business/tests/launch-settings.test.mjs:41: assert.throws(()=>migrateLaunch(old,{...mapping,families:{opus:'missing',sonnet:'sonnet'}},f.file,{rolesDir:f.rolesDir}));assert.throws(()=>migrateLaunch(old,{...mapping,families:{opus:'opus',sonnet:'opus'}},f.file,{rolesDir:f.rolesDir}),/ambiguous/);assert.throws(()=>migrateLaunch(old,{...mapping,models:{...mapping.models,proxy:{provider:'proxy',route:'anthropic',model:'claude-opus-5-5'}},instances:{pm:'proxy'}},f.file,{rolesDir:f.rolesDir}),/ambiguous/);const onlyOpus=structuredClone(old);onlyOpus.launch.max={opus:4};assert.throws(()=>migrateLaunch(onlyOpus,mapping,f.file,{rolesDir:f.rolesDir}),/unknown or ambiguous/);const allOpus=structuredClone(old);for(const r of Object.values(allOpus.roles))r.vars.model='claude-opus-5-5';assert.throws(()=>migrateLaunch(allOpus,{...mapping,families:{opus:'opus',sonnet:'opus'}},f.file,{rolesDir:f.rolesDir}),/ambiguous/);assert.equal(readFileSync(f.file,'utf8'),bytes);assert.equal(statSync(f.file).mtimeMs,mtime);
packages/business/tests/launch-settings.test.mjs:45: const result=settings.set('acme',{revision:view.revision,limits:{total:0},instances:{coder:'opus'}},'jason');assert.equal(result.limits.total,0);assert.equal(result.instances.coder.modelKey,'opus');const models=structuredClone(result.models);models.opus.provider='proxy';models.opus.route='anthropic';const updated=settings.set('acme',{revision:result.revision,models},'jason');assert.equal(updated.instances.pm.provider,'proxy');assert.throws(()=>settings.set('acme',{revision:result.revision,instances:{coder:'ghost'}},'jason'));assert.throws(()=>settings.set('acme',{revision:result.revision,roles:{}},'jason'));
packages/business/tests/launch-settings.test.mjs:154: const moved={...models,[key]:{provider:'proxy',route:'anthropic',model:'claude-sonnet-5-5'}};
packages/business/tests/launch-settings.test.mjs:161: ({revision}=settings.set('acme',{revision,models:{...models,spare:{provider:'proxy',route:'anthropic',model:'claude-opus-5-5'}}},chief));
packages/business/tests/launch-settings.test.mjs:188: const sonnet={...models,sonnet:{provider:'proxy',route:'anthropic',model:'claude-sonnet-5-5'}};
packages/business/tests/launch-settings.test.mjs:198: ({revision}=settings.set('acme',{revision,models:{...models,opus:{provider:'proxy',route:'anthropic',model:'claude-opus-5-5'}}},chief));
packages/business/tests/proxy-launch.test.mjs:8: const models = { selected: { provider: 'proxy', model: 'proxy-only-id', route } };
packages/business/tests/proxy-launch.test.mjs:14: assert.throws(() => checkModels({ selected: { provider: 'proxy', model: 'proxy-only-id' } }), {
packages/business/tests/proxy-launch.test.mjs:21: assert.throws(() => checkModels({ selected: { provider: 'proxy', model: 'proxy-only-id', route } }), {
packages/business/tests/proxy-launch.test.mjs:35: assert.deepEqual(checkAccount({ name: 'proxy', credential: 'proxy' }), { name: 'proxy', credential: 'proxy' });
packages/business/tests/proxy-launch.test.mjs:43: assert.throws(() => checkAccount({ name: 'proxy', credential }), /launch\.account\.credential/);
packages/cli/tests/launcher.test.mjs:155: doc.launch.models['claude-opus-5-5'] = { provider: 'proxy', model: 'claude-fixture', route: 'anthropic' };
packages/cli/tests/model-proxy.test.mjs:11:test('proxy init agent and tester refuse before prompting or transport',async()=>{for(const args of [['proxy','init','--tester'],['proxy','init']]){const x=io(args.includes('--tester')?{}:{CODEX_THREAD_ID:'fixture'});await assert.rejects(main(args,x,{promptProxyKey:()=>{throw Error('must not prompt');}}),code('human-required'));}});
packages/cli/tests/model-proxy.test.mjs:12:test('proxy init prompts twice through no-echo seam and sends key only through human transport',async()=>{const x=io();x.stdin.isTTY=true;x.stdout.isTTY=true;const prompts=[],calls=[];await main(['proxy','init','--business','demo','--port','18432'],x,{system:fakeSystem(),promptProxyKey:async()=>{prompts.push('hidden');return 'p1-management';},transport:b=>async(verb,args)=>{calls.push({b,verb,args});return {port:18432,binary:'/fixture'};}});assert.equal(prompts.length,2);assert.deepEqual(calls,[{b:'demo',verb:'proxy.init',args:{key:'p1-management',port:18432}}]);assert.equal(x.out.text.includes('p1-management'),false);});
packages/cli/tests/model-proxy.test.mjs:13:test('proxy-key-mismatch: confirmation refuses without bus call',async()=>{const x=io();x.stdin.isTTY=true;x.stdout.isTTY=true;let count=0;await assert.rejects(main(['proxy','init','--business','demo'],x,{system:fakeSystem(),promptProxyKey:async()=>++count===1?'p1-one':'p1-two',transport:()=>()=>{throw Error('must not call');}}),code('proxy-key-mismatch'));});
packages/cli/tests/model-proxy.test.mjs:14:test('proxy-terminal-required: stdin redirection refuses',async()=>{await assert.rejects(main(['proxy','init'],io(),{system:fakeSystem()}),code('proxy-terminal-required'));});
packages/cli/tests/model-proxy.test.mjs:15:test('proxy-usage: invalid verb and repeated flags refuse',async()=>{for(const args of [['proxy','unknown'],['proxy','init','--port','18432','--port','18433']])await assert.rejects(main(args,io(),{system:fakeSystem()}),code('proxy-usage'));});
packages/cli/tests/model-proxy.test.mjs:16:test('proxy-config-invalid: port 8317 refuses before prompting',async()=>await assert.rejects(main(['proxy','init','--port','8317'],io(),{system:fakeSystem()}),code('proxy-config-invalid')));
packages/cli/tests/model-proxy.test.mjs:17:test('proxy-key-invalid: empty prompt refuses without printing input',async()=>{const x=io();x.stdin.isTTY=true;x.stdout.isTTY=true;await assert.rejects(main(['proxy','init','--business','demo'],x,{system:fakeSystem(),promptProxyKey:async()=>'',transport:()=>()=>{throw Error('must not call');}}),code('proxy-key-invalid'));});
packages/harness/tests/proxy-bundle.test.mjs:10: a: { provider: 'proxy', model: 'claude-fixture', route: 'anthropic' },
packages/harness/tests/proxy-bundle.test.mjs:11: z: { provider: 'proxy', model: 'glm-fixture', route: 'glm' },
packages/harness/tests/proxy-bundle.test.mjs:12: g: { provider: 'proxy', model: 'gpt-fixture', route: 'codex' },
packages/harness/tests/proxy-bundle.test.mjs:47: a: { provider: 'proxy', model: 'claude-fixture' },
packages/harness/tests/proxy-bundle.test.mjs:97: a: { provider: 'proxy', model: 'changed-model-id', route: 'anthropic' },
packages/harness/tests/proxy-bundle.test.mjs:98: z: { provider: 'proxy', model: 'changed-glm-id', route: 'glm' },
packages/model-proxy/tests/config-unit.test.mjs:14:test('loader proxy absent is byte-compatible; present validates sidecar and preserves config.json',()=>{const f=fixture(),before=readFileSync(f.file);let r=run(f,'scripts/mosaic-config.mjs',['validate']);assert.equal(r.status,0,r.stderr);assert.equal(Object.hasOwn(JSON.parse(r.stdout),'proxy'),false);const value=proxy(f);r=run(f,'scripts/mosaic-config.mjs',['validate']);assert.equal(r.status,0,r.stderr);assert.deepEqual(JSON.parse(r.stdout).proxy,value);assert.deepEqual(readFileSync(f.file),before);});
packages/model-proxy/tests/config-unit.test.mjs:23:test('historical no-proxy config loader works without new package dependency',()=>{const f=fixture();const copy=join(f.root,'historical/scripts');mkdirSync(copy,{recursive:true});writeFileSync(join(copy,'mosaic-config.mjs'),readFileSync(join(repo,'scripts/mosaic-config.mjs')));const r=spawnSync(process.execPath,[join(copy,'mosaic-config.mjs'),'validate'],{env:f.env,encoding:'utf8',timeout:10000});assert.equal(r.status,0,r.stderr);assert.equal(Object.hasOwn(JSON.parse(r.stdout),'proxy'),false);});
packages/model-proxy/tests/management-key-encoding.test.mjs:71: assert.deepEqual(added('data'), ['proxy', 'proxy/auth', 'proxy/config.yaml', 'proxy/logs']);
packages/model-proxy/tests/runner.test.mjs:9:test('runner verifies before spawning and supplies pinned panel and local model without ambient secrets',()=>{const {root,config,install}=fixture();const calls=[],child=new EventEmitter();startVerifiedProxy(config,{env:{HOME:join(root,'home'),MANAGEMENT_PASSWORD:'p1-management',OPENAI_API_KEY:'p1-upstream'},verify:dir=>{calls.push(['verify',dir]);return install;},spawnImpl:(...args)=>{calls.push(['spawn',...args]);return child;}});assert.equal(calls[0][0],'verify');assert.deepEqual(calls[1],['spawn',install.binary,['-config',join(config.dataRoot,'proxy/config.yaml'),'-local-model'],{cwd:join(config.dataRoot,'proxy'),stdio:'inherit',env:{HOME:join(root,'home'),PATH:'/usr/bin:/bin',MANAGEMENT_STATIC_PATH:join(root,'pin/static')}}]);});
packages/model-proxy/tests/settings.test.mjs:19:test('exclusive initialization writes private sentinel config, never rewrites config.json or exposes key',async()=>{const f=fixture();installed(f);const key='p1-management';const result=await initializeProxy({...f,pin,key});assert.ok(result.port>=1024&&result.port!==8317);assert.equal(JSON.stringify(result).includes(key),false);const conf=JSON.parse(readFileSync(join(f.dataRoot,'proxy/config.yaml'),'utf8'));assert.equal(conf.server.host,'127.0.0.1');assert.equal(conf.management['allow-remote'],false);assert.equal(conf.management['disable-auto-update-panel'],true);assert.equal(conf.routing.strategy,'fill-first');assert.equal(conf.routing.retry['request-retry'],0);assert.match(conf.access['api-keys'][0],/^msk-.*-sentinel-/);for(const file of [join(f.configDir,'secrets/proxy-management.key'),join(f.dataRoot,'proxy/config.yaml')])assert.equal(lstatSync(file).mode&0o777,0o600);for(const dir of ['proxy','proxy/auth','proxy/logs'])assert.equal(lstatSync(join(f.dataRoot,dir)).mode&0o777,0o700);assert.equal(readFileSync(join(f.configDir,'config.json'),'utf8'),'unchanged');await assert.rejects(initializeProxy({...f,pin,key}),code('proxy-already-initialized'));});
packages/model-proxy/tests/settings.test.mjs:23:test('proxy-already-initialized: each existing target is preserved and never followed',async()=>{for(const target of ['proxy','key','settings']){const f=fixture();installed(f);let file;if(target==='proxy'){file=join(f.dataRoot,'proxy');mkdirSync(file);writeFileSync(join(file,'marker'),'old');}else if(target==='key'){mkdirSync(join(f.configDir,'secrets'),{mode:0o700});file=join(f.configDir,'secrets/proxy-management.key');writeFileSync(file,'old');}else{file=join(f.configDir,'proxy.json');writeFileSync(file,'old');}await assert.rejects(initializeProxy({...f,pin,key:'p1-management'}),code('proxy-already-initialized'));assert.equal(readFileSync(target==='proxy'?join(file,'marker'):file,'utf8'),'old');}});
+402
View File
@@ -0,0 +1,402 @@
# Row 255 design: a bundled Pocket ID for users with no OIDC provider (Q203, Gitea #1760, Vikunja 458)
Launchpad, draft 1, 2026-10-25, on `launchpad/row255` off refactor 78b69e1e6. Brief
`docs/plans/2026-10-21_bundled-pocket-id.md` (blob 26f34400). Reviewer Webby. Sage checks it against Q203, O6,
REQ-WEB-2 and REQ-INST-1. REQ-INST-2 (PRD 1.10) is post-v1 (mos-1204), and so is everything here.
This is a design only. Nothing here installs, downloads or starts Pocket ID. It changes nothing on .53, .54 or
dragon-lin, which keeps Authentik.
## Sources
- Q203 and O6 as the brief quotes them. PRD `docs/prd/mosaic-stack.md` REQ-WEB-2 (:902), REQ-INST-1 (:1509),
REQ-INST-2 (:1513) and REQ-INST-3 (:1528). Lead decision 44 items 5 and 6
(`docs/plans/2026-09-26_lead-decisions.md:655-663`).
- The Q175 design `agents/sage/work/q175-sso/DESIGN.md` sections 4 and 10, and the code row 192 landed:
`packages/webui/src/sso-config.mjs` (the `console.sso` shape), `packages/webui/src/sso.mjs` (the slot read,
the discovery checks at :105-118, the client at :147-148, the callback at :133, the post-logout URI at :332).
- Researcher's note `agents/researcher/work/2026-10-04_vikunja-pocketid.md` part 2 (v2.17.0).
- A fresh read of upstream on 2026-10-25, from release metadata and source text only: no binary was fetched or
run. The latest stable release is **v2.19.1** (2026-10-22). Source paths below are under
`backend/internal/` at tag v2.19.1 in `github.com/pocket-id/pocket-id`, marked "P". Releases v2.18.0,
v2.19.0 and v2.19.1 are not marked breaking.
## What the Console already needs from any provider
This design keeps the Console's sign-in and start checks exactly as row 192 built them. Pocket ID becomes one
`console.sso.providers` entry, the same shape any compliant OP uses (Q175 section 4, "Several providers"). The
Console gets no new sign-in path, no password and no proxy-header identity (O6, REQ-WEB-2, REQ-INST-2). The
facts that drive the rest of the design:
- `publicOrigin` and every `issuer` must be https (`sso-config.mjs` `httpsURL`). A plain-http Pocket ID can't
be a provider at all.
- Each provider needs 1 to 64 `subjects`. A `console.sso` with no subject refuses to load. So the first
person's subject has to exist before the Console starts with `--sso` (section 5).
- The client authenticates with `client_secret_basic` (`sso.mjs:148`), so the client is confidential.
- The slot is `<configDir>/secrets/mosaic-stack/<slot>`: a regular file, owned by the Console's uid, mode
with no group or other bits, and outside the repo and every stack copy (`readSlot`).
- `config.json` is user-authored. bootstrap.sh creates it and nothing overwrites it (canon invariant 2, Q175
section 4). This matters for sections 1 and 5.
## 1. The choice
The installer is REQ-INST-3's install command (Vikunja #432; today `stack-upgrade.sh` and the per-case
install scripts). It takes one sign-in option per instance:
- `--oidc existing`. The user points the Console at one or more OIDC providers they already have. Nothing
is installed. The user writes `console.sso` themselves, as Q175 step 4 does today. The installer writes
nothing into `console.sso`; it prints the entry shape and the two URIs to register
(`<publicOrigin>/auth/callback`, `<publicOrigin>/auth/signed-out`).
- `--oidc bundled`. The stack installs Pocket ID as an install component (section 2), and
`console.sso.providers` holds exactly one entry, `id: "pocket-id"`, whose `issuer` is the component's
origin.
- No option keeps today's behaviour: no `console.sso`, and the Console runs without `--sso`.
How the bundled choice is recorded. REQ-INST-1 lets a component be switched on "in the organization file
or system config". It has to be the system config. The organization file can be written by agents through
`organizationWriter`, which is the reason Q175 B1 put `console.sso` in config.json, and the same reason
holds for a component that issues the Console's identities. So config.json gets one new optional key:
```json
"components": {
"pocket-id": {
"release": "v2.19.1",
"origin": "https://id.example.internal",
"port": 1411
}
}
```
The loader (`scripts/mosaic-config.mjs`) checks the shape: `release` is a `vX.Y.Z` tag, and the component script refuses one that
differs from the pin file (section 2), `origin` is an https origin, `port` is 1024 to 65535. It also cross-checks: when
`components["pocket-id"]` is present, `console.sso` must have exactly one provider, `id` `pocket-id`,
`issuer` equal to `origin`. A config with `console.sso` providers and no `components` is the existing
choice and loads as today.
**M1, approved by Mos with three conditions (mos-1666 item 3).** `components` is a new top-level config key.
The loader refuses unknown keys today, so this is a config schema change. The conditions:
1. **Rollback trap.** A copy older than P1 refuses a config that has the key, the same trap Q175 section 4
names for `console.sso`. P1 documents the order. On a rollback past P1, first take `components` out of
config.json (restore the backup made before the key went in), then roll back the pointer. The STATE check
after the rollback reads config.json and confirms the key is absent.
2. **Strict inside the key.** The loader refuses any name under `components` other than `pocket-id`, and any
field under `pocket-id` other than `release`, `origin` and `port`. Each refusal names the key path and
quotes no value, as `checkConsole` does.
3. **test-config.sh cases:**
- a valid `components` loads;
- a malformed one fails, naming the bad key path;
- a config without `components` loads;
- the cross-check refuses a `console.sso` whose provider doesn't match `origin`.
What each choice writes into `console.sso` is in section 5. For the bundled choice, Pocket ID is the only
providers entry. The design keeps it that way because REQ-INST-2 says "the Console's one providers entry".
A user who later adds an existing provider moves to `--oidc existing` and removes the component (section 2).
## 2. The component, against REQ-INST-1
**Pinned.** A Pocket ID release is a set of raw binaries plus `checksums.txt` (sha256). From v2.16.0 there is
an SPDX SBOM per binary, and the release workflow attests `checksums.txt` through Sigstore (`actions/attest`
in `.github/workflows/release.yml`). The repo holds one pin file,
`scripts/pocket-id-pins.sh`, sourced the way `scripts/case1-pins.sh` is: the tag, and for each supported platform (linux amd64 and arm64 to
start) the asset name and its sha256. The build row copies the sha256 from `checksums.txt` at the tag and
records the `gh attestation verify` output for each asset as its evidence. The pin is checked by hand at
build time, not trusted at install time. No Pocket ID source and no binary goes in the repo. The binary is
not in any image either, since the container install comes after v1 (REQ-INST-3).
Recommended pin: v2.19.1, the current release. The build row checks it again, because Pocket ID ships a
minor every one to four weeks. Upgrading is a pin file change in a reviewed commit.
**Fetched and checked.** `scripts/component-pocket-id.sh fetch` downloads the pinned asset for the host's
platform over https into a new 0700 staging directory, computes its sha256, and compares it with the pin.
On a mismatch it deletes the file and refuses with `pocket-id-digest-mismatch`, naming the expected value
and the computed one. On a match it installs the binary read-only (0555) at
`<dataRoot>/components/pocket-id/bin/pocket-id-<tag>`. The fetch is the only network step, and the user
runs it at install. Tests never run it against the network (section 9).
**Runs.** A systemd user unit, `mosaic-pocket-id.service` (`mosaic-pocket-id-NAME.service` for a named
instance, as row 190 names the bus and webui units), as the instance's user:
- `ExecStart=<dataRoot>/components/pocket-id/bin/pocket-id-<tag>`.
- `WorkingDirectory=<dataRoot>/components/pocket-id/run`, a directory the unit owns, so Pocket ID's habit of
reading `.env` from the working directory reads nothing we didn't write. The build row checks there is no
`.env` there at start.
- Environment, all from the rendered unit:
- `APP_URL=<origin>` and `HOST=127.0.0.1` (P `common/env_config.go`: HOST defaults to `0.0.0.0`).
- `PORT=<port>`.
- `DB_CONNECTION_STRING` and `UPLOAD_PATH` as absolute paths under `<dataRoot>/components/pocket-id/data/`
(P defaults are `data/pocket-id.db` and `data/uploads`, relative to the working directory).
- `ALLOW_USER_SIGNUPS=disabled` and `ALLOW_INSECURE_CALLBACK_URLS=false`.
- `EMAIL_ONE_TIME_ACCESS_AS_UNAUTHENTICATED_ENABLED=false` and `..._AS_ADMIN_ENABLED=false`.
- The `OUTBOUND_ALLOWED_HOSTS_*` allowlists set empty (added in 2.19.0).
- No `TRUST_PROXY` unless section 6's proxy step sets it to the proxy's address.
- `ENCRYPTION_KEY` (mandatory since v2.0, at least 16 bytes) never goes in the unit text. It lives in slot
`<configDir>/secrets/mosaic-stack/pocket-id-encryption-key`, 0600. The component script generates it from
`/dev/urandom` straight into the file and never prints it. The unit passes it with
`LoadCredential=` and `ENCRYPTION_KEY_FILE=%d/...`. The build row confirms `ENCRYPTION_KEY_FILE` at the pinned
tag; if it isn't there, it refuses rather than putting the key in `Environment=`.
- The unit never carries `STATIC_API_KEY`. That key exists only during the enroll run (section 4).
The data directory holds the SQLite database, Pocket ID's signing key (stored encrypted with
`ENCRYPTION_KEY`), and the passkey registrations. It is 0700. Agent sandboxes bind only an allowlist
(`packages/seat/src/sandbox.mjs`), and `<dataRoot>/components/` is not on it. The build row adds a sandbox
test that pins that.
**Health-checked.** `GET http://127.0.0.1:<port>/healthz` returns 204 (P `controller/healthz_controller.go`).
`component-pocket-id.sh status` reports the unit state, the binary tag against the pin, the binary's sha256
against the pin, and the health result. The Console's own `/healthz` already shows `sso: { "pocket-id": ready
| unreachable | refused }` from its discovery retries, so an operator sees the provider from either side.
**Removable.** `component-pocket-id.sh remove` refuses while `console.sso` still names `pocket-id`, so the
Console can't be left pointing at a provider that's gone. Once the user has taken the entry out (or moved to
`--oidc existing`), the script stops and removes the unit, then moves the data directory to
`<dataRoot>/components/pocket-id.removed-<utc>` with a receipt line in `<dataRoot>/state/components.log`
(append-only). It never deletes the passkey database outright. Deleting the moved directory and the
encryption key slot is a separate `purge` verb that names both paths and needs `--yes`. Removing the
`components` key from config.json is the user's edit.
## 3. The Q175 start checks against the bundled instance
The Console checks are unchanged. Here is each one against Pocket ID, and the setting it needs:
| Check (row 192) | Pocket ID v2.19.1 | Default that fails | Fix |
|---|---|---|---|
| `issuer` is https (loader) | issuer = `APP_URL` exactly (P `controller/well_known_controller.go`) | `APP_URL` defaults to `http://localhost:1411` | `APP_URL=<https origin>`, section 6 |
| discovery `issuer` equals config `issuer` | equal when `APP_URL` has no trailing slash; Pocket ID refuses a path | none | config `issuer` = `origin`, no trailing slash; the loader cross-check compares them |
| `id_token_signing_alg_values_supported` overlaps `algs` | advertises only the current key's alg. RS256 (RSA-2048) by default (P `service/jwt_service.go`) | none | `algs: ["RS256"]` |
| `code_challenge_methods_supported` has `S256` | advertises `plain` and `S256` | none | none. The Console always sends S256 (`sso.mjs:221`) |
| JWKS has a usable key for `algs` | one key at `/.well-known/jwks.json` | none | none. The build row's fake OP pins `use`/`alg`/`kid` as Pocket ID emits them |
| `end_session_endpoint` is https | `<APP_URL>/api/oidc/end-session` | http, if `APP_URL` is http | same fix as row 1 |
| `redirect_uri` is registered | exact match first, then wildcard patterns; loopback callbacks match any port (P `utils/callback_url_util.go`) | `ALLOW_INSECURE_CALLBACK_URLS` defaults to true | register exactly `<publicOrigin>/auth/callback`, with no `*`; set `ALLOW_INSECURE_CALLBACK_URLS=false` |
| post-logout URI | per-client `logoutCallbackURLs`, same matching | none | register exactly `<publicOrigin>/auth/signed-out` |
| ID token alg in `algs`, `iss` match | as above | none | none |
Two points the Console doesn't check, set on the client anyway:
- `pkceEnabled: true`. Then Pocket ID refuses an authorize request that has no `code_challenge`. Pocket ID has
no per-client S256-only setting (P `oidc/provider.go` turns on `plain` for the server). That doesn't relax
anything: the Console sends S256 every time, and `plain` stays available only to other clients.
- `isPublic: false`, which matches `client_secret_basic`.
Key rotation. `pocket-id key-rotate --alg ...` replaces the one signing key (P `cmds/key_rotate.go`). After a
rotation to another alg, the Console's discovery check refuses on the next restart (no overlap with
`algs`), and that is the intended fail-closed result. A rotation is a user step that updates `algs` in the
same edit. The component script never rotates.
## 4. The client, and where its secret goes
The person running the install creates the client through `component-pocket-id.sh enroll`. No agent runs
this verb. It refuses when any agent marker is in its environment: the `MARKERS` list in
`packages/bus/src/human.mjs` (`MOSAIC_RUN_ID`, `MOSAIC_BUS_CAP`, `CLAUDECODE` and the rest) that the human
boundary uses. A test pins the refusal.
Enroll needs admin rights before any person has a passkey. Pocket ID offers two ways to get them, and one of
them is a hazard:
- `/setup` and its backing `POST /api/signup/setup` are unauthenticated: whoever calls first becomes admin
(P `usersignup/service.go`). Sandboxed agents share the host's network namespace (`sandbox.mjs` unshares
user, pid and ipc, not net), so any agent could reach a loopback Pocket ID and take that first admin.
- `STATIC_API_KEY` is a fixed admin key with no expiry (P `apikey/service.go`). It doesn't count as
completing setup, so `/setup` stays open while it's set.
So enroll never lets the real unit serve before an admin person exists. It runs the pinned binary once in a
**private network namespace** (`unshare --user --net`, or `bwrap --unshare-net` with the binary and data
directory bound), where only enroll's own loopback can reach it:
1. Generate a one-run static key into a 0600 temp file in a new 0700 directory, and start Pocket ID inside
the namespace with `STATIC_API_KEY_FILE` pointing at it, plus the unit's environment.
2. Wait for `/healthz` 204.
3. Create the admin user, `POST /api/users` with `isAdmin: true` and the username and email given with
`--admin-user` and `--admin-email`. Keep the returned `id`. That is the OIDC `sub` (P
`oidc/claims_service.go` uses `user.ID`, a UUIDv4 set at creation, so it's stable).
4. Create the Console client: client id `mosaic-console-<instance>`, callback and logout URLs exactly as in
section 3, `pkceEnabled: true`, `isPublic: false`. Supply the secret instead of letting Pocket ID
generate it. Enroll generates 48 random bytes, base64url, and writes them straight to slot
`<configDir>/secrets/mosaic-stack/console-sso-pocket-id` (0600, `O_CREAT|O_EXCL`, not a symlink). It sends
the same bytes in the create body over the namespace's loopback (`dto/oidc_dto.go` accepts a supplied
secret of 16 or more characters). The value is never printed, logged or put in an argv, and a test pins
that it appears in no output.
5. Mint a one-time access token for the admin, `POST /api/users/<id>/one-time-access-token`.
6. Stop the namespaced process, then shred and remove the static key file. The real unit has never had a
static key, so no admin key survives enroll.
7. Start the real unit and wait for `/healthz` 204.
8. Print the sign-in link `<origin>/lc/<token>` to the user's terminal (section 5), and the `console.sso`
entry (section 5).
The build row confirms each route and body against the pinned tag's source before it writes the client (the
upstream read for this design didn't trace the create-client route). If any of steps 1 to 7 fails, enroll
stops the process, removes the static key, leaves no slot file it created, and refuses with the step name.
The secret never enters the repo or an image. It sits in two places only: the slot file and Pocket ID's
database (stored as a hash). The Console's `readSlot` reads it as it does any provider's.
## 5. The first person, and their subject in `console.sso`
Pocket ID is passkey-only for people (REQ-INST-2). The installing user enrolls like this:
1. Enroll prints `<origin>/lc/<token>`. The token is valid for one hour and is a credential, so it goes only
to the terminal of the person who ran enroll. It goes in no log and no file.
2. The user opens it in a browser that can reach `origin` (section 6). Pocket ID signs them in and asks them
to add a passkey. Without one they can't sign in again. If the hour passes, `pocket-id
one-time-access-token <username>` (P `cmds/one_time_access_token.go`), run by the user against the data
directory, prints a new link. `component-pocket-id.sh relink` wraps that call.
3. Enroll already has the subject, the `id` from step 3 of section 4. It doesn't wait for a sign-in or read a
`subject-unknown` log line.
How the subject gets into `console.sso`. config.json is user-authored and never auto-written. Two ways
to respect that; I recommend the first:
- **R1 (recommended).** Enroll prints the full entry and writes nothing:
```json
"console": { "sso": { "publicOrigin": "<publicOrigin>", "providers": [ {
"id": "pocket-id", "issuer": "<origin>", "clientId": "mosaic-console-<instance>",
"clientSecret": { "slot": "console-sso-pocket-id" }, "algs": ["RS256"],
"subjects": [ { "sub": "<id>", "name": "<admin-user>" } ] } ] } },
"components": { "pocket-id": { "release": "<tag>", "origin": "<origin>", "port": <port> } }
```
The user pastes it into config.json, as with Q175 step 4. Rerunning `scripts/bootstrap.sh` (or
`--instance NAME`) then validates it through the loader, including the section 1 cross-check, and writes
nothing. Nothing changes in invariant 2.
- **R2 (rejected, Sage sage-4401: R1 chosen).** `enroll --write-config` would write those two keys itself, with a backup of config.json first, and
refuse if `console` or `components` were already present. That would be the first tool to modify an
existing config.json, against canon invariant 2's "never overwritten" practice. Not built.
Whose subject. Enroll creates one person, the one running it, and only that subject goes in the entry. On
Jason's instances, only his subject goes into `console.sso` (mos-1197). Further people are added with
Pocket ID's admin UI (a user plus a one-time link), and their subjects go into `console.sso` by the user's
edit, never by an agent. Pocket ID users who aren't in `subjects` can sign in to Pocket ID, but the Console
refuses them `subject-unknown`, so REQ-WEB-2's "must map to an authorized human" holds.
## 6. Reach: origin, TLS and proxy
WebAuthn takes its RP id from `APP_URL`'s host name, and its allowed origin is `APP_URL`
(P `webauthn/module.go`). Browsers allow passkeys only on a secure origin. The Console also needs https for
both `publicOrigin` and `issuer`. Pocket ID serves plain http, and I found no TLS listener setting in its
environment config. So:
- Pocket ID always binds `127.0.0.1:<port>`. That is the default, and the component never binds anything
else (`HOST=127.0.0.1`; the status verb refuses a unit whose `HOST` differs).
- `origin` is an https origin served by a TLS front that the user already has for the Console. The Console
needs one anyway, since `publicOrigin` is https. Pocket ID goes behind the same front under **its own host
name**, for example `id.<console host>`. Pocket ID doesn't support a path prefix (`APP_URL` must have no
path). A separate host name also keeps Pocket ID's cookies apart from the Console's
`__Host-mosaic_*` cookies; the two share cookies if they sit on one host name on different ports.
- The front reaches Pocket ID on loopback, so the front has to run on the same host. If it doesn't, Pocket
ID would need a non-loopback bind, and that is a `network.expose` hard wait (REQ-WAIT-1), not a component
option.
- `TRUST_PROXY` is set to the front's address only, never `true`.
- The Console fetches discovery and JWKS from `issuer` over https from the server side, so the Console's
node has to trust the front's certificate. A public CA does that. A private CA needs
`NODE_EXTRA_CA_CERTS` in the Console unit, which the build row adds as a render flag.
These steps are the user's, and on Jason's hosts they are Jason's, because each one changes who can reach
the Console or Pocket ID, or who the host trusts:
- J1: the DNS name for `origin`;
- J2: the certificate for it, or a private CA and its trust in the browser and in `NODE_EXTRA_CA_CERTS`;
- J3: the TLS front's route from `origin` to `127.0.0.1:<port>` (a Traefik change on Jason's hosts);
- J4: any listener off loopback.
The component checks and refuses; it never does them itself. With none of them done, Pocket ID runs on
loopback with an https `APP_URL` that nothing serves yet. Enroll's step 2 health probe goes straight to
`127.0.0.1`, so enroll still works. The person can't add a passkey until J1 to J3 are done.
## 7. Agents
Unchanged. Agents keep their per-role service tokens (lead decision 44 item 6, REQ-INST-2). Pocket ID issues
nothing an agent uses. The Console client is the only client enroll creates. No API, no client-credentials
grant and no admin API key exist after enroll. Residuals, stated plainly:
- Agents can reach `127.0.0.1:<port>`, because the sandbox shares the host network. What they can reach there
is the public sign-in pages, discovery and JWKS. Signup is disabled, email codes are off, `/setup` is
closed because an admin exists, and there is no static key. A test of the rendered unit pins all four
settings.
- The data directory and the two slots are outside every sandbox bind (section 2).
- A seat that ran as the same OS user outside a sandbox could read the data directory. The Console's
existing slot has the same exposure; this design adds no new class of it.
## 8. Instances
One Pocket ID per named instance, never shared:
- Each instance has one system config (row 190), and `components` and `console.sso` live in it. A shared
Pocket ID would make one instance's config depend on a unit, a data directory and an encryption key that
belong to another instance's config and data root.
- Unit names, ports, data directory, slots and removal are all per instance (`mosaic-pocket-id-NAME`,
`<dataRoot of NAME>/components/pocket-id`), so removing one instance's component can't break another's
sign-in.
- Each instance needs its own `origin` (section 6), so passkeys are per instance too. A person enrolls once
per instance.
- An instance that wants to use another instance's Pocket ID can still do it with `--oidc existing`. Then it
is just an OIDC provider, with its own client registered by that instance's owner. Nothing special-cases it.
Two instances on one host each need their own `port`. The loader can't see other instances' configs, so
`component-pocket-id.sh` refuses at fetch and enroll when the port is already bound on loopback.
## 9. Tests, stand-ins only
No test downloads or starts a real Pocket ID, and no test touches auth.diversecanvas.com,
mosaic.woltje.com or 127.0.0.1:7332. The stand-ins:
- **Fake Pocket ID OP**, a node server like row 192's fake OP, shaped from v2.19.1:
- the discovery fields `well_known_controller.go` emits (issuer = origin, `plain` and `S256`,
`end_session_endpoint` at `/api/oidc/end-session`, the three auth methods);
- one RS256 JWK at `/.well-known/jwks.json`;
- a token endpoint that takes only `client_secret_basic`;
- `/healthz` 204.
The Console starts against it under `--sso` with the section 5 entry, with no check changed. Negative
cases:
- an http issuer refuses at load;
- an ES256-only JWKS against `algs: ["RS256"]` refuses at discovery;
- an issuer with a trailing slash refuses on the cross-check.
- **Fake admin API** on the same stand-in: `POST /api/users`, the client create, the one-time token, and a
static-key check. Enroll runs against it with the binary replaced by a stub script that serves the stand-in.
The tests pin:
- the namespace argv;
- the slot file's mode and `O_EXCL`;
- that the secret appears in no stdout, stderr or argv;
- the static key file gone after success and after a failure at each step;
- the refusal under an agent marker in the environment.
- **Fetch**: a local file served by a test https server (self-signed, trusted only by the test) with a
matching pin, a mismatched pin and a truncated file.
- **Unit render**: the environment table in section 2. `HOST=127.0.0.1`, no `STATIC_API_KEY`, no
`ENCRYPTION_KEY` value in the text, and `ALLOW_USER_SIGNUPS=disabled`.
- **Loader**: test-config.sh cases for the `components` key and the cross-check, and the copy-rollback note.
- **Sandbox**: `<dataRoot>/components/` is in no bind list.
## 10. Build rows, in landing order
All are post-v1 (REQ-INST-2). Each row has Webby or Sage's named reviewer and its own gate. None of them
runs on .53, .54 or dragon-lin, and none installs Pocket ID on any host.
1. **P1, loader key.** `components["pocket-id"]` in `mosaic-config.mjs`, strict inside the key, and the
cross-check against `console.sso` (section 1, M1 conditions from mos-1666 item 3). P1 also writes the
rollback order into `docs/TOOLS.md` beside Q175's: remove `components` (restore the backup) before the
pointer goes back, and the post-rollback STATE check confirms the key is absent from config.json. Gate:
test-config.sh green with the four M1 cases.
2. **P2, pin and fetch.** `scripts/pocket-id-pins.sh` with the build-time sha256 and the
attestation evidence, and `component-pocket-id.sh fetch|verify`. Gate: the fetch tests against the local
stand-in; the evidence file shows `gh attestation verify` output for each pinned asset.
3. **P3, unit.** The unit template, `render|install|status|remove|purge`, and the encryption key slot. Gate:
the render and remove tests, and the sandbox bind test.
4. **P4, enroll.** The namespaced bootstrap, the client, the subject, `relink`, and printing the entry (R1),
(R2 rejected). Gate: the enroll tests in section 9, and a secret-leak grep over every test log.
5. **P5, Console against the fake Pocket ID.** The section 9 fake-OP start tests, and the
`NODE_EXTRA_CA_CERTS` render flag for the Console unit. Gate: the webui suite, with no change to
`sso.mjs` checks (a diff of `sso.mjs` and `sso-config.mjs` against the base shows none).
6. **P6, installer option.** `--oidc existing|bundled` on REQ-INST-3's install command, calling P2 to P4 in
order, and the docs: `docs/TOOLS.md`, the host run sheet's J1 to J4 steps. Gate: the installer's own
suite against the stubs; the docs list J1 to J4 as the user's steps.
## Open items for review
- M1 approved by Mos with three conditions (mos-1666 item 3), written into section 1 and P1.
- M2 dropped: Sage chose R1 and rejected R2 (sage-4401).
- **Q1 (Webby):** the private network namespace for enroll (section 4). The other option is to start the
real unit and race `/setup`, which I think is unsafe while agents share the host network.
- **Q2 (Webby):** one-providers-entry for the bundled choice (section 1). REQ-INST-2's wording reads that
way. Mixing a bundled Pocket ID with existing providers would need Sage's ruling.
- Not covered: Pocket ID for Vikunja or Gitea people sign-in (the Researcher note's part 3), and
client-credentials between Mosaic services. Neither is in Q203.
@@ -0,0 +1,71 @@
// Sage, 2026-10-25: files two follow-ups as P19 tasks (mos-1647 item 3, Q109): the CLIProxyAPI startup version refreshes
// seen in row 332's isolated runs (a P7 cutover item) and Webby's row 284 N1 (library read path). No relation, labels,
// assignees, due dates or bucket moves. Sage's own key (bot user 13); the sync key reads back. Refuses if a title exists.
// Prints no secret.
// Usage: node file-1025-followups.mjs https://tasks.woltje.com SAGE_TOKEN_FILE SYNC_TOKEN_FILE OUT_JSON
import { readFileSync, writeFileSync, existsSync } from "node:fs";
const [ORIGIN, KEY, SYNC, OUT] = process.argv.slice(2);
if (!/^https:\/\/tasks\.woltje\.com$/.test(ORIGIN)) throw new Error("tasks.woltje.com only");
if (!OUT || existsSync(OUT)) throw new Error("OUT_JSON missing or exists; refusing");
const PROJECT = 19;
const SIG = "Created by Sage (T3 1ef1e4f8) with Sage's own key (bot user 13).";
const esc = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
const ps = (sig, xs) => xs.map((x) => `<p>${esc(x)}</p>`).join("") + `<p>${esc(sig)}</p>`;
const TASKS = [
{
title: "Stack P7 cutover: CLIProxyAPI 8.0.42 makes outbound version-refresh calls at startup (Grok CLI via npm, antigravity)",
description: ps(SIG, [
"Filed by Mos's ruling mos-1647 item 3. Seen by Fethry in row 332 (P3) isolated runs on 2026-10-24, pinned CLIProxyAPI 8.0.42 (commit bc064340, PIN binary sha256 74661f8c), run under unshare -rn with only lo, empty HOME and auth, panel auto-update disabled.",
"At startup the binary logged xai_version.go:96 'failed to fetch latest Grok CLI version from npm' for https://registry.npmjs.org/@xai-official/grok/latest (network unreachable inside the namespace), then xai_version.go:79 'periodic Grok CLI version refresh started (interval=3h0m0s)'. It also logged antigravity_version.go:71 'periodic antigravity version refresh started (interval=3h0m0s)'. Evidence: origin/fethry/row332-p1 agents/fethry/work/queue-332/BUILD.md:251-252 and evidence/offline.txt.",
"On the live host these calls would leave the machine every 3 hours, which P1's loopback-only design doesn't account for. The proxy kept working with the fallback version, so the failure is harmless to requests.",
"Needed before or at P7 cutover, with Jason present: find whether 8.0.42 has a config switch for these refreshes; if so set it in P1's initial config with a test, otherwise decide deliberately to allow or block the egress (unit-level network policy) and record the choice in P7's receipt. Also recorded in docs/plans/DEFERRED.md. Umbrella: 237.",
]),
},
{
title: "Stack: library get lists the whole served tree per read (row 284 N1, Webby)",
description: ps(SIG, [
"Filed by Mos's ruling mos-1647 item 3. Webby's round 1 note N1 on row 284 (#1789, landed ce0b6ed41 on 2026-10-25), carried in c31654. Not a correctness issue.",
"Each read that resolves one file walks the whole served tree with listTree (git ls-tree -r -l) and then finds the one entry: packages/library/src/mirror.mjs:257 and packages/library/src/query.mjs:142, both via packages/library/src/reader.mjs:28. On a large library that is one full tree listing per read.",
"Fix options: git rev-parse <commit>:<path> for the one oid, or a per-commit listing cache. listTree also bounds and checks the tree and its object IDs, so a replacement must keep those checks.",
"Bound to the next row that edits the library read path: that row measures a get on a library of realistic size and records the choice in its BUILD.md. Also recorded in docs/plans/DEFERRED.md.",
]),
},
];
const key = readFileSync(KEY, "utf8").trim(), sync = readFileSync(SYNC, "utf8").trim();
async function api(method, path, body, auth) {
const r = await fetch(ORIGIN + path, { method, headers: { Authorization: `Bearer ${auth}`, "Content-Type": "application/json" }, body: body === undefined ? undefined : JSON.stringify(body), redirect: "error" });
const t = await r.text(); let json = null; try { json = JSON.parse(t); } catch {}
return { status: r.status, json };
}
const list = (j) => j?.items ?? (Array.isArray(j) ? j : []);
async function existing() {
const out = [];
for (let page = 1; page < 20; page++) {
const r = await api("GET", `/api/v2/projects/${PROJECT}/tasks?per_page=50&page=${page}`, undefined, sync);
if (r.status !== 200) throw new Error(`list tasks: ${r.status}`);
out.push(...list(r.json));
if (list(r.json).length < 50) return out;
}
throw new Error("more than 19 pages");
}
const rec = { at: new Date().toISOString(), project: PROJECT, created: null, problems: [] };
const save = () => {
const out = JSON.stringify(rec, null, 1) + "\n";
if (out.includes(key) || out.includes(sync)) throw new Error("secret in the record; not written");
writeFileSync(OUT, out);
};
const have = await existing();
for (const T of TASKS) if (have.some((t) => t.title === T.title)) throw new Error("title exists; refusing");
writeFileSync(OUT, "", { flag: "wx" });
rec.created = [];
for (const T of TASKS) {
const r = await api("PUT", `/api/v1/projects/${PROJECT}/tasks`, { title: T.title, description: T.description }, key);
const c = { status: r.status, id: r.json?.id ?? null };
rec.created.push(c);
if (r.status >= 300 || !Number.isSafeInteger(r.json?.id)) { rec.problems.push(`create: ${r.status} ${r.json?.message ?? ""}`); continue; }
const back = await api("GET", `/api/v2/tasks/${r.json.id}`, undefined, sync);
Object.assign(c, { readBack: back.status, done: back.json?.done });
if (back.status !== 200 || back.json?.title !== T.title || back.json?.done) rec.problems.push(`read-back differs for ${r.json.id}`);
}
save();
console.log(JSON.stringify(rec));
@@ -0,0 +1,19 @@
{
"at": "2026-10-25T00:18:17.480Z",
"project": 19,
"created": [
{
"status": 201,
"id": 633,
"readBack": 200,
"done": false
},
{
"status": 201,
"id": 634,
"readBack": 200,
"done": false
}
],
"problems": []
}
+1 -24
View File
@@ -1693,27 +1693,4 @@ are never rewritten or removed; corrections are new entries.
2026-10-24 | magica | row329 round2 #1827 | In-progress rev4031; B1 ASCII-only key fix/new inventory tests and N1/N3/N4 docs, cleared reader verification running, old tests byte-identical.
2026-10-24 | magica | row329 R2 #1827 | ASCII management-key fix and docs verified: package66/66,bus readers261/261,CLI readers726/726,config55/55; no required failures/skips, slot returned. Preparing authorized ff review candidate; old tests unchanged.
2026-10-24 | Sage 1ef1e4f8 | row329 landing #1827 (mos-1634) | Gate GREEN 23:29:14Z unchanged, landed 61ebf2c34 pushed 23:31:27Z; #1827 closed c31650; queue note 4063, done 4064 (b24d917ec); DEFERRED N2/R2-N1 to 331, N1 to P7; Vikunja 631 filed, 237 c1109; 284 and 157 must rebase.
2026-10-24 | fethry (65673bd9-3bfa-412b-85d5-9b364187d8b6) | row332 P3 proxy harness configuration at c8a9bcf94 | Started recovery and design; npm ci in isolated worktree; tests held for Sage CLEAR; no live proxy or credentials accessed.
2026-10-24 | fethry (65673bd9-3bfa-412b-85d5-9b364187d8b6) | row332 crash stop (mos-1630) | Documentation-only handoff on fethry/row332; four unrun test files and import audit script left uncommitted; no tests/probes/production edits; no jobs restarted or other threads messaged.
2026-10-24 | fethry (65673bd9-3bfa-412b-85d5-9b364187d8b6) | row332 resume sage-4298 | Added unrun launcher persistence test and third mutant; regenerated import audit and delivered full inline report to Sage; no tests, probes, fetches or production edits; CLEAR and after-none notice pending.
2026-10-24 | fethry (65673bd9-3bfa-412b-85d5-9b364187d8b6) | row332 start sage-4301 | Canonical fethry-332-start succeeded rev4059 briefed→in-progress; no tests/probes/fetches pending CLEAR.
2026-10-24 | fethry (65673bd9-3bfa-412b-85d5-9b364187d8b6) | row332 P1 rebase/reader pre-step | Rebased to 9e2689dff, HEAD efe3e4697; uncommitted tests restored; P3 imports P1 broker through cli test helpers, stopped/reported under sage-4313 step1 before execution.
2026-10-24 | fethry (65673bd9-3bfa-412b-85d5-9b364187d8b6) | row332 first RED lane B | Ran four new files+whole launcher, all34 old launcher tests pass; two new fixture errors; fixes b285e581e then one rerun each: plugin valid RED1/4, bundle further fixture error0/5; reported/stopped, no mutants/probes/fetches, no test process leftovers.
2026-10-24 | fethry (65673bd9-3bfa-412b-85d5-9b364187d8b6) | row332 corrected bundle RED sage-4320 | Fixture-only56701f715 atop b285e581e; whole bundle0pass/5fail/0skip at23:44:40Z, all missing models.json generation; lane B returned, no production edits/mutants/probes/fetches.
2026-10-24 | fethry (65673bd9-3bfa-412b-85d5-9b364187d8b6) | row332 P3 implementation sage-4323/4325 | Production edits and authorized old fixtures written; optional route default Anthropic; GPT wire PENDING; no runs/probes/fetches, preparing pushed unverified checkpoint and import list.
2026-10-24 | fethry (65673bd9-3bfa-412b-85d5-9b364187d8b6) | row332 six-file run sage-4326 | business6/0,seat2/0,proxy-harness5/0,harness9/0,bundle1/5(PENDING),launcher34/1(old fallback lacks own pi key),zero skips; no reruns/behavior fixes, reported old RED before edit; title-only correction authorized, lane B free23:57:42Z,no test leftovers.
2026-10-24 | fethry (65673bd9-3bfa-412b-85d5-9b364187d8b6) | row332 fixture verification sage-4327 | f1e8cda07 bundle6/1(PENDING)/0skip,launcher35/0/0skip; no other failures, old fallback fixed in test only; lane B free23:59:45Z,no test leftovers.
2026-10-24 | fethry (65673bd9-3bfa-412b-85d5-9b364187d8b6) | row332 route required sage-4328 |9563fbc8b proxy-launch6/0,launch-settings18/0,bundle6/1(expected GPT PENDING),launcher35/0,zero skips; grep positive controls/old assertion preservation recorded; lane B free00:02:27Z UTC10-25,no test leftovers,no probes/fetches/mutants.
2026-10-24 | fethry (65673bd9-3bfa-412b-85d5-9b364187d8b6) | row332 pinned offline evidence sage-4329/4330 | One verified fetch; first setup0turns wrong provider shape; statically diagnosed bundled panel schema then one corrected isolated attempt: both GPT shapes+GLM exit0/marker,thinking retained,tool_stream untested(no tools); GPT choice inconclusive/PENDING,no real auth; process cleanup0,lane B free.
2026-10-24 | fethry (65673bd9-3bfa-412b-85d5-9b364187d8b6) | row332 sage-4331 API choice and GLM tool field | ef0939e35 responses constant per lead reasoning tie-break;rehash/no-fetch isolated GLM one turn0/tool_stream retained;bundle7/0/0skip,proxy-harness5/0/0skip;lane B free00:14:20Z UTC10-25,no test leftovers;wait row331 before further work.
2026-10-25 | Sage 1ef1e4f8 | row284 landing #1789 | Gate GREEN 00:09:04Z unchanged, landed ce0b6ed41 pushed 00:09:52Z; #1789 closed c31655; queue note 4071, done 4072 (7c8dc2033); DEFERRED Webby N1 to the next library read-path row; row 332 PROXY_CODEX_API ruled openai-responses (sage-4331), P3 holds for row 331.
+24
View File
@@ -796,3 +796,27 @@ Sage, for Dewey's round 1 N1 on row 329 (c31639). The acceptance netns had only
but never saw the real binary refuse a non-loopback client.
Bound to P7: at cutover, with Jason present, confirm the listener is on 127.0.0.1 only (`ss -ltnp`), and
record it in P7's receipt.
## Row 284 N1: library.get lists the whole served tree per read
Sage, for Webby's round 1 N1 on row 284 (c31654 carries it forward). Each library get runs `listTree`
(`git ls-tree -r -l`) over the whole served tree to find one blob oid. On a large library that is one full
tree listing per read. `git rev-parse <commit>:<path>`, or a per-commit cache, would avoid it. Not a
correctness issue. Bound to the next row that edits the library read path; that row measures a get on a
library of realistic size and records the choice in its BUILD.md.
## Row 284 N1: Vikunja task
Sage, for mos-1647 item 3 (Q109). The row 284 N1 entry above is tracked as Vikunja 634. No open task
covered the library read path.
## Row 332 finding: CLIProxyAPI startup version refreshes reach outside the host
Sage, for Fethry's row 332 isolated runs (2026-10-24, pinned 8.0.42, `unshare -rn` with only `lo`). At
startup the binary tried `https://registry.npmjs.org/@xai-official/grok/latest` (xai_version.go:96, blocked
by the namespace) and then started a 3-hour Grok CLI version refresh and a 3-hour antigravity version
refresh. The proxy kept serving with its fallback version. Evidence: origin/fethry/row332-p1
`agents/fethry/work/queue-332/BUILD.md`:251-252 and `evidence/offline.txt`. Bound to P7: before or at
cutover, find a config switch that turns these off and set it in P1's initial config with a test, or
decide on purpose to allow or block that egress and record it in P7's receipt. Tracked as Vikunja 633
(umbrella 237).
+2 -2
View File
@@ -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 4064 by `queue render`. Do not edit between the markers; change the queue with `scripts/mosaic queue`.
Generated from `docs/plans/queue.json` revision 4072 by `queue render`. Do not edit between the markers; change the queue with `scripts/mosaic queue`.
| # | Piece | Owner | Issues | State | After | Gate | Brief | Note |
|---|---|---|---|---|---|---|---|---|
@@ -320,7 +320,7 @@ Generated from `docs/plans/queue.json` revision 4064 by `queue render`. Do not e
| 281 | A fire or a delete revokes the instance's host and Gitea grants (194/236 follow-up, MVP, mos-1271) | megavolt; reviewers dewey | #1786 | done | 236 done | Dewey approves the design, then the manifest. Bus, business, cli and every touched test file run whole, plus the Docker gitea-grant test and every scripts/test-*.sh, green on Sage's gate. M1-M4 killed. Lands before .53 Case 1 hires a granted instance. Red goes to Sage, then Mos. (sage) | `docs/plans/2026-10-22_fire-revokes-grants.md` § Brief: no grant outlives its instance | LANDED e479521d3 ff on 385a7194c (17 commits, manifest b73d4c81). Slot on 7979fb41e green: bus 819, business 231, cli 837, dewey-bus 76 with gitea-grant-docker run, shells green under 3x limits, M1-M22 killed. M1 hang fixed in b4a (mos-1273). Skips: test-task row 244 live-provider pair, test-queue canonical root. DEFERRED: N1 host-unknown hint verb, N2 fire tool text, to the follow-up row. Dewey APPROVE c30614. |
| 282 | PRD REQ-LIB-6 rewritten to Q223 and Q226 (mos-1320 item 8) | gosalyn; reviewers webby | #1787 | done | — | Webby approves against the ruling. requirements.test.mjs and every scripts/test-*.sh that reads the PRD or requirements.json are green on Sage's gate. Jason gets a report. (sage) | `docs/plans/2026-10-20_case2-rows.md` § PRD REQ-LIB-6 rewritten to Q223 and Q226 (mos-1320 item 8) | Landed 647424442 on 86a665bdf: 1841f7d4e and 6b5b06819 rebased, patch-ids equal (4e50b4b6, 16a7a02f), range-diff =, tree 4f30ed10a = Gosalyn's gated trial tree. Webby APPROVE rev 3308 c30764 on 6b5b06819. Gate 19:06Z on the tip tree: bus+tasks requirements and tasks verbs 37/0/0, 0 skips; no scripts/test-*.sh reads the PRD (control ok). PRD 1.15. 1.16 is row 291, waits for Jason. |
| 283 | Case 2 C2-01d supporting folders, the supporting scope, the editor field and supportingPath (M12) | honker; reviewers webby | #1788 | done | 268 done, 282 done | Webby approves the manifest. The library and business suites are green on Sage's gate, along with every scripts/test-*.sh. (sage) | `docs/plans/2026-10-20_case2-rows.md` § C2-01d supporting folders, the supporting scope, the editor field and supportingPath (M12) | LANDED 8d2856ee3 (replay of 0bf308dba onto 59226f878, 13 patch-ids equal) plus DEFERRED N1 93694c518. Webby APPROVE r1 c31338 rev 3677, r2 c31342 rev 3683 (mos-1528 G1 mapping.test:52). Sage full gate GREEN 20:37:16Z: all package suites but queue plus every scripts/test-*.sh, 0 fail, library 98/0, webui npm ci, editor build required. supporting.test first-run red placed (mos-1272, 54d9e07bb). #1788 closed c31358. Live unchanged 45dca69f6. |
| 284 | Case 2 C2-05c the supporting scope and blob in the lookups | della; reviewers webby | #1789 | in-review, round 1, request posted | 224 done, 283 done | Dewey approves the manifest. Library, bus and harness suites and every scripts/test-*.sh green on Sage's gate. Grep packages/*/tests for the scope enum pin and ['canon', 'playground'] before in-review; update each. (sage) | `docs/plans/2026-10-20_case2-rows.md` § C2-05c the supporting scope and blob in the lookups (sage-2833) | — |
| 284 | Case 2 C2-05c the supporting scope and blob in the lookups | della; reviewers webby | #1789 | done | 224 done, 283 done | Dewey approves the manifest. Library, bus and harness suites and every scripts/test-*.sh green on Sage's gate. Grep packages/*/tests for the scope enum pin and ['canon', 'playground'] before in-review; update each. (sage) | `docs/plans/2026-10-20_case2-rows.md` § C2-05c the supporting scope and blob in the lookups (sage-2833) | LANDED ce0b6ed41 (fast-forward of Della r4 on 9e2689dff), pushed 00:09:52Z 10-25. Sage gate GREEN 00:09:04Z on ce0b6ed41: every package suite but queue (cli 999/0 + allowed FED R7 skip) and every scripts/test-*.sh rc 0. Webby APPROVE r2 c31654 rev 4070 on manifest-r4 de505cfd; landed tree matches. Della whole-file runs 51/0. #1789 closed with c31655. |
| 285 | Case 2 C2-08b role changes for agent writes and the chief's read grant | magica; reviewers poe, webby | #1790 | done | 213 done, 291 done | Webby approves the manifest. Business suite, test-config.sh and every scripts/test-*.sh green on Sage's gate. Grep for CREATIVE_KINDS and 64-hex pins of changed role files. Sage checks it against mos-1309 item 5. (sage) | `docs/plans/2026-10-20_case2-rows.md` § C2-08b role changes for agent writes and the chief's read grant (mos-1309 item 5) | LANDED 1f3d0350f 13:33:42Z: candidate 2e4503dc7 (14 commits) cherry-picked onto 25874bc86. Logs kept both sides; otherwise the tree equals the candidate except on 7 base paths. Poe c31568 rev 3919, Webby c31569 rev 3920. Sage gate GREEN 13:28:46Z with its own npm ci: 4236 package tests, 0 fail, 1 allowed FED R7 skip; 12 scripts rc 0. No CREATIVE_KINDS, no role-file hash pins. Roles match mos-1309 item 5. 286 rebases as r5. |
| 286 | Case 2 C2-03b push and per-seat credentials for the library mirror (with R4, mos-1323) | rockerduck; reviewers boyd, dewey | #1791 | done | 222 done | Dewey approves the manifest. Library and bus suites and every scripts/test-*.sh green on Sage's gate, mutant killed. A search of the run output for the fixture token finds nothing. (sage) | `docs/plans/2026-10-20_case2-rows.md` § C2-03b push and per-seat credentials for the library mirror | LANDED 5d7801dc1 14:37:02Z: r6 75f6d56b1 (19 commits) picked onto d55944edb; logs kept both sides, code equals the candidate. Boyd c31587 rev 3942, Dewey c31588 rev 3943 (r2 c31584/c31585). Sage gate GREEN 14:36:42Z, own npm ci: 4251 tests, 0 fail, 1 allowed FED R7 skip; 12 scripts rc 0; fixture values in 0 of 29 outputs; B285-M1 kills T7/T9. r6 shortened two fixtures after push-check STOP secrets (sage-4112). Chief seed per sage-4100. |
| 287 | Case 2 C2-21 the grant executor for a library project | steelbeak; reviewers boyd, dewey | #1792 | done | 226 done, 285 done | Dewey approves the manifest. Bus suite, Gitea Docker test, install test and every scripts/test-*.sh green on Sage's gate. A search of the run output for the fixture admin and seat tokens finds nothing. (sage) | `docs/plans/2026-10-20_case2-rows.md` § C2-21 the grant executor for a library project | LANDED 0e935776e 16:12:35Z 10-24 (cand c2338ed58 + a5370b198 on 9b6345466). Boyd APPROVE c31602 rev 3967, Dewey APPROVE c31603 rev 3968. Sage gate GREEN 16:11:38Z: bus 998/0 (Gitea Docker F-A/F-B + X-G3, minted 4 hits 0), business 283/0, cli 989 +1 allowed FED R7 skip, webui 442/0, 12 scripts rc 0. F-C negative record-only follow-up. Dewey N1-N3 non-blocking. #1792 closed c31606. No P19 task. |
+248 -9
View File
@@ -1,7 +1,7 @@
{
"version": 1,
"canonicalRoot": "/mnt/storage/src/mosaic-stack",
"revision": 4064,
"revision": 4072,
"rows": [
{
"id": 1,
@@ -30162,7 +30162,7 @@
"closes": [
1789
],
"state": "in-review",
"state": "done",
"previousState": null,
"required": false,
"requiredSince": null,
@@ -30241,18 +30241,69 @@
"candidate": "c403f7e3e4496c8eabfe29cce00582267c6dc5a5140b74fcb4ba4c2ec031ca65"
}
]
},
{
"n": 2,
"op": "della-284-r2-review",
"by": "della",
"at": "2026-10-24T23:43:28.297Z",
"issue": 1789,
"candidate": {
"kind": "manifest",
"digest": "de505cfd18c82f66ff6cc5faf00789e81c66d148e07e1972c5d664031ee0f727",
"text": "0cf1506f848cc1734e34625f101b60561ecdc8505e33b6a9d16e430b3cb2f68e agents/della/work/queue-284/BUILD.md\n591a412ed4243288da29c406269ff089a58bbcfcb0a2a0b3536b87bfa2e89eab packages/bus/src/broker.mjs\n9b974b53c7fde08b795e1a26c75ad1e6dd664fda72b79a656900ec96f1603d03 packages/bus/tests/library-lookups.test.mjs\n145ede2d2f5c9c776cc2a6eb5f48975e96b09e78c495401d5aaae435974496a4 packages/harness/src/tools.mjs\n21e78b4424ae0e8337aaf548e880abf297407301cb0ae41711bd794e99344276 packages/harness/tests/library-tools.test.mjs\nbafe113bee70f17bd249876d6bdd1c08fa051223c2111955e5d5f275bd76bba0 packages/library/src/query.mjs\n766b80f53f4565588ac48bd613f6099b1f7ca1c933994779fe6c6cb9eae23a29 packages/library/tests/query-fixture.mjs\nd99111d1a4f7ca42881ba699cbc55d2dad12f6c75e7b8e1bac44f05c7df56dec packages/library/tests/query.test.mjs\n"
},
"request": "comment",
"attempts": [
{
"op": "della-284-r2-review",
"by": "della",
"at": "2026-10-24T23:43:28.297Z",
"state": "failed",
"comment": null,
"transport": {
"outcome": "failed",
"status": null,
"comment": null,
"detail": "pre-send: the credential or account check failed"
},
"resolutions": []
},
{
"op": "sage-284-r2-request",
"by": "sage",
"at": "2026-10-24T23:46:18.731Z",
"state": "posted",
"comment": 31653,
"transport": {
"outcome": "posted",
"status": 201,
"comment": 31653,
"detail": "created"
},
"resolutions": []
}
],
"duplicateRisk": false,
"receipts": [
{
"reviewer": "webby",
"op": "webby-284-verdict-r2",
"at": "2026-10-24T23:48:52.791Z",
"verdict": "approve",
"comment": 31654,
"candidate": "de505cfd18c82f66ff6cc5faf00789e81c66d148e07e1972c5d664031ee0f727"
}
]
}
]
},
"claim": {
"seat": "della",
"op": "della-284-start-1"
},
"note": null,
"claim": null,
"note": "LANDED ce0b6ed41 (fast-forward of Della r4 on 9e2689dff), pushed 00:09:52Z 10-25. Sage gate GREEN 00:09:04Z on ce0b6ed41: every package suite but queue (cli 999/0 + allowed FED R7 skip) and every scripts/test-*.sh rc 0. Webby APPROVE r2 c31654 rev 4070 on manifest-r4 de505cfd; landed tree matches. Della whole-file runs 51/0. #1789 closed with c31655.",
"blockedReason": null,
"createdAt": "2026-10-22T18:28:04.590Z",
"updatedAt": "2026-10-24T23:25:20.620Z",
"updatedBy": "webby"
"updatedAt": "2026-10-25T00:12:13.878Z",
"updatedBy": "sage"
},
{
"id": 285,
@@ -140751,6 +140802,194 @@
"receipt": "ok sage-329-done-landed rev 4064 row 329 in-review→done round 2"
},
"viewSha": "cf64a27b66b579121eb5f4dba03d2b4a3e88ff1aedd95ffe2c3d713591edf8b4"
},
{
"rev": 4065,
"op": "della-284-r2-reopen",
"verb": "move",
"args": {
"id": 284,
"to": "in-progress",
"reason": null,
"candidate": null,
"evidence": null,
"issue": null
},
"by": "della",
"at": "2026-10-24T23:42:25.130Z",
"semantics": 2,
"result": {
"row": 284,
"from": "in-review",
"to": "in-progress",
"round": null,
"issue": null,
"candidate": null,
"receipt": "ok della-284-r2-reopen rev 4065 row 284 in-review→in-progress"
},
"viewSha": "1ca33a4b5b66adffafabf5096cc182b7dd13cd71cdab6186fba9a0d3974ead96"
},
{
"rev": 4066,
"op": "della-284-r2-review",
"verb": "move",
"args": {
"id": 284,
"to": "in-review",
"reason": null,
"candidate": "/mnt/storage/scratch/della-row284-r2-evidence/manifest-r4.txt",
"evidence": null,
"issue": null
},
"by": "della",
"at": "2026-10-24T23:43:28.297Z",
"semantics": 2,
"result": {
"row": 284,
"from": "in-progress",
"to": "in-review",
"round": 2,
"issue": 1789,
"candidate": {
"kind": "manifest",
"digest": "de505cfd18c82f66ff6cc5faf00789e81c66d148e07e1972c5d664031ee0f727",
"text": "0cf1506f848cc1734e34625f101b60561ecdc8505e33b6a9d16e430b3cb2f68e agents/della/work/queue-284/BUILD.md\n591a412ed4243288da29c406269ff089a58bbcfcb0a2a0b3536b87bfa2e89eab packages/bus/src/broker.mjs\n9b974b53c7fde08b795e1a26c75ad1e6dd664fda72b79a656900ec96f1603d03 packages/bus/tests/library-lookups.test.mjs\n145ede2d2f5c9c776cc2a6eb5f48975e96b09e78c495401d5aaae435974496a4 packages/harness/src/tools.mjs\n21e78b4424ae0e8337aaf548e880abf297407301cb0ae41711bd794e99344276 packages/harness/tests/library-tools.test.mjs\nbafe113bee70f17bd249876d6bdd1c08fa051223c2111955e5d5f275bd76bba0 packages/library/src/query.mjs\n766b80f53f4565588ac48bd613f6099b1f7ca1c933994779fe6c6cb9eae23a29 packages/library/tests/query-fixture.mjs\nd99111d1a4f7ca42881ba699cbc55d2dad12f6c75e7b8e1bac44f05c7df56dec packages/library/tests/query.test.mjs\n"
},
"receipt": "ok della-284-r2-review rev 4066 row 284 in-progress→in-review round 2 on #1789; request della-284-r2-review requesting"
},
"viewSha": "06c4188500095cb6d4a33ed66cf0ca641c422791578fd716de241899f8e6cd9a"
},
{
"rev": 4067,
"op": "della-284-r2-review.outcome",
"verb": "review-outcome",
"args": {
"id": 284,
"attempt": "della-284-r2-review",
"outcome": "failed",
"status": null,
"comment": null,
"detail": "pre-send: the credential or account check failed"
},
"by": "della",
"at": "2026-10-24T23:44:28.236Z",
"semantics": 2,
"result": {
"row": 284,
"round": 2,
"attempt": "della-284-r2-review",
"state": "failed",
"receipt": "ok della-284-r2-review.outcome rev 4067 row 284 round 2 request della-284-r2-review failed"
},
"viewSha": "c5746412794db34382b1445e1cf6653bd9bc5d18ced39eb7530f3d8b85f9dc71"
},
{
"rev": 4068,
"op": "sage-284-r2-request",
"verb": "review-request",
"args": {
"id": 284
},
"by": "sage",
"at": "2026-10-24T23:46:18.731Z",
"semantics": 2,
"result": {
"row": 284,
"round": 2,
"attempt": "sage-284-r2-request",
"state": "requesting",
"receipt": "ok sage-284-r2-request rev 4068 row 284 round 2 request sage-284-r2-request requesting"
},
"viewSha": "d88a0b75a5e83fc52e67f38060a10beb206122bd3c7b4c8f6e5abc59ec5db2cd"
},
{
"rev": 4069,
"op": "sage-284-r2-request.outcome",
"verb": "review-outcome",
"args": {
"id": 284,
"attempt": "sage-284-r2-request",
"outcome": "posted",
"status": 201,
"comment": 31653,
"detail": "created"
},
"by": "sage",
"at": "2026-10-24T23:47:19.540Z",
"semantics": 2,
"result": {
"row": 284,
"round": 2,
"attempt": "sage-284-r2-request",
"state": "posted",
"receipt": "ok sage-284-r2-request.outcome rev 4069 row 284 round 2 request sage-284-r2-request posted comment 31653"
},
"viewSha": "afadc7eb51a8de8bc7ea9e231718958e058ad4b34f355396d589e5b90d994ab0"
},
{
"rev": 4070,
"op": "webby-284-verdict-r2",
"verb": "review-record",
"args": {
"id": 284,
"verdict": "approve",
"comment": 31654,
"candidate": "de505cfd18c82f66ff6cc5faf00789e81c66d148e07e1972c5d664031ee0f727"
},
"by": "webby",
"at": "2026-10-24T23:48:52.791Z",
"semantics": 2,
"result": {
"row": 284,
"round": 2,
"verdict": "approve",
"receipt": "ok webby-284-verdict-r2 rev 4070 row 284 round 2 approve by webby (comment 31654)"
},
"viewSha": "fc73cc2acac68aad3f22e65bd531f278572839f3134073aafd3cbf1e495411a3"
},
{
"rev": 4071,
"op": "sage-284-note-landed",
"verb": "note",
"args": {
"id": 284,
"text": "LANDED ce0b6ed41 (fast-forward of Della r4 on 9e2689dff), pushed 00:09:52Z 10-25. Sage gate GREEN 00:09:04Z on ce0b6ed41: every package suite but queue (cli 999/0 + allowed FED R7 skip) and every scripts/test-*.sh rc 0. Webby APPROVE r2 c31654 rev 4070 on manifest-r4 de505cfd; landed tree matches. Della whole-file runs 51/0. #1789 closed with c31655."
},
"by": "sage",
"at": "2026-10-25T00:11:07.895Z",
"semantics": 2,
"result": {
"row": 284,
"field": "note",
"receipt": "ok sage-284-note-landed rev 4071 row 284 note"
},
"viewSha": "c02f6437f45a2ef9181cd3b05d90b331d0468534a294200a55e38dcc316d3ac9"
},
{
"rev": 4072,
"op": "sage-284-done-landed",
"verb": "move",
"args": {
"id": 284,
"to": "done",
"reason": null,
"candidate": null,
"evidence": null,
"issue": null
},
"by": "sage",
"at": "2026-10-25T00:12:13.878Z",
"semantics": 2,
"result": {
"row": 284,
"from": "in-review",
"to": "done",
"round": 2,
"issue": null,
"candidate": null,
"receipt": "ok sage-284-done-landed rev 4072 row 284 in-review→done round 2"
},
"viewSha": "546679f234a78b2d4582ed5a50b90c7427bf82cf2bd75243eeccad1f5730fa79"
}
]
}
+1 -1
View File
@@ -105,7 +105,7 @@ export const PROJECT_FILE_VERBS = Object.freeze(['project.files', 'project.file'
// here also makes server.mjs await their host effects instead of serializing a Promise as {}.
const LIBRARY_LOOKUPS = Object.freeze({
'library.find': { method: 'find', fields: ['universe', 'query', 'type', 'book', 'scope', 'offset'], required: ['universe', 'query'] },
'library.get': { method: 'get', fields: ['universe', 'path', 'from', 'links_from'], required: ['universe', 'path'] },
'library.get': { method: 'get', fields: ['universe', 'path', 'scope', 'from', 'links_from'], required: ['universe', 'path'] },
'library.search': { method: 'search', fields: ['universe', 'text', 'book', 'scope', 'offset'], required: ['universe', 'text'] },
'library.manuscript': { method: 'manuscript', fields: ['universe', 'book', 'scope', 'chapter', 'from', 'to'], required: ['universe', 'book'] },
'library.universe': { method: 'universeInfo', fields: ['universe'], required: ['universe'] },
+18 -2
View File
@@ -27,8 +27,8 @@ const TEXTS = {
'Second World/Characters/Elsewhere.md': note('character', 'Elsewhere', 'Other ferry.'),
};
async function world(t, { projects, adapter, claimed = true, now = () => NOW } = {}) {
const f = scratchRepo(t, TEXTS), dataRoot = join(f.root, 'data');
async function world(t, { projects, adapter, claimed = true, now = () => NOW, files = TEXTS } = {}) {
const f = scratchRepo(t, files), dataRoot = join(f.root, 'data');
mkdirSync(dataRoot);
const business = { id: 'acme', human: 'jason', vars: { 'bus.tester': true },
projects: projects ?? { books: mappingEntry() }, arbiters: { technical: 'coder', delivery: 'coder' },
@@ -235,3 +235,19 @@ test('runtime actually injects the lookup adapter, without exposing human librar
await assert.rejects(runtime.broker.request(cap, { verb: 'library.file', args: { project: 'books', path: GET.path } }),
{ code: 'human-required' });
});
test('C2-05c broker forwards supporting scope and returns the served blob without adding write verbs', async t => {
const projects = { books: mappingEntry() };
projects.books.universes.harbor.supporting = ['Book One/Support/'];
const path = 'Book One/Support/Helper.md';
const f = await world(t, { projects, files: { ...TEXTS, [path]: note('summary', 'Helper', 'Supporting fixture.') } });
assert.deepEqual((await f.call('library.find', { universe: 'harbor', query: '', scope: 'supporting' })).results.map(x => x.path), [path]);
assert.deepEqual((await f.call('library.search', { universe: 'harbor', text: 'Supporting fixture', scope: 'supporting' })).results.map(x => x.path), [path]);
assert.equal(await f.call('library.get', { universe: 'harbor', path }), null);
const result = await f.call('library.get', { universe: 'harbor', path, scope: 'supporting' });
assert.equal(result.scope, 'supporting');
assert.equal(result.commit, f.commit);
assert.equal(result.blob, git(f.mirror, 'rev-parse', `${f.commit}:${path}`));
assert.equal(await f.call('library.get', { universe: 'second', path, scope: 'supporting' }), null);
await assert.rejects(f.call('library.manuscript', { universe: 'harbor', book: 'Book One', scope: 'supporting' }), { code: 'query-argument-invalid' });
});
+3 -12
View File
@@ -1,6 +1,6 @@
// REQ-LIMIT-1: editable concurrency policy, never a compiled-in capacity ceiling.
import { requireObject, requireId, requireString, rejectUnknownKeys } from "./util.mjs";
import { BusinessError, refuse } from "./errors.mjs";
import { refuse } from "./errors.mjs";
const name = (value, at) => requireString(value, at, { max: 200 });
const count = (value, at) => {
@@ -15,19 +15,10 @@ export function checkModels(value, where = "launch.models") {
return Object.fromEntries(Object.entries(value).map(([key, entry]) => {
requireId(key, where);
requireObject(entry, `${where}.${key}`);
rejectUnknownKeys(entry, entry.provider === "proxy" ? ["provider", "model", "route"] : ["provider", "model"], `${where}.${key}`);
if (entry.provider === "proxy") {
const missing = !Object.hasOwn(entry, "route");
if (missing || !["anthropic", "glm", "codex"].includes(entry.route)) {
throw Object.assign(new BusinessError(`${where}.${key}.route must name anthropic, glm or codex`), {
code: missing ? "proxy-route-missing" : "proxy-route-unknown",
});
}
}
rejectUnknownKeys(entry, ["provider", "model"], `${where}.${key}`);
return [key, {
provider: name(entry.provider, `${where}.${key}.provider`),
model: name(entry.model, `${where}.${key}.model`),
...(entry.provider === "proxy" && Object.hasOwn(entry, "route") ? { route: entry.route } : {}),
}];
}));
}
@@ -91,7 +82,7 @@ export function checkAccount(value, where = "launch.account") {
requireObject(value, where);
rejectUnknownKeys(value, ["name", "credential"], where);
const accountName = requireId(value.name, `${where}.name`);
if (typeof value.credential !== "string" || (value.credential !== "proxy" && !CREDENTIAL.test(value.credential))) {
if (typeof value.credential !== "string" || !CREDENTIAL.test(value.credential)) {
refuse(`${where}.credential must name environment variables, joined with "+"`);
}
return { name: accountName, credential: value.credential };
@@ -38,11 +38,11 @@ test('REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery
test('REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent',async()=>{
const {migrateLaunch}=await import('../src/migrate-launch.mjs');const f=fixture(),old=structuredClone(f.doc);old.roles.pm.vars.model='claude-opus-5-5';for(const [name,r] of Object.entries(old.roles))if(name!=='pm')r.vars.model='claude-sonnet-5-5';old.launch={by:'chief',instances:['coder','reviewer'],max:{opus:4,sonnet:4}};writeJson(f.file,old);const bytes=readFileSync(f.file,'utf8'),mtime=statSync(f.file).mtimeMs;
const mapping={models:f.doc.launch.models,families:{opus:'opus',sonnet:'sonnet'}};const next=migrateLaunch(old,mapping,f.file,{rolesDir:f.rolesDir});assert.deepEqual(next.launch.limits, f.doc.launch.limits);assert.equal(next.roles.pm.vars.model,'opus');assert.equal(next.roles.coder.vars.model,'sonnet');assert.deepEqual(migrateLaunch(next,mapping,f.file,{rolesDir:f.rolesDir}),next);
assert.throws(()=>migrateLaunch(old,{...mapping,families:{opus:'missing',sonnet:'sonnet'}},f.file,{rolesDir:f.rolesDir}));assert.throws(()=>migrateLaunch(old,{...mapping,families:{opus:'opus',sonnet:'opus'}},f.file,{rolesDir:f.rolesDir}),/ambiguous/);assert.throws(()=>migrateLaunch(old,{...mapping,models:{...mapping.models,proxy:{provider:'proxy',route:'anthropic',model:'claude-opus-5-5'}},instances:{pm:'proxy'}},f.file,{rolesDir:f.rolesDir}),/ambiguous/);const onlyOpus=structuredClone(old);onlyOpus.launch.max={opus:4};assert.throws(()=>migrateLaunch(onlyOpus,mapping,f.file,{rolesDir:f.rolesDir}),/unknown or ambiguous/);const allOpus=structuredClone(old);for(const r of Object.values(allOpus.roles))r.vars.model='claude-opus-5-5';assert.throws(()=>migrateLaunch(allOpus,{...mapping,families:{opus:'opus',sonnet:'opus'}},f.file,{rolesDir:f.rolesDir}),/ambiguous/);assert.equal(readFileSync(f.file,'utf8'),bytes);assert.equal(statSync(f.file).mtimeMs,mtime);
assert.throws(()=>migrateLaunch(old,{...mapping,families:{opus:'missing',sonnet:'sonnet'}},f.file,{rolesDir:f.rolesDir}));assert.throws(()=>migrateLaunch(old,{...mapping,families:{opus:'opus',sonnet:'opus'}},f.file,{rolesDir:f.rolesDir}),/ambiguous/);assert.throws(()=>migrateLaunch(old,{...mapping,models:{...mapping.models,proxy:{provider:'proxy',model:'claude-opus-5-5'}},instances:{pm:'proxy'}},f.file,{rolesDir:f.rolesDir}),/ambiguous/);const onlyOpus=structuredClone(old);onlyOpus.launch.max={opus:4};assert.throws(()=>migrateLaunch(onlyOpus,mapping,f.file,{rolesDir:f.rolesDir}),/unknown or ambiguous/);const allOpus=structuredClone(old);for(const r of Object.values(allOpus.roles))r.vars.model='claude-opus-5-5';assert.throws(()=>migrateLaunch(allOpus,{...mapping,families:{opus:'opus',sonnet:'opus'}},f.file,{rolesDir:f.rolesDir}),/ambiguous/);assert.equal(readFileSync(f.file,'utf8'),bytes);assert.equal(statSync(f.file).mtimeMs,mtime);
});
test('REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor',async()=>{
const {launchSettings}=await import('../src/launch-settings.mjs');const f=fixture(),system={environment:'development',dataRoot:join(f.root,'data'),'execution.backend':'docker','execution.provider':'anthropic','execution.model':'sonnet','execution.adapter':'pi'};const settings=launchSettings({dir:f.root,rolesDir:f.rolesDir,system,sessions:()=>[{business:'acme',provider:'anthropic',model:'claude-opus-5-5'}]});const view=settings.read('acme');assert.equal(view.usage.total,1);assert.equal(view.instances.pm.modelKey,'opus');
const result=settings.set('acme',{revision:view.revision,limits:{total:0},instances:{coder:'opus'}},'jason');assert.equal(result.limits.total,0);assert.equal(result.instances.coder.modelKey,'opus');const models=structuredClone(result.models);models.opus.provider='proxy';models.opus.route='anthropic';const updated=settings.set('acme',{revision:result.revision,models},'jason');assert.equal(updated.instances.pm.provider,'proxy');assert.throws(()=>settings.set('acme',{revision:result.revision,instances:{coder:'ghost'}},'jason'));assert.throws(()=>settings.set('acme',{revision:result.revision,roles:{}},'jason'));
const result=settings.set('acme',{revision:view.revision,limits:{total:0},instances:{coder:'opus'}},'jason');assert.equal(result.limits.total,0);assert.equal(result.instances.coder.modelKey,'opus');const models=structuredClone(result.models);models.opus.provider='proxy';const updated=settings.set('acme',{revision:result.revision,models},'jason');assert.equal(updated.instances.pm.provider,'proxy');assert.throws(()=>settings.set('acme',{revision:result.revision,instances:{coder:'ghost'}},'jason'));assert.throws(()=>settings.set('acme',{revision:result.revision,roles:{}},'jason'));
});
test('REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts',async()=>{
const {limitHit}=await import('../src/launch.mjs');const {sessionModel}=await import('../../harness/src/bundle.mjs');
@@ -151,14 +151,14 @@ test('B7 kept instance: the models keys it names and the instances key are the h
const chief='chief-of-staff.chief';let {revision}=settings.read('acme');
const models=structuredClone(settings.read('acme').models);
const key=doc.roles.coder.vars.model;
const moved={...models,[key]:{provider:'proxy',route:'anthropic',model:'claude-sonnet-5-5'}};
const moved={...models,[key]:{provider:'proxy',model:'claude-sonnet-5-5'}};
for(const actor of [chief,'tester']){
const bytes=file();
assert.throws(()=>settings.set('acme',{revision,models:moved},actor),code('instance-kept'),actor);
assert.throws(()=>settings.set('acme',{revision,instances:{coder:'opus'}},actor),code('instance-kept'),actor);
assert.equal(file(),bytes,actor);
}
({revision}=settings.set('acme',{revision,models:{...models,spare:{provider:'proxy',route:'anthropic',model:'claude-opus-5-5'}}},chief));
({revision}=settings.set('acme',{revision,models:{...models,spare:{provider:'proxy',model:'claude-opus-5-5'}}},chief));
({revision}=settings.set('acme',{revision,models:{...settings.read('acme').models,[key]:moved[key]}},'jason'));
settings.set('acme',{revision,instances:{coder:'opus'}},'jason');
assert.equal(JSON.parse(file()).roles.coder.vars.model,'opus');
@@ -185,7 +185,7 @@ test('M10 creative instance: models keys it names, the instances key and its rou
const g={...f,doc};const {settings}=await routeSettings(g);const file=()=>readFileSync(f.file,'utf8');
const chief='chief-of-staff.chief';let {revision}=settings.read('acme');
const models=structuredClone(settings.read('acme').models);
const sonnet={...models,sonnet:{provider:'proxy',route:'anthropic',model:'claude-sonnet-5-5'}};
const sonnet={...models,sonnet:{provider:'proxy',model:'claude-sonnet-5-5'}};
for(const actor of [chief,'tester']){
const bytes=file();
assert.throws(()=>settings.set('acme',{revision,models:sonnet},actor),code('organization-creative-human-only'),actor);
@@ -195,7 +195,7 @@ test('M10 creative instance: models keys it names, the instances key and its rou
assert.equal(file(),bytes,actor);
}
// A key no creative instance names stays the chief's.
({revision}=settings.set('acme',{revision,models:{...models,opus:{provider:'proxy',route:'anthropic',model:'claude-opus-5-5'}}},chief));
({revision}=settings.set('acme',{revision,models:{...models,opus:{provider:'proxy',model:'claude-opus-5-5'}}},chief));
assert.throws(()=>settings.set('acme',{revision,instances:{bean:'opus'}},'jason'),code('organization-creative-instance'));
({revision}=settings.set('acme',{revision,models:sonnet},'jason'));
({revision}=settings.setRoutes('acme',{revision,routes:{bean:{harness:'pi',model:'sonnet',thinking:'high',fallback:{harness:'pi',model:'opus',thinking:'low'}}}},'jason'));
@@ -1,45 +0,0 @@
// P3: the proxy account is a declared credential source, never a secret value.
import test from 'node:test';
import assert from 'node:assert/strict';
import { checkAccount, checkModels } from '../src/launch.mjs';
test('P3 proxy model validation preserves each explicit wire route and the proxy model id', () => {
for (const route of ['anthropic', 'glm', 'codex']) {
const models = { selected: { provider: 'proxy', model: 'proxy-only-id', route } };
assert.deepEqual(checkModels(models), models, route);
}
});
test('P3 a proxy model without route refuses proxy-route-missing', () => {
assert.throws(() => checkModels({ selected: { provider: 'proxy', model: 'proxy-only-id' } }), {
code: 'proxy-route-missing',
});
});
test('P3 an unknown proxy route refuses proxy-route-unknown', () => {
for (const route of ['openai-codex', 'unknown', '', null, 7]) {
assert.throws(() => checkModels({ selected: { provider: 'proxy', model: 'proxy-only-id', route } }), {
code: 'proxy-route-unknown',
});
}
});
test('P3 nonproxy models retain their provider/model-only shape and reject route metadata', () => {
assert.deepEqual(checkModels({ selected: { provider: 'zai', model: 'glm-fixture' } }), {
selected: { provider: 'zai', model: 'glm-fixture' },
});
assert.throws(() => checkModels({ selected: { provider: 'zai', model: 'glm-fixture', route: 'glm' } }), /unsupported/);
});
test('P3 launch.account accepts the proxy credential source without naming host variables', () => {
assert.deepEqual(checkAccount({ name: 'proxy', credential: 'proxy' }), { name: 'proxy', credential: 'proxy' });
});
test('P3 existing environment-set accounts retain their validated representation', () => {
for (const credential of ['CLAUDE_CODE_OAUTH_TOKEN', 'ANTHROPIC_API_KEY', 'ANTHROPIC_AUTH_TOKEN+ANTHROPIC_BASE_URL']) {
assert.deepEqual(checkAccount({ name: 'max', credential }), { name: 'max', credential });
}
for (const credential of ['', 'fx332-fake', 'proxy+ANTHROPIC_API_KEY', 'PROXY+proxy']) {
assert.throws(() => checkAccount({ name: 'proxy', credential }), /launch\.account\.credential/);
}
});
+12 -41
View File
@@ -157,7 +157,6 @@ import {
runnerOf,
SESSION_CREDENTIALS,
sessionEnv,
isProviderVariable,
sessionExit,
sessionStore,
sessionWorkspace,
@@ -217,9 +216,6 @@ export function createLauncher({
host,
system,
env = process.env,
// P2 supplies only {baseUrl,key}; a factory may supply the current agent's
// context per check. P3 never reads a key store or calls the proxy itself.
proxy = null,
tracker = false,
launches = true,
makeLoader = createLoader,
@@ -392,18 +388,7 @@ export function createLauncher({
let harness = await harnessOf(primary);
let route = "primary";
let routeReason = null;
const proxyFor = async (selected) => {
if (selected.provider !== "proxy") return null;
const context = typeof proxy === "function" ? await proxy({ business: b.id, instance }) : proxy;
if (!context || typeof context.key !== "string" || !context.key
|| typeof context.baseUrl !== "string" || !/^http:\/\/127\.0\.0\.1:[0-9]+$/.test(context.baseUrl)) {
throw new Refusal("no-session-credential", "proxy model needs its own session proxy context");
}
// Copy only the agreed seam; never keep a store or management handle.
return { baseUrl: context.baseUrl, key: context.key };
};
let sessionProxy = await proxyFor(primary);
const failed = call(primary.harness, "preflight", () => harness.preflight({ env: sessionProxy ? sessionEnv(env, "preflight", sessionProxy) : env, proxy: sessionProxy }));
const failed = call(primary.harness, "preflight", () => harness.preflight({ env }));
if (failed) {
if (!fallback) throw new Refusal(failed.code, failed.message);
// The fallback only on a failed primary preflight, and only at launch (row 65). Any refusal of
@@ -412,8 +397,7 @@ export function createLauncher({
if (e instanceof Refusal) e.message += ` (primary ${primary.harness}: ${failed.message})`;
throw e;
});
sessionProxy = await proxyFor(fallback);
const also = call(fallback.harness, "preflight", () => second.preflight({ env: sessionProxy ? sessionEnv(env, "preflight", sessionProxy) : env, proxy: sessionProxy }));
const also = call(fallback.harness, "preflight", () => second.preflight({ env }));
if (also) throw new Refusal(also.code, `fallback ${fallback.harness}: ${also.message} (primary ${primary.harness}: ${failed.message})`);
[model, harness, route, routeReason] = [fallback, second, "fallback", failed.code];
}
@@ -424,18 +408,12 @@ export function createLauncher({
if (account !== null) {
// The usage records keep this name (bus schema 3i), so it must never be a credential's value.
const holds = [...new Set(SESSION_CREDENTIALS.flat())].filter((k) => env[k] === account);
if (sessionProxy?.key === account) holds.push("session proxy key");
if (holds.length) throw new Refusal("account-is-credential", `launch.account.name is the value of ${holds.join(", ")}; it names the account, never its credential`);
if (sessionProxy || b.launch.account.credential === "proxy") {
if (!sessionProxy || b.launch.account.credential !== "proxy")
throw new Refusal("account-credential-missing", `account ${account} needs the declared proxy credential`);
} else {
const named = b.launch.account.credential.split("+");
if (!SESSION_CREDENTIALS.some((set) => set.join("+") === named.join("+")) || !named.every((k) => Boolean(env[k])))
throw new Refusal("account-credential-missing", `account ${account} names ${named.join(" with ")}, which the bus host doesn't hold as a session login`);
const other = [...new Set(SESSION_CREDENTIALS.flat())].filter((k) => !named.includes(k) && Boolean(env[k]));
if (other.length) throw new Refusal("account-credential-ambiguous", `account ${account} names ${named.join(" with ")}, but the bus host also sets ${other.join(", ")}`);
}
const named = b.launch.account.credential.split("+");
if (!SESSION_CREDENTIALS.some((set) => set.join("+") === named.join("+")) || !named.every((k) => Boolean(env[k])))
throw new Refusal("account-credential-missing", `account ${account} names ${named.join(" with ")}, which the bus host doesn't hold as a session login`);
const other = [...new Set(SESSION_CREDENTIALS.flat())].filter((k) => !named.includes(k) && Boolean(env[k]));
if (other.length) throw new Refusal("account-credential-ambiguous", `account ${account} names ${named.join(" with ")}, but the bus host also sets ${other.join(", ")}`);
}
const unavailable = sandboxProblem({ bwrap });
if (unavailable) throw new Refusal("sandbox-unavailable", unavailable);
@@ -454,7 +432,7 @@ export function createLauncher({
throw new Refusal("limit-check-failed", `${may?.check ?? "bus"}: ${may?.code ?? "malformed-answer"}`);
}
admission(admissionGeneration);
return { resolved, model, account, harness, route, routeReason, admissionGeneration, sessionProxy };
return { resolved, model, account, harness, route, routeReason, admissionGeneration };
}
// Bundle, spawn, bind, register, hand over the capability.
@@ -525,8 +503,8 @@ export function createLauncher({
if (c.outcome === "kept") record({ event: "checkout-kept", instance, project: c.project, reason: c.reason });
else if (c.outcome === "fetched") record({ event: "checkout-fetched", instance, project: c.project, reason: c.reason });
}
let harness, route, routeReason, sessionProxy;
({resolved,model,account,harness,route,routeReason,sessionProxy}=await check(instance,{pm:instance===b.launch.by,thread,session,human}));
let harness, route, routeReason;
({resolved,model,account,harness,route,routeReason}=await check(instance,{pm:instance===b.launch.by,thread,session,human}));
admission(admissionGeneration);
const { run, runDir } = newRun(dataRoot, b.id);
const sessionDir = store ? store.session : join(runDir, "session");
@@ -547,7 +525,6 @@ export function createLauncher({
dir: join(runDir, "bundle"),
resolved,
models: b.launch.models,
proxy: sessionProxy,
contract: readFileSync(resolved.contract, "utf8"),
arbiter: Object.values(b.arbiters).includes(instance),
tracker,
@@ -571,12 +548,6 @@ export function createLauncher({
// Row 199 (D11): or publishes it, once a reviewed commit routes git.push.remote within-role.
const held = [...resolved.limits.authority.withinRole, ...resolved.limits.authority.crossRole];
const git = land || ["git.push.working", "review.verdict", "git.push.remote"].some((a) => held.includes(a)) ? gitSocketPath(dataRoot) : null;
// Secrets go only to spawn, never session.json. Keep this split at the
// actual serialization boundary, even if a harness adds another key.
const harnessEnv = {}, transientEnv = {};
for (const [name, value] of Object.entries(bundle.env)) {
(sessionProxy && isProviderVariable(name) ? transientEnv : harnessEnv)[name] = value;
}
writeSessionFile(runDir, {
...sessionDefaults,
business: b.id,
@@ -594,7 +565,7 @@ export function createLauncher({
sessionDir,
adapter,
bundle: files,
harnessEnv,
harnessEnv: bundle.env,
turnEnd,
toolSocket,
turnMarker,
@@ -618,7 +589,7 @@ export function createLauncher({
try {
admission(admissionGeneration);
spawnedAt.set(run, Date.now());
child = spawnSession({ runDir, env: { ...sessionEnv(env, run, sessionProxy), ...transientEnv }, paths, business: b.id, role: instance, bwrap });
child = spawnSession({ runDir, env: sessionEnv(env, run), paths, business: b.id, role: instance, bwrap });
} catch (e) {
spawnedAt.delete(run);
unregisterRuntime(dataRoot, managed.id);
+4 -31
View File
@@ -82,8 +82,6 @@ function prepare(t, more = (doc) => doc) {
const f = fixture(root, "acme", (doc) => more(edit(doc)));
for (const k of SESSION_CREDENTIALS.flat()) delete f.env[k];
f.env.CLAUDE_CODE_OAUTH_TOKEN = "stand-in";
if (f.doc.roles.chief.vars.harness === "pi" || f.doc.roles.chief.vars["fallback.harness"] === "pi")
f.env.ZAI_API_KEY = "fx332-pi";
// The project root is a repository on main, so each launch can clone it.
const project = f.doc.projects.stack.root;
gitIn(project, "init", "-q", "-b", "main");
@@ -147,29 +145,6 @@ function ask(path, line) {
const log = (f) => readFileSync(launchLogFile(f.dataRoot, "acme"), "utf8").trim().split("\n").map((l) => JSON.parse(l));
// Named mutant: proxy key serialized into session.json. Keep the real launcher,
// harness env generation, session writer and runner; only the model adapter is fake.
test('P3 proxy key reaches the spawned runner but never session.json or the bundle', { skip, timeout: 30000 }, async t => {
const proxy = { baseUrl: 'http://127.0.0.1:12345', key: 'fx332-agent-a' };
const prepared = prepare(t, doc => {
doc.launch.models['claude-opus-5-5'] = { provider: 'proxy', model: 'claude-fixture', route: 'anthropic' };
return doc;
});
const { launcher, f, close } = await setup(t, doc => doc, prepared, { proxy });
const launched = await launcher.launchPm();
const session = readSessions(f.dataRoot).find(s => s.run === launched.run);
assert.ok(session);
const environ = readFileSync(`/proc/${session.runnerPid}/environ`, 'utf8').split('\0');
assert.ok(environ.includes(`ANTHROPIC_API_KEY=${proxy.key}`));
assert.ok(!environ.some(value => value.startsWith('CLAUDE_CODE_OAUTH_TOKEN=')));
const stored = readFileSync(join(session.runDir, 'session.json'), 'utf8');
assert.ok(!stored.includes(proxy.key), 'session.json must never persist the proxy key');
const bundleFiles = readdirSync(join(session.runDir, 'bundle'), { recursive: true, withFileTypes: true })
.filter(entry => entry.isFile()).map(entry => join(entry.parentPath, entry.name));
for (const file of bundleFiles) assert.ok(!readFileSync(file, 'utf8').includes(proxy.key), file);
assert.equal(await close(), 0);
});
test("bus start --pm: the launcher instance (the chief of staff) runs under its own PID namespace, registered, with a manifest", { skip, timeout: 30000 }, async (t) => {
// Row 122: uncertain write receipts cannot prevent the window's first chief launch.
const prepared = prepare(t);
@@ -697,15 +672,14 @@ test("a Claude Code launch with no session credential refuses before it starts",
assert.deepEqual(readdirSync(join(f.dataRoot, "launches")), ["acme.jsonl"], "no run was made");
});
test("a pi launch with no own credential refuses no-session-credential", { skip, timeout: 30000 }, async (t) => {
test("a pi launch needs no session credential: pi logs in through its own ENV_ALLOW variables", { skip, timeout: 30000 }, async (t) => {
const given = prepare(t);
delete given.f.env.CLAUDE_CODE_OAUTH_TOKEN;
delete given.f.env.ZAI_API_KEY;
assert.deepEqual(SESSION_CREDENTIALS.flat().filter((k) => k in given.f.env), []);
const { f, launcher } = await setup(t, undefined, given);
await assert.rejects(launcher.launchPm(), /PM launch refused: no-session-credential/);
assert.deepEqual(log(f).map((e) => [e.event, e.code]), [["refused", "no-session-credential"]]);
assert.deepEqual(readSessions(f.dataRoot), []);
const chief = await launcher.launchPm();
assert.equal(chief.harness, "pi");
assert.deepEqual(log(f).map((e) => [e.event, e.instance]), [["launch", "chief"]]);
});
// Row 65: a harness module no core file names, switched on in the organization file, runs a real
@@ -722,7 +696,6 @@ test("row 65 a failed primary preflight launches the fallback on a fixture harne
write("harness", "down", `export * from ${pi};\nexport const preflight = () => ({ code: "fixture-down", message: "fixture preflight fails" });\n`);
write("harness", "fixture", `export * from ${pi};\nexport const adapter = () => ${JSON.stringify(given.adapter)};\n`);
});
given.f.env.ZAI_API_KEY = "fx332-pi";
const { f, launcher } = await setup(t, undefined, given, { makeLoader });
const chief = await launcher.launchPm();
assert.deepEqual({ ...chief, run: undefined }, { run: undefined, instance: "chief", harness: "fixture", model: "claude-sonnet-5-5" });
+5 -15
View File
@@ -83,13 +83,7 @@ export function sessionModel(resolved, models = null, which = "primary") {
if (models === null) return { harness, provider: null, model, thinking };
const entry = Object.hasOwn(models, model) ? models[model] : null;
if (!entry) throw new BundleError(`instance ${resolved.instance}: unknown model table selection ${model}`);
if (entry.provider === "proxy") {
const missing = !Object.hasOwn(entry, "route");
if (missing || !["anthropic", "glm", "codex"].includes(entry.route))
throw new BundleError("proxy model needs an explicit anthropic, glm or codex route", missing ? "proxy-route-missing" : "proxy-route-unknown");
}
return { harness, provider: entry.provider, model: entry.model, modelKey: model, thinking,
...(entry.provider === "proxy" ? { proxyRoute: entry.route } : {}) };
return { harness, provider: entry.provider, model: entry.model, modelKey: model, thinking };
}
// Row 91 (#1585): the project clones the host made or kept in the workspace.
@@ -315,14 +309,10 @@ function prompt({ contract, resolved, session, tools, untyped, builtins, persona
// personaDir <configDir>/personas, where a creative instance's persona file is read from
// (row 213); an instance with persona.sha256 and no personaDir refuses
// Returns { manifest, files, policy, tools, env } with absolute paths; env is the module's
// adapter variables. In proxy mode the host splits credentials into its
// transient spawn environment before writing the remaining variables to session.json.
export function buildBundle({ dir, resolved, contract, arbiter = false, tracker = false, library = false, credentials = [], session, harness, route = "primary", routeReason = null, harnessVersion = null, models = null, land = false, skillsDir = null, personaDir = null, proxy = null }) {
// adapter variables, which the host writes into session.json.
export function buildBundle({ dir, resolved, contract, arbiter = false, tracker = false, library = false, credentials = [], session, harness, route = "primary", routeReason = null, harnessVersion = null, models = null, land = false, skillsDir = null, personaDir = null }) {
if (route !== "primary" && route !== "fallback") throw new BundleError(`route ${JSON.stringify(route)} isn't primary or fallback`);
const model = sessionModel(resolved, models, route);
if (model.provider === "proxy" && !proxy) throw new BundleError("proxy model needs its own session credential", "no-session-credential");
if (proxy && (typeof proxy.key !== "string" || !proxy.key || typeof proxy.baseUrl !== "string"
|| !/^http:\/\/127\.0\.0\.1:[0-9]+$/.test(proxy.baseUrl))) throw new BundleError("invalid session proxy context");
const web = webPlan(resolved, model.harness, harness.builtinWeb());
const tools = typedTools({ resolved, arbiter, tracker, library, projects: (session.checkouts ?? []).map((c) => c.project), webTyped: !web.builtin, land });
const untyped = untypedActions(resolved, tools);
@@ -356,7 +346,7 @@ export function buildBundle({ dir, resolved, contract, arbiter = false, tracker
write("tools.json", JSON.stringify(tools, null, 2) + "\n"),
];
// The module's own files. A name the bundle already wrote refuses at write (flag wx).
const own = harness.bundle({ dir, files: { ...files }, session: { ...session, ...model }, write, quote, models, proxy });
const own = harness.bundle({ dir, files: { ...files }, session, write, quote });
Object.assign(files, own.files);
digests.push(...own.digests);
const sources = { gate: SOURCES.gate, tools: SOURCES.tools, ...own.sources };
@@ -383,6 +373,6 @@ export function buildBundle({ dir, resolved, contract, arbiter = false, tracker
sources: Object.fromEntries(Object.entries(sources).map(([k, p]) => [k, { path: p, sha256: sha256(readFileSync(p)) }])),
};
writeFileSync(files.manifest, JSON.stringify(manifest, null, 2) + "\n", { mode: 0o600, flag: "wx" });
const env = harness.env({ files, policy, tools, session: { ...session, ...model }, models, proxy });
const env = harness.env({ files, policy, tools, session: { ...session, ...model } });
return { manifest, files, policy, tools, env };
}
+7 -6
View File
@@ -228,24 +228,25 @@ export function typedTools({ resolved, arbiter = false, tracker = false, project
if (library) {
const universe = str("Universe ID in the configured library", { minLength: 1 });
const project = str("Library project ID; omit only when the business has one library");
const scope = str("canon by default; playground is opt-in", { enum: ["canon", "playground"] });
const scope = str("canon by default; playground and supporting are opt-in", { enum: ["canon", "playground", "supporting"] });
const manuscriptScope = str("canon by default; playground is opt-in", { enum: ["canon", "playground"] });
const book = str("Book folder from library_universe");
const offset = { type: "integer", minimum: 0, description: "next from the previous page" };
const line = { type: "integer", minimum: 1, description: "One-based line number" };
const base = { universe, project };
add("library_find", "library.find", null, "Find names in one universe, at the served commit. At most 50 results; continue with next as offset.", obj({
add("library_find", "library.find", null, "Find names in one universe, at the served commit. At most 50 results; continue with next as offset. Playground and supporting are opt-in.", obj({
...base, query: str("Case-insensitive name or filename substring; empty matches all"),
type: str("Mapped type", { enum: ["character", "place", "research", "tracker", "summary"] }),
book, scope, offset,
}, ["universe", "query"]));
add("library_get", "library.get", null, "Read a mapped note and visible links in one universe at the served commit. next pages lines; links_next pages links. An explicit own-universe playground path is readable.", obj({
...base, path: str("Mapped note path relative to the library"), from: line, links_from: offset,
add("library_get", "library.get", null, "Read a note and its blob at the served commit, canon by default. Playground/supporting paths need matching scope; mismatch returns null. next pages lines; links_next pages visible links in supporting/playground/canon order.", obj({
...base, path: str("Mapped note path relative to the library"), scope, from: line, links_from: offset,
}, ["universe", "path"]));
add("library_search", "library.search", null, "Search text in one universe at the served commit. At most 50 hits; use next as offset. Playground is opt-in.", obj({
add("library_search", "library.search", null, "Search text in one universe at the served commit. At most 50 hits; use next as offset. Playground and supporting are opt-in.", obj({
...base, text: str("Nonempty case-insensitive substring", { minLength: 1 }), book, scope, offset,
}, ["universe", "text"]));
add("library_manuscript", "library.manuscript", null, "Read one chapter of a book at the served commit, at most 400 lines. Omit chapter for the first; continue with next or next_chapter.", obj({
...base, book, scope, chapter: str("Chapter filename without extension"), from: line, to: line,
...base, book, scope: manuscriptScope, chapter: str("Chapter filename without extension"), from: line, to: line,
}, ["universe", "book"]));
add("library_universe", "library.universe", null, "Read a universe's mapping at the served commit: books, types, playground prefixes, and hybrid sources/constraints/notes or draft metadata.", obj(base, ["universe"]));
}
+12 -1
View File
@@ -46,7 +46,7 @@ test('lookup schemas require a universe even for get, include paging, and cannot
for (const key of ['repo', 'commit', 'business', 'accept']) assert.equal(Object.hasOwn(tool.parameters.properties, key), false);
}
const byName = Object.fromEntries(tools.map(t => [t.name, t]));
assert.deepEqual(byName.library_find.parameters.properties.scope.enum, ['canon', 'playground']);
assert.deepEqual(byName.library_find.parameters.properties.scope.enum, ['canon', 'playground', 'supporting']);
assert.deepEqual(byName.library_find.parameters.properties.type.enum, [...TYPES]);
assert.equal(byName.library_find.parameters.properties.offset.minimum, 0);
assert.equal(byName.library_get.parameters.properties.from.minimum, 1);
@@ -69,3 +69,14 @@ test('bundle flag reaches both harness tool manifests and creative prompt withou
assert.doesNotMatch(prompt, /Bus tools: [^\n]*(read_spec|list_agents|inbox|trail|write_record|raise_decision|list_tasks)/);
}
});
test('C2-05c scope schemas expand only find/search/get, keeping manuscript and tool names unchanged', t => {
const tools = typedTools({ resolved: role(t, 'ideas'), library: true });
assert.deepEqual(tools.map(t => t.name), ['send_message', ...LOOKUPS]);
for (const name of ['library_find', 'library_search', 'library_get']) {
const tool = tools.find(t => t.name === name);
assert.deepEqual(tool.parameters.properties.scope.enum, ['canon', 'playground', 'supporting']);
assert.ok(!tool.parameters.required.includes('scope'));
}
assert.deepEqual(tools.find(t => t.name === 'library_manuscript').parameters.properties.scope.enum, ['canon', 'playground']);
});
@@ -1,113 +0,0 @@
// P3: generate real harness config through buildBundle; credentials never enter disk artifacts.
import test from 'node:test';
import assert from 'node:assert/strict';
import { mkdirSync, readFileSync, statSync } from 'node:fs';
import { join } from 'node:path';
import { buildBundle } from '../src/bundle.mjs';
import { HARNESS, REPO_SKILLS, resolvedFor, scratch } from './helpers.mjs';
const models = {
a: { provider: 'proxy', model: 'claude-fixture', route: 'anthropic' },
z: { provider: 'proxy', model: 'glm-fixture', route: 'glm' },
g: { provider: 'proxy', model: 'gpt-fixture', route: 'codex' },
};
function build(t, selection, proxy, declared) {
const root = scratch(t, 'p332-'), runDir = join(root, 'run');
mkdirSync(runDir, { mode: 0o700 });
const valid = resolvedFor(t, 'pm');
assert.ok(Object.hasOwn(declared, selection), 'fixture selection must exist in declared launch.models');
const resolved = { ...valid, vars: { ...valid.vars, harness: 'pi', model: selection } };
const bundle = buildBundle({
dir: join(runDir, 'bundle'), resolved, models: declared,
contract: '# Fixture\n', harness: HARNESS.pi, harnessVersion: 'fixture',
skillsDir: REPO_SKILLS, proxy,
session: { run: 'r332', launchedBy: 'chief', workspace: join(root, 'ws'),
toolSocket: join(runDir, 'tools.sock'), turnMarker: join(runDir, 'turn.done') },
});
const file = join(runDir, 'home', '.pi', 'agent', 'models.json');
return { ...bundle, file, runDir, text: readFileSync(file, 'utf8') };
}
function assertSafe(value) {
if (typeof value === 'string') assert.ok(!value.startsWith('!'), value);
else if (value && typeof value === 'object') for (const item of Object.values(value)) assertSafe(item);
}
test('P3 Anthropic route uses messages at proxy root and the declared model id', t => {
const b = build(t, 'a', { baseUrl: 'http://127.0.0.1:12345', key: 'fx332-agent-a' }, { a: models.a });
const { anthropic } = JSON.parse(b.text).providers;
assert.equal(anthropic.api, 'anthropic-messages');
assert.equal(anthropic.baseUrl, 'http://127.0.0.1:12345');
assert.deepEqual(anthropic.models.map(m => m.id), ['claude-fixture']);
assert.equal(b.env.PI_PROVIDER, 'anthropic');
assert.equal(b.env.PI_MODEL, 'claude-fixture');
});
test('P3 omitted route refuses proxy-route-missing before model config generation', t => {
assert.throws(() => build(t, 'a', { baseUrl: 'http://127.0.0.1:12345', key: 'fx332-agent-a' }, {
a: { provider: 'proxy', model: 'claude-fixture' },
}), { code: 'proxy-route-missing' });
});
test('P3 GLM route uses completions at proxy /v1 with explicit z.ai compatibility', t => {
const b = build(t, 'z', { baseUrl: 'http://127.0.0.1:12345', key: 'fx332-agent-a' }, { z: models.z });
const glm = JSON.parse(b.text).providers['mosaic-proxy-glm'];
assert.equal(glm.api, 'openai-completions');
assert.equal(glm.baseUrl, 'http://127.0.0.1:12345/v1');
assert.deepEqual(glm.models.map(m => m.id), ['glm-fixture']);
assert.equal(glm.compat.thinkingFormat, 'zai');
assert.equal(glm.compat.zaiToolStream, true);
assert.equal(b.env.PI_PROVIDER, 'mosaic-proxy-glm');
});
test('P3 GPT route selects a stack-owned provider instead of pi Codex OAuth', t => {
const b = build(t, 'g', { baseUrl: 'http://127.0.0.1:12345', key: 'fx332-agent-a' }, { g: models.g });
const providers = JSON.parse(b.text).providers;
assert.equal(Object.hasOwn(providers, 'openai-codex'), false);
const gpt = providers['mosaic-proxy-codex'];
assert.equal(gpt.api, 'openai-responses');
assert.equal(gpt.baseUrl, 'http://127.0.0.1:12345/v1');
assert.deepEqual(gpt.models.map(m => m.id), ['gpt-fixture']);
assert.equal(b.env.PI_PROVIDER, 'mosaic-proxy-codex');
});
test('P3 a declared Codex route generates only the single build-time responses provider', t => {
const b = build(t, 'g', { baseUrl: 'http://127.0.0.1:12345', key: 'fx332-agent-a' }, {
g: models.g,
});
const providers = JSON.parse(b.text).providers;
assert.deepEqual(Object.keys(providers), ['mosaic-proxy-codex']);
assert.equal(providers['mosaic-proxy-codex'].api, 'openai-responses');
assert.equal(providers['mosaic-proxy-codex'].apiKey, '$ANTHROPIC_API_KEY');
});
test('P3 models file is private, references the one session key, and stores no executable values or keys', t => {
const key = 'fx332-agent-a';
const b = build(t, 'a', { baseUrl: 'http://127.0.0.1:12345', key }, { a: models.a, z: models.z });
const document = JSON.parse(b.text);
assert.deepEqual(Object.keys(document.providers).sort(), ['anthropic', 'mosaic-proxy-glm']);
for (const provider of Object.values(document.providers)) assert.equal(provider.apiKey, '$ANTHROPIC_API_KEY');
assertSafe(document);
assert.ok(!b.text.includes(key));
assert.equal(b.env.ANTHROPIC_API_KEY, key);
assert.equal(statSync(b.file).mode & 0o777, 0o600);
for (const dir of ['home', 'home/.pi', 'home/.pi/agent']) assert.equal(statSync(join(b.runDir, dir)).mode & 0o777, 0o700);
for (const file of Object.values(b.files)) assert.ok(!readFileSync(file, 'utf8').includes(key), file);
assert.ok(!JSON.stringify(b.manifest).includes(key));
});
test('P3 every launch regenerates proxy port, declared models and own key without caching', t => {
const first = build(t, 'a', { baseUrl: 'http://127.0.0.1:12345', key: 'fx332-agent-a' }, { a: models.a, z: models.z });
const second = build(t, 'a', { baseUrl: 'http://127.0.0.1:23456', key: 'fx332-agent-b' }, {
a: { provider: 'proxy', model: 'changed-model-id', route: 'anthropic' },
z: { provider: 'proxy', model: 'changed-glm-id', route: 'glm' },
});
assert.equal(second.env.ANTHROPIC_API_KEY, 'fx332-agent-b');
assert.ok(!JSON.stringify(second).includes('fx332-agent-a'));
const { providers } = JSON.parse(second.text);
assert.deepEqual(Object.keys(providers), ['anthropic', 'mosaic-proxy-glm']);
assert.equal(providers.anthropic.baseUrl, 'http://127.0.0.1:23456');
assert.deepEqual(providers.anthropic.models.map(m => m.id), ['changed-model-id']);
assert.equal(providers['mosaic-proxy-glm'].baseUrl, 'http://127.0.0.1:23456/v1');
assert.deepEqual(providers['mosaic-proxy-glm'].models.map(m => m.id), ['changed-glm-id']);
assert.equal(JSON.parse(first.text).providers.anthropic.baseUrl, 'http://127.0.0.1:12345');
});
+19 -9
View File
@@ -7,12 +7,15 @@
import { raise } from './problems.mjs';
import { TYPES } from './mapping.mjs';
import { indexFor } from './index-build.mjs';
import { listTree } from './reader.mjs';
// The same cap as packages/harness/src/tools.mjs REPLY_CAP. The query tests assert the two stay equal.
export const QUERY_REPLY_CAP = 40_000;
export const LOOKUP_LIMIT = 50;
export const MANUSCRIPT_LINES = 400;
const SCOPES = Object.freeze(['canon', 'playground']);
const SCOPES = Object.freeze(['canon', 'playground', 'supporting']);
const MANUSCRIPT_SCOPES = Object.freeze(['canon', 'playground']);
const SCOPE_RANK = Object.freeze({ supporting: 0, playground: 1, canon: 2 });
const bytes = value => JSON.stringify(value).length;
const invalid = message => raise('query-argument-invalid', message);
@@ -22,9 +25,9 @@ function textArg(value, name) {
if (typeof value !== 'string') invalid(`${name} must be text`);
return value;
}
function scopeArg(value) {
function scopeArg(value, allowed = SCOPES) {
if (value === undefined) return 'canon';
if (!SCOPES.includes(value)) invalid('scope must be "canon" or "playground"');
if (!allowed.includes(value)) invalid(`scope must be one of ${allowed.join(", ")}`);
return value;
}
function positionArg(value, name, fallback) {
@@ -109,7 +112,8 @@ export async function find(source, { universe: name, query, type, book, scope, o
});
}
// get: one visible file, its front matter, its lines from `from`, and its visible links both ways.
// get: one file in the requested scope (canon default), its served-tree blob, front matter,
// lines and visible links both ways. Links keep all visible scopes, ordered supporting/playground/canon.
// Returns null when the file is missing or not visible, so a caller cannot tell the two apart. Lines page
// by `from` (reply `next`), links page together by `links_from` (reply `links_next`); `links_out` come
// before `links_in`. Every page carries the front matter. Links take at most half the cap, so a hub note
@@ -117,27 +121,33 @@ export async function find(source, { universe: name, query, type, book, scope, o
// least one line, so links shrink when a line needs the room; read on with `from: next` and
// `links_from: links_next`. A `from` past the last line returns links alone. Only front matter, or a
// line that cannot fit with no links beside it, is refused.
export async function get(source, { universe: name, path, from, links_from: linksFrom } = {}) {
export async function get(source, { universe: name, path, scope, from, links_from: linksFrom } = {}) {
const universe = universeArg(source.mapping, name);
const requestedScope = scopeArg(scope);
const startLine = positionArg(from, 'from', 1);
const linkStart = offsetArg(linksFrom);
if (typeof path !== 'string') invalid('path must be text');
const index = await indexFor(source);
const file = index.files.get(path);
if (!file || !sees(index.mapping, universe, file)) return null;
if (!file || file.scope !== requestedScope || !sees(index.mapping, universe, file)) return null;
const reachable = links => links.filter(link => {
const other = index.files.get(link.path);
return other !== undefined && sees(index.mapping, universe, other);
});
}).sort((a, b) => SCOPE_RANK[index.files.get(a.path).scope] - SCOPE_RANK[index.files.get(b.path).scope]);
const outs = reachable(index.linksOut.get(file.path) ?? []);
const ins = reachable(index.linksIn.get(file.path) ?? []);
const links = [...outs.map(link => ({ out: true, link })), ...ins.map(link => ({ out: false, link }))];
// The reader/index does not keep tree oids. Resolve only in this immutable served
// snapshot, never HEAD; listTree already checks/bounds the tree and its object IDs.
const entry = (await listTree(source.repo, index.commit)).find(entry => entry.path === file.path);
if (!entry || entry.mode !== '100644' || entry.type !== 'blob') raise('library-commit', 'indexed file is absent from the served tree');
const blob = entry.oid;
const lines = file.lines.slice(startLine - 1);
const linkRest = Math.max(0, links.length - linkStart);
const page = (nLines, nLinks) => {
const taken = links.slice(linkStart, linkStart + nLinks);
return {
path: file.path, commit: index.commit, scope: file.scope, frontmatter: file.frontmatter,
path: file.path, commit: index.commit, blob, scope: file.scope, frontmatter: file.frontmatter,
lines: lines.slice(0, nLines),
links_out: taken.filter(item => item.out).map(item => item.link),
links_in: taken.filter(item => !item.out).map(item => item.link),
@@ -201,7 +211,7 @@ export async function manuscript(source, { universe: name, book, scope, chapter,
const start = positionArg(from, 'from', 1);
const end = positionArg(to, 'to', Infinity);
if (end < start) invalid('to must not be before from');
const { index, files } = await visible(source, universe, { scope: scopeArg(scope), book: bookName, type: 'manuscript' });
const { index, files } = await visible(source, universe, { scope: scopeArg(scope, MANUSCRIPT_SCOPES), book: bookName, type: 'manuscript' });
let at = 0;
if (chapterName !== undefined) {
const matches = files.filter(file => file.stem === chapterName);
+19
View File
@@ -29,3 +29,22 @@ export const note = (type, name, body = '', extra = []) => ['---', `type: ${type
// `exclude` (a path prefix today); swapping these two constants is the whole change to the tests.
export const EXCLUSION = { exclude: 'Book One/Research' };
export const EXCLUDED_PATHS = ['Book One/Research/Ferry Logs.md'];
// C2-05c: synthetic scope fixture, including same-prefix precedence and a draft.
export const SUPPORT_FILES = {
'Book One/Characters/Canon.md': note('character', 'Canon', 'Scope fixture canon.'),
'Book One/Playground/Plan.md': note('summary', 'Plan', 'Scope fixture playground.'),
'Book One/Support/Notes/Helper.md': note('summary', 'Helper', 'Scope fixture supporting.'),
'Notes/HarborSupport/Loose.md': note('summary', 'Loose', 'Scope fixture supporting loose.'),
'Drafts/Idea/Support/Seed.md': note('summary', 'Seed', 'Scope fixture supporting draft.'),
};
export const withSupporting = entry => ({
...entry,
universes: {
...entry.universes,
harbor: { ...entry.universes.harbor,
playground: [...entry.universes.harbor.playground, 'Book One/Support/'],
supporting: ['Book One/Support/', 'Notes/HarborSupport/'] },
idea: { kind: 'draft', name: 'Idea', playground: ['Drafts/Idea/'], supporting: ['Drafts/Idea/Support/'] },
},
});
+103 -6
View File
@@ -1,11 +1,13 @@
// Query tests for design 3 (C2-05a): universe isolation, scope labels, unmapped files, hybrids, paging
// under the reply cap, refusals and manuscript paging. Fixtures are made up and built under the scratch area.
import { test } from 'node:test';
import { writeFileSync } from 'node:fs';
import { join } from 'node:path';
import assert from 'node:assert/strict';
import { REPLY_CAP } from '../../harness/src/tools.mjs';
import { find, get, search, manuscript, universeInfo, QUERY_REPLY_CAP, LOOKUP_LIMIT, MANUSCRIPT_LINES } from '../src/query.mjs';
import { mapping, MARKER } from './helpers.mjs';
import { scratchRepo, note, EXCLUSION, EXCLUDED_PATHS } from './query-fixture.mjs';
import { mapping, MARKER, git } from './helpers.mjs';
import { scratchRepo, note, EXCLUSION, EXCLUDED_PATHS, SUPPORT_FILES, withSupporting } from './query-fixture.mjs';
// A hybrid over harbor and second. Its one constraint is EXCLUSION (query-fixture.mjs) and it declares no
// books or playground.
@@ -345,9 +347,9 @@ test('PRD 1.14: a draft universe has no canon, so its lookups return files only
assert.ok(found.results.every(r => r.scope === 'playground' && r.universe === 'idea' && r.book === null));
const hits = (await search(s, { universe: 'idea', text: 'draft', scope: 'playground' })).results;
assert.equal(hits.length, 2);
const rin = await get(s, { universe: 'idea', path: 'Drafts/New World/Characters/Rin.md' });
const rin = await get(s, { universe: 'idea', path: 'Drafts/New World/Characters/Rin.md', scope: 'playground' });
assert.equal(rin.scope, 'playground');
assert.equal(await get(s, { universe: 'harbor', path: 'Drafts/New World/Characters/Rin.md' }), null);
assert.equal(await get(s, { universe: 'harbor', path: 'Drafts/New World/Characters/Rin.md', scope: 'playground' }), null);
});
test('PRD 1.14: library_universe on a draft returns its kind, name and prefixes', async t => {
@@ -363,7 +365,102 @@ test('PRD 1.14: library_universe on a draft returns its kind, name and prefixes'
test('a hybrid gets a source playground file as null, while the source gets it with scope playground', async t => {
const ref = scratchRepo(t, FILES);
const path = 'Book One/Playground/What If.md';
assert.equal(await get(src(ref, mapping(WITH_BLEND)), { universe: 'blend', path }), null);
const own = await get(src(ref), { universe: 'harbor', path });
assert.equal(await get(src(ref, mapping(WITH_BLEND)), { universe: 'blend', path, scope: 'playground' }), null);
const own = await get(src(ref), { universe: 'harbor', path, scope: 'playground' });
assert.equal(own.scope, 'playground');
});
// mos-1330 item3: the new get contract defaults to canon even for an explicit playground path.
test('C2-05c get without scope returns null for a playground path', async t => {
const s = src(scratchRepo(t, FILES));
assert.equal(await get(s, { universe: 'harbor', path: 'Book One/Playground/What If.md' }), null);
});
// Row284: scope is explicit for get as well as lists; blob and lines share a served snapshot.
test('C2-05c supporting find/search/get are opt-in at book, universe and draft level', async t => {
const s = src(scratchRepo(t, SUPPORT_FILES), mapping(withSupporting));
const expected = ['Book One/Support/Notes/Helper.md', 'Notes/HarborSupport/Loose.md'];
assert.deepEqual(paths(await find(s, { universe: 'harbor', query: '', scope: 'supporting' })), expected);
assert.deepEqual((await search(s, { universe: 'harbor', text: 'Scope fixture', scope: 'supporting' })).results.map(x => x.path), expected);
assert.deepEqual(paths(await find(s, { universe: 'harbor', query: '' })), ['Book One/Characters/Canon.md']);
assert.deepEqual((await search(s, { universe: 'harbor', text: 'Scope fixture' })).results.map(x => x.path), ['Book One/Characters/Canon.md']);
for (const path of expected) {
assert.equal(await get(s, { universe: 'harbor', path }), null);
assert.equal(await get(s, { universe: 'harbor', path, scope: 'playground' }), null);
assert.equal((await get(s, { universe: 'harbor', path, scope: 'supporting' })).scope, 'supporting');
assert.equal(await get(s, { universe: 'second', path, scope: 'supporting' }), null);
}
const draftPath = 'Drafts/Idea/Support/Seed.md';
assert.deepEqual(paths(await find(s, { universe: 'idea', query: '', scope: 'supporting' })), [draftPath]);
assert.equal((await get(s, { universe: 'idea', path: draftPath, scope: 'supporting' })).scope, 'supporting');
assert.equal(await get(s, { universe: 'idea', path: draftPath }), null);
assert.equal((await find(s, { universe: 'harbor', query: '', book: 'Book One', scope: 'supporting' })).results.length, 1);
});
test('C2-05c an absent supporting prefix returns nothing without refusal', async t => {
const s = src(scratchRepo(t, SUPPORT_FILES));
assert.deepEqual((await find(s, { universe: 'harbor', query: '', scope: 'supporting' })).results, []);
assert.deepEqual((await search(s, { universe: 'harbor', text: 'Scope fixture', scope: 'supporting' })).results, []);
assert.equal(await get(s, { universe: 'harbor', path: 'Book One/Characters/Canon.md', scope: 'supporting' }), null);
assert.equal(await get(s, { universe: 'harbor', path: 'Book One/Support/Notes/Helper.md', scope: 'supporting' }), null);
});
test('C2-05c each get blob equals its served tree object, even after source HEAD advances', async t => {
const ref = scratchRepo(t, SUPPORT_FILES), s = src(ref, mapping(withSupporting));
const canon = 'Book One/Characters/Canon.md';
const priorBlob = git(ref.repo, 'rev-parse', `${ref.commit}:${canon}`);
writeFileSync(join(ref.repo, canon), note('character', 'Canon changed', 'New HEAD must not be read.'));
git(ref.repo, 'add', '-A'); git(ref.repo, 'commit', '-qm', 'advance head fixture');
assert.notEqual(git(ref.repo, 'rev-parse', `HEAD:${canon}`), priorBlob);
for (const [scope, path] of [['canon', canon], ['playground', 'Book One/Playground/Plan.md'], ['supporting', 'Book One/Support/Notes/Helper.md']]) {
const result = await get(s, { universe: 'harbor', path, scope });
assert.equal(result.commit, ref.commit);
assert.equal(result.blob, git(ref.repo, 'rev-parse', `${ref.commit}:${path}`));
assert.ok(!JSON.stringify(result.lines).includes('New HEAD must not be read'));
}
});
test('C2-05c full outgoing and incoming links stay in scope order across pages without losing cross-scope links', async t => {
const files = {}, groups = { supporting: [], playground: [], canon: [] };
for (const [scope, folder] of [['canon', 'Book One/Characters'], ['playground', 'Book One/Playground'], ['supporting', 'Book One/Support']]) {
for (let n = 0; n < 100; n++) {
const path = `${folder}/${scope}-${String(n).padStart(3, '0')}-${'x'.repeat(80)}.md`;
groups[scope].push(path);
files[path] = `[[Book One/Characters/Hub]]\n`;
}
}
const all = [...groups.canon, ...groups.playground, ...groups.supporting];
files['Book One/Characters/Hub.md'] = all.map(path => `[[${path.slice(0, -3)}]]`).join('\n');
// Other-universe links are never returned, regardless of rank.
files['Second World/Other.md'] = '[[Book One/Characters/Hub]]\n';
const s = src(scratchRepo(t, files), mapping(withSupporting));
const outs = [], ins = [];
let offset = 0, pages = 0;
for (; pages < 20; pages++) {
const page = await get(s, { universe: 'harbor', path: 'Book One/Characters/Hub.md', from: 999_999, links_from: offset });
assert.ok(JSON.stringify(page).length <= QUERY_REPLY_CAP);
outs.push(...page.links_out.map(x => x.path)); ins.push(...page.links_in.map(x => x.path));
if (page.links_next === null) break;
offset = page.links_next;
}
const expected = [...groups.supporting, ...groups.playground, ...groups.canon];
assert.ok(pages > 0 && pages < 20, 'links occupy multiple bounded pages');
assert.deepEqual(outs, expected);
assert.deepEqual(ins, expected);
assert.equal(new Set(outs).size, 300);
assert.equal(new Set(ins).size, 300);
});
test('C2-05c manuscript still refuses supporting rather than silently widening its scope', async t => {
const s = src(scratchRepo(t, SUPPORT_FILES), mapping(withSupporting));
await assert.rejects(manuscript(s, { universe: 'harbor', book: 'Book One', scope: 'supporting' }), { code: 'query-argument-invalid' });
});
test('C2-05c scope expansion keeps hybrid sources canon-only and refuses all/array scopes', async t => {
const s = src(scratchRepo(t, SUPPORT_FILES), mapping(entry => withSupporting(WITH_BLEND(entry))));
assert.deepEqual((await find(s, { universe: 'blend', query: '', scope: 'supporting' })).results, []);
assert.equal(await get(s, { universe: 'blend', path: 'Book One/Support/Notes/Helper.md', scope: 'supporting' }), null);
assert.equal((await get(s, { universe: 'blend', path: 'Book One/Characters/Canon.md' })).scope, 'canon');
for (const scope of ['all', ['canon', 'supporting']])
await assert.rejects(get(s, { universe: 'harbor', path: 'Book One/Characters/Canon.md', scope }), { code: 'query-argument-invalid' });
});
-29
View File
@@ -327,32 +327,3 @@ organization file or unavailable bus.
For the re-pin introducing this kind, Jason enables both channels through
plugins.set immediately after activate in Mos's window, then smokes CLI thread
listing and Console chat. No development seat performs that live step.
## Per-session proxy context (P3)
The launcher's injected `proxy` is either a `{ baseUrl, key }` context supplied by
P2, or a factory receiving `{ business, instance }` and returning that context.
Checks may repeat before spawn; the factory must return that agent's current
credential. P3 does not acquire, issue or revoke keys. No context means existing
nonproxy launch behavior; a selected proxy model without context refuses.
The harness `preflight`, `bundle` and `env` calls receive an optional `proxy`
argument; `bundle` and `env` also receive the declared model table. In proxy
mode the launcher removes instance provider variables, then separates the
harness's credential variables from `harnessEnv` before writing `session.json`.
Only the spawned runner's environment receives those variables.
A proxy `launch.models` entry requires `route: anthropic|glm|codex`. Omission
refuses `proxy-route-missing`; unknown routes refuse `proxy-route-unknown`. Other providers
retain provider/model-only entries. `launch.account.credential: proxy` names the
proxy credential source. Pi needs its own provider key or a supplied proxy key;
Claude OAuth alone cannot satisfy pi preflight.
Pi writes private, fresh run-local `home/.pi/agent/models.json`, with
`$ANTHROPIC_API_KEY` references. Anthropic uses messages at the proxy root; GLM
uses completions at `/v1` with z.ai compatibility fields. GPT uses the stack-owned
`mosaic-proxy-codex` provider, never pi's Codex OAuth provider. Its build-time API
value is `openai-responses` per Sage's sage-4331 ruling: both shapes passed the
pinned offline probe, so this is a reasoning-based tie-break rather than an
evidence-decided pick. Row209 phase A step7 verifies the first real Codex turn.
There is no runtime API selection or fallback.
@@ -53,8 +53,8 @@ function binary(env) {
}
// A session needs a credential from the host's environment and the binary it runs.
export function preflight({ env, proxy = null }) {
if (!(typeof proxy?.key === "string" && proxy.key) && !hasSessionCredential(env)) {
export function preflight({ env }) {
if (!hasSessionCredential(env)) {
const names = SESSION_CREDENTIALS.map((set) => set.join(" with ")).join(", ");
return { code: "no-session-credential", message: `the bus host has none of ${names}; the bus unit's EnvironmentFile sets one when the bus starts` };
}
@@ -116,13 +116,12 @@ export function bundle({ dir, files: core, session, write, quote }) {
return { files, digests, sources: { claudeGate: GATE, mcpServer: MCP_SERVER, ...UNSLOP } };
}
export function env({ files, policy, session, proxy = null }) {
export function env({ files, policy, session }) {
return {
MOSAIC_TOOLS: claudeBuiltins(policy).join(","),
MOSAIC_CLAUDE_SETTINGS: files.settings,
MOSAIC_CLAUDE_MCP_CONFIG: files.mcp,
MOSAIC_THINKING: session.thinking,
...(proxy ? { ANTHROPIC_BASE_URL: proxy.baseUrl, ANTHROPIC_AUTH_TOKEN: proxy.key } : {}),
};
}
+6 -51
View File
@@ -3,9 +3,8 @@
// Pi extension, which stays in packages/harness (a module can't change that boundary). The
// launcher, the bundle and the usage reader call these on the host; the runner gets the answers
// as data in session.json. packages/plugins/README.md lists the interface.
import { existsSync, lstatSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { createHash } from "node:crypto";
import { existsSync, readFileSync, realpathSync } from "node:fs";
import { join } from "node:path";
import { fileURLToPath } from "node:url";
export const interfaceVersion = 1;
@@ -13,10 +12,6 @@ export const interfaceVersion = 1;
const REPO = fileURLToPath(new URL("../../../../", import.meta.url));
const PACKAGE = "@earendil-works/pi-coding-agent";
const BIN = join(REPO, "node_modules", ".bin", "pi");
// Sage sage-4331: reasoning-based tie-break; both pinned-proxy shapes passed.
// First real Codex verification remains row209 phase A step7. No runtime switch.
const PROXY_CODEX_API = "openai-responses";
const PROXY_PROVIDERS = Object.freeze({ anthropic: "anthropic", glm: "mosaic-proxy-glm", codex: "mosaic-proxy-codex" });
const EXTENSION = fileURLToPath(new URL("../../../harness/src/pi-extension.mjs", import.meta.url));
// Row 66 (#1559): the unslop check, loaded as a second extension. It logs to MOSAIC_UNSLOP_LOG,
// which the runner sets, and the runner tells the operator.
@@ -35,11 +30,7 @@ export const adapter = () => join(REPO, "adapters", "pi", "adapter.sh");
export const levels = () => LEVELS;
// The session runs pi from the repository's node_modules, which the sandbox mounts.
export function preflight({ env = {}, proxy = null } = {}) {
if (!(typeof proxy?.key === "string" && proxy.key)
&& !["ANTHROPIC_API_KEY", "OPENAI_API_KEY", "OPENROUTER_API_KEY", "ZAI_API_KEY"].some(name => Boolean(env[name]))) {
return { code: "no-session-credential", message: "pi needs its own provider key or a session proxy key" };
}
export function preflight() {
if (!existsSync(BIN)) return { code: "harness-binary-missing", message: `pi isn't installed at ${BIN}; run npm ci in the repository` };
return null;
}
@@ -66,52 +57,16 @@ export const builtins = ({ tools }) => [...tools];
export const typedName = (name) => name;
export const reliesOn = () => RELIES_ON;
export const gateTimeout = () => null;
export function bundle({ dir, models, proxy = null }) {
const sources = { piExtension: EXTENSION, ...UNSLOP };
if (!proxy) return { files: {}, digests: [], sources };
const providers = {};
for (const entry of Object.values(models ?? {})) {
if (entry.provider !== "proxy") continue;
const route = entry.route;
if (!Object.hasOwn(PROXY_PROVIDERS, route)) throw new Error("proxy model has no supported route");
const provider = PROXY_PROVIDERS[route];
if (typeof entry.model !== "string" || !entry.model || entry.model.startsWith("!")) throw new Error("unsafe proxy model id");
const api = route === "anthropic" ? "anthropic-messages"
: route === "glm" ? "openai-completions" : PROXY_CODEX_API;
providers[provider] ??= {
baseUrl: proxy.baseUrl + (route === "anthropic" ? "" : "/v1"),
api, apiKey: "$ANTHROPIC_API_KEY",
...(route === "glm" ? { compat: { thinkingFormat: "zai", zaiToolStream: true } } : {}),
models: [],
};
if (!providers[provider].models.some(model => model.id === entry.model)) {
providers[provider].models.push({ id: entry.model, reasoning: true });
}
}
const text = JSON.stringify({ providers }, null, 2) + "\n";
// Even an accidental collision between a configured model id and the key fails closed.
if (typeof proxy.key !== "string" || !proxy.key || text.includes(proxy.key)) throw new Error("unsafe proxy model configuration");
const runDir = dirname(dir);
for (const part of ["home", "home/.pi", "home/.pi/agent"]) {
const path = join(runDir, part);
mkdirSync(path, { recursive: true, mode: 0o700 });
const stat = lstatSync(path);
if (!stat.isDirectory() || (stat.mode & 0o777) !== 0o700) throw new Error("pi proxy config needs private run-local directories");
}
const file = join(runDir, "home", ".pi", "agent", "models.json");
writeFileSync(file, text, { mode: 0o600, flag: "wx" });
return { files: { proxyModels: file }, digests: [["../home/.pi/agent/models.json", createHash("sha256").update(text).digest("hex")]], sources };
}
export const bundle = () => ({ files: {}, digests: [], sources: { piExtension: EXTENSION, ...UNSLOP } });
// The tool limit is the built-ins plus the typed tools, which the extension serves.
export function env({ policy, tools, session, proxy = null }) {
export function env({ policy, tools, session }) {
return {
MOSAIC_TOOLS: [...policy.tools, ...tools.map((t) => t.name)].join(","),
MOSAIC_EXTENSIONS: [EXTENSION, UNSLOP.unslopExtension].join(","),
PI_PROVIDER: proxy ? PROXY_PROVIDERS[session.proxyRoute] : session.provider ?? "",
PI_PROVIDER: session.provider ?? "",
PI_MODEL: session.model,
MOSAIC_THINKING: session.thinking,
...(proxy ? { ANTHROPIC_API_KEY: proxy.key } : {}),
};
}
+2 -2
View File
@@ -97,9 +97,9 @@ test("row 65 claude-code version asks MOSAIC_CLAUDE_BIN when set, else claude on
assert.equal(claude.version({ env: { PATH: join(dir, "none") } }), null);
});
test("row 65 pi preflight refuses missing credentials, and its version is the package pin", async () => {
test("row 65 pi preflight passes with the repository's pi, and its version is the package pin", async () => {
const pi = await load("pi");
assert.equal(pi.preflight({ env: {} }).code, "no-session-credential");
assert.equal(pi.preflight({ env: {} }), null);
const pkg = JSON.parse(readFileSync(join(REPO, "package.json"), "utf8"));
assert.equal(pi.version({ env: {} }), pkg.dependencies?.["@earendil-works/pi-coding-agent"] ?? pkg.devDependencies?.["@earendil-works/pi-coding-agent"]);
// Row 66: the unslop extension's files, bound read-only at their own paths.
@@ -1,65 +0,0 @@
// P3: run real harness exports through the plug-in loader, with made-up session keys only.
import test from 'node:test';
import assert from 'node:assert/strict';
import { chmodSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { createLoader } from '../src/loader.mjs';
import { sessionEnv } from '../../seat/src/session.mjs';
async function harness(name) {
const loader = createLoader({ log() {} });
const result = await loader.load({ harness: [name] });
assert.deepEqual(result.refused, []);
return loader.modules('harness')[0];
}
function scratch(t) {
const root = mkdtempSync(join(tmpdir(), 'p332-'));
t.after(() => rmSync(root, { recursive: true, force: true }));
return root;
}
const policy = { tools: [], typed: [] };
const session = { model: 'claude-fixture', thinking: 'low' };
test('P3 Claude env receives the session proxy URL and key, without another agent or host credential', async () => {
const claude = await harness('claude-code');
const host = { CLAUDE_CODE_OAUTH_TOKEN: 'fx332-host', OPENAI_API_KEY: 'fx332-upstream' };
for (const [run, key] of [['r332a', 'fx332-agent-a'], ['r332b', 'fx332-agent-b']]) {
const proxy = { baseUrl: 'http://127.0.0.1:12345', key };
const env = { ...sessionEnv(host, run, proxy), ...claude.env({ files: {}, policy, session, proxy }) };
assert.equal(env.ANTHROPIC_BASE_URL, 'http://127.0.0.1:12345');
assert.equal(env.ANTHROPIC_AUTH_TOKEN, key);
assert.equal(Object.hasOwn(env, 'CLAUDE_CODE_OAUTH_TOKEN'), false);
assert.equal(Object.hasOwn(env, 'OPENAI_API_KEY'), false);
const other = run === 'r332a' ? 'fx332-agent-b' : 'fx332-agent-a';
assert.ok(!Object.values(env).includes(other));
}
});
test('P3 Claude preflight accepts a proxy key without a host provider credential', async t => {
const claude = await harness('claude-code');
const root = scratch(t), binary = join(root, 'claude');
writeFileSync(binary, '#!/bin/sh\nexit 0\n');
chmodSync(binary, 0o700);
assert.equal(claude.preflight({ env: { MOSAIC_CLAUDE_BIN: binary }, proxy: {
baseUrl: 'http://127.0.0.1:12345', key: 'fx332-agent-a',
} }), null);
});
test('P3 pi refuses no-session-credential with no provider key', async () => {
const pi = await harness('pi');
assert.equal(pi.preflight({ env: {} })?.code, 'no-session-credential');
});
test('P3 pi refuses no-session-credential with only a Claude OAuth token', async () => {
const pi = await harness('pi');
assert.equal(pi.preflight({ env: { CLAUDE_CODE_OAUTH_TOKEN: 'fx332-oauth' } })?.code, 'no-session-credential');
});
test('P3 pi accepts its own provider key or a session proxy key', async () => {
const pi = await harness('pi');
for (const name of ['ANTHROPIC_API_KEY', 'OPENAI_API_KEY', 'OPENROUTER_API_KEY', 'ZAI_API_KEY']) {
assert.equal(pi.preflight({ env: { [name]: 'fx332-own' } }), null, name);
}
assert.equal(pi.preflight({ env: {}, proxy: { baseUrl: 'http://127.0.0.1:12345', key: 'fx332-agent-a' } }), null);
});
+2 -6
View File
@@ -253,13 +253,9 @@ export const ENV_ALLOW = Object.freeze([
export const SESSION_CREDENTIALS = Object.freeze([["CLAUDE_CODE_OAUTH_TOKEN"], ["ANTHROPIC_API_KEY"], ["ANTHROPIC_AUTH_TOKEN", "ANTHROPIC_BASE_URL"]].map((set) => Object.freeze(set)));
export const hasSessionCredential = (env) => SESSION_CREDENTIALS.some((set) => set.every((k) => Boolean(env[k])));
// Used again at the serialization boundary: provider credentials are transient.
export const isProviderVariable = (name) => name.startsWith("ANTHROPIC_")
|| ["CLAUDE_CODE_OAUTH_TOKEN", "OPENAI_API_KEY", "OPENROUTER_API_KEY", "ZAI_API_KEY"].includes(name);
export function sessionEnv(env, run, proxy = null) {
export function sessionEnv(env, run) {
const out = {};
for (const k of ENV_ALLOW) if (env[k] !== undefined && !(proxy && isProviderVariable(k))) out[k] = env[k];
for (const k of ENV_ALLOW) if (env[k] !== undefined) out[k] = env[k];
out.PATH = [join(REPO, "node_modules", ".bin"), env.PATH ?? "/usr/bin:/bin"].join(":");
out.MOSAIC_RUN_ID = run;
return out;
@@ -1,37 +0,0 @@
// P3: catches the named OAuth-leak mutant and reuse of another session's key.
import test from 'node:test';
import assert from 'node:assert/strict';
import { ENV_ALLOW, sessionEnv } from '../src/session.mjs';
const instance = {
HOME: '/fixture-home', USER: 'fixture', PATH: '/usr/bin', LANG: 'C',
CLAUDE_CODE_OAUTH_TOKEN: 'fx332-oauth', ANTHROPIC_API_KEY: 'fx332-anthropic',
ANTHROPIC_AUTH_TOKEN: 'fx332-auth', ANTHROPIC_BASE_URL: 'http://upstream.invalid',
OPENAI_API_KEY: 'fx332-openai', OPENROUTER_API_KEY: 'fx332-router', ZAI_API_KEY: 'fx332-zai',
MOSAIC_CLAUDE_BIN: '/fixture/claude', GITEA_TOKEN: 'fx332-gitea',
};
const forbidden = ['CLAUDE_CODE_OAUTH_TOKEN', 'ANTHROPIC_API_KEY', 'ANTHROPIC_AUTH_TOKEN',
'ANTHROPIC_BASE_URL', 'OPENAI_API_KEY', 'OPENROUTER_API_KEY', 'ZAI_API_KEY'];
test('P3 proxy sessionEnv removes every instance provider credential without widening ENV_ALLOW', () => {
const original = [...ENV_ALLOW];
const env = sessionEnv(instance, 'r332a', { baseUrl: 'http://127.0.0.1:12345', key: 'fx332-agent-a' });
for (const name of forbidden) assert.equal(Object.hasOwn(env, name), false, name);
assert.equal(env.USER, 'fixture');
assert.equal(env.MOSAIC_CLAUDE_BIN, '/fixture/claude');
assert.equal(Object.hasOwn(env, 'GITEA_TOKEN'), false);
assert.equal(env.MOSAIC_RUN_ID, 'r332a');
assert.deepEqual([...ENV_ALLOW], original);
});
test('P3 no proxy retains the full existing allowlist and run environment', () => {
const env = sessionEnv(instance, 'r332b');
assert.deepEqual(env, {
HOME: '/fixture-home', USER: 'fixture', LANG: 'C',
CLAUDE_CODE_OAUTH_TOKEN: 'fx332-oauth', ANTHROPIC_API_KEY: 'fx332-anthropic',
ANTHROPIC_AUTH_TOKEN: 'fx332-auth', ANTHROPIC_BASE_URL: 'http://upstream.invalid',
OPENAI_API_KEY: 'fx332-openai', OPENROUTER_API_KEY: 'fx332-router', ZAI_API_KEY: 'fx332-zai',
MOSAIC_CLAUDE_BIN: '/fixture/claude', PATH: env.PATH, MOSAIC_RUN_ID: 'r332b',
});
assert.ok(env.PATH.endsWith('node_modules/.bin:/usr/bin'));
});