docs(queue-48): darkwing round 1 review, approve
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
3107d6a48dbbd7e269bd2b65cdab47f32a7f66f9394b99d5a6c806ec804131ab agents/dewey/work/queue-48/evidence.md
|
||||
ed4c1d1bdbbc0f4e087aca97a6ce47f0987dffa724c838c4e084b0c1881705ae packages/queue/tests/commit.test.mjs
|
||||
8b08f75f1350ca14fe4e3879c3f7df4043b1d1dcf6a0a1a9f403193ee0f94125 scripts/test-task.sh
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
# Row 48 gate: queue node suite, then every scripts/test-*.sh with Docker unreachable.
|
||||
export TMPDIR=~/darkwing-scratch/r48a/tmp DOCKER_HOST=unix:///nonexistent.sock
|
||||
cd ~/darkwing-scratch/r48a/wt
|
||||
O=~/darkwing-scratch/r48a/out
|
||||
: > $O/summary.txt
|
||||
echo "start $(date -u +%FT%TZ)" >> $O/summary.txt
|
||||
node --test packages/queue/tests/*.test.mjs > $O/node-queue.txt 2>&1; e=$?
|
||||
echo "node-queue exit=$e $(grep -E '^ℹ (pass|fail)' $O/node-queue.txt | tr '\n' ' ')" >> $O/summary.txt
|
||||
for f in scripts/test-*.sh; do
|
||||
s=$(basename $f .sh)
|
||||
$f > $O/$s.txt 2>&1; e=$?
|
||||
echo "$s exit=$e $(grep -E 'passed, [0-9]+ failed' $O/$s.txt | tail -1)" >> $O/summary.txt
|
||||
done
|
||||
echo "end $(date -u +%FT%TZ)" >> $O/summary.txt
|
||||
echo DONE >> $O/summary.txt
|
||||
@@ -0,0 +1,17 @@
|
||||
diff --git a/packages/queue/tests/commit.test.mjs b/packages/queue/tests/commit.test.mjs
|
||||
index c254dce5..41ee7538 100644
|
||||
--- a/packages/queue/tests/commit.test.mjs
|
||||
+++ b/packages/queue/tests/commit.test.mjs
|
||||
@@ -166,10 +166,10 @@ async function pausedCommit(t, form) {
|
||||
const go = join(r.ctl, "editor-go");
|
||||
const editor = join(r.ctl, "editor.sh");
|
||||
writeFileSync(editor, `#!/bin/sh\n: > ${q(started)}\nwhile [ ! -e ${q(go)} ]; do sleep 0.05; done\necho "ordinary" > "$1"\n`, { mode: 0o755 });
|
||||
- const child = spawn("git", ["-C", r.root, "commit", "-e", "-q", ...form], { env: { ...r.env, GIT_EDITOR: editor }, stdio: ["ignore", "pipe", "pipe"] });
|
||||
+ const child = spawn("sh", ["-c", 'git "$@" 2>"$0"; s=$?; (sleep 0.5; cat "$0" >&2) & exit $s', join(r.ctl, "git-err"), "-C", r.root, "commit", "-e", "-q", ...form], { env: { ...r.env, GIT_EDITOR: editor }, stdio: ["ignore", "pipe", "pipe"] });
|
||||
let childErr = "";
|
||||
child.stderr.on("data", (d) => { childErr += d; });
|
||||
- const exited = new Promise((resolve) => child.on("exit", resolve));
|
||||
+ const exited = new Promise((resolve) => child.on("close", resolve));
|
||||
for (let i = 0; i < 200 && !existsSync(started); i++) sleepMs(50);
|
||||
assert.ok(existsSync(started), "the editor never started");
|
||||
const locked = existsSync(join(r.gitDir, "index.lock"));
|
||||
@@ -0,0 +1,18 @@
|
||||
✔ F1: an ordinary commit after update-ref is refused until step 8; then it commits and the queue stays at C (1411.374746ms)
|
||||
✔ F1: a plain `commit -e` whose guard ran before update-ref fails at its own HEAD update (1612.695499ms)
|
||||
ℹ git commit -e: index.lock free during the editor
|
||||
✔ F1: a `commit -e -- path` whose guard ran before update-ref fails at its own HEAD update (1669.334822ms)
|
||||
ℹ git commit -e -- src.txt: index.lock held during the editor
|
||||
✔ F1: a queue commit landing after H is recorded: step 1 says HEAD moved, not the guard (1485.27192ms)
|
||||
✔ F1: a queue commit landing between the HEAD check and the canary: the failed clean run is reported as HEAD moved (1059.81047ms)
|
||||
✔ F1: a shared-index change during the procedure is not committed (1265.621309ms)
|
||||
✔ F1: a queue path staged after update-ref: step 8 stops and touches nothing (1259.89775ms)
|
||||
✔ F1: a missing or a different hook refuses (870.937246ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 8
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 10712.952509
|
||||
@@ -0,0 +1,13 @@
|
||||
diff --git a/packages/queue/tests/commit.test.mjs b/packages/queue/tests/commit.test.mjs
|
||||
index c254dce5..b101cebc 100644
|
||||
--- a/packages/queue/tests/commit.test.mjs
|
||||
+++ b/packages/queue/tests/commit.test.mjs
|
||||
@@ -166,7 +166,7 @@ async function pausedCommit(t, form) {
|
||||
const go = join(r.ctl, "editor-go");
|
||||
const editor = join(r.ctl, "editor.sh");
|
||||
writeFileSync(editor, `#!/bin/sh\n: > ${q(started)}\nwhile [ ! -e ${q(go)} ]; do sleep 0.05; done\necho "ordinary" > "$1"\n`, { mode: 0o755 });
|
||||
- const child = spawn("git", ["-C", r.root, "commit", "-e", "-q", ...form], { env: { ...r.env, GIT_EDITOR: editor }, stdio: ["ignore", "pipe", "pipe"] });
|
||||
+ const child = spawn("sh", ["-c", 'git "$@" 2>"$0"; s=$?; (sleep 0.5; cat "$0" >&2) & exit $s', join(r.ctl, "git-err"), "-C", r.root, "commit", "-e", "-q", ...form], { env: { ...r.env, GIT_EDITOR: editor }, stdio: ["ignore", "pipe", "pipe"] });
|
||||
let childErr = "";
|
||||
child.stderr.on("data", (d) => { childErr += d; });
|
||||
const exited = new Promise((resolve) => child.on("exit", resolve));
|
||||
@@ -0,0 +1,58 @@
|
||||
✔ F1: an ordinary commit after update-ref is refused until step 8; then it commits and the queue stays at C (1019.923821ms)
|
||||
✖ F1: a plain `commit -e` whose guard ran before update-ref fails at its own HEAD update (987.757774ms)
|
||||
ℹ git commit -e: index.lock free during the editor
|
||||
✖ F1: a `commit -e -- path` whose guard ran before update-ref fails at its own HEAD update (1002.567379ms)
|
||||
ℹ git commit -e -- src.txt: index.lock held during the editor
|
||||
✔ F1: a queue commit landing after H is recorded: step 1 says HEAD moved, not the guard (1435.596039ms)
|
||||
✔ F1: a queue commit landing between the HEAD check and the canary: the failed clean run is reported as HEAD moved (1023.967614ms)
|
||||
✔ F1: a shared-index change during the procedure is not committed (1197.76575ms)
|
||||
✔ F1: a queue path staged after update-ref: step 8 stops and touches nothing (1265.30256ms)
|
||||
✔ F1: a missing or a different hook refuses (1148.064136ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 6
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 9135.584908
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/queue/tests/commit.test.mjs:195:1
|
||||
✖ F1: a plain `commit -e` whose guard ran before update-ref fails at its own HEAD update (987.757774ms)
|
||||
AssertionError [ERR_ASSERTION]: The input did not match the regular expression /cannot lock ref 'HEAD': is at 86e954928bfbe30c3845659fcbc78e6b9a6dd75d but expected 8300cce534f153bba6f53613705e7913099548c1/. Input:
|
||||
|
||||
''
|
||||
|
||||
at pausedCommit (file:///home/jwoltje/darkwing-scratch/r48a/wt2/packages/queue/tests/commit.test.mjs:186:10)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/darkwing-scratch/r48a/wt2/packages/queue/tests/commit.test.mjs:196:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: '',
|
||||
expected: /cannot lock ref 'HEAD': is at 86e954928bfbe30c3845659fcbc78e6b9a6dd75d but expected 8300cce534f153bba6f53613705e7913099548c1/,
|
||||
operator: 'match',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/queue/tests/commit.test.mjs:199:1
|
||||
✖ F1: a `commit -e -- path` whose guard ran before update-ref fails at its own HEAD update (1002.567379ms)
|
||||
AssertionError [ERR_ASSERTION]: The input did not match the regular expression /cannot lock ref 'HEAD': is at e80c11b19ec36f5363799f753548696214e105a7 but expected 53249eecfa65a35d8748e6b1e5b0353649f4b0e6/. Input:
|
||||
|
||||
''
|
||||
|
||||
at pausedCommit (file:///home/jwoltje/darkwing-scratch/r48a/wt2/packages/queue/tests/commit.test.mjs:186:10)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/darkwing-scratch/r48a/wt2/packages/queue/tests/commit.test.mjs:200:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: '',
|
||||
expected: /cannot lock ref 'HEAD': is at e80c11b19ec36f5363799f753548696214e105a7 but expected 53249eecfa65a35d8748e6b1e5b0353649f4b0e6/,
|
||||
operator: 'match',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
# Fake docker for the row 48 review: "info" succeeds, everything else goes to
|
||||
# the real client, which can't reach the daemon (DOCKER_HOST unreachable).
|
||||
if [ "$1" = info ]; then echo "fake docker info"; exit 0; fi
|
||||
exec /usr/bin/docker "$@"
|
||||
@@ -0,0 +1,2 @@
|
||||
packages/queue/tests/commit.test.mjs: OK
|
||||
scripts/test-task.sh: OK
|
||||
@@ -0,0 +1,19 @@
|
||||
# mutate.py <id>: apply one named variant to commit.test.mjs (exact text, must match once). Run from the tree root.
|
||||
import sys
|
||||
F = "packages/queue/tests/commit.test.mjs"
|
||||
SPAWN = 'spawn("git", ["-C", r.root, "commit", "-e", "-q", ...form]'
|
||||
# git exits with its own status at once; a background subshell keeps the
|
||||
# stderr pipe open and writes git's message 0.5 s later.
|
||||
DELAYED = 'spawn("sh", ["-c", \'git "$@" 2>"$0"; s=$?; (sleep 0.5; cat "$0" >&2) & exit $s\', join(r.ctl, "git-err"), "-C", r.root, "commit", "-e", "-q", ...form]'
|
||||
CLOSE = 'child.on("close", resolve)'
|
||||
M = {
|
||||
"delay-close": [(SPAWN, DELAYED)],
|
||||
"delay-exit": [(SPAWN, DELAYED), (CLOSE, 'child.on("exit", resolve)')],
|
||||
}
|
||||
s = open(F).read()
|
||||
for old, new in M[sys.argv[1]]:
|
||||
n = s.count(old)
|
||||
if n != 1: sys.exit(f"{sys.argv[1]}: {n} matches")
|
||||
s = s.replace(old, new)
|
||||
open(F, "w").write(s)
|
||||
print(sys.argv[1], "applied")
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
# Runs after the gate: commit.test variants, then test-task with the fake docker.
|
||||
export TMPDIR=~/darkwing-scratch/r48a/tmp
|
||||
R=~/darkwing-scratch/r48a; M=$R/mut; W=$R/wt2
|
||||
: > $M/summary.txt
|
||||
echo "start $(date -u +%FT%TZ)" >> $M/summary.txt
|
||||
for v in delay-exit delay-close; do
|
||||
(cd $W && git checkout -q -- packages/queue/tests/commit.test.mjs && cp $R/snap/packages/queue/tests/commit.test.mjs packages/queue/tests/ && python3 $M/mutate.py $v && git diff -- packages/queue/tests/commit.test.mjs > $M/$v.diff)
|
||||
(cd $W && node --test --test-name-pattern="F1: a" packages/queue/tests/commit.test.mjs > $M/$v.txt 2>&1); e=$?
|
||||
echo "$v exit=$e $(grep -E '^ℹ (pass|fail)' $M/$v.txt | tr '\n' ' ')" >> $M/summary.txt
|
||||
done
|
||||
(cd $W && cp $R/snap/packages/queue/tests/commit.test.mjs packages/queue/tests/)
|
||||
# The candidate's paused-commit tests, unmodified, ten times in a row.
|
||||
for i in $(seq 1 10); do
|
||||
(cd $W && node --test --test-name-pattern="F1: a" packages/queue/tests/commit.test.mjs > $M/repeat-$i.txt 2>&1); e=$?
|
||||
echo "repeat-$i exit=$e $(grep -E '^ℹ (pass|fail)' $M/repeat-$i.txt | tr '\n' ' ')" >> $M/summary.txt
|
||||
done
|
||||
# test-task with docker info answering yes and the daemon unreachable.
|
||||
(cd $W && DOCKER_HOST=unix:///nonexistent.sock PATH=$R/fakebin:$PATH scripts/test-task.sh > $M/test-task-fakedocker.txt 2>&1); e=$?
|
||||
echo "test-task-fakedocker exit=$e $(grep -E 'passed, [0-9]+ failed' $M/test-task-fakedocker.txt | tail -1)" >> $M/summary.txt
|
||||
(cd $W && sha256sum -c $R/manifest-mine.sha256) > $M/manifest-after.txt 2>&1
|
||||
echo "end $(date -u +%FT%TZ)" >> $M/summary.txt
|
||||
echo DONE >> $M/summary.txt
|
||||
@@ -0,0 +1,16 @@
|
||||
start 2026-10-10T08:45:22Z
|
||||
delay-exit exit=1 ℹ pass 6 ℹ fail 2
|
||||
delay-close exit=0 ℹ pass 8 ℹ fail 0
|
||||
repeat-1 exit=0 ℹ pass 8 ℹ fail 0
|
||||
repeat-2 exit=0 ℹ pass 8 ℹ fail 0
|
||||
repeat-3 exit=0 ℹ pass 8 ℹ fail 0
|
||||
repeat-4 exit=0 ℹ pass 8 ℹ fail 0
|
||||
repeat-5 exit=0 ℹ pass 8 ℹ fail 0
|
||||
repeat-6 exit=0 ℹ pass 8 ℹ fail 0
|
||||
repeat-7 exit=0 ℹ pass 8 ℹ fail 0
|
||||
repeat-8 exit=0 ℹ pass 8 ℹ fail 0
|
||||
repeat-9 exit=0 ℹ pass 8 ℹ fail 0
|
||||
repeat-10 exit=0 ℹ pass 8 ℹ fail 0
|
||||
test-task-fakedocker exit=1 selftest: 67 passed, 31 failed
|
||||
end 2026-10-10T08:47:18Z
|
||||
DONE
|
||||
@@ -0,0 +1,134 @@
|
||||
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)
|
||||
FAIL mock adapter: gate passes on matching mock response (exit 1, expected 0)
|
||||
OK mock adapter: expect-mismatch recorded (exit 1)
|
||||
FAIL mismatch reason recorded
|
||||
OK unknown adapter fails closed (exit 1)
|
||||
FAIL mission task runs via mock adapter (exit 1, expected 0)
|
||||
grep: /home/jwoltje/darkwing-scratch/r48a/tmp/tmp.HNVro0rxF9/data/system-prompt.md: No such file or directory
|
||||
FAIL mission section injected into generated prompt
|
||||
FAIL retry of mission run succeeds (exit 1, expected 0)
|
||||
OK retriedFrom lineage recorded
|
||||
grep: /home/jwoltje/darkwing-scratch/r48a/tmp/tmp.HNVro0rxF9/data/system-prompt.md: No such file or directory
|
||||
FAIL mission section present after retry (relative path resolved)
|
||||
OK retry of missing run exits 4 (exit 4)
|
||||
OK skill install bundled ms-tools (exit 0)
|
||||
OK installed to skills-available
|
||||
OK double install refuses (exit 1)
|
||||
OK activate enables skill (exit 0)
|
||||
OK enabled dir populated
|
||||
OK uninstall while enabled refuses (exit 1)
|
||||
OK deactivate moves back to available (exit 0)
|
||||
OK uninstall removes from available (exit 0)
|
||||
FAIL seat with enabled skill launches (exit 1)
|
||||
SEATCASE stderr:
|
||||
failed to connect to the docker API at unix:///nonexistent.sock; check if the path is correct and if the daemon is running: dial unix /nonexistent.sock: connect: no such file or directory
|
||||
FAIL skill path delivered to adapter
|
||||
OK shipped researcher contract resolves (ceiling + network)
|
||||
OK resolve-role refuses a non-role document (conductor policy) (exit 2)
|
||||
OK resolve-role refuses name/filename mismatch (exit 2)
|
||||
OK resolve-role refuses unknown network declaration (exit 2)
|
||||
OK resolve-role refuses duplicate role tool (exit 2)
|
||||
OK resolve-role refuses unsupported tool (exit 2)
|
||||
OK resolve-role refuses missing contract file (exit 4)
|
||||
OK version 1 role prints no contract line
|
||||
OK shipped version 2 roles resolve with their contracts (pm, cto, coder, reviewer)
|
||||
OK resolve-role accepts a minimal version 2 role (exit 0)
|
||||
OK resolve-role refuses an action outside the vocabulary (exit 2)
|
||||
OK resolve-role refuses a gated-only action in a role file (exit 2)
|
||||
OK resolve-role refuses a Vikunja verb no role may hold (exit 2)
|
||||
OK resolve-role refuses a version 2 role whose contract is missing (exit 2)
|
||||
OK resolve-role refuses a contract that is a symbolic link (exit 2)
|
||||
FAIL seat launches under role ceiling (exit 1)
|
||||
ROLESEAT stderr:
|
||||
agent: capability policy: role 'analyst' ceiling narrowed tools -> read,bash
|
||||
failed to connect to the docker API at unix:///nonexistent.sock; check if the path is correct and if the daemon is running: dial unix /nonexistent.sock: connect: no such file or directory
|
||||
FAIL role ceiling narrows seat tools (read,write,bash -> read,bash)
|
||||
OK narrowing recorded loudly
|
||||
OK missing role contract refuses launch (exit 2)
|
||||
OK missing-contract refusal names the role
|
||||
FAIL empty ceiling intersection -> tool-free seat
|
||||
OK tool-free outcome recorded loudly
|
||||
OK overridden agents dir without seat definition refuses (exit 4)
|
||||
OK seat-resolution refusal names the seat
|
||||
FAIL policy: mission only -> mission tools
|
||||
FAIL policy: task only -> task tools
|
||||
FAIL policy: both -> intersection (task narrowed)
|
||||
FAIL policy: empty intersection -> tool-free
|
||||
OK invalid mission capabilities rejected (exit 2)
|
||||
mosaic-task: unsupported mission tool: "sudo" (supported: read, write, edit, bash, grep, find, ls)
|
||||
FAIL task run with user layer present (exit 1, expected 0)
|
||||
grep: /home/jwoltje/darkwing-scratch/r48a/tmp/tmp.HNVro0rxF9/data/system-prompt.md: No such file or directory
|
||||
FAIL user context dispatched into generated prompt
|
||||
FAIL workspace+tools task runs via mock (exit 1, expected 0)
|
||||
FAIL workspace path + tools delivered to adapter
|
||||
OK persistent workspace created on host
|
||||
FAIL plain task still runs (no workspace/tools) (exit 1, expected 0)
|
||||
FAIL workspace var present but empty when absent
|
||||
FAIL tools empty when absent
|
||||
OK unknown tool exits 2 (exit 2)
|
||||
OK workspace traversal exits 2 (exit 2)
|
||||
FAIL live hello task succeeds with exact marker
|
||||
--- latest run evidence: /home/jwoltje/darkwing-scratch/r48a/tmp/tmp.HNVro0rxF9/data/runs/r-20261010T084717Z-c421be ---
|
||||
--- stderr.txt (tail) ---
|
||||
OK result.json written in run dir
|
||||
FAIL result.json contents are correct
|
||||
FAIL wrong expectExact (exit 1, reason: 'exit-nonzero')
|
||||
--- latest run evidence: /home/jwoltje/darkwing-scratch/r48a/tmp/tmp.HNVro0rxF9/data/runs/r-20261010T084718Z-fccf9d ---
|
||||
--- stderr.txt (tail) ---
|
||||
OK each run gets a distinct run dir (no clobber)
|
||||
OK list shows both runs
|
||||
FAIL fork base: teach succeeds (exit 1, expected 0)
|
||||
FAIL fork child recalls ancestor context (exit 4, expected 0)
|
||||
node:fs:621
|
||||
return binding.readFileUtf8(path, stringToFlags(options.flag));
|
||||
^
|
||||
|
||||
Error: ENOENT: no such file or directory, open '/home/jwoltje/darkwing-scratch/r48a/tmp/tmp.HNVro0rxF9/data/runs/r-20261010T084718Z-5a44e7/result.json'
|
||||
at Object.readFileSync (node:fs:621:20)
|
||||
at [eval]:1:34
|
||||
at runScriptInThisContext (node:internal/vm:219:10)
|
||||
at node:internal/process/execution:485:12
|
||||
at [eval]-wrapper:6:24
|
||||
at runScriptInContext (node:internal/process/execution:483:60)
|
||||
at evalFunction (node:internal/process/execution:317:30)
|
||||
at evalTypeScript (node:internal/process/execution:329:3)
|
||||
at node:internal/main/eval_string:71:3 {
|
||||
errno: -2,
|
||||
code: 'ENOENT',
|
||||
syscall: 'open',
|
||||
path: '/home/jwoltje/darkwing-scratch/r48a/tmp/tmp.HNVro0rxF9/data/runs/r-20261010T084718Z-5a44e7/result.json'
|
||||
}
|
||||
|
||||
Node.js v26.8.1
|
||||
FAIL forked child recalled ancestor code word
|
||||
OK ancestor session untouched by fork
|
||||
FAIL child session dir has its own branch file
|
||||
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
|
||||
FAIL user recall run succeeds (exit 1)
|
||||
FAIL recalled user name (response: )
|
||||
OK no agent identity on headless run
|
||||
|
||||
selftest: 67 passed, 31 failed
|
||||
@@ -0,0 +1,158 @@
|
||||
✔ F1: an ordinary commit after update-ref is refused until step 8; then it commits and the queue stays at C (1531.501337ms)
|
||||
✔ F1: a plain `commit -e` whose guard ran before update-ref fails at its own HEAD update (1161.077924ms)
|
||||
ℹ git commit -e: index.lock free during the editor
|
||||
✔ F1: a `commit -e -- path` whose guard ran before update-ref fails at its own HEAD update (1083.010591ms)
|
||||
ℹ git commit -e -- src.txt: index.lock held during the editor
|
||||
✔ F1: step 8 with index.lock held exits 3, and ordinary commits stay refused until the printed command runs (1215.184151ms)
|
||||
✔ F1: HEAD moving after the step-7 guard check and before update-ref: refused, nothing published (1184.065991ms)
|
||||
✔ F1: H is recorded before the canary, so HEAD moving during the step-1 canary is refused at step 7 (1128.47923ms)
|
||||
✔ F1: a queue commit landing after H is recorded: step 1 says HEAD moved, not the guard (1342.058049ms)
|
||||
✔ F1: a queue commit landing between the HEAD check and the canary: the failed clean run is reported as HEAD moved (947.181707ms)
|
||||
✔ F1: a shared-index change during the procedure is not committed (1130.0633ms)
|
||||
✔ F1: a queue path staged after update-ref: step 8 stops and touches nothing (1040.512442ms)
|
||||
✔ F1: a missing or a different hook refuses (739.480406ms)
|
||||
✔ F1: same bytes without the exec bit, a symlinked hook, and core.hooksPath in the local or global scope each refuse before update-ref (1169.125226ms)
|
||||
✔ F1: the canary refuses a hook that git would not run (661.843976ms)
|
||||
✔ F1: the guard deactivated after step 1 is refused at the step-7 recheck (935.428692ms)
|
||||
✔ bootstrap: implementation-only HEAD, the guard, genesis, the --genesis commit, then an extending commit (898.575201ms)
|
||||
✔ bootstrap: --genesis with a base present, no base without --genesis, an op before the first commit, a changed map, another branch (936.249459ms)
|
||||
✔ bootstrap: the archived tests and validator run outside any repository (868.280964ms)
|
||||
✔ general: an unrelated staged file stays staged, and the committed blobs are the snapshot bytes (949.350742ms)
|
||||
✔ general: a queue write after the snapshot is not committed (1330.564723ms)
|
||||
✔ general: a snapshot whose log does not extend the base refuses (1197.082601ms)
|
||||
✔ general: install-hook privilege, repair of a same-bytes hook, and its refusals (160.827838ms)
|
||||
✔ general: environment overrides, a linked worktree and usage (671.473149ms)
|
||||
✔ general: a queue path staged before the run refuses at step 1 (766.792514ms)
|
||||
✔ general: HEAD's queue tests failing in the archive refuse (887.336513ms)
|
||||
✔ genesis document serializes deterministically and replays (4.026047ms)
|
||||
✔ a hand edit that stays valid JSON fails replay; a formatting-only edit fails re-serialization (2.298581ms)
|
||||
✔ a tampered result, receipt or viewSha fails replay (2.147875ms)
|
||||
✔ op ids: 8 to 72 characters for callers, 80 in the log for .outcome entries (0.151213ms)
|
||||
✔ add: defaults for an ordinary seat, privileged extras, refusals (4.593521ms)
|
||||
✔ matrix: queued→briefed privileged; briefed→in-progress owner with after satisfied (7.483789ms)
|
||||
✔ matrix: release, review round, changes requested and waiting-on-jason (17.27717ms)
|
||||
✔ matrix J5: in-review→done by the gate owner with evidence naming the current round (10.978861ms)
|
||||
✔ review issue, lead decision 23: none refuses, one is used, several need --issue, later rounds keep it (20.602956ms)
|
||||
✔ the row schema refuses a round with a null issue, and the A1 review shape (P2) (3.172689ms)
|
||||
✔ matrix R1: every state × target × actor class matches 8.7, gate owner jason or not, required or not (1553.614941ms)
|
||||
✔ matrix: blocked keeps the claim and returns only to previousState (3.693869ms)
|
||||
✔ matrix J4: parking is Jason's, refused while required; unpark returns to queued (2.470748ms)
|
||||
✔ field edits: who may change what (6.546166ms)
|
||||
✔ set issues keeps a logged narrowing of closes (N10) (4.13696ms)
|
||||
✔ text the table shows refuses \ and <, everywhere it enters (N8) (1.952963ms)
|
||||
✔ every accepted text renders to nine cells on every row (N8) (23.261139ms)
|
||||
✔ genesis: the map refuses an owner among its row's reviewers; replay doesn't (2026-10-04) (0.524363ms)
|
||||
✔ times and dates must be calendar values, not just the shape (2026-10-04) (1.507788ms)
|
||||
✔ replay holds every op id to the caller's rule (N11) (5.050325ms)
|
||||
✔ note: owner, listed reviewer or privileged; empty clears (1.109607ms)
|
||||
✔ assign moves the claim with the owner; done clears it (2.474914ms)
|
||||
✔ render is byte-stable and escapes pipes (0.496042ms)
|
||||
✔ view classification: current, genuine stale, edited stale marker, changed current body, markers (0.594203ms)
|
||||
✔ next: resume, then review, then start, then wait, then nothing; lowest id first (22.585954ms)
|
||||
✔ canonical args make a retry's identity independent of list order (0.33659ms)
|
||||
✔ manifests, headings and blob ids (0.538689ms)
|
||||
✔ the migration map: one queue-map block, exact keys (0.656175ms)
|
||||
✔ every call but `queue` reaches the seat CLI exactly as before A2 (670.022459ms)
|
||||
✔ `queue` reaches the queue CLI with the rest of the arguments (213.8728ms)
|
||||
✔ the pre-A2 fixture is the script A2 changed (1.513614ms)
|
||||
✔ acquire publishes the record by link; release removes only its own lock (10.159169ms)
|
||||
✔ a kill between the temp write and the link leaves no lock (67.158611ms)
|
||||
✔ a short or failed temp write refuses and leaves no lock and no temp (9.122205ms)
|
||||
✔ a link error other than EEXIST refuses (11.688567ms)
|
||||
✔ an error after the link releases the lock: unreadable gate, failing temp stat (24.423932ms)
|
||||
✔ a release that fails on a gate path is reported, never a stack trace (P1) (47.551358ms)
|
||||
✔ a paused holder: another writer waits 10 s, then refuses naming it live (10102.409604ms)
|
||||
✔ two concurrent unlockers: the second refuses on the gate (40.058729ms)
|
||||
✔ a writer publishing during an unlock, lock first: unlock sees it live and refuses (14.018763ms)
|
||||
✔ a writer publishing during an unlock, gate first: the writer releases and refuses (11.026477ms)
|
||||
✔ a gate swapped while held is left in place and reported, on success and on refusal (N1) (11.233607ms)
|
||||
✔ a reused pid within one boot is mismatch; unlock removes the lock and never signals the process (12.211658ms)
|
||||
✔ the same pid and start on a different boot is mismatch (1.345584ms)
|
||||
✔ a foreign host is unknown whatever the local pid says; unlock refuses (69.410494ms)
|
||||
✔ unreadable /proc: classification is unknown and acquire refuses (0.63259ms)
|
||||
✔ invalid records: empty, unparsable, wrong keys, bad start or boot (0.192671ms)
|
||||
✔ a stale gate blocks writers; --check-gate says mismatch for a reused pid (19.27061ms)
|
||||
✔ a delayed release by a dead owner, after unlock and a new owner: the inode check keeps the new lock (21.173216ms)
|
||||
✔ release checks the inode too: a byte-identical lock file with a new inode is left in place (7.482332ms)
|
||||
✔ unlock refuses a live, unknown or invalid lock, and does nothing without one (31.341033ms)
|
||||
✔ the migration map validates and renders the golden genesis table (4.280454ms)
|
||||
✔ the marked QUEUE.md holds every row and parked item between its markers (1.700032ms)
|
||||
✔ map-check reports each kind of drift (4.957619ms)
|
||||
✔ a request posts once as the requester; a retry sends nothing (1027.42552ms)
|
||||
✔ each transport answer maps to posted, failed or uncertain (8.9 step 3) (5056.627475ms)
|
||||
✔ the pre-send checks: GET user must name the requester, under the deadline (1807.060537ms)
|
||||
✔ the lead's request refuses a token for login sage (896.678358ms)
|
||||
✔ the credential file: the seat's own, 0600, no symlink, never the shared default (781.945755ms)
|
||||
✔ an unresolved request blocks a new request, a new round, waiting-on-jason and done (2225.736661ms)
|
||||
✔ a same-op retry after a kill sends nothing, even with a stale view (2988.433742ms)
|
||||
✔ a held lock at the outcome exits 3 and names what the transport said (691.126594ms)
|
||||
✔ late outcomes: after an abandon, and after a resolve with the same or another id (2263.964507ms)
|
||||
✔ resolve checks the comment: issue, markers, round, candidate and author (1723.878652ms)
|
||||
✔ the lead resolves a seat's request: the comment's author is the requester, fetched with the lead's token (734.561187ms)
|
||||
✔ validateRow checks a request round's shape, which every replayed entry must keep (532.640941ms)
|
||||
✔ request, changes, a new candidate, approval: every round pinned; no review files (2188.598637ms)
|
||||
✔ a row with no reviewers opens a round that posts nothing (1206.674425ms)
|
||||
✔ verify-commit: a prospective tree must hold exactly the candidate's paths (1795.85522ms)
|
||||
✔ semantics: v1 entries replay as before; review entries need v2 (709.091871ms)
|
||||
✔ set reviewers refuses the row's owner (2026-09-28) (361.989356ms)
|
||||
✔ the owner records no verdict, even as a listed reviewer (514.455279ms)
|
||||
✔ a request comment over the length limit is not sent (601.634189ms)
|
||||
✔ a late POST on a closed row leaves a conflict nothing can resolve, and resolve asks nothing (983.019857ms)
|
||||
✔ a Jason-gated row reaches waiting-on-jason only on every reviewer's approval (4427.326493ms)
|
||||
✔ genesis: refusals before anything is written (453.091743ms)
|
||||
✔ genesis: the map must be committed, well formed, with committed briefs and seats (738.032363ms)
|
||||
✔ genesis: markers, a stray witness, once only; a retry returns the receipt (705.369058ms)
|
||||
✔ genesis: a file holding genesis alone with no witness is confirmed by sync or a retry (487.089577ms)
|
||||
✔ canonical checks: worktree, second clone, detached HEAD, wrong branch, GIT_DIR, foreign code; a symlink works (713.997434ms)
|
||||
✔ --by that differs from MOSAIC_AGENT_NAME warns on stderr and logs nothing more (N12) (921.685533ms)
|
||||
✔ op ids: missing, too long, reserved; a retry answers; another payload refuses (800.244923ms)
|
||||
✔ a retried add returns the id it first allocated, after reassignment and after done (1084.80495ms)
|
||||
✔ Rocko's S4 schedule: a lost result, another writer, then the retry opens no second round (819.846ms)
|
||||
✔ the review issue and the evidence round through the CLI (lead decision 23, 8.7) (1319.403243ms)
|
||||
✔ claims and add defaults through the CLI; candidates are manifests or reachable commits (774.41141ms)
|
||||
✔ add, set reviewers and assign refuse the row's owner as a reviewer (499.086804ms)
|
||||
✔ the working-brief check: a changed working copy refuses the start and flags next (648.106951ms)
|
||||
✔ next: resume first, then nothing for an idle seat; needs a seat (368.110729ms)
|
||||
✔ view stale: new ops and verify refuse naming the unshown op; retries answer; reads warn; render fixes (678.034104ms)
|
||||
✔ view unknown: a hand edit, an old marker over an edited body, missing or duplicate markers (1184.889423ms)
|
||||
✔ a hand edit to queue.json refuses every verb, reads included (570.452253ms)
|
||||
✔ verify and render --check leave bytes and mtimes unchanged (416.969308ms)
|
||||
✔ render is byte-stable across runs and repositories (324.131877ms)
|
||||
✔ snapshot and verify --snapshot (761.556178ms)
|
||||
✔ usage errors exit 4 (503.602105ms)
|
||||
✔ a short write, ENOSPC or a file fsync failure: nothing visible, temp removed (401.229971ms)
|
||||
✔ a rename failure: nothing visible, temp removed (204.432783ms)
|
||||
✔ a directory fsync failure: uncertain, exit 3, no receipt; the tail refuses new ops; a retry confirms (337.21166ms)
|
||||
✔ a directory fsync failure, then sync names the op (424.153558ms)
|
||||
✔ a witness write failure: uncertain, durable, exit 3; the view is untouched (311.285092ms)
|
||||
✔ the .git fsync after the witness rename fails: uncertain, exit 3, the witness says so (232.10849ms)
|
||||
✔ confirming a tail fsyncs queue.json and docs/plans before the witness; either failure changes nothing (263.277107ms)
|
||||
✔ the docs/plans fsync after the view rename fails: the op stands, the view is written, a warning says so (203.425485ms)
|
||||
✔ a lock swapped while held is left in place and reported, on a receipt and on a refusal (235.683469ms)
|
||||
✔ a lock that cannot be released after an op is reported, on a receipt and on a refusal (235.375ms)
|
||||
✔ unlock prints a swapped gate's warning on stderr, the result on stdout (150.82536ms)
|
||||
✔ a view write that fails keeps the op and reports a stale view (211.642707ms)
|
||||
✔ SIGKILL before the rename: nothing recorded; the retry removes the leftover temp (690.824969ms)
|
||||
✔ SIGKILL after the rename, before the witness: the tail refuses new ops and sync names the op (724.641647ms)
|
||||
✔ SIGKILL after the witness, before the view: the stale refusal names the op (700.191807ms)
|
||||
✔ SIGKILL after the view, before the receipt: the retry returns the receipt (728.279727ms)
|
||||
✔ git checkout between steps 1 and 7: step 7 refuses and nothing is written (318.332383ms)
|
||||
✔ git stash restoring an older valid pair: history lost; accept-history needs privilege, a reason and --yes (1158.650713ms)
|
||||
✔ a deleted witness: refused after the locked recheck; accept-history records it absent (347.20694ms)
|
||||
✔ a header edit during a write: the op stands, the view write is skipped with a warning (195.357948ms)
|
||||
✔ a reader paused between the witness and the file while a writer finishes: no lost-history report (209.29275ms)
|
||||
✔ file-then-witness order forced by a hook: the locked recheck prevents a false report (222.653744ms)
|
||||
✔ a writer paused before and after the witness rename: readers see a tail, then a match (207.50805ms)
|
||||
✔ a true rollback is reported only after the locked recheck; a held lock names its holder instead (589.973193ms)
|
||||
✔ an accept-history in progress: an unlocked reader waits on the lock and never reports lost history (584.936039ms)
|
||||
✔ the platform check refuses other filesystems (190.20406ms)
|
||||
✔ tmpfs passes only a test layer that allows it (N5) (236.81327ms)
|
||||
✔ unlock keeps a multi-line lock record on stdout (P3) (217.332847ms)
|
||||
ℹ tests 148
|
||||
ℹ suites 0
|
||||
ℹ pass 148
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 33598.350827
|
||||
@@ -0,0 +1,13 @@
|
||||
start 2026-10-10T08:43:13Z
|
||||
node-queue exit=0 ℹ pass 148 ℹ fail 0
|
||||
test-auth exit=0 selftest: 15 passed, 0 failed
|
||||
test-conductor exit=0 selftest: 17 passed, 0 failed
|
||||
test-config exit=0 selftest: 24 passed, 0 failed
|
||||
test-discord exit=0 discord suite: 66 passed, 0 failed
|
||||
test-extension-package exit=0 extension package selftest: 18 passed, 0 failed
|
||||
test-foundation exit=0 selftest: 44 passed, 0 failed
|
||||
test-queue exit=0 queue suite: 27 passed, 0 failed
|
||||
test-release exit=0 selftest: 4 passed, 0 failed
|
||||
test-task exit=0 selftest: 26 passed, 0 failed
|
||||
end 2026-10-10T08:45:19Z
|
||||
DONE
|
||||
@@ -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
|
||||
scripts/test-extension-package.sh: line 14: 358493 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,35 @@
|
||||
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/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 148
|
||||
ℹ pass 148
|
||||
ℹ fail 0
|
||||
OK node --test packages/queue/tests/
|
||||
OK scripts/mosaic queue help
|
||||
skip queue verify and render --check: this checkout (/home/jwoltje/darkwing-scratch/r48a/wt) is not the queue's canonical root (/mnt/storage/src/mosaic-stack)
|
||||
|
||||
queue suite: 27 passed, 0 failed
|
||||
@@ -0,0 +1,16 @@
|
||||
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
|
||||
OK status safe on empty state (exit 0)
|
||||
OK status created no pointer
|
||||
OK fault-injected activation refuses (exit 1)
|
||||
OK refused activation wrote no pointer
|
||||
OK refusal logged exactly once with valid fields
|
||||
OK healthy activation succeeds (exit 0)
|
||||
OK pointer written with valid fields
|
||||
OK repeat activation succeeds (log grows) (exit 0)
|
||||
OK log is append-only across activations
|
||||
OK rollback without previous refuses (exit 1)
|
||||
|
||||
selftest: 14 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,118 @@
|
||||
# Row 48, test hygiene, round 1 review (Darkwing)
|
||||
|
||||
Issue #1534, request comment 27097, notes comment 27098, queue revs
|
||||
317-319. Brief: `docs/plans/2026-10-10_s5-follow-up-and-hygiene.md`,
|
||||
section "Test hygiene: commit.test exit wait and test-task Docker skip".
|
||||
Base `5e87c41f`, which differs from `2d935f59` only in `docs/plans/QUEUE.md`
|
||||
and `docs/plans/queue.json`. Candidate manifest sha256
|
||||
`285a4ec13d3b2a9419911e7b0cc3ffe3af99dd8e564dea69eace339319df5259`. It
|
||||
lists three files: the two changed files and Dewey's `evidence.md`. All
|
||||
three check OK in the canonical tree.
|
||||
|
||||
Verdict: **approve**. Both changes do what the brief's "What ships" asks.
|
||||
Without Docker, the recall pair prints a skip and leaves both counts
|
||||
alone. When `docker info` says yes and the run fails, both checks still
|
||||
fail. Waiting on `close` fixes the stderr race, and I reproduced the race
|
||||
the same way Dewey did. Nothing blocks. I have three small notes.
|
||||
|
||||
## Method
|
||||
|
||||
- I read the diff in full and the brief's section, then compared the new
|
||||
guard and skip line against the three Docker guards already in
|
||||
`test-task.sh` (lines 139, 395, 442). They use the same `docker info`
|
||||
test, and the skip line follows the same `skip ... (docker daemon
|
||||
unavailable)` form.
|
||||
- Detached worktree at `5e87c41f`, with the two files copied from a
|
||||
snapshot of the canonical tree, then `sha256sum -c`: 2 OK. A second
|
||||
worktree for the variants. Both of its files still check OK after the
|
||||
runs (`r1/mut/manifest-after.txt`).
|
||||
- A fake `docker` (`r1/mut/fake-docker`) answers `info` with exit 0 and
|
||||
passes every other call to the real client, with `DOCKER_HOST` pointing
|
||||
at a socket that doesn't exist. The guard sees Docker, and
|
||||
`docker compose run` in `mosaic-task.mjs` fails before any container
|
||||
starts. That exercises the "Docker present, run fails" path with no
|
||||
model call.
|
||||
- Two variants of the paused-commit tests (`r1/mut/mutate.py`): git's
|
||||
stderr delayed 0.5 s by a background subshell that holds the pipe,
|
||||
waited on `exit` and then on `close`. Then the unchanged candidate tests
|
||||
ten times in a row, to check that `close` never hangs.
|
||||
|
||||
Node v26.8.1, `TMPDIR=~/darkwing-scratch/r48a/tmp`, `gate.sh` with
|
||||
`DOCKER_HOST=unix:///nonexistent.sock`, 08:43:13Z to 08:45:19Z. Variants
|
||||
ran 08:45:22Z to 08:47:18Z, then `test-release` with Docker.
|
||||
|
||||
## Suites
|
||||
|
||||
| Suite | Result |
|
||||
|---|---|
|
||||
| queue (node) | 148/0 |
|
||||
| test-auth | 15/0 |
|
||||
| test-conductor | 17/0 |
|
||||
| test-config | 24/0 |
|
||||
| test-discord | 66/0 |
|
||||
| test-extension-package | 18/0 |
|
||||
| test-foundation | 44/0 |
|
||||
| test-queue | 27/0 |
|
||||
| test-release | 4/0 without Docker, 14/0 with it (`test-release-docker.txt`) |
|
||||
| test-task, Docker unreachable | 26/0, four skip lines, the last the new recall-pair skip |
|
||||
| test-task, fake `docker info`, daemon unreachable | 67/31, rc 1 (below) |
|
||||
|
||||
I didn't run test-task with real Docker. That run makes live model
|
||||
calls, and Dewey's 98/0 and Sage's 98/0 on row 52's landing already cover
|
||||
it. The fake-Docker run is the one that tests the new branch with Docker
|
||||
present.
|
||||
|
||||
## The Docker skip
|
||||
|
||||
| Run | Recall pair | Total |
|
||||
|---|---|---|
|
||||
| base, no Docker (rows 51 and 52) | both fail | 26/2 |
|
||||
| candidate, no Docker | `skip live recall pair: ...` | 26/0 |
|
||||
| candidate, fake `docker info`, run fails | `FAIL user recall run succeeds (exit 1)`, `FAIL recalled user name (response: )` | 67/31, rc 1 |
|
||||
|
||||
The pass count is 26 both with the pair failing and with it skipped, so
|
||||
the skip adds nothing to `PASS`. With the fake Docker, the totals add up to
|
||||
98, the same number of checks as Dewey's real run. The 31 failures are
|
||||
every Docker-gated check failing at `docker compose run`. The two recall
|
||||
checks are among them, and no skip line is printed.
|
||||
|
||||
## exit versus close
|
||||
|
||||
| Variant | `--test-name-pattern="F1: a"` |
|
||||
|---|---|
|
||||
| stderr delayed, wait on `exit` | 6/2: both paused-commit tests, `childErr` is `''` against `/cannot lock ref 'HEAD': .../` |
|
||||
| stderr delayed, wait on `close` | 8/0 |
|
||||
| candidate unchanged, ten runs | 8/0 each |
|
||||
|
||||
`close` resolves with the same exit code as the first argument, so
|
||||
`assert.notEqual(code, 0)` still means what it did. The editor script runs
|
||||
no background process, so nothing outlives git while holding the pipe, and
|
||||
`close` can't hang on it.
|
||||
|
||||
The other four `exit` waits in the queue tests (`write.test.mjs:368`,
|
||||
`lock.test.mjs:33`, `:65`, `:151`) read no output after the wait. They
|
||||
don't need the change, which matches the brief's scope.
|
||||
|
||||
## Notes (not blocking)
|
||||
|
||||
1. The brief's problem statement says "Docker and a model". The guard
|
||||
checks Docker only. With Docker up and no model credentials, the pair
|
||||
still fails, along with every other live block. That's what "What
|
||||
ships" asks for, and it's consistent with the three guards above it. I
|
||||
agree with it.
|
||||
2. The guard asks `docker info`, but the run uses `docker compose run`. A
|
||||
host with the daemon and no compose plugin would fail the pair rather
|
||||
than skip it. The other three blocks share this, so it isn't this row's
|
||||
problem.
|
||||
3. Dewey's two follow-ups stand. The fake-Docker run shows the second one:
|
||||
"no agent identity on headless run" printed `OK` after a run that never
|
||||
started. The first one (`FR` picks the newest run record) showed an
|
||||
empty response here, not another run's, because the fork child's run
|
||||
failed too.
|
||||
|
||||
## Files
|
||||
|
||||
- `r1/candidate-manifest.sha256`: copy of Dewey's.
|
||||
- `r1/gate.sh`, `r1/out/`: suite runs and `summary.txt`.
|
||||
- `r1/mut/`: variant definitions, runner, fake `docker`, outputs,
|
||||
`summary.txt`, and the manifest check after the runs.
|
||||
Reference in New Issue
Block a user