Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4b14952e2 |
No files matched your search
@@ -5430,12 +5430,6 @@ Row 299 (573, #1806, Gander, Filbert): before, the P10 band test timed a fault r
|
||||
|
||||
2026-10-23T22:41:07Z | Boyd | Row 298 (#1804), rebase after row 239 | Rebased onto 833ec1cc8d7c11842efb82e57c1a0b256c8d22d7 on boyd/row298-r2 without altering published boyd/row298. Only append-log conflicts; upstream bytes preserved and Boyd suffixes appended. Product merges automatic; row 239 writer-lock revoke and post-revoke error handling preserved, organization.mjs unchanged from new base. Static checks only; UNTESTED on new base pending Sage CLEAR. Details in Boyd BUILD.md.
|
||||
|
||||
2026-10-23 | Goldie | Row 322 / #1818 F8/F9 before | The library installer runs the clone importer, whose yaml dependency is absent on fresh clones, and tail -n 1 hides uncaught errors behind Node's version banner. Plan: run the same-commit copy importer, include it in COPY_PATHS, keep the first error line with last-line fallback, append isolated regression coverage. Mos-1550 approves setup-only world(t) additions and the one-path copy-file pin addition. No tests run yet; Sage slot required.
|
||||
|
||||
2026-10-23 | Goldie | Row 322 / #1818 F8/F9 after | Importer now runs from the same-commit dependency-equipped copy; COPY_PATHS includes it. One-line refusal selects an actual Error/ERR_ line, avoiding Node's source excerpt/banner, with last-line fallback. Mos-1550-approved fixture setup and one-file pin changes; two append-only regression tests. Under sage-3808 CLEAR, serialized timeout -k 10 runs in /mnt/storage/scratch/tmp/goldieuQ2664: install26/26, copy18/18, pinned-copy10/10; new tests2/2 first run and restored; N installer expected-red2/2, F8 and F9 mutants killed, installer SHA256 restored each time. No unexpected red. Evidence and exact old-test changes in agents/goldie/work/queue-322/BUILD.md; full gate and Morgana review belong to Sage.
|
||||
|
||||
2026-10-23 | Goldie | Row 324 / #1820 before (Q247, mos-1555) | New branch goldie/row324 at row298 approved860afc2b6. Design/readers audit in agents/goldie/work/queue-324/BUILD.md: normalize omitted tracker to null, preserve present validation, guard sync readers/adapter config; runtime/instance-settings/broker checks already optional. Existing business.test.mjs98 explicitly requires tracker, so implementation held for Mos approval of removing that one list entry; no old test or product edit, no tests run.
|
||||
|
||||
2026-10-23 | Goldie | Row 324 / #1820 draft built (sage-3836, mos-1556) | Claim rev3759. Omitted tracker normalizes null; present including null/malformed stays validated. Loader, business validate, bootConfig trackerFor and Console sync reader handle absence. Row298's guarded runtime/instance-settings/broker paths preserved. Two new test files (9 planned tests); sole old-test edit drops tracker from required-key list under mos-1556. node --check6/6 and diff check pass. No tests run: untested branch push expressly ordered before CLEAR; Duckworth review and Sage gate pending.
|
||||
|
||||
2026-10-23 | Goldie | Row 324 / #1820 rebased verification (sage-3850) | Rebased onto3569bf54f as7e59ba8b3; only append-log conflicts, eight manifest files byte-equal. Serialized timeout-k10 scratch TMPDIR goldieOdgIjr: new business5/5, new CLI4/4 (includes Console absent read), existing business21/21; presence mutant killed, bytes restored, new files rerun5/5 and4/4. No unexpected red. Published rebased branch goldie/row324-r2 preserves original remote draft without force-push. Evidence/mutant diff/reader list in BUILD.md; review/full gate pending.
|
||||
@@ -1,56 +0,0 @@
|
||||
# Row 324 round 1 verdict: goldie/row324-r2 dbdfcfd52 (duckworth-0298)
|
||||
|
||||
Request: sage-3853 (#1820, comment 31469, round 1, rev 3768/3769). Candidate: dbdfcfd52 on refactor
|
||||
3569bf54f, code commit 7e59ba8b3. Brief: docs/plans/2026-10-23_optional-tracker-brief.md.
|
||||
Method: static. Git reads of local objects only. No node, no tests, no fetch, no queue reads.
|
||||
|
||||
## Verdict: APPROVE (static)
|
||||
|
||||
- **The manifest matches.** agents/goldie/work/queue-324/MANIFEST.sha256 hashes to 52874356…2b473d,
|
||||
the digest Sage gave. All 8 listed blobs match the files at dbdfcfd52.
|
||||
- **The loader change is narrow.**
|
||||
- business.mjs:239 drops "tracker" from the required-key loop.
|
||||
- business.mjs:296 is `Object.hasOwn(document, "tracker") ? checkTracker(document.tracker, file) : null`.
|
||||
Omission gives `tracker: null`. A present key always goes through checkTracker.
|
||||
- business.mjs:298 guards the role tracker comparison on `tracker &&`. An absent business tracker
|
||||
doesn't waive the role pm tracker check, and the new test covers that.
|
||||
- **A present null still refuses.** checkTracker (business.mjs:85) calls requireObject first, so a
|
||||
present null, false, [] or a non-object refuses. {} and {sync:{}} refuse further in. The new
|
||||
refusal test covers each of them.
|
||||
- **Every business.tracker reader handles absence.** I read each hit in Goldie's reader-audit.txt and
|
||||
the two outside it in scripts:
|
||||
- bus runtime.mjs:131 registers `<business>/@sync` only under `b.tracker?.sync?.credentials`. An
|
||||
absent tracker registers nothing.
|
||||
- bus runtime.mjs:247 hashes `b.tracker?.sync ?? null`.
|
||||
- broker.mjs:6242 reads `b.tracker?.sync?.bot`. Broker 3969 and 4497 read the role-level tracker
|
||||
only.
|
||||
- cli.mjs:85 and webui reads.mjs:166 use `tracker?.sync?.credentials ?? {}`. The
|
||||
`b.tracker.sync.bot` inside the reads.mjs loop runs only when there are entries.
|
||||
- cli config.mjs:58 trackerFor returns null on an absent tracker before the vars check. bootConfig
|
||||
(config.mjs:138-139) sets config.trackers only for a non-null result.
|
||||
- tasks/adapter.mjs loads only for configured trackers (process.mjs:136), and its settings refuse
|
||||
with tracker-config at :25 before the :35 and :81 reads.
|
||||
- instance-settings.mjs:127 reads `old.tracker?.sync`.
|
||||
- stack-release.sh:2074 and :2120 use `b.tracker?.sync?.credentials`.
|
||||
- launch-settings, resolve, instances.mjs and public/bus.js:785 read role-level trackers only.
|
||||
conversation/controller exec.tracker is a different object.
|
||||
- **Writers don't serialize the loader's null.** The setters build `next` from the raw file bytes
|
||||
(organization.mjs:88-93), not from the loaded object, and validate before writing
|
||||
(organization.mjs:201, :208). A business file without a tracker stays without one.
|
||||
- **The brief's tests are there.**
|
||||
- business/tests/optional-tracker.test.mjs has 5 tests: omission loads null, CLI validate with the
|
||||
sync file gone, a present tracker preserved and frozen, the refusal set, and the role pm check.
|
||||
- cli/tests/optional-tracker.test.mjs has 4 tests: no trackers from bootConfig with tracker vars
|
||||
set, startBroker with no @sync credential, businessView with no credentials, and a present
|
||||
tracker with a missing token refusing credential-file.
|
||||
- The existing-tracker case runs through business.test.mjs unchanged apart from :98.
|
||||
- **The one old-test edit is in bounds.** business.test.mjs:98 drops "tracker" from the
|
||||
required-key loop, as mos-1556 allows.
|
||||
- **The run, as Goldie reported it (sage-3850 CLEAR, I didn't rerun it):** 5/5, 4/4 and
|
||||
business.test 21/21. The presence mutant at business.mjs:296 is killed, and the restore matched
|
||||
sha256 e76db421.
|
||||
|
||||
## Notes
|
||||
|
||||
- N1 (doc). The 'undefined' refusal case only exists in memory. A JSON file can't carry undefined,
|
||||
so on disk it is the same as omission. The test is still correct.
|
||||
@@ -1,171 +0,0 @@
|
||||
# Row 321: F7 wrapper environment and F10 first adoption (#1817)
|
||||
|
||||
Owner Gladstone; reviewer Boyd (separate Codex thread); queue/review/landing Sage.
|
||||
Authorized by sage-3791. Branch gladstone/row321 starts at fetched origin/refactor
|
||||
833ec1cc8d7c11842efb82e57c1a0b256c8d22d7. The row320 branch is unchanged.
|
||||
Brief: docs/plans/2026-10-23_host-fixes-1816-brief.md, section
|
||||
"Brief: F7, the wrapper step's PATH and umask under sudo", including F10;
|
||||
verified blob 7333f94ba9cfd58f87c5a3580d428b84c65845b6 (requested pin 7333f94ba9cf).
|
||||
Only the run sheet and this BUILD.md change. No scripts, tests, config, credentials,
|
||||
queue state, deployment or live host operation changed. No tests or Node commands run.
|
||||
|
||||
## Before and after
|
||||
|
||||
F7: sudo secure_path omits the pinned Node directory, so wrapper creation reaches
|
||||
instance.sh's bare node and exits127. An inherited umask can leave the bin dir0775.
|
||||
The MOSAIC_WRAPPER heredoc now sets umask077 and the sheet's existing pinned Node
|
||||
PATH before mkdir. One sentence names secure_path and why the step sets both.
|
||||
The existing Mos go remains explicit. No wrapper command is executed here.
|
||||
|
||||
F10: first install omits adoption, so the first activate refuses no-pointer.
|
||||
The release-transport section now places explicit adoption after both units are
|
||||
running (section10) and before any activate/upgrade, run as mosaic on Mos's go by
|
||||
Jason or Mos, citing stack-release.sh:14. It uses the configured dev instance and
|
||||
external units, with the same pinned Node PATH under sudo.
|
||||
Adjacent to the upgrade command, the sheet now says only the first upgrade after
|
||||
adopt takes --no-rehearsal: adopt writes no backup; missing flag refuses no-backup;
|
||||
later upgrades omit it, because a backup with that flag refuses rehearsal-required.
|
||||
Source checks: stack-release.sh pointer_for_business refuses no-pointer and directs
|
||||
adopt; stack-upgrade.sh rehearse handles rc3/no-backup and rc0/rehearsal-required.
|
||||
This records existing behavior and authority; it adds no requirement or live go.
|
||||
|
||||
## Test-reference grep (negative and positive control)
|
||||
|
||||
The required negative grep covers both F7 and F10 because neither is read by any
|
||||
matched test. The positive control locates the precheck path that the unit/install
|
||||
tests actually execute, showing the pathspecs reach their test files.
|
||||
|
||||
Negative grep:
|
||||
|
||||
```sh
|
||||
git grep -n 'host-run-sheet' -- 'packages/*/tests/*' 'scripts/test-*.sh'
|
||||
# exit 1
|
||||
# no matches
|
||||
```
|
||||
|
||||
Positive control:
|
||||
|
||||
```sh
|
||||
git grep -n 'case2-precheck.sh' -- 'packages/*/tests/*' 'scripts/test-*.sh'
|
||||
# exit 0
|
||||
packages/cli/tests/case1-accept.test.mjs:26:const PRECHECK = `${HOME}/.local/share/mosaic-stack/copies/${COPY}/scripts/case2-precheck.sh`;
|
||||
packages/cli/tests/case2-install.test.mjs:2:// scripts/case2-precheck.sh's library checks and --library-status mode. Brief:
|
||||
packages/cli/tests/case2-install.test.mjs:23:const PRECHECK = join(REPO, "scripts", "case2-precheck.sh");
|
||||
packages/cli/tests/case2-install.test.mjs:271:// ---- case2-precheck.sh, the library profile (D6a) ----
|
||||
packages/cli/tests/case2-install.test.mjs:334:// ---- case2-precheck.sh --library-status (D6b) ----
|
||||
packages/cli/tests/case2-unit.test.mjs:2:// and scripts/case2-precheck.sh checks the host before they start. Brief: docs/plans/2026-10-20_case2-rows.md
|
||||
packages/cli/tests/case2-unit.test.mjs:20:const PRECHECK = join(REPO, "scripts", "case2-precheck.sh");
|
||||
packages/cli/tests/case2-unit.test.mjs:588:// ---- case2-precheck.sh ----
|
||||
```
|
||||
|
||||
## Run-sheet diff against the pinned base (git diff --unified=0)
|
||||
|
||||
```diff
|
||||
diff --git a/docs/guides/host-run-sheet.md b/docs/guides/host-run-sheet.md
|
||||
index d2ba28d7c..96fd4f363 100644
|
||||
--- a/docs/guides/host-run-sheet.md
|
||||
+++ b/docs/guides/host-run-sheet.md
|
||||
@@ -209,0 +210,9 @@ sudo -u mosaic -H git clone -q -b refactor /srv/mosaic/incoming/<sha>.bundle /sr
|
||||
+After a first install, once both units are running (section 10), adopt the installed copy before
|
||||
+any activate or upgrade. This step runs only on Mos's go, with Jason or Mos running it
|
||||
+(`scripts/stack-release.sh:14`):
|
||||
+
|
||||
+```sh
|
||||
+sudo -u mosaic -H env PATH=/opt/mosaic-stack/node-<v>/bin:/usr/sbin:/usr/bin:/sbin:/bin \
|
||||
+ /srv/mosaic/src/mosaic-stack/scripts/stack-release.sh adopt <business> --instance dev --units external
|
||||
+```
|
||||
+
|
||||
@@ -211,0 +221,4 @@ Each upgrade, before `stack-upgrade.sh upgrade`:
|
||||
+Only the first upgrade after adopt takes `--no-rehearsal`: append it to the upgrade command below.
|
||||
+Adopt writes no backup, so omitting the flag then refuses `no-backup`. Subsequent upgrades omit it;
|
||||
+when a backup exists, supplying it refuses `rehearsal-required`.
|
||||
+
|
||||
@@ -246,0 +260 @@ step requiring Mos's go (`scripts/stack-copy.sh:3`); the install does not create
|
||||
+The step runs under sudo's `secure_path`, so it sets its own PATH and umask.
|
||||
@@ -250,0 +265,2 @@ cd / || exit 1
|
||||
+umask 077
|
||||
+PATH=/opt/mosaic-stack/node-<v>/bin:/usr/sbin:/usr/bin:/sbin:/bin; export PATH
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
||||
No matching test reads the changed lines, so the stop condition did not apply.
|
||||
No test run or slot is required under sage-3791. Verification is static: the
|
||||
required grep and positive control above, exact brief/base pins, scoped diff,
|
||||
and git diff --check. Reviewer Boyd and Sage own review/landing; no approval
|
||||
or landing is claimed here.
|
||||
|
||||
Receipt correction: the first commit embedded ordinary diff context lines that
|
||||
contain a single space. git diff --check flagged those as trailing whitespace.
|
||||
This follow-up uses the exact zero-context diff instead. The run sheet is
|
||||
unchanged, no tests or Node commands run, and no amend or force-push is used.
|
||||
|
||||
## F11 addition (sage-3805, mos-1549, ops-0275)
|
||||
|
||||
The brief was extended after F7/F10 drafting and re-pinned at revision3733:
|
||||
canonical local commit a9bae9af2, same F7 section anchor, full verified blob
|
||||
0e684ef2103447dcc2013b6bf81b1c4ca5bbc0bd (requested pin0e684ef21034).
|
||||
Read using git show from the canonical checkout; no fetch, rebase or queue write
|
||||
is required. This new pin supersedes the earlier brief pin for this follow-up.
|
||||
|
||||
Defect: a precheck one second after unit start found no bus.sqlite yet.
|
||||
Section10 now requires loopback healthz success after a unit start before any
|
||||
case2-precheck.sh, including section9's --library-status. It uses the same
|
||||
127.0.0.1:<port>/healthz curl form as scripts/case1-accept.sh:458. The subshell
|
||||
tries at most30 times, each curl capped at2 seconds, with1 second between failed
|
||||
attempts (at most89 seconds plus scheduling overhead). Exhaustion prints STOP
|
||||
and exits only the subshell. The instruction says to stop before precheck/adopt;
|
||||
it does not exit the interactive operator shell. The section9 library-gitea row
|
||||
now explicitly requires this bounded wait before --library-status. <port> is the
|
||||
installed Console unit's --port, not an assumed port or business name.
|
||||
No host action, test, Node command or credential access occurred.
|
||||
|
||||
Required grep repeated for the widened scope:
|
||||
|
||||
```sh
|
||||
git grep -n 'host-run-sheet' -- 'packages/*/tests/*' 'scripts/test-*.sh'
|
||||
# exit1, no matches
|
||||
git grep -n 'case2-precheck.sh' -- 'packages/*/tests/*' 'scripts/test-*.sh'
|
||||
# exit0, positive control; output follows
|
||||
packages/cli/tests/case1-accept.test.mjs:26:const PRECHECK = `${HOME}/.local/share/mosaic-stack/copies/${COPY}/scripts/case2-precheck.sh`;
|
||||
packages/cli/tests/case2-install.test.mjs:2:// scripts/case2-precheck.sh's library checks and --library-status mode. Brief:
|
||||
packages/cli/tests/case2-install.test.mjs:23:const PRECHECK = join(REPO, "scripts", "case2-precheck.sh");
|
||||
packages/cli/tests/case2-install.test.mjs:271:// ---- case2-precheck.sh, the library profile (D6a) ----
|
||||
packages/cli/tests/case2-install.test.mjs:334:// ---- case2-precheck.sh --library-status (D6b) ----
|
||||
packages/cli/tests/case2-unit.test.mjs:2:// and scripts/case2-precheck.sh checks the host before they start. Brief: docs/plans/2026-10-20_case2-rows.md
|
||||
packages/cli/tests/case2-unit.test.mjs:20:const PRECHECK = join(REPO, "scripts", "case2-precheck.sh");
|
||||
packages/cli/tests/case2-unit.test.mjs:588:// ---- case2-precheck.sh ----
|
||||
```
|
||||
|
||||
No test reads the changed run-sheet lines; the stop condition does not apply.
|
||||
No test run is needed under the docs-only brief. Static verification checks both
|
||||
locations, retry limit/timeout, the loopback URL, unchanged F7/F10 and scoped diff.
|
||||
|
||||
F11 delta against d9400f0d3 (git diff --unified=0):
|
||||
|
||||
```diff
|
||||
diff --git a/docs/guides/host-run-sheet.md b/docs/guides/host-run-sheet.md
|
||||
index 96fd4f363..e9fa87f24 100644
|
||||
--- a/docs/guides/host-run-sheet.md
|
||||
+++ b/docs/guides/host-run-sheet.md
|
||||
@@ -322 +322 @@ file with `stat -c '%U %a %n' PATH`, never `cat`. `<business>` is the host's bus
|
||||
-| `/srv/mosaic/.config/mosaic-dev/secrets/<business>/` | `library-gitea` | 0600 | mosaic | library | `case2-precheck.sh --business <business> --library-status`, after the bus is up: `library-last-error library-credential-missing` until it's placed, then `library <project> last fetched ...` |
|
||||
+| `/srv/mosaic/.config/mosaic-dev/secrets/<business>/` | `library-gitea` | 0600 | mosaic | library | After a unit start, wait for loopback `/healthz` with the bounded retry in section 10 before `case2-precheck.sh --business <business> --library-status`: `library-last-error library-credential-missing` until it's placed, then `library <project> last fetched ...` |
|
||||
@@ -357,0 +358,16 @@ None by hand. I2's `case2-unit.sh` enables both units, starts the bus, then the
|
||||
+After a unit start, wait for the Console's loopback `/healthz` to succeed before running
|
||||
+`case2-precheck.sh`, including `--library-status` in section 9. Replace `<port>` with the installed
|
||||
+Console unit's `--port`. This retry is bounded to 30 attempts, each with a 2-second timeout, with
|
||||
+1 second between failed attempts. If it prints STOP, stop here; do not run the precheck or adopt.
|
||||
+
|
||||
+```sh
|
||||
+(
|
||||
+ attempts=0
|
||||
+ until curl -fsS --max-time 2 -o /dev/null 'http://127.0.0.1:<port>/healthz'; do
|
||||
+ attempts=$((attempts + 1))
|
||||
+ [ "$attempts" -lt 30 ] || { echo "STOP: loopback healthz did not become ready; do not continue" >&2; exit 1; }
|
||||
+ sleep 1
|
||||
+ done
|
||||
+)
|
||||
+```
|
||||
+
|
||||
```
|
||||
@@ -1,69 +0,0 @@
|
||||
# Row 322 / #1818 — F8 and F9
|
||||
|
||||
Goldie, 2026-10-23. Branch goldie/row322, base 833ec1cc8d7c11842efb82e57c1a0b256c8d22d7.
|
||||
Brief: docs/plans/2026-10-23_host-fixes-1816-brief.md, F8/F9 section at 7333f94ba9cf.
|
||||
Issue #1818 is supplied by Sage; no new issue is needed. Reviewer Morgana; Sage owns landing/full gate.
|
||||
|
||||
## Implementation and authority
|
||||
|
||||
F8 runs the importer from `$COPIES/$COMMIT/scripts/case2-persona-import.mjs`. This uses Node's normal ESM resolution, finding yaml beside the copy and the relative harness module in that same commit. It avoids a custom loader or ambient resolution setting. The copy closure already includes harness/src and business/src, but omitted the importer itself; COPY_PATHS now includes that one script. No new dependency or dependency version change.
|
||||
|
||||
F9 selects the first line beginning with an Error type (including TypeError etc.) or ERR_, falling back to the last line for the importer's handled refusal. awk exits after the first matching line and emits exactly one line, keeping the stack and version banner out of the install refusal. Anchoring avoids selecting Node's earlier `throw new ERR_MODULE_NOT_FOUND(...)` source excerpt instead of the actual Error line.
|
||||
|
||||
Mos-1550 authorizes the copy-path addition, setup-only additions to world(t), and adding the single new filename to any existing copy-file pin. Existing test edits outside the appended row-322 block:
|
||||
|
||||
- case2-install.test.mjs: the fake stack-copy setup gains a loop copying the importer, harness bundle.mjs/tools.mjs, and business vocabulary.mjs; it copies yaml into the fake copy's node_modules. The existing last template-string line is extended to add those setup commands. No existing assertion changes.
|
||||
- packages/webui/tests/pinned-copy.test.mjs:76: the scripts file-list assertion gains only `case2-persona-import.mjs`, in sorted order. No other change in this test.
|
||||
|
||||
The new append-only block builds a scratch clone outside the repository with no node_modules, real installer and importer, stubbed bootstrap/business validation, and a copy with the real importer, relative module closure and yaml. F8 checks installed persona bytes/mode; F9 removes yaml from that copy to produce a real uncaught Node missing-package error, then checks one refusal line carries the cause and no stack/banner. Existing tests missed F8 because the real importer ran from the development checkout, which has yaml installed; the fake copy held only scripts/mosaic. The old fixtures thus never exercised the dependency boundary or an uncaught importer load error.
|
||||
|
||||
## Class check and copy-test audit
|
||||
|
||||
Before change:
|
||||
|
||||
```
|
||||
grep -n 'node "$REPO/' scripts/case2-install.sh scripts/case2-precheck.sh scripts/stack-copy.sh
|
||||
scripts/case2-install.sh:185: out="$(node "$REPO/scripts/case2-persona-import.mjs" ...
|
||||
```
|
||||
|
||||
After change: same grep has no hits (exit 1). Direct clone-side .mjs entry points in the three scripts with a bare package import: **scripts/case2-persona-import.mjs → yaml**, moved to the copy by F8. No other direct entry point imports a bare package. Precheck's inline Node programs dynamically import cli/src/config.mjs, business/src/index.mjs, library/src/index.mjs and cli/src/cli.mjs; those entry files import builtins/relative modules only. Library reader.mjs uses its own front-matter parser and has no yaml import. stack-copy sources instance.sh, whose mosaic-config.mjs imports builtins only. Installer bootstrap likewise runs mosaic-config.mjs, and business validation runs business/src/cli.mjs, also no direct bare imports. No other product fix made.
|
||||
|
||||
Audit commands (read-only):
|
||||
|
||||
```
|
||||
rg -n 'COPY_PATHS|copy carries|copy.*(hash|sha256|files|file set)|sha256.*copy' packages/*/tests/* scripts/test-*.sh
|
||||
rg -n 'COPY_PATHS|stack-copy\.sh|readdirSync|sha256|deepEqual' packages/webui/tests/pinned-copy.test.mjs packages/cli/tests/stack-copy.test.mjs
|
||||
```
|
||||
|
||||
Relevant hits: cli/tests/stack-copy.test.mjs:35-47 checks harness file closure (positive control: COPY_PATHS at :36), :52 asserts a required-file subset, :248-264 computes hashes/modes and compares bundle/check-out copy trees dynamically, :274 compares another bundle tree. None freezes a complete path list/hash. webui/tests/pinned-copy.test.mjs:75 pins top-level entries (unchanged), :76 pins scripts' exact file set (approved one-path update). Other readdir hits in those files check cleanup/existing-target behavior, not COPY_PATHS identity. Broad initial grep also hits business/tests/helpers.mjs:33, cli/tests/stack-upgrade.test.mjs:295, webui/tests/views.test.mjs:172, cli/tests/stack-release.test.mjs:1751 and :1987; inspected contexts are unrelated comments/UI copy or different fixture copies. No scripts/test-*.sh hit for these path/hash patterns.
|
||||
|
||||
## Verification plan
|
||||
|
||||
Pending Sage CLEAR before any test: run new tests on fixed build first, then whole case2-install.test.mjs, whole stack-copy.test.mjs and webui pinned-copy.test.mjs. Demonstrate expected failure at 094124b4e with new block applied (baseline importer path), and kill the `$REPO` reversion mutant. Record all outcomes. First unexpected new-test red is recorded/reported under mos-1272; existing-test edits outside mos-1550 or a second unexpected red stop for Sage.
|
||||
|
||||
No tests run yet. No commit/push yet. No host changes, live state, secrets, deploy or release actions.
|
||||
|
||||
## Verified results — sage-3808 CLEAR, 2026-10-23T22:47Z
|
||||
|
||||
All runs were serialized with `TMPDIR=/mnt/storage/scratch/tmp/goldieuQ2664` (created by `mktemp -d /mnt/storage/scratch/tmp/goldieXXXXXX`), using `timeout -k 10 90` for focused tests and `timeout -k 10 180` for whole files/negative-proof driver. Node v26.8.1. Dependencies were read through the ignored, uncommitted node_modules symlink approved by sage-3804; each scratch clone had no node_modules. No /tmp fixture was used.
|
||||
|
||||
| Run | Result | Evidence |
|
||||
| --- | --- | --- |
|
||||
| New tests, first run | 2/2 pass, exit 0 | test-new.log |
|
||||
| Whole case2-install.test.mjs | 26/26 pass, exit 0 | test-install.log |
|
||||
| Whole stack-copy.test.mjs | 18/18 pass, exit 0 | test-copy.log |
|
||||
| Whole webui pinned-copy.test.mjs | 10/10 pass, exit 0 | test-pinned-copy.log |
|
||||
| Installer from 094124b4e, new tests | 0/2 pass, exit 1, expected red | baseline-094124b4e.log |
|
||||
| F8 mutant: restore `$REPO` importer path only | 0/1 pass, exit 1, killed | mutant-F8.log |
|
||||
| F9 mutant: restore tail-only refusal only | 0/1 pass, exit 1, killed | mutant-F9.log |
|
||||
| Fixed installer restored, new tests rerun | 2/2 pass, exit 0 | test-restored.log |
|
||||
|
||||
The baseline proof temporarily installs the exact installer bytes from `git show 094124b4e:scripts/case2-install.sh`, retaining the newly appended tests and approved fixture setup. Relevant installer/importer/copy/test source paths have no changes between N and the branch base 833ec1cc8 (`git diff 094124b4e 833ec1cc8 --` those paths is empty). It is a targeted baseline proof, not a full checkout/suite run at N. Baseline failures show `persona-import: Node.js v26.8.1`; the F8-only mutant exposes the underlying `Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'yaml'` from the scratch clone. F9-only mutant again prints the banner. All expected failures are deliberate acceptance checks; no unexpected first-run red occurred.
|
||||
|
||||
negative-proof.py records each run, checks the expected failure count/exit, restores in a finally block, and verifies fixed installer bytes after each run. Restored SHA-256 each time: `c23a08324528cc29895014093c661948a5c8eb40316c7b2e21c6f833cf5d6462`. Final focused green confirms restoration. git diff --check passed.
|
||||
|
||||
`git diff --numstat -- packages/cli/tests/case2-install.test.mjs`: **57 additions, 1 deletion**. Outside the new appended block, original line 70's template-string close moves after four new setup lines: the existing mkdir/empty mosaic/echo command is unchanged, followed by the `for file ...` line, mkdir/cp loop body, `done`, and mkdir/cp yaml line. All pre-existing assertions remain byte-for-byte unchanged. The only pre-existing assertion edit anywhere is the expressly approved one-filename addition at packages/webui/tests/pinned-copy.test.mjs:76.
|
||||
|
||||
Sage's full package/script gate and Morgana's review remain pending. This builder ran only the approved three whole test files and targeted acceptance checks. Sage retains queue transition/review posting and integration authority; no PR was created by Goldie.
|
||||
|
||||
Evidence log lines have trailing whitespace removed for git diff --check; test content and outcomes are unchanged.
|
||||
@@ -1,4 +0,0 @@
|
||||
c23a08324528cc29895014093c661948a5c8eb40316c7b2e21c6f833cf5d6462 scripts/case2-install.sh
|
||||
cb1a4fef997b9696406e324878d7a0e5181892622162c9ce77a8fd625b5cd59a scripts/stack-copy.sh
|
||||
a7b02af4b5df92e6d727fe8c67565ea0483d6d57531765dee68f54fd97e7c23f packages/cli/tests/case2-install.test.mjs
|
||||
2574b414459f4cfb187de64b9a2fbe34ab4b4d64f582caae8baf6a1985e8cd3c packages/webui/tests/pinned-copy.test.mjs
|
||||
@@ -1,70 +0,0 @@
|
||||
TAP version 13
|
||||
# Subtest: row 322 F8: library personas install from the copy with no clone node_modules
|
||||
not ok 1 - row 322 F8: library personas install from the copy with no clone node_modules
|
||||
---
|
||||
duration_ms: 90.885888
|
||||
type: 'test'
|
||||
location: '/home/jwoltje/.t3/worktrees/mosaic-stack/goldie-row322/packages/cli/tests/case2-install.test.mjs:451:1'
|
||||
failureType: 'testCodeFailure'
|
||||
error: |-
|
||||
case2-install: config /mnt/storage/scratch/tmp/goldieuQ2664/case2-install-rQM4ct/home/.config/mosaic-dev/config.json
|
||||
case2-install: copy /mnt/storage/scratch/tmp/goldieuQ2664/case2-install-rQM4ct/home/.local/share/mosaic-stack/copies/cccccccccccccccccccccccccccccccccccccccc
|
||||
case2-install: refused: persona-import: Node.js v26.8.1
|
||||
|
||||
|
||||
1 !== 0
|
||||
|
||||
code: 'ERR_ASSERTION'
|
||||
name: 'AssertionError'
|
||||
expected: 0
|
||||
actual: 1
|
||||
operator: 'strictEqual'
|
||||
stack: |-
|
||||
TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/goldie-row322/packages/cli/tests/case2-install.test.mjs:454:10)
|
||||
Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
Test.run (node:internal/test_runner/test:1402:25)
|
||||
Test.start (node:internal/test_runner/test:1262:17)
|
||||
startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17)
|
||||
...
|
||||
# Subtest: row 322 F9: importer refusal keeps the error line rather than the Node banner
|
||||
not ok 2 - row 322 F9: importer refusal keeps the error line rather than the Node banner
|
||||
---
|
||||
duration_ms: 91.239243
|
||||
type: 'test'
|
||||
location: '/home/jwoltje/.t3/worktrees/mosaic-stack/goldie-row322/packages/cli/tests/case2-install.test.mjs:462:1'
|
||||
failureType: 'testCodeFailure'
|
||||
error: |-
|
||||
The input did not match the regular expression /persona-import: Error \[ERR_MODULE_NOT_FOUND\]: Cannot find package 'yaml'/. Input:
|
||||
|
||||
'case2-install: config /mnt/storage/scratch/tmp/goldieuQ2664/case2-install-O6VWs2/home/.config/mosaic-dev/config.json\n' +
|
||||
'case2-install: copy /mnt/storage/scratch/tmp/goldieuQ2664/case2-install-O6VWs2/home/.local/share/mosaic-stack/copies/cccccccccccccccccccccccccccccccccccccccc\n' +
|
||||
'case2-install: refused: persona-import: Node.js v26.8.1\n'
|
||||
|
||||
code: 'ERR_ASSERTION'
|
||||
name: 'AssertionError'
|
||||
expected:
|
||||
actual: |-
|
||||
case2-install: config /mnt/storage/scratch/tmp/goldieuQ2664/case2-install-O6VWs2/home/.config/mosaic-dev/config.json
|
||||
case2-install: copy /mnt/storage/scratch/tmp/goldieuQ2664/case2-install-O6VWs2/home/.local/share/mosaic-stack/copies/cccccccccccccccccccccccccccccccccccccccc
|
||||
case2-install: refused: persona-import: Node.js v26.8.1
|
||||
|
||||
operator: 'match'
|
||||
stack: |-
|
||||
refused (file:///home/jwoltje/.t3/worktrees/mosaic-stack/goldie-row322/packages/cli/tests/case2-install.test.mjs:137:10)
|
||||
TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/goldie-row322/packages/cli/tests/case2-install.test.mjs:469:3)
|
||||
Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
Test.run (node:internal/test_runner/test:1402:25)
|
||||
Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
Test.run (node:internal/test_runner/test:1467:12)
|
||||
async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3)
|
||||
...
|
||||
1..2
|
||||
# tests 2
|
||||
# suites 0
|
||||
# pass 0
|
||||
# fail 2
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 287.462723
|
||||
@@ -1,37 +0,0 @@
|
||||
TAP version 13
|
||||
# Subtest: row 322 F8: library personas install from the copy with no clone node_modules
|
||||
not ok 1 - row 322 F8: library personas install from the copy with no clone node_modules
|
||||
---
|
||||
duration_ms: 90.468116
|
||||
type: 'test'
|
||||
location: '/home/jwoltje/.t3/worktrees/mosaic-stack/goldie-row322/packages/cli/tests/case2-install.test.mjs:451:1'
|
||||
failureType: 'testCodeFailure'
|
||||
error: |-
|
||||
case2-install: config /mnt/storage/scratch/tmp/goldieuQ2664/case2-install-bzVkal/home/.config/mosaic-dev/config.json
|
||||
case2-install: copy /mnt/storage/scratch/tmp/goldieuQ2664/case2-install-bzVkal/home/.local/share/mosaic-stack/copies/cccccccccccccccccccccccccccccccccccccccc
|
||||
case2-install: refused: persona-import: Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'yaml' imported from /mnt/storage/scratch/tmp/goldieuQ2664/case2-install-bzVkal/clone/scripts/case2-persona-import.mjs
|
||||
|
||||
|
||||
1 !== 0
|
||||
|
||||
code: 'ERR_ASSERTION'
|
||||
name: 'AssertionError'
|
||||
expected: 0
|
||||
actual: 1
|
||||
operator: 'strictEqual'
|
||||
stack: |-
|
||||
TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/goldie-row322/packages/cli/tests/case2-install.test.mjs:454:10)
|
||||
Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
Test.run (node:internal/test_runner/test:1402:25)
|
||||
Test.start (node:internal/test_runner/test:1262:17)
|
||||
startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17)
|
||||
...
|
||||
1..1
|
||||
# tests 1
|
||||
# suites 0
|
||||
# pass 0
|
||||
# fail 1
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 194.231229
|
||||
@@ -1,41 +0,0 @@
|
||||
TAP version 13
|
||||
# Subtest: row 322 F9: importer refusal keeps the error line rather than the Node banner
|
||||
not ok 1 - row 322 F9: importer refusal keeps the error line rather than the Node banner
|
||||
---
|
||||
duration_ms: 92.814376
|
||||
type: 'test'
|
||||
location: '/home/jwoltje/.t3/worktrees/mosaic-stack/goldie-row322/packages/cli/tests/case2-install.test.mjs:462:1'
|
||||
failureType: 'testCodeFailure'
|
||||
error: |-
|
||||
The input did not match the regular expression /persona-import: Error \[ERR_MODULE_NOT_FOUND\]: Cannot find package 'yaml'/. Input:
|
||||
|
||||
'case2-install: config /mnt/storage/scratch/tmp/goldieuQ2664/case2-install-6HcR0m/home/.config/mosaic-dev/config.json\n' +
|
||||
'case2-install: copy /mnt/storage/scratch/tmp/goldieuQ2664/case2-install-6HcR0m/home/.local/share/mosaic-stack/copies/cccccccccccccccccccccccccccccccccccccccc\n' +
|
||||
'case2-install: refused: persona-import: Node.js v26.8.1\n'
|
||||
|
||||
code: 'ERR_ASSERTION'
|
||||
name: 'AssertionError'
|
||||
expected:
|
||||
actual: |-
|
||||
case2-install: config /mnt/storage/scratch/tmp/goldieuQ2664/case2-install-6HcR0m/home/.config/mosaic-dev/config.json
|
||||
case2-install: copy /mnt/storage/scratch/tmp/goldieuQ2664/case2-install-6HcR0m/home/.local/share/mosaic-stack/copies/cccccccccccccccccccccccccccccccccccccccc
|
||||
case2-install: refused: persona-import: Node.js v26.8.1
|
||||
|
||||
operator: 'match'
|
||||
stack: |-
|
||||
refused (file:///home/jwoltje/.t3/worktrees/mosaic-stack/goldie-row322/packages/cli/tests/case2-install.test.mjs:137:10)
|
||||
TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/goldie-row322/packages/cli/tests/case2-install.test.mjs:469:3)
|
||||
Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
Test.run (node:internal/test_runner/test:1402:25)
|
||||
Test.start (node:internal/test_runner/test:1262:17)
|
||||
startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17)
|
||||
...
|
||||
1..1
|
||||
# tests 1
|
||||
# suites 0
|
||||
# pass 0
|
||||
# fail 1
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 200.516406
|
||||
@@ -1,6 +0,0 @@
|
||||
baseline-094124b4e: exit 1, expected failures 2
|
||||
restored sha256 c23a08324528cc29895014093c661948a5c8eb40316c7b2e21c6f833cf5d6462
|
||||
mutant-F8: exit 1, expected failures 1
|
||||
restored sha256 c23a08324528cc29895014093c661948a5c8eb40316c7b2e21c6f833cf5d6462
|
||||
mutant-F9: exit 1, expected failures 1
|
||||
restored sha256 c23a08324528cc29895014093c661948a5c8eb40316c7b2e21c6f833cf5d6462
|
||||
@@ -1,39 +0,0 @@
|
||||
"""Run row-322 expected-red proofs, always restoring installer bytes."""
|
||||
import hashlib
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
|
||||
root = Path(__file__).resolve().parents[4]
|
||||
installer = root / 'scripts/case2-install.sh'
|
||||
logs = Path(__file__).resolve().parent
|
||||
fixed = installer.read_bytes()
|
||||
baseline = subprocess.check_output(['git', 'show', '094124b4e:scripts/case2-install.sh'], cwd=root)
|
||||
f8 = fixed.replace(b'$COPIES/$COMMIT/scripts/case2-persona-import.mjs', b'$REPO/scripts/case2-persona-import.mjs')
|
||||
assert f8 != fixed
|
||||
old_error = baseline.splitlines()[185]
|
||||
new_error = fixed.splitlines()[185]
|
||||
f9 = fixed.replace(new_error, old_error)
|
||||
assert f9 != fixed
|
||||
try:
|
||||
for label, source, pattern, failures in [
|
||||
('baseline-094124b4e', baseline, 'row 322', 2),
|
||||
('mutant-F8', f8, 'row 322 F8', 1),
|
||||
('mutant-F9', f9, 'row 322 F9', 1),
|
||||
]:
|
||||
installer.write_bytes(source)
|
||||
result = subprocess.run([
|
||||
'timeout', '-k', '10', '90', 'node', '--test', '--test-reporter=tap',
|
||||
f'--test-name-pattern={pattern}', 'packages/cli/tests/case2-install.test.mjs',
|
||||
], cwd=root, env=os.environ, text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
(logs / f'{label}.log').write_text(result.stdout)
|
||||
print(f'{label}: exit {result.returncode}, expected failures {failures}', flush=True)
|
||||
assert result.returncode == 1, result.stdout
|
||||
assert f'# fail {failures}\n' in result.stdout, result.stdout
|
||||
assert 'ERR_MODULE_NOT_FOUND' in result.stdout, result.stdout
|
||||
installer.write_bytes(fixed)
|
||||
assert installer.read_bytes() == fixed
|
||||
print('restored sha256 ' + hashlib.sha256(fixed).hexdigest(), flush=True)
|
||||
finally:
|
||||
installer.write_bytes(fixed)
|
||||
assert installer.read_bytes() == fixed
|
||||
@@ -1,26 +0,0 @@
|
||||
✔ a copy carries every file the harness modules read from it (891.310838ms)
|
||||
✔ shared copy: npm ci, pushed reachability, readonly/existing copy, webui delegation (537.82282ms)
|
||||
✔ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (713.621566ms)
|
||||
✔ row 190 N6: check --instance passes only when the wrapper exports the instance's MOSAIC_CONFIG (657.082198ms)
|
||||
✔ bus unit copy/pm pins, install refuses all busy states and failed reads, drop-in refusal (799.380065ms)
|
||||
✔ missing package manifest refuses before npm; npm failure removes the unpublished temp copy (499.872009ms)
|
||||
✔ real pinned install loads bus and Console; same-copy mosaic talk passes proof, other trees refuse (3824.368055ms)
|
||||
✔ bus status reads effective copy/pm/drop-ins without writes; check refuses an overridden ExecStart (668.500662ms)
|
||||
✔ drop-ins in either override field and malformed metadata refuse; uninstall also checks --no-reload (399.490955ms)
|
||||
✔ install never shows a template name on systemd 261; template drop-ins still refuse (318.110324ms)
|
||||
✔ unlisted instance drop-in is found in another unit lookup directory; path discovery errors refuse (347.788225ms)
|
||||
✔ inherited mosaic-.service.d override refuses without changing the unit (403.142763ms)
|
||||
✔ inherited service.d override refuses without changing the unit (384.337811ms)
|
||||
✔ inherited drop-in unreadable directory or file refuses before writing (370.630432ms)
|
||||
✔ row 232: copy --bundle copies a SHA the bundle's refactor reaches, byte-identical to copy SHA, and refuses the rest (2257.394077ms)
|
||||
✔ row 232: wrapper --create writes the first wrapper only, the same bytes wrapper ID writes, and refuses over any file (779.276348ms)
|
||||
✔ row 232: check --units external reads the system units, the default reads the user units (641.792634ms)
|
||||
✔ Vikunja 614: bundle and checkout copy leave an unreadable caller directory before find (1047.143772ms)
|
||||
ℹ tests 18
|
||||
ℹ suites 0
|
||||
ℹ pass 18
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 15638.417631
|
||||
@@ -1,34 +0,0 @@
|
||||
✔ the library install writes the business file, personas and slot dir, makes the copy and starts nothing (258.707115ms)
|
||||
✔ a library re-run passes and leaves every file as it was (391.278216ms)
|
||||
✔ a re-run refuses business-file-differs and leaves the file unchanged (274.686097ms)
|
||||
✔ a re-run refuses persona-differs when an installed persona isn't the staged one, and writes nothing (274.084555ms)
|
||||
✔ the factory install writes no library mapping, persona or slot dir (175.791904ms)
|
||||
✔ the factory install refuses a library project and bus.tester off, before anything is written (72.301025ms)
|
||||
✔ the library install refuses bus.tester on and a persona var in the input (76.469642ms)
|
||||
✔ the install refuses root, a business id mismatch, another --home and a config dir with group bits (57.89739ms)
|
||||
✔ the library install needs --personas (5.495139ms)
|
||||
✔ a validate refusal removes the business file this run wrote (230.311754ms)
|
||||
✔ N4: a validate refusal on a re-run leaves the matching business file in place, byte for byte (397.123924ms)
|
||||
✔ a clean library host passes the precheck with no mirror yet (404.408689ms)
|
||||
✔ the library precheck refuses a persona file at 0644 (399.17119ms)
|
||||
✔ the library precheck refuses a persona whose digest isn't persona.sha256 (402.47159ms)
|
||||
✔ the library precheck refuses a persona dir with group bits (390.108413ms)
|
||||
✔ the library precheck refuses a business file at 0644 (402.829663ms)
|
||||
✔ the library precheck refuses a changes.jsonl at 0644 (573.861228ms)
|
||||
✔ the library precheck refuses a Discord binding (386.405794ms)
|
||||
✔ --library-status refuses library-mirror-missing before the bus has made the mirror (309.213305ms)
|
||||
✔ --library-status refuses library-never-synced on a fresh mirror (330.922116ms)
|
||||
✔ --library-status names a recorded lastError before the null lastFetch it leaves (N3) (335.576032ms)
|
||||
✔ --library-status prints each R-problem's path as an escaped JSON string, then the count, and passes (379.69927ms)
|
||||
✔ --library-status takes no --profile (5.544173ms)
|
||||
✔ Vikunja 614: install preserves the explicit notifier decision bytes and mode and creates none when absent (465.015156ms)
|
||||
✔ row 322 F8: library personas install from the copy with no clone node_modules (139.662489ms)
|
||||
✔ row 322 F9: importer refusal keeps the error line rather than the Node banner (95.452368ms)
|
||||
ℹ tests 26
|
||||
ℹ suites 0
|
||||
ℹ pass 26
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 7340.739711
|
||||
@@ -1,10 +0,0 @@
|
||||
✔ row 322 F8: library personas install from the copy with no clone node_modules (178.794273ms)
|
||||
✔ row 322 F9: importer refusal keeps the error line rather than the Node banner (101.739988ms)
|
||||
ℹ tests 2
|
||||
ℹ suites 0
|
||||
ℹ pass 2
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 394.59041
|
||||
@@ -1,18 +0,0 @@
|
||||
✔ copy writes the Console paths at the full id, read-only, and leaves an existing copy alone (872.104795ms)
|
||||
✔ copy refuses a commit off refactor, an unknown one, a worktree and a bad copies directory (1245.376299ms)
|
||||
✔ copy writes nothing when an archived path is missing at the commit (409.033887ms)
|
||||
✔ a copy that loses the rename race leaves no read-only temp directory behind (548.743561ms)
|
||||
✔ a copy whose rename fails with no target refuses, writes no copy and leaves no temp directory (534.468073ms)
|
||||
✔ a copy that meets a target holding files says exists: and moves nothing into it (541.303916ms)
|
||||
✔ a copy that meets an empty target directory replaces it by rename, not by moving into it (547.966283ms)
|
||||
✔ serve runs from a copy: /healthz 200, the config check, roles and RELEASE from the copy, the queue from --checkout (856.865742ms)
|
||||
✔ serve refuses a --checkout that is not an absolute directory path (274.552284ms)
|
||||
✔ consoleReads runs the queue read under queueRoot and reads RELEASE under root (49.311324ms)
|
||||
ℹ tests 10
|
||||
ℹ suites 0
|
||||
ℹ pass 10
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 6003.825092
|
||||
@@ -1,10 +0,0 @@
|
||||
✔ row 322 F8: library personas install from the copy with no clone node_modules (148.410784ms)
|
||||
✔ row 322 F9: importer refusal keeps the error line rather than the Node banner (94.205865ms)
|
||||
ℹ tests 2
|
||||
ℹ suites 0
|
||||
ℹ pass 2
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 344.990842
|
||||
@@ -58,33 +58,3 @@ No tests run. New node_modules symlink points to canonical checkout dependencies
|
||||
Static verification: node --check passed for all four edited source modules and both new test files; git diff --check passed. No node --test or shell suite was run. reader-audit.txt captures the requested grep on the draft. MANIFEST.sha256 pins README, four source files, the one existing test and both new tests. mutant.py prepares the required omission-presence mutant and restores/checks bytes in finally; it has not run.
|
||||
|
||||
Proposed CLEAR run order: new business optional-tracker.test.mjs whole (5 tests), new cli optional-tracker.test.mjs whole (4 tests), existing business.test.mjs whole, then the targeted presence mutant and restored new tests. Broaden to business/CLI/Console/bus package gates only when Sage assigns that scope/slot. All test runs use timeout -k 10 and an explicitly allocated TMPDIR under /mnt/storage/scratch/tmp.
|
||||
|
||||
## Rebased verification — sage-3850 CLEAR
|
||||
|
||||
Rebased c4b14952e onto pushed refactor `3569bf54f53870fcd4e92cdbbb95e3412f629f3a` as `7e59ba8b3d6f63c30a0fa308c0607dfc1e47dd12`. The landing range has no changes in this row's business/config/Console source paths. Only BUILD-LOG.md and docs/SESSIONS.md conflicted: retained the entire landed file then appended this row's original suffix. All eight manifest-pinned files remain byte-equal to the draft; range-diff differences are log context only. To obey no-force-push while preserving the published draft, the rebased candidate is published on `goldie/row324-r2`; original remote goldie/row324 remains at c4b14952e.
|
||||
|
||||
Scratch TMPDIR was created by `mktemp -d /mnt/storage/scratch/tmp/goldieXXXXXX`: `/mnt/storage/scratch/tmp/goldieOdgIjr`. All runs were serialized, with timeout -k 10 (120s new files/mutant driver, 180s existing whole file). Node v26.8.1. No test used /tmp or a real host configuration/credential.
|
||||
|
||||
| Order | Whole file / check | Result | Evidence |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | packages/business/tests/optional-tracker.test.mjs | 5/5 pass, exit0 | test-business-optional.log |
|
||||
| 2 | packages/cli/tests/optional-tracker.test.mjs | 4/4 pass, exit0 | test-cli-optional.log |
|
||||
| 3 | packages/business/tests/business.test.mjs | 21/21 pass, exit0 | test-business-existing.log |
|
||||
| 4 | Presence-check mutant, targeted omission test | 0/1 pass, exit1, killed as expected | mutant.log, mutant-driver.log |
|
||||
| 5 | Restored new business file whole | 5/5 pass, exit0 | test-business-restored.log |
|
||||
| 6 | Restored new CLI file whole | 4/4 pass, exit0 | test-cli-restored.log |
|
||||
|
||||
No unexpected first-run red or old-test red. The Console absent-tracker read test is the third test in the new CLI file and passed on both whole-file runs. There is no separate edited webui test file; the only test files touched by this row are the three whole files above. Existing fixture preservation is covered by the whole business.test.mjs, including its untouched fixture, role bot, credential, sync bot collision and example checks. Broader package/script gates remain Sage's.
|
||||
|
||||
Required mutant diff (business/src/business.mjs:296):
|
||||
|
||||
```diff
|
||||
- const tracker = Object.hasOwn(document, "tracker") ? checkTracker(document.tracker, file) : null;
|
||||
+ const tracker = checkTracker(document.tracker, file);
|
||||
```
|
||||
|
||||
The new omission test fails with BusinessError `tracker must be a JSON object`. mutant.py restores in finally and checks exact bytes. Restored business.mjs SHA256: `e76db42158f396ec6a44f97320355d6c2254dccb5fc53cd04e8ac42843b0d60a`. Full manifest check passes after restoration. git diff --check passes. The full reader list remains above; reader-audit.txt is its raw grep receipt.
|
||||
|
||||
The only pre-existing test delta still is exactly one list entry removed at business.test.mjs:98, under mos-1556: tracker is removed; human/arbiters/projects/roles and the assertion remain. No production/test source changed during verification. Only evidence and append-only log notes follow the tested rebased commit. Slot is returned in the completion report; Duckworth review and Sage's full landing gate remain pending.
|
||||
|
||||
Evidence log trailing whitespace is normalized for git diff --check; test results and output content are unchanged.
|
||||
@@ -1,2 +0,0 @@
|
||||
presence mutant: exit 1
|
||||
restored sha256 e76db42158f396ec6a44f97320355d6c2254dccb5fc53cd04e8ac42843b0d60a
|
||||
@@ -1,32 +0,0 @@
|
||||
TAP version 13
|
||||
# Subtest: Q247: omitting tracker loads as null and preserves independent role bots
|
||||
not ok 1 - Q247: omitting tracker loads as null and preserves independent role bots
|
||||
---
|
||||
duration_ms: 4.653674
|
||||
type: 'test'
|
||||
location: '/home/jwoltje/.t3/worktrees/mosaic-stack/goldie-row324/packages/business/tests/optional-tracker.test.mjs:21:1'
|
||||
failureType: 'testCodeFailure'
|
||||
error: '/mnt/storage/scratch/tmp/goldieOdgIjr/mosaic-business-IHRJco/config/businesses/acme.json tracker must be a JSON object'
|
||||
code: 'ERR_TEST_FAILURE'
|
||||
name: 'BusinessError'
|
||||
stack: |-
|
||||
refuse (file:///home/jwoltje/.t3/worktrees/mosaic-stack/goldie-row324/packages/business/src/errors.mjs:12:9)
|
||||
requireObject (file:///home/jwoltje/.t3/worktrees/mosaic-stack/goldie-row324/packages/business/src/util.mjs:11:30)
|
||||
checkTracker (file:///home/jwoltje/.t3/worktrees/mosaic-stack/goldie-row324/packages/business/src/business.mjs:87:3)
|
||||
validateBusinessDocument (file:///home/jwoltje/.t3/worktrees/mosaic-stack/goldie-row324/packages/business/src/business.mjs:296:19)
|
||||
loadBusiness (file:///home/jwoltje/.t3/worktrees/mosaic-stack/goldie-row324/packages/business/src/business.mjs:325:10)
|
||||
TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/goldie-row324/packages/business/tests/optional-tracker.test.mjs:25:13)
|
||||
Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
Test.run (node:internal/test_runner/test:1402:25)
|
||||
Test.start (node:internal/test_runner/test:1262:17)
|
||||
startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17)
|
||||
...
|
||||
1..1
|
||||
# tests 1
|
||||
# suites 0
|
||||
# pass 0
|
||||
# fail 1
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 54.363835
|
||||
@@ -1,136 +0,0 @@
|
||||
TAP version 13
|
||||
# Subtest: C2-04: library mappings load without roots, remain frozen, and retain mapping refusals
|
||||
ok 1 - C2-04: library mappings load without roots, remain frozen, and retain mapping refusals
|
||||
---
|
||||
duration_ms: 10.358877
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: C2-04: an otherwise valid publish grant cannot name a library repo
|
||||
ok 2 - C2-04: an otherwise valid publish grant cannot name a library repo
|
||||
---
|
||||
duration_ms: 1.405968
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: config directory and file path follow MOSAIC_CONFIG
|
||||
ok 3 - config directory and file path follow MOSAIC_CONFIG
|
||||
---
|
||||
duration_ms: 0.194682
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: the fixture business validates and comes back frozen
|
||||
ok 4 - the fixture business validates and comes back frozen
|
||||
---
|
||||
duration_ms: 0.883527
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: two instances may share a definition
|
||||
ok 5 - two instances may share a definition
|
||||
---
|
||||
duration_ms: 0.869413
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: top-level refusals
|
||||
ok 6 - top-level refusals
|
||||
---
|
||||
duration_ms: 2.622608
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: arbiters and projects
|
||||
ok 7 - arbiters and projects
|
||||
---
|
||||
duration_ms: 3.523393
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: role instances
|
||||
ok 8 - role instances
|
||||
---
|
||||
duration_ms: 2.015683
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: Vikunja bots
|
||||
ok 9 - Vikunja bots
|
||||
---
|
||||
duration_ms: 4.64219
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: a role without Vikunja takes no tracker block
|
||||
ok 10 - a role without Vikunja takes no tracker block
|
||||
---
|
||||
duration_ms: 5.70969
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: credential references match the definition's services
|
||||
ok 11 - credential references match the definition's services
|
||||
---
|
||||
duration_ms: 1.94586
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: launch
|
||||
ok 12 - launch
|
||||
---
|
||||
duration_ms: 6.957271
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: REQ-THREAD-2 REQ-LAUNCH-1 launch.threadIdleSeconds: absent is the default, a positive integer is used, anything else refuses
|
||||
ok 13 - REQ-THREAD-2 REQ-LAUNCH-1 launch.threadIdleSeconds: absent is the default, a positive integer is used, anything else refuses
|
||||
---
|
||||
duration_ms: 3.58016
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: loadBusiness: file checks
|
||||
ok 14 - loadBusiness: file checks
|
||||
---
|
||||
duration_ms: 1.772126
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: loadBusiness: not a regular file
|
||||
ok 15 - loadBusiness: not a regular file
|
||||
---
|
||||
duration_ms: 40.121918
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: loading writes nothing
|
||||
ok 16 - loading writes nothing
|
||||
---
|
||||
duration_ms: 1.07771
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: names that are Object.prototype properties don't count as declared
|
||||
ok 17 - names that are Object.prototype properties don't count as declared
|
||||
---
|
||||
duration_ms: 3.194384
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: the shipped example refuses as written and validates once filled in
|
||||
ok 18 - the shipped example refuses as written and validates once filled in
|
||||
---
|
||||
duration_ms: 0.919964
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: persona vars: agent layer, creative definition only, both or neither
|
||||
ok 19 - persona vars: agent layer, creative definition only, both or neither
|
||||
---
|
||||
duration_ms: 7.866405
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 194 keep, noHire and retired validate, and a file without them loads as before
|
||||
ok 20 - row 194 keep, noHire and retired validate, and a file without them loads as before
|
||||
---
|
||||
duration_ms: 1.704708
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 194 each bad keep, noHire or retired entry refuses
|
||||
ok 21 - row 194 each bad keep, noHire or retired entry refuses
|
||||
---
|
||||
duration_ms: 5.095541
|
||||
type: 'test'
|
||||
...
|
||||
1..21
|
||||
# tests 21
|
||||
# suites 0
|
||||
# pass 21
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 159.214713
|
||||
@@ -1,40 +0,0 @@
|
||||
TAP version 13
|
||||
# Subtest: Q247: omitting tracker loads as null and preserves independent role bots
|
||||
ok 1 - Q247: omitting tracker loads as null and preserves independent role bots
|
||||
---
|
||||
duration_ms: 5.298841
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: Q247: real business validate passes without a sync credential reference or file
|
||||
ok 2 - Q247: real business validate passes without a sync credential reference or file
|
||||
---
|
||||
duration_ms: 71.475563
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: Q247: present tracker retains its values and validation without mutating the input
|
||||
ok 3 - Q247: present tracker retains its values and validation without mutating the input
|
||||
---
|
||||
duration_ms: 2.384907
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: Q247: present null, undefined and malformed trackers still refuse
|
||||
ok 4 - Q247: present null, undefined and malformed trackers still refuse
|
||||
---
|
||||
duration_ms: 3.746
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: Q247: absent business tracker does not waive a role's Vikunja bot requirement
|
||||
ok 5 - Q247: absent business tracker does not waive a role's Vikunja bot requirement
|
||||
---
|
||||
duration_ms: 0.804648
|
||||
type: 'test'
|
||||
...
|
||||
1..5
|
||||
# tests 5
|
||||
# suites 0
|
||||
# pass 5
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 135.467249
|
||||
@@ -1,40 +0,0 @@
|
||||
TAP version 13
|
||||
# Subtest: Q247: omitting tracker loads as null and preserves independent role bots
|
||||
ok 1 - Q247: omitting tracker loads as null and preserves independent role bots
|
||||
---
|
||||
duration_ms: 5.02203
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: Q247: real business validate passes without a sync credential reference or file
|
||||
ok 2 - Q247: real business validate passes without a sync credential reference or file
|
||||
---
|
||||
duration_ms: 68.916604
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: Q247: present tracker retains its values and validation without mutating the input
|
||||
ok 3 - Q247: present tracker retains its values and validation without mutating the input
|
||||
---
|
||||
duration_ms: 2.414133
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: Q247: present null, undefined and malformed trackers still refuse
|
||||
ok 4 - Q247: present null, undefined and malformed trackers still refuse
|
||||
---
|
||||
duration_ms: 3.820979
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: Q247: absent business tracker does not waive a role's Vikunja bot requirement
|
||||
ok 5 - Q247: absent business tracker does not waive a role's Vikunja bot requirement
|
||||
---
|
||||
duration_ms: 0.873886
|
||||
type: 'test'
|
||||
...
|
||||
1..5
|
||||
# tests 5
|
||||
# suites 0
|
||||
# pass 5
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 135.196828
|
||||
@@ -1,34 +0,0 @@
|
||||
TAP version 13
|
||||
# Subtest: Q247: bootConfig omits tracker setup even with tracker variables left in the business
|
||||
ok 1 - Q247: bootConfig omits tracker setup even with tracker variables left in the business
|
||||
---
|
||||
duration_ms: 5.854825
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: Q247: trackerless business boots and registers no @sync credential
|
||||
ok 2 - Q247: trackerless business boots and registers no @sync credential
|
||||
---
|
||||
duration_ms: 48.935736
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: Q247: Console business read works with tracker absent and shows no sync credential
|
||||
ok 3 - Q247: Console business read works with tracker absent and shows no sync credential
|
||||
---
|
||||
duration_ms: 1.663483
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: Q247: a present tracker with a missing token still refuses bus boot
|
||||
ok 4 - Q247: a present tracker with a missing token still refuses bus boot
|
||||
---
|
||||
duration_ms: 11.355417
|
||||
type: 'test'
|
||||
...
|
||||
1..4
|
||||
# tests 4
|
||||
# suites 0
|
||||
# pass 4
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 226.91643
|
||||
@@ -1,34 +0,0 @@
|
||||
TAP version 13
|
||||
# Subtest: Q247: bootConfig omits tracker setup even with tracker variables left in the business
|
||||
ok 1 - Q247: bootConfig omits tracker setup even with tracker variables left in the business
|
||||
---
|
||||
duration_ms: 5.203349
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: Q247: trackerless business boots and registers no @sync credential
|
||||
ok 2 - Q247: trackerless business boots and registers no @sync credential
|
||||
---
|
||||
duration_ms: 46.033814
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: Q247: Console business read works with tracker absent and shows no sync credential
|
||||
ok 3 - Q247: Console business read works with tracker absent and shows no sync credential
|
||||
---
|
||||
duration_ms: 1.547096
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: Q247: a present tracker with a missing token still refuses bus boot
|
||||
ok 4 - Q247: a present tracker with a missing token still refuses bus boot
|
||||
---
|
||||
duration_ms: 11.051525
|
||||
type: 'test'
|
||||
...
|
||||
1..4
|
||||
# tests 4
|
||||
# suites 0
|
||||
# pass 4
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 195.359585
|
||||
@@ -1603,10 +1603,5 @@ are never rewritten or removed; corrections are new entries.
|
||||
2026-10-23T19:29:00Z | Boyd (48a3ae38) | Row 298 (#1804) targeted T1 lane B | Five whole files 29/0/0, ten mutants killed, source restored; reviewer delta prepared. Earlier startup timestamp corrected in Boyd BUILD.md. Full gate and queue/landing remain Sage's.
|
||||
|
||||
2026-10-23T22:41:07Z | Boyd (48a3ae38) | Row 298 rebase under sage-3794; row 321 review assigned | Rebased candidate on boyd/row298-r2 at base833ec1cc8; append-only log conflicts resolved preserving upstream, writer-lock revoke retained; no Node/tests before CLEAR. Row321 awaits pushed candidate/review request.
|
||||
2026-10-23 | Goldie (a13dd6d5-5e73-4b7d-8318-02abeff24940) | Row 322 / #1818 F8/F9 | Investigated clone dependency failure, recovered pinned brief and queue assignment; building on goldie/row322 under mos-1550, tests pending Sage CLEAR.
|
||||
2026-10-23T22:48Z | Goldie (a13dd6d5-5e73-4b7d-8318-02abeff24940) | Row 322 / #1818 F8/F9 builder verification | sage-3808 slot: 54/54 across three whole files, new tests first-run/restored2/2, original-N installer and both mutants fail as intended; bytes restored. Candidate ready for goldie/row322 push and Morgana review; no merge/full-gate claim.
|
||||
2026-10-23T23:15Z | Goldie (a13dd6d5-5e73-4b7d-8318-02abeff24940) | Row 324 / #1820 optional tracker design | New goldie/row324 worktree from approved860afc2b6, pinned brief f375f4e92, complete reader audit/plan. Existing required-key test contradicts Q247; requesting Mos exception before implementation. Tests held until CLEAR; row323 remains deferred until324 lands.
|
||||
2026-10-23T23:18Z | Goldie (a13dd6d5-5e73-4b7d-8318-02abeff24940) | Row 324 / #1820 untested draft | Claim3759; optional tracker implementation, new loader/CLI/boot/Console tests, complete reader audit and prepared mutant. Mos-1556 permits sole existing required-key-list change. Syntax/diff checks pass; no tests before CLEAR. Untested push authorized sage-3836.
|
||||
2026-10-23T23:44Z | Goldie (a13dd6d5-5e73-4b7d-8318-02abeff24940) | Row 324 / #1820 verified rebased candidate | sage-3850: rebase onto3569bf54f, only append-log conflicts; 5/5 +4/4 +21/21, mutant killed/restored, new files rerun9/9; no unexpected red. Publishing goldie/row324-r2 avoids force push. Duckworth review and Sage full gate pending.
|
||||
2026-10-23T23:43:13Z | Sage (1ef1e4f8) | Landed rows 298 (860afc2b6), 322 (467b05fe2) and 321 (5283d3745..3569bf54f), one full gate GREEN on tip 3569bf54f, pushed 23:32:54Z; #1804 #1817 #1818 closed; queue revs 3733-3765 in fb49fa63e; row 324 CLEAR to Goldie; B2-2 to DEFERRED | landed
|
||||
2026-10-23T23:52Z | Duckworth (Opus 5.5) | row 324 round 1 static review on dbdfcfd52 (sage-3853) | APPROVE (static), manifest 52874356 matches, every business.tracker reader handles absence, present null refuses, no @sync when absent, N1 doc (duckworth-0298) |
|
||||
@@ -207,21 +207,8 @@ install -o mosaic -g mosaic -m 0600 /root/<sha>.bundle /srv/mosaic/incoming/<sha
|
||||
sudo -u mosaic -H git clone -q -b refactor /srv/mosaic/incoming/<sha>.bundle /srv/mosaic/src/mosaic-stack
|
||||
```
|
||||
|
||||
After a first install, once both units are running (section 10), adopt the installed copy before
|
||||
any activate or upgrade. This step runs only on Mos's go, with Jason or Mos running it
|
||||
(`scripts/stack-release.sh:14`):
|
||||
|
||||
```sh
|
||||
sudo -u mosaic -H env PATH=/opt/mosaic-stack/node-<v>/bin:/usr/sbin:/usr/bin:/sbin:/bin \
|
||||
/srv/mosaic/src/mosaic-stack/scripts/stack-release.sh adopt <business> --instance dev --units external
|
||||
```
|
||||
|
||||
Each upgrade, before `stack-upgrade.sh upgrade`:
|
||||
|
||||
Only the first upgrade after adopt takes `--no-rehearsal`: append it to the upgrade command below.
|
||||
Adopt writes no backup, so omitting the flag then refuses `no-backup`. Subsequent upgrades omit it;
|
||||
when a backup exists, supplying it refuses `rehearsal-required`.
|
||||
|
||||
```sh
|
||||
echo "<bundle sha256> /root/<sha>.bundle" | sha256sum -c -
|
||||
(
|
||||
@@ -257,13 +244,10 @@ When a run doesn't exit 0, send Mos the exit and the last lines of `/var/log/mos
|
||||
After `case2-install.sh` succeeds, create the human CLI wrapper before running
|
||||
`stack-copy.sh check --units external`. Creating this wrapper is a separate live
|
||||
step requiring Mos's go (`scripts/stack-copy.sh:3`); the install does not create it. Run only on that go:
|
||||
The step runs under sudo's `secure_path`, so it sets its own PATH and umask.
|
||||
|
||||
```sh
|
||||
sudo -u mosaic -H /bin/sh <<'MOSAIC_WRAPPER'
|
||||
cd / || exit 1
|
||||
umask 077
|
||||
PATH=/opt/mosaic-stack/node-<v>/bin:/usr/sbin:/usr/bin:/sbin:/bin; export PATH
|
||||
mkdir -p -- "$HOME/.npm-global/bin" || exit 1
|
||||
"$HOME/src/mosaic-stack/scripts/stack-copy.sh" wrapper <sha> --create
|
||||
MOSAIC_WRAPPER
|
||||
@@ -319,7 +303,7 @@ file with `stat -c '%U %a %n' PATH`, never `cat`. `<business>` is the host's bus
|
||||
|---|---|---|---|---|---|
|
||||
| `/srv/mosaic/.config/mosaic-dev/secrets/` | `claude-session.env`, one line `ZAI_API_KEY=...` | 0600 | mosaic | library | `<path> sets ZAI_API_KEY` |
|
||||
| `/srv/mosaic/.config/mosaic-dev/secrets/` | the Console's proof file, the path the args file's `--proof-file` names | 0600 or 0400 | mosaic | library | none. `case2-unit.sh` refuses at render. Precheck line missing. |
|
||||
| `/srv/mosaic/.config/mosaic-dev/secrets/<business>/` | `library-gitea` | 0600 | mosaic | library | After a unit start, wait for loopback `/healthz` with the bounded retry in section 10 before `case2-precheck.sh --business <business> --library-status`: `library-last-error library-credential-missing` until it's placed, then `library <project> last fetched ...` |
|
||||
| `/srv/mosaic/.config/mosaic-dev/secrets/<business>/` | `library-gitea` | 0600 | mosaic | library | `case2-precheck.sh --business <business> --library-status`, after the bus is up: `library-last-error library-credential-missing` until it's placed, then `library <project> last fetched ...` |
|
||||
| `/srv/mosaic/.config/mosaic-dev/secrets/agents/<business>/<agent>/` | one file per service | 0600, dirs 0700 | mosaic | both | none. Filled only by `mosaic credentials issue`, or Approve after #436. Never by hand. |
|
||||
|
||||
The installer key, `<configDir>/secrets/hosts/<business>/<hostId>/installer`, is not a slot anyone places.
|
||||
@@ -355,20 +339,4 @@ Precheck line: `ok notifier config <dataRoot>/notify/<business>/notify.json
|
||||
None by hand. I2's `case2-unit.sh` enables both units, starts the bus, then the Console (Q189, mos-1122).
|
||||
`stack-upgrade.sh` stops and starts both units itself.
|
||||
|
||||
After a unit start, wait for the Console's loopback `/healthz` to succeed before running
|
||||
`case2-precheck.sh`, including `--library-status` in section 9. Replace `<port>` with the installed
|
||||
Console unit's `--port`. This retry is bounded to 30 attempts, each with a 2-second timeout, with
|
||||
1 second between failed attempts. If it prints STOP, stop here; do not run the precheck or adopt.
|
||||
|
||||
```sh
|
||||
(
|
||||
attempts=0
|
||||
until curl -fsS --max-time 2 -o /dev/null 'http://127.0.0.1:<port>/healthz'; do
|
||||
attempts=$((attempts + 1))
|
||||
[ "$attempts" -lt 30 ] || { echo "STOP: loopback healthz did not become ready; do not continue" >&2; exit 1; }
|
||||
sleep 1
|
||||
done
|
||||
)
|
||||
```
|
||||
|
||||
Precheck line: none. Both units active after the render: precheck line missing.
|
||||
@@ -1,45 +0,0 @@
|
||||
# Case 1 factory business file for .53 (#414 stage 2)
|
||||
|
||||
Written 2026-10-23 by Sage for ops-01's stage-2 request (ops-0277, mos-1551, sage-3807).
|
||||
|
||||
## Brief: the Case 1 factory business file
|
||||
|
||||
**Why.** The .53 factory install (#414) runs `scripts/case2-install.sh --business mosaic-stack
|
||||
--business-file FILE --commit SHA --profile factory`. No Case 1 business file is committed. Row 195 left the
|
||||
role set to the go (agents/darkwing/work/queue-195/DESIGN.md:141 at b65014647). ops-01 needs FILE as a path
|
||||
at a commit.
|
||||
|
||||
**What to write.** One business document, `docs/guides/case1-business.mosaic-stack.json`, and one test that
|
||||
loads it.
|
||||
|
||||
The file's terms come from these sources. Read each one before writing.
|
||||
- Id `mosaic-stack` (DESIGN.md section 7).
|
||||
- `vars` has `bus.tester` true. The file has no `library` key and no library project
|
||||
(case2-install.sh:106-108; case2-precheck.sh's factory profile, `profile-library-business`).
|
||||
- The smallest role set that passes Case 1: a chief of staff from `roles/chief-of-staff.json` with
|
||||
`vars.harness` set to the claude harness, and `launch.by` naming it (case1-accept.sh F3 and F7, :545-559;
|
||||
packages/business/src/business.mjs:123 and :177-199). Add no other role unless the loader or the Case 1
|
||||
checks refuse without it. If one is needed, say which check needs it in BUILD.md.
|
||||
- Claude only. No pi harness and no pi role (P19 #383, mos-0865).
|
||||
- No credential value anywhere. A credential entry, if the loader needs one, is a file path under the
|
||||
install's home, and BUILD.md says which file the operator creates. The chief holds no credential and no
|
||||
tracker bot (packages/business/tests/helpers.mjs:71-72).
|
||||
- `human`, project roots and any other host path use the .53 install's values from DESIGN.md (the `mosaic`
|
||||
user and its home). Where DESIGN.md doesn't give a value, stop and ask me; don't guess a host path.
|
||||
|
||||
**Test.** A new test file, packages/business/tests/case1-business-file.test.mjs, that:
|
||||
1. loads the committed file through the business loader with a temporary config dir and passes;
|
||||
2. runs case2-install.sh's factory-profile checks on it (the same input path the install uses) and passes;
|
||||
3. fails when `bus.tester` is false and when a `library` key is added, with the install's refusal codes.
|
||||
|
||||
No old test changes. If one seems needed, stop and ask me (mos-1272).
|
||||
|
||||
**Gate.** The new test file whole, then packages/business and packages/cli suites whole, on my CLEAR only.
|
||||
One mutant: flip `bus.tester` in the committed file and show the test red, then restore and check bytes.
|
||||
|
||||
**Boundaries.** No host action, no .53 contact, no credential reads, no queue writes, no push to refactor.
|
||||
Work in a new worktree off refactor, on branch `<seat>/row323`. Push the branch and report the tip,
|
||||
base and manifest to Sage. Record design choices in agents/<seat>/work/queue-323/BUILD.md.
|
||||
|
||||
**Acceptance.** The file at a landed commit loads and passes the factory checks. ops-01 can pass its path to
|
||||
case2-install.sh unchanged.
|
||||
@@ -98,13 +98,6 @@ F10, added to this row (ops-0274, mos-1548). Both are confirmed at 094124b4e.
|
||||
ops-01 is testing both on 1013 (mos-1548). F10 is also docs only. The grep in the acceptance list covers its lines too,
|
||||
and BUILD.md records them.
|
||||
|
||||
F11, added to this row (ops-0275, mos-1549): wait for healthz 200 before the precheck. On 1013 a precheck run 1 s
|
||||
after unit start found no `bus.sqlite` yet. Section 10 (Console start) and the `--library-status` row in section 9
|
||||
(":306, after the bus is up") get one instruction: after a unit start, wait until
|
||||
`curl -fsS -o /dev/null http://127.0.0.1:<port>/healthz` succeeds (HTTP 200) before running `case2-precheck.sh`.
|
||||
Use the same loopback form as `scripts/case1-accept.sh:458`, with a bounded retry. F11 is docs only, and the
|
||||
acceptance grep covers its lines too.
|
||||
|
||||
## Brief: F8 and F9, the library persona import runs without the clone's node_modules
|
||||
|
||||
Row: F8 and F9 for the 433 Run B rerun (ops-0273, mos-1546). Builder: a new Codex thread (mos-1542). Reviewer:
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
# Optional tracker in the business file (Q247)
|
||||
|
||||
Written 2026-10-23 by Sage under Mos's mos-1555 (DECISIONS Q247; Jason can reverse it).
|
||||
|
||||
## Brief: tracker becomes optional in the business file
|
||||
|
||||
**Why.** Row 323 (#1819) writes the .53 Case 1 factory business file. The factory has no tracker, and .53
|
||||
has no Vikunja sync bot. Today every business file must carry `tracker.sync` with a bot and a vikunja token
|
||||
file, and both validate and boot refuse a missing token file (goldie-0009). Mos ruled the requirement an
|
||||
implementation constraint, not a PRD one (Q247), and chose an optional tracker over a dummy credential or a
|
||||
new bot (mos-1555).
|
||||
|
||||
**What changes.** A business file may omit the top-level `tracker` key.
|
||||
- Absent `tracker` means no tracker sync, no `@sync` credential, and no `@sync` registration in the bus.
|
||||
- A present `tracker` behaves exactly as today, with the same checks and the same refusals.
|
||||
- Every reader of the business tracker handles the absent case. The ones I found:
|
||||
packages/business/src/business.mjs:85-96 and :293-297 (checkTracker and the own-bot check),
|
||||
packages/business/src/cli.mjs:84-86 (validate's credential refs), packages/bus/src/runtime.mjs:131 and
|
||||
:247, packages/bus/src/broker.mjs:6123, packages/business/src/instance-settings.mjs:126, and
|
||||
packages/cli/src/config.mjs's trackerFor. Grep for the rest
|
||||
(`git grep -n -E 'tracker\.sync|\.tracker\b' -- 'packages/*/src/*'`) and list every reader in BUILD.md
|
||||
with what it does when tracker is absent.
|
||||
- A role whose definition uses vikunja still needs its own `tracker` bot (business.mjs:143). That rule stays.
|
||||
|
||||
**Tests.** New tests only. No pre-existing test changes without Mos's OK (mos-1272); if one seems needed,
|
||||
stop and tell me.
|
||||
1. A business file with no `tracker` passes the loader and `mosaic business validate`.
|
||||
2. The bus boots with that file and raises no credential-file error, and `@sync` isn't registered.
|
||||
3. Existing fixtures, all of which carry a tracker, load unchanged. The existing suites show this.
|
||||
4. One mutant that skips the presence check, treating an absent tracker as present, is killed by a new test.
|
||||
|
||||
**Gate.** New test files whole, then the whole touched test files, then the mutant, all on my CLEAR. My
|
||||
landing gate is the full one (mos-1455).
|
||||
|
||||
**Boundaries.** No host action, no credentials read, no queue writes beyond your own claimant moves, no
|
||||
push to refactor. Use a new worktree off refactor on branch `<seat>/row324`. Push the branch, then report
|
||||
the tip, base and manifest to Sage. Record design notes in agents/<seat>/work/queue-324/BUILD.md.
|
||||
Duckworth reviews, because this touches credential registration.
|
||||
|
||||
**Acceptance.** Row 323's file, written without `tracker`, passes validate and boots. Every file with a
|
||||
tracker behaves exactly as before.
|
||||
@@ -711,34 +711,3 @@ webby/reviews c6ea27aab). docs/case2/SURVEY-RUN.md:96 documents the `--mapping`
|
||||
`scopes canon .., playground .., unmapped ..; indexed ..`, which predates the supporting scope 283 adds.
|
||||
Nothing reads the file (decision 137). Bound to the next docs commit that touches SURVEY-RUN.md: add the
|
||||
supporting count to that line.
|
||||
|
||||
## ops-0275 O2 and O3: triage, no row
|
||||
|
||||
Sage, for Mos's mos-1549 (433 factory on 1013, ops-0275). Neither is a defect, so neither gets a row.
|
||||
|
||||
O2, `bus status` shows writer.lock pid 4174 while the unit's host pid is 4078. By design. `scripts/mosaic`
|
||||
execs node (scripts/mosaic:44), so the unit's MainPID is the bus host. The host forks the broker
|
||||
(packages/cli/src/host.mjs:1, :215), and the broker's Store writes its own `process.pid` into
|
||||
`<dataRoot>/bus/writer.lock` (packages/bus/src/store.mjs). The lock holder is the host's child. The
|
||||
status line's liveness check (packages/cli/src/cli.mjs:612) reported it running, so it isn't stale.
|
||||
If an operator note is wanted, the next row that edits `bus status` output can name the broker pid as the
|
||||
host's child; nothing binds it now.
|
||||
|
||||
O3, the copy's npm step warns that @google/genai, esbuild and protobufjs have install scripts outside
|
||||
allowScripts. scripts/stack-copy.sh:74 runs `npm ci --no-audit --no-fund`. On npm 12.0.2 (dragon-lin)
|
||||
dependency install scripts are blocked by default: npm skips any dependency script with no allowScripts
|
||||
entry and lists the skipped packages at the end (`npm help install-scripts`). So the copy skips all three.
|
||||
The 433 factory passed on that copy, and the landing gates (webui included) pass with the same skip.
|
||||
Recommendation: refuse, not allow. An explicit `false` entry for each in package.json allowScripts makes
|
||||
the tested behavior the written policy and drops the warning (`npm help config`, strict-allow-scripts:
|
||||
explicit denials are always skipped silently). That edits package.json, so it waits for the next reviewed
|
||||
row that touches package.json; bound there.
|
||||
|
||||
## ops-0282 B2-2: the run sheet doesn't state the Console proof file format
|
||||
|
||||
Sage, for Mos's mos-1557 (433 Run B P1 at 3569bf54f). docs/guides/host-run-sheet.md:321, the .54 library
|
||||
table, gives the Console proof file's mode (0600 or 0400) and owner but not its format. The Console reads
|
||||
one base64url line of at least 32 characters, `[A-Za-z0-9_-]` only (packages/webui/src/serve.mjs:264), and
|
||||
exits 2 at start otherwise (:267). case2-unit.sh doesn't open the file, so a short or malformed proof fails
|
||||
only at Console start. That's what stopped Run B P1 (B2-1, ops-01's 24-byte fixture). Fix: add the format to
|
||||
the File cell of that row. Doc only, no test reads it; bound to the next doc row that edits the run sheet.
|
||||
+4
-6
@@ -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 3765 by `queue render`. Do not edit between the markers; change the queue with `scripts/mosaic queue`.
|
||||
Generated from `docs/plans/queue.json` revision 3732 by `queue render`. Do not edit between the markers; change the queue with `scripts/mosaic queue`.
|
||||
|
||||
| # | Piece | Owner | Issues | State | After | Gate | Brief | Note |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
@@ -334,7 +334,7 @@ Generated from `docs/plans/queue.json` revision 3765 by `queue render`. Do not e
|
||||
| 295 | FED R4: revocation | morgana; reviewers dewey | #1801 | done | — | Dewey approves the manifest. The bus, cli and business suites and every scripts/test-*.sh are green on Sage's gate, and the mutants are killed. (sage) | `docs/plans/2026-10-23_mvp-readiness-rows.md` § Brief: FED R4, revocation | LANDED 2efd127ce on refactor 10:10Z 10-23 (9 commits cherry-picked onto 07802dc57, range-diff all =, patch-ids match, HEAD~1 tree a86592ffc = gated tree, top commit BUILD.md doc-only). Gate d68b4300d manifest e94c9aeb: 13 whole files, bus 886/0, business 231/0, cli 924/0, harness 151/0, all test-*.sh rc 0, M1-M16 killed, M8 per mos-1436. Dewey approve rev 3500 c31102. Re-pin precheck mos-1436 cond 11 binds. |
|
||||
| 296 | FED R7: scratch two-instance acceptance | lena; reviewers filbert | #1802 | briefed | 190 done, 294 done, 295 done | Filbert approves the manifest. The script test and every scripts/test-*.sh are green on Sage's gate, and no unit, port or socket of the script's outlives the run. (sage) | `docs/plans/2026-10-23_mvp-readiness-rows.md` § Brief: FED R7, scratch two-instance acceptance | — |
|
||||
| 297 | GitHub grant method (Bushroot's half of #436b) | violet; reviewers dewey | #1803 | briefed | 198 done | Dewey approves the manifest. The touched suites and every scripts/test-*.sh are green on Sage's gate, and the mutants are killed. (sage) | `docs/plans/2026-10-23_mvp-readiness-rows.md` § Brief: the GitHub grant method (Bushroot's half of #436b) | — |
|
||||
| 298 | Q228: chief-of-staff grant scope | boyd; reviewers dewey | #1804 | done | 252 done | Dewey approves the manifest. The touched suites and every scripts/test-*.sh are green on Sage's gate, and the mutants are killed. (sage) | `docs/plans/2026-10-23_mvp-readiness-rows.md` § Brief: the chief-of-staff grant scope (Q228) | LANDED 860afc2b6 (ff from 833ec1cc8), pushed with tip 3569bf54f 23:32:54Z 10-23. Dewey APPROVE c31449 rev 3754. Boyd reruns 29/0, M1-M10 killed. Sage full gate GREEN 23:32:28Z on combined tip 3569bf54f (298+322+321): every package suite 0 fail 0 skip (bus 924, business 249, cli 982, plugins 119, webui 411), every scripts/test-*.sh rc 0, queue 156/0. Live unchanged 45dca69f6 schema 3n. |
|
||||
| 298 | Q228: chief-of-staff grant scope | boyd; reviewers dewey | #1804 | in-review, round 1, request posted | 252 done | Dewey approves the manifest. The touched suites and every scripts/test-*.sh are green on Sage's gate, and the mutants are killed. (sage) | `docs/plans/2026-10-23_mvp-readiness-rows.md` § Brief: the chief-of-staff grant scope (Q228) | — |
|
||||
| 299 | 573: the P10 hop band (Vikunja 573) | gander; reviewers filbert | #1806 | done | 293 done | Filbert approves. The whole file under load at least 3 times, then the cli suite, are green on Sage's gate. (sage) | `docs/plans/2026-10-23_mvp-readiness-rows.md` § Brief: 573, the P10 hop band (Vikunja 573) | landed ffb2fedfb 08:03Z on 15e688cc0 via Filbert SESSIONS c1f910b4c; 5 commits = gander/row299-gate-277ace0b 63db96d8b (range-diff 5/5 =, tree differs only BUILD-LOG/SESSIONS); manifest 277ace0b sha256 -c OK. Gate green on ffa93b054: case1 whole 3x 53/0/0, cli whole 917/0/0 (59 files), P10 inner 2.27 outer 4.01, M1-M6 killed (gander-0189). Filbert approve rev 3485 c31084; N1 M1 1.23 s margin. |
|
||||
| 300 | R6-N1: HTTP-level test of the user-session option swap (294 N1) | launchpad; reviewers duckworth | #1807 | done | 294 done | Duckworth approves the manifest; new test file whole, webui suite, mutant M12 killed (sage) | `docs/plans/2026-10-23_r6-followup-rows.md` § Brief: R6-N1, an HTTP-level test of the user-session option swap | Landed on refactor as 9d929911c..07315e651 (from launchpad/row300 a00b25b37, range-diff equal), pushed 5b846b048 12:28Z. Duckworth approved r2 (c31158, rev 3559). Sage gate on bcf3c1dac: user-option-swap 1/0, webui 375/0 with pinned esbuild and MOSAIC_REQUIRE_EDITOR_BUILD=1, M12 killed at :151. Run 1 red placed under mos-1272 (headers). N1 deferred: board proxy upstream has no recorder. |
|
||||
| 301 | R6-N4: fold user-bus.mjs back into bus.mjs (294 N4) | launchpad; reviewers duckworth | #1808 | done | 294 done | Duckworth approves the manifest; channel-proof.test, webui suite and 294 user-transport tests whole and green; re-pin only with Mos go (sage) | `docs/plans/2026-10-23_r6-followup-rows.md` § Brief: R6-N4, fold user-bus.mjs back into bus.mjs | Landed on refactor as bb031ec84..5b846b048 (from launchpad/row301 acc97fb9c, range-diff equal), pushed 12:28Z. Re-pin of webui bus.mjs to 39fcb27c is its own commit 59f0e44f4 (mos-1449); fixture stubs per mos-1451. Duckworth approved r2 (c31159, rev 3560). Sage gate: channel-proof 2/0, webui 374/0 pinned esbuild, granted-user 19/0. Live unchanged; 301 makes its own re-pin window. |
|
||||
@@ -357,10 +357,8 @@ Generated from `docs/plans/queue.json` revision 3765 by `queue render`. Do not e
|
||||
| 318 | 571 W8: Console Connections view for Markdown and DOCX story files, before W7's first real import (post-10-27, mos-1470) | unassigned | — | queued | 314 done, 315 done, 317 done | Independent Opus 5.5 reviewer, not the author, approves the manifest; the brief section's Gate and G1 pass on Sage's slot: touched test files whole, affected package suites green, named mutants killed. Post-10-27; MVP rows keep slot priority (sage) | `docs/plans/2026-10-21_q195-writing-editor.md` § W8 Console Connections view for Markdown and DOCX story files | fenton-0017 carry: connections.test.mjs must test that links inside comments and tracked deletions are excluded. W8 follows W7's closed routing candidate and lands before W7's first real import opens (mos-1470) |
|
||||
| 319 | GitHub consumer for row 297's protected githubWithToken callback, honoring expiry and cancellation (post-10-27) | unassigned; reviewers dewey | — | queued | 297 done | Dewey approves the design and the manifest. The touched suites and every scripts/test-*.sh are green on Sage's gate, and the signal and expiry mutants are killed. (sage) | `docs/plans/2026-10-23_github-consumer-brief.md` § Brief: a GitHub consumer for Broker.githubWithToken | — |
|
||||
| 320 | Case 1/2 host fixes for the 433 P1 rerun: hostcheck item 5 mode 750, run sheet bundle verify, case2-unit --claude @, stack-copy unreadable cwd, notify.json step and precheck, mosaic wrapper step (10-27 path) | gladstone; reviewers morgana | #1816 | required; done | — | Morgana approves. Touched test files run whole (case1-hostcheck, case2-unit, case2-install, stack-copy) and the 8 named mutants are killed; Sage's full landing gate runs every package suite and every scripts/test-*.sh. After landing Mos sends ops-01 the new N. (sage) | `docs/plans/2026-10-23_host-fixes-1816-brief.md` § Brief: hostcheck item 5, bundle verify, case2-unit @, stack-copy cwd | LANDED 094124b4e 21:53Z (replay of faf55618e onto 45e3ca7bd, code paths patch-id equal, log appends in one final commit). F1-F6 hostcheck item 5, bundle verify, case2-unit scoped paths and cwd, precheck notify decision, run sheet 9a notify dirs 0700, wrapper step. Morgana APPROVE r2 c31403 rev 3715. Full gate GREEN 21:53:00Z, 0 fail (mos-1453/1455/1456). Vikunja 614 done. 433 P1 reruns on this N (mos-1532). |
|
||||
| 321 | F7, F10, F11: run sheet wrapper step umask and node PATH under sudo; adopt step after a first install; --no-rehearsal on the first upgrade; wait for healthz 200 before a precheck (433, ops-0271/0274/0275); docs only | gladstone; reviewers boyd | #1817 | required; done | — | Boyd (Codex) approves. A git grep with a positive control shows no test reads the changed run sheet lines; BUILD.md records the diff and the grep. Doc only, lands with any row (mos-1544). (sage) | `docs/plans/2026-10-23_host-fixes-1816-brief.md` § Brief: F7, the wrapper step's PATH and umask under sudo | LANDED 5283d3745, 3fd5307e1, 3569bf54f: cherry-picks of b5d4d7903, d9400f0d3, 9aae73ade with equal patch-ids. Doc only. Pushed tip 3569bf54f 23:32:54Z 10-23. Boyd APPROVE c31450 rev 3757, grep with positive control in BUILD.md. Rode the full gate GREEN 23:32:28Z on 3569bf54f. Live unchanged 45dca69f6. |
|
||||
| 322 | F8/F9: case2-install.sh runs the library persona import from the stack copy, and its refusal carries the error line (433 Run B, ops-0273) | goldie; reviewers morgana | #1818 | required; done | — | Morgana approves (install path). The new case2-install test fails on 094124b4e and passes on the candidate; a mutant restoring REPO at :185 is killed; Sage's full landing gate runs every package suite and scripts/test-*.sh. Then ops-01 reruns Run B P1. (sage) | `docs/plans/2026-10-23_host-fixes-1816-brief.md` § Brief: F8 and F9, the library persona import runs without the clone's node_modules | LANDED 467b05fe2, cherry-pick of 7b4ea4217 on 860afc2b6; added and removed lines identical, patch-id differs only by BUILD-LOG/SESSIONS append context (both sides kept). Pushed with tip 3569bf54f 23:32:54Z 10-23. Morgana APPROVE c31451 rev 3758, N1-N3 non-blocking. Sage full gate GREEN 23:32:28Z on 3569bf54f, all suites 0 fail, every scripts/test-*.sh rc 0. Next: ops-01 Run B P1 rerun on 467b05fe2 (mos-1553). Live unchanged 45dca69f6. |
|
||||
| 323 | Case 1 factory business file for .53: docs/guides/case1-business.mosaic-stack.json plus a loader and factory-check test (#414 stage 2, ops-0277) | goldie; reviewers duckworth | #1819 | in-progress | — | Sage full gate: all package suites except queue plus every scripts/test-*.sh (mos-1455); Duckworth review; new test file and one bus.tester mutant on CLEAR (sage) | `docs/plans/2026-10-23_case1-business-file-brief.md` § Brief: the Case 1 factory business file | — |
|
||||
| 324 | Tracker optional in the business file (Q247) | goldie; reviewers duckworth | #1820 | in-progress | — | New tests only. Absent tracker: loader and validate pass, the bus boots with no credential-file error and no @sync. Present tracker unchanged. A mutant that skips the presence check is killed. Then whole touched test files, then the full landing gate. (sage) | `docs/plans/2026-10-23_optional-tracker-brief.md` § Brief: tracker becomes optional in the business file | — |
|
||||
| 321 | F7 and F10: host run sheet wrapper step sets umask 077 and the node PATH under sudo secure_path; adopt step after a first install; --no-rehearsal on the first upgrade after adopt (433, ops-0271/0274); docs only | gladstone; reviewers boyd | #1817 | required; briefed | — | Boyd (Codex) approves. A git grep with a positive control shows no test reads the changed run sheet lines; BUILD.md records the diff and the grep. Doc only, lands with any row (mos-1544). (sage) | `docs/plans/2026-10-23_host-fixes-1816-brief.md` § Brief: F7, the wrapper step's PATH and umask under sudo | — |
|
||||
| 322 | F8/F9: case2-install.sh runs the library persona import from the stack copy, and its refusal carries the error line (433 Run B, ops-0273) | goldie; reviewers morgana | #1818 | required; briefed | — | Morgana approves (install path). The new case2-install test fails on 094124b4e and passes on the candidate; a mutant restoring REPO at :185 is killed; Sage's full landing gate runs every package suite and scripts/test-*.sh. Then ops-01 reruns Run B P1. (sage) | `docs/plans/2026-10-23_host-fixes-1816-brief.md` § Brief: F8 and F9, the library persona import runs without the clone's node_modules | — |
|
||||
|
||||
<!-- mosaic-queue:end -->
|
||||
|
||||
|
||||
+19
-1080
File diff suppressed because it is too large.
Load diff
@@ -67,11 +67,7 @@ function world(t, { profile = "library" } = {}) {
|
||||
const log = join(root, "calls.log");
|
||||
script(join(bin, "stack-copy"), `echo "stack-copy $*" >>'${log}'
|
||||
[ "$1" = copy ] && [ "$3" = --copies ] || exit 4
|
||||
mkdir -p "$4/$2/scripts" && : >"$4/$2/scripts/mosaic" && echo "copied: $4/$2"
|
||||
for file in scripts/case2-persona-import.mjs packages/harness/src/bundle.mjs packages/harness/src/tools.mjs packages/business/src/vocabulary.mjs; do
|
||||
mkdir -p "$4/$2/$(dirname "$file")" && cp '${REPO}'"$file" "$4/$2/$file" || exit 1
|
||||
done
|
||||
mkdir -p "$4/$2/node_modules" && cp -R '${REPO}node_modules/yaml' "$4/$2/node_modules/yaml"`);
|
||||
mkdir -p "$4/$2/scripts" && : >"$4/$2/scripts/mosaic" && echo "copied: $4/$2"`);
|
||||
script(join(bin, "systemctl"), `echo "systemctl $*" >>'${log}'`);
|
||||
const me = spawnSync("id", ["-un"], { encoding: "utf8" }).stdout.trim();
|
||||
script(join(bin, "getent"), `[ "$1" = passwd ] && [ "$2" = '${me}' ] && echo '${me}:x:${UID}:${GID}::${home}:/bin/bash'`);
|
||||
@@ -421,55 +417,3 @@ test("Vikunja 614: install preserves the explicit notifier decision bytes and mo
|
||||
assert.equal(fresh.code, 0, fresh.out);
|
||||
assert.equal(existsSync(missing), false);
|
||||
});
|
||||
|
||||
// Row 322 (#1818), F8/F9: a clone without dependencies and a dependency-equipped copy.
|
||||
import { cpSync } from "node:fs";
|
||||
|
||||
function dependencyFreeClone(t) {
|
||||
const x = world(t);
|
||||
const clone = join(x.root, "clone");
|
||||
mkdirSync(join(clone, "scripts"), { recursive: true });
|
||||
for (const file of ["case2-install.sh", "case2-persona-import.mjs"]) {
|
||||
cpSync(join(REPO, "scripts", file), join(clone, "scripts", file));
|
||||
}
|
||||
// Isolate the persona step; bootstrap and business validation are covered above.
|
||||
script(join(clone, "scripts", "bootstrap.sh"), "exit 0");
|
||||
script(join(clone, "scripts", "mosaic"), "exit 0");
|
||||
assert.equal(existsSync(join(clone, "node_modules")), false);
|
||||
const run = () => {
|
||||
const r = spawnSync(join(clone, "scripts", "case2-install.sh"), [
|
||||
"--business", "acme", "--business-file", x.input, "--commit", COMMIT,
|
||||
"--profile", "library", "--personas", x.staging,
|
||||
], { env: env(x), encoding: "utf8", timeout: 30000 });
|
||||
const out = r.stdout + r.stderr;
|
||||
clean(out);
|
||||
return { code: r.status, out };
|
||||
};
|
||||
return { ...x, clone, run };
|
||||
}
|
||||
|
||||
test("row 322 F8: library personas install from the copy with no clone node_modules", (t) => {
|
||||
const x = dependencyFreeClone(t);
|
||||
const r = x.run();
|
||||
assert.equal(r.code, 0, r.out);
|
||||
for (const instance of ["bean", "chet"]) {
|
||||
assert.equal(readFileSync(join(x.personaDir, `${instance}.md`), "utf8"), PERSONA_TEXT[instance]);
|
||||
assert.equal(mode(join(x.personaDir, `${instance}.md`)), 0o600);
|
||||
}
|
||||
assert.equal(existsSync(join(x.clone, "node_modules")), false);
|
||||
});
|
||||
|
||||
test("row 322 F9: importer refusal keeps the error line rather than the Node banner", (t) => {
|
||||
const x = dependencyFreeClone(t);
|
||||
const copy = join(x.home, ".local", "share", "mosaic-stack", "copies", COMMIT);
|
||||
// Real Node module-load error: the error precedes its stack and version banner.
|
||||
const fake = join(x.bin, "stack-copy");
|
||||
writeFileSync(fake, `${readFileSync(fake, "utf8")}\nrm -rf '${copy}/node_modules/yaml'\n`);
|
||||
const r = x.run();
|
||||
refused(r, /persona-import: Error \[ERR_MODULE_NOT_FOUND\]: Cannot find package 'yaml'/);
|
||||
const refusal = r.out.split("\n").filter((line) => line.includes("refused:"));
|
||||
assert.equal(refusal.length, 1, r.out);
|
||||
assert.doesNotMatch(r.out, /Node\.js v|\n\s+at /);
|
||||
assert.equal(existsSync(x.business), false);
|
||||
assert.equal(existsSync(x.personaDir), false);
|
||||
});
|
||||
@@ -73,7 +73,7 @@ test('copy writes the Console paths at the full id, read-only, and leaves an exi
|
||||
assert.match(r.stdout, new RegExp(`^copied: ${target}$`, 'm'));
|
||||
assert.deepEqual(readdirSync(copies), [head], 'no temp directory left behind');
|
||||
assert.deepEqual(readdirSync(target).sort(), ['RELEASE', 'adapters', 'package-lock.json', 'package.json', 'packages', 'roles', 'scripts', 'tools']);
|
||||
assert.deepEqual(readdirSync(join(target, 'scripts')), ['case2-persona-import.mjs', 'mosaic', 'mosaic-config.mjs']);
|
||||
assert.deepEqual(readdirSync(join(target, 'scripts')), ['mosaic', 'mosaic-config.mjs']);
|
||||
assert.ok(existsSync(join(target, 'packages', 'webui', 'README.md')), "the unit's Documentation=");
|
||||
assert.equal(statSync(join(target, 'packages', 'webui', 'README.md')).mode & 0o222, 0, 'README.md is read-only');
|
||||
assert.ok(existsSync(join(target, 'packages', 'tasks', 'fields.json')), 'the task field table');
|
||||
|
||||
@@ -182,8 +182,8 @@ say "copy $COPIES/$COMMIT"
|
||||
# 4. library: the personas, from the staging dir.
|
||||
if [ "$PROFILE" = library ]; then
|
||||
if [ "$PERSONA_STATE" = install ]; then
|
||||
out="$(node "$COPIES/$COMMIT/scripts/case2-persona-import.mjs" install --staging "$PERSONAS" --config-dir "$CONFIG_DIR" --business "$BUSINESS" 2>&1)" \
|
||||
|| refuse "persona-import: $(printf '%s\n' "$out" | awk '/^[[:alnum:]_]*Error|^ERR_/ { print; found=1; exit } { last=$0 } END { if (!found) print last }')"
|
||||
out="$(node "$REPO/scripts/case2-persona-import.mjs" install --staging "$PERSONAS" --config-dir "$CONFIG_DIR" --business "$BUSINESS" 2>&1)" \
|
||||
|| refuse "persona-import: $(printf '%s' "$out" | tail -n 1)"
|
||||
while IFS=$'\t' read -r _ inst name sum; do
|
||||
printf '%s\n' "$out" | grep -qxF "instance $inst: persona.name $name, persona.sha256 $sum" \
|
||||
|| refuse "persona-import: the import did not report $inst with the manifest's sha256"
|
||||
|
||||
@@ -27,7 +27,7 @@ copy_root() { [[ "$ID" =~ ^[0-9a-f]{40}$ ]] || die '--copy must be a full 40-cha
|
||||
# Closure of scripts/mosaic, bus process/notifier/launcher, Console serve,
|
||||
# human-cli and both harness adapters, including on-demand children/data.
|
||||
COPY_PATHS=(
|
||||
scripts/mosaic scripts/mosaic-config.mjs scripts/case2-persona-import.mjs
|
||||
scripts/mosaic scripts/mosaic-config.mjs
|
||||
adapters roles RELEASE package.json package-lock.json
|
||||
packages/bus/src packages/bus/schema.sql packages/business/src packages/cli/src packages/project
|
||||
packages/conversation/src packages/discord/src packages/discord/bin packages/discord/extension packages/harness/src
|
||||
|
||||
Reference in new issue
Block a user