work: Rocko row 108 round 1 packet (#1602), candidate manifest 19ef7133db59
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -0,0 +1,127 @@
|
|||||||
|
# Row 108 — Bus unit drop-in guard, usage and wrapper (#1602)
|
||||||
|
|
||||||
|
Rocko, GPT-6.1-Sol. Reviewer Filbert. Base 234121b30 (base.txt).
|
||||||
|
Sage assignment sage-0223 and slot grant sage-0224, 2026-10-14.
|
||||||
|
Detached worktree /mnt/storage/src/mosaic-stack-rocko-108. No candidate
|
||||||
|
code commit or live action; Sage moves in-review and requests as jarvis.
|
||||||
|
|
||||||
|
## Scope and implementation
|
||||||
|
|
||||||
|
Same existing guard scans each systemd-analyze lookup directory for the
|
||||||
|
bus instance/template drop-ins plus mosaic-.service.d and service.d.
|
||||||
|
Overriding ExecStart/WorkingDirectory, unreadable directory/file or discovery
|
||||||
|
failure refuses before writing. Tests pin both inherited directory types,
|
||||||
|
both overriding fields, unchanged prior unit, allowed Environment-only
|
||||||
|
files, and unreadable dangling directory/file symlinks. All systemd reads
|
||||||
|
and writes in tests hit fakes, install --dir temporary --no-reload only.
|
||||||
|
|
||||||
|
Header render/install comments now include --copy, --copies and --pm.
|
||||||
|
Dead show replies were removed from both host install fakes and all stack
|
||||||
|
install fakes. The systemd261 template-show rejection remains deliberately
|
||||||
|
exercised by a fixture-only probe; the status fake's show arm is reached by
|
||||||
|
status. Thus every retained show arm has a test and no successful template
|
||||||
|
show is reintroduced.
|
||||||
|
|
||||||
|
Wrapper writes copy-root and Q81 mosaic-old lease comments after the marker.
|
||||||
|
Marker stays line 2, exact lease stays unchanged, copy exec stays last.
|
||||||
|
Tests assert both comments, lease execution, same-copy check success and a
|
||||||
|
foreign marker refusal with all effective roots and the exec path matching.
|
||||||
|
No wrapper preservation beyond these defined lines or copy-path change.
|
||||||
|
|
||||||
|
## Install-script audit — recorded finding, no policy change
|
||||||
|
|
||||||
|
Read-only audit-install-scripts.py reads package-lock and installed package
|
||||||
|
metadata (versions verified); out/install-scripts-audit.json records hashes,
|
||||||
|
lifecycle commands, copied-source mentions and external bundle imports.
|
||||||
|
No npm lifecycle is executed by the audit, and it reads no config/token.
|
||||||
|
|
||||||
|
| Package | Pinned version / blocked lifecycle | Runtime relevance |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| @google/genai | 1.52.0; preinstall echoes preinstall: no-op | No copied source reference or external bundled Pi import; script creates no runtime artifact. |
|
||||||
|
| esbuild | 0.28.1; postinstall node install.js installs/checks the build binary | No copied source reference or external bundled Pi import; copy runs published code and does not build Pi. |
|
||||||
|
| protobufjs | 7.6.6; postinstall node scripts/postinstall | No copied source reference or external bundled Pi import; inspected script reads package versions and warns about dependency version schemes, creates no runtime artifact. |
|
||||||
|
|
||||||
|
The dependency edge is not sufficient to declare an installed entrypoint
|
||||||
|
active: unbundled pi-ai providers do import @google/genai when selected,
|
||||||
|
but Mosaic's paths launch the published **bundled** CLI, not those SDK
|
||||||
|
modules. Controller imports PI_BIN from conversation/src/pi-pin.mjs:34,
|
||||||
|
which selects node_modules/@earendil-works/pi-coding-agent/dist/bundle/cli.js;
|
||||||
|
adapters/pi/adapter.sh execs pi, whose package.json bin selects the same
|
||||||
|
entry. The audit scans every bundle chunk, including dynamic literal
|
||||||
|
imports and require, and finds no external load of these three entrypoints.
|
||||||
|
Installed unbundled SDK/extension paths or future runtime loaders would need
|
||||||
|
a new audit; this finding does not authorize allowScripts. README states
|
||||||
|
why the present copy warnings are expected. No blocked script is needed by
|
||||||
|
the observed current copy paths; no allowScripts change is proposed.
|
||||||
|
|
||||||
|
## Verification and honest correction
|
||||||
|
|
||||||
|
Focused red: four expected assertion failures against unchanged product
|
||||||
|
code (out/red.txt). Focused green: four pass after the minimal changes.
|
||||||
|
The first full gate passed; first mutants killed 6/7. The foreign marker
|
||||||
|
mutant survived because the foreign fixture also had a mismatched exec.
|
||||||
|
The final fixture matches its exec and all effective roots, isolating the
|
||||||
|
marker; its normal test passes, and the full mutation/gate runs are repeated.
|
||||||
|
First receipts remain out/full-first and out/mutants-first.
|
||||||
|
|
||||||
|
Mutants use their own process groups and kill the group on timeout, restore
|
||||||
|
source in finally and run serially. DOCKER_HOST=unix:///nonexistent.sock for
|
||||||
|
all node/script/mutant runs. Docker-dependent script checks are explicitly
|
||||||
|
skipped, not passing claims. CLI includes the real pinned npm-ci integration
|
||||||
|
fixture; no live bus, Console, binding or token is read. Final counts,
|
||||||
|
mutation table and process/network-clear receipts follow below.
|
||||||
|
|
||||||
|
## Protected boundary and review
|
||||||
|
|
||||||
|
No real systemd read/write, install/enable/reload/restart or ~/.npm-global/bin
|
||||||
|
access. No source commit, push or live re-pin. This row takes effect only
|
||||||
|
in a future copy/re-pin separately approved in Mos's window. Row114 starts
|
||||||
|
only after this row's landing, on a base including it. Decision137: any
|
||||||
|
review doc-only follow-ups ship in a separate packet after landing.
|
||||||
|
|
||||||
|
## Final gate and mutation evidence
|
||||||
|
|
||||||
|
| Suite | Passed | Failures / coverage |
|
||||||
|
| --- | ---: | --- |
|
||||||
|
| CLI node | 187 | 0 failed, skipped or cancelled |
|
||||||
|
| test-auth.sh | 15 | 0 |
|
||||||
|
| test-conductor.sh | 17 | 0 |
|
||||||
|
| test-config.sh | 24 | 0 |
|
||||||
|
| test-discord.sh | 66 | 0; also Discord node 178 |
|
||||||
|
| test-extension-package.sh | 18 | 0 |
|
||||||
|
| test-foundation.sh | 44 | 0; also foundation node 80 |
|
||||||
|
| test-land-work.sh | 84 | 0 |
|
||||||
|
| test-queue.sh | 28 | 0; also queue node 156; two canonical-root checks skipped |
|
||||||
|
| test-release.sh | 4 | 0; Docker state-machine cases skipped |
|
||||||
|
| test-task.sh | 26 | 0; four Docker-dependent blocks skipped |
|
||||||
|
|
||||||
|
DOCKER_HOST=unix:///nonexistent.sock. Task skips the adapter/mission/retry/
|
||||||
|
skills/roles/seat/policy/user-injection block, workspace/capability block,
|
||||||
|
live task/session-fork block and live recall pair. It does not establish
|
||||||
|
Docker/provider coverage. No observed #258/#261/#262/#263 gate recurrence.
|
||||||
|
|
||||||
|
| Mutant | Exit | Result |
|
||||||
|
| --- | ---: | --- |
|
||||||
|
| miss-prefix | 1 | killed |
|
||||||
|
| miss-all-services | 1 | killed |
|
||||||
|
| ignore-unreadable-directory | 1 | killed |
|
||||||
|
| ignore-unreadable-file | 1 | killed |
|
||||||
|
| omit-copy-comment | 1 | killed |
|
||||||
|
| omit-lease-comment | 1 | killed |
|
||||||
|
| accept-foreign-check-wrapper | 1 | killed |
|
||||||
|
|
||||||
|
Final 7/7 killed, no timeout. Final full gate 20:08:16-20:09:52 UTC.
|
||||||
|
Own process-group timeout cleanup is in mutants.py. Runner completions
|
||||||
|
were confirmed before process-sweep.py exited 0 with busy []. Docker's
|
||||||
|
read-only network inspect explicitly reported mosaic-stack-rocko-108_default
|
||||||
|
not found, so no network removal was needed. Slot returned to Sage at
|
||||||
|
20:09:59 UTC. No subsequent tests.
|
||||||
|
|
||||||
|
Candidate manifest SHA256:
|
||||||
|
19ef7133db592787c24fa473357687a5741ccd7823627b970624c930a7611dbc.
|
||||||
|
6/6 candidate hashes match after all fault injections. build.patch applies
|
||||||
|
to canonical HEAD and diff --check is clean; no candidate-path drift.
|
||||||
|
No source commit or protected action performed. Sage owns the in-review
|
||||||
|
move/request; row remains in-progress at builder rev1178 until that move.
|
||||||
|
|
||||||
|
Own append-only log commit: d7430483626f82c8c8c39b84cae03925d2c811bb. Candidate source remains uncommitted.
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
"""Read-only audit of pinned local source and installed package metadata. No import/evaluation."""
|
||||||
|
from pathlib import Path
|
||||||
|
import json,re,hashlib
|
||||||
|
root=Path.cwd();lock=json.loads((root/'package-lock.json').read_text());report={}
|
||||||
|
names=['@google/genai','esbuild','protobufjs'];bundle=root/'node_modules/@earendil-works/pi-coding-agent/dist/bundle'
|
||||||
|
for name in names:
|
||||||
|
p=root/'node_modules'/name/'package.json';pkg=json.loads(p.read_text());entry=lock['packages']['node_modules/'+name];assert pkg['version']==entry['version']
|
||||||
|
report[name]={'version':entry['version'],'hasInstallScript':entry.get('hasInstallScript'),'lifecycle':{k:v for k,v in pkg['scripts'].items() if k in ['preinstall','postinstall']},'installedPackageJsonSha256':hashlib.sha256(p.read_bytes()).hexdigest(),'externalBundleImports':[]}
|
||||||
|
for p in bundle.rglob('*.js'):
|
||||||
|
s=p.read_text()
|
||||||
|
for m in re.finditer(r'(?:from\s*|\bimport\s*\(|\brequire\s*\(|\b__require\s*\()\s*["\']([^"\']+)',s):
|
||||||
|
for name in names:
|
||||||
|
if m.group(1)==name or m.group(1).startswith(name+'/'):report[name]['externalBundleImports'].append({'file':str(p.relative_to(root)),'specifier':m.group(1)})
|
||||||
|
# Direct package specifiers in the files the copy archives. No node_modules
|
||||||
|
# SDK entrypoint is assumed active merely because npm installed it.
|
||||||
|
script=(root/'scripts/stack-copy.sh').read_text();block=script.split('COPY_PATHS=(\n',1)[1].split('\n)',1)[0];paths=block.split()
|
||||||
|
for name in names:report[name]['copiedSourceMentions']=[]
|
||||||
|
for rel in paths:
|
||||||
|
p=root/rel;files=p.rglob('*') if p.is_dir() else [p]
|
||||||
|
for f in files:
|
||||||
|
if f.is_file() and f.suffix in ['.mjs','.js','.sh']:
|
||||||
|
s=f.read_text()
|
||||||
|
for name in names:
|
||||||
|
if name in s:report[name]['copiedSourceMentions'].append(str(f.relative_to(root)))
|
||||||
|
print(json.dumps(report,indent=2))
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
234121b3028143b7b0e0a9bb1a7d45d53bfe30b3
|
||||||
@@ -0,0 +1,205 @@
|
|||||||
|
diff --git a/docs/TOOLS.md b/docs/TOOLS.md
|
||||||
|
index 8fecefb40..20be532e9 100644
|
||||||
|
--- a/docs/TOOLS.md
|
||||||
|
+++ b/docs/TOOLS.md
|
||||||
|
@@ -291,7 +291,8 @@ Failure publishes nothing and removes the temporary tree.
|
||||||
|
`wrapper` is a live switching step, reserved for Jason or Mos. It accepts
|
||||||
|
only an existing copy and a regular non-symlink mosaic wrapper with the
|
||||||
|
Q81 marker on line 2 and its exact lease line to mosaic-old. It preserves
|
||||||
|
-both lines and atomically replaces the wrapper's final exec with the
|
||||||
|
+both lines, adds comments naming the copy root and Q81's mosaic-old lease
|
||||||
|
+probe, and atomically replaces the wrapper's final exec with the
|
||||||
|
copy's scripts/mosaic. --bin is a fixture override; the default is
|
||||||
|
~/.npm-global/bin. Neither the Q81 worktree nor mosaic-old is removed.
|
||||||
|
`check` changes nothing: it reads effective systemd WorkingDirectory and
|
||||||
|
@@ -305,7 +306,8 @@ Bus render/install accept --copy ID, --copies DIR, --pm and the unchanged
|
||||||
|
--pm adds the PM startup; a refusal exits 3, and RestartPreventExitStatus
|
||||||
|
prevents a retry. Install refuses any busy bus instance, even with
|
||||||
|
--no-reload; a failed state/drop-in read also refuses. Any template or
|
||||||
|
-instance drop-in assigning ExecStart or WorkingDirectory refuses,
|
||||||
|
+instance drop-in, or inherited mosaic-.service.d/ or service.d/ drop-in,
|
||||||
|
+assigning ExecStart or WorkingDirectory refuses,
|
||||||
|
naming the file. Status reads effective roots, --pm and DropInPaths,
|
||||||
|
reports checkout or copy identity and refactor drift, and writes nothing.
|
||||||
|
|
||||||
|
diff --git a/packages/cli/README.md b/packages/cli/README.md
|
||||||
|
index 4c05b4213..fb4532c84 100644
|
||||||
|
--- a/packages/cli/README.md
|
||||||
|
+++ b/packages/cli/README.md
|
||||||
|
@@ -470,11 +470,25 @@ mosaic-stack/copies/<full id>. bus-service.sh render/install take --copy
|
||||||
|
ID and --pm alongside the existing --claude pin. Without --copy render
|
||||||
|
keeps today's checkout unit. A PM refusal exits 3 and the unit does not
|
||||||
|
retry it. Install refuses every busy instance (also --no-reload), failed
|
||||||
|
-state reads and drop-ins overriding ExecStart or WorkingDirectory.
|
||||||
|
+state reads and drop-ins overriding ExecStart or WorkingDirectory, including
|
||||||
|
+inherited mosaic-.service.d/ and service.d/ in every unit lookup directory.
|
||||||
|
Status reads effective systemd properties, reports the tree/copy, PM flag,
|
||||||
|
refactor drift and drop-in files; it changes nothing. The temporary PM
|
||||||
|
ExecStart drop-in must be removed by Mos before installing the pinned unit.
|
||||||
|
|
||||||
|
+The wrapper keeps the Q81 marker on line 2 and the final copy exec on the
|
||||||
|
+last line. Comments name the copy root and explain that the Q81 lease probe
|
||||||
|
+still answers at mosaic-old.
|
||||||
|
+
|
||||||
|
+Copy npm ci may warn that @google/genai's preinstall, esbuild's postinstall
|
||||||
|
+and protobufjs's postinstall are blocked. This is expected for the current
|
||||||
|
+copy paths: Mosaic launches Pi's published bundled CLI, whose runtime does
|
||||||
|
+not load those installed package entrypoints. @google/genai's preinstall
|
||||||
|
+only echoes; esbuild's script installs/checks its build binary; protobufjs's
|
||||||
|
+script only warns about dependency version schemes. The copy runs the
|
||||||
|
+already published bundle and does not build it. No allowScripts change is
|
||||||
|
+needed for these paths; adding a runtime loader requires a fresh audit.
|
||||||
|
+
|
||||||
|
The one update and rollback plan is [TOOLS.md, Pinned stack update](../../docs/TOOLS.md#pinned-stack-update).
|
||||||
|
Each live switch/unit change/stop/start requires Mos's go; agents build
|
||||||
|
and test fixtures only. Restarting the bus ends its sessions, so no PM
|
||||||
|
diff --git a/packages/cli/tests/host.test.mjs b/packages/cli/tests/host.test.mjs
|
||||||
|
index 6a1170357..63dab06c3 100644
|
||||||
|
--- a/packages/cli/tests/host.test.mjs
|
||||||
|
+++ b/packages/cli/tests/host.test.mjs
|
||||||
|
@@ -828,7 +828,7 @@ test("bus-service.sh renders the unit and installs it into a given directory", (
|
||||||
|
// A user unit cannot order on a system target (Darkwing F3).
|
||||||
|
assert.doesNotMatch(render.stdout, /network-online/);
|
||||||
|
const fakeBin=join(dir,"bin");mkdirSync(fakeBin);
|
||||||
|
- writeFileSync(join(fakeBin,"systemctl"),"#!/bin/sh\ncase \"$*\" in *show*) echo DropInPaths=;; esac\nexit 0\n");chmodSync(join(fakeBin,"systemctl"),0o755);
|
||||||
|
+ writeFileSync(join(fakeBin,"systemctl"),"#!/bin/sh\ncase \"$*\" in *list-units*) exit 0;; *)exit 99;; esac\n");chmodSync(join(fakeBin,"systemctl"),0o755);
|
||||||
|
writeFileSync(join(fakeBin,"systemd-analyze"),`#!/bin/sh\nprintf '%s\\n' '${dir}/unit-search'\n`);chmodSync(join(fakeBin,"systemd-analyze"),0o755);
|
||||||
|
const unitEnv={...process.env,PATH:`${fakeBin}:${process.env.PATH}`};
|
||||||
|
const first = spawnSync(script, ["install", "--dir", dir, "--no-reload"], { encoding: "utf8",env:unitEnv });
|
||||||
|
@@ -852,7 +852,7 @@ test("bus-service.sh pins the claude binary, refuses one the unit can't carry, a
|
||||||
|
return p;
|
||||||
|
};
|
||||||
|
mkdirSync(join(dir, "bin"));
|
||||||
|
- writeFileSync(join(dir,"bin","systemctl"),'#!/bin/sh\ncase "$*" in *show*) echo DropInPaths=;; esac\nexit 0\n');chmodSync(join(dir,"bin","systemctl"),0o755);
|
||||||
|
+ writeFileSync(join(dir,"bin","systemctl"),'#!/bin/sh\ncase "$*" in *list-units*) exit 0;; *)exit 99;; esac\n');chmodSync(join(dir,"bin","systemctl"),0o755);
|
||||||
|
writeFileSync(join(dir,"bin","systemd-analyze"),`#!/bin/sh\nprintf '%s\\n' '${dir}/unit-search'\n`);chmodSync(join(dir,"bin","systemd-analyze"),0o755);
|
||||||
|
const onPath = stand(join(dir, "bin", "claude"));
|
||||||
|
const named = stand(join(dir, "claude-named"));
|
||||||
|
diff --git a/packages/cli/tests/stack-copy.test.mjs b/packages/cli/tests/stack-copy.test.mjs
|
||||||
|
index 8460b9198..d98e771ac 100644
|
||||||
|
--- a/packages/cli/tests/stack-copy.test.mjs
|
||||||
|
+++ b/packages/cli/tests/stack-copy.test.mjs
|
||||||
|
@@ -46,6 +46,11 @@ test('wrapper preserves Q81 lease and marker, rejects foreign/symlink; check use
|
||||||
|
const lease=`[ "\${1:-}" = __lease-capability ] && exec "${s.bin}/mosaic-old" "$@"`;
|
||||||
|
writeFileSync(wrapper,`#!/usr/bin/env bash\n${marker}\n${lease}\nexec "/old/scripts/mosaic" "$@"\n`);
|
||||||
|
assert.equal(s.run('stack-copy.sh',['wrapper',s.id,'--copies',s.copies,'--bin',s.bin]).status,0);
|
||||||
|
+ const lines=readFileSync(wrapper,'utf8').trimEnd().split('\n');
|
||||||
|
+ assert.equal(lines[1],marker);
|
||||||
|
+ assert.equal(lines[2],`# CLI runs from pinned copy: ${join(s.copies,s.id)}`);
|
||||||
|
+ assert.equal(lines[3],'# The Q81 lease probe still answers at mosaic-old.');
|
||||||
|
+ assert.equal(lines.at(-1),`exec "${join(s.copies,s.id)}/scripts/mosaic" "$@"`);
|
||||||
|
assert.match(readFileSync(wrapper,'utf8'),new RegExp(s.id));assert.ok(readFileSync(wrapper,'utf8').includes(lease));
|
||||||
|
const old=join(s.bin,'mosaic-old');writeFileSync(old,'#!/bin/sh\nprintf \"legacy:%s\\n\" \"$1\"\n');chmodSync(old,0o755);
|
||||||
|
assert.equal(spawnSync(wrapper,['__lease-capability'],{env:s.env,encoding:'utf8'}).stdout,'legacy:__lease-capability\n');
|
||||||
|
@@ -54,7 +59,11 @@ test('wrapper preserves Q81 lease and marker, rejects foreign/symlink; check use
|
||||||
|
s.fake(`echo 'LoadState=loaded'; echo 'WorkingDirectory=${copy}';case \"$*\" in *mosaic-bus*)echo 'ExecStart={ path=/other/scripts/mosaic ; argv[]=/other/scripts/mosaic bus start demo ; }';; *)echo 'ExecStart={ path=/usr/bin/node ; argv[]=/usr/bin/node ${copy}/packages/webui/src/cli.mjs serve ; }';;esac\n`);
|
||||||
|
assert.equal(s.run('stack-copy.sh',['check','--copies',s.copies,'--bin',s.bin]).status,1,'effective ExecStart mismatch');
|
||||||
|
s.fake(`echo 'LoadState=loaded'; echo 'WorkingDirectory=/other';\n`);assert.equal(s.run('stack-copy.sh',['check','--copies',s.copies,'--bin',s.bin]).status,1);
|
||||||
|
- const foreign=`#!/usr/bin/env bash\n# foreign wrapper\n${lease}\nexec \"/old/scripts/mosaic\" \"$@\"\n`;writeFileSync(wrapper,foreign);assert.notEqual(s.run('stack-copy.sh',['wrapper',s.id,'--copies',s.copies,'--bin',s.bin]).status,0);assert.equal(readFileSync(wrapper,'utf8'),foreign);
|
||||||
|
+ const foreign=`#!/usr/bin/env bash\n# foreign wrapper\n${lease}\nexec \"${copy}/scripts/mosaic\" \"$@\"\n`;writeFileSync(wrapper,foreign);
|
||||||
|
+ // Restore matching effective roots: only the foreign marker refuses check.
|
||||||
|
+ s.fake(`echo 'LoadState=loaded';echo 'WorkingDirectory=${copy}';case "$*" in *mosaic-bus*) echo 'ExecStart={ path=${copy}/scripts/mosaic ; argv[]=${copy}/scripts/mosaic bus start demo ; }';; *)echo 'ExecStart={ path=/usr/bin/node ; argv[]=/usr/bin/node ${copy}/packages/webui/src/cli.mjs serve ; }';;esac\n`);
|
||||||
|
+ assert.equal(s.run('stack-copy.sh',['check','--copies',s.copies,'--bin',s.bin]).status,1);
|
||||||
|
+ assert.notEqual(s.run('stack-copy.sh',['wrapper',s.id,'--copies',s.copies,'--bin',s.bin]).status,0);assert.equal(readFileSync(wrapper,'utf8'),foreign);
|
||||||
|
const backing=join(s.bin,'backing');writeFileSync(backing,`#!/usr/bin/env bash\n${marker}\n${lease}\nexec \"/old/scripts/mosaic\" \"$@\"\n`);unlinkSync(wrapper);symlinkSync(backing,wrapper);assert.notEqual(s.run('stack-copy.sh',['wrapper',s.id,'--copies',s.copies,'--bin',s.bin]).status,0);
|
||||||
|
});
|
||||||
|
test('bus unit copy/pm pins, install refuses all busy states and failed reads, drop-in refusal',t=>{
|
||||||
|
@@ -65,7 +74,7 @@ test('bus unit copy/pm pins, install refuses all busy states and failed reads, d
|
||||||
|
for(const state of ['active','activating','deactivating','reloading']){s.fake(`echo '[email protected] loaded ${state} running fixture';\n`);const r=s.run('bus-service.sh',['install',...args,'--dir',units,'--no-reload']);assert.notEqual(r.status,0,state);assert.ok(!existsSync(units));}
|
||||||
|
s.fake('exit 1\n');assert.notEqual(s.run('bus-service.sh',['install',...args,'--dir',units,'--no-reload']).status,0);assert.ok(!existsSync(units));
|
||||||
|
const dropdir=join(s.search,'[email protected]');mkdirSync(dropdir);const drop=join(dropdir,'pm.conf');writeFileSync(drop,'[Service]\nExecStart=elsewhere\n');
|
||||||
|
- s.fake(`case "$*" in *list-units*) echo '[email protected] loaded inactive dead fixture';; *show*) echo 'LoadState=loaded';echo 'DropInPaths=${drop}';; esac\n`);
|
||||||
|
+ s.fake(`case "$*" in *list-units*) echo '[email protected] loaded inactive dead fixture';; *)exit 99;; esac\n`);
|
||||||
|
const refused=s.run('bus-service.sh',['install',...args,'--dir',units,'--no-reload']);assert.notEqual(refused.status,0);assert.ok(refused.stderr.includes(drop));assert.ok(!existsSync(units));
|
||||||
|
writeFileSync(drop,'[Service]\nEnvironment=SAFE=1\n');assert.equal(s.run('bus-service.sh',['install',...args,'--dir',units,'--no-reload']).status,0);
|
||||||
|
});
|
||||||
|
@@ -151,7 +160,7 @@ test('drop-ins in either override field and malformed metadata refuse; uninstall
|
||||||
|
const s=setup(t),units=join(s.root,'units'),dropdir=join(s.search,'[email protected]');mkdirSync(dropdir);const drop=join(dropdir,'override.conf');
|
||||||
|
for(const field of ['ExecStart','WorkingDirectory']){
|
||||||
|
writeFileSync(drop,`[Service]\n${field}=override\n`);
|
||||||
|
- s.fake(`case "$*" in *list-units*) echo '[email protected] loaded inactive dead fixture';; *[email protected]*) echo 'DropInPaths=${drop}';; *)echo DropInPaths=;;esac\n`);
|
||||||
|
+ s.fake(`case "$*" in *list-units*) echo '[email protected] loaded inactive dead fixture';; *)exit 99;;esac\n`);
|
||||||
|
const r=s.run('bus-service.sh',['install','--dir',units,'--no-reload']);assert.notEqual(r.status,0);assert.ok(r.stderr.includes(drop));assert.ok(!existsSync(units));
|
||||||
|
}
|
||||||
|
s.fake('exit 0\n');s.analyze('exit 0\n');const unknown=s.run('bus-service.sh',['install','--dir',units,'--no-reload']);assert.notEqual(unknown.status,0);assert.match(unknown.stderr,/unknown/);
|
||||||
|
@@ -162,9 +171,11 @@ test('drop-ins in either override field and malformed metadata refuse; uninstall
|
||||||
|
|
||||||
|
test('install never shows a template name on systemd 261; template drop-ins still refuse',t=>{
|
||||||
|
const s=setup(t),units=join(s.root,'units'),calls=join(s.root,'systemctl-calls');
|
||||||
|
- s.fake(`echo "$*" >> '${calls}'\ncase "$*" in *show*[email protected]*) echo 'neither a valid invocation ID nor unit name' >&2; exit 1;; *list-units*) echo '[email protected] loaded inactive dead fixture';; *show*)echo DropInPaths=;; esac\n`);
|
||||||
|
+ s.fake(`echo "$*" >> '${calls}'\ncase "$*" in *show*[email protected]*) echo 'neither a valid invocation ID nor unit name' >&2; exit 1;; *list-units*) echo '[email protected] loaded inactive dead fixture';; *)exit 99;; esac\n`);
|
||||||
|
const result=s.run('bus-service.sh',['install','--dir',units,'--no-reload']);assert.equal(result.status,0,result.stderr);
|
||||||
|
assert.doesNotMatch(readFileSync(calls,'utf8'),/show mosaic-bus@\.service/);
|
||||||
|
+ // This rejection arm is deliberately exercised; it is not a dead show reply.
|
||||||
|
+ assert.equal(spawnSync(join(s.bin,'systemctl'),['--user','show','[email protected]'],{env:s.env}).status,1);
|
||||||
|
const dropdir=join(s.search,'[email protected]');mkdirSync(dropdir);const file=join(dropdir,'pm.conf');writeFileSync(file,'[Service]\nExecStart=override\n');
|
||||||
|
const before=readFileSync(join(units,'[email protected]'),'utf8');
|
||||||
|
const denied=s.run('bus-service.sh',['install','--dir',units,'--no-reload']);assert.notEqual(denied.status,0);assert.ok(denied.stderr.includes(file));assert.equal(readFileSync(join(units,'[email protected]'),'utf8'),before);
|
||||||
|
@@ -173,7 +184,29 @@ test('unlisted instance drop-in is found in another unit lookup directory; path
|
||||||
|
const s=setup(t),units=join(s.root,'units'),second=join(s.root,'second-search');mkdirSync(second);
|
||||||
|
const dropdir=join(second,'[email protected]');mkdirSync(dropdir);const file=join(dropdir,'cwd.conf');writeFileSync(file,'[Service]\nWorkingDirectory=/other\n');
|
||||||
|
s.analyze(`printf '%s\\n' '${s.search}' '${second}'\n`);
|
||||||
|
- s.fake("case \"$*\" in *list-units*) echo '[email protected] loaded inactive dead fixture';; *show*)echo DropInPaths=;; esac\n");
|
||||||
|
+ s.fake("case \"$*\" in *list-units*) echo '[email protected] loaded inactive dead fixture';; *)exit 99;; esac\n");
|
||||||
|
const denied=s.run('bus-service.sh',['install','--dir',units,'--no-reload']);assert.notEqual(denied.status,0);assert.ok(denied.stderr.includes(file));assert.ok(!existsSync(units));
|
||||||
|
s.analyze('exit 1\n');const failed=s.run('bus-service.sh',['install','--dir',units,'--no-reload']);assert.notEqual(failed.status,0);assert.match(failed.stderr,/unit-paths failed/);assert.ok(!existsSync(units));
|
||||||
|
});
|
||||||
|
+
|
||||||
|
+// Row 108: inherited drop-ins apply even without a loaded bus instance.
|
||||||
|
+for(const name of ['mosaic-.service.d','service.d'])test(`inherited ${name} override refuses without changing the unit`,t=>{
|
||||||
|
+ const s=setup(t),units=join(s.root,'units');mkdirSync(units);
|
||||||
|
+ const target=join(units,'[email protected]');writeFileSync(target,'previous unit bytes');
|
||||||
|
+ s.fake('exit 0\n');
|
||||||
|
+ const dropdir=join(s.search,name);mkdirSync(dropdir);const file=join(dropdir,'override.conf');
|
||||||
|
+ for(const field of ['WorkingDirectory','ExecStart']){
|
||||||
|
+ writeFileSync(file,`[Service]\n${field}=/other\n`);
|
||||||
|
+ const denied=s.run('bus-service.sh',['install','--dir',units,'--no-reload']);
|
||||||
|
+ assert.equal(denied.status,1,denied.stderr);assert.ok(denied.stderr.includes(file));assert.equal(readFileSync(target,'utf8'),'previous unit bytes');
|
||||||
|
+ }
|
||||||
|
+ writeFileSync(file,'[Service]\nEnvironment=SAFE=1\n');
|
||||||
|
+ const allowed=s.run('bus-service.sh',['install','--dir',units,'--no-reload']);assert.equal(allowed.status,0,allowed.stderr);
|
||||||
|
+});
|
||||||
|
+test('inherited drop-in unreadable directory or file refuses before writing',t=>{
|
||||||
|
+ const s=setup(t),units=join(s.root,'units');mkdirSync(units);const target=join(units,'[email protected]');writeFileSync(target,'previous unit bytes');s.fake('exit 0\n');
|
||||||
|
+ const dropdir=join(s.search,'service.d');symlinkSync(join(s.root,'absent-dir'),dropdir);
|
||||||
|
+ const dir=s.run('bus-service.sh',['install','--dir',units,'--no-reload']);assert.equal(dir.status,1);assert.ok(dir.stderr.includes(dropdir));assert.equal(readFileSync(target,'utf8'),'previous unit bytes');
|
||||||
|
+ unlinkSync(dropdir);mkdirSync(dropdir);const file=join(dropdir,'broken.conf');symlinkSync(join(s.root,'absent-file'),file);
|
||||||
|
+ const broken=s.run('bus-service.sh',['install','--dir',units,'--no-reload']);assert.equal(broken.status,1);assert.ok(broken.stderr.includes(file));assert.equal(readFileSync(target,'utf8'),'previous unit bytes');
|
||||||
|
+});
|
||||||
|
diff --git a/scripts/bus-service.sh b/scripts/bus-service.sh
|
||||||
|
index 297c633b2..f71250204 100755
|
||||||
|
--- a/scripts/bus-service.sh
|
||||||
|
+++ b/scripts/bus-service.sh
|
||||||
|
@@ -7,8 +7,8 @@
|
||||||
|
# business (mosaic-bus@<business>). Nothing here reads a capability, the
|
||||||
|
# binding or the token. See packages/cli/README.md, "Bus host".
|
||||||
|
#
|
||||||
|
-# render [--claude PATH] print the rendered unit on stdout
|
||||||
|
-# install [--dir DIR] [--no-reload] [--claude PATH]
|
||||||
|
+# render [--copy ID [--copies DIR]] [--pm] [--claude PATH] print the rendered unit on stdout
|
||||||
|
+# install [--copy ID [--copies DIR]] [--pm] [--dir DIR] [--no-reload] [--claude PATH]
|
||||||
|
# write the unit (write to a temp file, then
|
||||||
|
# rename) and run `systemctl --user daemon-reload`
|
||||||
|
# uninstall [--dir DIR] [--no-reload]
|
||||||
|
@@ -115,7 +115,7 @@ install_guard() {
|
||||||
|
[ -e "$directory" ] || [ -L "$directory" ] || continue
|
||||||
|
[ -d "$directory" ] && [ -r "$directory" ] && [ -x "$directory" ] || die "refusing: cannot inspect unit path $directory; nothing was changed"
|
||||||
|
# * includes the empty instance, i.e. [email protected].
|
||||||
|
- for dropdir in "$directory"/mosaic-bus@*.service.d; do
|
||||||
|
+ for dropdir in "$directory"/mosaic-bus@*.service.d "$directory"/mosaic-.service.d "$directory"/service.d; do
|
||||||
|
[ -e "$dropdir" ] || [ -L "$dropdir" ] || continue
|
||||||
|
[ -d "$dropdir" ] && [ -r "$dropdir" ] && [ -x "$dropdir" ] || die "refusing: cannot inspect drop-ins $dropdir; nothing was changed"
|
||||||
|
for file in "$dropdir"/*.conf; do
|
||||||
|
diff --git a/scripts/stack-copy.sh b/scripts/stack-copy.sh
|
||||||
|
index a3b6f9143..f384a983d 100755
|
||||||
|
--- a/scripts/stack-copy.sh
|
||||||
|
+++ b/scripts/stack-copy.sh
|
||||||
|
@@ -66,7 +66,7 @@ wrapper() {
|
||||||
|
[ "$(grep -Fxc "$lease" "$file" || true)" = 1 ] || die 'refusing: Q81 lease line missing or ambiguous'
|
||||||
|
tmp="$(mktemp "$BIN/.mosaic.XXXXXX")"
|
||||||
|
trap 'rm -f "$tmp"' EXIT
|
||||||
|
- printf '#!/usr/bin/env bash\n%s\n%s\nexec "%s/scripts/mosaic" "$@"\n' "$MARKER" "$lease" "$root" > "$tmp"
|
||||||
|
+ printf '#!/usr/bin/env bash\n%s\n# CLI runs from pinned copy: %s\n# The Q81 lease probe still answers at mosaic-old.\n%s\nexec "%s/scripts/mosaic" "$@"\n' "$MARKER" "$root" "$lease" "$root" > "$tmp"
|
||||||
|
chmod 0755 "$tmp";mv -f "$tmp" "$file";trap - EXIT
|
||||||
|
echo "wrapper: $root"
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
891b7543a85dee16332ce72e75be12d34e37f4cd9a5d46047a71e8a4f89e512c docs/TOOLS.md
|
||||||
|
c9910fe249fd1dc09dd370e51022fd377664627f8a89f4a9cd440cb087630591 packages/cli/README.md
|
||||||
|
4fe719a1ddca8ca876ba44024c777d32c65d1c13e21de06155b1cca6393e2e43 packages/cli/tests/host.test.mjs
|
||||||
|
b64eadec44ff8ddaf8b21520dd5c7db83d1ad0d34719565b8f2ca6c22de4bdb3 packages/cli/tests/stack-copy.test.mjs
|
||||||
|
cf3aff18d0b6b7befa3b7c99e01703bccafe83aee61fd34537cc884543a161ec scripts/bus-service.sh
|
||||||
|
3a25251516fe24ce47a9027c1bfcbc7542fe56aba1ec66ad3d968ac196d7e64a scripts/stack-copy.sh
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
docs/TOOLS.md
|
||||||
|
packages/cli/README.md
|
||||||
|
packages/cli/tests/host.test.mjs
|
||||||
|
packages/cli/tests/stack-copy.test.mjs
|
||||||
|
scripts/bus-service.sh
|
||||||
|
scripts/stack-copy.sh
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Run shell suites from a detached worktree, capture every exit."""
|
||||||
|
import pathlib, subprocess, json, datetime, sys, os
|
||||||
|
root=pathlib.Path.cwd()
|
||||||
|
if root == pathlib.Path('/mnt/storage/src/mosaic-stack'):
|
||||||
|
raise SystemExit('gate refuses canonical checkout')
|
||||||
|
if subprocess.check_output(['git','branch','--show-current'],text=True).strip():
|
||||||
|
raise SystemExit('gate requires detached HEAD')
|
||||||
|
if os.environ.get('DOCKER_HOST') != 'unix:///nonexistent.sock':
|
||||||
|
raise SystemExit('decision 127 requires DOCKER_HOST=unix:///nonexistent.sock')
|
||||||
|
out=pathlib.Path(sys.argv[1]); out.mkdir(parents=True,exist_ok=True)
|
||||||
|
results=[]
|
||||||
|
commands=[]
|
||||||
|
for package in [root/'packages/cli']:
|
||||||
|
tests=sorted(package.glob('tests/**/*.test.mjs'))
|
||||||
|
if tests: commands.append(('node-'+package.name,['node','--test',*[str(t.relative_to(root)) for t in tests]],600))
|
||||||
|
for suite in sorted(root.glob('scripts/test-*.sh')):
|
||||||
|
commands.append((suite.stem,['bash',str(suite)],600))
|
||||||
|
for name,command,timeout in commands:
|
||||||
|
began=datetime.datetime.now(datetime.timezone.utc).isoformat()
|
||||||
|
with (out/(name+'.txt')).open('w') as log:
|
||||||
|
p=subprocess.run(command,cwd=root,stdout=log,stderr=subprocess.STDOUT,timeout=timeout)
|
||||||
|
row={'suite':name,'exit':p.returncode,'began':began,'ended':datetime.datetime.now(datetime.timezone.utc).isoformat()}
|
||||||
|
results.append(row)
|
||||||
|
(out/'gate-results.json').write_text(json.dumps(results,indent=2)+'\n')
|
||||||
|
print(json.dumps(row),flush=True)
|
||||||
|
sys.exit(any(r['exit'] for r in results))
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import pathlib,subprocess,sys,json,os,signal
|
||||||
|
root=pathlib.Path.cwd();out=pathlib.Path(sys.argv[1]);out.mkdir(parents=True,exist_ok=True)
|
||||||
|
assert root != pathlib.Path('/mnt/storage/src/mosaic-stack')
|
||||||
|
assert os.environ.get('DOCKER_HOST')=='unix:///nonexistent.sock'
|
||||||
|
bus='scripts/bus-service.sh';stack='scripts/stack-copy.sh';test='packages/cli/tests/stack-copy.test.mjs'
|
||||||
|
muts=[
|
||||||
|
('miss-prefix',bus,' "$directory"/mosaic-.service.d','', 'inherited mosaic'),
|
||||||
|
('miss-all-services',bus,' "$directory"/service.d','', 'inherited service'),
|
||||||
|
('ignore-unreadable-directory',bus,'[ -d "$dropdir" ] && [ -r "$dropdir" ] && [ -x "$dropdir" ] || die',': || die','inherited drop-in unreadable'),
|
||||||
|
('ignore-unreadable-file',bus,'content="$(cat "$file" 2>/dev/null)" || die "refusing: cannot read drop-in $file; nothing was changed"','content="$(cat "$file" 2>/dev/null)" || content=""','inherited drop-in unreadable'),
|
||||||
|
('omit-copy-comment',stack,'# CLI runs from pinned copy: %s','# CLI copy unspecified: %s','wrapper preserves'),
|
||||||
|
('omit-lease-comment',stack,'# The Q81 lease probe still answers at mosaic-old.','# Lease explanation omitted.','wrapper preserves'),
|
||||||
|
('accept-foreign-check-wrapper',stack,'[ "$(sed -n \'2p\' "$BIN/mosaic")" = "$MARKER" ]; then','[ 1 = 1 ]; then','wrapper preserves'),
|
||||||
|
]
|
||||||
|
results=[]
|
||||||
|
for name,file,old,new,pattern in muts:
|
||||||
|
p=root/file;original=p.read_text();assert original.count(old)==1,(name,original.count(old))
|
||||||
|
try:
|
||||||
|
p.write_text(original.replace(old,new,1))
|
||||||
|
with (out/(name+'.txt')).open('w') as log:
|
||||||
|
child=subprocess.Popen(['node','--test','--test-name-pattern='+pattern,test],stdout=log,stderr=subprocess.STDOUT,start_new_session=True)
|
||||||
|
try:code=child.wait(timeout=60);status='killed' if code else 'survived'
|
||||||
|
except subprocess.TimeoutExpired:os.killpg(child.pid,signal.SIGKILL);child.wait();code=124;status='timeout'
|
||||||
|
row={'name':name,'exit':code,'status':status};results.append(row);print(json.dumps(row),flush=True)
|
||||||
|
(out/'summary.json').write_text(json.dumps(results,indent=2)+'\n')
|
||||||
|
finally:p.write_text(original)
|
||||||
|
sys.exit(any(r['status']!='killed' for r in results))
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
6/6 candidate hashes match after gate and mutants; patch equals detached worktree diff; canonical apply --check passes; git diff --check clean; logs-only commit d7430483626f82c8c8c39b84cae03925d2c811bb; no source commit.
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"suite": "node-cli",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:05:00.721454+00:00",
|
||||||
|
"ended": "2026-10-14T20:05:13.966268+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-auth",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:05:13.966534+00:00",
|
||||||
|
"ended": "2026-10-14T20:05:14.581652+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-conductor",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:05:14.581919+00:00",
|
||||||
|
"ended": "2026-10-14T20:05:19.256693+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-config",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:05:19.256945+00:00",
|
||||||
|
"ended": "2026-10-14T20:05:20.876187+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-discord",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:05:20.876446+00:00",
|
||||||
|
"ended": "2026-10-14T20:05:27.405639+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-extension-package",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:05:27.405892+00:00",
|
||||||
|
"ended": "2026-10-14T20:05:28.722298+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-foundation",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:05:28.722555+00:00",
|
||||||
|
"ended": "2026-10-14T20:06:07.275537+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-land-work",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:06:07.275850+00:00",
|
||||||
|
"ended": "2026-10-14T20:06:16.059005+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-queue",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:06:16.059326+00:00",
|
||||||
|
"ended": "2026-10-14T20:06:36.263997+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-release",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:06:36.264278+00:00",
|
||||||
|
"ended": "2026-10-14T20:06:36.428496+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-task",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:06:36.428788+00:00",
|
||||||
|
"ended": "2026-10-14T20:06:38.397111+00:00"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,197 @@
|
|||||||
|
✔ every screen and overlay fits 120x36, 80x24 and the narrow layout, row for row (1324.255253ms)
|
||||||
|
✔ width counts terminal cells: wide CJK and emoji 2, U+FE0F after a one-cell base 1, marks 0 (73.164371ms)
|
||||||
|
✔ broker text is shown, never interpreted: no raw control character or bidi override reaches the terminal (161.886353ms)
|
||||||
|
✔ NO_COLOR: no escape codes, except reverse video on the selected row (258.751578ms)
|
||||||
|
✔ 1-9 shows the decide flow's own lines and question; only y resolves (55.31198ms)
|
||||||
|
✔ the app shows the same decide text as mosaic decide (34.108291ms)
|
||||||
|
✔ any key but y or Y at the question answers No; nothing is sent (224.453199ms)
|
||||||
|
✔ below 40x10 the question is hidden, so every key answers it No, y included (Filbert R3) (104.416927ms)
|
||||||
|
✔ under 40 columns a tall terminal shows the too-small screen even where the decide box would fit; y sends nothing (Filbert N10) (377.281955ms)
|
||||||
|
✔ a hidden decide box names the way out, and the status line under it does not promise y (Filbert N12) (38.416063ms)
|
||||||
|
✔ a throw while answering the question goes to crash, sends nothing and leaves no job pending (29.237208ms)
|
||||||
|
✔ type-ahead never answers the question: a paste, keys typed before it is drawn, keys inside askMs (443.098483ms)
|
||||||
|
✔ quitting at the question answers No and sends nothing, armed or not (54.023187ms)
|
||||||
|
✔ a timer tick reads nothing under an overlay, never answers the question, and keeps a resolved status (47.501421ms)
|
||||||
|
✔ a long question is cut inside the question; the action, target, choice and prompt stay (Dewey B1) (64.057095ms)
|
||||||
|
✔ a decide box too big for the terminal says so, and every key answers it No, y included (Dewey B1, round 3) (419.339807ms)
|
||||||
|
✔ at every size the decide box shows each line y depends on, or says it is hidden (8529.753063ms)
|
||||||
|
✔ outcome unknown: the CLI's sentence, no retry, then the trail or a re-read (62.276549ms)
|
||||||
|
✔ refused and failed reads keep the last list, marked stale; a refused decide says refused (29.049886ms)
|
||||||
|
✔ help or a detail box cut to fit keeps its last line, Esc included (Dewey) (13.898205ms)
|
||||||
|
✔ keys: views, moving, trail of a selection, the command line, help and quit (71.484737ms)
|
||||||
|
✔ one option: the status line says Press 1, not 1-1 (14.04437ms)
|
||||||
|
✔ no business: the app says so and :business picks one (7.943052ms)
|
||||||
|
✔ mosaic with no argument: exit 3 in an agent run, exit 4 with the usage off a terminal, the app on one (1.742299ms)
|
||||||
|
✔ scripts/mosaic with no argument reaches the app entry; the seat usage it printed before has not drifted (166.59363ms)
|
||||||
|
✔ strings to keep exactly live once, in the decide flow and the transport; the app does not restate them (0.437712ms)
|
||||||
|
✔ decide with --note still asks; a No sends nothing (9.437952ms)
|
||||||
|
✔ the app's business comes from a live bus host only (1.037954ms)
|
||||||
|
✔ runApp leaves the terminal as it found it on q, end of input, SIGTERM, SIGINT, SIGHUP and an error, the first frame's included (6.879287ms)
|
||||||
|
✔ draw is pure: same state, same frame (0.785457ms)
|
||||||
|
✔ inbox lists only decisions routed to the human, with what approving authorizes and how to decide (28.941921ms)
|
||||||
|
✔ decide resolves by id prefix with --yes, and the trail shows it in broker order with the task to follow (27.735949ms)
|
||||||
|
✔ decide refuses without a terminal or --yes, on an unknown option and on a short reference (21.86062ms)
|
||||||
|
✔ decide prints a declining choice as declining (22.183401ms)
|
||||||
|
✔ an unknown outcome is reported once and never resent (16.490674ms)
|
||||||
|
✔ a decision closed before the answer arrives exits 2 and points at its trail (16.6485ms)
|
||||||
|
✔ a prefix that matches two open decisions exits 2 and resolves neither (14.568569ms)
|
||||||
|
✔ without --business a command uses the live host's business, and a stale host.json is not a host (13.204451ms)
|
||||||
|
✔ every human command refuses inside an agent run before it touches the bus (12.099752ms)
|
||||||
|
✔ usage errors exit 4; no business and no host is a usage error (14.992015ms)
|
||||||
|
✔ agents and tasks print through the broker (13.28199ms)
|
||||||
|
✔ notify.json: missing, loose, malformed and extra keys refuse; a binding or null passes (2.009071ms)
|
||||||
|
✔ bootConfig builds the broker's boot message for one business, with no trackers key when no project names one (72.200723ms)
|
||||||
|
✔ trackers come from the tracker.* variables of the one project that names a tracker project (100.274785ms)
|
||||||
|
✔ with two projects, the one that sets tracker.project supplies the tracker and the other is no conflict (41.938935ms)
|
||||||
|
✔ two projects that each name a tracker project refuse, since the boot shape holds one (44.839011ms)
|
||||||
|
✔ a business without tracker.baseUrl gets no trackers entry (42.013242ms)
|
||||||
|
✔ an unknown business and a broken system config refuse with exit 3 (64.809989ms)
|
||||||
|
✔ follow prints an unsolicited message after plain talk returned (42.966398ms)
|
||||||
|
✔ talk --follow continues after reply and prints a later unsolicited message (36.903114ms)
|
||||||
|
✔ inbox lists all unread human messages under decisions, does not deliver or read them (298.901768ms)
|
||||||
|
✔ follow refuses agent context and bad arguments (8.125493ms)
|
||||||
|
✔ follow Ctrl-C wakes the poll sleep and removes its handler; transport errors also clean up (12.661688ms)
|
||||||
|
✔ plain talk leaves the process SIGINT handlers unchanged (10.937406ms)
|
||||||
|
✔ empty views say so (1.129747ms)
|
||||||
|
✔ the trail keeps the broker's order and names a decision's task without its rows (1.566478ms)
|
||||||
|
✔ tasks print the tracker fields the snapshot carries (0.2397ms)
|
||||||
|
✔ the review loop: the coder pushes and asks, the reviewer fetches and approves, and the task's trail holds each step (459.454493ms)
|
||||||
|
✔ refusals: no action, non-fast-forward, an unknown commit or request, and a push for another task moves only that task's ref (289.884086ms)
|
||||||
|
✔ the size cap refuses a push before any byte (143.94549ms)
|
||||||
|
✔ a fetch over the cap refuses before any byte reaches the reviewer (321.951612ms)
|
||||||
|
✔ the socket refuses a request with no capability, an unknown one, and a bad request line (162.728107ms)
|
||||||
|
✔ a rigged clone runs nothing: hooks, fsmonitor, a filter, a gitlink and a symlinked .git/config leave no marker (264.961547ms)
|
||||||
|
✔ an identity with no role, or of another business, refuses not-a-role and moves no ref (212.942363ms)
|
||||||
|
✔ a review of a project the business no longer has refuses unknown-project (204.401342ms)
|
||||||
|
✔ past maxActive connections the socket refuses git-busy, and a hung-up connection frees its slot (168.319256ms)
|
||||||
|
✔ close() answers host-closing to a connection still sending its request line (179.982033ms)
|
||||||
|
✔ a bundle that trickles in refuses body-timeout at its deadline and frees its slot (617.669913ms)
|
||||||
|
✔ a reviewer gone before its bundle was sent is filed fetch-aborted, not as the host's fault (598.213203ms)
|
||||||
|
✔ a reviewer that hangs up the moment it has the whole bundle was served, not aborted (674.069328ms)
|
||||||
|
✔ send: a close after every byte left is served; one that fails a queued write is fetch-aborted (41.934417ms)
|
||||||
|
✔ a bundle with no bytes for bodyIdle refuses body-timeout long before its deadline (484.096653ms)
|
||||||
|
✔ send: a close once the loop is past its last chunk is served, and a failed write there is fetch-aborted (44.70515ms)
|
||||||
|
✔ letGo waits for an answer to leave for at most its cap, then destroys the socket (302.466069ms)
|
||||||
|
✔ a record that fails and can't be undone refuses rollback-failed, which the host logs (334.245772ms)
|
||||||
|
✔ the host boots the broker, binds a launch in process, and the notifier DMs a blocking decision exactly once (926.2985ms)
|
||||||
|
✔ a notifier that dies takes the host down with exit 1, so the unit restarts the pair (144.864941ms)
|
||||||
|
✔ a second host for the same data root refuses with exit 3 while the first runs (77.793275ms)
|
||||||
|
✔ two bus starts racing for one data root leave one host running; the other refuses that a host already runs (479.472687ms)
|
||||||
|
✔ a host takes over a host.lock its dead host left, and puts back a live claim that replaced it meanwhile (1.515899ms)
|
||||||
|
✔ a host.lock that goes between the check and the read is tried again; one that can't be parsed still refuses as unreadable (0.847609ms)
|
||||||
|
✔ a live host's lock stays, however old the file is (0.572998ms)
|
||||||
|
✔ a host.lock left by a host killed with SIGKILL doesn't stop the next bus start (822.870952ms)
|
||||||
|
✔ while a host boots, a reader sees no host: the human commands still ask for --business, stop and status find none (264.279654ms)
|
||||||
|
✔ a host started before host.lock existed, holding only host.json, still refuses a second start, which leaves no lock (39.650988ms)
|
||||||
|
✔ a broker fork that throws leaves no host.lock and no host.json (36.428573ms)
|
||||||
|
✔ a broker send that throws leaves no host.lock and no host.json (38.329846ms)
|
||||||
|
✔ a broker that misses its boot wait leaves no host.lock and no host.json (43.834281ms)
|
||||||
|
✔ a notifier fork that throws stops the broker and leaves no host.lock and no host.json (140.953834ms)
|
||||||
|
✔ a notifier send that throws stops the broker and leaves no host.lock and no host.json (124.148834ms)
|
||||||
|
✔ a boot reply with no reader for the business refuses with exit 3 naming it, before the notifier starts, and leaves no host.lock and no live broker (114.940435ms)
|
||||||
|
✔ a boot reply with no reader for the business refuses with exit 3 naming it, with no notifier, and leaves no host.lock and no live broker (122.512177ms)
|
||||||
|
✔ a host.json that can't be written stops both children and leaves no host.lock (267.206694ms)
|
||||||
|
✔ an error event on the broker before it replies fails the start at once, and leaves no host.lock and no live child (42.38589ms)
|
||||||
|
✔ an error event on the notifier before it replies fails the start at once, and leaves no host.lock and no live child (109.73294ms)
|
||||||
|
✔ an error event on the broker while the notifier starts fails the start once the notifier replies (292.115473ms)
|
||||||
|
✔ an error event on the broker once the host is up stops the host with exit 1, and leaves no host.lock and no host.json (287.331653ms)
|
||||||
|
✔ an error event on the notifier once the host is up stops the host with exit 1, and leaves no host.lock and no host.json (259.641899ms)
|
||||||
|
✔ a broker reply that misses the wait breaks the channel: the late reply answers nothing, later requests refuse, the host exits 1 (1118.402795ms)
|
||||||
|
✔ a broker reply with another request's id, or none, breaks the channel and the host exits 1 (177.746672ms)
|
||||||
|
✔ a broker reply with no request waiting breaks the channel and the host exits 1 (76.67044ms)
|
||||||
|
✔ a notifier that refuses stops the broker and the host refuses with exit 3 (131.130488ms)
|
||||||
|
✔ a notifier that refuses after the broker died still refuses with exit 3, without a send to the dead broker (125.642606ms)
|
||||||
|
✔ a notifier that dies before it replies, after the broker died, still refuses, without a send to the dead broker (77.176599ms)
|
||||||
|
✔ a close send that fails with EPIPE after the notifier refuses still gives the notifier's refusal, exit 3 (130.157155ms)
|
||||||
|
✔ a close send that fails with EPIPE after the notifier dies unanswered still gives the notifier's error (78.190572ms)
|
||||||
|
✔ close() whose stop and close sends fail with EPIPE still finishes, with exit 1 (148.177ms)
|
||||||
|
✔ watchChildren reports a child that died before it was called, and one that dies later (21.234097ms)
|
||||||
|
✔ bus stop refuses to signal a live pid that is not a bus host (202.638255ms)
|
||||||
|
✔ bus start refuses with exit 3 and the code when the broker refuses to boot; bus status names the lock (253.144743ms)
|
||||||
|
✔ bus start refuses with exit 3 without a notifier config (112.345897ms)
|
||||||
|
✔ bus start runs until bus stop; status reports it while it runs (693.66935ms)
|
||||||
|
✔ bus-service.sh renders the unit and installs it into a given directory (55.424401ms)
|
||||||
|
✔ bus-service.sh pins the claude binary, refuses one the unit can't carry, and renders without one (69.120281ms)
|
||||||
|
✔ bus-service.sh refuses a directory pin and keeps a symlink default unresolved (12.928652ms)
|
||||||
|
✔ bus-service.sh refuses a default claude without the execute bit, or in a PATH dir with a space (8.238887ms)
|
||||||
|
✔ bus start --pm: the PM runs under its own PID namespace, registered, with a manifest (1259.91577ms)
|
||||||
|
✔ the PM launches a coder through its launch tool; the coder answers; refusals name their code (421.993272ms)
|
||||||
|
✔ each launch makes sure the workspace has a clone of the project: cloned, fast-forwarded, or fetched and logged (3682.176739ms)
|
||||||
|
✔ a project clone that can't be made refuses checkout-failed, from --pm and from a session, with no run and no clone left (111.127903ms)
|
||||||
|
✔ a runner that stops at once ends its launch with the runner's reason (186.299304ms)
|
||||||
|
✔ a Claude Code launch with no session credential refuses before it starts (94.110448ms)
|
||||||
|
✔ a pi launch needs no session credential: pi logs in through its own ENV_ALLOW variables (187.408127ms)
|
||||||
|
✔ a runner killed from the host ends its launch as killed, not failed (227.753219ms)
|
||||||
|
✔ a missing or failing bwrap refuses sandbox-unavailable before anything starts; there is no unconfined fallback (99.764384ms)
|
||||||
|
✔ a real Claude Code coder's shell can't read a stand-in secret or anything else its sandbox doesn't hold (1198.642345ms)
|
||||||
|
✔ a host that died hard leaves its sessions to the next host, which kills them and ends their runs so the role can be launched again (590.515632ms)
|
||||||
|
✔ a host that died hard leaves its sessions to the next host, which finds one already exited (23) and ends their runs so the role can be launched again (3530.185396ms)
|
||||||
|
✔ a malformed sessions.json refuses the host start with exit 3 and stays as it was (81.930017ms)
|
||||||
|
✔ an over-long launch request is refused at once, not at the 10 s idle timeout (89.919353ms)
|
||||||
|
✔ a launch client that never closes its side doesn't hold the host's close (86.185996ms)
|
||||||
|
✔ a runner that ignores SIGTERM is killed when the host closes (1197.271782ms)
|
||||||
|
✔ claudeVersion asks MOSAIC_CLAUDE_BIN when set, else claude on PATH (4.322061ms)
|
||||||
|
✔ zoned uses the IANA zone across DST (25.906922ms)
|
||||||
|
✔ each open blocking decision is DM'd once, across polls and a restart; non-blocking ones are not (30.887735ms)
|
||||||
|
✔ two blocking decisions get two DMs with different nonces (21.783906ms)
|
||||||
|
✔ the digest nonce differs per business and per day and fits Discord's 25 characters (0.273831ms)
|
||||||
|
✔ a failed DM is journaled, backs off, and is retried until it lands (21.084358ms)
|
||||||
|
✔ five definite refusals stop a DM: one gave-up line, one log line, and a restart keeps the count (24.571308ms)
|
||||||
|
✔ 429s, 5xx-style unknowns and refusals without a status never count toward the limit (29.734616ms)
|
||||||
|
✔ a crash between the fifth refusal and its gave-up line: the next poll appends it and sends nothing (17.793905ms)
|
||||||
|
✔ polled every POLL_MS against a permanent 403, a DM is sent at 0, 30, 60, 90 and 120 min and gives up only then (113.895861ms)
|
||||||
|
✔ a restart after the second refusal does not send before that refusal's 30 min are up (45.076869ms)
|
||||||
|
✔ the digest goes at 08:00 Chicago once a day, with blocking ones marked as DM'd (14.015711ms)
|
||||||
|
✔ a late start with no digest for the day sends one at once; an empty inbox gets one line (10.272029ms)
|
||||||
|
✔ an inbox read failure is logged and the next poll retries (0.736646ms)
|
||||||
|
✔ no Discord id reaches the journal or the log (11.319672ms)
|
||||||
|
✔ the journal: a torn tail is copied out and truncated, so an append after it reopens cleanly (2.289477ms)
|
||||||
|
✔ the journal: a crash between the copy and the truncate leaves a tail the next open repairs (2.379193ms)
|
||||||
|
✔ the journal: a whole file that is one torn line truncates to empty (1.562892ms)
|
||||||
|
✔ the journal: a malformed complete line refuses and leaves the file and any torn tail alone (0.566013ms)
|
||||||
|
✔ the journal: a loose file mode, a loose directory or a symlinked journal refuses (0.786074ms)
|
||||||
|
✔ the journal: a line with a wrong type refuses with exit 3 and names the field (2.432193ms)
|
||||||
|
✔ the journal: a symlinked directory refuses and says it is a link (0.407908ms)
|
||||||
|
✔ the journal: a dangling directory link, a parent that is a file and a journal that is a directory each refuse with exit 3 (2.05593ms)
|
||||||
|
✔ the journal: an append after the file was swapped for a symlink refuses and writes nothing through it (0.44111ms)
|
||||||
|
✔ the journal: a directory it cannot write or create refuses with exit 3 and names the path (0.462544ms)
|
||||||
|
✔ digest content stays within Discord's 2000 characters (0.264637ms)
|
||||||
|
✔ runLoop never overlaps ticks and stops after the one in flight (111.299932ms)
|
||||||
|
✔ shared copy: npm ci, pushed reachability, readonly/existing copy, webui delegation (507.03983ms)
|
||||||
|
✔ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (402.394593ms)
|
||||||
|
✔ bus unit copy/pm pins, install refuses all busy states and failed reads, drop-in refusal (413.745167ms)
|
||||||
|
✔ missing package manifest refuses before npm; npm failure removes the unpublished temp copy (276.296237ms)
|
||||||
|
✔ real pinned install loads bus and Console; same-copy mosaic talk passes proof, other trees refuse (4239.076738ms)
|
||||||
|
✔ bus status reads effective copy/pm/drop-ins without writes; check refuses an overridden ExecStart (464.792063ms)
|
||||||
|
✔ drop-ins in either override field and malformed metadata refuse; uninstall also checks --no-reload (170.42422ms)
|
||||||
|
✔ install never shows a template name on systemd 261; template drop-ins still refuse (165.159816ms)
|
||||||
|
✔ unlisted instance drop-in is found in another unit lookup directory; path discovery errors refuse (147.646857ms)
|
||||||
|
✔ inherited mosaic-.service.d override refuses without changing the unit (169.98802ms)
|
||||||
|
✔ inherited service.d override refuses without changing the unit (175.813221ms)
|
||||||
|
✔ inherited drop-in unreadable directory or file refuses before writing (135.769183ms)
|
||||||
|
✔ talk --tester sends a [mos test] message as tester from inside an agent and prints the role's reply (36.774632ms)
|
||||||
|
✔ talk --tester refuses text without the [mos test] prefix before any call (17.644945ms)
|
||||||
|
✔ the read verbs take --tester inside an agent, and the trail shows the tester as the sender (25.032622ms)
|
||||||
|
✔ decide, stop and launches take no --tester (16.261267ms)
|
||||||
|
✔ the tester transport runs tester-cli.mjs, and the tester's refusals exit 3 (0.416855ms)
|
||||||
|
✔ with no stand-in transport, --tester runs tester-cli.mjs on the data root's socket (0.739971ms)
|
||||||
|
task.close {} answered: invalid-request; fake saw 18 requests, first GET /info 200, GET /projects/1 200, GET /projects/1/views 200
|
||||||
|
task.close on a missing task answered: task-not-found; it made GET /tasks/999 404
|
||||||
|
✔ bootConfig trackers reach the S3 adapter in the real broker child, which goes ready against a fake Vikunja (324.44889ms)
|
||||||
|
✔ the transport writes {business, verb, args} to the child and reads its JSON (53.800157ms)
|
||||||
|
✔ a bus code on stderr becomes the exit code; garbage and timeouts are outcome problems (2209.810815ms)
|
||||||
|
✔ busExit and refuseInsideAgent (0.8034ms)
|
||||||
|
✔ talk sends a REQUEST, prints and reads everything that arrives, and stops at the reply (56.585616ms)
|
||||||
|
✔ talk --wait 0 only sends; no reply within --wait exits 1 and says where it will show (1039.018927ms)
|
||||||
|
✔ a late reply the Console has listed still reaches the next talk (2031.309429ms)
|
||||||
|
✔ talk, stop and launches off/on refuse inside an agent run; bad arguments are usage errors (17.228178ms)
|
||||||
|
✔ launches off and on go to the broker and change the business's launch state (15.619332ms)
|
||||||
|
✔ launches list reads sessions.json and marks a stale entry; stop reports it and refuses a non-runner (17.161962ms)
|
||||||
|
ℹ tests 187
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 187
|
||||||
|
ℹ fail 0
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 13212.307403
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
OK status with missing harness credential exits 3 and still lists accounts
|
||||||
|
OK status reports harness credential (read-only) + mosaic accounts
|
||||||
|
OK api key material never reaches output
|
||||||
|
OK oauth token material never reaches output
|
||||||
|
OK unparseable credential file exits 2
|
||||||
|
OK symlinked credential file exits 4
|
||||||
|
OK env-side credential names reported
|
||||||
|
OK env var values never reach output
|
||||||
|
OK accounts without an accounts dir reports none and creates nothing
|
||||||
|
OK accounts lists files and marks the active one
|
||||||
|
OK loose account perms flagged in listing
|
||||||
|
OK agent --auth with missing account file refuses (exit 4)
|
||||||
|
OK agent --auth with non-0600 account file refuses
|
||||||
|
OK agent --auth with invalid account name refuses
|
||||||
|
OK auth.sh without valid config refuses
|
||||||
|
|
||||||
|
selftest: 15 passed, 0 failed
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
On branch refactor
|
||||||
|
Your branch is up to date with 'origin/refactor'.
|
||||||
|
|
||||||
|
nothing to commit, working tree clean
|
||||||
|
OK dry-run: allowed change, exit 0, nothing committed (exit 0)
|
||||||
|
OK dry-run committed nothing
|
||||||
|
OK apply: allowed change exits 0 (exit 0)
|
||||||
|
OK apply: attribution in commit subject
|
||||||
|
OK apply: target tree clean after commit
|
||||||
|
OK disallowed path refused (exit 1)
|
||||||
|
OK disallowed path: target untouched
|
||||||
|
OK syntax gate refused broken .mjs (exit 1)
|
||||||
|
OK syntax gate: target untouched
|
||||||
|
OK suite failure refused (exit 1)
|
||||||
|
OK suite failure: target reverted to clean
|
||||||
|
OK disabled policy refused (exit 2)
|
||||||
|
OK disabled policy: target untouched
|
||||||
|
OK failed run refused (exit 1)
|
||||||
|
OK failed run: target untouched
|
||||||
|
OK missing run exits 4 (exit 4)
|
||||||
|
OK invalid policy exits 2 (exit 2)
|
||||||
|
|
||||||
|
selftest: 17 passed, 0 failed
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
OK absent adapter defaults to pi
|
||||||
|
OK adapter mock validates (exit 0)
|
||||||
|
OK unsupported adapter exits 2 (exit 2)
|
||||||
|
OK env exports adapter
|
||||||
|
OK bootstrap creates default when absent (exit 0)
|
||||||
|
OK bootstrap wrote config file
|
||||||
|
OK bootstrap is idempotent on existing config (exit 0)
|
||||||
|
OK bootstrap did not rewrite existing config
|
||||||
|
OK validate missing config exits 3 (exit 3)
|
||||||
|
OK malformed JSON exits 2 (exit 2)
|
||||||
|
OK unsupported configVersion exits 2 (exit 2)
|
||||||
|
OK unknown top-level key exits 2 (exit 2)
|
||||||
|
OK unknown execution key exits 2 (exit 2)
|
||||||
|
OK unsupported backend exits 2 (exit 2)
|
||||||
|
OK unsupported environment exits 2 (exit 2)
|
||||||
|
OK relative dataRoot exits 2 (exit 2)
|
||||||
|
OK non-canonical dataRoot exits 2 (exit 2)
|
||||||
|
OK filesystem root dataRoot exits 2 (exit 2)
|
||||||
|
OK home directory dataRoot exits 2 (exit 2)
|
||||||
|
OK dataRoot containing config dir exits 2 (exit 2)
|
||||||
|
OK control character in provider exits 2 (exit 2)
|
||||||
|
OK symlinked config file exits 2 (exit 2)
|
||||||
|
OK env exports resolve correctly
|
||||||
|
OK failed validation modified nothing
|
||||||
|
|
||||||
|
selftest: 24 passed, 0 failed
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
toolchain: node v26.8.1
|
||||||
|
|
||||||
|
OK syntax: packages/discord/src/approvals.mjs
|
||||||
|
OK syntax: packages/discord/src/authorize.mjs
|
||||||
|
OK syntax: packages/discord/src/binding.mjs
|
||||||
|
OK syntax: packages/discord/src/cli.mjs
|
||||||
|
OK syntax: packages/discord/src/connector.mjs
|
||||||
|
OK syntax: packages/discord/src/context.mjs
|
||||||
|
OK syntax: packages/discord/src/engine-pi.mjs
|
||||||
|
OK syntax: packages/discord/src/errors.mjs
|
||||||
|
OK syntax: packages/discord/src/gateway.mjs
|
||||||
|
OK syntax: packages/discord/src/git.mjs
|
||||||
|
OK syntax: packages/discord/src/journal.mjs
|
||||||
|
OK syntax: packages/discord/src/notify.mjs
|
||||||
|
OK syntax: packages/discord/src/rest.mjs
|
||||||
|
OK syntax: packages/discord/src/setspark.mjs
|
||||||
|
OK syntax: packages/discord/src/tools.mjs
|
||||||
|
OK syntax: packages/discord/src/web.mjs
|
||||||
|
OK syntax: packages/discord/bin/git-credential.mjs
|
||||||
|
OK syntax: packages/discord/extension/tools.mjs
|
||||||
|
OK syntax: packages/discord/tests/approvals.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/authorize.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/binding.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/connector.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/context.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/engine.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/fake-pi.mjs
|
||||||
|
OK syntax: packages/discord/tests/gateway.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/git.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/helpers.mjs
|
||||||
|
OK syntax: packages/discord/tests/journal.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/notify.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/recover.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/rest.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/setspark.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/tools.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/web.test.mjs
|
||||||
|
OK syntax: packages/discord/fixtures/claim-worker.mjs
|
||||||
|
OK syntax: packages/discord/fixtures/legacy-owner-worker.mjs
|
||||||
|
OK syntax: scripts/discord.sh
|
||||||
|
OK syntax: scripts/discord-service.sh
|
||||||
|
OK packages/discord declares no dependencies
|
||||||
|
OK no bot-token-shaped string in packages/discord
|
||||||
|
OK fixture binding uses placeholder ids only
|
||||||
|
OK fixture binding validates
|
||||||
|
OK real pi with the extension exposes exactly list_dir, read_file, search and no built-in tool
|
||||||
|
OK real pi with a writable root exposes exactly the three reads plus write_file and edit_file, and writes nothing at start
|
||||||
|
OK real pi with a web key exposes the three reads plus web_fetch and web_search, and no write tool without a writable root
|
||||||
|
OK real pi with a git root exposes the reads, writes and the four git verbs, commits nothing at start, and never shows the token
|
||||||
|
OK real pi with protocol vault adds reserve_id to the git verbs
|
||||||
|
OK real pi with a setspark key exposes the reads and the eight record verbs, no counters, and never shows the key
|
||||||
|
OK real pi refuses a git key on a read-only root (fail closed)
|
||||||
|
OK real pi with the pilot flags (--no-tools) exposes no tool at all
|
||||||
|
OK real pi exits non-zero without MOSAIC_DISCORD_TOOLS: no session, no tools (fail closed)
|
||||||
|
OK a failing nested test fails the run under a parent runner's NODE_TEST_CONTEXT
|
||||||
|
OK node --test packages/discord/tests/ (ℹ pass 178)
|
||||||
|
OK scripts/discord.sh --help exits 0
|
||||||
|
OK scripts/discord.sh check without a binding exits 4
|
||||||
|
OK scripts/discord.sh recover without a binding exits 4
|
||||||
|
OK scripts/discord.sh reload without a binding exits 4
|
||||||
|
OK scripts/discord-service.sh without a command exits 4
|
||||||
|
OK service unit renders with the repository path, a supervised run as the main process, exit 3 never retried, and reload as SIGHUP
|
||||||
|
OK service install writes the rendered unit (0644) and leaves no temp file
|
||||||
|
OK service install a second time reports unchanged
|
||||||
|
OK systemd-analyze verify accepts the rendered unit
|
||||||
|
OK service uninstall removes the unit file
|
||||||
|
OK service install with an unknown flag exits 4
|
||||||
|
OK service install with USER unset finishes and names the account for lingering
|
||||||
|
|
||||||
|
discord suite: 66 passed, 0 failed
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
OK initial ordinary-file install
|
||||||
|
OK installed tree matches canonical source
|
||||||
|
OK installed tree has no symlinks
|
||||||
|
OK check detects installation drift
|
||||||
|
OK sync refuses to overwrite installation drift
|
||||||
|
OK check detects an extra destination file
|
||||||
|
OK check detects an extra destination directory
|
||||||
|
OK check rejects a destination symlink
|
||||||
|
OK sync accepts a canonical source update
|
||||||
|
OK updated installation matches canonical source
|
||||||
|
/mnt/storage/src/mosaic-stack-rocko-108/scripts/test-extension-package.sh: line 14: 1488135 Killed "$@" > /dev/null 2>&1
|
||||||
|
OK forced interruption kills the replacing process
|
||||||
|
OK next invocation recovers old consistent installation
|
||||||
|
OK interrupted replacement rolled back
|
||||||
|
OK sync succeeds after interruption recovery
|
||||||
|
OK unlocked stale lock file does not block
|
||||||
|
OK active lock refuses a concurrent sync
|
||||||
|
OK source symlink fails closed
|
||||||
|
OK nested second entrypoint fails closed
|
||||||
|
|
||||||
|
extension package selftest: 18 passed, 0 failed
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
toolchain: node v26.8.1, python 3.12.8, jsonschema 4.26.0
|
||||||
|
|
||||||
|
OK syntax: scripts/foundation-inspect.mjs
|
||||||
|
OK syntax: scripts/foundation/strict-json.mjs
|
||||||
|
OK syntax: scripts/foundation/canonical.mjs
|
||||||
|
OK syntax: scripts/foundation/resolve.mjs
|
||||||
|
OK syntax: scripts/foundation/validate-record.mjs
|
||||||
|
OK syntax: scripts/foundation/fixtures/build-fixtures.mjs
|
||||||
|
OK syntax: scripts/foundation/canonical.test.mjs
|
||||||
|
OK syntax: scripts/foundation/cli.test.mjs
|
||||||
|
OK syntax: scripts/foundation/fixtures.test.mjs
|
||||||
|
OK syntax: scripts/foundation/resolve.test.mjs
|
||||||
|
OK syntax: scripts/foundation/strict-json.test.mjs
|
||||||
|
OK syntax: scripts/foundation/verify-schema.py (ast only; no bytecode written)
|
||||||
|
OK fixture generator runs
|
||||||
|
OK checked-in fixtures/bundles equal a fresh generation
|
||||||
|
OK checked-in fixtures/raw equal a fresh generation
|
||||||
|
OK checked-in fixtures/index.json equal a fresh generation
|
||||||
|
OK checked-in demo bundles equal a fresh generation
|
||||||
|
OK a failing nested test fails the run under a parent runner's NODE_TEST_CONTEXT
|
||||||
|
OK node --test scripts/foundation/ (ℹ pass 80)
|
||||||
|
OK differential schema oracle: PASS: differential schema oracle (finite corpus; compatibility evidence, not equivalence proof)
|
||||||
|
platform witness: strftime('%Y') for year 999 -> '999' (pinned checker refuses years 0001..0999)
|
||||||
|
node v26.8.1; corpus 1568 records (38 pinned fixtures, 478 unique bundle records, 1052 typeCase/mutation/lexical cases)
|
||||||
|
schema column: agree-valid 540, agree-invalid 991, DISAGREEMENTS 0; strict-only (parser-bound) cases: 27; unsupported-kind records not schema-assessed by the inspector: 10
|
||||||
|
profile column (schema-valid records only): profile-valid 510, profile-invalid 30
|
||||||
|
profile refusals asserted: 30 schema-agreed-valid records refused only by the strict typed-string profile (rule profile-pattern-mismatch), 12 declared by name; 73 named probes verified against declared schema/profile columns
|
||||||
|
OK oracle: zero schema-column disagreements with the pinned checker
|
||||||
|
OK oracle: strict-only profile refusals are counted and asserted
|
||||||
|
OK demo: permitted read preview exits 0 (exit 0)
|
||||||
|
OK demo: permitted file.change preview exits 0 (exit 0)
|
||||||
|
OK demo: assignment.change proposal is unresolved (exit 3) (exit 3)
|
||||||
|
OK demo: revoked registration is refused (exit 3) (exit 3)
|
||||||
|
OK demo: message is not authority (exit 3) (exit 3)
|
||||||
|
OK usage: no arguments exits 2 (exit 2)
|
||||||
|
OK io: missing file exits 4 (exit 4)
|
||||||
|
OK io: directory exits 4 (exit 4)
|
||||||
|
OK io: symlink exits 4 (O_NOFOLLOW) (exit 4)
|
||||||
|
OK bound: oversize fixture exits 2 (exit 2)
|
||||||
|
OK profile: one final LF in a typed selection id is refused before admission (exit 2) (exit 2)
|
||||||
|
OK profile: two final LFs fail the schema pattern itself (exit 2) (exit 2)
|
||||||
|
OK profile: escaped newlines in free-form text stay allowed (exit 0) (exit 0)
|
||||||
|
OK profile refusal is invalid-request/profile-pattern-mismatch with selection and operation withheld, value not echoed
|
||||||
|
OK text output starts with the disclaimer
|
||||||
|
OK json output is valid JSON with result allowed and exactly the charter §7 fields
|
||||||
|
OK json golden matches byte-for-byte
|
||||||
|
OK sandboxed bundle run (env -i, PATH=/nonexistent) produced the unresolved proposal
|
||||||
|
OK sandbox inventory (path/type/size/mode/uid/gid/inode/mtime/sha256) unchanged by runs
|
||||||
|
OK canary never printed (bundle run and credential-file run)
|
||||||
|
OK a non-bundle JSON file is refused at the shape gate, not read into output
|
||||||
|
OK no field of the non-bundle file is echoed
|
||||||
|
|
||||||
|
selftest: 44 passed, 0 failed
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
OK args: exit 2, target-branch
|
||||||
|
OK args: exit 2, target-branch
|
||||||
|
OK args: exit 4
|
||||||
|
OK args: exit 4
|
||||||
|
OK args: exit 4
|
||||||
|
OK --base next refuses before the config is read (got 2)
|
||||||
|
OK a missing system config exits 3 (got 3)
|
||||||
|
OK nobus: exit 3
|
||||||
|
OK schema-table: exit 2, bus-schema
|
||||||
|
OK schema-meta: exit 2, bus-schema
|
||||||
|
OK openBus opens the database read-only
|
||||||
|
OK other-business: exit 2, decision-not-found
|
||||||
|
OK no-raise: exit 2, decision-not-found
|
||||||
|
OK not-a-merge: exit 2, not-a-merge
|
||||||
|
OK open: exit 2, not-resolved
|
||||||
|
OK withdrawn: exit 2, not-resolved
|
||||||
|
OK by-agent: exit 2, not-human
|
||||||
|
OK via-webui: exit 2, not-human
|
||||||
|
OK no-answer: exit 2, not-human
|
||||||
|
OK answer-role: exit 2, not-human
|
||||||
|
OK answer-run: exit 2, not-human
|
||||||
|
OK answer-choice: exit 2, not-human
|
||||||
|
OK two-answers: exit 2, not-human
|
||||||
|
OK chose-no: exit 2, not-merge-option
|
||||||
|
OK two-refs: exit 2, work-ref
|
||||||
|
OK bad-ref: exit 2, work-ref
|
||||||
|
OK task-ref-disagrees: exit 2, work-ref
|
||||||
|
OK raise-task-disagrees: exit 2, work-ref
|
||||||
|
OK target-main: exit 2, target-branch
|
||||||
|
OK superseded-question: exit 2, superseded
|
||||||
|
OK superseded-task: exit 2, superseded
|
||||||
|
OK superseded-by: exit 2, superseded
|
||||||
|
OK no-verdict: exit 2, no-verdict
|
||||||
|
OK changes-later: exit 2, not-approved
|
||||||
|
OK short-commit: exit 2, not-approved
|
||||||
|
OK wrong-task-body: exit 2, not-approved
|
||||||
|
OK args: exit 2, decision-not-found
|
||||||
|
OK earlier-merge: exit 0
|
||||||
|
OK ref-moved: exit 2, ref-moved
|
||||||
|
OK root-top: exit 2, root-file
|
||||||
|
OK root-newdir: exit 2, root-file
|
||||||
|
OK root-src: exit 2, root-file
|
||||||
|
OK unrelated: exit 2, base-conflict
|
||||||
|
OK empty: exit 2, base-conflict
|
||||||
|
OK an empty reviewed diff says so
|
||||||
|
OK dirty-changed: exit 2, checkout-dirty
|
||||||
|
OK dirty-staged: exit 2, checkout-dirty
|
||||||
|
OK dirty-untracked: exit 2, checkout-dirty
|
||||||
|
OK conflict: exit 2, base-conflict
|
||||||
|
OK a refusal after the worktree is added leaves no worktree or scratch
|
||||||
|
OK cleanup looks for the worktree's Docker network
|
||||||
|
OK dirty-during: exit 2, checkout-dirty
|
||||||
|
OK a reviewed path dirtied during the gate moves no ref
|
||||||
|
OK drift: exit 2, patch-drift
|
||||||
|
OK patch-drift leaves no worktree or scratch
|
||||||
|
OK gate-pkg: exit 2, gate-failed
|
||||||
|
OK gate-failed names the failing step's log, and it exists
|
||||||
|
OK gate-failed leaves no worktree or scratch
|
||||||
|
OK gate-script: exit 2, gate-failed
|
||||||
|
OK a failing scripts/test-*.sh fails the gate
|
||||||
|
OK a failed gate moves no ref
|
||||||
|
OK nomods: exit 4
|
||||||
|
OK a target without node_modules leaves no worktree or scratch
|
||||||
|
OK moved: exit 2, base-moved
|
||||||
|
OK base-moved keeps the base where it moved to
|
||||||
|
OK dry: exit 0
|
||||||
|
OK --dry-run writes no ref
|
||||||
|
OK --dry-run prints the commit with --subject and --attribution
|
||||||
|
OK --dry-run runs the gate
|
||||||
|
OK --dry-run leaves no worktree or scratch
|
||||||
|
OK land: exit 0
|
||||||
|
OK the landing is one commit on the old base
|
||||||
|
OK its diff is the reviewed diff by patch-id
|
||||||
|
OK its tree is the dry run's
|
||||||
|
OK the message has the option's subject, the citations and the attribution last
|
||||||
|
OK it prints the line for the PM
|
||||||
|
OK the checked-out base has the reviewed paths and keeps the unrelated edit
|
||||||
|
OK only refs/heads/refactor exists in the target
|
||||||
|
OK the work ref is unchanged
|
||||||
|
OK the bus database is unchanged
|
||||||
|
OK the gate ran each package suite but queue, and each scripts/test-*.sh
|
||||||
|
OK the landing leaves no worktree or scratch
|
||||||
|
OK the target's node_modules is still there, with its contents
|
||||||
|
OK the worktree's Docker network is removed
|
||||||
|
---
|
||||||
|
land-work selftests: 84 passed, 0 failed
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
toolchain: node v26.8.1, git version 2.55.0
|
||||||
|
|
||||||
|
OK syntax: packages/queue/src/cli.mjs
|
||||||
|
OK syntax: packages/queue/src/errors.mjs
|
||||||
|
OK syntax: packages/queue/src/io.mjs
|
||||||
|
OK syntax: packages/queue/src/lock.mjs
|
||||||
|
OK syntax: packages/queue/src/queue.mjs
|
||||||
|
OK syntax: packages/queue/src/review.mjs
|
||||||
|
OK syntax: packages/queue/src/store.mjs
|
||||||
|
OK syntax: packages/queue/tests/commit.test.mjs
|
||||||
|
OK syntax: packages/queue/tests/data.test.mjs
|
||||||
|
OK syntax: packages/queue/tests/dispatch.test.mjs
|
||||||
|
OK syntax: packages/queue/tests/gate-owner.test.mjs
|
||||||
|
OK syntax: packages/queue/tests/helpers.mjs
|
||||||
|
OK syntax: packages/queue/tests/lock.test.mjs
|
||||||
|
OK syntax: packages/queue/tests/migration.test.mjs
|
||||||
|
OK syntax: packages/queue/tests/review.test.mjs
|
||||||
|
OK syntax: packages/queue/tests/store.test.mjs
|
||||||
|
OK syntax: packages/queue/tests/write.test.mjs
|
||||||
|
OK syntax: packages/queue/tests/fixtures/fake-gitea.mjs
|
||||||
|
OK syntax: packages/queue/tests/fixtures/kill-at.mjs
|
||||||
|
OK syntax: packages/queue/tests/fixtures/lock-child.mjs
|
||||||
|
OK syntax: packages/queue/tests/fixtures/mosaic-pre-a2.sh
|
||||||
|
OK syntax: scripts/queue-commit.sh
|
||||||
|
OK syntax: scripts/git-hooks/pre-commit
|
||||||
|
OK syntax: scripts/mosaic
|
||||||
|
OK queue-commit.sh, the guard and scripts/mosaic are executable
|
||||||
|
OK packages/queue declares no dependencies
|
||||||
|
ℹ tests 156
|
||||||
|
ℹ pass 156
|
||||||
|
ℹ fail 0
|
||||||
|
OK node --test packages/queue/tests/
|
||||||
|
OK scripts/mosaic queue help
|
||||||
|
skip queue verify and render --check: this checkout (/mnt/storage/src/mosaic-stack-rocko-108) is not the queue's canonical root (/mnt/storage/src/mosaic-stack)
|
||||||
|
|
||||||
|
queue suite: 28 passed, 0 failed
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
OK valid RELEASE resolves (exit 0)
|
||||||
|
OK invalid RELEASE exits 1 (exit 1)
|
||||||
|
OK missing RELEASE exits 1 (exit 1)
|
||||||
|
OK valid RELEASE leaves image tag consistent with version
|
||||||
|
skip state-machine cases (docker daemon unavailable)
|
||||||
|
|
||||||
|
selftest: 4 passed, 0 failed
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
OK valid task validates (exit 0)
|
||||||
|
OK unknown task key exits 2 (exit 2)
|
||||||
|
OK unsupported taskVersion exits 2 (exit 2)
|
||||||
|
OK invalid task id exits 2 (exit 2)
|
||||||
|
OK empty prompt exits 2 (exit 2)
|
||||||
|
OK NUL in expectExact exits 2 (exit 2)
|
||||||
|
OK out-of-range timeout exits 2 (exit 2)
|
||||||
|
OK missing mission file exits 4 (exit 4)
|
||||||
|
OK task with valid mission validates (exit 0)
|
||||||
|
OK invalid mission exits 2 (exit 2)
|
||||||
|
OK validate missing task exits 4 (exit 4)
|
||||||
|
OK validation does not modify the task file
|
||||||
|
OK prune dry-run exits 0 (exit 0)
|
||||||
|
OK dry-run deleted nothing
|
||||||
|
OK prune --keep=2 --yes removes oldest (exit 0)
|
||||||
|
OK kept exactly 2 newest runs
|
||||||
|
OK newest run kept, oldest pruned
|
||||||
|
OK append-only receipt written (3 entries)
|
||||||
|
OK sessions/workspaces untouched by prune
|
||||||
|
OK prune with invalid keep exits 4 (exit 4)
|
||||||
|
skip adapter seam cases (docker daemon unavailable)
|
||||||
|
skip workspace/capability cases (docker daemon unavailable)
|
||||||
|
skip live task cases (docker unavailable)
|
||||||
|
OK onboard without name exits 4 (non-interactive) (exit 4)
|
||||||
|
OK onboard --name renders profile (exit 0)
|
||||||
|
OK profile written
|
||||||
|
OK canon structure: required filled, optional placeholdered
|
||||||
|
OK canon sections present
|
||||||
|
skip live recall pair: user recall run, recalled user name (docker daemon unavailable)
|
||||||
|
OK no agent identity on headless run
|
||||||
|
|
||||||
|
selftest: 26 passed, 0 failed
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"suite": "node-cli",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:08:16.669752+00:00",
|
||||||
|
"ended": "2026-10-14T20:08:29.916793+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-auth",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:08:29.917023+00:00",
|
||||||
|
"ended": "2026-10-14T20:08:30.532205+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-conductor",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:08:30.532452+00:00",
|
||||||
|
"ended": "2026-10-14T20:08:35.257973+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-config",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:08:35.258217+00:00",
|
||||||
|
"ended": "2026-10-14T20:08:36.927811+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-discord",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:08:36.928073+00:00",
|
||||||
|
"ended": "2026-10-14T20:08:43.506603+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-extension-package",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:08:43.506874+00:00",
|
||||||
|
"ended": "2026-10-14T20:08:44.823470+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-foundation",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:08:44.823736+00:00",
|
||||||
|
"ended": "2026-10-14T20:09:21.468582+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-land-work",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:09:21.468850+00:00",
|
||||||
|
"ended": "2026-10-14T20:09:29.950720+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-queue",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:09:29.951035+00:00",
|
||||||
|
"ended": "2026-10-14T20:09:50.306428+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-release",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:09:50.306714+00:00",
|
||||||
|
"ended": "2026-10-14T20:09:50.420924+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-task",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:09:50.421163+00:00",
|
||||||
|
"ended": "2026-10-14T20:09:52.390220+00:00"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,197 @@
|
|||||||
|
✔ every screen and overlay fits 120x36, 80x24 and the narrow layout, row for row (1477.376378ms)
|
||||||
|
✔ width counts terminal cells: wide CJK and emoji 2, U+FE0F after a one-cell base 1, marks 0 (68.456805ms)
|
||||||
|
✔ broker text is shown, never interpreted: no raw control character or bidi override reaches the terminal (173.578768ms)
|
||||||
|
✔ NO_COLOR: no escape codes, except reverse video on the selected row (250.133787ms)
|
||||||
|
✔ 1-9 shows the decide flow's own lines and question; only y resolves (54.740106ms)
|
||||||
|
✔ the app shows the same decide text as mosaic decide (23.028442ms)
|
||||||
|
✔ any key but y or Y at the question answers No; nothing is sent (198.172467ms)
|
||||||
|
✔ below 40x10 the question is hidden, so every key answers it No, y included (Filbert R3) (62.782956ms)
|
||||||
|
✔ under 40 columns a tall terminal shows the too-small screen even where the decide box would fit; y sends nothing (Filbert N10) (270.375393ms)
|
||||||
|
✔ a hidden decide box names the way out, and the status line under it does not promise y (Filbert N12) (32.954214ms)
|
||||||
|
✔ a throw while answering the question goes to crash, sends nothing and leaves no job pending (21.639014ms)
|
||||||
|
✔ type-ahead never answers the question: a paste, keys typed before it is drawn, keys inside askMs (404.232785ms)
|
||||||
|
✔ quitting at the question answers No and sends nothing, armed or not (46.718151ms)
|
||||||
|
✔ a timer tick reads nothing under an overlay, never answers the question, and keeps a resolved status (33.5244ms)
|
||||||
|
✔ a long question is cut inside the question; the action, target, choice and prompt stay (Dewey B1) (54.356483ms)
|
||||||
|
✔ a decide box too big for the terminal says so, and every key answers it No, y included (Dewey B1, round 3) (335.035339ms)
|
||||||
|
✔ at every size the decide box shows each line y depends on, or says it is hidden (8489.83376ms)
|
||||||
|
✔ outcome unknown: the CLI's sentence, no retry, then the trail or a re-read (62.891626ms)
|
||||||
|
✔ refused and failed reads keep the last list, marked stale; a refused decide says refused (30.493765ms)
|
||||||
|
✔ help or a detail box cut to fit keeps its last line, Esc included (Dewey) (15.406428ms)
|
||||||
|
✔ keys: views, moving, trail of a selection, the command line, help and quit (73.149516ms)
|
||||||
|
✔ one option: the status line says Press 1, not 1-1 (15.210703ms)
|
||||||
|
✔ no business: the app says so and :business picks one (8.619387ms)
|
||||||
|
✔ mosaic with no argument: exit 3 in an agent run, exit 4 with the usage off a terminal, the app on one (1.803719ms)
|
||||||
|
✔ scripts/mosaic with no argument reaches the app entry; the seat usage it printed before has not drifted (164.997031ms)
|
||||||
|
✔ strings to keep exactly live once, in the decide flow and the transport; the app does not restate them (0.443614ms)
|
||||||
|
✔ decide with --note still asks; a No sends nothing (9.732223ms)
|
||||||
|
✔ the app's business comes from a live bus host only (0.979552ms)
|
||||||
|
✔ runApp leaves the terminal as it found it on q, end of input, SIGTERM, SIGINT, SIGHUP and an error, the first frame's included (6.861451ms)
|
||||||
|
✔ draw is pure: same state, same frame (0.746609ms)
|
||||||
|
✔ inbox lists only decisions routed to the human, with what approving authorizes and how to decide (31.010812ms)
|
||||||
|
✔ decide resolves by id prefix with --yes, and the trail shows it in broker order with the task to follow (23.849413ms)
|
||||||
|
✔ decide refuses without a terminal or --yes, on an unknown option and on a short reference (21.145861ms)
|
||||||
|
✔ decide prints a declining choice as declining (16.669356ms)
|
||||||
|
✔ an unknown outcome is reported once and never resent (16.143936ms)
|
||||||
|
✔ a decision closed before the answer arrives exits 2 and points at its trail (16.817295ms)
|
||||||
|
✔ a prefix that matches two open decisions exits 2 and resolves neither (15.339209ms)
|
||||||
|
✔ without --business a command uses the live host's business, and a stale host.json is not a host (13.980476ms)
|
||||||
|
✔ every human command refuses inside an agent run before it touches the bus (13.442105ms)
|
||||||
|
✔ usage errors exit 4; no business and no host is a usage error (15.069535ms)
|
||||||
|
✔ agents and tasks print through the broker (13.574066ms)
|
||||||
|
✔ notify.json: missing, loose, malformed and extra keys refuse; a binding or null passes (1.971942ms)
|
||||||
|
✔ bootConfig builds the broker's boot message for one business, with no trackers key when no project names one (72.814485ms)
|
||||||
|
✔ trackers come from the tracker.* variables of the one project that names a tracker project (89.258734ms)
|
||||||
|
✔ with two projects, the one that sets tracker.project supplies the tracker and the other is no conflict (42.902867ms)
|
||||||
|
✔ two projects that each name a tracker project refuse, since the boot shape holds one (46.122674ms)
|
||||||
|
✔ a business without tracker.baseUrl gets no trackers entry (46.961323ms)
|
||||||
|
✔ an unknown business and a broken system config refuse with exit 3 (65.294014ms)
|
||||||
|
✔ follow prints an unsolicited message after plain talk returned (37.572482ms)
|
||||||
|
✔ talk --follow continues after reply and prints a later unsolicited message (34.69679ms)
|
||||||
|
✔ inbox lists all unread human messages under decisions, does not deliver or read them (300.970315ms)
|
||||||
|
✔ follow refuses agent context and bad arguments (10.27396ms)
|
||||||
|
✔ follow Ctrl-C wakes the poll sleep and removes its handler; transport errors also clean up (9.023136ms)
|
||||||
|
✔ plain talk leaves the process SIGINT handlers unchanged (10.297506ms)
|
||||||
|
✔ empty views say so (1.20063ms)
|
||||||
|
✔ the trail keeps the broker's order and names a decision's task without its rows (1.32809ms)
|
||||||
|
✔ tasks print the tracker fields the snapshot carries (0.221093ms)
|
||||||
|
✔ the review loop: the coder pushes and asks, the reviewer fetches and approves, and the task's trail holds each step (462.894648ms)
|
||||||
|
✔ refusals: no action, non-fast-forward, an unknown commit or request, and a push for another task moves only that task's ref (335.907022ms)
|
||||||
|
✔ the size cap refuses a push before any byte (146.574784ms)
|
||||||
|
✔ a fetch over the cap refuses before any byte reaches the reviewer (355.906517ms)
|
||||||
|
✔ the socket refuses a request with no capability, an unknown one, and a bad request line (162.154682ms)
|
||||||
|
✔ a rigged clone runs nothing: hooks, fsmonitor, a filter, a gitlink and a symlinked .git/config leave no marker (265.237099ms)
|
||||||
|
✔ an identity with no role, or of another business, refuses not-a-role and moves no ref (215.575656ms)
|
||||||
|
✔ a review of a project the business no longer has refuses unknown-project (195.751869ms)
|
||||||
|
✔ past maxActive connections the socket refuses git-busy, and a hung-up connection frees its slot (127.067561ms)
|
||||||
|
✔ close() answers host-closing to a connection still sending its request line (122.81349ms)
|
||||||
|
✔ a bundle that trickles in refuses body-timeout at its deadline and frees its slot (533.669416ms)
|
||||||
|
✔ a reviewer gone before its bundle was sent is filed fetch-aborted, not as the host's fault (446.171438ms)
|
||||||
|
✔ a reviewer that hangs up the moment it has the whole bundle was served, not aborted (509.475251ms)
|
||||||
|
✔ send: a close after every byte left is served; one that fails a queued write is fetch-aborted (41.582627ms)
|
||||||
|
✔ a bundle with no bytes for bodyIdle refuses body-timeout long before its deadline (453.725854ms)
|
||||||
|
✔ send: a close once the loop is past its last chunk is served, and a failed write there is fetch-aborted (44.714286ms)
|
||||||
|
✔ letGo waits for an answer to leave for at most its cap, then destroys the socket (300.745188ms)
|
||||||
|
✔ a record that fails and can't be undone refuses rollback-failed, which the host logs (355.23866ms)
|
||||||
|
✔ the host boots the broker, binds a launch in process, and the notifier DMs a blocking decision exactly once (924.003791ms)
|
||||||
|
✔ a notifier that dies takes the host down with exit 1, so the unit restarts the pair (182.905222ms)
|
||||||
|
✔ a second host for the same data root refuses with exit 3 while the first runs (85.586283ms)
|
||||||
|
✔ two bus starts racing for one data root leave one host running; the other refuses that a host already runs (478.889989ms)
|
||||||
|
✔ a host takes over a host.lock its dead host left, and puts back a live claim that replaced it meanwhile (1.579175ms)
|
||||||
|
✔ a host.lock that goes between the check and the read is tried again; one that can't be parsed still refuses as unreadable (0.970864ms)
|
||||||
|
✔ a live host's lock stays, however old the file is (0.659135ms)
|
||||||
|
✔ a host.lock left by a host killed with SIGKILL doesn't stop the next bus start (760.448816ms)
|
||||||
|
✔ while a host boots, a reader sees no host: the human commands still ask for --business, stop and status find none (221.046742ms)
|
||||||
|
✔ a host started before host.lock existed, holding only host.json, still refuses a second start, which leaves no lock (27.428979ms)
|
||||||
|
✔ a broker fork that throws leaves no host.lock and no host.json (30.784261ms)
|
||||||
|
✔ a broker send that throws leaves no host.lock and no host.json (31.486212ms)
|
||||||
|
✔ a broker that misses its boot wait leaves no host.lock and no host.json (37.74624ms)
|
||||||
|
✔ a notifier fork that throws stops the broker and leaves no host.lock and no host.json (83.279435ms)
|
||||||
|
✔ a notifier send that throws stops the broker and leaves no host.lock and no host.json (90.942799ms)
|
||||||
|
✔ a boot reply with no reader for the business refuses with exit 3 naming it, before the notifier starts, and leaves no host.lock and no live broker (86.153244ms)
|
||||||
|
✔ a boot reply with no reader for the business refuses with exit 3 naming it, with no notifier, and leaves no host.lock and no live broker (80.064267ms)
|
||||||
|
✔ a host.json that can't be written stops both children and leaves no host.lock (198.679676ms)
|
||||||
|
✔ an error event on the broker before it replies fails the start at once, and leaves no host.lock and no live child (33.223042ms)
|
||||||
|
✔ an error event on the notifier before it replies fails the start at once, and leaves no host.lock and no live child (84.449929ms)
|
||||||
|
✔ an error event on the broker while the notifier starts fails the start once the notifier replies (209.469683ms)
|
||||||
|
✔ an error event on the broker once the host is up stops the host with exit 1, and leaves no host.lock and no host.json (203.256422ms)
|
||||||
|
✔ an error event on the notifier once the host is up stops the host with exit 1, and leaves no host.lock and no host.json (195.462446ms)
|
||||||
|
✔ a broker reply that misses the wait breaks the channel: the late reply answers nothing, later requests refuse, the host exits 1 (1091.518407ms)
|
||||||
|
✔ a broker reply with another request's id, or none, breaks the channel and the host exits 1 (167.344726ms)
|
||||||
|
✔ a broker reply with no request waiting breaks the channel and the host exits 1 (85.563382ms)
|
||||||
|
✔ a notifier that refuses stops the broker and the host refuses with exit 3 (147.73826ms)
|
||||||
|
✔ a notifier that refuses after the broker died still refuses with exit 3, without a send to the dead broker (136.407305ms)
|
||||||
|
✔ a notifier that dies before it replies, after the broker died, still refuses, without a send to the dead broker (76.875591ms)
|
||||||
|
✔ a close send that fails with EPIPE after the notifier refuses still gives the notifier's refusal, exit 3 (136.686127ms)
|
||||||
|
✔ a close send that fails with EPIPE after the notifier dies unanswered still gives the notifier's error (87.172494ms)
|
||||||
|
✔ close() whose stop and close sends fail with EPIPE still finishes, with exit 1 (155.273501ms)
|
||||||
|
✔ watchChildren reports a child that died before it was called, and one that dies later (24.019176ms)
|
||||||
|
✔ bus stop refuses to signal a live pid that is not a bus host (203.114406ms)
|
||||||
|
✔ bus start refuses with exit 3 and the code when the broker refuses to boot; bus status names the lock (267.40057ms)
|
||||||
|
✔ bus start refuses with exit 3 without a notifier config (119.409713ms)
|
||||||
|
✔ bus start runs until bus stop; status reports it while it runs (733.89035ms)
|
||||||
|
✔ bus-service.sh renders the unit and installs it into a given directory (64.276204ms)
|
||||||
|
✔ bus-service.sh pins the claude binary, refuses one the unit can't carry, and renders without one (81.417527ms)
|
||||||
|
✔ bus-service.sh refuses a directory pin and keeps a symlink default unresolved (14.605023ms)
|
||||||
|
✔ bus-service.sh refuses a default claude without the execute bit, or in a PATH dir with a space (9.333543ms)
|
||||||
|
✔ bus start --pm: the PM runs under its own PID namespace, registered, with a manifest (1242.257226ms)
|
||||||
|
✔ the PM launches a coder through its launch tool; the coder answers; refusals name their code (419.563448ms)
|
||||||
|
✔ each launch makes sure the workspace has a clone of the project: cloned, fast-forwarded, or fetched and logged (3539.169985ms)
|
||||||
|
✔ a project clone that can't be made refuses checkout-failed, from --pm and from a session, with no run and no clone left (121.12262ms)
|
||||||
|
✔ a runner that stops at once ends its launch with the runner's reason (191.187442ms)
|
||||||
|
✔ a Claude Code launch with no session credential refuses before it starts (98.040699ms)
|
||||||
|
✔ a pi launch needs no session credential: pi logs in through its own ENV_ALLOW variables (178.633716ms)
|
||||||
|
✔ a runner killed from the host ends its launch as killed, not failed (244.156ms)
|
||||||
|
✔ a missing or failing bwrap refuses sandbox-unavailable before anything starts; there is no unconfined fallback (105.311418ms)
|
||||||
|
✔ a real Claude Code coder's shell can't read a stand-in secret or anything else its sandbox doesn't hold (1260.203462ms)
|
||||||
|
✔ a host that died hard leaves its sessions to the next host, which kills them and ends their runs so the role can be launched again (626.499496ms)
|
||||||
|
✔ a host that died hard leaves its sessions to the next host, which finds one already exited (23) and ends their runs so the role can be launched again (3548.422588ms)
|
||||||
|
✔ a malformed sessions.json refuses the host start with exit 3 and stays as it was (89.14685ms)
|
||||||
|
✔ an over-long launch request is refused at once, not at the 10 s idle timeout (89.756313ms)
|
||||||
|
✔ a launch client that never closes its side doesn't hold the host's close (86.455323ms)
|
||||||
|
✔ a runner that ignores SIGTERM is killed when the host closes (1199.159784ms)
|
||||||
|
✔ claudeVersion asks MOSAIC_CLAUDE_BIN when set, else claude on PATH (4.464462ms)
|
||||||
|
✔ zoned uses the IANA zone across DST (25.683299ms)
|
||||||
|
✔ each open blocking decision is DM'd once, across polls and a restart; non-blocking ones are not (40.95855ms)
|
||||||
|
✔ two blocking decisions get two DMs with different nonces (21.854105ms)
|
||||||
|
✔ the digest nonce differs per business and per day and fits Discord's 25 characters (0.312043ms)
|
||||||
|
✔ a failed DM is journaled, backs off, and is retried until it lands (19.49567ms)
|
||||||
|
✔ five definite refusals stop a DM: one gave-up line, one log line, and a restart keeps the count (23.848827ms)
|
||||||
|
✔ 429s, 5xx-style unknowns and refusals without a status never count toward the limit (23.074812ms)
|
||||||
|
✔ a crash between the fifth refusal and its gave-up line: the next poll appends it and sends nothing (17.076166ms)
|
||||||
|
✔ polled every POLL_MS against a permanent 403, a DM is sent at 0, 30, 60, 90 and 120 min and gives up only then (120.61351ms)
|
||||||
|
✔ a restart after the second refusal does not send before that refusal's 30 min are up (59.927136ms)
|
||||||
|
✔ the digest goes at 08:00 Chicago once a day, with blocking ones marked as DM'd (14.12565ms)
|
||||||
|
✔ a late start with no digest for the day sends one at once; an empty inbox gets one line (11.094881ms)
|
||||||
|
✔ an inbox read failure is logged and the next poll retries (0.747952ms)
|
||||||
|
✔ no Discord id reaches the journal or the log (9.790072ms)
|
||||||
|
✔ the journal: a torn tail is copied out and truncated, so an append after it reopens cleanly (1.934302ms)
|
||||||
|
✔ the journal: a crash between the copy and the truncate leaves a tail the next open repairs (2.61942ms)
|
||||||
|
✔ the journal: a whole file that is one torn line truncates to empty (1.264351ms)
|
||||||
|
✔ the journal: a malformed complete line refuses and leaves the file and any torn tail alone (0.57017ms)
|
||||||
|
✔ the journal: a loose file mode, a loose directory or a symlinked journal refuses (0.702592ms)
|
||||||
|
✔ the journal: a line with a wrong type refuses with exit 3 and names the field (2.003221ms)
|
||||||
|
✔ the journal: a symlinked directory refuses and says it is a link (0.342545ms)
|
||||||
|
✔ the journal: a dangling directory link, a parent that is a file and a journal that is a directory each refuse with exit 3 (0.603549ms)
|
||||||
|
✔ the journal: an append after the file was swapped for a symlink refuses and writes nothing through it (2.090942ms)
|
||||||
|
✔ the journal: a directory it cannot write or create refuses with exit 3 and names the path (0.510464ms)
|
||||||
|
✔ digest content stays within Discord's 2000 characters (0.315826ms)
|
||||||
|
✔ runLoop never overlaps ticks and stops after the one in flight (110.940236ms)
|
||||||
|
✔ shared copy: npm ci, pushed reachability, readonly/existing copy, webui delegation (529.621208ms)
|
||||||
|
✔ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (442.829774ms)
|
||||||
|
✔ bus unit copy/pm pins, install refuses all busy states and failed reads, drop-in refusal (482.787297ms)
|
||||||
|
✔ missing package manifest refuses before npm; npm failure removes the unpublished temp copy (285.730656ms)
|
||||||
|
✔ real pinned install loads bus and Console; same-copy mosaic talk passes proof, other trees refuse (3360.500362ms)
|
||||||
|
✔ bus status reads effective copy/pm/drop-ins without writes; check refuses an overridden ExecStart (497.115879ms)
|
||||||
|
✔ drop-ins in either override field and malformed metadata refuse; uninstall also checks --no-reload (173.893178ms)
|
||||||
|
✔ install never shows a template name on systemd 261; template drop-ins still refuse (179.721222ms)
|
||||||
|
✔ unlisted instance drop-in is found in another unit lookup directory; path discovery errors refuse (162.632738ms)
|
||||||
|
✔ inherited mosaic-.service.d override refuses without changing the unit (187.103951ms)
|
||||||
|
✔ inherited service.d override refuses without changing the unit (182.031116ms)
|
||||||
|
✔ inherited drop-in unreadable directory or file refuses before writing (158.469248ms)
|
||||||
|
✔ talk --tester sends a [mos test] message as tester from inside an agent and prints the role's reply (30.270079ms)
|
||||||
|
✔ talk --tester refuses text without the [mos test] prefix before any call (16.542949ms)
|
||||||
|
✔ the read verbs take --tester inside an agent, and the trail shows the tester as the sender (22.603548ms)
|
||||||
|
✔ decide, stop and launches take no --tester (16.225884ms)
|
||||||
|
✔ the tester transport runs tester-cli.mjs, and the tester's refusals exit 3 (0.50164ms)
|
||||||
|
✔ with no stand-in transport, --tester runs tester-cli.mjs on the data root's socket (0.958693ms)
|
||||||
|
task.close {} answered: invalid-request; fake saw 18 requests, first GET /info 200, GET /projects/1 200, GET /projects/1/views 200
|
||||||
|
task.close on a missing task answered: task-not-found; it made GET /tasks/999 404
|
||||||
|
✔ bootConfig trackers reach the S3 adapter in the real broker child, which goes ready against a fake Vikunja (336.025062ms)
|
||||||
|
✔ the transport writes {business, verb, args} to the child and reads its JSON (59.959474ms)
|
||||||
|
✔ a bus code on stderr becomes the exit code; garbage and timeouts are outcome problems (2208.096258ms)
|
||||||
|
✔ busExit and refuseInsideAgent (0.494712ms)
|
||||||
|
✔ talk sends a REQUEST, prints and reads everything that arrives, and stops at the reply (57.061086ms)
|
||||||
|
✔ talk --wait 0 only sends; no reply within --wait exits 1 and says where it will show (1021.863658ms)
|
||||||
|
✔ a late reply the Console has listed still reaches the next talk (2032.93961ms)
|
||||||
|
✔ talk, stop and launches off/on refuse inside an agent run; bad arguments are usage errors (13.662668ms)
|
||||||
|
✔ launches off and on go to the broker and change the business's launch state (13.761276ms)
|
||||||
|
✔ launches list reads sessions.json and marks a stale entry; stop reports it and refuses a non-runner (12.454406ms)
|
||||||
|
ℹ tests 187
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 187
|
||||||
|
ℹ fail 0
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 13204.628602
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
OK status with missing harness credential exits 3 and still lists accounts
|
||||||
|
OK status reports harness credential (read-only) + mosaic accounts
|
||||||
|
OK api key material never reaches output
|
||||||
|
OK oauth token material never reaches output
|
||||||
|
OK unparseable credential file exits 2
|
||||||
|
OK symlinked credential file exits 4
|
||||||
|
OK env-side credential names reported
|
||||||
|
OK env var values never reach output
|
||||||
|
OK accounts without an accounts dir reports none and creates nothing
|
||||||
|
OK accounts lists files and marks the active one
|
||||||
|
OK loose account perms flagged in listing
|
||||||
|
OK agent --auth with missing account file refuses (exit 4)
|
||||||
|
OK agent --auth with non-0600 account file refuses
|
||||||
|
OK agent --auth with invalid account name refuses
|
||||||
|
OK auth.sh without valid config refuses
|
||||||
|
|
||||||
|
selftest: 15 passed, 0 failed
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
On branch refactor
|
||||||
|
Your branch is up to date with 'origin/refactor'.
|
||||||
|
|
||||||
|
nothing to commit, working tree clean
|
||||||
|
OK dry-run: allowed change, exit 0, nothing committed (exit 0)
|
||||||
|
OK dry-run committed nothing
|
||||||
|
OK apply: allowed change exits 0 (exit 0)
|
||||||
|
OK apply: attribution in commit subject
|
||||||
|
OK apply: target tree clean after commit
|
||||||
|
OK disallowed path refused (exit 1)
|
||||||
|
OK disallowed path: target untouched
|
||||||
|
OK syntax gate refused broken .mjs (exit 1)
|
||||||
|
OK syntax gate: target untouched
|
||||||
|
OK suite failure refused (exit 1)
|
||||||
|
OK suite failure: target reverted to clean
|
||||||
|
OK disabled policy refused (exit 2)
|
||||||
|
OK disabled policy: target untouched
|
||||||
|
OK failed run refused (exit 1)
|
||||||
|
OK failed run: target untouched
|
||||||
|
OK missing run exits 4 (exit 4)
|
||||||
|
OK invalid policy exits 2 (exit 2)
|
||||||
|
|
||||||
|
selftest: 17 passed, 0 failed
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
OK absent adapter defaults to pi
|
||||||
|
OK adapter mock validates (exit 0)
|
||||||
|
OK unsupported adapter exits 2 (exit 2)
|
||||||
|
OK env exports adapter
|
||||||
|
OK bootstrap creates default when absent (exit 0)
|
||||||
|
OK bootstrap wrote config file
|
||||||
|
OK bootstrap is idempotent on existing config (exit 0)
|
||||||
|
OK bootstrap did not rewrite existing config
|
||||||
|
OK validate missing config exits 3 (exit 3)
|
||||||
|
OK malformed JSON exits 2 (exit 2)
|
||||||
|
OK unsupported configVersion exits 2 (exit 2)
|
||||||
|
OK unknown top-level key exits 2 (exit 2)
|
||||||
|
OK unknown execution key exits 2 (exit 2)
|
||||||
|
OK unsupported backend exits 2 (exit 2)
|
||||||
|
OK unsupported environment exits 2 (exit 2)
|
||||||
|
OK relative dataRoot exits 2 (exit 2)
|
||||||
|
OK non-canonical dataRoot exits 2 (exit 2)
|
||||||
|
OK filesystem root dataRoot exits 2 (exit 2)
|
||||||
|
OK home directory dataRoot exits 2 (exit 2)
|
||||||
|
OK dataRoot containing config dir exits 2 (exit 2)
|
||||||
|
OK control character in provider exits 2 (exit 2)
|
||||||
|
OK symlinked config file exits 2 (exit 2)
|
||||||
|
OK env exports resolve correctly
|
||||||
|
OK failed validation modified nothing
|
||||||
|
|
||||||
|
selftest: 24 passed, 0 failed
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
toolchain: node v26.8.1
|
||||||
|
|
||||||
|
OK syntax: packages/discord/src/approvals.mjs
|
||||||
|
OK syntax: packages/discord/src/authorize.mjs
|
||||||
|
OK syntax: packages/discord/src/binding.mjs
|
||||||
|
OK syntax: packages/discord/src/cli.mjs
|
||||||
|
OK syntax: packages/discord/src/connector.mjs
|
||||||
|
OK syntax: packages/discord/src/context.mjs
|
||||||
|
OK syntax: packages/discord/src/engine-pi.mjs
|
||||||
|
OK syntax: packages/discord/src/errors.mjs
|
||||||
|
OK syntax: packages/discord/src/gateway.mjs
|
||||||
|
OK syntax: packages/discord/src/git.mjs
|
||||||
|
OK syntax: packages/discord/src/journal.mjs
|
||||||
|
OK syntax: packages/discord/src/notify.mjs
|
||||||
|
OK syntax: packages/discord/src/rest.mjs
|
||||||
|
OK syntax: packages/discord/src/setspark.mjs
|
||||||
|
OK syntax: packages/discord/src/tools.mjs
|
||||||
|
OK syntax: packages/discord/src/web.mjs
|
||||||
|
OK syntax: packages/discord/bin/git-credential.mjs
|
||||||
|
OK syntax: packages/discord/extension/tools.mjs
|
||||||
|
OK syntax: packages/discord/tests/approvals.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/authorize.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/binding.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/connector.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/context.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/engine.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/fake-pi.mjs
|
||||||
|
OK syntax: packages/discord/tests/gateway.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/git.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/helpers.mjs
|
||||||
|
OK syntax: packages/discord/tests/journal.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/notify.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/recover.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/rest.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/setspark.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/tools.test.mjs
|
||||||
|
OK syntax: packages/discord/tests/web.test.mjs
|
||||||
|
OK syntax: packages/discord/fixtures/claim-worker.mjs
|
||||||
|
OK syntax: packages/discord/fixtures/legacy-owner-worker.mjs
|
||||||
|
OK syntax: scripts/discord.sh
|
||||||
|
OK syntax: scripts/discord-service.sh
|
||||||
|
OK packages/discord declares no dependencies
|
||||||
|
OK no bot-token-shaped string in packages/discord
|
||||||
|
OK fixture binding uses placeholder ids only
|
||||||
|
OK fixture binding validates
|
||||||
|
OK real pi with the extension exposes exactly list_dir, read_file, search and no built-in tool
|
||||||
|
OK real pi with a writable root exposes exactly the three reads plus write_file and edit_file, and writes nothing at start
|
||||||
|
OK real pi with a web key exposes the three reads plus web_fetch and web_search, and no write tool without a writable root
|
||||||
|
OK real pi with a git root exposes the reads, writes and the four git verbs, commits nothing at start, and never shows the token
|
||||||
|
OK real pi with protocol vault adds reserve_id to the git verbs
|
||||||
|
OK real pi with a setspark key exposes the reads and the eight record verbs, no counters, and never shows the key
|
||||||
|
OK real pi refuses a git key on a read-only root (fail closed)
|
||||||
|
OK real pi with the pilot flags (--no-tools) exposes no tool at all
|
||||||
|
OK real pi exits non-zero without MOSAIC_DISCORD_TOOLS: no session, no tools (fail closed)
|
||||||
|
OK a failing nested test fails the run under a parent runner's NODE_TEST_CONTEXT
|
||||||
|
OK node --test packages/discord/tests/ (ℹ pass 178)
|
||||||
|
OK scripts/discord.sh --help exits 0
|
||||||
|
OK scripts/discord.sh check without a binding exits 4
|
||||||
|
OK scripts/discord.sh recover without a binding exits 4
|
||||||
|
OK scripts/discord.sh reload without a binding exits 4
|
||||||
|
OK scripts/discord-service.sh without a command exits 4
|
||||||
|
OK service unit renders with the repository path, a supervised run as the main process, exit 3 never retried, and reload as SIGHUP
|
||||||
|
OK service install writes the rendered unit (0644) and leaves no temp file
|
||||||
|
OK service install a second time reports unchanged
|
||||||
|
OK systemd-analyze verify accepts the rendered unit
|
||||||
|
OK service uninstall removes the unit file
|
||||||
|
OK service install with an unknown flag exits 4
|
||||||
|
OK service install with USER unset finishes and names the account for lingering
|
||||||
|
|
||||||
|
discord suite: 66 passed, 0 failed
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
OK initial ordinary-file install
|
||||||
|
OK installed tree matches canonical source
|
||||||
|
OK installed tree has no symlinks
|
||||||
|
OK check detects installation drift
|
||||||
|
OK sync refuses to overwrite installation drift
|
||||||
|
OK check detects an extra destination file
|
||||||
|
OK check detects an extra destination directory
|
||||||
|
OK check rejects a destination symlink
|
||||||
|
OK sync accepts a canonical source update
|
||||||
|
OK updated installation matches canonical source
|
||||||
|
/mnt/storage/src/mosaic-stack-rocko-108/scripts/test-extension-package.sh: line 14: 1554475 Killed "$@" > /dev/null 2>&1
|
||||||
|
OK forced interruption kills the replacing process
|
||||||
|
OK next invocation recovers old consistent installation
|
||||||
|
OK interrupted replacement rolled back
|
||||||
|
OK sync succeeds after interruption recovery
|
||||||
|
OK unlocked stale lock file does not block
|
||||||
|
OK active lock refuses a concurrent sync
|
||||||
|
OK source symlink fails closed
|
||||||
|
OK nested second entrypoint fails closed
|
||||||
|
|
||||||
|
extension package selftest: 18 passed, 0 failed
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
toolchain: node v26.8.1, python 3.12.8, jsonschema 4.26.0
|
||||||
|
|
||||||
|
OK syntax: scripts/foundation-inspect.mjs
|
||||||
|
OK syntax: scripts/foundation/strict-json.mjs
|
||||||
|
OK syntax: scripts/foundation/canonical.mjs
|
||||||
|
OK syntax: scripts/foundation/resolve.mjs
|
||||||
|
OK syntax: scripts/foundation/validate-record.mjs
|
||||||
|
OK syntax: scripts/foundation/fixtures/build-fixtures.mjs
|
||||||
|
OK syntax: scripts/foundation/canonical.test.mjs
|
||||||
|
OK syntax: scripts/foundation/cli.test.mjs
|
||||||
|
OK syntax: scripts/foundation/fixtures.test.mjs
|
||||||
|
OK syntax: scripts/foundation/resolve.test.mjs
|
||||||
|
OK syntax: scripts/foundation/strict-json.test.mjs
|
||||||
|
OK syntax: scripts/foundation/verify-schema.py (ast only; no bytecode written)
|
||||||
|
OK fixture generator runs
|
||||||
|
OK checked-in fixtures/bundles equal a fresh generation
|
||||||
|
OK checked-in fixtures/raw equal a fresh generation
|
||||||
|
OK checked-in fixtures/index.json equal a fresh generation
|
||||||
|
OK checked-in demo bundles equal a fresh generation
|
||||||
|
OK a failing nested test fails the run under a parent runner's NODE_TEST_CONTEXT
|
||||||
|
OK node --test scripts/foundation/ (ℹ pass 80)
|
||||||
|
OK differential schema oracle: PASS: differential schema oracle (finite corpus; compatibility evidence, not equivalence proof)
|
||||||
|
platform witness: strftime('%Y') for year 999 -> '999' (pinned checker refuses years 0001..0999)
|
||||||
|
node v26.8.1; corpus 1568 records (38 pinned fixtures, 478 unique bundle records, 1052 typeCase/mutation/lexical cases)
|
||||||
|
schema column: agree-valid 540, agree-invalid 991, DISAGREEMENTS 0; strict-only (parser-bound) cases: 27; unsupported-kind records not schema-assessed by the inspector: 10
|
||||||
|
profile column (schema-valid records only): profile-valid 510, profile-invalid 30
|
||||||
|
profile refusals asserted: 30 schema-agreed-valid records refused only by the strict typed-string profile (rule profile-pattern-mismatch), 12 declared by name; 73 named probes verified against declared schema/profile columns
|
||||||
|
OK oracle: zero schema-column disagreements with the pinned checker
|
||||||
|
OK oracle: strict-only profile refusals are counted and asserted
|
||||||
|
OK demo: permitted read preview exits 0 (exit 0)
|
||||||
|
OK demo: permitted file.change preview exits 0 (exit 0)
|
||||||
|
OK demo: assignment.change proposal is unresolved (exit 3) (exit 3)
|
||||||
|
OK demo: revoked registration is refused (exit 3) (exit 3)
|
||||||
|
OK demo: message is not authority (exit 3) (exit 3)
|
||||||
|
OK usage: no arguments exits 2 (exit 2)
|
||||||
|
OK io: missing file exits 4 (exit 4)
|
||||||
|
OK io: directory exits 4 (exit 4)
|
||||||
|
OK io: symlink exits 4 (O_NOFOLLOW) (exit 4)
|
||||||
|
OK bound: oversize fixture exits 2 (exit 2)
|
||||||
|
OK profile: one final LF in a typed selection id is refused before admission (exit 2) (exit 2)
|
||||||
|
OK profile: two final LFs fail the schema pattern itself (exit 2) (exit 2)
|
||||||
|
OK profile: escaped newlines in free-form text stay allowed (exit 0) (exit 0)
|
||||||
|
OK profile refusal is invalid-request/profile-pattern-mismatch with selection and operation withheld, value not echoed
|
||||||
|
OK text output starts with the disclaimer
|
||||||
|
OK json output is valid JSON with result allowed and exactly the charter §7 fields
|
||||||
|
OK json golden matches byte-for-byte
|
||||||
|
OK sandboxed bundle run (env -i, PATH=/nonexistent) produced the unresolved proposal
|
||||||
|
OK sandbox inventory (path/type/size/mode/uid/gid/inode/mtime/sha256) unchanged by runs
|
||||||
|
OK canary never printed (bundle run and credential-file run)
|
||||||
|
OK a non-bundle JSON file is refused at the shape gate, not read into output
|
||||||
|
OK no field of the non-bundle file is echoed
|
||||||
|
|
||||||
|
selftest: 44 passed, 0 failed
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
OK args: exit 2, target-branch
|
||||||
|
OK args: exit 2, target-branch
|
||||||
|
OK args: exit 4
|
||||||
|
OK args: exit 4
|
||||||
|
OK args: exit 4
|
||||||
|
OK --base next refuses before the config is read (got 2)
|
||||||
|
OK a missing system config exits 3 (got 3)
|
||||||
|
OK nobus: exit 3
|
||||||
|
OK schema-table: exit 2, bus-schema
|
||||||
|
OK schema-meta: exit 2, bus-schema
|
||||||
|
OK openBus opens the database read-only
|
||||||
|
OK other-business: exit 2, decision-not-found
|
||||||
|
OK no-raise: exit 2, decision-not-found
|
||||||
|
OK not-a-merge: exit 2, not-a-merge
|
||||||
|
OK open: exit 2, not-resolved
|
||||||
|
OK withdrawn: exit 2, not-resolved
|
||||||
|
OK by-agent: exit 2, not-human
|
||||||
|
OK via-webui: exit 2, not-human
|
||||||
|
OK no-answer: exit 2, not-human
|
||||||
|
OK answer-role: exit 2, not-human
|
||||||
|
OK answer-run: exit 2, not-human
|
||||||
|
OK answer-choice: exit 2, not-human
|
||||||
|
OK two-answers: exit 2, not-human
|
||||||
|
OK chose-no: exit 2, not-merge-option
|
||||||
|
OK two-refs: exit 2, work-ref
|
||||||
|
OK bad-ref: exit 2, work-ref
|
||||||
|
OK task-ref-disagrees: exit 2, work-ref
|
||||||
|
OK raise-task-disagrees: exit 2, work-ref
|
||||||
|
OK target-main: exit 2, target-branch
|
||||||
|
OK superseded-question: exit 2, superseded
|
||||||
|
OK superseded-task: exit 2, superseded
|
||||||
|
OK superseded-by: exit 2, superseded
|
||||||
|
OK no-verdict: exit 2, no-verdict
|
||||||
|
OK changes-later: exit 2, not-approved
|
||||||
|
OK short-commit: exit 2, not-approved
|
||||||
|
OK wrong-task-body: exit 2, not-approved
|
||||||
|
OK args: exit 2, decision-not-found
|
||||||
|
OK earlier-merge: exit 0
|
||||||
|
OK ref-moved: exit 2, ref-moved
|
||||||
|
OK root-top: exit 2, root-file
|
||||||
|
OK root-newdir: exit 2, root-file
|
||||||
|
OK root-src: exit 2, root-file
|
||||||
|
OK unrelated: exit 2, base-conflict
|
||||||
|
OK empty: exit 2, base-conflict
|
||||||
|
OK an empty reviewed diff says so
|
||||||
|
OK dirty-changed: exit 2, checkout-dirty
|
||||||
|
OK dirty-staged: exit 2, checkout-dirty
|
||||||
|
OK dirty-untracked: exit 2, checkout-dirty
|
||||||
|
OK conflict: exit 2, base-conflict
|
||||||
|
OK a refusal after the worktree is added leaves no worktree or scratch
|
||||||
|
OK cleanup looks for the worktree's Docker network
|
||||||
|
OK dirty-during: exit 2, checkout-dirty
|
||||||
|
OK a reviewed path dirtied during the gate moves no ref
|
||||||
|
OK drift: exit 2, patch-drift
|
||||||
|
OK patch-drift leaves no worktree or scratch
|
||||||
|
OK gate-pkg: exit 2, gate-failed
|
||||||
|
OK gate-failed names the failing step's log, and it exists
|
||||||
|
OK gate-failed leaves no worktree or scratch
|
||||||
|
OK gate-script: exit 2, gate-failed
|
||||||
|
OK a failing scripts/test-*.sh fails the gate
|
||||||
|
OK a failed gate moves no ref
|
||||||
|
OK nomods: exit 4
|
||||||
|
OK a target without node_modules leaves no worktree or scratch
|
||||||
|
OK moved: exit 2, base-moved
|
||||||
|
OK base-moved keeps the base where it moved to
|
||||||
|
OK dry: exit 0
|
||||||
|
OK --dry-run writes no ref
|
||||||
|
OK --dry-run prints the commit with --subject and --attribution
|
||||||
|
OK --dry-run runs the gate
|
||||||
|
OK --dry-run leaves no worktree or scratch
|
||||||
|
OK land: exit 0
|
||||||
|
OK the landing is one commit on the old base
|
||||||
|
OK its diff is the reviewed diff by patch-id
|
||||||
|
OK its tree is the dry run's
|
||||||
|
OK the message has the option's subject, the citations and the attribution last
|
||||||
|
OK it prints the line for the PM
|
||||||
|
OK the checked-out base has the reviewed paths and keeps the unrelated edit
|
||||||
|
OK only refs/heads/refactor exists in the target
|
||||||
|
OK the work ref is unchanged
|
||||||
|
OK the bus database is unchanged
|
||||||
|
OK the gate ran each package suite but queue, and each scripts/test-*.sh
|
||||||
|
OK the landing leaves no worktree or scratch
|
||||||
|
OK the target's node_modules is still there, with its contents
|
||||||
|
OK the worktree's Docker network is removed
|
||||||
|
---
|
||||||
|
land-work selftests: 84 passed, 0 failed
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
toolchain: node v26.8.1, git version 2.55.0
|
||||||
|
|
||||||
|
OK syntax: packages/queue/src/cli.mjs
|
||||||
|
OK syntax: packages/queue/src/errors.mjs
|
||||||
|
OK syntax: packages/queue/src/io.mjs
|
||||||
|
OK syntax: packages/queue/src/lock.mjs
|
||||||
|
OK syntax: packages/queue/src/queue.mjs
|
||||||
|
OK syntax: packages/queue/src/review.mjs
|
||||||
|
OK syntax: packages/queue/src/store.mjs
|
||||||
|
OK syntax: packages/queue/tests/commit.test.mjs
|
||||||
|
OK syntax: packages/queue/tests/data.test.mjs
|
||||||
|
OK syntax: packages/queue/tests/dispatch.test.mjs
|
||||||
|
OK syntax: packages/queue/tests/gate-owner.test.mjs
|
||||||
|
OK syntax: packages/queue/tests/helpers.mjs
|
||||||
|
OK syntax: packages/queue/tests/lock.test.mjs
|
||||||
|
OK syntax: packages/queue/tests/migration.test.mjs
|
||||||
|
OK syntax: packages/queue/tests/review.test.mjs
|
||||||
|
OK syntax: packages/queue/tests/store.test.mjs
|
||||||
|
OK syntax: packages/queue/tests/write.test.mjs
|
||||||
|
OK syntax: packages/queue/tests/fixtures/fake-gitea.mjs
|
||||||
|
OK syntax: packages/queue/tests/fixtures/kill-at.mjs
|
||||||
|
OK syntax: packages/queue/tests/fixtures/lock-child.mjs
|
||||||
|
OK syntax: packages/queue/tests/fixtures/mosaic-pre-a2.sh
|
||||||
|
OK syntax: scripts/queue-commit.sh
|
||||||
|
OK syntax: scripts/git-hooks/pre-commit
|
||||||
|
OK syntax: scripts/mosaic
|
||||||
|
OK queue-commit.sh, the guard and scripts/mosaic are executable
|
||||||
|
OK packages/queue declares no dependencies
|
||||||
|
ℹ tests 156
|
||||||
|
ℹ pass 156
|
||||||
|
ℹ fail 0
|
||||||
|
OK node --test packages/queue/tests/
|
||||||
|
OK scripts/mosaic queue help
|
||||||
|
skip queue verify and render --check: this checkout (/mnt/storage/src/mosaic-stack-rocko-108) is not the queue's canonical root (/mnt/storage/src/mosaic-stack)
|
||||||
|
|
||||||
|
queue suite: 28 passed, 0 failed
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
OK valid RELEASE resolves (exit 0)
|
||||||
|
OK invalid RELEASE exits 1 (exit 1)
|
||||||
|
OK missing RELEASE exits 1 (exit 1)
|
||||||
|
OK valid RELEASE leaves image tag consistent with version
|
||||||
|
skip state-machine cases (docker daemon unavailable)
|
||||||
|
|
||||||
|
selftest: 4 passed, 0 failed
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
OK valid task validates (exit 0)
|
||||||
|
OK unknown task key exits 2 (exit 2)
|
||||||
|
OK unsupported taskVersion exits 2 (exit 2)
|
||||||
|
OK invalid task id exits 2 (exit 2)
|
||||||
|
OK empty prompt exits 2 (exit 2)
|
||||||
|
OK NUL in expectExact exits 2 (exit 2)
|
||||||
|
OK out-of-range timeout exits 2 (exit 2)
|
||||||
|
OK missing mission file exits 4 (exit 4)
|
||||||
|
OK task with valid mission validates (exit 0)
|
||||||
|
OK invalid mission exits 2 (exit 2)
|
||||||
|
OK validate missing task exits 4 (exit 4)
|
||||||
|
OK validation does not modify the task file
|
||||||
|
OK prune dry-run exits 0 (exit 0)
|
||||||
|
OK dry-run deleted nothing
|
||||||
|
OK prune --keep=2 --yes removes oldest (exit 0)
|
||||||
|
OK kept exactly 2 newest runs
|
||||||
|
OK newest run kept, oldest pruned
|
||||||
|
OK append-only receipt written (3 entries)
|
||||||
|
OK sessions/workspaces untouched by prune
|
||||||
|
OK prune with invalid keep exits 4 (exit 4)
|
||||||
|
skip adapter seam cases (docker daemon unavailable)
|
||||||
|
skip workspace/capability cases (docker daemon unavailable)
|
||||||
|
skip live task cases (docker unavailable)
|
||||||
|
OK onboard without name exits 4 (non-interactive) (exit 4)
|
||||||
|
OK onboard --name renders profile (exit 0)
|
||||||
|
OK profile written
|
||||||
|
OK canon structure: required filled, optional placeholdered
|
||||||
|
OK canon sections present
|
||||||
|
skip live recall pair: user recall run, recalled user name (docker daemon unavailable)
|
||||||
|
OK no agent identity on headless run
|
||||||
|
|
||||||
|
selftest: 26 passed, 0 failed
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
✔ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (384.189666ms)
|
||||||
|
ℹ tests 1
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 1
|
||||||
|
ℹ fail 0
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 433.222778
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
✔ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (519.268069ms)
|
||||||
|
✔ inherited mosaic-.service.d override refuses without changing the unit (157.551223ms)
|
||||||
|
✔ inherited service.d override refuses without changing the unit (155.66251ms)
|
||||||
|
✔ inherited drop-in unreadable directory or file refuses before writing (135.472565ms)
|
||||||
|
ℹ tests 4
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 4
|
||||||
|
ℹ fail 0
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 1017.932833
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"@google/genai": {
|
||||||
|
"version": "1.52.0",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"lifecycle": {
|
||||||
|
"preinstall": "echo 'preinstall: no-op'"
|
||||||
|
},
|
||||||
|
"installedPackageJsonSha256": "ec761756421ea5502c23dbebfb4bc2b74c3ff842597199f2f330afc49cbdedc7",
|
||||||
|
"externalBundleImports": [],
|
||||||
|
"copiedSourceMentions": []
|
||||||
|
},
|
||||||
|
"esbuild": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"lifecycle": {
|
||||||
|
"postinstall": "node install.js"
|
||||||
|
},
|
||||||
|
"installedPackageJsonSha256": "d55d1d19fcc5b6079e4a71dd4111340c79c682bc36835ac7058a0c364c7db58a",
|
||||||
|
"externalBundleImports": [],
|
||||||
|
"copiedSourceMentions": []
|
||||||
|
},
|
||||||
|
"protobufjs": {
|
||||||
|
"version": "7.6.6",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"lifecycle": {
|
||||||
|
"postinstall": "node scripts/postinstall"
|
||||||
|
},
|
||||||
|
"installedPackageJsonSha256": "0e56b70de03bffc143e74311b42ae22b557370a4a1f4b5066568fbc77857639a",
|
||||||
|
"externalBundleImports": [],
|
||||||
|
"copiedSourceMentions": []
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
✔ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (371.608739ms)
|
||||||
|
ℹ tests 1
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 1
|
||||||
|
ℹ fail 0
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 423.313405
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
✖ inherited drop-in unreadable directory or file refuses before writing (176.202383ms)
|
||||||
|
ℹ tests 1
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 0
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 226.195254
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/cli/tests/stack-copy.test.mjs:206:1
|
||||||
|
✖ inherited drop-in unreadable directory or file refuses before writing (176.202383ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||||
|
|
||||||
|
0 !== 1
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-108/packages/cli/tests/stack-copy.test.mjs:209:83)
|
||||||
|
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||||
|
at Test.run (node:internal/test_runner/test:1402:25)
|
||||||
|
at Test.start (node:internal/test_runner/test:1262:17)
|
||||||
|
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: 0,
|
||||||
|
expected: 1,
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
✖ inherited drop-in unreadable directory or file refuses before writing (153.010377ms)
|
||||||
|
ℹ tests 1
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 0
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 207.505872
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/cli/tests/stack-copy.test.mjs:206:1
|
||||||
|
✖ inherited drop-in unreadable directory or file refuses before writing (153.010377ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||||
|
|
||||||
|
0 !== 1
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-108/packages/cli/tests/stack-copy.test.mjs:211:86)
|
||||||
|
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||||
|
at Test.run (node:internal/test_runner/test:1402:25)
|
||||||
|
at Test.start (node:internal/test_runner/test:1262:17)
|
||||||
|
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: 0,
|
||||||
|
expected: 1,
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
✖ inherited service.d override refuses without changing the unit (149.469589ms)
|
||||||
|
ℹ tests 1
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 0
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 204.588195
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/cli/tests/stack-copy.test.mjs:193:53
|
||||||
|
✖ inherited service.d override refuses without changing the unit (149.469589ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||||
|
|
||||||
|
0 !== 1
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-108/packages/cli/tests/stack-copy.test.mjs:201:10)
|
||||||
|
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||||
|
at Test.run (node:internal/test_runner/test:1402:25)
|
||||||
|
at Test.start (node:internal/test_runner/test:1262:17)
|
||||||
|
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: 0,
|
||||||
|
expected: 1,
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
✖ inherited mosaic-.service.d override refuses without changing the unit (157.223428ms)
|
||||||
|
ℹ tests 1
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 0
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 207.691119
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/cli/tests/stack-copy.test.mjs:193:53
|
||||||
|
✖ inherited mosaic-.service.d override refuses without changing the unit (157.223428ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||||
|
|
||||||
|
0 !== 1
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-108/packages/cli/tests/stack-copy.test.mjs:201:10)
|
||||||
|
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||||
|
at Test.run (node:internal/test_runner/test:1402:25)
|
||||||
|
at Test.start (node:internal/test_runner/test:1262:17)
|
||||||
|
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: 0,
|
||||||
|
expected: 1,
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
✖ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (332.205475ms)
|
||||||
|
ℹ tests 1
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 0
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 382.931859
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/cli/tests/stack-copy.test.mjs:43:1
|
||||||
|
✖ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (332.205475ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||||
|
+ actual - expected
|
||||||
|
|
||||||
|
+ '# CLI copy unspecified: /mnt/storage/scratch/tmp/stack-copy-UZgQWO/copies/9a8600610d3b67a76bc0831530b76bcef2184c55'
|
||||||
|
- '# CLI runs from pinned copy: /mnt/storage/scratch/tmp/stack-copy-UZgQWO/copies/9a8600610d3b67a76bc0831530b76bcef2184c55'
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-108/packages/cli/tests/stack-copy.test.mjs:51:9)
|
||||||
|
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||||
|
at Test.run (node:internal/test_runner/test:1402:25)
|
||||||
|
at Test.start (node:internal/test_runner/test:1262:17)
|
||||||
|
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: '# CLI copy unspecified: /mnt/storage/scratch/tmp/stack-copy-UZgQWO/copies/9a8600610d3b67a76bc0831530b76bcef2184c55',
|
||||||
|
expected: '# CLI runs from pinned copy: /mnt/storage/scratch/tmp/stack-copy-UZgQWO/copies/9a8600610d3b67a76bc0831530b76bcef2184c55',
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
✖ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (331.301415ms)
|
||||||
|
ℹ tests 1
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 0
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 386.556311
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/cli/tests/stack-copy.test.mjs:43:1
|
||||||
|
✖ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (331.301415ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||||
|
+ actual - expected
|
||||||
|
|
||||||
|
+ '# Lease explanation omitted.'
|
||||||
|
- '# The Q81 lease probe still answers at mosaic-old.'
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-108/packages/cli/tests/stack-copy.test.mjs:52:9)
|
||||||
|
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||||
|
at Test.run (node:internal/test_runner/test:1402:25)
|
||||||
|
at Test.start (node:internal/test_runner/test:1262:17)
|
||||||
|
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: '# Lease explanation omitted.',
|
||||||
|
expected: '# The Q81 lease probe still answers at mosaic-old.',
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "miss-prefix",
|
||||||
|
"exit": 1,
|
||||||
|
"status": "killed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "miss-all-services",
|
||||||
|
"exit": 1,
|
||||||
|
"status": "killed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ignore-unreadable-directory",
|
||||||
|
"exit": 1,
|
||||||
|
"status": "killed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ignore-unreadable-file",
|
||||||
|
"exit": 1,
|
||||||
|
"status": "killed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "omit-copy-comment",
|
||||||
|
"exit": 1,
|
||||||
|
"status": "killed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "omit-lease-comment",
|
||||||
|
"exit": 1,
|
||||||
|
"status": "killed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "accept-foreign-check-wrapper",
|
||||||
|
"exit": 0,
|
||||||
|
"status": "survived"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
✖ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (370.564265ms)
|
||||||
|
ℹ tests 1
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 0
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 423.590927
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/cli/tests/stack-copy.test.mjs:43:1
|
||||||
|
✖ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (370.564265ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||||
|
|
||||||
|
0 !== 1
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-108/packages/cli/tests/stack-copy.test.mjs:65:9)
|
||||||
|
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||||
|
at Test.run (node:internal/test_runner/test:1402:25)
|
||||||
|
at Test.start (node:internal/test_runner/test:1262:17)
|
||||||
|
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: 0,
|
||||||
|
expected: 1,
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
✖ inherited drop-in unreadable directory or file refuses before writing (149.650683ms)
|
||||||
|
ℹ tests 1
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 0
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 201.468523
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/cli/tests/stack-copy.test.mjs:206:1
|
||||||
|
✖ inherited drop-in unreadable directory or file refuses before writing (149.650683ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||||
|
|
||||||
|
0 !== 1
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-108/packages/cli/tests/stack-copy.test.mjs:209:83)
|
||||||
|
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||||
|
at Test.run (node:internal/test_runner/test:1402:25)
|
||||||
|
at Test.start (node:internal/test_runner/test:1262:17)
|
||||||
|
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: 0,
|
||||||
|
expected: 1,
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
✖ inherited drop-in unreadable directory or file refuses before writing (157.344125ms)
|
||||||
|
ℹ tests 1
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 0
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 206.277407
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/cli/tests/stack-copy.test.mjs:206:1
|
||||||
|
✖ inherited drop-in unreadable directory or file refuses before writing (157.344125ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||||
|
|
||||||
|
0 !== 1
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-108/packages/cli/tests/stack-copy.test.mjs:211:86)
|
||||||
|
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||||
|
at Test.run (node:internal/test_runner/test:1402:25)
|
||||||
|
at Test.start (node:internal/test_runner/test:1262:17)
|
||||||
|
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: 0,
|
||||||
|
expected: 1,
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
✖ inherited service.d override refuses without changing the unit (147.698195ms)
|
||||||
|
ℹ tests 1
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 0
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 202.087926
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/cli/tests/stack-copy.test.mjs:193:53
|
||||||
|
✖ inherited service.d override refuses without changing the unit (147.698195ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||||
|
|
||||||
|
0 !== 1
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-108/packages/cli/tests/stack-copy.test.mjs:201:10)
|
||||||
|
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||||
|
at Test.run (node:internal/test_runner/test:1402:25)
|
||||||
|
at Test.start (node:internal/test_runner/test:1262:17)
|
||||||
|
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: 0,
|
||||||
|
expected: 1,
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
✖ inherited mosaic-.service.d override refuses without changing the unit (150.701816ms)
|
||||||
|
ℹ tests 1
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 0
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 200.884936
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/cli/tests/stack-copy.test.mjs:193:53
|
||||||
|
✖ inherited mosaic-.service.d override refuses without changing the unit (150.701816ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||||
|
|
||||||
|
0 !== 1
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-108/packages/cli/tests/stack-copy.test.mjs:201:10)
|
||||||
|
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||||
|
at Test.run (node:internal/test_runner/test:1402:25)
|
||||||
|
at Test.start (node:internal/test_runner/test:1262:17)
|
||||||
|
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: 0,
|
||||||
|
expected: 1,
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
✖ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (329.834503ms)
|
||||||
|
ℹ tests 1
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 0
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 386.342447
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/cli/tests/stack-copy.test.mjs:43:1
|
||||||
|
✖ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (329.834503ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||||
|
+ actual - expected
|
||||||
|
|
||||||
|
+ '# CLI copy unspecified: /mnt/storage/scratch/tmp/stack-copy-14DZ3i/copies/68b0dcbc6b74877aa3d7f4273f25c60c82a2fed0'
|
||||||
|
- '# CLI runs from pinned copy: /mnt/storage/scratch/tmp/stack-copy-14DZ3i/copies/68b0dcbc6b74877aa3d7f4273f25c60c82a2fed0'
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-108/packages/cli/tests/stack-copy.test.mjs:51:9)
|
||||||
|
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||||
|
at Test.run (node:internal/test_runner/test:1402:25)
|
||||||
|
at Test.start (node:internal/test_runner/test:1262:17)
|
||||||
|
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: '# CLI copy unspecified: /mnt/storage/scratch/tmp/stack-copy-14DZ3i/copies/68b0dcbc6b74877aa3d7f4273f25c60c82a2fed0',
|
||||||
|
expected: '# CLI runs from pinned copy: /mnt/storage/scratch/tmp/stack-copy-14DZ3i/copies/68b0dcbc6b74877aa3d7f4273f25c60c82a2fed0',
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
✖ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (336.722572ms)
|
||||||
|
ℹ tests 1
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 0
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 387.262429
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/cli/tests/stack-copy.test.mjs:43:1
|
||||||
|
✖ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (336.722572ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||||
|
+ actual - expected
|
||||||
|
|
||||||
|
+ '# Lease explanation omitted.'
|
||||||
|
- '# The Q81 lease probe still answers at mosaic-old.'
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-108/packages/cli/tests/stack-copy.test.mjs:52:9)
|
||||||
|
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||||
|
at Test.run (node:internal/test_runner/test:1402:25)
|
||||||
|
at Test.start (node:internal/test_runner/test:1262:17)
|
||||||
|
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: '# Lease explanation omitted.',
|
||||||
|
expected: '# The Q81 lease probe still answers at mosaic-old.',
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "miss-prefix",
|
||||||
|
"exit": 1,
|
||||||
|
"status": "killed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "miss-all-services",
|
||||||
|
"exit": 1,
|
||||||
|
"status": "killed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ignore-unreadable-directory",
|
||||||
|
"exit": 1,
|
||||||
|
"status": "killed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ignore-unreadable-file",
|
||||||
|
"exit": 1,
|
||||||
|
"status": "killed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "omit-copy-comment",
|
||||||
|
"exit": 1,
|
||||||
|
"status": "killed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "omit-lease-comment",
|
||||||
|
"exit": 1,
|
||||||
|
"status": "killed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "accept-foreign-check-wrapper",
|
||||||
|
"exit": 1,
|
||||||
|
"status": "killed"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Named network absent or Docker unavailable; gate used a nonexistent socket and created no Docker network.
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
[]
|
||||||
|
Error response from daemon: network mosaic-stack-rocko-108_default not found
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
busy: []
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
✖ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (338.641838ms)
|
||||||
|
✖ inherited mosaic-.service.d override refuses without changing the unit (163.843449ms)
|
||||||
|
✖ inherited service.d override refuses without changing the unit (160.748391ms)
|
||||||
|
✖ inherited drop-in unreadable directory or file refuses before writing (156.421459ms)
|
||||||
|
ℹ tests 4
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 0
|
||||||
|
ℹ fail 4
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 874.645626
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/cli/tests/stack-copy.test.mjs:43:1
|
||||||
|
✖ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (338.641838ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||||
|
+ actual - expected
|
||||||
|
|
||||||
|
+ '[ "${1:-}" = __lease-capability ] && exec "/mnt/storage/scratch/tmp/stack-copy-CqFcXA/bin/mosaic-old" "$@"'
|
||||||
|
- '# CLI runs from pinned copy: /mnt/storage/scratch/tmp/stack-copy-CqFcXA/copies/532780c22bd934403daeb69912a99e3818815e56'
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-108/packages/cli/tests/stack-copy.test.mjs:51:9)
|
||||||
|
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||||
|
at Test.run (node:internal/test_runner/test:1402:25)
|
||||||
|
at Test.start (node:internal/test_runner/test:1262:17)
|
||||||
|
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: '[ "${1:-}" = __lease-capability ] && exec "/mnt/storage/scratch/tmp/stack-copy-CqFcXA/bin/mosaic-old" "$@"',
|
||||||
|
expected: '# CLI runs from pinned copy: /mnt/storage/scratch/tmp/stack-copy-CqFcXA/copies/532780c22bd934403daeb69912a99e3818815e56',
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
|
|
||||||
|
test at packages/cli/tests/stack-copy.test.mjs:191:53
|
||||||
|
✖ inherited mosaic-.service.d override refuses without changing the unit (163.843449ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||||
|
|
||||||
|
0 !== 1
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-108/packages/cli/tests/stack-copy.test.mjs:199:10)
|
||||||
|
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||||
|
at Test.run (node:internal/test_runner/test:1402:25)
|
||||||
|
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||||
|
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||||
|
at node:internal/test_runner/test:1305:31
|
||||||
|
at node:internal/process/task_queues:151:7
|
||||||
|
at AsyncResource.runInAsyncScope (node:async_hooks:226:14)
|
||||||
|
at AsyncResource.runMicrotask (node:internal/process/task_queues:148:8) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: 0,
|
||||||
|
expected: 1,
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
|
|
||||||
|
test at packages/cli/tests/stack-copy.test.mjs:191:53
|
||||||
|
✖ inherited service.d override refuses without changing the unit (160.748391ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||||
|
|
||||||
|
0 !== 1
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-108/packages/cli/tests/stack-copy.test.mjs:199:10)
|
||||||
|
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||||
|
at Test.run (node:internal/test_runner/test:1402:25)
|
||||||
|
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||||
|
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||||
|
at Test.run (node:internal/test_runner/test:1467:12)
|
||||||
|
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: 0,
|
||||||
|
expected: 1,
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
|
|
||||||
|
test at packages/cli/tests/stack-copy.test.mjs:204:1
|
||||||
|
✖ inherited drop-in unreadable directory or file refuses before writing (156.421459ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||||
|
|
||||||
|
0 !== 1
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-108/packages/cli/tests/stack-copy.test.mjs:207:83)
|
||||||
|
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||||
|
at Test.run (node:internal/test_runner/test:1402:25)
|
||||||
|
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||||
|
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||||
|
at Test.run (node:internal/test_runner/test:1467:12)
|
||||||
|
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: 0,
|
||||||
|
expected: 1,
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"suite": "node-cli",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:08:16.669752+00:00",
|
||||||
|
"ended": "2026-10-14T20:08:29.916793+00:00",
|
||||||
|
"summaries": [
|
||||||
|
"\u2714 a runner killed from the host ends its launch as killed, not failed (244.156ms)",
|
||||||
|
"\u2714 a failed DM is journaled, backs off, and is retried until it lands (19.49567ms)",
|
||||||
|
"\u2714 bus unit copy/pm pins, install refuses all busy states and failed reads, drop-in refusal (482.787297ms)",
|
||||||
|
"\u2139 tests 187",
|
||||||
|
"\u2139 pass 187",
|
||||||
|
"\u2139 fail 0",
|
||||||
|
"\u2139 cancelled 0",
|
||||||
|
"\u2139 skipped 0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-auth",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:08:29.917023+00:00",
|
||||||
|
"ended": "2026-10-14T20:08:30.532205+00:00",
|
||||||
|
"summaries": [
|
||||||
|
"selftest: 15 passed, 0 failed"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-conductor",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:08:30.532452+00:00",
|
||||||
|
"ended": "2026-10-14T20:08:35.257973+00:00",
|
||||||
|
"summaries": [
|
||||||
|
"OK failed run refused (exit 1)",
|
||||||
|
"OK failed run: target untouched",
|
||||||
|
"selftest: 17 passed, 0 failed"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-config",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:08:35.258217+00:00",
|
||||||
|
"ended": "2026-10-14T20:08:36.927811+00:00",
|
||||||
|
"summaries": [
|
||||||
|
"OK failed validation modified nothing",
|
||||||
|
"selftest: 24 passed, 0 failed"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-discord",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:08:36.928073+00:00",
|
||||||
|
"ended": "2026-10-14T20:08:43.506603+00:00",
|
||||||
|
"summaries": [
|
||||||
|
"OK node --test packages/discord/tests/ (\u2139 pass 178)",
|
||||||
|
"discord suite: 66 passed, 0 failed"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-extension-package",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:08:43.506874+00:00",
|
||||||
|
"ended": "2026-10-14T20:08:44.823470+00:00",
|
||||||
|
"summaries": [
|
||||||
|
"extension package selftest: 18 passed, 0 failed"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-foundation",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:08:44.823736+00:00",
|
||||||
|
"ended": "2026-10-14T20:09:21.468582+00:00",
|
||||||
|
"summaries": [
|
||||||
|
"OK node --test scripts/foundation/ (\u2139 pass 80)",
|
||||||
|
"selftest: 44 passed, 0 failed"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-land-work",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:09:21.468850+00:00",
|
||||||
|
"ended": "2026-10-14T20:09:29.950720+00:00",
|
||||||
|
"summaries": [
|
||||||
|
"OK gate-pkg: exit 2, gate-failed",
|
||||||
|
"OK gate-failed names the failing step's log, and it exists",
|
||||||
|
"OK gate-failed leaves no worktree or scratch",
|
||||||
|
"OK gate-script: exit 2, gate-failed",
|
||||||
|
"OK a failed gate moves no ref",
|
||||||
|
"land-work selftests: 84 passed, 0 failed"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-queue",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:09:29.951035+00:00",
|
||||||
|
"ended": "2026-10-14T20:09:50.306428+00:00",
|
||||||
|
"summaries": [
|
||||||
|
"\u2139 tests 156",
|
||||||
|
"\u2139 pass 156",
|
||||||
|
"\u2139 fail 0",
|
||||||
|
"skip queue verify and render --check: this checkout (/mnt/storage/src/mosaic-stack-rocko-108) is not the queue's canonical root (/mnt/storage/src/mosaic-stack)",
|
||||||
|
"queue suite: 28 passed, 0 failed"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-release",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:09:50.306714+00:00",
|
||||||
|
"ended": "2026-10-14T20:09:50.420924+00:00",
|
||||||
|
"summaries": [
|
||||||
|
"skip state-machine cases (docker daemon unavailable)",
|
||||||
|
"selftest: 4 passed, 0 failed"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"suite": "test-task",
|
||||||
|
"exit": 0,
|
||||||
|
"began": "2026-10-14T20:09:50.421163+00:00",
|
||||||
|
"ended": "2026-10-14T20:09:52.390220+00:00",
|
||||||
|
"summaries": [
|
||||||
|
"skip adapter seam cases (docker daemon unavailable)",
|
||||||
|
"skip workspace/capability cases (docker daemon unavailable)",
|
||||||
|
"skip live task cases (docker unavailable)",
|
||||||
|
"skip live recall pair: user recall run, recalled user name (docker daemon unavailable)",
|
||||||
|
"selftest: 26 passed, 0 failed"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
5e8e8555b75b9f8cde109bf4d4618ed32635502c7e4c0a803a1ff3839f8df07c BUILD.md
|
||||||
|
585c050b0dbb1141063cb8b0c36781a33f78362e97be677750cac5858156de87 audit-install-scripts.py
|
||||||
|
003cabffa810b8cc58b269e7ddb2049ac1016afaa3763118e500b0d0417bc19b base.txt
|
||||||
|
e8c49c1f8781520248a1d081ad33d5b9bfb5ee100c8bd457fcbf0a2436a8bf17 build.patch
|
||||||
|
19ef7133db592787c24fa473357687a5741ccd7823627b970624c930a7611dbc candidate-manifest.sha256
|
||||||
|
a25433983b7945d18aa0717d9323a9593c50d3ea95fa73c886583e06e75d48c9 files.txt
|
||||||
|
1eb6d322c6864f21d2194b257a7d7f97e0a55761bf476b80cf3e3685b40fce94 gate.py
|
||||||
|
93c47f6773497c180b6afc5479bcd0a4e1b57957400d785793a55027413c8cc8 mutants.py
|
||||||
|
ffa47b17a6b98aadf890737dea27518afb3726ae0f09193ec70ee548c2ebe3af out/final-verification.txt
|
||||||
|
64a7b7656cac69dad18383be6eb04192244bc9b53132316cd3c4a495216fe27c out/full/gate-results.json
|
||||||
|
18a032eb2cab4739954ea172a4a10310c3d5a3f76c8a568100fe44289a932deb out/full/node-cli.txt
|
||||||
|
f91fc95a173339137f981e24fbf630acfde957e32c3cd71e28304532083c6a77 out/full/test-auth.txt
|
||||||
|
e1206366f07f3d9029530dcdcb55c0282d3f052adc60fc7fd51642d5d4ec3600 out/full/test-conductor.txt
|
||||||
|
52d211444489ea729dafc3c9745d4474d9dfd50f41055cbad792424197f04073 out/full/test-config.txt
|
||||||
|
7d5016ded1994048642f8b9ae845e52e8af4a069ba05c056c8f580a4589bacbe out/full/test-discord.txt
|
||||||
|
03501c913499fa5b3c3b9e71d5d60a8a51f71d3336f3cb791ab27e46dac8c15a out/full/test-extension-package.txt
|
||||||
|
83dfaa21c4e4ad941088efab3f69e87ebd2f6bd3cc72ede938e21dc06da8a34f out/full/test-foundation.txt
|
||||||
|
8e2254aa3e1bb9b205ab72c68273d447c0328c9f156ccba2a46f3a0476468b58 out/full/test-land-work.txt
|
||||||
|
37bb16fe964cf2bfa6b6be1a34a0ca92a87b9b51a9e6be047dcd4d9950bb96f7 out/full/test-queue.txt
|
||||||
|
6183e6b9b05edb497e92ffd09a19bba49c6f656c750ecb2acc283021113d1a98 out/full/test-release.txt
|
||||||
|
5dc16a91c36d6ff437e5fbb66764ece758e412f32f74b5a6d0c9cb9cad332f59 out/full/test-task.txt
|
||||||
|
f81b1dbf039fcb9980eab6b5812c28fff5c80bfb37c13ce738682bc03d783ccd out/full-first/gate-results.json
|
||||||
|
edf055e251ecde70ba9651cc759dd2438f02c5dba8b80ea252c1c98a73b9262a out/full-first/node-cli.txt
|
||||||
|
f91fc95a173339137f981e24fbf630acfde957e32c3cd71e28304532083c6a77 out/full-first/test-auth.txt
|
||||||
|
e1206366f07f3d9029530dcdcb55c0282d3f052adc60fc7fd51642d5d4ec3600 out/full-first/test-conductor.txt
|
||||||
|
52d211444489ea729dafc3c9745d4474d9dfd50f41055cbad792424197f04073 out/full-first/test-config.txt
|
||||||
|
7d5016ded1994048642f8b9ae845e52e8af4a069ba05c056c8f580a4589bacbe out/full-first/test-discord.txt
|
||||||
|
61c4e82851afe59369ffb17bdc55e1a077080b8aa81681cc0b0811d445918fb2 out/full-first/test-extension-package.txt
|
||||||
|
83dfaa21c4e4ad941088efab3f69e87ebd2f6bd3cc72ede938e21dc06da8a34f out/full-first/test-foundation.txt
|
||||||
|
8e2254aa3e1bb9b205ab72c68273d447c0328c9f156ccba2a46f3a0476468b58 out/full-first/test-land-work.txt
|
||||||
|
37bb16fe964cf2bfa6b6be1a34a0ca92a87b9b51a9e6be047dcd4d9950bb96f7 out/full-first/test-queue.txt
|
||||||
|
6183e6b9b05edb497e92ffd09a19bba49c6f656c750ecb2acc283021113d1a98 out/full-first/test-release.txt
|
||||||
|
5dc16a91c36d6ff437e5fbb66764ece758e412f32f74b5a6d0c9cb9cad332f59 out/full-first/test-task.txt
|
||||||
|
d151c8be4ba3e351a770c5853a54b197ef08dca1f662cddc4c0acad6e1eeaa52 out/green-isolated-marker.txt
|
||||||
|
42d55b5184fbc5ed95b8d4ff0bf7a3802839a60023308cfabbfc5825c9fef02f out/green.txt
|
||||||
|
c146253914903ad51ba9884201fa32d4606d7aceb49f48cfd084744139915e9d out/install-scripts-audit.json
|
||||||
|
5e07879b690ae4eeaa7df4856a15f9b7cead4cd782c637bc48556c264e09301a out/mutants/accept-foreign-check-wrapper.txt
|
||||||
|
4a9123a9aeb702659a7fe7037008aa6c8b6f1aeaa2ee3f03e3b5e620e1501a50 out/mutants/ignore-unreadable-directory.txt
|
||||||
|
326b0c2744b5865d722c4efdd14ef68c5a5a6d5f5b16d248b90d0ada39d90150 out/mutants/ignore-unreadable-file.txt
|
||||||
|
3e8174e924ab6b6bff1d706ac41b8a918f3e2ace417ef9e1cbedec6755851671 out/mutants/miss-all-services.txt
|
||||||
|
93724848a18905a0270d6239953525d66f60ad71f3804401008f8c1ed8460355 out/mutants/miss-prefix.txt
|
||||||
|
dee162b11afd058f1501eb7d957be1b6f5884528824651c187a6e6757b844275 out/mutants/omit-copy-comment.txt
|
||||||
|
a008d047f2b2e69efd1d8339d2b4c240a4ee5bbb25efe3bd424ac510e7e0a507 out/mutants/omit-lease-comment.txt
|
||||||
|
84d231d180685822733f326e4453ef0ca7ce40c16af6809f487bfbbbc5f6eefd out/mutants/summary.json
|
||||||
|
7fbbbe1b7cbc8af9df31b8bcb2c75a43822f3cbfa4e53ed32fb81b31fbdbab39 out/mutants-first/accept-foreign-check-wrapper.txt
|
||||||
|
d7901da7c6c4f23944c5a34633acc95a5c64d98534be69e34d5bad1bafd18f93 out/mutants-first/ignore-unreadable-directory.txt
|
||||||
|
554ca87470e161b579dc3590c670ef7493167d2a386a5edb91a3c6ed0d30c280 out/mutants-first/ignore-unreadable-file.txt
|
||||||
|
a2a460f462f1091350b9fd6f1bdd543921cf56649534d12520f07382e3a917b6 out/mutants-first/miss-all-services.txt
|
||||||
|
0f6e498da07b1e8b38cfdc6f421f26fe73dfca259b8a1fb31f36e56d281422c5 out/mutants-first/miss-prefix.txt
|
||||||
|
a626b75eaefae7368d7fe2a10611f07f22a0cebfdf6af5cf5df85fa0b1403856 out/mutants-first/omit-copy-comment.txt
|
||||||
|
bed2e0fa233e895c0a1ec23f1b5820f47e3bf45959e0c0e4dceb50107d1abcf8 out/mutants-first/omit-lease-comment.txt
|
||||||
|
ad3e9e23c2239a7e894a236624e23b7091b9c509eaf748ea629aa23f852488ee out/mutants-first/summary.json
|
||||||
|
e9708e31600a4fedf102465e4bdf32a58ca944912088a74cad48819fd140d6ae out/network-clear.txt
|
||||||
|
2b0654a7fadd83483005123095dcd7eb27cc88ec06fab628d937c28a42ba74de out/network-inspect.txt
|
||||||
|
7b1c894bf5ac4017fc38d5d07b725f71fa4f0edd11ff68028ed53b8e6a2263a9 out/process-clear.txt
|
||||||
|
f54aab59de13c531c6ab7fab0a2ac4883c0f6445301871f5f7d2b801203c5a8c out/red.txt
|
||||||
|
2bcaa72f44c6698ec3416b2d65b1fd1c279eff0426a4f5ad97e60897e3fbbb5d out/suite-counts.json
|
||||||
|
6c5dc14fb2f79c16a3910d8e5161f9bfbfbc6826e0c82be0de8b9bb9ed67c0cc process-sweep.py
|
||||||
|
ef911b81f33b3ba1a721047248503ae12c17c44601d371a28acaa2eba81a965c verify.sh
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
"""Inspect only processes under this row's worktree; no unrelated argv/env."""
|
||||||
|
from pathlib import Path
|
||||||
|
import os,sys
|
||||||
|
root='/mnt/storage/src/mosaic-stack-rocko-108';busy=[]
|
||||||
|
for p in Path('/proc').iterdir():
|
||||||
|
if not p.name.isdigit():continue
|
||||||
|
try:
|
||||||
|
cwd=os.readlink(p/'cwd')
|
||||||
|
if cwd==root or cwd.startswith(root+'/'):
|
||||||
|
busy.append((int(p.name),(p/'comm').read_text().strip(),cwd))
|
||||||
|
except OSError:pass
|
||||||
|
print('busy:',busy)
|
||||||
|
sys.exit(bool(busy))
|
||||||
Executable
+10
@@ -0,0 +1,10 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
packet=/mnt/storage/src/mosaic-stack/agents/rocko/work/queue-108/r1
|
||||||
|
[ -z "$(git branch --show-current)" ] || { echo 'detached worktree required' >&2;exit 2; }
|
||||||
|
export DOCKER_HOST=unix:///nonexistent.sock
|
||||||
|
sha256sum -c "$packet/candidate-manifest.sha256"
|
||||||
|
git diff --check
|
||||||
|
python "$packet/gate.py" "${1:?pass absolute gate output directory}"
|
||||||
|
python "$packet/mutants.py" "${2:?pass separate absolute mutant output directory}"
|
||||||
|
sha256sum -c "$packet/candidate-manifest.sha256"
|
||||||
Reference in New Issue
Block a user