Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd5720662e | ||
|
|
78b69e1e68 | ||
|
|
48b89db33b | ||
|
|
7c8dc20335 |
No files matched your search
@@ -5583,3 +5583,9 @@ 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-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/.
|
||||
|
||||
2026-10-25 — Rockerduck row334 (#1832), before: Case 2 renders bus/Console only. Plan: reuse P1 proxy template/runner under --proxy, enforce three-unit re-install checks and proxy→bus→Console starts, cover refusals and both named mutants. Tests held for Sage CLEAR; design in agents/rockerduck/work/queue-334/BUILD.md.
|
||||
|
||||
2026-10-25 — Rockerduck row334 (#1832), RED evidence: whole case2-unit.test.mjs against baseline has 48 pass/33 expected new fail; whole case2-install.test.mjs has 27 pass/1 expected new fail. All 74 older tests pass. Implementations restored. Sage sage-4390 authorizes seat-branch candidate commit/push before GREEN; GREEN/mutants held until separate CLEAR after row331. Per-failure evidence: agents/rockerduck/work/queue-334/red-results.txt.
|
||||
@@ -0,0 +1,102 @@
|
||||
# Row 334 — Case 2 proxy unit (#1832)
|
||||
|
||||
## Design at 78b69e1e6 (2026-10-25)
|
||||
|
||||
Scope: mos-1616 ruling 1, P1 item 7 only. No template, runner, PIN,
|
||||
user-unit path, config/secret access, or live unit changes.
|
||||
|
||||
Current references: case2-unit.sh template seams 44-45, defaults 54-57,
|
||||
render 435, check_unit 489, render checks 548-551, re-install 553-573,
|
||||
active-state capture 576-580, writes/start/report 583-610.
|
||||
case2-install.sh Next: 231. P1 instance.sh PROXY_UNIT 86;
|
||||
bus-service.sh dependency insertion 93. P1 template ExecStart 13;
|
||||
run.mjs validates config 11-13 and calls startVerifiedProxy 14;
|
||||
runner.mjs refuses proxy-not-configured 8, verifyInstall 9;
|
||||
settings.mjs verifyInstall 23-30 refuses proxy-install-invalid for a hash
|
||||
mismatch. run.mjs catches that and exits 3. P1 item 7 is rows doc 86-90;
|
||||
row209 entry check 2 remains 32-36.
|
||||
|
||||
Add bare --proxy and CASE2_PROXY_TEMPLATE. Render P1's unmodified template
|
||||
with copy, PATH, node and deleted CONFIG_ENV; add User/Group plus bus's four
|
||||
hardening lines, no capabilities or EnvironmentFile. check_unit proxy uses
|
||||
exact node + copy/packages/model-proxy/src/run.mjs, NoNewPrivileges=yes,
|
||||
and every common refusal. Restrict CLAUDE_ENV expectation and capabilities
|
||||
to their existing bus/webui kinds. Insert bus Wants/After immediately after
|
||||
Description exactly as P1 does, only with --proxy. No-proxy output remains
|
||||
byte identical.
|
||||
|
||||
Re-install checks all selected units against render modulo copy id and
|
||||
compares every installed copy id. Existing proxy without --proxy refuses
|
||||
before writes, including a dangling symlink. No deletion. Enable all
|
||||
selected units, then start proxy, bus, Console. Capture/report already-running
|
||||
proxy with the others and name all three in restart-together guidance.
|
||||
Change only case2-install.sh's closing Next: to tell root to add --proxy
|
||||
when the config has a proxy section.
|
||||
|
||||
Tests first, unrun until Sage CLEAR: byte-identical non-proxy renders;
|
||||
proxy content and exact dependencies; each common/proxy check_unit refusal
|
||||
by message; rendered ExecStart wrong-PIN refusal proxy-install-invalid rc 3;
|
||||
three-unit re-install and mixed copies including proxy-only mismatch;
|
||||
installed proxy without flag preserves files; start order and failures;
|
||||
already-running report; install Next: guidance. Named mutants: remove bus
|
||||
After=; direct binary ExecStart bypassing run.mjs. Whole-file run list will
|
||||
be derived from static imports before any run; case1-accept stays off.
|
||||
|
||||
P2 is not present on this base (row331 still in progress); inspect landed
|
||||
P2 refusal code before final handoff. No flag/config false-positive check:
|
||||
P1 startVerifiedProxy refuses proxy-not-configured, run.mjs exits 3.
|
||||
|
||||
## Slot / session
|
||||
|
||||
No tests run. CLEAR pending from Sage. Canonical queue start initially
|
||||
refused: lock held by magica-331-start since 03:57:01.839Z. Same operation
|
||||
will be retried after a minute; no lock manipulation.
|
||||
|
||||
Correction to line references above: row209 entry check 2 is 29-33;
|
||||
run.mjs config validation 8-10, runner call 11, refusal exit status 18.
|
||||
case2-unit.sh is byte-identical to brief base 58b2bbb3a (sha256
|
||||
4ca8769134d83ee391bcc73af5bd042b9e2b161cac22821d29fcca710a9afad4).
|
||||
P1 paths named above have no diff between 86cb5c221 and 78b69e1e6.
|
||||
Own-worktree root npm ci --ignore-scripts --no-audit --no-fund: rc 0,
|
||||
128 packages. No tests invoked.
|
||||
|
||||
Sage sage-4346 accepts design, authorizes writing RED tests then code while
|
||||
holding all runs until CLEAR. Tests were written first, then implementation;
|
||||
no RED run has occurred. Installed proxy without --proxy explicitly refuses
|
||||
and preserves bytes; dangling symlink also refuses, never deletes. P2 code
|
||||
remains pending until row331 lands. Both wrong-flag P1 runner paths covered.
|
||||
|
||||
Import-manifest correction: expanded traversal to include multiline import
|
||||
and export-from edges (the business/library barrel modules). Closure is
|
||||
53 local modules; only the same two test entrypoints occur. The run list
|
||||
is unchanged; this is source inspection, no tests executed.
|
||||
|
||||
Queue start completed: rockerduck-334-start rev4079, row334
|
||||
briefed→in-progress. git diff --check passed. Implementation, tests and
|
||||
import manifest prepared; no tests, commits or pushes performed. Verification
|
||||
awaits Sage's CLEAR; no live host/instance access occurred.
|
||||
|
||||
## RED run authorized by sage-4387, 2026-10-25 04:21Z
|
||||
|
||||
Whole files, sequential, with each corresponding script temporarily restored
|
||||
from 78b69e1e6 and its implementation restored by EXIT trap afterwards:
|
||||
- case2-unit.test.mjs: rc1, 81 tests, 48 pass, 33 fail, 0 skips;
|
||||
TMPDIR=/mnt/storage/scratch/tmp/QD3vp5, nice=19, 77995.928687 ms.
|
||||
All 47 old tests pass; new no-proxy byte equality passes. 32 new failures
|
||||
encounter baseline unsupported --proxy usage rc4; dangling installed proxy
|
||||
symlink case gets rc0 rather than refusal because baseline ignores it.
|
||||
- case2-install.test.mjs: rc1, 28 tests, 27 pass, 1 fail, 0 skips;
|
||||
TMPDIR=/mnt/storage/scratch/tmp/YAGfKJ, nice=19, 10016.247032 ms.
|
||||
All old tests pass. New Next: guidance assertion fails because baseline
|
||||
lacks add --proxy when the config has a proxy section.
|
||||
|
||||
Every failure and cause is listed in red-results.txt; full plain-text
|
||||
outputs in red-unit.log and red-install.log. Absolute node/test paths used.
|
||||
Implementation restored, git diff --check clean. No old-test red, rerun,
|
||||
assertion change, GREEN or mutant run. P2 check still pending row331.
|
||||
Slot returned to Sage; GREEN and mutants await separate CLEAR.
|
||||
|
||||
Sage sage-4390 accepts clean RED and explicitly authorizes committing and
|
||||
pushing this candidate to rockerduck/row334 before GREEN. No force push.
|
||||
GREEN and mutants remain held for a separate CLEAR after row331 lands;
|
||||
then rebase onto landed P2 and check its missing-flag refusal code.
|
||||
@@ -0,0 +1,69 @@
|
||||
# Row334 whole-file run list (UNRUN; awaiting CLEAR)
|
||||
|
||||
Entrypoints are the brief-owned tests, which spawn the changed shell scripts.
|
||||
Their import graph is recorded below; no imported module is itself a test entrypoint.
|
||||
case1-accept.test.mjs is excluded (mos-1612).
|
||||
|
||||
packages/cli/tests/case2-unit.test.mjs -> packages/business/tests/helpers.mjs, packages/seat/src/sandbox.mjs, packages/cli/tests/helpers.mjs, packages/cli/tests/case-sudo-fixture.mjs
|
||||
packages/business/tests/helpers.mjs -> (builtins/external only)
|
||||
packages/seat/src/sandbox.mjs -> packages/business/src/vocabulary.mjs
|
||||
packages/business/src/vocabulary.mjs -> (builtins/external only)
|
||||
packages/cli/tests/helpers.mjs -> packages/bus/src/broker.mjs, packages/bus/src/store.mjs, packages/business/tests/helpers.mjs, packages/harness/tests/helpers.mjs, packages/plugins/tests/helpers.mjs, packages/cli/src/transport.mjs
|
||||
packages/bus/src/broker.mjs -> packages/bus/src/address.mjs, packages/processing-control/src/state.mjs, packages/plugins/src/kinds.mjs, packages/tasks/src/requirements.mjs, packages/bus/src/landing.mjs, packages/business/src/vocabulary.mjs
|
||||
packages/bus/src/address.mjs -> (builtins/external only)
|
||||
packages/processing-control/src/state.mjs -> (builtins/external only)
|
||||
packages/plugins/src/kinds.mjs -> (builtins/external only)
|
||||
packages/tasks/src/requirements.mjs -> (builtins/external only)
|
||||
packages/bus/src/landing.mjs -> (builtins/external only)
|
||||
packages/bus/src/store.mjs -> (builtins/external only)
|
||||
packages/harness/tests/helpers.mjs -> packages/business/src/index.mjs, packages/business/tests/helpers.mjs, packages/plugins/src/loader.mjs
|
||||
packages/business/src/index.mjs -> packages/business/src/errors.mjs, packages/business/src/vocabulary.mjs, packages/business/src/role.mjs, packages/business/src/vars.mjs, packages/business/src/credentials.mjs, packages/business/src/business.mjs, packages/business/src/access.mjs, packages/business/src/project.mjs, packages/business/src/resolve.mjs, packages/business/src/library-seats.mjs
|
||||
packages/business/src/errors.mjs -> (builtins/external only)
|
||||
packages/business/src/role.mjs -> packages/business/src/errors.mjs, packages/business/src/vocabulary.mjs, packages/business/src/util.mjs
|
||||
packages/business/src/util.mjs -> packages/business/src/errors.mjs, packages/business/src/vocabulary.mjs
|
||||
packages/business/src/vars.mjs -> packages/business/src/errors.mjs, packages/business/src/vocabulary.mjs, packages/business/src/util.mjs, packages/plugins/src/kinds.mjs
|
||||
packages/business/src/credentials.mjs -> packages/business/src/errors.mjs, packages/business/src/vocabulary.mjs, packages/business/src/util.mjs
|
||||
packages/business/src/business.mjs -> packages/business/src/errors.mjs, packages/business/src/launch.mjs, packages/business/src/vars.mjs, packages/business/src/credentials.mjs, packages/business/src/role.mjs, packages/business/src/vocabulary.mjs, packages/plugins/src/kinds.mjs, packages/library/src/mapping.mjs, packages/business/src/util.mjs
|
||||
packages/business/src/launch.mjs -> packages/business/src/util.mjs, packages/business/src/errors.mjs
|
||||
packages/library/src/mapping.mjs -> packages/library/src/problems.mjs
|
||||
packages/library/src/problems.mjs -> (builtins/external only)
|
||||
packages/business/src/access.mjs -> packages/business/src/errors.mjs, packages/business/src/business.mjs, packages/business/src/util.mjs, packages/business/src/vocabulary.mjs
|
||||
packages/business/src/project.mjs -> packages/business/src/errors.mjs, packages/business/src/vars.mjs, packages/business/src/util.mjs
|
||||
packages/business/src/resolve.mjs -> packages/business/src/errors.mjs, packages/business/src/vocabulary.mjs, packages/business/src/vars.mjs, packages/business/src/util.mjs, packages/business/src/project.mjs
|
||||
packages/business/src/library-seats.mjs -> packages/business/src/errors.mjs, packages/business/src/business.mjs, packages/business/src/vocabulary.mjs
|
||||
packages/plugins/src/loader.mjs -> packages/plugins/src/kinds.mjs
|
||||
packages/plugins/tests/helpers.mjs -> (builtins/external only)
|
||||
packages/cli/src/transport.mjs -> packages/cli/src/errors.mjs
|
||||
packages/cli/src/errors.mjs -> (builtins/external only)
|
||||
packages/cli/tests/case-sudo-fixture.mjs -> (builtins/external only)
|
||||
packages/cli/tests/case2-install.test.mjs -> packages/business/tests/helpers.mjs, packages/library/tests/helpers.mjs, packages/library/src/index.mjs, packages/seat/src/checkout.mjs, packages/project/src/git.mjs, packages/cli/tests/helpers.mjs
|
||||
packages/library/tests/helpers.mjs -> packages/library/src/mapping.mjs
|
||||
packages/library/src/index.mjs -> packages/library/src/problems.mjs, packages/library/src/mapping.mjs, packages/library/src/scope.mjs, packages/library/src/supporting.mjs, packages/library/src/links.mjs, packages/library/src/reader.mjs, packages/library/src/render.mjs, packages/library/src/survey.mjs, packages/library/src/mirror.mjs, packages/library/src/sync.mjs, packages/library/src/index-build.mjs, packages/library/src/query.mjs, packages/library/src/limits.mjs, packages/library/src/guard.mjs
|
||||
packages/library/src/scope.mjs -> (builtins/external only)
|
||||
packages/library/src/supporting.mjs -> packages/library/src/problems.mjs, packages/library/src/scope.mjs
|
||||
packages/library/src/links.mjs -> (builtins/external only)
|
||||
packages/library/src/reader.mjs -> packages/project/src/git.mjs, packages/library/src/scope.mjs, packages/library/src/links.mjs, packages/library/src/problems.mjs
|
||||
packages/project/src/git.mjs -> packages/seat/src/checkout.mjs, packages/project/src/paths.mjs, packages/processing-control/src/effects.mjs
|
||||
packages/seat/src/checkout.mjs -> packages/processing-control/src/effects.mjs
|
||||
packages/processing-control/src/effects.mjs -> packages/processing-control/src/state.mjs, packages/processing-control/src/runtimes.mjs
|
||||
packages/processing-control/src/runtimes.mjs -> packages/processing-control/src/state.mjs
|
||||
packages/project/src/paths.mjs -> (builtins/external only)
|
||||
packages/library/src/render.mjs -> (builtins/external only)
|
||||
packages/library/src/survey.mjs -> packages/library/src/mapping.mjs, packages/library/src/scope.mjs, packages/library/src/links.mjs, packages/library/src/reader.mjs, packages/library/src/problems.mjs
|
||||
packages/library/src/mirror.mjs -> packages/project/src/paths.mjs, packages/project/src/git.mjs, packages/library/src/mapping.mjs, packages/library/src/scope.mjs, packages/library/src/problems.mjs, packages/library/src/reader.mjs
|
||||
packages/library/src/sync.mjs -> packages/seat/src/checkout.mjs, packages/project/src/git.mjs, packages/library/src/mapping.mjs, packages/library/src/problems.mjs, packages/library/src/reader.mjs, packages/library/src/mirror.mjs
|
||||
packages/library/src/index-build.mjs -> packages/library/src/reader.mjs, packages/library/src/problems.mjs
|
||||
packages/library/src/query.mjs -> packages/library/src/problems.mjs, packages/library/src/mapping.mjs, packages/library/src/index-build.mjs, packages/library/src/reader.mjs
|
||||
packages/library/src/limits.mjs -> (builtins/external only)
|
||||
packages/library/src/guard.mjs -> packages/project/src/git.mjs, packages/library/src/scope.mjs, packages/library/src/reader.mjs, packages/library/src/problems.mjs, packages/library/src/mirror.mjs, packages/library/src/limits.mjs, packages/library/src/reply-protocol.mjs
|
||||
packages/library/src/reply-protocol.mjs -> (builtins/external only)
|
||||
|
||||
Whole-file commands after CLEAR (one fresh shell-mktemp TMPDIR each; nice=19):
|
||||
node --test packages/cli/tests/case2-unit.test.mjs
|
||||
node --test packages/cli/tests/case2-install.test.mjs
|
||||
|
||||
Before these: new row334 tests only on saved 78b69e1e6 scripts for RED,
|
||||
then restored implementation. After GREEN: named mutants individually,
|
||||
each with its directly relevant row334 test. No scripts/test-*.sh builder run planned.
|
||||
|
||||
Includes multiline imports and export-from module edges: 53 local modules.
|
||||
@@ -0,0 +1,68 @@
|
||||
TMPDIR=/mnt/storage/scratch/tmp/YAGfKJ nice=19
|
||||
✔ the library install writes the business file, personas and slot dir, makes the copy and starts nothing (386.113555ms)
|
||||
✔ a library re-run passes and leaves every file as it was (496.225906ms)
|
||||
✔ a re-run refuses business-file-differs and leaves the file unchanged (376.395513ms)
|
||||
✔ a re-run refuses persona-differs when an installed persona isn't the staged one, and writes nothing (398.216221ms)
|
||||
✔ the factory install writes no library mapping, persona or slot dir (247.905208ms)
|
||||
✔ the factory install refuses a library project and bus.tester off, before anything is written (105.176208ms)
|
||||
✔ the library install refuses bus.tester on and a persona var in the input (104.503599ms)
|
||||
✔ the install refuses root, a business id mismatch, another --home and a config dir with group bits (80.144703ms)
|
||||
✔ the library install needs --personas (7.831929ms)
|
||||
✔ a validate refusal removes the business file this run wrote (311.701322ms)
|
||||
✔ N4: a validate refusal on a re-run leaves the matching business file in place, byte for byte (537.848604ms)
|
||||
✔ a clean library host passes the precheck with no mirror yet (509.009214ms)
|
||||
✔ the library precheck refuses a persona file at 0644 (506.697677ms)
|
||||
✔ the library precheck refuses a persona whose digest isn't persona.sha256 (495.113108ms)
|
||||
✔ the library precheck refuses a persona dir with group bits (481.900638ms)
|
||||
✔ the library precheck refuses a business file at 0644 (462.626038ms)
|
||||
✔ the library precheck refuses a changes.jsonl at 0644 (687.490332ms)
|
||||
✔ the library precheck refuses a Discord binding (499.568905ms)
|
||||
✔ --library-status refuses library-mirror-missing before the bus has made the mirror (377.717622ms)
|
||||
✔ --library-status refuses library-never-synced on a fresh mirror (410.956236ms)
|
||||
✔ --library-status names a recorded lastError before the null lastFetch it leaves (N3) (417.888767ms)
|
||||
✔ --library-status prints each R-problem's path as an escaped JSON string, then the count, and passes (481.141014ms)
|
||||
✔ --library-status takes no --profile (6.246241ms)
|
||||
✔ Vikunja 614: install preserves the explicit notifier decision bytes and mode and creates none when absent (560.431267ms)
|
||||
✔ row 322 F8: library personas install from the copy with no clone node_modules (183.399079ms)
|
||||
✔ row 322 F9: importer refusal keeps the error line rather than the Node banner (118.731885ms)
|
||||
✔ C2-21: library install supplies chief identity and books publish for its real read grant (330.48101ms)
|
||||
✖ row334 install Next tells root to select proxy only when configured (302.965779ms)
|
||||
ℹ tests 28
|
||||
ℹ suites 0
|
||||
ℹ pass 27
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 10016.247032
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/cli/tests/case2-install.test.mjs:495:1
|
||||
✖ row334 install Next tells root to select proxy only when configured (302.965779ms)
|
||||
AssertionError [ERR_ASSERTION]: The input did not match the regular expression /Next: root runs case2-unit.sh[^\n]+add --proxy when the config has a proxy section/. Input:
|
||||
|
||||
'case2-install: config /mnt/storage/scratch/tmp/YAGfKJ/case2-install-lXA9Qd/home/.config/mosaic-dev/config.json\n' +
|
||||
'case2-install: copy /mnt/storage/scratch/tmp/YAGfKJ/case2-install-lXA9Qd/home/.local/share/mosaic-stack/copies/cccccccccccccccccccccccccccccccccccccccc\n' +
|
||||
'case2-install: personas installed under /mnt/storage/scratch/tmp/YAGfKJ/case2-install-lXA9Qd/home/.config/mosaic-dev/personas/acme\n' +
|
||||
'case2-install: business file /mnt/storage/scratch/tmp/YAGfKJ/case2-install-lXA9Qd/home/.config/mosaic-dev/businesses/acme.json written\n' +
|
||||
'case2-install: slot dir /mnt/storage/scratch/tmp/YAGfKJ/case2-install-lXA9Qd/home/.config/mosaic-dev/secrets/acme\n' +
|
||||
'case2-install: business acme validates\n' +
|
||||
'case2-install: done. Next: root runs case2-unit.sh --copy cccccccccccccccccccccccccccccccccccccccc --business acme (design 10 step 2c), then 2d and 3.\n' +
|
||||
'case2-install: Then Jason places the library token in /mnt/storage/scratch/tmp/YAGfKJ/case2-install-lXA9Qd/home/.config/mosaic-dev/secrets/acme (step 4), and <user> runs case2-precheck.sh --business acme --library-status (step 4a).\n'
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-install.test.mjs:498: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 process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 'case2-install: config /mnt/storage/scratch/tmp/YAGfKJ/case2-install-lXA9Qd/home/.config/mosaic-dev/config.json\ncase2-install: copy /mnt/storage/scratch/tmp/YAGfKJ/case2-install-lXA9Qd/home/.local/share/mosaic-stack/copies/cccccccccccccccccccccccccccccccccccccccc\ncase2-install: personas installed under /mnt/storage/scratch/tmp/YAGfKJ/case2-install-lXA9Qd/home/.config/mosaic-dev/personas/acme\ncase2-install: business file /mnt/storage/scratch/tmp/YAGfKJ/case2-install-lXA9Qd/home/.config/mosaic-dev/businesses/acme.json written\ncase2-install: slot dir /mnt/storage/scratch/tmp/YAGfKJ/case2-install-lXA9Qd/home/.config/mosaic-dev/secrets/acme\ncase2-install: business acme validates\ncase2-install: done. Next: root runs case2-unit.sh --copy cccccccccccccccccccccccccccccccccccccccc --business acme (design 10 step 2c), then 2d and 3.\ncase2-install: Then Jason places the library token in /mnt/storage/scratch/tmp/YAGfKJ/case2-install-lXA9Qd/home/.config/mosaic-dev/secrets/acme (step 4), and <user> runs case2-precheck.sh --business acme --library-status (step 4a).\n',
|
||||
expected: /Next: root runs case2-unit.sh[^\n]+add --proxy when the config has a proxy section/,
|
||||
operator: 'match',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
# RED results — sage-4387 (2026-10-25)
|
||||
|
||||
Baseline scripts: 78b69e1e6. Current row334 tests. Whole files, sequential.
|
||||
Both implementation scripts restored via EXIT traps after their run.
|
||||
No GREEN or mutant run. No old-test failure. No assertion changed.
|
||||
|
||||
case2-unit.test.mjs: exit 1; 81 tests, 48 pass, 33 fail, 0 skip.
|
||||
47 existing tests plus new byte-identical no-proxy test pass.
|
||||
TMPDIR=/mnt/storage/scratch/tmp/QD3vp5; nice=19; duration 77995.928687 ms.
|
||||
|
||||
Every unit failure and its observed reason:
|
||||
- row334 proxy uses P1 runner, bus dependencies and proxy bus Console start order: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy refuses continuation by message before writing: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy refuses not-setting by message before writing: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy refuses RestrictNamespaces by message before writing: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy refuses PrivateUsers by message before writing: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy refuses SystemCallFilter by message before writing: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy refuses PermissionsStartOnly by message before writing: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy refuses EnvironmentFile by message before writing: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy refuses AmbientCapabilities by message before writing: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy refuses CapabilityBoundingSet by message before writing: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy refuses privileged by message before writing: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy refuses direct-binary by message before writing: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy refuses nnp by message before writing: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy refuses cwd by message before writing: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy refuses environment by message before writing: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy refuses install by message before writing: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy refuses user by message before writing: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy refuses group by message before writing: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy refuses ProtectSystem by message before writing: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy refuses ReadWritePaths by message before writing: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy refuses ProtectHome by message before writing: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy refuses PrivateTmp by message before writing: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy refuses token by message before writing: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy template missing or symlink refuses: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 rendered ExecStart refuses wrong PIN and missing proxy with P1 status: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 reinstall repins all three and refuses a proxy copy mismatch: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 installed proxy without --proxy refuses and preserves all bytes: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 dangling proxy symlink without flag refuses without deleting: baseline ignores installed proxy symlink without flag, returns 0 instead of refusal 1.
|
||||
- row334 active proxy reports old copy and all three must restart together: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 failed mosaic-proxy.service start leaves later units unstarted: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 failed [email protected] start leaves later units unstarted: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 installed proxy enforces hardening order and remaining common refusals: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
- row334 proxy installed path rejects symlink and non-regular file: baseline does not parse --proxy: usage exit 4, before the proxy-specific assertion/setup can be reached.
|
||||
|
||||
case2-install.test.mjs: exit 1; 28 tests, 27 pass, 1 fail, 0 skip.
|
||||
TMPDIR=/mnt/storage/scratch/tmp/YAGfKJ; nice=19; duration 10016.247032 ms.
|
||||
- row334 install Next tells root to select proxy only when configured: baseline Next: lacks add --proxy when the config has a proxy section.
|
||||
|
||||
Commands used absolute /usr/bin/node --test and absolute test-file paths.
|
||||
Full plain-text outputs: red-unit.log and red-install.log beside this file.
|
||||
P2 refusal-code check remains pending row331. Slot returned to Sage.
|
||||
@@ -0,0 +1,873 @@
|
||||
TMPDIR=/mnt/storage/scratch/tmp/QD3vp5 nice=19
|
||||
✔ row253 factory socket uses actual config and target-uid query without widening hardening (351.144059ms)
|
||||
✔ row253 installer refuses unsafe location and query facts before unit writes (3621.94316ms)
|
||||
✔ row253 query timeout kills its process group and leaves no running child (7054.318085ms)
|
||||
✔ row253 protected homes refuse before any filesystem access (9.291102ms)
|
||||
✔ row253 C4 sleep query has exact inner reason and cleans all members (10796.380077ms)
|
||||
✔ row253 C4 signals query has exact inner reason and cleans all members (10819.227773ms)
|
||||
✔ row253 C4 member query has exact inner reason and cleans all members (10897.328548ms)
|
||||
✔ row253 C4 overflow is output-limit in both sudo modes (554.12811ms)
|
||||
✔ row253 C4 stalled supervisor uses the outer reason and explicit residual cleanup (14201.797743ms)
|
||||
✔ row253 C4 inline supervisor is byte-identical in both host scripts (0.888234ms)
|
||||
✔ row253 C4 cleanup budget starts after inventory pass one (46.615614ms)
|
||||
✔ row253 query reaps its group even when a child closes stdout before the query returns (152.118314ms)
|
||||
✔ row253 config parser is strict (11.560624ms)
|
||||
✔ a clean library render writes both units 0644 with the fixed lines, and enables both then starts the bus then the Console (120.676804ms)
|
||||
✔ PATH starts with the --node directory, for a node outside the default list and for /usr/bin/node (131.630623ms)
|
||||
✔ a failed bus start refuses with the Console not started (123.177864ms)
|
||||
✔ the script never links a unit file (0.18683ms)
|
||||
✔ factory renders --pm once and one MOSAIC_CLAUDE_BIN line, and without them both tokens render empty (746.075081ms)
|
||||
✔ a re-install over running units says they are still on the old copy and must restart together, never that it started them (494.63679ms)
|
||||
✔ a re-install to another copy re-renders both units, and an edited installed unit refuses (1175.719345ms)
|
||||
✔ a template with a namespace, user or system call restriction refuses (335.625113ms)
|
||||
✔ the bus template's EnvironmentFile line must be there and point at the session env, and the Console template must have none (214.600182ms)
|
||||
✔ a template holding an unknown token, PermissionsStartOnly or a privileged Exec prefix refuses (151.081813ms)
|
||||
✔ a symlink at either unit path refuses (203.555513ms)
|
||||
✔ a --node that is relative, not root-owned or under <home> refuses (27.297759ms)
|
||||
✔ a re-install with a different --node or different serve flags refuses (599.873393ms)
|
||||
✔ an installed pair whose units name different copies refuses (328.321083ms)
|
||||
✔ a copy id that is short, uppercase, holds / or .., or names no directory refuses (46.028703ms)
|
||||
✔ library refuses a privileged-floor miss, a bad proof pair and every flag outside its set (344.833107ms)
|
||||
✔ library refuses a proof file not owned by <user>'s uid (18.013172ms)
|
||||
✔ factory refuses duplicate socket, a missing --port or --business, and each proxy flag (209.757808ms)
|
||||
✔ row253 factory refuses retired TCP and a value after the socket marker (59.218628ms)
|
||||
✔ factory refuses a --claude that is relative, not root-owned or under <home>, and a re-install with another --pm or --claude (1686.680735ms)
|
||||
✔ the precheck passes on a good host and prints free memory, without the key (226.963557ms)
|
||||
✔ the precheck refuses each failed host check (1765.731095ms)
|
||||
✔ the precheck refuses a user missing from passwd, a business file that does not load, and a symlinked run root (927.260864ms)
|
||||
✔ a bwrap that fails refuses and prints the sysctl and where bwrap is (200.731617ms)
|
||||
✔ an unprivileged port floor at or below the Console's port refuses, and so does a missing Console unit (1055.360802ms)
|
||||
✔ bus.tester: library refuses it on, factory needs it on, and factory refuses a library business (927.574539ms)
|
||||
✔ the claude check runs only for a claude-code instance, and refuses a claude that appends or answers wrong (1694.074713ms)
|
||||
✔ the claude check runs the bus unit's MOSAIC_CLAUDE_BIN over claude on PATH (498.707509ms)
|
||||
✔ the session env file refuses when missing, open to others, a symlink, empty, or emptied by a later line (1155.959127ms)
|
||||
✔ inside a session's sandbox a bind below 1024 fails with EACCES, and a bind on a free high port succeeds (106.466066ms)
|
||||
✔ Vikunja 614 factory: scoped @anthropic-ai Claude path renders and passes installed read-back (1024.721235ms)
|
||||
✔ Vikunja 614 factory: plain paths still refuse every named unsafe character (117.946806ms)
|
||||
✔ Vikunja 614 precheck: explicit null and named notifier decisions pass (384.090317ms)
|
||||
✔ Vikunja 614 precheck: notifier config refuses missing, public, malformed and extra-key decisions (1596.303308ms)
|
||||
✔ row334 no-proxy renders stay byte-identical to the pre-row renderer (316.417263ms)
|
||||
✖ row334 proxy uses P1 runner, bus dependencies and proxy bus Console start order (6.436602ms)
|
||||
✖ row334 proxy refuses continuation by message before writing (6.291734ms)
|
||||
✖ row334 proxy refuses not-setting by message before writing (5.588449ms)
|
||||
✖ row334 proxy refuses RestrictNamespaces by message before writing (5.71389ms)
|
||||
✖ row334 proxy refuses PrivateUsers by message before writing (5.34285ms)
|
||||
✖ row334 proxy refuses SystemCallFilter by message before writing (5.400994ms)
|
||||
✖ row334 proxy refuses PermissionsStartOnly by message before writing (5.443023ms)
|
||||
✖ row334 proxy refuses EnvironmentFile by message before writing (5.052075ms)
|
||||
✖ row334 proxy refuses AmbientCapabilities by message before writing (5.027453ms)
|
||||
✖ row334 proxy refuses CapabilityBoundingSet by message before writing (5.604853ms)
|
||||
✖ row334 proxy refuses privileged by message before writing (5.176325ms)
|
||||
✖ row334 proxy refuses direct-binary by message before writing (5.301058ms)
|
||||
✖ row334 proxy refuses nnp by message before writing (4.978268ms)
|
||||
✖ row334 proxy refuses cwd by message before writing (4.903056ms)
|
||||
✖ row334 proxy refuses environment by message before writing (4.928207ms)
|
||||
✖ row334 proxy refuses install by message before writing (4.935225ms)
|
||||
✖ row334 proxy refuses user by message before writing (4.996881ms)
|
||||
✖ row334 proxy refuses group by message before writing (4.740792ms)
|
||||
✖ row334 proxy refuses ProtectSystem by message before writing (7.412574ms)
|
||||
✖ row334 proxy refuses ReadWritePaths by message before writing (5.039647ms)
|
||||
✖ row334 proxy refuses ProtectHome by message before writing (4.948113ms)
|
||||
✖ row334 proxy refuses PrivateTmp by message before writing (5.049564ms)
|
||||
✖ row334 proxy refuses token by message before writing (5.291145ms)
|
||||
✖ row334 proxy template missing or symlink refuses (4.77612ms)
|
||||
✖ row334 rendered ExecStart refuses wrong PIN and missing proxy with P1 status (5.907949ms)
|
||||
✖ row334 reinstall repins all three and refuses a proxy copy mismatch (5.706372ms)
|
||||
✖ row334 installed proxy without --proxy refuses and preserves all bytes (4.919106ms)
|
||||
✖ row334 dangling proxy symlink without flag refuses without deleting (127.81539ms)
|
||||
✖ row334 active proxy reports old copy and all three must restart together (5.181396ms)
|
||||
✖ row334 failed mosaic-proxy.service start leaves later units unstarted (4.827066ms)
|
||||
✖ row334 failed [email protected] start leaves later units unstarted (4.558348ms)
|
||||
✖ row334 installed proxy enforces hardening order and remaining common refusals (5.170683ms)
|
||||
✖ row334 proxy installed path rejects symlink and non-regular file (4.685001ms)
|
||||
ℹ tests 81
|
||||
ℹ suites 0
|
||||
ℹ pass 48
|
||||
ℹ fail 33
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 77995.928687
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:966:1
|
||||
✖ row334 proxy uses P1 runner, bus dependencies and proxy bus Console start order (6.436602ms)
|
||||
AssertionError [ERR_ASSERTION]: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 0
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:969: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 process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 0,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1004:52
|
||||
✖ row334 proxy refuses continuation by message before writing (6.291734ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1007:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1004:52
|
||||
✖ row334 proxy refuses not-setting by message before writing (5.588449ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1007:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1004:52
|
||||
✖ row334 proxy refuses RestrictNamespaces by message before writing (5.71389ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1007:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1004:52
|
||||
✖ row334 proxy refuses PrivateUsers by message before writing (5.34285ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1007:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1004:52
|
||||
✖ row334 proxy refuses SystemCallFilter by message before writing (5.400994ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1007:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1004:52
|
||||
✖ row334 proxy refuses PermissionsStartOnly by message before writing (5.443023ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1007:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1004:52
|
||||
✖ row334 proxy refuses EnvironmentFile by message before writing (5.052075ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1007:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1004:52
|
||||
✖ row334 proxy refuses AmbientCapabilities by message before writing (5.027453ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1007:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1004:52
|
||||
✖ row334 proxy refuses CapabilityBoundingSet by message before writing (5.604853ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1007:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1004:52
|
||||
✖ row334 proxy refuses privileged by message before writing (5.176325ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1007:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1004:52
|
||||
✖ row334 proxy refuses direct-binary by message before writing (5.301058ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1007:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1004:52
|
||||
✖ row334 proxy refuses nnp by message before writing (4.978268ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1007:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1004:52
|
||||
✖ row334 proxy refuses cwd by message before writing (4.903056ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1007:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1004:52
|
||||
✖ row334 proxy refuses environment by message before writing (4.928207ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1007:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1004:52
|
||||
✖ row334 proxy refuses install by message before writing (4.935225ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1007:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1004:52
|
||||
✖ row334 proxy refuses user by message before writing (4.996881ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1007:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1004:52
|
||||
✖ row334 proxy refuses group by message before writing (4.740792ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1007:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1004:52
|
||||
✖ row334 proxy refuses ProtectSystem by message before writing (7.412574ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1007:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1004:52
|
||||
✖ row334 proxy refuses ReadWritePaths by message before writing (5.039647ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1007:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1004:52
|
||||
✖ row334 proxy refuses ProtectHome by message before writing (4.948113ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1007:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1004:52
|
||||
✖ row334 proxy refuses PrivateTmp by message before writing (5.049564ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1007:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1004:52
|
||||
✖ row334 proxy refuses token by message before writing (5.291145ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1007:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1012:1
|
||||
✖ row334 proxy template missing or symlink refuses (4.77612ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1014:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1019:1
|
||||
✖ row334 rendered ExecStart refuses wrong PIN and missing proxy with P1 status (5.907949ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
4 !== 0
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1021: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 process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 0,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1044:1
|
||||
✖ row334 reinstall repins all three and refuses a proxy copy mismatch (5.706372ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
4 !== 0
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1046: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 process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 0,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1055:1
|
||||
✖ row334 installed proxy without --proxy refuses and preserves all bytes (4.919106ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
4 !== 0
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1057: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 process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 0,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1065:1
|
||||
✖ row334 dangling proxy symlink without flag refuses without deleting (127.81539ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 0: case2-unit: wrote /mnt/storage/scratch/tmp/QD3vp5/case2-unit-h4V4Zn/units/[email protected] and /mnt/storage/scratch/tmp/QD3vp5/case2-unit-h4V4Zn/units/mosaic-webui.service from copy aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; enabled and started [email protected], then mosaic-webui.service
|
||||
|
||||
|
||||
0 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1068:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 0,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1072:1
|
||||
✖ row334 active proxy reports old copy and all three must restart together (5.181396ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
4 !== 0
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1074: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 process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 0,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1080:73
|
||||
✖ row334 failed mosaic-proxy.service start leaves later units unstarted (4.827066ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1082:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1080:73
|
||||
✖ row334 failed [email protected] start leaves later units unstarted (4.558348ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1082:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1088:1
|
||||
✖ row334 installed proxy enforces hardening order and remaining common refusals (5.170683ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
4 !== 0
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1090: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 process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 0,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:1103:1
|
||||
✖ row334 proxy installed path rejects symlink and non-regular file (4.685001ms)
|
||||
AssertionError [ERR_ASSERTION]: expected a refusal, got 4: usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS
|
||||
|
||||
|
||||
4 !== 1
|
||||
|
||||
at refuses (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:292:10)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/rockerduck-row334/packages/cli/tests/case2-unit.test.mjs:1106:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 4,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -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, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
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": []
|
||||
}
|
||||
@@ -1693,3 +1693,7 @@ 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-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.
|
||||
2026-10-25 — rockerduck — row334 (#1832), Case 2 proxy system unit — design/read phase; tests held for Sage CLEAR; queue start lock diagnosed.
|
||||
2026-10-25 — rockerduck — row334 (#1832), Case 2 proxy system unit — queue start rev4079; tests then implementation written, design accepted by Sage; verification held for CLEAR, P2 refusal-code check pending row331.
|
||||
2026-10-25 — rockerduck — row334 RED-only slot sage-4387 — both whole files against pre-change scripts: 74 older tests pass, 34 new expected failures; implementations restored, slot returned; GREEN/mutants held.
|
||||
@@ -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
@@ -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
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -490,3 +490,10 @@ test('C2-21: library install supplies chief identity and books publish for its r
|
||||
assert.ok(doc.roles.chief.identity?.gitea?.user);
|
||||
assert.notEqual(doc.roles.chief.identity?.gitea?.user, 'writer');
|
||||
});
|
||||
|
||||
|
||||
test('row334 install Next tells root to select proxy only when configured', t => {
|
||||
const x = world(t), r = install(x);
|
||||
assert.equal(r.code, 0, r.out);
|
||||
assert.match(r.out, /Next: root runs case2-unit.sh[^\n]+add --proxy when the config has a proxy section/);
|
||||
});
|
||||
@@ -7,10 +7,10 @@ import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { createServer } from "node:net";
|
||||
import { chmodSync, existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, rmSync, statSync, symlinkSync, writeFileSync } from "node:fs";
|
||||
import { chmodSync, cpSync, existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, rmSync, statSync, symlinkSync, writeFileSync } from "node:fs";
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { businessDoc, writeJson } from "../../business/tests/helpers.mjs";
|
||||
import { businessDoc, systemConfig, writeJson } from "../../business/tests/helpers.mjs";
|
||||
import { binds, prepareRun, sandboxArgv, sandboxProblem } from "../../seat/src/sandbox.mjs";
|
||||
import { tmp } from "./helpers.mjs";
|
||||
import { CASE_SUDO_SESSION, recordedLivePids, killRecordedPids, fixtureGuard, cleanupFixture, pollFixtureGone, blockingQuerySource } from "./case-sudo-fixture.mjs";
|
||||
@@ -940,3 +940,171 @@ test("Vikunja 614 precheck: notifier config refuses missing, public, malformed a
|
||||
assert.match(r.out, /REFUSED notifier config:/, `${fault}: ${r.out}`);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Row334: render only into the scratch hub; fake systemctl never touches the host.
|
||||
const PROXY_TEMPLATE = join(REPO, 'packages/cli/systemd/mosaic-proxy.service.in');
|
||||
const proxyFile = h => join(h.units, 'mosaic-proxy.service');
|
||||
const proxyUnit = (h, options = {}) => unit(h, { ...options, extra: ['--proxy', ...(options.extra ?? [])] });
|
||||
|
||||
test('row334 no-proxy renders stay byte-identical to the pre-row renderer', t => {
|
||||
const h = hub(t);
|
||||
// Immutable committed baseline, executed only with the same scratch seams.
|
||||
const baseline = spawnSync('git', ['show', '78b69e1e6:scripts/case2-unit.sh'], { cwd: REPO, encoding: 'utf8' });
|
||||
assert.equal(baseline.status, 0, baseline.stderr);
|
||||
const old = script(join(h.root, 'baseline/scripts/case2-unit.sh'), baseline.stdout);
|
||||
const args = ['--user', 'mosaic', '--home', h.home, '--business', 'acme', '--copy', COPY_A, '--node', USR_NODE, '--', ...libraryFlags(h)];
|
||||
const r = spawnSync(old, args, { encoding: 'utf8', env: { PATH: `${h.bin}:${process.env.PATH}`, CASE2_UNIT_DIR: h.units,
|
||||
CASE2_SYSTEMCTL: join(h.bin, 'systemctl'), CASE2_GETENT: join(h.bin, 'getent'), CASE2_BUS_TEMPLATE: BUS_TEMPLATE, CASE2_WEBUI_TEMPLATE: WEBUI_TEMPLATE } });
|
||||
assert.equal(r.status, 0, r.stderr);
|
||||
const before = [read(busFile(h)), read(webuiFile(h))];
|
||||
assert.equal(unit(h).code, 0);
|
||||
assert.deepEqual([read(busFile(h)), read(webuiFile(h))], before);
|
||||
assert.equal(existsSync(proxyFile(h)), false);
|
||||
});
|
||||
|
||||
test('row334 proxy uses P1 runner, bus dependencies and proxy bus Console start order', t => {
|
||||
const h = hub(t);
|
||||
const r = proxyUnit(h, { profile: 'factory', flags: ['--port', '443', '--business', 'acme'], extra: ['--claude', TRUE_BIN] });
|
||||
assert.equal(r.code, 0, r.err);
|
||||
const proxy = read(proxyFile(h));
|
||||
const expected = read(PROXY_TEMPLATE).replaceAll('@REPO@', copyDir(h)).replaceAll('@PATH@', '/usr/bin:/usr/local/bin:/bin')
|
||||
.replaceAll('@NODE@', USR_NODE).replace(/^@CONFIG_ENV@\n/m, '').replace('WantedBy=default.target', 'WantedBy=multi-user.target')
|
||||
.replace('TimeoutStopSec=60', `TimeoutStopSec=60\nUser=mosaic\nGroup=mosaic\n${HARDENING(h).join('\n')}`);
|
||||
assert.equal(proxy, expected);
|
||||
assert.equal(statSync(proxyFile(h)).mode & 0o777, 0o644);
|
||||
assert.match(read(busFile(h)), /Description=[^\n]+\nWants=mosaic-proxy.service\nAfter=mosaic-proxy.service\n/);
|
||||
assert.deepEqual(lines(proxy, 'ExecStart'), [`${USR_NODE} ${copyDir(h)}/packages/model-proxy/src/run.mjs`]);
|
||||
assert.doesNotMatch(proxy, /EnvironmentFile=|Capabilities=|CapabilityBoundingSet=|MOSAIC_CLAUDE_BIN/);
|
||||
assert.doesNotMatch(read(webuiFile(h)), /Wants=|After=/);
|
||||
assert.deepEqual(read(h.log).trim().split('\n'), [
|
||||
'is-active --quiet mosaic-proxy.service', 'is-active --quiet [email protected]', 'is-active --quiet mosaic-webui.service',
|
||||
'daemon-reload', 'enable mosaic-proxy.service [email protected] mosaic-webui.service',
|
||||
'start mosaic-proxy.service', 'start [email protected]', 'start mosaic-webui.service',
|
||||
]);
|
||||
});
|
||||
|
||||
const proxyRefusals = [
|
||||
['continuation', s => s.replace('Type=simple', 'Type=simple' + String.fromCharCode(92)), /a line continues onto the next/],
|
||||
['not-setting', s => s.replace('Type=simple', 'not a setting'), /neither a section/],
|
||||
...['RestrictNamespaces', 'PrivateUsers', 'SystemCallFilter', 'PermissionsStartOnly', 'EnvironmentFile', 'AmbientCapabilities', 'CapabilityBoundingSet'].map(k =>
|
||||
[k, s => s.replace('Type=simple', `Type=simple\n${k}=yes`), new RegExp(`refusing ${k}=`)]),
|
||||
['privileged', s => s.replace('ExecStart=', 'ExecStart=+'), /Exec line that runs with full privileges/],
|
||||
['direct-binary', s => s.replace('packages/model-proxy/src/run.mjs', 'opt/cli-proxy-api'), /ExecStart= must be exactly once/],
|
||||
['nnp', s => s.replace('NoNewPrivileges=yes', 'NoNewPrivileges=no'), /NoNewPrivileges= must be exactly once/],
|
||||
['cwd', s => s.replace('WorkingDirectory=@REPO@', 'WorkingDirectory=/elsewhere'), /WorkingDirectory= must be exactly once/],
|
||||
['environment', s => s.replace('Environment=PATH=@PATH@', 'Environment=PATH=/elsewhere'), /Environment= lines must be exactly/],
|
||||
['install', s => s.replace('WantedBy=default.target', 'WantedBy=other.target'), /WantedBy= must be exactly once/],
|
||||
['user', s => s.replace('Type=simple', 'Type=simple\nUser=other'), /User= must be exactly once/],
|
||||
['group', s => s.replace('Type=simple', 'Type=simple\nGroup=other'), /Group= must be exactly once/],
|
||||
...['ProtectSystem', 'ReadWritePaths', 'ProtectHome', 'PrivateTmp'].map(k =>
|
||||
[k, s => s.replace('Type=simple', `Type=simple\n${k}=other`), new RegExp(`${k}= must be exactly once`)]),
|
||||
['token', s => s.replace('Type=simple', 'Type=simple\nX-Note=@UNKNOWN@'), /a token is left after the render/],
|
||||
];
|
||||
for (const [name, edit, message] of proxyRefusals) test(`row334 proxy refuses ${name} by message before writing`, t => {
|
||||
const h = hub(t);
|
||||
const file = template(h, PROXY_TEMPLATE, `${name}.in`, edit);
|
||||
refuses(proxyUnit(h, { env: { CASE2_PROXY_TEMPLATE: file } }), message);
|
||||
assert.deepEqual(readdirSync(h.units), []);
|
||||
assert.equal(existsSync(h.log), false);
|
||||
});
|
||||
|
||||
test('row334 proxy template missing or symlink refuses', t => {
|
||||
const h = hub(t), missing = join(h.root, 'missing.in');
|
||||
refuses(proxyUnit(h, { env: { CASE2_PROXY_TEMPLATE: missing } }), /template missing or not a regular file/);
|
||||
symlinkSync(PROXY_TEMPLATE, missing);
|
||||
refuses(proxyUnit(h, { env: { CASE2_PROXY_TEMPLATE: missing } }), /template missing or not a regular file/);
|
||||
});
|
||||
|
||||
test('row334 rendered ExecStart refuses wrong PIN and missing proxy with P1 status', t => {
|
||||
const h = hub(t);
|
||||
assert.equal(proxyUnit(h).code, 0);
|
||||
const copy = copyDir(h);
|
||||
cpSync(join(REPO, 'packages/model-proxy'), join(copy, 'packages/model-proxy'), { recursive: true });
|
||||
cpSync(join(REPO, 'scripts/mosaic-config.mjs'), join(copy, 'scripts/mosaic-config.mjs'));
|
||||
const config = systemConfig(join(h.root, 'runner'));
|
||||
const doc = JSON.parse(read(config));
|
||||
mkdirSync(doc.dataRoot, { recursive: true, mode: 0o700 });
|
||||
const pin = JSON.parse(read(join(REPO, 'packages/model-proxy/PIN')));
|
||||
const binary = join(doc.dataRoot, 'opt/cliproxyapi', pin.version, 'cli-proxy-api');
|
||||
script(binary, `echo unexpected-spawn > '${h.root}/spawned'`);
|
||||
writeJson(join(dirname(config), 'proxy.json'), { port: 18541, binary });
|
||||
const argv = lines(read(proxyFile(h)), 'ExecStart')[0].split(' ');
|
||||
const run = () => spawnSync(argv[0], argv.slice(1), { encoding: 'utf8', env: { PATH: '/usr/bin:/bin', HOME: h.home, MOSAIC_CONFIG: config } });
|
||||
const bad = run();
|
||||
assert.equal(bad.status, 3, bad.stderr);
|
||||
assert.equal(bad.stderr, 'proxy-install-invalid\n');
|
||||
assert.equal(existsSync(join(h.root, 'spawned')), false);
|
||||
rmSync(join(dirname(config), 'proxy.json'));
|
||||
const absent = run();
|
||||
assert.equal(absent.status, 3, absent.stderr);
|
||||
assert.equal(absent.stderr, 'proxy-not-configured\n');
|
||||
});
|
||||
|
||||
test('row334 reinstall repins all three and refuses a proxy copy mismatch', t => {
|
||||
const h = hub(t);
|
||||
assert.equal(proxyUnit(h).code, 0);
|
||||
assert.equal(proxyUnit(h, { copy: COPY_B }).code, 0);
|
||||
for (const file of [proxyFile(h), busFile(h), webuiFile(h)]) assert.match(read(file), new RegExp(copyDir(h, COPY_B)));
|
||||
writeFileSync(proxyFile(h), read(proxyFile(h)).replaceAll(copyDir(h, COPY_B), copyDir(h)));
|
||||
const before = [proxyFile(h), busFile(h), webuiFile(h)].map(read);
|
||||
refuses(proxyUnit(h), /installed units name different copies/);
|
||||
assert.deepEqual([proxyFile(h), busFile(h), webuiFile(h)].map(read), before);
|
||||
});
|
||||
|
||||
test('row334 installed proxy without --proxy refuses and preserves all bytes', t => {
|
||||
const h = hub(t);
|
||||
assert.equal(proxyUnit(h).code, 0);
|
||||
const files = [proxyFile(h), busFile(h), webuiFile(h)], before = files.map(read);
|
||||
writeFileSync(h.log, '');
|
||||
refuses(unit(h), /installed mosaic-proxy.service requires --proxy/);
|
||||
assert.deepEqual(files.map(read), before);
|
||||
assert.equal(read(h.log), '');
|
||||
});
|
||||
|
||||
test('row334 dangling proxy symlink without flag refuses without deleting', t => {
|
||||
const h = hub(t);
|
||||
symlinkSync(join(h.root, 'absent'), proxyFile(h));
|
||||
refuses(unit(h), /installed mosaic-proxy.service requires --proxy/);
|
||||
assert.equal(readdirSync(h.units).includes('mosaic-proxy.service'), true);
|
||||
});
|
||||
|
||||
test('row334 active proxy reports old copy and all three must restart together', t => {
|
||||
const h = hub(t);
|
||||
assert.equal(proxyUnit(h).code, 0);
|
||||
const r = proxyUnit(h, { copy: COPY_B, env: { CASE2_TEST_ACTIVE: 'mosaic-proxy.service [email protected] mosaic-webui.service' } });
|
||||
assert.equal(r.code, 0, r.err);
|
||||
assert.match(r.out, /mosaic-proxy.service was already running/);
|
||||
assert.match(r.out, /restart mosaic-proxy.service, [email protected] and mosaic-webui.service together/);
|
||||
});
|
||||
for (const name of ['mosaic-proxy.service', '[email protected]']) test(`row334 failed ${name} start leaves later units unstarted`, t => {
|
||||
const h = hub(t);
|
||||
refuses(proxyUnit(h, { env: { CASE2_TEST_FAIL: `start ${name}` } }), /systemctl start .* failed/);
|
||||
assert.doesNotMatch(read(h.log), /start mosaic-webui.service/);
|
||||
if (name === 'mosaic-proxy.service') assert.doesNotMatch(read(h.log), /start [email protected]/);
|
||||
});
|
||||
|
||||
|
||||
test('row334 installed proxy enforces hardening order and remaining common refusals', t => {
|
||||
const h = hub(t);
|
||||
assert.equal(proxyUnit(h).code, 0);
|
||||
const original = read(proxyFile(h));
|
||||
for (const [edit, message] of [
|
||||
[s => s.replace('ProtectSystem=strict\nReadWritePaths=' + h.home, 'ReadWritePaths=' + h.home + '\nProtectSystem=strict'), /hardening lines must be in the order/],
|
||||
[s => s.replace('WorkingDirectory=' + copyDir(h), 'WorkingDirectory=%h'), /names no copy/],
|
||||
[s => s.replace('Type=simple', 'Type=simple\nX-Note=%h'), /%h is left; a system unit/],
|
||||
[s => s.replace('RestartSec=15', 'RestartSec=16'), /differs from the render in more than the copy id/],
|
||||
]) {
|
||||
writeFileSync(proxyFile(h), edit(original));
|
||||
refuses(proxyUnit(h), message);
|
||||
}
|
||||
});
|
||||
|
||||
test('row334 proxy installed path rejects symlink and non-regular file', t => {
|
||||
const h = hub(t);
|
||||
symlinkSync(join(h.root, 'absent'), proxyFile(h));
|
||||
refuses(proxyUnit(h), /is a symlink/);
|
||||
rmSync(proxyFile(h));
|
||||
mkdirSync(proxyFile(h));
|
||||
refuses(proxyUnit(h), /is not a regular file/);
|
||||
});
|
||||
@@ -228,7 +228,7 @@ fi
|
||||
say "business $BUSINESS validates"
|
||||
|
||||
# 8. What comes next. Root's steps run from root's own checkout.
|
||||
say "done. Next: root runs case2-unit.sh --copy $COMMIT --business $BUSINESS (design 10 step 2c), then 2d and 3."
|
||||
say "done. Next: root runs case2-unit.sh --copy $COMMIT --business $BUSINESS (add --proxy when the config has a proxy section; design 10 step 2c), then 2d and 3."
|
||||
if [ "$PROFILE" = library ]; then
|
||||
say "Then Jason places the library token in $SLOT (step 4), and <user> runs case2-precheck.sh --business $BUSINESS --library-status (step 4a)."
|
||||
fi
|
||||
|
||||
+65
-22
@@ -1,11 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
# Case 2 row C2-13a (design 9.3, 10 step 2c): render and install the two
|
||||
# system units a hub runs as, [email protected] (enabled as
|
||||
# system units a hub runs as (plus P1's proxy with --proxy), [email protected] (enabled as
|
||||
# mosaic-bus@<business>.service) and mosaic-webui.service, from the existing
|
||||
# templates, which it doesn't change.
|
||||
#
|
||||
# case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH
|
||||
# [--profile factory|library] [--pm] [--claude PATH]
|
||||
# [--profile factory|library] [--proxy] [--pm] [--claude PATH]
|
||||
# -- SERVE FLAGS
|
||||
#
|
||||
# Root runs it from a root-owned checkout of the reviewed commit outside
|
||||
@@ -31,8 +31,8 @@
|
||||
# --pm and --claude.
|
||||
#
|
||||
# On a re-install the installed units must equal the render in everything
|
||||
# but the copy id, and both must name one copy, so a re-pin or rollback
|
||||
# re-renders the pair together. A unit that was already running stays on its
|
||||
# but the copy id, and all selected units must name one copy, so a re-pin or rollback
|
||||
# re-renders them together. A unit that was already running stays on its
|
||||
# old copy, since `systemctl start` leaves it alone; the script says so and
|
||||
# that the bus and Console must restart together, and restarts nothing.
|
||||
#
|
||||
@@ -41,6 +41,7 @@
|
||||
# the root and root-owned checks apply only there
|
||||
# CASE2_SYSTEMCTL the systemctl command, default systemctl
|
||||
# CASE2_GETENT the getent command, default getent
|
||||
# CASE2_PROXY_TEMPLATE default packages/cli/systemd/mosaic-proxy.service.in
|
||||
# CASE2_BUS_TEMPLATE default packages/cli/systemd/mosaic-bus.service.in
|
||||
# CASE2_WEBUI_TEMPLATE default packages/webui/systemd/mosaic-webui.service.in
|
||||
#
|
||||
@@ -53,10 +54,12 @@ SYSTEMCTL="${CASE2_SYSTEMCTL:-systemctl}"
|
||||
GETENT="${CASE2_GETENT:-getent}"
|
||||
BUS_TEMPLATE="${CASE2_BUS_TEMPLATE:-$REPO/packages/cli/systemd/mosaic-bus.service.in}"
|
||||
WEBUI_TEMPLATE="${CASE2_WEBUI_TEMPLATE:-$REPO/packages/webui/systemd/mosaic-webui.service.in}"
|
||||
PROXY_TEMPLATE="${CASE2_PROXY_TEMPLATE:-$REPO/packages/cli/systemd/mosaic-proxy.service.in}"
|
||||
PROXY_UNIT=mosaic-proxy.service
|
||||
BUS_UNIT=[email protected]
|
||||
WEBUI_UNIT=mosaic-webui.service
|
||||
|
||||
usage() { echo 'usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--pm] [--claude PATH] -- SERVE FLAGS' >&2; exit 4; }
|
||||
usage() { echo 'usage: case2-unit.sh --user NAME --home DIR --business ID --copy ID --node PATH [--profile factory|library] [--proxy] [--pm] [--claude PATH] -- SERVE FLAGS' >&2; exit 4; }
|
||||
die() { echo "case2-unit: $*" >&2; exit 1; }
|
||||
# A value the unit carries as itself: no space, %, $, quote, backslash, & or |.
|
||||
plain() { case "$1" in *[!A-Za-z0-9/._+@-]*) return 1 ;; esac; }
|
||||
@@ -67,7 +70,7 @@ abs_plain() {
|
||||
[ "$1" = / ] || [ "${1%/}" = "$1" ] || die "$2 must not end in /: $1"
|
||||
}
|
||||
|
||||
PROFILE=library USER_NAME='' HOME_DIR='' BUSINESS='' COPY_ID='' NODE='' PM=0 CLAUDE='' CLAUDE_SET=0
|
||||
PROFILE=library USER_NAME='' HOME_DIR='' BUSINESS='' COPY_ID='' NODE='' PROXY=0 PM=0 CLAUDE='' CLAUDE_SET=0
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--profile|--user|--home|--business|--copy|--node|--claude)
|
||||
@@ -78,6 +81,7 @@ while [ $# -gt 0 ]; do
|
||||
--claude) CLAUDE="$2"; CLAUDE_SET=1 ;;
|
||||
esac
|
||||
shift 2 ;;
|
||||
--proxy) PROXY=1; shift ;;
|
||||
--pm) PM=1; shift ;;
|
||||
--) shift; break ;;
|
||||
*) usage ;;
|
||||
@@ -150,6 +154,7 @@ fi
|
||||
# The checkout the templates come from, when installing for real.
|
||||
if [ "$UNIT_DIR" = "$DEFAULT_UNIT_DIR" ]; then
|
||||
case "$REPO/" in "$HOME_DIR"/*) die "run this from a root-owned checkout outside $HOME_DIR, not $REPO" ;; esac
|
||||
[ "$PROXY" = 0 ] || root_only "$PROXY_TEMPLATE" 'proxy template'
|
||||
root_only "$BUS_TEMPLATE" 'bus template'
|
||||
root_only "$WEBUI_TEMPLATE" 'Console template'
|
||||
fi
|
||||
@@ -449,7 +454,10 @@ render() {
|
||||
fi
|
||||
if printf '%s\n' "$text" | grep -q '%h'; then die "$template: %h is left after the render"; fi
|
||||
local add="User=$USER_NAME\nGroup=$GROUP\n${HARDENING//$'\n'/\\n}\n"
|
||||
[ "$kind" = bus ] || add="$add${CAPS//$'\n'/\\n}\n"
|
||||
[ "$kind" != webui ] || add="$add${CAPS//$'\n'/\\n}\n"
|
||||
if [ "$kind" = bus ] && [ "$PROXY" = 1 ]; then
|
||||
text="$(printf '%s\n' "$text" | sed "/^Description=/a Wants=$PROXY_UNIT\\nAfter=$PROXY_UNIT")"
|
||||
fi
|
||||
# The added lines go at the end of [Service], before its trailing blank
|
||||
# lines. In [Install], WantedBy=multi-user.target replaces
|
||||
# WantedBy=default.target in both units, so both start at boot (Q189).
|
||||
@@ -517,7 +525,7 @@ check_unit() {
|
||||
one WorkingDirectory "$copy"
|
||||
# Environment= lines: PATH, and MOSAIC_CLAUDE_BIN only with --claude.
|
||||
local envs want_envs="[Service] PATH=$UNIT_PATH"
|
||||
[ "$kind" = webui ] || [ -z "$CLAUDE_ENV" ] || want_envs="$want_envs
|
||||
[ "$kind" != bus ] || [ -z "$CLAUDE_ENV" ] || want_envs="$want_envs
|
||||
[Service] MOSAIC_CLAUDE_BIN=$CLAUDE"
|
||||
envs="$(printf '%s\n' "$s" | awk -F'\t' '$2 == "Environment" { print $1 "\t" $3 }')"
|
||||
[ "$envs" = "$want_envs" ] || die "$what: the Environment= lines must be exactly: $(printf '%s' "$want_envs" | cut -f2 | tr '\n' ' ')"
|
||||
@@ -537,6 +545,11 @@ check_unit() {
|
||||
one EnvironmentFile "$ENV_FILE"
|
||||
none AmbientCapabilities
|
||||
none CapabilityBoundingSet
|
||||
elif [ "$kind" = proxy ]; then
|
||||
one ExecStart "$NODE $copy/packages/model-proxy/src/run.mjs"
|
||||
none EnvironmentFile
|
||||
none AmbientCapabilities
|
||||
none CapabilityBoundingSet
|
||||
else
|
||||
one ExecStart "$NODE $copy/packages/webui/src/cli.mjs serve $FLAGS"
|
||||
none EnvironmentFile
|
||||
@@ -554,7 +567,16 @@ check_unit webui "$WEBUI_TEXT" "rendered $WEBUI_UNIT" "$COPY"
|
||||
# copy, and each equals the render once its copy id is the new one.
|
||||
[ -d "$UNIT_DIR" ] && [ ! -L "$UNIT_DIR" ] || die "no unit directory $UNIT_DIR"
|
||||
installed_ids=''
|
||||
for pair in "bus:$BUS_UNIT:BUS_TEXT" "webui:$WEBUI_UNIT:WEBUI_TEXT"; do
|
||||
PAIRS=("bus:$BUS_UNIT:BUS_TEXT" "webui:$WEBUI_UNIT:WEBUI_TEXT")
|
||||
if [ "$PROXY" = 1 ]; then
|
||||
PROXY_TEXT="$(render proxy "$PROXY_TEMPLATE")" || exit 1
|
||||
check_unit proxy "$PROXY_TEXT" "rendered $PROXY_UNIT" "$COPY"
|
||||
PAIRS=("proxy:$PROXY_UNIT:PROXY_TEXT" "${PAIRS[@]}")
|
||||
else
|
||||
[ ! -e "$UNIT_DIR/$PROXY_UNIT" ] && [ ! -L "$UNIT_DIR/$PROXY_UNIT" ] \
|
||||
|| die "installed $PROXY_UNIT requires --proxy; nothing was changed"
|
||||
fi
|
||||
for pair in "${PAIRS[@]}"; do
|
||||
IFS=: read -r kind name var <<<"$pair"
|
||||
path="$UNIT_DIR/$name"
|
||||
[ ! -L "$path" ] || die "refusing: $path is a symlink"
|
||||
@@ -569,13 +591,17 @@ for pair in "bus:$BUS_UNIT:BUS_TEXT" "webui:$WEBUI_UNIT:WEBUI_TEXT"; do
|
||||
installed_ids="$installed_ids $old"
|
||||
done
|
||||
read -r -a ids <<<"$installed_ids"
|
||||
[ "${#ids[@]}" -lt 2 ] || [ "${ids[0]}" = "${ids[1]}" ] || die "the installed units name different copies, ${ids[0]} and ${ids[1]}"
|
||||
for old in "${ids[@]}"; do
|
||||
[ "$old" = "${ids[0]}" ] || die "the installed units name different copies, ${ids[0]} and $old"
|
||||
done
|
||||
|
||||
# `systemctl start` leaves a running unit on the copy it started from, so
|
||||
# note which units run before the write (row 195 owns the restart).
|
||||
BUS_NAME="mosaic-bus@$BUSINESS.service"
|
||||
NAMES=("$BUS_NAME" "$WEBUI_UNIT")
|
||||
[ "$PROXY" = 0 ] || NAMES=("$PROXY_UNIT" "${NAMES[@]}")
|
||||
running=''
|
||||
for name in "$BUS_NAME" "$WEBUI_UNIT"; do
|
||||
for name in "${NAMES[@]}"; do
|
||||
if "$SYSTEMCTL" is-active --quiet "$name"; then running="$running $name"; fi
|
||||
done
|
||||
|
||||
@@ -588,23 +614,40 @@ write_unit() {
|
||||
[ "$(id -u)" != 0 ] || chown root:root "$tmp"
|
||||
mv -fT -- "$tmp" "$UNIT_DIR/$name"
|
||||
}
|
||||
write_unit "$BUS_UNIT" "$BUS_TEXT"
|
||||
write_unit "$WEBUI_UNIT" "$WEBUI_TEXT"
|
||||
# Enable both, then start the bus, then the Console (design 10 step 2c).
|
||||
# serve calls the bus per request, so the units carry no After= or Wants=.
|
||||
for pair in "${PAIRS[@]}"; do
|
||||
IFS=: read -r kind name var <<<"$pair"
|
||||
write_unit "$name" "${!var}"
|
||||
done
|
||||
# Enable all selected units before starting proxy (if selected), bus, Console.
|
||||
# Only the bus depends on the proxy; the Console calls the bus per request.
|
||||
"$SYSTEMCTL" daemon-reload || die "systemctl daemon-reload failed; the units are written, nothing is enabled or started"
|
||||
"$SYSTEMCTL" enable "$BUS_NAME" "$WEBUI_UNIT" || die "systemctl enable $BUS_NAME $WEBUI_UNIT failed; nothing is started"
|
||||
"$SYSTEMCTL" enable "${NAMES[@]}" || die "systemctl enable ${NAMES[*]} failed; nothing is started"
|
||||
if [ "$PROXY" = 1 ]; then
|
||||
"$SYSTEMCTL" start "$PROXY_UNIT" || die "systemctl start $PROXY_UNIT failed; the bus and Console are not started"
|
||||
fi
|
||||
"$SYSTEMCTL" start "$BUS_NAME" || die "systemctl start $BUS_NAME failed; the Console is not started"
|
||||
"$SYSTEMCTL" start "$WEBUI_UNIT" || die "systemctl start $WEBUI_UNIT failed; the bus is running"
|
||||
if [ -z "$running" ]; then
|
||||
echo "case2-unit: wrote $UNIT_DIR/$BUS_UNIT and $UNIT_DIR/$WEBUI_UNIT from copy $COPY_ID; enabled and started $BUS_NAME, then $WEBUI_UNIT"
|
||||
exit 0
|
||||
if [ "$PROXY" = 1 ]; then
|
||||
echo "case2-unit: wrote $UNIT_DIR/$PROXY_UNIT, $UNIT_DIR/$BUS_UNIT and $UNIT_DIR/$WEBUI_UNIT from copy $COPY_ID and enabled all three"
|
||||
if [ -z "$running" ]; then
|
||||
echo "case2-unit: enabled and started $PROXY_UNIT, then $BUS_NAME, then $WEBUI_UNIT"
|
||||
exit 0
|
||||
fi
|
||||
else
|
||||
if [ -z "$running" ]; then
|
||||
echo "case2-unit: wrote $UNIT_DIR/$BUS_UNIT and $UNIT_DIR/$WEBUI_UNIT from copy $COPY_ID; enabled and started $BUS_NAME, then $WEBUI_UNIT"
|
||||
exit 0
|
||||
fi
|
||||
echo "case2-unit: wrote $UNIT_DIR/$BUS_UNIT and $UNIT_DIR/$WEBUI_UNIT from copy $COPY_ID and enabled both"
|
||||
fi
|
||||
echo "case2-unit: wrote $UNIT_DIR/$BUS_UNIT and $UNIT_DIR/$WEBUI_UNIT from copy $COPY_ID and enabled both"
|
||||
for name in "$BUS_NAME" "$WEBUI_UNIT"; do
|
||||
for name in "${NAMES[@]}"; do
|
||||
case " $running " in
|
||||
*" $name "*) echo "case2-unit: $name was already running, so it is still on ${ids[0]:+copy }${ids[0]:-the copy it started from}, not copy $COPY_ID" ;;
|
||||
*) echo "case2-unit: started $name on copy $COPY_ID" ;;
|
||||
esac
|
||||
done
|
||||
echo "case2-unit: restart $BUS_NAME and $WEBUI_UNIT together to put both on copy $COPY_ID; until then they may run different copies"
|
||||
if [ "$PROXY" = 1 ]; then
|
||||
echo "case2-unit: restart $PROXY_UNIT, $BUS_NAME and $WEBUI_UNIT together to put all three on copy $COPY_ID; until then they may run different copies"
|
||||
else
|
||||
echo "case2-unit: restart $BUS_NAME and $WEBUI_UNIT together to put both on copy $COPY_ID; until then they may run different copies"
|
||||
fi
|
||||
Reference in new issue
Block a user