From 8e46a8619d13188fb11438eea89bc8de9a272659 Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Sat, 10 Oct 2026 12:17:11 -0500 Subject: [PATCH] review(56): Darkwing round 2 packet, approve (#1545 comment 27123) Co-Authored-By: Claude Opus 5.5 --- .../r2/candidate-manifest.sha256 | 15 + .../darkwing/work/queue-56-review/r2/gate.sh | 16 + .../work/queue-56-review/r2/mut/D01.diff | 13 + .../work/queue-56-review/r2/mut/D01.txt | 73 ++++ .../work/queue-56-review/r2/mut/D03.diff | 14 + .../work/queue-56-review/r2/mut/D03.txt | 121 ++++++ .../work/queue-56-review/r2/mut/D04.diff | 12 + .../work/queue-56-review/r2/mut/D04.txt | 103 +++++ .../work/queue-56-review/r2/mut/D05.diff | 11 + .../work/queue-56-review/r2/mut/D05.txt | 98 +++++ .../work/queue-56-review/r2/mut/D06.diff | 12 + .../work/queue-56-review/r2/mut/D06.txt | 97 +++++ .../work/queue-56-review/r2/mut/D07.diff | 13 + .../work/queue-56-review/r2/mut/D07.txt | 68 ++++ .../work/queue-56-review/r2/mut/D08.diff | 12 + .../work/queue-56-review/r2/mut/D08.txt | 68 ++++ .../work/queue-56-review/r2/mut/D09.diff | 13 + .../work/queue-56-review/r2/mut/D09.txt | 68 ++++ .../work/queue-56-review/r2/mut/D10.diff | 13 + .../work/queue-56-review/r2/mut/D10.txt | 49 +++ .../work/queue-56-review/r2/mut/D11.diff | 13 + .../work/queue-56-review/r2/mut/D11.txt | 93 +++++ .../work/queue-56-review/r2/mut/D13.diff | 12 + .../work/queue-56-review/r2/mut/D13.txt | 65 ++++ .../work/queue-56-review/r2/mut/D14.diff | 13 + .../work/queue-56-review/r2/mut/D14.txt | 353 ++++++++++++++++++ .../work/queue-56-review/r2/mut/D15.diff | 13 + .../work/queue-56-review/r2/mut/D15.txt | 67 ++++ .../work/queue-56-review/r2/mut/D16.diff | 13 + .../work/queue-56-review/r2/mut/D16.txt | 70 ++++ .../work/queue-56-review/r2/mut/D17.diff | 13 + .../work/queue-56-review/r2/mut/D17.txt | 89 +++++ .../work/queue-56-review/r2/mut/D18.diff | 13 + .../work/queue-56-review/r2/mut/D18.txt | 83 ++++ .../work/queue-56-review/r2/mut/D19.diff | 12 + .../work/queue-56-review/r2/mut/D19.txt | 68 ++++ .../work/queue-56-review/r2/mut/D20.diff | 13 + .../work/queue-56-review/r2/mut/D20.txt | 99 +++++ .../work/queue-56-review/r2/mut/D21.diff | 13 + .../work/queue-56-review/r2/mut/D21.txt | 68 ++++ .../work/queue-56-review/r2/mut/D22.diff | 13 + .../work/queue-56-review/r2/mut/D22.txt | 95 +++++ .../work/queue-56-review/r2/mut/D23.diff | 13 + .../work/queue-56-review/r2/mut/D23.txt | 69 ++++ .../queue-56-review/r2/mut/manifest-after.txt | 15 + .../work/queue-56-review/r2/mut/mutate.py | 32 ++ .../work/queue-56-review/r2/mut/run.sh | 15 + .../work/queue-56-review/r2/mut/summary.txt | 24 ++ .../queue-56-review/r2/out/byte-check.txt | 2 + .../queue-56-review/r2/out/delta-check.txt | 118 ++++++ .../work/queue-56-review/r2/out/node-runs.txt | 49 +++ .../work/queue-56-review/r2/out/probes.txt | 27 ++ .../queue-56-review/r2/out/src-against-r1.txt | 7 + .../work/queue-56-review/r2/out/src-diff.txt | 12 + .../work/queue-56-review/r2/out/summary.txt | 13 + .../work/queue-56-review/r2/out/test-auth.txt | 17 + .../queue-56-review/r2/out/test-conductor.txt | 55 +++ .../queue-56-review/r2/out/test-config.txt | 26 ++ .../r2/out/test-discord-r2.txt | 70 ++++ .../queue-56-review/r2/out/test-discord.txt | 74 ++++ .../r2/out/test-extension-package.txt | 21 ++ .../r2/out/test-foundation.txt | 53 +++ .../queue-56-review/r2/out/test-queue.txt | 35 ++ .../r2/out/test-release-docker.txt | 16 + .../queue-56-review/r2/out/test-release.txt | 7 + .../work/queue-56-review/r2/out/test-task.txt | 32 ++ .../work/queue-56-review/r2/probes.sh | 36 ++ .../work/queue-56-review/review-r2.md | 154 ++++++++ 68 files changed, 3172 insertions(+) create mode 100644 agents/darkwing/work/queue-56-review/r2/candidate-manifest.sha256 create mode 100755 agents/darkwing/work/queue-56-review/r2/gate.sh create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D01.diff create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D01.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D03.diff create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D03.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D04.diff create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D04.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D05.diff create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D05.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D06.diff create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D06.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D07.diff create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D07.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D08.diff create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D08.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D09.diff create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D09.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D10.diff create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D10.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D11.diff create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D11.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D13.diff create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D13.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D14.diff create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D14.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D15.diff create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D15.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D16.diff create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D16.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D17.diff create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D17.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D18.diff create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D18.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D19.diff create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D19.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D20.diff create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D20.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D21.diff create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D21.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D22.diff create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D22.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D23.diff create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/D23.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/manifest-after.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/mutate.py create mode 100755 agents/darkwing/work/queue-56-review/r2/mut/run.sh create mode 100644 agents/darkwing/work/queue-56-review/r2/mut/summary.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/out/byte-check.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/out/delta-check.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/out/node-runs.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/out/probes.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/out/src-against-r1.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/out/src-diff.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/out/summary.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/out/test-auth.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/out/test-conductor.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/out/test-config.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/out/test-discord-r2.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/out/test-discord.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/out/test-extension-package.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/out/test-foundation.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/out/test-queue.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/out/test-release-docker.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/out/test-release.txt create mode 100644 agents/darkwing/work/queue-56-review/r2/out/test-task.txt create mode 100755 agents/darkwing/work/queue-56-review/r2/probes.sh create mode 100644 agents/darkwing/work/queue-56-review/review-r2.md diff --git a/agents/darkwing/work/queue-56-review/r2/candidate-manifest.sha256 b/agents/darkwing/work/queue-56-review/r2/candidate-manifest.sha256 new file mode 100644 index 00000000..f90942be --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/candidate-manifest.sha256 @@ -0,0 +1,15 @@ +1afe07062349b097b955f0391bffb839b083492d02644421def6c39cc19ff4a4 agents/rocko/work/queue-56/byte-check.sh +09788e902a54207ef5f94de1c8b7f2f31c049fb028fa68847115da83060d90f9 agents/rocko/work/queue-56/delta-check.sh +15d575cc45313906114f7edda9379b66af7624d9e894bb98812deb7acf5d87ba agents/rocko/work/queue-56/seed.sh +146b236a37bf665979e28f1794c4c4437b6e85feb43b892e8d9d697506fc453f packages/runs/package.json +895dd393a43221ffb12a5dc1b76ab61118b5562a5d7acbc50450ebb3ea6388d3 packages/runs/README.md +f686212fa10e8541a1d8055fe30d65558a516245276aa53ecefd97bd7ca0a20c packages/runs/src/errors.mjs +eb7063a8ee0417699b45f4bfec69c3ffcde8b3b276956ca4fea266ec0abd6b23 packages/runs/src/index.mjs +3f9d025f0615a08edd440bb2aa6cea48f21cafa1f680332fffca3c7ee586cc65 packages/runs/src/paths.mjs +ba64e50c3a63e693fc313278ff6cf440234649a6719dd9229bce20272a518ec1 packages/runs/src/runs.mjs +ae546df81c6da7ef51680e23a12c01f08c5a6dc1b68cdf26c8d4210772149940 packages/runs/src/state.mjs +7c941596020b14d8627ccb09b66e0e51195318e86add60eba9d2c4409e6f8dd6 packages/runs/tests/helpers.mjs +fbaa092b5c8a1b54bc52c090da71f0da4313b4a8221fd7a2e89404a2a1b04633 packages/runs/tests/runs.test.mjs +d0f33cb945cb5960847cd9e9af05f5a85731cb68bc5131efb084a7ecea81591f packages/runs/tests/state.test.mjs +be5d1bdf95340e6c4a697531a225f08b40901ad1b570da7371efe7994e3e1413 packages/runs/tests/task-cli.test.mjs +4873187609897c643e62acf7f1d074fa3c03369fe6702b9b0c7776138e776401 scripts/mosaic-task.mjs diff --git a/agents/darkwing/work/queue-56-review/r2/gate.sh b/agents/darkwing/work/queue-56-review/r2/gate.sh new file mode 100755 index 00000000..d42e0364 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/gate.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# Row 56 gate: packages/runs node suite, then every scripts/test-*.sh with Docker unreachable. +export TMPDIR=~/darkwing-scratch/r56b/tmp DOCKER_HOST=unix:///nonexistent.sock +cd ~/darkwing-scratch/r56b/cand +O=~/darkwing-scratch/r56b/out +: > $O/summary.txt +echo "start $(date -u +%FT%TZ)" >> $O/summary.txt +env -u NODE_TEST_CONTEXT node --test packages/runs/tests/*.test.mjs > $O/node-runs.txt 2>&1; e=$? +echo "node-runs exit=$e $(grep -E '^ℹ (pass|fail)' $O/node-runs.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 diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D01.diff b/agents/darkwing/work/queue-56-review/r2/mut/D01.diff new file mode 100644 index 00000000..96b8bdc7 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D01.diff @@ -0,0 +1,13 @@ +diff --git a/scripts/mosaic-task.mjs b/scripts/mosaic-task.mjs +index cf8399a0..b5a9564e 100755 +--- a/scripts/mosaic-task.mjs ++++ b/scripts/mosaic-task.mjs +@@ -486,7 +486,7 @@ function listRuns() { + } + + function showRun(runId) { +- if (!isRunId(runId)) { ++ if (false) { + fail(4, `invalid run id: ${JSON.stringify(runId)} (expected r-)`); + } + const resolved = loadConfig(); diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D01.txt b/agents/darkwing/work/queue-56-review/r2/mut/D01.txt new file mode 100644 index 00000000..8f5a7359 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D01.txt @@ -0,0 +1,73 @@ +✔ isRunId accepts the run id shape and nothing else (1.187366ms) +✔ a missing data root or runs directory lists nothing (2.073148ms) +✔ runs as a regular file lists nothing, as before (0.667967ms) +✔ listRunIds keeps r- names only, sorted oldest first (1.065405ms) +✔ listRunRecords returns each result, or null for an incomplete or unreadable one (2.710197ms) +✔ readRunRecord returns documents and artifacts in directory order (1.212073ms) +✔ readRunRecord is null for a missing run, a dangling link or a file (0.794819ms) +✔ readRunRecord and readRunDocument refuse an invalid run id before touching the disk (0.87404ms) +✔ readRunDocument reads only the three run documents (0.73155ms) +✔ a link inside the data root is followed (1.101065ms) +✔ a data root that is itself a link is trusted as configured (0.92173ms) +✔ a run directory linked out of the data root is never read (1.182722ms) +✔ a document linked out of the data root reads as null (1.519156ms) +✔ a runs directory linked out of the data root refuses (0.971294ms) +✔ a relative link that climbs out of the data root refuses (0.602539ms) +✔ a sibling whose name starts with the data root's name is outside it (0.602411ms) +✔ a link loop refuses instead of reading as missing (0.836417ms) +✔ an unreadable runs directory refuses instead of listing nothing (0.588817ms) +✔ an unreadable run directory refuses instead of reading as missing (0.764263ms) +✔ a link to the data root's parent is outside it (0.478523ms) +✔ listRunIds sorts whatever order the directory returns (1.303967ms) +✔ listRunRecords lists an r- name that isn't a valid run id, as before (1.087459ms) +✔ the readers write nothing (3.286472ms) +✔ no pointer is null (2.356044ms) +✔ the pointer release.sh writes reads back (1.496897ms) +✔ a pointer that isn't the version 1 shape refuses with exit 2 (2.651413ms) +✔ a pointer that is a directory refuses with exit 4 (1.669957ms) +✔ a state file linked out of the data root refuses (2.02127ms) +✔ a state directory linked out of the data root refuses (1.056491ms) +✔ a state directory linked out to nothing reads as no release and an empty log (0.702711ms) +✔ a missing log is empty (1.296972ms) +✔ the log reads oldest first and counts malformed lines (1.656559ms) +✔ last must be a positive integer (0.721034ms) +✔ the state readers write nothing (1.365288ms) +✔ list prints each run in the established format (100.715833ms) +✔ show prints the run in the established format (108.835407ms) +✔ show of a missing run and an invalid id exit 4 as before (180.126942ms) +✔ list and show refuse a runs directory linked out of the data root (192.410504ms) +✔ show refuses a run linked out of the data root; list reports it unknown (163.544111ms) +✔ list shows an r- name that isn't a valid run id, as before (74.327067ms) +✖ show refuses an invalid id before reading the config (172.108882ms) +ℹ tests 41 +ℹ suites 0 +ℹ pass 40 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 1064.413393 + +✖ failing tests: + +test at packages/runs/tests/task-cli.test.mjs:104:1 +✖ show refuses an invalid id before reading the config (172.108882ms) + AssertionError [ERR_ASSERTION]: mosaic-task: configuration problem (exit 3); run scripts/bootstrap.sh or fix config.json + + + 3 !== 4 + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/task-cli.test.mjs:109: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: false, + code: 'ERR_ASSERTION', + actual: 3, + expected: 4, + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D03.diff b/agents/darkwing/work/queue-56-review/r2/mut/D03.diff new file mode 100644 index 00000000..1a33b122 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D03.diff @@ -0,0 +1,14 @@ +diff --git a/packages/runs/src/paths.mjs b/packages/runs/src/paths.mjs +index 1dbb5539..f7c5f4ea 100644 +--- a/packages/runs/src/paths.mjs ++++ b/packages/runs/src/paths.mjs +@@ -43,7 +43,8 @@ export function readJsonObject(dataRoot, ...parts) { + if (file === null) return null; + const value = JSON.parse(fs.readFileSync(file, "utf8")); + return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null; +- } catch { ++ } catch (error) { ++ if (error instanceof RunsError) throw error; + return null; + } + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D03.txt b/agents/darkwing/work/queue-56-review/r2/mut/D03.txt new file mode 100644 index 00000000..2bbf8eb9 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D03.txt @@ -0,0 +1,121 @@ +✔ isRunId accepts the run id shape and nothing else (1.400398ms) +✔ a missing data root or runs directory lists nothing (1.988221ms) +✔ runs as a regular file lists nothing, as before (0.707746ms) +✔ listRunIds keeps r- names only, sorted oldest first (1.622032ms) +✔ listRunRecords returns each result, or null for an incomplete or unreadable one (1.758806ms) +✔ readRunRecord returns documents and artifacts in directory order (1.221436ms) +✔ readRunRecord is null for a missing run, a dangling link or a file (1.088578ms) +✔ readRunRecord and readRunDocument refuse an invalid run id before touching the disk (1.038079ms) +✔ readRunDocument reads only the three run documents (0.884663ms) +✔ a link inside the data root is followed (2.038475ms) +✔ a data root that is itself a link is trusted as configured (1.134007ms) +✖ a run directory linked out of the data root is never read (0.752745ms) +✖ a document linked out of the data root reads as null (0.763986ms) +✔ a runs directory linked out of the data root refuses (0.653651ms) +✔ a relative link that climbs out of the data root refuses (0.478299ms) +✔ a sibling whose name starts with the data root's name is outside it (0.531338ms) +✖ a link loop refuses instead of reading as missing (0.601651ms) +✔ an unreadable runs directory refuses instead of listing nothing (0.458441ms) +✔ an unreadable run directory refuses instead of reading as missing (0.547674ms) +✔ a link to the data root's parent is outside it (0.51465ms) +✔ listRunIds sorts whatever order the directory returns (0.836887ms) +✔ listRunRecords lists an r- name that isn't a valid run id, as before (0.736515ms) +✔ the readers write nothing (2.225785ms) +✔ no pointer is null (2.030231ms) +✔ the pointer release.sh writes reads back (1.320527ms) +✔ a pointer that isn't the version 1 shape refuses with exit 2 (135.180496ms) +✔ a pointer that is a directory refuses with exit 4 (0.722154ms) +✔ a state file linked out of the data root refuses (1.394205ms) +✔ a state directory linked out of the data root refuses (0.524668ms) +✔ a state directory linked out to nothing reads as no release and an empty log (0.412215ms) +✔ a missing log is empty (0.308456ms) +✔ the log reads oldest first and counts malformed lines (0.862537ms) +✔ last must be a positive integer (0.41004ms) +✔ the state readers write nothing (0.697997ms) +✔ list prints each run in the established format (102.363954ms) +✔ show prints the run in the established format (99.691103ms) +✔ show of a missing run and an invalid id exit 4 as before (133.511964ms) +✔ list and show refuse a runs directory linked out of the data root (188.487781ms) +✖ show refuses a run linked out of the data root; list reports it unknown (167.45552ms) +✔ list shows an r- name that isn't a valid run id, as before (88.153586ms) +✔ show refuses an invalid id before reading the config (62.195932ms) +ℹ tests 41 +ℹ suites 0 +ℹ pass 37 +ℹ fail 4 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 905.338616 + +✖ failing tests: + +test at packages/runs/tests/runs.test.mjs:119:1 +✖ a run directory linked out of the data root is never read (0.752745ms) + Error [RunsError]: /home/jwoltje/darkwing-scratch/r56b/tmp/mosaic-runs-test-LFk8Oo/data/runs/r-20260101T000000Z-aaaaaa/result.json resolves outside the data root (/home/jwoltje/darkwing-scratch/r56b/tmp/mosaic-runs-test-LFk8Oo/data) + at resolveInside (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/paths.mjs:33:11) + at readJsonObject (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/paths.mjs:42:18) + at file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/runs.mjs:46:13 + at Array.map () + at listRunRecords (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/runs.mjs:44:31) + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/runs.test.mjs:125:20) + at Test.runInAsyncScope (node:async_hooks:226:14) + at Test.run (node:internal/test_runner/test:1402:25) + at Test.processPendingSubtests (node:internal/test_runner/test:974:18) + at Test.postRun (node:internal/test_runner/test:1542:19) { + exitCode: 4 + } + +test at packages/runs/tests/runs.test.mjs:129:1 +✖ a document linked out of the data root reads as null (0.763986ms) + Error [RunsError]: /home/jwoltje/darkwing-scratch/r56b/tmp/mosaic-runs-test-ge63ie/data/runs/r-20260101T000000Z-aaaaaa/result.json resolves outside the data root (/home/jwoltje/darkwing-scratch/r56b/tmp/mosaic-runs-test-ge63ie/data) + at resolveInside (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/paths.mjs:33:11) + at readJsonObject (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/paths.mjs:42:18) + at readRunDocument (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/runs.mjs:37:10) + at readRunRecord (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/runs.mjs:67:13) + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/runs.test.mjs:136:18) + 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) { + exitCode: 4 + } + +test at packages/runs/tests/runs.test.mjs:168:1 +✖ a link loop refuses instead of reading as missing (0.601651ms) + Error [RunsError]: cannot resolve /home/jwoltje/darkwing-scratch/r56b/tmp/mosaic-runs-test-HLtM1w/data/runs/r-20260101T000000Z-aaaaaa/result.json: ELOOP + at resolveInside (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/paths.mjs:30:11) + at readJsonObject (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/paths.mjs:42:18) + at file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/runs.mjs:46:13 + at Array.map () + at listRunRecords (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/runs.mjs:44:31) + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/runs.test.mjs:174:20) + at Test.runInAsyncScope (node:async_hooks:226:14) + at Test.run (node:internal/test_runner/test:1402:25) + at Test.processPendingSubtests (node:internal/test_runner/test:974:18) + at Test.postRun (node:internal/test_runner/test:1542:19) { + exitCode: 4 + } + +test at packages/runs/tests/task-cli.test.mjs:82:1 +✖ show refuses a run linked out of the data root; list reports it unknown (167.45552ms) + AssertionError [ERR_ASSERTION]: mosaic-task: /home/jwoltje/darkwing-scratch/r56b/tmp/mosaic-runs-test-QZ52Qw/data/runs/r-20260101T000000Z-aaaaaa/result.json resolves outside the data root (/home/jwoltje/darkwing-scratch/r56b/tmp/mosaic-runs-test-QZ52Qw/data) + + + 4 !== 0 + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/task-cli.test.mjs:92: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: false, + code: 'ERR_ASSERTION', + actual: 4, + expected: 0, + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D04.diff b/agents/darkwing/work/queue-56-review/r2/mut/D04.diff new file mode 100644 index 00000000..1ae95fe2 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D04.diff @@ -0,0 +1,12 @@ +diff --git a/packages/runs/src/runs.mjs b/packages/runs/src/runs.mjs +index 03730c33..5096f921 100644 +--- a/packages/runs/src/runs.mjs ++++ b/packages/runs/src/runs.mjs +@@ -52,7 +52,6 @@ export function listRunRecords(dataRoot) { + export function readRunRecord(dataRoot, runId) { + requireRunId(runId); + // The runs directory first, so a refusal names the link that escapes. +- if (resolveInside(dataRoot, RUNS_DIRNAME) === null) return null; + const dir = resolveInside(dataRoot, RUNS_DIRNAME, runId); + if (dir === null) return null; + let artifacts; diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D04.txt b/agents/darkwing/work/queue-56-review/r2/mut/D04.txt new file mode 100644 index 00000000..82b32031 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D04.txt @@ -0,0 +1,103 @@ +✔ isRunId accepts the run id shape and nothing else (1.065207ms) +✔ a missing data root or runs directory lists nothing (1.698841ms) +✔ runs as a regular file lists nothing, as before (0.630984ms) +✔ listRunIds keeps r- names only, sorted oldest first (1.49914ms) +✔ listRunRecords returns each result, or null for an incomplete or unreadable one (2.076647ms) +✔ readRunRecord returns documents and artifacts in directory order (1.038104ms) +✔ readRunRecord is null for a missing run, a dangling link or a file (0.613748ms) +✔ readRunRecord and readRunDocument refuse an invalid run id before touching the disk (0.680147ms) +✔ readRunDocument reads only the three run documents (0.554692ms) +✔ a link inside the data root is followed (0.956197ms) +✔ a data root that is itself a link is trusted as configured (0.633126ms) +✔ a run directory linked out of the data root is never read (0.687083ms) +✔ a document linked out of the data root reads as null (0.817475ms) +✖ a runs directory linked out of the data root refuses (1.147289ms) +✔ a relative link that climbs out of the data root refuses (0.420625ms) +✔ a sibling whose name starts with the data root's name is outside it (0.432331ms) +✔ a link loop refuses instead of reading as missing (0.580696ms) +✔ an unreadable runs directory refuses instead of listing nothing (0.420343ms) +✔ an unreadable run directory refuses instead of reading as missing (0.505363ms) +✔ a link to the data root's parent is outside it (0.365301ms) +✔ listRunIds sorts whatever order the directory returns (0.728115ms) +✔ listRunRecords lists an r- name that isn't a valid run id, as before (0.572555ms) +✔ the readers write nothing (2.015551ms) +✔ no pointer is null (2.257117ms) +✔ the pointer release.sh writes reads back (1.314201ms) +✔ a pointer that isn't the version 1 shape refuses with exit 2 (132.331487ms) +✔ a pointer that is a directory refuses with exit 4 (1.218663ms) +✔ a state file linked out of the data root refuses (0.870713ms) +✔ a state directory linked out of the data root refuses (0.504281ms) +✔ a state directory linked out to nothing reads as no release and an empty log (0.501277ms) +✔ a missing log is empty (0.321384ms) +✔ the log reads oldest first and counts malformed lines (0.866945ms) +✔ last must be a positive integer (0.46119ms) +✔ the state readers write nothing (0.714278ms) +✔ list prints each run in the established format (77.057222ms) +✔ show prints the run in the established format (65.031466ms) +✔ show of a missing run and an invalid id exit 4 as before (124.475617ms) +✖ list and show refuse a runs directory linked out of the data root (170.366112ms) +✔ show refuses a run linked out of the data root; list reports it unknown (163.564218ms) +✔ list shows an r- name that isn't a valid run id, as before (76.840622ms) +✔ show refuses an invalid id before reading the config (49.249577ms) +ℹ tests 41 +ℹ suites 0 +ℹ pass 39 +ℹ fail 2 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 801.494548 + +✖ failing tests: + +test at packages/runs/tests/runs.test.mjs:143:1 +✖ a runs directory linked out of the data root refuses (1.147289ms) + AssertionError [ERR_ASSERTION]: The input did not match the regular expression /runs resolves outside the data root/. Input: + + 'RunsError: /home/jwoltje/darkwing-scratch/r56b/tmp/mosaic-runs-test-ZzTrSZ/data/runs/r-20260101T000000Z-aaaaaa resolves outside the data root (/home/jwoltje/darkwing-scratch/r56b/tmp/mosaic-runs-test-ZzTrSZ/data)' + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/runs.test.mjs:149: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: RunsError: /home/jwoltje/darkwing-scratch/r56b/tmp/mosaic-runs-test-ZzTrSZ/data/runs/r-20260101T000000Z-aaaaaa resolves outside the data root (/home/jwoltje/darkwing-scratch/r56b/tmp/mosaic-runs-test-ZzTrSZ/data) + at resolveInside (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/paths.mjs:33:11) + at readRunRecord (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/runs.mjs:55:15) + at file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/runs.test.mjs:149:23 + at getActual (node:assert:580:5) + at strict.throws (node:assert:728:24) + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/runs.test.mjs:149: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), + expected: /runs resolves outside the data root/, + operator: 'throws', + diff: 'simple' + } + +test at packages/runs/tests/task-cli.test.mjs:70:1 +✖ list and show refuse a runs directory linked out of the data root (170.366112ms) + AssertionError [ERR_ASSERTION]: The input did not match the regular expression /^mosaic-task: .*runs resolves outside the data root/. Input: + + 'mosaic-task: /home/jwoltje/darkwing-scratch/r56b/tmp/mosaic-runs-test-p4YqkE/data/runs/r-20260101T000000Z-aaaaaa resolves outside the data root (/home/jwoltje/darkwing-scratch/r56b/tmp/mosaic-runs-test-p4YqkE/data)\n' + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/task-cli.test.mjs:78:12) + at Test.runInAsyncScope (node:async_hooks:226:14) + at Test.run (node:internal/test_runner/test:1402:25) + at Test.processPendingSubtests (node:internal/test_runner/test:974:18) + at Test.postRun (node:internal/test_runner/test:1542:19) + at Test.run (node:internal/test_runner/test:1467:12) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: 'mosaic-task: /home/jwoltje/darkwing-scratch/r56b/tmp/mosaic-runs-test-p4YqkE/data/runs/r-20260101T000000Z-aaaaaa resolves outside the data root (/home/jwoltje/darkwing-scratch/r56b/tmp/mosaic-runs-test-p4YqkE/data)\n', + expected: /^mosaic-task: .*runs resolves outside the data root/, + operator: 'match', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D05.diff b/agents/darkwing/work/queue-56-review/r2/mut/D05.diff new file mode 100644 index 00000000..a13f4019 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D05.diff @@ -0,0 +1,11 @@ +diff --git a/packages/runs/src/state.mjs b/packages/runs/src/state.mjs +index af5cc927..3c78f1a3 100644 +--- a/packages/runs/src/state.mjs ++++ b/packages/runs/src/state.mjs +@@ -79,5 +79,5 @@ export function readActivationLog(dataRoot, { last } = {}) { + if (entry === null) malformed += 1; + else entries.push(entry); + } +- return { entries: last === undefined ? entries : entries.slice(-last), malformed }; ++ return { entries: last === undefined ? entries : entries.slice(0, last), malformed }; + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D05.txt b/agents/darkwing/work/queue-56-review/r2/mut/D05.txt new file mode 100644 index 00000000..6c3afe98 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D05.txt @@ -0,0 +1,98 @@ +✔ isRunId accepts the run id shape and nothing else (1.07446ms) +✔ a missing data root or runs directory lists nothing (9.100856ms) +✔ runs as a regular file lists nothing, as before (5.813261ms) +✔ listRunIds keeps r- names only, sorted oldest first (17.34251ms) +✔ listRunRecords returns each result, or null for an incomplete or unreadable one (1.86616ms) +✔ readRunRecord returns documents and artifacts in directory order (26.002078ms) +✔ readRunRecord is null for a missing run, a dangling link or a file (3.693151ms) +✔ readRunRecord and readRunDocument refuse an invalid run id before touching the disk (1.008653ms) +✔ readRunDocument reads only the three run documents (0.813628ms) +✔ a link inside the data root is followed (1.508103ms) +✔ a data root that is itself a link is trusted as configured (1.817532ms) +✔ a run directory linked out of the data root is never read (1.130005ms) +✔ a document linked out of the data root reads as null (22.199116ms) +✔ a runs directory linked out of the data root refuses (1.18345ms) +✔ a relative link that climbs out of the data root refuses (0.698018ms) +✔ a sibling whose name starts with the data root's name is outside it (0.773861ms) +✔ a link loop refuses instead of reading as missing (1.009039ms) +✔ an unreadable runs directory refuses instead of listing nothing (0.659472ms) +✔ an unreadable run directory refuses instead of reading as missing (0.692031ms) +✔ a link to the data root's parent is outside it (0.58212ms) +✔ listRunIds sorts whatever order the directory returns (1.167948ms) +✔ listRunRecords lists an r- name that isn't a valid run id, as before (0.76835ms) +✔ the readers write nothing (3.410202ms) +✔ no pointer is null (5.069465ms) +✔ the pointer release.sh writes reads back (6.698682ms) +✔ a pointer that isn't the version 1 shape refuses with exit 2 (48.474502ms) +✔ a pointer that is a directory refuses with exit 4 (1.375452ms) +✔ a state file linked out of the data root refuses (0.982791ms) +✔ a state directory linked out of the data root refuses (0.595852ms) +✔ a state directory linked out to nothing reads as no release and an empty log (0.475898ms) +✔ a missing log is empty (1.243422ms) +✖ the log reads oldest first and counts malformed lines (2.965998ms) +✔ last must be a positive integer (0.75225ms) +✔ the state readers write nothing (1.350016ms) +✔ list prints each run in the established format (78.922855ms) +✔ show prints the run in the established format (95.821873ms) +✔ show of a missing run and an invalid id exit 4 as before (127.675112ms) +✔ list and show refuse a runs directory linked out of the data root (177.883313ms) +✔ show refuses a run linked out of the data root; list reports it unknown (197.934639ms) +✔ list shows an r- name that isn't a valid run id, as before (99.346507ms) +✔ show refuses an invalid id before reading the config (67.610285ms) +ℹ tests 41 +ℹ suites 0 +ℹ pass 40 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 908.204283 + +✖ failing tests: + +test at packages/runs/tests/state.test.mjs:87:1 +✖ the log reads oldest first and counts malformed lines (2.965998ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: + + actual - expected + + { + entries: [ + { + + at: '2026-09-03T20:57:00Z', + + event: 'package', + + imageTag: 'mosaic-poc-agent:0.84.4-r0.0.12', + + release: '0.0.12' + - at: '2026-09-03T20:57:50Z', + - event: 'refused', + - imageTag: 'mosaic-poc-agent:0.84.4-r0.0.11', + - note: 'health check failed (fault-injected)', + - release: '0.0.11' + }, + { + + at: '2026-09-03T20:57:47Z', + + event: 'activate', + + imageTag: 'mosaic-poc-agent:0.84.4-r0.0.12', + + release: '0.0.12' + - at: '2026-09-03T20:58:15Z', + - event: 'rollback', + - imageTag: 'mosaic-poc-agent:0.84.4-r0.0.11', + - release: '0.0.11' + } + ], + malformed: 7 + } + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/state.test.mjs:111: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: { entries: [ [Object], [Object] ], malformed: 7 }, + expected: { entries: [ [Object], [Object] ], malformed: 7 }, + operator: 'deepStrictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D06.diff b/agents/darkwing/work/queue-56-review/r2/mut/D06.diff new file mode 100644 index 00000000..be450405 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D06.diff @@ -0,0 +1,12 @@ +diff --git a/packages/runs/src/state.mjs b/packages/runs/src/state.mjs +index af5cc927..73c4093f 100644 +--- a/packages/runs/src/state.mjs ++++ b/packages/runs/src/state.mjs +@@ -56,7 +56,6 @@ function logEntry(line) { + if (typeof entry !== "object" || entry === null || Array.isArray(entry)) return null; + if (Object.keys(entry).some((key) => !LOG_KEYS.includes(key))) return null; + if (!["at", "event", "release", "imageTag"].every((key) => typeof entry[key] === "string")) return null; +- if (entry.note !== undefined && typeof entry.note !== "string") return null; + return entry; + } + diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D06.txt b/agents/darkwing/work/queue-56-review/r2/mut/D06.txt new file mode 100644 index 00000000..d4b1ebd2 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D06.txt @@ -0,0 +1,97 @@ +✔ isRunId accepts the run id shape and nothing else (1.868216ms) +✔ a missing data root or runs directory lists nothing (2.86021ms) +✔ runs as a regular file lists nothing, as before (8.40054ms) +✔ listRunIds keeps r- names only, sorted oldest first (1.308516ms) +✔ listRunRecords returns each result, or null for an incomplete or unreadable one (12.488337ms) +✔ readRunRecord returns documents and artifacts in directory order (2.16147ms) +✔ readRunRecord is null for a missing run, a dangling link or a file (1.338434ms) +✔ readRunRecord and readRunDocument refuse an invalid run id before touching the disk (1.147922ms) +✔ readRunDocument reads only the three run documents (0.986952ms) +✔ a link inside the data root is followed (1.887611ms) +✔ a data root that is itself a link is trusted as configured (1.157689ms) +✔ a run directory linked out of the data root is never read (1.147918ms) +✔ a document linked out of the data root reads as null (1.04803ms) +✔ a runs directory linked out of the data root refuses (0.885659ms) +✔ a relative link that climbs out of the data root refuses (0.747769ms) +✔ a sibling whose name starts with the data root's name is outside it (0.85256ms) +✔ a link loop refuses instead of reading as missing (0.911623ms) +✔ an unreadable runs directory refuses instead of listing nothing (0.49244ms) +✔ an unreadable run directory refuses instead of reading as missing (0.674212ms) +✔ a link to the data root's parent is outside it (0.66393ms) +✔ listRunIds sorts whatever order the directory returns (1.041093ms) +✔ listRunRecords lists an r- name that isn't a valid run id, as before (0.720282ms) +✔ the readers write nothing (2.783068ms) +✔ no pointer is null (3.212571ms) +✔ the pointer release.sh writes reads back (8.322256ms) +✔ a pointer that isn't the version 1 shape refuses with exit 2 (20.560714ms) +✔ a pointer that is a directory refuses with exit 4 (1.915186ms) +✔ a state file linked out of the data root refuses (3.438269ms) +✔ a state directory linked out of the data root refuses (0.97389ms) +✔ a state directory linked out to nothing reads as no release and an empty log (0.862097ms) +✔ a missing log is empty (0.580293ms) +✖ the log reads oldest first and counts malformed lines (3.096371ms) +✔ last must be a positive integer (0.860788ms) +✔ the state readers write nothing (1.568966ms) +✔ list prints each run in the established format (103.556364ms) +✔ show prints the run in the established format (99.367753ms) +✔ show of a missing run and an invalid id exit 4 as before (132.794709ms) +✔ list and show refuse a runs directory linked out of the data root (165.176683ms) +✔ show refuses a run linked out of the data root; list reports it unknown (179.243689ms) +✔ list shows an r- name that isn't a valid run id, as before (97.090709ms) +✔ show refuses an invalid id before reading the config (45.621371ms) +ℹ tests 41 +ℹ suites 0 +ℹ pass 40 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 892.03822 + +✖ failing tests: + +test at packages/runs/tests/state.test.mjs:87:1 +✖ the log reads oldest first and counts malformed lines (3.096371ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: + + actual - expected + ... Skipped lines + + { + entries: [ + { + at: '2026-09-03T20:57:00Z', + event: 'package', + ... + { + + at: '2026-09-03T20:57:47Z', + + event: 'activate', + + imageTag: 'mosaic-poc-agent:0.84.4-r0.0.12', + + note: null, + + release: '0.0.12' + + }, + + { + at: '2026-09-03T20:57:50Z', + event: 'refused', + imageTag: 'mosaic-poc-agent:0.84.4-r0.0.11', + note: 'health check failed (fault-injected)', + release: '0.0.11' + ... + ], + + malformed: 6 + - malformed: 7 + } + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/state.test.mjs:110: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: { entries: [ [Object], [Object], [Object], [Object], [Object] ], malformed: 6 }, + expected: { entries: [ [Object], [Object], [Object], [Object] ], malformed: 7 }, + operator: 'deepStrictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D07.diff b/agents/darkwing/work/queue-56-review/r2/mut/D07.diff new file mode 100644 index 00000000..e64be3d6 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D07.diff @@ -0,0 +1,13 @@ +diff --git a/packages/runs/src/runs.mjs b/packages/runs/src/runs.mjs +index 03730c33..e02fea8e 100644 +--- a/packages/runs/src/runs.mjs ++++ b/packages/runs/src/runs.mjs +@@ -23,7 +23,7 @@ export function listRunIds(dataRoot) { + try { + names = fs.readdirSync(root); + } catch (error) { +- if (isMissing(error)) return []; ++ return []; + throw new RunsError(`cannot read ${root}: ${error.code ?? error.message}`); + } + return names.filter((name) => name.startsWith("r-")).sort(); diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D07.txt b/agents/darkwing/work/queue-56-review/r2/mut/D07.txt new file mode 100644 index 00000000..f256d334 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D07.txt @@ -0,0 +1,68 @@ +✔ isRunId accepts the run id shape and nothing else (1.15727ms) +✔ a missing data root or runs directory lists nothing (1.956821ms) +✔ runs as a regular file lists nothing, as before (0.653312ms) +✔ listRunIds keeps r- names only, sorted oldest first (0.813695ms) +✔ listRunRecords returns each result, or null for an incomplete or unreadable one (3.027323ms) +✔ readRunRecord returns documents and artifacts in directory order (1.453954ms) +✔ readRunRecord is null for a missing run, a dangling link or a file (1.14821ms) +✔ readRunRecord and readRunDocument refuse an invalid run id before touching the disk (0.817061ms) +✔ readRunDocument reads only the three run documents (0.720775ms) +✔ a link inside the data root is followed (1.127818ms) +✔ a data root that is itself a link is trusted as configured (0.797552ms) +✔ a run directory linked out of the data root is never read (0.790744ms) +✔ a document linked out of the data root reads as null (1.158428ms) +✔ a runs directory linked out of the data root refuses (0.708719ms) +✔ a relative link that climbs out of the data root refuses (0.456699ms) +✔ a sibling whose name starts with the data root's name is outside it (0.530538ms) +✔ a link loop refuses instead of reading as missing (0.815137ms) +✖ an unreadable runs directory refuses instead of listing nothing (1.594931ms) +✔ an unreadable run directory refuses instead of reading as missing (0.811632ms) +✔ a link to the data root's parent is outside it (0.524666ms) +✔ listRunIds sorts whatever order the directory returns (0.997613ms) +✔ listRunRecords lists an r- name that isn't a valid run id, as before (0.610554ms) +✔ the readers write nothing (3.04337ms) +✔ no pointer is null (2.483326ms) +✔ the pointer release.sh writes reads back (1.671155ms) +✔ a pointer that isn't the version 1 shape refuses with exit 2 (2.225357ms) +✔ a pointer that is a directory refuses with exit 4 (0.654324ms) +✔ a state file linked out of the data root refuses (2.682094ms) +✔ a state directory linked out of the data root refuses (0.672495ms) +✔ a state directory linked out to nothing reads as no release and an empty log (0.52315ms) +✔ a missing log is empty (0.407223ms) +✔ the log reads oldest first and counts malformed lines (1.064471ms) +✔ last must be a positive integer (0.626993ms) +✔ the state readers write nothing (1.360837ms) +✔ list prints each run in the established format (93.09785ms) +✔ show prints the run in the established format (76.906223ms) +✔ show of a missing run and an invalid id exit 4 as before (134.282509ms) +✔ list and show refuse a runs directory linked out of the data root (173.332729ms) +✔ show refuses a run linked out of the data root; list reports it unknown (176.342642ms) +✔ list shows an r- name that isn't a valid run id, as before (102.946334ms) +✔ show refuses an invalid id before reading the config (57.272253ms) +ℹ tests 41 +ℹ suites 0 +ℹ pass 40 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 877.786601 + +✖ failing tests: + +test at packages/runs/tests/runs.test.mjs:177:1 +✖ an unreadable runs directory refuses instead of listing nothing (1.594931ms) + AssertionError [ERR_ASSERTION]: Missing expected exception. + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/runs.test.mjs:183:12) + at Test.runInAsyncScope (node:async_hooks:226:14) + at Test.run (node:internal/test_runner/test:1402:25) + at Test.processPendingSubtests (node:internal/test_runner/test:974:18) + at Test.postRun (node:internal/test_runner/test:1542:19) + at Test.run (node:internal/test_runner/test:1467:12) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: false, + code: 'ERR_ASSERTION', + actual: undefined, + operator: 'throws', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D08.diff b/agents/darkwing/work/queue-56-review/r2/mut/D08.diff new file mode 100644 index 00000000..32719d12 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D08.diff @@ -0,0 +1,12 @@ +diff --git a/packages/runs/src/state.mjs b/packages/runs/src/state.mjs +index af5cc927..ea5b6e96 100644 +--- a/packages/runs/src/state.mjs ++++ b/packages/runs/src/state.mjs +@@ -18,6 +18,7 @@ function readStateFile(dataRoot, name) { + try { + return { file, text: fs.readFileSync(file, "utf8") }; + } catch (error) { ++ return null; + throw new RunsError(`cannot read ${file}: ${error.code ?? error.message}`); + } + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D08.txt b/agents/darkwing/work/queue-56-review/r2/mut/D08.txt new file mode 100644 index 00000000..a7df497c --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D08.txt @@ -0,0 +1,68 @@ +✔ isRunId accepts the run id shape and nothing else (1.695864ms) +✔ a missing data root or runs directory lists nothing (2.111524ms) +✔ runs as a regular file lists nothing, as before (0.687688ms) +✔ listRunIds keeps r- names only, sorted oldest first (0.876875ms) +✔ listRunRecords returns each result, or null for an incomplete or unreadable one (3.457534ms) +✔ readRunRecord returns documents and artifacts in directory order (1.739748ms) +✔ readRunRecord is null for a missing run, a dangling link or a file (1.186074ms) +✔ readRunRecord and readRunDocument refuse an invalid run id before touching the disk (1.159887ms) +✔ readRunDocument reads only the three run documents (1.675916ms) +✔ a link inside the data root is followed (1.744427ms) +✔ a data root that is itself a link is trusted as configured (1.031912ms) +✔ a run directory linked out of the data root is never read (1.011737ms) +✔ a document linked out of the data root reads as null (1.210562ms) +✔ a runs directory linked out of the data root refuses (0.875407ms) +✔ a relative link that climbs out of the data root refuses (0.538894ms) +✔ a sibling whose name starts with the data root's name is outside it (0.616345ms) +✔ a link loop refuses instead of reading as missing (1.019959ms) +✔ an unreadable runs directory refuses instead of listing nothing (0.963002ms) +✔ an unreadable run directory refuses instead of reading as missing (0.667147ms) +✔ a link to the data root's parent is outside it (0.500073ms) +✔ listRunIds sorts whatever order the directory returns (0.863784ms) +✔ listRunRecords lists an r- name that isn't a valid run id, as before (0.689777ms) +✔ the readers write nothing (2.395707ms) +✔ no pointer is null (1.987192ms) +✔ the pointer release.sh writes reads back (1.500792ms) +✔ a pointer that isn't the version 1 shape refuses with exit 2 (4.484566ms) +✖ a pointer that is a directory refuses with exit 4 (1.455589ms) +✔ a state file linked out of the data root refuses (1.342733ms) +✔ a state directory linked out of the data root refuses (0.904937ms) +✔ a state directory linked out to nothing reads as no release and an empty log (0.979319ms) +✔ a missing log is empty (0.601833ms) +✔ the log reads oldest first and counts malformed lines (1.626737ms) +✔ last must be a positive integer (0.825438ms) +✔ the state readers write nothing (0.984388ms) +✔ list prints each run in the established format (103.938354ms) +✔ show prints the run in the established format (99.605055ms) +✔ show of a missing run and an invalid id exit 4 as before (141.552513ms) +✔ list and show refuse a runs directory linked out of the data root (263.632285ms) +✔ show refuses a run linked out of the data root; list reports it unknown (241.004316ms) +✔ list shows an r- name that isn't a valid run id, as before (92.044439ms) +✔ show refuses an invalid id before reading the config (48.767538ms) +ℹ tests 41 +ℹ suites 0 +ℹ pass 40 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 1064.094476 + +✖ failing tests: + +test at packages/runs/tests/state.test.mjs:51:1 +✖ a pointer that is a directory refuses with exit 4 (1.455589ms) + AssertionError [ERR_ASSERTION]: Missing expected exception. + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/state.test.mjs:54: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: false, + code: 'ERR_ASSERTION', + actual: undefined, + operator: 'throws', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D09.diff b/agents/darkwing/work/queue-56-review/r2/mut/D09.diff new file mode 100644 index 00000000..b2377383 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D09.diff @@ -0,0 +1,13 @@ +diff --git a/packages/runs/src/state.mjs b/packages/runs/src/state.mjs +index af5cc927..a73160bf 100644 +--- a/packages/runs/src/state.mjs ++++ b/packages/runs/src/state.mjs +@@ -37,7 +37,7 @@ export function readActivePointer(dataRoot) { + const invalid = (why) => new RunsError(`release pointer ${why} (${state.file})`, 2); + if (typeof pointer !== "object" || pointer === null || Array.isArray(pointer)) throw invalid("must be a JSON object"); + for (const key of Object.keys(pointer)) { +- if (!POINTER_KEYS.includes(key)) throw invalid(`has an unsupported key: "${key}"`); ++ if (false) throw invalid(`has an unsupported key: "${key}"`); + } + if (pointer.pointerVersion !== 1) throw invalid(`has unsupported pointerVersion ${JSON.stringify(pointer.pointerVersion)}`); + for (const key of ["release", "imageTag", "activatedAt"]) { diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D09.txt b/agents/darkwing/work/queue-56-review/r2/mut/D09.txt new file mode 100644 index 00000000..ac7df2d5 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D09.txt @@ -0,0 +1,68 @@ +✔ isRunId accepts the run id shape and nothing else (2.597935ms) +✔ a missing data root or runs directory lists nothing (7.197028ms) +✔ runs as a regular file lists nothing, as before (0.660483ms) +✔ listRunIds keeps r- names only, sorted oldest first (0.967792ms) +✔ listRunRecords returns each result, or null for an incomplete or unreadable one (2.465777ms) +✔ readRunRecord returns documents and artifacts in directory order (1.16948ms) +✔ readRunRecord is null for a missing run, a dangling link or a file (0.822948ms) +✔ readRunRecord and readRunDocument refuse an invalid run id before touching the disk (0.725039ms) +✔ readRunDocument reads only the three run documents (0.682165ms) +✔ a link inside the data root is followed (1.147589ms) +✔ a data root that is itself a link is trusted as configured (0.764645ms) +✔ a run directory linked out of the data root is never read (0.777721ms) +✔ a document linked out of the data root reads as null (0.934673ms) +✔ a runs directory linked out of the data root refuses (0.660635ms) +✔ a relative link that climbs out of the data root refuses (0.494374ms) +✔ a sibling whose name starts with the data root's name is outside it (0.543282ms) +✔ a link loop refuses instead of reading as missing (0.711437ms) +✔ an unreadable runs directory refuses instead of listing nothing (0.727803ms) +✔ an unreadable run directory refuses instead of reading as missing (0.685592ms) +✔ a link to the data root's parent is outside it (0.407671ms) +✔ listRunIds sorts whatever order the directory returns (4.167937ms) +✔ listRunRecords lists an r- name that isn't a valid run id, as before (0.916379ms) +✔ the readers write nothing (3.641306ms) +✔ no pointer is null (5.346721ms) +✔ the pointer release.sh writes reads back (1.585894ms) +✖ a pointer that isn't the version 1 shape refuses with exit 2 (28.811661ms) +✔ a pointer that is a directory refuses with exit 4 (1.063525ms) +✔ a state file linked out of the data root refuses (1.952364ms) +✔ a state directory linked out of the data root refuses (0.628002ms) +✔ a state directory linked out to nothing reads as no release and an empty log (0.543924ms) +✔ a missing log is empty (3.99435ms) +✔ the log reads oldest first and counts malformed lines (1.194387ms) +✔ last must be a positive integer (0.54103ms) +✔ the state readers write nothing (1.220604ms) +✔ list prints each run in the established format (94.412961ms) +✔ show prints the run in the established format (121.913576ms) +✔ show of a missing run and an invalid id exit 4 as before (161.486907ms) +✔ list and show refuse a runs directory linked out of the data root (220.557107ms) +✔ show refuses a run linked out of the data root; list reports it unknown (192.17414ms) +✔ list shows an r- name that isn't a valid run id, as before (106.896964ms) +✔ show refuses an invalid id before reading the config (58.262537ms) +ℹ tests 41 +ℹ suites 0 +ℹ pass 40 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 1040.073192 + +✖ failing tests: + +test at packages/runs/tests/state.test.mjs:32:1 +✖ a pointer that isn't the version 1 shape refuses with exit 2 (28.811661ms) + AssertionError [ERR_ASSERTION]: Missing expected exception: /unsupported key: "extra"/ + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/state.test.mjs:47:12) + at Test.runInAsyncScope (node:async_hooks:226:14) + at Test.run (node:internal/test_runner/test:1402:25) + at Test.processPendingSubtests (node:internal/test_runner/test:974:18) + at Test.postRun (node:internal/test_runner/test:1542:19) + at Test.run (node:internal/test_runner/test:1467:12) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: false, + code: 'ERR_ASSERTION', + actual: undefined, + operator: 'throws', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D10.diff b/agents/darkwing/work/queue-56-review/r2/mut/D10.diff new file mode 100644 index 00000000..73fbfb7d --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D10.diff @@ -0,0 +1,13 @@ +diff --git a/packages/runs/src/paths.mjs b/packages/runs/src/paths.mjs +index 1dbb5539..fe56cb9b 100644 +--- a/packages/runs/src/paths.mjs ++++ b/packages/runs/src/paths.mjs +@@ -11,7 +11,7 @@ export function isMissing(error) { + + function isInside(root, target) { + const relative = path.relative(root, target); +- return relative === "" || (relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative)); ++ return false || (relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative)); + } + + // Resolves / through any symbolic links and returns the diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D10.txt b/agents/darkwing/work/queue-56-review/r2/mut/D10.txt new file mode 100644 index 00000000..ab6324a2 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D10.txt @@ -0,0 +1,49 @@ +✔ isRunId accepts the run id shape and nothing else (1.6626ms) +✔ a missing data root or runs directory lists nothing (2.557802ms) +✔ runs as a regular file lists nothing, as before (0.993455ms) +✔ listRunIds keeps r- names only, sorted oldest first (2.10845ms) +✔ listRunRecords returns each result, or null for an incomplete or unreadable one (2.526378ms) +✔ readRunRecord returns documents and artifacts in directory order (1.74364ms) +✔ readRunRecord is null for a missing run, a dangling link or a file (3.435233ms) +✔ readRunRecord and readRunDocument refuse an invalid run id before touching the disk (1.009532ms) +✔ readRunDocument reads only the three run documents (0.836393ms) +✔ a link inside the data root is followed (1.471449ms) +✔ a data root that is itself a link is trusted as configured (4.897625ms) +✔ a run directory linked out of the data root is never read (1.428292ms) +✔ a document linked out of the data root reads as null (1.498822ms) +✔ a runs directory linked out of the data root refuses (0.935108ms) +✔ a relative link that climbs out of the data root refuses (0.709396ms) +✔ a sibling whose name starts with the data root's name is outside it (0.882846ms) +✔ a link loop refuses instead of reading as missing (1.058619ms) +✔ an unreadable runs directory refuses instead of listing nothing (2.11653ms) +✔ an unreadable run directory refuses instead of reading as missing (0.930758ms) +✔ a link to the data root's parent is outside it (1.598177ms) +✔ listRunIds sorts whatever order the directory returns (1.288405ms) +✔ listRunRecords lists an r- name that isn't a valid run id, as before (0.870374ms) +✔ the readers write nothing (3.744027ms) +✔ no pointer is null (2.085388ms) +✔ the pointer release.sh writes reads back (5.493014ms) +✔ a pointer that isn't the version 1 shape refuses with exit 2 (15.128508ms) +✔ a pointer that is a directory refuses with exit 4 (5.23987ms) +✔ a state file linked out of the data root refuses (1.810665ms) +✔ a state directory linked out of the data root refuses (0.998991ms) +✔ a state directory linked out to nothing reads as no release and an empty log (0.803279ms) +✔ a missing log is empty (0.565342ms) +✔ the log reads oldest first and counts malformed lines (1.636209ms) +✔ last must be a positive integer (0.735553ms) +✔ the state readers write nothing (2.258054ms) +✔ list prints each run in the established format (116.9074ms) +✔ show prints the run in the established format (92.239762ms) +✔ show of a missing run and an invalid id exit 4 as before (138.161653ms) +✔ list and show refuse a runs directory linked out of the data root (180.575601ms) +✔ show refuses a run linked out of the data root; list reports it unknown (155.863719ms) +✔ list shows an r- name that isn't a valid run id, as before (66.034048ms) +✔ show refuses an invalid id before reading the config (45.978715ms) +ℹ tests 41 +ℹ suites 0 +ℹ pass 41 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 873.417164 diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D11.diff b/agents/darkwing/work/queue-56-review/r2/mut/D11.diff new file mode 100644 index 00000000..7f6cfd84 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D11.diff @@ -0,0 +1,13 @@ +diff --git a/scripts/mosaic-task.mjs b/scripts/mosaic-task.mjs +index cf8399a0..7c4bfb80 100755 +--- a/scripts/mosaic-task.mjs ++++ b/scripts/mosaic-task.mjs +@@ -462,7 +462,7 @@ function readRuns(read) { + try { + return read(); + } catch (error) { +- if (error instanceof RunsError) fail(error.exitCode, error.message); ++ if (false) fail(error.exitCode, error.message); + throw error; + } + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D11.txt b/agents/darkwing/work/queue-56-review/r2/mut/D11.txt new file mode 100644 index 00000000..c7540396 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D11.txt @@ -0,0 +1,93 @@ +✔ isRunId accepts the run id shape and nothing else (1.160098ms) +✔ a missing data root or runs directory lists nothing (1.712897ms) +✔ runs as a regular file lists nothing, as before (0.650182ms) +✔ listRunIds keeps r- names only, sorted oldest first (1.113564ms) +✔ listRunRecords returns each result, or null for an incomplete or unreadable one (2.406922ms) +✔ readRunRecord returns documents and artifacts in directory order (1.572189ms) +✔ readRunRecord is null for a missing run, a dangling link or a file (0.777226ms) +✔ readRunRecord and readRunDocument refuse an invalid run id before touching the disk (0.754688ms) +✔ readRunDocument reads only the three run documents (0.682826ms) +✔ a link inside the data root is followed (1.118588ms) +✔ a data root that is itself a link is trusted as configured (0.860124ms) +✔ a run directory linked out of the data root is never read (1.212714ms) +✔ a document linked out of the data root reads as null (1.539772ms) +✔ a runs directory linked out of the data root refuses (0.792065ms) +✔ a relative link that climbs out of the data root refuses (0.634973ms) +✔ a sibling whose name starts with the data root's name is outside it (0.819447ms) +✔ a link loop refuses instead of reading as missing (1.025891ms) +✔ an unreadable runs directory refuses instead of listing nothing (0.73579ms) +✔ an unreadable run directory refuses instead of reading as missing (0.654308ms) +✔ a link to the data root's parent is outside it (0.431647ms) +✔ listRunIds sorts whatever order the directory returns (0.90279ms) +✔ listRunRecords lists an r- name that isn't a valid run id, as before (0.544152ms) +✔ the readers write nothing (2.666725ms) +✔ no pointer is null (1.95949ms) +✔ the pointer release.sh writes reads back (1.316236ms) +✔ a pointer that isn't the version 1 shape refuses with exit 2 (1.881776ms) +✔ a pointer that is a directory refuses with exit 4 (1.406961ms) +✔ a state file linked out of the data root refuses (1.07326ms) +✔ a state directory linked out of the data root refuses (0.649188ms) +✔ a state directory linked out to nothing reads as no release and an empty log (0.583015ms) +✔ a missing log is empty (0.436768ms) +✔ the log reads oldest first and counts malformed lines (1.10825ms) +✔ last must be a positive integer (0.518269ms) +✔ the state readers write nothing (0.908431ms) +✔ list prints each run in the established format (88.182372ms) +✔ show prints the run in the established format (90.40074ms) +✔ show of a missing run and an invalid id exit 4 as before (163.139175ms) +✖ list and show refuse a runs directory linked out of the data root (86.669533ms) +✖ show refuses a run linked out of the data root; list reports it unknown (87.589376ms) +✔ list shows an r- name that isn't a valid run id, as before (78.640786ms) +✔ show refuses an invalid id before reading the config (41.75937ms) +ℹ tests 41 +ℹ suites 0 +ℹ pass 39 +ℹ fail 2 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 697.746994 + +✖ failing tests: + +test at packages/runs/tests/task-cli.test.mjs:70:1 +✖ list and show refuse a runs directory linked out of the data root (86.669533ms) + AssertionError [ERR_ASSERTION]: list + + 1 !== 4 + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/task-cli.test.mjs:76:12) + at Test.runInAsyncScope (node:async_hooks:226:14) + at Test.run (node:internal/test_runner/test:1402:25) + at Test.processPendingSubtests (node:internal/test_runner/test:974:18) + at Test.postRun (node:internal/test_runner/test:1542:19) + at Test.run (node:internal/test_runner/test:1467:12) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: false, + code: 'ERR_ASSERTION', + actual: 1, + expected: 4, + operator: 'strictEqual', + diff: 'simple' + } + +test at packages/runs/tests/task-cli.test.mjs:82:1 +✖ show refuses a run linked out of the data root; list reports it unknown (87.589376ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + + 1 !== 4 + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/task-cli.test.mjs:88: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: 1, + expected: 4, + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D13.diff b/agents/darkwing/work/queue-56-review/r2/mut/D13.diff new file mode 100644 index 00000000..12214802 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D13.diff @@ -0,0 +1,12 @@ +diff --git a/packages/runs/src/runs.mjs b/packages/runs/src/runs.mjs +index 03730c33..943dadfa 100644 +--- a/packages/runs/src/runs.mjs ++++ b/packages/runs/src/runs.mjs +@@ -59,7 +59,6 @@ export function readRunRecord(dataRoot, runId) { + try { + artifacts = fs.readdirSync(dir); + } catch (error) { +- if (isMissing(error)) return null; + throw new RunsError(`cannot read ${dir}: ${error.code ?? error.message}`); + } + return { diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D13.txt b/agents/darkwing/work/queue-56-review/r2/mut/D13.txt new file mode 100644 index 00000000..29de8ce6 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D13.txt @@ -0,0 +1,65 @@ +✔ isRunId accepts the run id shape and nothing else (1.019792ms) +✔ a missing data root or runs directory lists nothing (1.537162ms) +✔ runs as a regular file lists nothing, as before (0.626401ms) +✔ listRunIds keeps r- names only, sorted oldest first (0.70396ms) +✔ listRunRecords returns each result, or null for an incomplete or unreadable one (1.605381ms) +✔ readRunRecord returns documents and artifacts in directory order (0.978894ms) +✖ readRunRecord is null for a missing run, a dangling link or a file (0.782736ms) +✔ readRunRecord and readRunDocument refuse an invalid run id before touching the disk (0.618964ms) +✔ readRunDocument reads only the three run documents (0.639582ms) +✔ a link inside the data root is followed (0.953467ms) +✔ a data root that is itself a link is trusted as configured (0.675656ms) +✔ a run directory linked out of the data root is never read (0.689555ms) +✔ a document linked out of the data root reads as null (0.894036ms) +✔ a runs directory linked out of the data root refuses (0.600981ms) +✔ a relative link that climbs out of the data root refuses (0.422303ms) +✔ a sibling whose name starts with the data root's name is outside it (0.542892ms) +✔ a link loop refuses instead of reading as missing (0.66723ms) +✔ an unreadable runs directory refuses instead of listing nothing (0.512036ms) +✔ an unreadable run directory refuses instead of reading as missing (0.626632ms) +✔ a link to the data root's parent is outside it (0.403352ms) +✔ listRunIds sorts whatever order the directory returns (0.81109ms) +✔ listRunRecords lists an r- name that isn't a valid run id, as before (0.63346ms) +✔ the readers write nothing (2.24943ms) +✔ no pointer is null (1.762831ms) +✔ the pointer release.sh writes reads back (1.161502ms) +✔ a pointer that isn't the version 1 shape refuses with exit 2 (1.684703ms) +✔ a pointer that is a directory refuses with exit 4 (1.066646ms) +✔ a state file linked out of the data root refuses (0.95879ms) +✔ a state directory linked out of the data root refuses (0.598971ms) +✔ a state directory linked out to nothing reads as no release and an empty log (0.443066ms) +✔ a missing log is empty (0.346331ms) +✔ the log reads oldest first and counts malformed lines (0.900263ms) +✔ last must be a positive integer (0.433079ms) +✔ the state readers write nothing (0.791434ms) +✔ list prints each run in the established format (78.266364ms) +✔ show prints the run in the established format (69.618235ms) +✔ show of a missing run and an invalid id exit 4 as before (112.18599ms) +✔ list and show refuse a runs directory linked out of the data root (147.542974ms) +✔ show refuses a run linked out of the data root; list reports it unknown (133.430679ms) +✔ list shows an r- name that isn't a valid run id, as before (76.660284ms) +✔ show refuses an invalid id before reading the config (45.844203ms) +ℹ tests 41 +ℹ suites 0 +ℹ pass 40 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 718.130278 + +✖ failing tests: + +test at packages/runs/tests/runs.test.mjs:75:1 +✖ readRunRecord is null for a missing run, a dangling link or a file (0.782736ms) + Error [RunsError]: cannot read /home/jwoltje/darkwing-scratch/r56b/tmp/mosaic-runs-test-b3hgCt/data/runs/r-20260101T000100Z-bbbbbb: ENOTDIR + at readRunRecord (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/runs.mjs:62:11) + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/runs.test.mjs:83:16) + at Test.runInAsyncScope (node:async_hooks:226:14) + at Test.run (node:internal/test_runner/test:1402:25) + at Test.processPendingSubtests (node:internal/test_runner/test:974:18) + at Test.postRun (node:internal/test_runner/test:1542:19) + at Test.run (node:internal/test_runner/test:1467:12) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + exitCode: 4 + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D14.diff b/agents/darkwing/work/queue-56-review/r2/mut/D14.diff new file mode 100644 index 00000000..38ce93f2 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D14.diff @@ -0,0 +1,13 @@ +diff --git a/packages/runs/src/paths.mjs b/packages/runs/src/paths.mjs +index 1dbb5539..7ce9d52c 100644 +--- a/packages/runs/src/paths.mjs ++++ b/packages/runs/src/paths.mjs +@@ -24,7 +24,7 @@ export function resolveInside(dataRoot, ...parts) { + let real; + try { + root = fs.realpathSync(dataRoot); +- real = fs.realpathSync(target); ++ real = path.resolve(target); + } catch (error) { + if (isMissing(error)) return null; + throw new RunsError(`cannot resolve ${target}: ${error.code ?? error.message}`); diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D14.txt b/agents/darkwing/work/queue-56-review/r2/mut/D14.txt new file mode 100644 index 00000000..19757bd6 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D14.txt @@ -0,0 +1,353 @@ +✔ isRunId accepts the run id shape and nothing else (1.054784ms) +✔ a missing data root or runs directory lists nothing (1.652336ms) +✔ runs as a regular file lists nothing, as before (0.551128ms) +✔ listRunIds keeps r- names only, sorted oldest first (1.225706ms) +✔ listRunRecords returns each result, or null for an incomplete or unreadable one (1.355194ms) +✔ readRunRecord returns documents and artifacts in directory order (0.964287ms) +✔ readRunRecord is null for a missing run, a dangling link or a file (0.660858ms) +✔ readRunRecord and readRunDocument refuse an invalid run id before touching the disk (0.691905ms) +✔ readRunDocument reads only the three run documents (0.56909ms) +✔ a link inside the data root is followed (0.880389ms) +✖ a data root that is itself a link is trusted as configured (0.699319ms) +✖ a run directory linked out of the data root is never read (1.673175ms) +✖ a document linked out of the data root reads as null (0.958721ms) +✖ a runs directory linked out of the data root refuses (0.510659ms) +✖ a relative link that climbs out of the data root refuses (0.603903ms) +✖ a sibling whose name starts with the data root's name is outside it (0.702796ms) +✔ a link loop refuses instead of reading as missing (0.614909ms) +✔ an unreadable runs directory refuses instead of listing nothing (0.453137ms) +✔ an unreadable run directory refuses instead of reading as missing (0.602137ms) +✖ a link to the data root's parent is outside it (0.550265ms) +✔ listRunIds sorts whatever order the directory returns (0.752446ms) +✔ listRunRecords lists an r- name that isn't a valid run id, as before (0.486875ms) +✔ the readers write nothing (2.072302ms) +✖ no pointer is null (1.751412ms) +✔ the pointer release.sh writes reads back (1.046095ms) +✔ a pointer that isn't the version 1 shape refuses with exit 2 (1.648482ms) +✔ a pointer that is a directory refuses with exit 4 (0.585862ms) +✖ a state file linked out of the data root refuses (1.759557ms) +✖ a state directory linked out of the data root refuses (0.604972ms) +✖ a state directory linked out to nothing reads as no release and an empty log (0.425196ms) +✖ a missing log is empty (0.475951ms) +✔ the log reads oldest first and counts malformed lines (0.961794ms) +✔ last must be a positive integer (0.506807ms) +✔ the state readers write nothing (0.83569ms) +✔ list prints each run in the established format (82.854009ms) +✔ show prints the run in the established format (77.561091ms) +✔ show of a missing run and an invalid id exit 4 as before (119.793186ms) +✖ list and show refuse a runs directory linked out of the data root (92.256203ms) +✖ show refuses a run linked out of the data root; list reports it unknown (80.040594ms) +✔ list shows an r- name that isn't a valid run id, as before (72.307362ms) +✔ show refuses an invalid id before reading the config (47.222817ms) +ℹ tests 41 +ℹ suites 0 +ℹ pass 27 +ℹ fail 14 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 641.071641 + +✖ failing tests: + +test at packages/runs/tests/runs.test.mjs:111:1 +✖ a data root that is itself a link is trusted as configured (0.699319ms) + Error [RunsError]: /home/jwoltje/darkwing-scratch/r56b/tmp/mosaic-runs-test-J1fCqk/alias/runs resolves outside the data root (/home/jwoltje/darkwing-scratch/r56b/tmp/mosaic-runs-test-J1fCqk/data) + at resolveInside (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/paths.mjs:33:11) + at listRunIds (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/runs.mjs:20:16) + at listRunRecords (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/runs.mjs:44:10) + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/runs.test.mjs:116:20) + at Test.runInAsyncScope (node:async_hooks:226:14) + at Test.run (node:internal/test_runner/test:1402:25) + at Test.processPendingSubtests (node:internal/test_runner/test:974:18) + at Test.postRun (node:internal/test_runner/test:1542:19) + at Test.run (node:internal/test_runner/test:1467:12) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + exitCode: 4 + } + +test at packages/runs/tests/runs.test.mjs:119:1 +✖ a run directory linked out of the data root is never read (1.673175ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: + + actual - expected + + [ + { + + result: { + + durationMs: 1000, + + exitCode: 0, + + expectedExact: null, + + finishedAt: '2026-01-01T00:00:01.000Z', + + missionId: null, + + model: 'm', + + provider: 'zai', + + reason: null, + + request: 'hi', + + response: 'hi', + + runId: 'r-20260101T000000Z-aaaaaa', + + runVersion: 1, + + session: null, + + sessionForkFrom: null, + + signal: null, + + startedAt: '2026-01-01T00:00:00.000Z', + + status: 'succeeded', + + taskId: 't-one', + + tools: null, + + workspace: null + + }, + - result: null, + runId: 'r-20260101T000000Z-aaaaaa' + } + ] + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/runs.test.mjs:125: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: [ { runId: 'r-20260101T000000Z-aaaaaa', result: [Object] } ], + expected: [ { runId: 'r-20260101T000000Z-aaaaaa', result: null } ], + operator: 'deepStrictEqual', + diff: 'simple' + } + +test at packages/runs/tests/runs.test.mjs:129:1 +✖ a document linked out of the data root reads as null (0.958721ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + + actual - expected + + + { + + durationMs: 1000, + + exitCode: 0, + + expectedExact: null, + + finishedAt: '2026-01-01T00:00:01.000Z', + + missionId: null, + + model: 'm', + + provider: 'zai', + + reason: null, + + request: 'hi', + + response: 'hi', + + runId: 'r-20260101T000000Z-aaaaaa', + + runVersion: 1, + + session: null, + + sessionForkFrom: null, + + signal: null, + + startedAt: '2026-01-01T00:00:00.000Z', + + status: 'succeeded', + + taskId: 't-one', + + tools: null, + + workspace: null + + } + - null + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/runs.test.mjs:137: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: { runVersion: 1, runId: 'r-20260101T000000Z-aaaaaa', taskId: 't-one', missionId: null, status: 'succeeded', reason: null, request: 'hi', response: 'hi', expectedExact: null, workspace: null, tools: null, session: null, sessionForkFrom: null, exitCode: 0, signal: null, provider: 'zai', model: 'm', startedAt: '2026-01-01T00:00:00.000Z', finishedAt: '2026-01-01T00:00:01.000Z', durationMs: 1000 }, + expected: null, + operator: 'strictEqual', + diff: 'simple' + } + +test at packages/runs/tests/runs.test.mjs:143:1 +✖ a runs directory linked out of the data root refuses (0.510659ms) + AssertionError [ERR_ASSERTION]: Missing expected exception. + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/runs.test.mjs:147: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: false, + code: 'ERR_ASSERTION', + actual: undefined, + expected: /runs resolves outside the data root/, + operator: 'throws', + diff: 'simple' + } + +test at packages/runs/tests/runs.test.mjs:152:1 +✖ a relative link that climbs out of the data root refuses (0.603903ms) + AssertionError [ERR_ASSERTION]: Missing expected exception. + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/runs.test.mjs:156: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: false, + code: 'ERR_ASSERTION', + actual: undefined, + expected: /resolves outside the data root/, + operator: 'throws', + diff: 'simple' + } + +test at packages/runs/tests/runs.test.mjs:159:1 +✖ a sibling whose name starts with the data root's name is outside it (0.702796ms) + AssertionError [ERR_ASSERTION]: Missing expected exception. + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/runs.test.mjs:165: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: false, + code: 'ERR_ASSERTION', + actual: undefined, + expected: /resolves outside the data root/, + operator: 'throws', + diff: 'simple' + } + +test at packages/runs/tests/runs.test.mjs:201:1 +✖ a link to the data root's parent is outside it (0.550265ms) + AssertionError [ERR_ASSERTION]: Missing expected exception. + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/runs.test.mjs:205: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: false, + code: 'ERR_ASSERTION', + actual: undefined, + expected: /resolves outside the data root/, + operator: 'throws', + diff: 'simple' + } + +test at packages/runs/tests/state.test.mjs:18:1 +✖ no pointer is null (1.751412ms) + Error [RunsError]: cannot read /home/jwoltje/darkwing-scratch/r56b/tmp/mosaic-runs-test-Hvm8Hi/data/state/active.json: ENOENT + at readStateFile (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/state.mjs:21:11) + at readActivePointer (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/state.mjs:29:17) + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/state.test.mjs:20:16) + at Test.runInAsyncScope (node:async_hooks:226:14) + at Test.run (node:internal/test_runner/test:1402:25) + at Test.start (node:internal/test_runner/test:1262:17) + at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) { + exitCode: 4 + } + +test at packages/runs/tests/state.test.mjs:57:1 +✖ a state file linked out of the data root refuses (1.759557ms) + AssertionError [ERR_ASSERTION]: Missing expected exception. + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/state.test.mjs:64: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: false, + code: 'ERR_ASSERTION', + actual: undefined, + expected: /resolves outside the data root/, + operator: 'throws', + diff: 'simple' + } + +test at packages/runs/tests/state.test.mjs:68:1 +✖ a state directory linked out of the data root refuses (0.604972ms) + AssertionError [ERR_ASSERTION]: Missing expected exception. + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/state.test.mjs:72: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: false, + code: 'ERR_ASSERTION', + actual: undefined, + expected: /state\/active.json resolves outside the data root/, + operator: 'throws', + diff: 'simple' + } + +test at packages/runs/tests/state.test.mjs:75:1 +✖ a state directory linked out to nothing reads as no release and an empty log (0.425196ms) + Error [RunsError]: cannot read /home/jwoltje/darkwing-scratch/r56b/tmp/mosaic-runs-test-SAMKL6/data/state/active.json: ENOENT + at readStateFile (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/state.mjs:21:11) + at readActivePointer (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/state.mjs:29:17) + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/state.test.mjs:78:16) + at Test.runInAsyncScope (node:async_hooks:226:14) + at Test.run (node:internal/test_runner/test:1402:25) + at Test.processPendingSubtests (node:internal/test_runner/test:974:18) + at Test.postRun (node:internal/test_runner/test:1542:19) + at Test.run (node:internal/test_runner/test:1467:12) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + exitCode: 4 + } + +test at packages/runs/tests/state.test.mjs:82:1 +✖ a missing log is empty (0.475951ms) + Error [RunsError]: cannot read /home/jwoltje/darkwing-scratch/r56b/tmp/mosaic-runs-test-YDcaud/data/state/activation-log.jsonl: ENOENT + at readStateFile (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/state.mjs:21:11) + at readActivationLog (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/state.mjs:72:17) + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/state.test.mjs:84:20) + at Test.runInAsyncScope (node:async_hooks:226:14) + at Test.run (node:internal/test_runner/test:1402:25) + at Test.processPendingSubtests (node:internal/test_runner/test:974:18) + at Test.postRun (node:internal/test_runner/test:1542:19) + at Test.run (node:internal/test_runner/test:1467:12) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + exitCode: 4 + } + +test at packages/runs/tests/task-cli.test.mjs:70:1 +✖ list and show refuse a runs directory linked out of the data root (92.256203ms) + AssertionError [ERR_ASSERTION]: list + + 0 !== 4 + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/task-cli.test.mjs:76:12) + at Test.runInAsyncScope (node:async_hooks:226:14) + at Test.run (node:internal/test_runner/test:1402:25) + at Test.processPendingSubtests (node:internal/test_runner/test:974:18) + at Test.postRun (node:internal/test_runner/test:1542:19) + at Test.run (node:internal/test_runner/test:1467:12) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: false, + code: 'ERR_ASSERTION', + actual: 0, + expected: 4, + operator: 'strictEqual', + diff: 'simple' + } + +test at packages/runs/tests/task-cli.test.mjs:82:1 +✖ show refuses a run linked out of the data root; list reports it unknown (80.040594ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + + 0 !== 4 + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/task-cli.test.mjs:88: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: 4, + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D15.diff b/agents/darkwing/work/queue-56-review/r2/mut/D15.diff new file mode 100644 index 00000000..34ccf6d7 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D15.diff @@ -0,0 +1,13 @@ +diff --git a/packages/runs/src/paths.mjs b/packages/runs/src/paths.mjs +index 1dbb5539..2cbffca6 100644 +--- a/packages/runs/src/paths.mjs ++++ b/packages/runs/src/paths.mjs +@@ -23,7 +23,7 @@ export function resolveInside(dataRoot, ...parts) { + let root; + let real; + try { +- root = fs.realpathSync(dataRoot); ++ root = path.resolve(dataRoot); + real = fs.realpathSync(target); + } catch (error) { + if (isMissing(error)) return null; diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D15.txt b/agents/darkwing/work/queue-56-review/r2/mut/D15.txt new file mode 100644 index 00000000..fd633068 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D15.txt @@ -0,0 +1,67 @@ +✔ isRunId accepts the run id shape and nothing else (0.997986ms) +✔ a missing data root or runs directory lists nothing (1.607466ms) +✔ runs as a regular file lists nothing, as before (0.66625ms) +✔ listRunIds keeps r- names only, sorted oldest first (2.247012ms) +✔ listRunRecords returns each result, or null for an incomplete or unreadable one (2.325328ms) +✔ readRunRecord returns documents and artifacts in directory order (1.518989ms) +✔ readRunRecord is null for a missing run, a dangling link or a file (0.91467ms) +✔ readRunRecord and readRunDocument refuse an invalid run id before touching the disk (0.688117ms) +✔ readRunDocument reads only the three run documents (0.679207ms) +✔ a link inside the data root is followed (1.094892ms) +✖ a data root that is itself a link is trusted as configured (0.717025ms) +✔ a run directory linked out of the data root is never read (0.971395ms) +✔ a document linked out of the data root reads as null (1.253566ms) +✔ a runs directory linked out of the data root refuses (0.793626ms) +✔ a relative link that climbs out of the data root refuses (0.713461ms) +✔ a sibling whose name starts with the data root's name is outside it (0.825603ms) +✔ a link loop refuses instead of reading as missing (0.703219ms) +✔ an unreadable runs directory refuses instead of listing nothing (0.451785ms) +✔ an unreadable run directory refuses instead of reading as missing (0.578206ms) +✔ a link to the data root's parent is outside it (0.386068ms) +✔ listRunIds sorts whatever order the directory returns (0.739358ms) +✔ listRunRecords lists an r- name that isn't a valid run id, as before (0.531107ms) +✔ the readers write nothing (1.843235ms) +✔ no pointer is null (1.972129ms) +✔ the pointer release.sh writes reads back (1.24273ms) +✔ a pointer that isn't the version 1 shape refuses with exit 2 (1.770283ms) +✔ a pointer that is a directory refuses with exit 4 (0.565257ms) +✔ a state file linked out of the data root refuses (1.498773ms) +✔ a state directory linked out of the data root refuses (0.660361ms) +✔ a state directory linked out to nothing reads as no release and an empty log (0.59035ms) +✔ a missing log is empty (0.482079ms) +✔ the log reads oldest first and counts malformed lines (1.084198ms) +✔ last must be a positive integer (0.634979ms) +✔ the state readers write nothing (0.860207ms) +✔ list prints each run in the established format (87.530195ms) +✔ show prints the run in the established format (78.052145ms) +✔ show of a missing run and an invalid id exit 4 as before (114.872261ms) +✔ list and show refuse a runs directory linked out of the data root (200.792804ms) +✔ show refuses a run linked out of the data root; list reports it unknown (194.493903ms) +✔ list shows an r- name that isn't a valid run id, as before (129.049237ms) +✔ show refuses an invalid id before reading the config (48.628287ms) +ℹ tests 41 +ℹ suites 0 +ℹ pass 40 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 914.584975 + +✖ failing tests: + +test at packages/runs/tests/runs.test.mjs:111:1 +✖ a data root that is itself a link is trusted as configured (0.717025ms) + Error [RunsError]: /home/jwoltje/darkwing-scratch/r56b/tmp/mosaic-runs-test-ZbqJkI/alias/runs resolves outside the data root (/home/jwoltje/darkwing-scratch/r56b/tmp/mosaic-runs-test-ZbqJkI/alias) + at resolveInside (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/paths.mjs:33:11) + at listRunIds (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/runs.mjs:20:16) + at listRunRecords (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/runs.mjs:44:10) + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/runs.test.mjs:116:20) + at Test.runInAsyncScope (node:async_hooks:226:14) + at Test.run (node:internal/test_runner/test:1402:25) + at Test.processPendingSubtests (node:internal/test_runner/test:974:18) + at Test.postRun (node:internal/test_runner/test:1542:19) + at Test.run (node:internal/test_runner/test:1467:12) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + exitCode: 4 + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D16.diff b/agents/darkwing/work/queue-56-review/r2/mut/D16.diff new file mode 100644 index 00000000..da349b88 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D16.diff @@ -0,0 +1,13 @@ +diff --git a/packages/runs/src/runs.mjs b/packages/runs/src/runs.mjs +index 03730c33..08a71fab 100644 +--- a/packages/runs/src/runs.mjs ++++ b/packages/runs/src/runs.mjs +@@ -2,7 +2,7 @@ import fs from "node:fs"; + import { RunsError } from "./errors.mjs"; + import { RUNS_DIRNAME, isMissing, readJsonObject, resolveInside } from "./paths.mjs"; + +-export const RUN_ID_PATTERN = /^r-[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/; ++export const RUN_ID_PATTERN = /^r-[A-Za-z0-9][A-Za-z0-9._-]{0,64}$/; + export const RUN_DOCUMENTS = ["result.json", "task.json", "mission.json"]; + + export function isRunId(value) { diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D16.txt b/agents/darkwing/work/queue-56-review/r2/mut/D16.txt new file mode 100644 index 00000000..38f2aba5 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D16.txt @@ -0,0 +1,70 @@ +✖ isRunId accepts the run id shape and nothing else (2.210226ms) +✔ a missing data root or runs directory lists nothing (2.603108ms) +✔ runs as a regular file lists nothing, as before (0.935946ms) +✔ listRunIds keeps r- names only, sorted oldest first (1.163969ms) +✔ listRunRecords returns each result, or null for an incomplete or unreadable one (2.413922ms) +✔ readRunRecord returns documents and artifacts in directory order (1.371064ms) +✔ readRunRecord is null for a missing run, a dangling link or a file (1.118632ms) +✔ readRunRecord and readRunDocument refuse an invalid run id before touching the disk (0.780695ms) +✔ readRunDocument reads only the three run documents (0.621037ms) +✔ a link inside the data root is followed (1.177301ms) +✔ a data root that is itself a link is trusted as configured (0.764799ms) +✔ a run directory linked out of the data root is never read (0.722632ms) +✔ a document linked out of the data root reads as null (0.995435ms) +✔ a runs directory linked out of the data root refuses (0.710336ms) +✔ a relative link that climbs out of the data root refuses (0.470174ms) +✔ a sibling whose name starts with the data root's name is outside it (0.553622ms) +✔ a link loop refuses instead of reading as missing (1.050635ms) +✔ an unreadable runs directory refuses instead of listing nothing (0.578181ms) +✔ an unreadable run directory refuses instead of reading as missing (0.593413ms) +✔ a link to the data root's parent is outside it (0.486943ms) +✔ listRunIds sorts whatever order the directory returns (0.94863ms) +✔ listRunRecords lists an r- name that isn't a valid run id, as before (0.588248ms) +✔ the readers write nothing (5.231385ms) +✔ no pointer is null (2.354597ms) +✔ the pointer release.sh writes reads back (1.773315ms) +✔ a pointer that isn't the version 1 shape refuses with exit 2 (2.415432ms) +✔ a pointer that is a directory refuses with exit 4 (1.450113ms) +✔ a state file linked out of the data root refuses (1.244576ms) +✔ a state directory linked out of the data root refuses (0.652045ms) +✔ a state directory linked out to nothing reads as no release and an empty log (0.621644ms) +✔ a missing log is empty (0.549717ms) +✔ the log reads oldest first and counts malformed lines (1.224628ms) +✔ last must be a positive integer (0.607716ms) +✔ the state readers write nothing (1.009192ms) +✔ list prints each run in the established format (89.320943ms) +✔ show prints the run in the established format (94.517441ms) +✔ show of a missing run and an invalid id exit 4 as before (144.124028ms) +✔ list and show refuse a runs directory linked out of the data root (170.44307ms) +✔ show refuses a run linked out of the data root; list reports it unknown (157.310275ms) +✔ list shows an r- name that isn't a valid run id, as before (89.274742ms) +✔ show refuses an invalid id before reading the config (45.834389ms) +ℹ tests 41 +ℹ suites 0 +ℹ pass 40 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 861.630104 + +✖ failing tests: + +test at packages/runs/tests/runs.test.mjs:13:1 +✖ isRunId accepts the run id shape and nothing else (2.210226ms) + AssertionError [ERR_ASSERTION]: r-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + true !== false + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/runs.test.mjs:16:12) + at Test.runInAsyncScope (node:async_hooks:226:14) + at Test.run (node:internal/test_runner/test:1402:25) + at Test.start (node:internal/test_runner/test:1262:17) + at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) { + generatedMessage: false, + code: 'ERR_ASSERTION', + actual: true, + expected: false, + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D17.diff b/agents/darkwing/work/queue-56-review/r2/mut/D17.diff new file mode 100644 index 00000000..16674d0a --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D17.diff @@ -0,0 +1,13 @@ +diff --git a/packages/runs/src/runs.mjs b/packages/runs/src/runs.mjs +index 03730c33..db7d57c1 100644 +--- a/packages/runs/src/runs.mjs ++++ b/packages/runs/src/runs.mjs +@@ -43,7 +43,7 @@ export function readRunDocument(dataRoot, runId, name) { + export function listRunRecords(dataRoot) { + return listRunIds(dataRoot).map((runId) => ({ + runId, +- result: readJsonObject(dataRoot, RUNS_DIRNAME, runId, "result.json"), ++ result: readRunDocument(dataRoot, runId, "result.json"), + })); + } + diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D17.txt b/agents/darkwing/work/queue-56-review/r2/mut/D17.txt new file mode 100644 index 00000000..da0bb82a --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D17.txt @@ -0,0 +1,89 @@ +✔ isRunId accepts the run id shape and nothing else (1.590741ms) +✔ a missing data root or runs directory lists nothing (2.330311ms) +✔ runs as a regular file lists nothing, as before (0.907679ms) +✔ listRunIds keeps r- names only, sorted oldest first (1.181581ms) +✔ listRunRecords returns each result, or null for an incomplete or unreadable one (2.54764ms) +✔ readRunRecord returns documents and artifacts in directory order (1.169101ms) +✔ readRunRecord is null for a missing run, a dangling link or a file (0.818664ms) +✔ readRunRecord and readRunDocument refuse an invalid run id before touching the disk (0.787166ms) +✔ readRunDocument reads only the three run documents (0.619749ms) +✔ a link inside the data root is followed (1.130548ms) +✔ a data root that is itself a link is trusted as configured (0.756907ms) +✔ a run directory linked out of the data root is never read (1.079323ms) +✔ a document linked out of the data root reads as null (1.034215ms) +✔ a runs directory linked out of the data root refuses (0.684294ms) +✔ a relative link that climbs out of the data root refuses (0.532266ms) +✔ a sibling whose name starts with the data root's name is outside it (0.611387ms) +✔ a link loop refuses instead of reading as missing (0.723085ms) +✔ an unreadable runs directory refuses instead of listing nothing (0.536617ms) +✔ an unreadable run directory refuses instead of reading as missing (0.640848ms) +✔ a link to the data root's parent is outside it (0.451118ms) +✔ listRunIds sorts whatever order the directory returns (0.968119ms) +✖ listRunRecords lists an r- name that isn't a valid run id, as before (0.6552ms) +✔ the readers write nothing (2.352082ms) +✔ no pointer is null (3.071243ms) +✔ the pointer release.sh writes reads back (2.029825ms) +✔ a pointer that isn't the version 1 shape refuses with exit 2 (37.796406ms) +✔ a pointer that is a directory refuses with exit 4 (0.729401ms) +✔ a state file linked out of the data root refuses (1.672903ms) +✔ a state directory linked out of the data root refuses (0.622978ms) +✔ a state directory linked out to nothing reads as no release and an empty log (0.586589ms) +✔ a missing log is empty (0.450358ms) +✔ the log reads oldest first and counts malformed lines (1.135566ms) +✔ last must be a positive integer (0.515257ms) +✔ the state readers write nothing (0.965261ms) +✔ list prints each run in the established format (100.007368ms) +✔ show prints the run in the established format (76.759238ms) +✔ show of a missing run and an invalid id exit 4 as before (165.294787ms) +✔ list and show refuse a runs directory linked out of the data root (137.384111ms) +✔ show refuses a run linked out of the data root; list reports it unknown (152.698033ms) +✖ list shows an r- name that isn't a valid run id, as before (73.773092ms) +✔ show refuses an invalid id before reading the config (39.617828ms) +ℹ tests 41 +ℹ suites 0 +ℹ pass 39 +ℹ fail 2 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 809.245413 + +✖ failing tests: + +test at packages/runs/tests/runs.test.mjs:220:1 +✖ listRunRecords lists an r- name that isn't a valid run id, as before (0.6552ms) + Error [RunsError]: invalid run id: "r-.bad" (expected r-) + at requireRunId (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/runs.mjs:13:30) + at readRunDocument (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/runs.mjs:35:3) + at file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/runs.mjs:46:13 + at Array.map () + at listRunRecords (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/src/runs.mjs:44:31) + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/runs.test.mjs:225:20) + at Test.runInAsyncScope (node:async_hooks:226:14) + at Test.run (node:internal/test_runner/test:1402:25) + at Test.processPendingSubtests (node:internal/test_runner/test:974:18) + at Test.postRun (node:internal/test_runner/test:1542:19) { + exitCode: 4 + } + +test at packages/runs/tests/task-cli.test.mjs:96:1 +✖ list shows an r- name that isn't a valid run id, as before (73.773092ms) + AssertionError [ERR_ASSERTION]: mosaic-task: invalid run id: "r-.bad" (expected r-) + + + 4 !== 0 + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/task-cli.test.mjs:100: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: false, + code: 'ERR_ASSERTION', + actual: 4, + expected: 0, + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D18.diff b/agents/darkwing/work/queue-56-review/r2/mut/D18.diff new file mode 100644 index 00000000..30a919bb --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D18.diff @@ -0,0 +1,13 @@ +diff --git a/packages/runs/src/state.mjs b/packages/runs/src/state.mjs +index af5cc927..9788bfca 100644 +--- a/packages/runs/src/state.mjs ++++ b/packages/runs/src/state.mjs +@@ -74,7 +74,7 @@ export function readActivationLog(dataRoot, { last } = {}) { + const entries = []; + let malformed = 0; + for (const line of state.text.split("\n")) { +- if (line.trim() === "") continue; ++ if (line === "") continue; + const entry = logEntry(line); + if (entry === null) malformed += 1; + else entries.push(entry); diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D18.txt b/agents/darkwing/work/queue-56-review/r2/mut/D18.txt new file mode 100644 index 00000000..6282f96b --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D18.txt @@ -0,0 +1,83 @@ +✔ isRunId accepts the run id shape and nothing else (2.009126ms) +✔ a missing data root or runs directory lists nothing (13.094847ms) +✔ runs as a regular file lists nothing, as before (2.278303ms) +✔ listRunIds keeps r- names only, sorted oldest first (2.327495ms) +✔ listRunRecords returns each result, or null for an incomplete or unreadable one (4.905919ms) +✔ readRunRecord returns documents and artifacts in directory order (7.96623ms) +✔ readRunRecord is null for a missing run, a dangling link or a file (3.918579ms) +✔ readRunRecord and readRunDocument refuse an invalid run id before touching the disk (5.602756ms) +✔ readRunDocument reads only the three run documents (3.521732ms) +✔ a link inside the data root is followed (3.442024ms) +✔ a data root that is itself a link is trusted as configured (2.005087ms) +✔ a run directory linked out of the data root is never read (2.084232ms) +✔ a document linked out of the data root reads as null (7.619635ms) +✔ a runs directory linked out of the data root refuses (1.250289ms) +✔ a relative link that climbs out of the data root refuses (0.818784ms) +✔ a sibling whose name starts with the data root's name is outside it (3.850288ms) +✔ a link loop refuses instead of reading as missing (4.675288ms) +✔ an unreadable runs directory refuses instead of listing nothing (1.954118ms) +✔ an unreadable run directory refuses instead of reading as missing (1.858696ms) +✔ a link to the data root's parent is outside it (1.178473ms) +✔ listRunIds sorts whatever order the directory returns (1.430997ms) +✔ listRunRecords lists an r- name that isn't a valid run id, as before (3.626875ms) +✔ the readers write nothing (3.631659ms) +✔ no pointer is null (12.722881ms) +✔ the pointer release.sh writes reads back (2.956634ms) +✔ a pointer that isn't the version 1 shape refuses with exit 2 (23.610773ms) +✔ a pointer that is a directory refuses with exit 4 (2.467786ms) +✔ a state file linked out of the data root refuses (9.154475ms) +✔ a state directory linked out of the data root refuses (5.636323ms) +✔ a state directory linked out to nothing reads as no release and an empty log (0.989436ms) +✔ a missing log is empty (0.893401ms) +✖ the log reads oldest first and counts malformed lines (3.734558ms) +✔ last must be a positive integer (0.948278ms) +✔ the state readers write nothing (2.050762ms) +✔ list prints each run in the established format (139.06499ms) +✔ show prints the run in the established format (91.810125ms) +✔ show of a missing run and an invalid id exit 4 as before (268.025853ms) +✔ list and show refuse a runs directory linked out of the data root (205.373671ms) +✔ show refuses a run linked out of the data root; list reports it unknown (196.491701ms) +✔ list shows an r- name that isn't a valid run id, as before (89.089467ms) +✔ show refuses an invalid id before reading the config (49.958959ms) +ℹ tests 41 +ℹ suites 0 +ℹ pass 40 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 1233.510304 + +✖ failing tests: + +test at packages/runs/tests/state.test.mjs:87:1 +✖ the log reads oldest first and counts malformed lines (3.734558ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: + + actual - expected + ... Skipped lines + + { + entries: [ + { + at: '2026-09-03T20:57:00Z', + event: 'package', + ... + ], + + malformed: 8 + - malformed: 7 + } + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/state.test.mjs:110: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: { entries: [ [Object], [Object], [Object], [Object] ], malformed: 8 }, + expected: { entries: [ [Object], [Object], [Object], [Object] ], malformed: 7 }, + operator: 'deepStrictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D19.diff b/agents/darkwing/work/queue-56-review/r2/mut/D19.diff new file mode 100644 index 00000000..ebb385f6 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D19.diff @@ -0,0 +1,12 @@ +diff --git a/packages/runs/src/runs.mjs b/packages/runs/src/runs.mjs +index 03730c33..d8cb0e58 100644 +--- a/packages/runs/src/runs.mjs ++++ b/packages/runs/src/runs.mjs +@@ -32,7 +32,6 @@ export function listRunIds(dataRoot) { + // One of RUN_DOCUMENTS from a run, or null when it is missing, unreadable, + // not a JSON object or outside the data root. + export function readRunDocument(dataRoot, runId, name) { +- requireRunId(runId); + if (!RUN_DOCUMENTS.includes(name)) throw new RunsError(`unknown run document: ${JSON.stringify(name)}`); + return readJsonObject(dataRoot, RUNS_DIRNAME, runId, name); + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D19.txt b/agents/darkwing/work/queue-56-review/r2/mut/D19.txt new file mode 100644 index 00000000..01ad6834 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D19.txt @@ -0,0 +1,68 @@ +✔ isRunId accepts the run id shape and nothing else (1.789031ms) +✔ a missing data root or runs directory lists nothing (2.597337ms) +✔ runs as a regular file lists nothing, as before (1.16149ms) +✔ listRunIds keeps r- names only, sorted oldest first (1.463129ms) +✔ listRunRecords returns each result, or null for an incomplete or unreadable one (4.240373ms) +✔ readRunRecord returns documents and artifacts in directory order (2.086403ms) +✔ readRunRecord is null for a missing run, a dangling link or a file (1.577833ms) +✖ readRunRecord and readRunDocument refuse an invalid run id before touching the disk (2.195478ms) +✔ readRunDocument reads only the three run documents (1.16193ms) +✔ a link inside the data root is followed (2.748711ms) +✔ a data root that is itself a link is trusted as configured (2.929924ms) +✔ a run directory linked out of the data root is never read (1.362183ms) +✔ a document linked out of the data root reads as null (3.606348ms) +✔ a runs directory linked out of the data root refuses (1.731427ms) +✔ a relative link that climbs out of the data root refuses (0.783109ms) +✔ a sibling whose name starts with the data root's name is outside it (0.924617ms) +✔ a link loop refuses instead of reading as missing (1.189822ms) +✔ an unreadable runs directory refuses instead of listing nothing (0.74324ms) +✔ an unreadable run directory refuses instead of reading as missing (1.046894ms) +✔ a link to the data root's parent is outside it (0.803458ms) +✔ listRunIds sorts whatever order the directory returns (1.402974ms) +✔ listRunRecords lists an r- name that isn't a valid run id, as before (0.820001ms) +✔ the readers write nothing (5.081678ms) +✔ no pointer is null (3.322821ms) +✔ the pointer release.sh writes reads back (2.043259ms) +✔ a pointer that isn't the version 1 shape refuses with exit 2 (6.549959ms) +✔ a pointer that is a directory refuses with exit 4 (6.005478ms) +✔ a state file linked out of the data root refuses (4.026755ms) +✔ a state directory linked out of the data root refuses (1.081501ms) +✔ a state directory linked out to nothing reads as no release and an empty log (1.876666ms) +✔ a missing log is empty (0.648509ms) +✔ the log reads oldest first and counts malformed lines (2.286529ms) +✔ last must be a positive integer (0.996248ms) +✔ the state readers write nothing (1.822738ms) +✔ list prints each run in the established format (191.335275ms) +✔ show prints the run in the established format (358.090605ms) +✔ show of a missing run and an invalid id exit 4 as before (647.478452ms) +✔ list and show refuse a runs directory linked out of the data root (725.179038ms) +✔ show refuses a run linked out of the data root; list reports it unknown (595.356633ms) +✔ list shows an r- name that isn't a valid run id, as before (144.877778ms) +✔ show refuses an invalid id before reading the config (138.198732ms) +ℹ tests 41 +ℹ suites 0 +ℹ pass 40 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 2929.86496 + +✖ failing tests: + +test at packages/runs/tests/runs.test.mjs:86:1 +✖ readRunRecord and readRunDocument refuse an invalid run id before touching the disk (2.195478ms) + AssertionError [ERR_ASSERTION]: Missing expected exception (RunsError). + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/runs.test.mjs:90:12) + at Test.runInAsyncScope (node:async_hooks:226:14) + at Test.run (node:internal/test_runner/test:1402:25) + at Test.processPendingSubtests (node:internal/test_runner/test:974:18) + at Test.postRun (node:internal/test_runner/test:1542:19) + at Test.run (node:internal/test_runner/test:1467:12) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: false, + code: 'ERR_ASSERTION', + actual: undefined, + operator: 'throws', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D20.diff b/agents/darkwing/work/queue-56-review/r2/mut/D20.diff new file mode 100644 index 00000000..fee8da7c --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D20.diff @@ -0,0 +1,13 @@ +diff --git a/packages/runs/src/runs.mjs b/packages/runs/src/runs.mjs +index 03730c33..3814b6a5 100644 +--- a/packages/runs/src/runs.mjs ++++ b/packages/runs/src/runs.mjs +@@ -26,7 +26,7 @@ export function listRunIds(dataRoot) { + if (isMissing(error)) return []; + throw new RunsError(`cannot read ${root}: ${error.code ?? error.message}`); + } +- return names.filter((name) => name.startsWith("r-")).sort(); ++ return names.filter(isRunId).sort(); + } + + // One of RUN_DOCUMENTS from a run, or null when it is missing, unreadable, diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D20.txt b/agents/darkwing/work/queue-56-review/r2/mut/D20.txt new file mode 100644 index 00000000..6404001d --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D20.txt @@ -0,0 +1,99 @@ +✔ isRunId accepts the run id shape and nothing else (2.349624ms) +✔ a missing data root or runs directory lists nothing (3.06341ms) +✔ runs as a regular file lists nothing, as before (1.261241ms) +✔ listRunIds keeps r- names only, sorted oldest first (1.52865ms) +✔ listRunRecords returns each result, or null for an incomplete or unreadable one (4.80885ms) +✔ readRunRecord returns documents and artifacts in directory order (1.949916ms) +✔ readRunRecord is null for a missing run, a dangling link or a file (3.289521ms) +✔ readRunRecord and readRunDocument refuse an invalid run id before touching the disk (1.223411ms) +✔ readRunDocument reads only the three run documents (0.817925ms) +✔ a link inside the data root is followed (1.649226ms) +✔ a data root that is itself a link is trusted as configured (1.268864ms) +✔ a run directory linked out of the data root is never read (1.271219ms) +✔ a document linked out of the data root reads as null (4.558659ms) +✔ a runs directory linked out of the data root refuses (1.24361ms) +✔ a relative link that climbs out of the data root refuses (0.769591ms) +✔ a sibling whose name starts with the data root's name is outside it (0.855321ms) +✔ a link loop refuses instead of reading as missing (1.125869ms) +✔ an unreadable runs directory refuses instead of listing nothing (0.92955ms) +✔ an unreadable run directory refuses instead of reading as missing (1.103476ms) +✔ a link to the data root's parent is outside it (0.933244ms) +✔ listRunIds sorts whatever order the directory returns (1.548586ms) +✖ listRunRecords lists an r- name that isn't a valid run id, as before (3.063895ms) +✔ the readers write nothing (5.728488ms) +✔ no pointer is null (2.85157ms) +✔ the pointer release.sh writes reads back (2.167674ms) +✔ a pointer that isn't the version 1 shape refuses with exit 2 (28.992167ms) +✔ a pointer that is a directory refuses with exit 4 (1.210931ms) +✔ a state file linked out of the data root refuses (2.779979ms) +✔ a state directory linked out of the data root refuses (1.069934ms) +✔ a state directory linked out to nothing reads as no release and an empty log (0.943535ms) +✔ a missing log is empty (0.677356ms) +✔ the log reads oldest first and counts malformed lines (2.389984ms) +✔ last must be a positive integer (4.101041ms) +✔ the state readers write nothing (1.756571ms) +✔ list prints each run in the established format (213.459424ms) +✔ show prints the run in the established format (146.704832ms) +✔ show of a missing run and an invalid id exit 4 as before (380.104067ms) +✔ list and show refuse a runs directory linked out of the data root (310.571356ms) +✔ show refuses a run linked out of the data root; list reports it unknown (175.66159ms) +✖ list shows an r- name that isn't a valid run id, as before (72.884478ms) +✔ show refuses an invalid id before reading the config (55.520564ms) +ℹ tests 41 +ℹ suites 0 +ℹ pass 39 +ℹ fail 2 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 1453.463752 + +✖ failing tests: + +test at packages/runs/tests/runs.test.mjs:220:1 +✖ listRunRecords lists an r- name that isn't a valid run id, as before (3.063895ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: + + actual - expected + + + [] + - [ + - 'r-.bad' + - ] + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/runs.test.mjs:224: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: [], + expected: [ 'r-.bad' ], + operator: 'deepStrictEqual', + diff: 'simple' + } + +test at packages/runs/tests/task-cli.test.mjs:96:1 +✖ list shows an r- name that isn't a valid run id, as before (72.884478ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + + actual - expected + + + '' + - 'r-.bad succeeded task=t-one ws=- session=-\n' + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/task-cli.test.mjs:101: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: '', + expected: 'r-.bad succeeded task=t-one ws=- session=-\n', + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D21.diff b/agents/darkwing/work/queue-56-review/r2/mut/D21.diff new file mode 100644 index 00000000..7fc9429e --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D21.diff @@ -0,0 +1,13 @@ +diff --git a/packages/runs/src/state.mjs b/packages/runs/src/state.mjs +index af5cc927..6b777627 100644 +--- a/packages/runs/src/state.mjs ++++ b/packages/runs/src/state.mjs +@@ -39,7 +39,7 @@ export function readActivePointer(dataRoot) { + for (const key of Object.keys(pointer)) { + if (!POINTER_KEYS.includes(key)) throw invalid(`has an unsupported key: "${key}"`); + } +- if (pointer.pointerVersion !== 1) throw invalid(`has unsupported pointerVersion ${JSON.stringify(pointer.pointerVersion)}`); ++ if (false) throw invalid(`has unsupported pointerVersion ${JSON.stringify(pointer.pointerVersion)}`); + for (const key of ["release", "imageTag", "activatedAt"]) { + if (!isNonEmptyString(pointer[key])) throw invalid(`needs a non-empty string "${key}"`); + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D21.txt b/agents/darkwing/work/queue-56-review/r2/mut/D21.txt new file mode 100644 index 00000000..8f199ab4 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D21.txt @@ -0,0 +1,68 @@ +✔ isRunId accepts the run id shape and nothing else (1.070238ms) +✔ a missing data root or runs directory lists nothing (15.238793ms) +✔ runs as a regular file lists nothing, as before (0.630315ms) +✔ listRunIds keeps r- names only, sorted oldest first (0.749971ms) +✔ listRunRecords returns each result, or null for an incomplete or unreadable one (1.868706ms) +✔ readRunRecord returns documents and artifacts in directory order (0.975396ms) +✔ readRunRecord is null for a missing run, a dangling link or a file (0.713914ms) +✔ readRunRecord and readRunDocument refuse an invalid run id before touching the disk (0.676303ms) +✔ readRunDocument reads only the three run documents (0.521547ms) +✔ a link inside the data root is followed (0.939391ms) +✔ a data root that is itself a link is trusted as configured (0.658101ms) +✔ a run directory linked out of the data root is never read (0.61921ms) +✔ a document linked out of the data root reads as null (0.876784ms) +✔ a runs directory linked out of the data root refuses (0.544007ms) +✔ a relative link that climbs out of the data root refuses (0.387288ms) +✔ a sibling whose name starts with the data root's name is outside it (0.479327ms) +✔ a link loop refuses instead of reading as missing (0.619689ms) +✔ an unreadable runs directory refuses instead of listing nothing (0.410005ms) +✔ an unreadable run directory refuses instead of reading as missing (0.46599ms) +✔ a link to the data root's parent is outside it (0.377274ms) +✔ listRunIds sorts whatever order the directory returns (0.719835ms) +✔ listRunRecords lists an r- name that isn't a valid run id, as before (0.463838ms) +✔ the readers write nothing (12.891696ms) +✔ no pointer is null (13.84385ms) +✔ the pointer release.sh writes reads back (1.126812ms) +✖ a pointer that isn't the version 1 shape refuses with exit 2 (78.389391ms) +✔ a pointer that is a directory refuses with exit 4 (1.045036ms) +✔ a state file linked out of the data root refuses (2.729789ms) +✔ a state directory linked out of the data root refuses (0.95196ms) +✔ a state directory linked out to nothing reads as no release and an empty log (0.776137ms) +✔ a missing log is empty (0.563476ms) +✔ the log reads oldest first and counts malformed lines (6.585745ms) +✔ last must be a positive integer (0.943606ms) +✔ the state readers write nothing (0.995233ms) +✔ list prints each run in the established format (95.360894ms) +✔ show prints the run in the established format (99.253996ms) +✔ show of a missing run and an invalid id exit 4 as before (122.191371ms) +✔ list and show refuse a runs directory linked out of the data root (188.490155ms) +✔ show refuses a run linked out of the data root; list reports it unknown (171.206385ms) +✔ list shows an r- name that isn't a valid run id, as before (96.606326ms) +✔ show refuses an invalid id before reading the config (48.391711ms) +ℹ tests 41 +ℹ suites 0 +ℹ pass 40 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 886.752441 + +✖ failing tests: + +test at packages/runs/tests/state.test.mjs:32:1 +✖ a pointer that isn't the version 1 shape refuses with exit 2 (78.389391ms) + AssertionError [ERR_ASSERTION]: Missing expected exception: /unsupported pointerVersion 2/ + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/state.test.mjs:47:12) + at Test.runInAsyncScope (node:async_hooks:226:14) + at Test.run (node:internal/test_runner/test:1402:25) + at Test.processPendingSubtests (node:internal/test_runner/test:974:18) + at Test.postRun (node:internal/test_runner/test:1542:19) + at Test.run (node:internal/test_runner/test:1467:12) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: false, + code: 'ERR_ASSERTION', + actual: undefined, + operator: 'throws', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D22.diff b/agents/darkwing/work/queue-56-review/r2/mut/D22.diff new file mode 100644 index 00000000..fb7d2ba8 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D22.diff @@ -0,0 +1,13 @@ +diff --git a/packages/runs/src/state.mjs b/packages/runs/src/state.mjs +index af5cc927..2029992d 100644 +--- a/packages/runs/src/state.mjs ++++ b/packages/runs/src/state.mjs +@@ -55,7 +55,7 @@ function logEntry(line) { + } + if (typeof entry !== "object" || entry === null || Array.isArray(entry)) return null; + if (Object.keys(entry).some((key) => !LOG_KEYS.includes(key))) return null; +- if (!["at", "event", "release", "imageTag"].every((key) => typeof entry[key] === "string")) return null; ++ if (!["at", "event", "release"].every((key) => typeof entry[key] === "string")) return null; + if (entry.note !== undefined && typeof entry.note !== "string") return null; + return entry; + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D22.txt b/agents/darkwing/work/queue-56-review/r2/mut/D22.txt new file mode 100644 index 00000000..c306cc3a --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D22.txt @@ -0,0 +1,95 @@ +✔ isRunId accepts the run id shape and nothing else (1.252447ms) +✔ a missing data root or runs directory lists nothing (6.093709ms) +✔ runs as a regular file lists nothing, as before (1.075597ms) +✔ listRunIds keeps r- names only, sorted oldest first (1.214686ms) +✔ listRunRecords returns each result, or null for an incomplete or unreadable one (3.148367ms) +✔ readRunRecord returns documents and artifacts in directory order (1.124565ms) +✔ readRunRecord is null for a missing run, a dangling link or a file (0.746849ms) +✔ readRunRecord and readRunDocument refuse an invalid run id before touching the disk (1.009428ms) +✔ readRunDocument reads only the three run documents (0.573239ms) +✔ a link inside the data root is followed (1.02649ms) +✔ a data root that is itself a link is trusted as configured (0.812922ms) +✔ a run directory linked out of the data root is never read (1.139725ms) +✔ a document linked out of the data root reads as null (1.475949ms) +✔ a runs directory linked out of the data root refuses (0.79783ms) +✔ a relative link that climbs out of the data root refuses (0.644081ms) +✔ a sibling whose name starts with the data root's name is outside it (0.543714ms) +✔ a link loop refuses instead of reading as missing (0.716483ms) +✔ an unreadable runs directory refuses instead of listing nothing (0.471177ms) +✔ an unreadable run directory refuses instead of reading as missing (0.534855ms) +✔ a link to the data root's parent is outside it (0.400246ms) +✔ listRunIds sorts whatever order the directory returns (0.78587ms) +✔ listRunRecords lists an r- name that isn't a valid run id, as before (0.471629ms) +✔ the readers write nothing (2.396636ms) +✔ no pointer is null (1.913757ms) +✔ the pointer release.sh writes reads back (1.272056ms) +✔ a pointer that isn't the version 1 shape refuses with exit 2 (125.829499ms) +✔ a pointer that is a directory refuses with exit 4 (1.62796ms) +✔ a state file linked out of the data root refuses (1.042007ms) +✔ a state directory linked out of the data root refuses (0.558456ms) +✔ a state directory linked out to nothing reads as no release and an empty log (0.478057ms) +✔ a missing log is empty (0.450056ms) +✖ the log reads oldest first and counts malformed lines (2.013903ms) +✔ last must be a positive integer (0.569281ms) +✔ the state readers write nothing (0.848332ms) +✔ list prints each run in the established format (82.056594ms) +✔ show prints the run in the established format (115.447797ms) +✔ show of a missing run and an invalid id exit 4 as before (143.98818ms) +✔ list and show refuse a runs directory linked out of the data root (346.242982ms) +✔ show refuses a run linked out of the data root; list reports it unknown (230.004362ms) +✔ list shows an r- name that isn't a valid run id, as before (128.157444ms) +✔ show refuses an invalid id before reading the config (43.502473ms) +ℹ tests 41 +ℹ suites 0 +ℹ pass 40 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 1149.126501 + +✖ failing tests: + +test at packages/runs/tests/state.test.mjs:87:1 +✖ the log reads oldest first and counts malformed lines (2.013903ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: + + actual - expected + ... Skipped lines + + { + entries: [ + { + at: '2026-09-03T20:57:00Z', + event: 'package', + ... + { + + at: '2026-09-03T20:57:47Z', + + event: 'activate', + + release: '0.0.12' + + }, + + { + at: '2026-09-03T20:57:50Z', + event: 'refused', + imageTag: 'mosaic-poc-agent:0.84.4-r0.0.11', + note: 'health check failed (fault-injected)', + release: '0.0.11' + ... + ], + + malformed: 6 + - malformed: 7 + } + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/state.test.mjs:110: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: { entries: [ [Object], [Object], [Object], [Object], [Object] ], malformed: 6 }, + expected: { entries: [ [Object], [Object], [Object], [Object] ], malformed: 7 }, + operator: 'deepStrictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D23.diff b/agents/darkwing/work/queue-56-review/r2/mut/D23.diff new file mode 100644 index 00000000..e054b3e4 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D23.diff @@ -0,0 +1,13 @@ +diff --git a/packages/runs/src/state.mjs b/packages/runs/src/state.mjs +index af5cc927..0b58f712 100644 +--- a/packages/runs/src/state.mjs ++++ b/packages/runs/src/state.mjs +@@ -66,7 +66,7 @@ function logEntry(line) { + // rollback, which skips only lines that aren't JSON. A missing log is empty. + // With last, only the newest last well-formed entries are returned. + export function readActivationLog(dataRoot, { last } = {}) { +- if (last !== undefined && (!Number.isInteger(last) || last < 1)) { ++ if (last !== undefined && (!Number.isInteger(last) || last < 0)) { + throw new RunsError(`last must be a positive integer (got ${JSON.stringify(last)})`); + } + const state = readStateFile(dataRoot, ACTIVATION_LOG_FILE); diff --git a/agents/darkwing/work/queue-56-review/r2/mut/D23.txt b/agents/darkwing/work/queue-56-review/r2/mut/D23.txt new file mode 100644 index 00000000..8c2aa21a --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/D23.txt @@ -0,0 +1,69 @@ +✔ isRunId accepts the run id shape and nothing else (1.895901ms) +✔ a missing data root or runs directory lists nothing (19.117981ms) +✔ runs as a regular file lists nothing, as before (1.156194ms) +✔ listRunIds keeps r- names only, sorted oldest first (2.786988ms) +✔ listRunRecords returns each result, or null for an incomplete or unreadable one (6.490428ms) +✔ readRunRecord returns documents and artifacts in directory order (3.065151ms) +✔ readRunRecord is null for a missing run, a dangling link or a file (1.740552ms) +✔ readRunRecord and readRunDocument refuse an invalid run id before touching the disk (2.297296ms) +✔ readRunDocument reads only the three run documents (1.292545ms) +✔ a link inside the data root is followed (2.752987ms) +✔ a data root that is itself a link is trusted as configured (1.709382ms) +✔ a run directory linked out of the data root is never read (7.227673ms) +✔ a document linked out of the data root reads as null (2.243894ms) +✔ a runs directory linked out of the data root refuses (1.063142ms) +✔ a relative link that climbs out of the data root refuses (0.744008ms) +✔ a sibling whose name starts with the data root's name is outside it (0.882094ms) +✔ a link loop refuses instead of reading as missing (1.142281ms) +✔ an unreadable runs directory refuses instead of listing nothing (3.150174ms) +✔ an unreadable run directory refuses instead of reading as missing (0.853351ms) +✔ a link to the data root's parent is outside it (0.651315ms) +✔ listRunIds sorts whatever order the directory returns (1.091854ms) +✔ listRunRecords lists an r- name that isn't a valid run id, as before (0.60074ms) +✔ the readers write nothing (3.036123ms) +✔ no pointer is null (14.514676ms) +✔ the pointer release.sh writes reads back (3.228549ms) +✔ a pointer that isn't the version 1 shape refuses with exit 2 (72.542192ms) +✔ a pointer that is a directory refuses with exit 4 (1.930314ms) +✔ a state file linked out of the data root refuses (1.407715ms) +✔ a state directory linked out of the data root refuses (0.738704ms) +✔ a state directory linked out to nothing reads as no release and an empty log (0.801635ms) +✔ a missing log is empty (0.664066ms) +✔ the log reads oldest first and counts malformed lines (2.17924ms) +✖ last must be a positive integer (1.668759ms) +✔ the state readers write nothing (2.415105ms) +✔ list prints each run in the established format (147.726988ms) +✔ show prints the run in the established format (108.731864ms) +✔ show of a missing run and an invalid id exit 4 as before (172.540569ms) +✔ list and show refuse a runs directory linked out of the data root (269.573796ms) +✔ show refuses a run linked out of the data root; list reports it unknown (185.736528ms) +✔ list shows an r- name that isn't a valid run id, as before (100.838017ms) +✔ show refuses an invalid id before reading the config (64.187937ms) +ℹ tests 41 +ℹ suites 0 +ℹ pass 40 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 1135.081876 + +✖ failing tests: + +test at packages/runs/tests/state.test.mjs:115:1 +✖ last must be a positive integer (1.668759ms) + AssertionError [ERR_ASSERTION]: Missing expected exception: 0 + at TestContext. (file:///home/jwoltje/darkwing-scratch/r56b/mutwt/packages/runs/tests/state.test.mjs:118:12) + at Test.runInAsyncScope (node:async_hooks:226:14) + at Test.run (node:internal/test_runner/test:1402:25) + at Test.processPendingSubtests (node:internal/test_runner/test:974:18) + at Test.postRun (node:internal/test_runner/test:1542:19) + at Test.run (node:internal/test_runner/test:1467:12) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: false, + code: 'ERR_ASSERTION', + actual: undefined, + expected: /last must be a positive integer/, + operator: 'throws', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-56-review/r2/mut/manifest-after.txt b/agents/darkwing/work/queue-56-review/r2/mut/manifest-after.txt new file mode 100644 index 00000000..5a406f60 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/manifest-after.txt @@ -0,0 +1,15 @@ +agents/rocko/work/queue-56/byte-check.sh: OK +agents/rocko/work/queue-56/delta-check.sh: OK +agents/rocko/work/queue-56/seed.sh: OK +packages/runs/package.json: OK +packages/runs/README.md: OK +packages/runs/src/errors.mjs: OK +packages/runs/src/index.mjs: OK +packages/runs/src/paths.mjs: OK +packages/runs/src/runs.mjs: OK +packages/runs/src/state.mjs: OK +packages/runs/tests/helpers.mjs: OK +packages/runs/tests/runs.test.mjs: OK +packages/runs/tests/state.test.mjs: OK +packages/runs/tests/task-cli.test.mjs: OK +scripts/mosaic-task.mjs: OK diff --git a/agents/darkwing/work/queue-56-review/r2/mut/mutate.py b/agents/darkwing/work/queue-56-review/r2/mut/mutate.py new file mode 100644 index 00000000..59da85f1 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/mutate.py @@ -0,0 +1,32 @@ +# mutate.py : apply one named mutant to the candidate (exact text, must match once). Run from the tree root. +import sys +P, R, T, X = "packages/runs/src/paths.mjs", "packages/runs/src/runs.mjs", "packages/runs/src/state.mjs", "scripts/mosaic-task.mjs" +M = { + "D01": [(X, " if (!isRunId(runId)) {\n fail(4, `invalid run id", " if (false) {\n fail(4, `invalid run id")], + "D03": [(P, " } catch {\n return null;\n }\n}", " } catch (error) {\n if (error instanceof RunsError) throw error;\n return null;\n }\n}")], + "D04": [(R, " if (resolveInside(dataRoot, RUNS_DIRNAME) === null) return null;\n", "")], + "D05": [(T, "entries.slice(-last)", "entries.slice(0, last)")], + "D06": [(T, ' if (entry.note !== undefined && typeof entry.note !== "string") return null;\n', "")], + "D07": [(R, " if (isMissing(error)) return [];\n throw new RunsError(`cannot read ${root}", " return [];\n throw new RunsError(`cannot read ${root}")], + "D08": [(T, " } catch (error) {\n throw new RunsError(`cannot read ${file}", " } catch (error) {\n return null;\n throw new RunsError(`cannot read ${file}")], + "D09": [(T, "if (!POINTER_KEYS.includes(key))", "if (false)")], + "D10": [(P, 'return relative === "" ||', "return false ||")], + "D11": [(X, "if (error instanceof RunsError) fail(error.exitCode, error.message);\n throw error;\n }\n}\n\nfunction listRuns", "if (false) fail(error.exitCode, error.message);\n throw error;\n }\n}\n\nfunction listRuns")], + "D13": [(R, " if (isMissing(error)) return null;\n throw new RunsError(`cannot read ${dir}", " throw new RunsError(`cannot read ${dir}")], + "D14": [(P, "real = fs.realpathSync(target);", "real = path.resolve(target);")], + "D15": [(P, "root = fs.realpathSync(dataRoot);", "root = path.resolve(dataRoot);")], + "D16": [(R, "{0,63}$/", "{0,64}$/")], + "D17": [(R, ' result: readJsonObject(dataRoot, RUNS_DIRNAME, runId, "result.json"),', ' result: readRunDocument(dataRoot, runId, "result.json"),')], + "D18": [(T, 'if (line.trim() === "") continue;', 'if (line === "") continue;')], + "D19": [(R, " requireRunId(runId);\n if (!RUN_DOCUMENTS", " if (!RUN_DOCUMENTS")], + "D20": [(R, 'filter((name) => name.startsWith("r-")).sort()', "filter(isRunId).sort()")], + "D21": [(T, "if (pointer.pointerVersion !== 1)", "if (false)")], + "D22": [(T, '["at", "event", "release", "imageTag"].every', '["at", "event", "release"].every')], + "D23": [(T, "last < 1)", "last < 0)")], +} +for f, old, new in M[sys.argv[1]]: + s = open(f).read() + n = s.count(old) + if n != 1: sys.exit(f"{sys.argv[1]}: {n} matches in {f}") + open(f, "w").write(s.replace(old, new)) +print(sys.argv[1], "applied") diff --git a/agents/darkwing/work/queue-56-review/r2/mut/run.sh b/agents/darkwing/work/queue-56-review/r2/mut/run.sh new file mode 100755 index 00000000..72f6a8d5 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/run.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# Each mutant against the packages/runs suite in a second candidate worktree, then restores from the index. +export TMPDIR=~/darkwing-scratch/r56b/tmp +S=~/darkwing-scratch/r56b; M=$S/mut; W=$S/mutwt +: > $M/summary.txt +echo "start $(date -u +%FT%TZ)" >> $M/summary.txt +for v in $(python3 -c 'import re;print(" ".join(sorted(set(re.findall(r"\"(D\d\d)\"", open("'$M'/mutate.py").read())))))'); do + (cd $W && git checkout -q -- packages scripts && python3 $M/mutate.py $v > /dev/null && git diff > $M/$v.diff) || { echo "$v APPLY-FAILED" >> $M/summary.txt; continue; } + (cd $W && env -u NODE_TEST_CONTEXT node --test packages/runs/tests/*.test.mjs > $M/$v.txt 2>&1); e=$? + r=killed; [ $e = 0 ] && r=SURVIVED + echo "$v $r exit=$e $(grep -E '^ℹ (pass|fail)' $M/$v.txt | tr '\n' ' ')" >> $M/summary.txt +done +(cd $W && git checkout -q -- packages scripts && sha256sum -c $S/pkt/candidate-manifest.sha256) > $M/manifest-after.txt 2>&1 +echo "end $(date -u +%FT%TZ)" >> $M/summary.txt +echo DONE >> $M/summary.txt diff --git a/agents/darkwing/work/queue-56-review/r2/mut/summary.txt b/agents/darkwing/work/queue-56-review/r2/mut/summary.txt new file mode 100644 index 00000000..b75b5553 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/mut/summary.txt @@ -0,0 +1,24 @@ +start 2026-10-10T17:12:08Z +D01 killed exit=1 ℹ pass 40 ℹ fail 1 +D03 killed exit=1 ℹ pass 37 ℹ fail 4 +D04 killed exit=1 ℹ pass 39 ℹ fail 2 +D05 killed exit=1 ℹ pass 40 ℹ fail 1 +D06 killed exit=1 ℹ pass 40 ℹ fail 1 +D07 killed exit=1 ℹ pass 40 ℹ fail 1 +D08 killed exit=1 ℹ pass 40 ℹ fail 1 +D09 killed exit=1 ℹ pass 40 ℹ fail 1 +D10 SURVIVED exit=0 ℹ pass 41 ℹ fail 0 +D11 killed exit=1 ℹ pass 39 ℹ fail 2 +D13 killed exit=1 ℹ pass 40 ℹ fail 1 +D14 killed exit=1 ℹ pass 27 ℹ fail 14 +D15 killed exit=1 ℹ pass 40 ℹ fail 1 +D16 killed exit=1 ℹ pass 40 ℹ fail 1 +D17 killed exit=1 ℹ pass 39 ℹ fail 2 +D18 killed exit=1 ℹ pass 40 ℹ fail 1 +D19 killed exit=1 ℹ pass 40 ℹ fail 1 +D20 killed exit=1 ℹ pass 39 ℹ fail 2 +D21 killed exit=1 ℹ pass 40 ℹ fail 1 +D22 killed exit=1 ℹ pass 40 ℹ fail 1 +D23 killed exit=1 ℹ pass 40 ℹ fail 1 +end 2026-10-10T17:12:34Z +DONE diff --git a/agents/darkwing/work/queue-56-review/r2/out/byte-check.txt b/agents/darkwing/work/queue-56-review/r2/out/byte-check.txt new file mode 100644 index 00000000..483b79c9 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/out/byte-check.txt @@ -0,0 +1,2 @@ +byte-check: 16 cases, stdout, stderr and exit identical +byte-check: data root unchanged diff --git a/agents/darkwing/work/queue-56-review/r2/out/delta-check.txt b/agents/darkwing/work/queue-56-review/r2/out/delta-check.txt new file mode 100644 index 00000000..11048dca --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/out/delta-check.txt @@ -0,0 +1,118 @@ + +== run directory linked out of the data root: list + base: exit 0 + out| r-20260101T000000Z-aaaaaa succeeded task=t-out ws=- session=- + cand: exit 0 + out| r-20260101T000000Z-aaaaaa unknown task=- ws=- session=- + +== run directory linked out of the data root: show + base: exit 0 + out| run: r-20260101T000000Z-aaaaaa + out| status: succeeded + out| task: t-out + out| adapter: (see config) provider=p model=m + out| request: "r" + out| response: "s" + out| timing: a -> b (1 ms) + out| exit: 0 + out| artifacts: result.json + cand: exit 4 + err| mosaic-task: /home/jwoltje/darkwing-scratch/r56b/dc/run-link/data/runs/r-20260101T000000Z-aaaaaa resolves outside the data root (/home/jwoltje/darkwing-scratch/r56b/dc/run-link/data) + +== result.json linked out of the data root: list + base: exit 0 + out| r-20260101T000000Z-aaaaaa succeeded task=t-out ws=- session=- + cand: exit 0 + out| r-20260101T000000Z-aaaaaa unknown task=- ws=- session=- + +== result.json linked out of the data root: show + base: exit 0 + out| run: r-20260101T000000Z-aaaaaa + out| status: succeeded + out| task: t-out + out| adapter: (see config) provider=p model=m + out| request: "r" + out| response: "s" + out| timing: a -> b (1 ms) + out| exit: 0 + out| artifacts: result.json + cand: exit 0 + out| run: r-20260101T000000Z-aaaaaa + out| result.json: (missing or unreadable) + out| artifacts: result.json + +== runs directory linked out of the data root: list + base: exit 0 + out| r-20260101T000000Z-aaaaaa succeeded task=t-out ws=- session=- + cand: exit 4 + err| mosaic-task: /home/jwoltje/darkwing-scratch/r56b/dc/runs-link/data/runs resolves outside the data root (/home/jwoltje/darkwing-scratch/r56b/dc/runs-link/data) + +== runs directory linked out of the data root: show + base: exit 0 + out| run: r-20260101T000000Z-aaaaaa + out| status: succeeded + out| task: t-out + out| adapter: (see config) provider=p model=m + out| request: "r" + out| response: "s" + out| timing: a -> b (1 ms) + out| exit: 0 + out| artifacts: result.json + cand: exit 4 + err| mosaic-task: /home/jwoltje/darkwing-scratch/r56b/dc/runs-link/data/runs resolves outside the data root (/home/jwoltje/darkwing-scratch/r56b/dc/runs-link/data) + +== result.json is 5 and task.json is []: list + base: exit 1 + err| file:///home/jwoltje/darkwing-scratch/r56b/base/scripts/mosaic-task.mjs:483 + cand: exit 0 + out| r-20260101T000000Z-aaaaaa unknown task=- ws=- session=- + +== result.json is 5 and task.json is []: show + base: exit 0 + out| run: r-20260101T000000Z-aaaaaa + out| status: undefined + out| task: undefined + out| adapter: (see config) provider=undefined model=undefined + out| request: undefined + out| response: undefined + out| timing: undefined -> undefined (undefined ms) + out| exit: undefined + out| task snapshot: task.json present + out| artifacts: result.json, task.json + cand: exit 0 + out| run: r-20260101T000000Z-aaaaaa + out| result.json: (missing or unreadable) + out| artifacts: result.json, task.json + +== run is a regular file: show + base: exit 1 + out| run: r-20260101T000000Z-aaaaaa + out| result.json: (missing or unreadable) + err| node:fs:1954 + cand: exit 4 + err| mosaic-task: run not found: r-20260101T000000Z-aaaaaa (under /home/jwoltje/darkwing-scratch/r56b/dc/run-file/data/runs) + +== run is a link loop: show + base: exit 4 + err| mosaic-task: run not found: r-20260101T000000Z-aaaaaa (under /home/jwoltje/darkwing-scratch/r56b/dc/loop/data/runs) + cand: exit 4 + err| mosaic-task: cannot resolve /home/jwoltje/darkwing-scratch/r56b/dc/loop/data/runs/r-20260101T000000Z-aaaaaa: ELOOP + +== runs directory unreadable: list + base: exit 0 + cand: exit 4 + err| mosaic-task: cannot read /home/jwoltje/darkwing-scratch/r56b/dc/unreadable/data/runs: EACCES + +== runs directory unreadable: show + base: exit 4 + err| mosaic-task: run not found: r-20260101T000000Z-aaaaaa (under /home/jwoltje/darkwing-scratch/r56b/dc/unreadable/data/runs) + cand: exit 4 + err| mosaic-task: cannot resolve /home/jwoltje/darkwing-scratch/r56b/dc/unreadable/data/runs/r-20260101T000000Z-aaaaaa: EACCES + +== run directory unreadable: show + base: exit 1 + out| run: r-20260101T000000Z-aaaaaa + out| result.json: (missing or unreadable) + err| node:fs:1954 + cand: exit 4 + err| mosaic-task: cannot read /home/jwoltje/darkwing-scratch/r56b/dc/run-unreadable/data/runs/r-20260101T000000Z-aaaaaa: EACCES diff --git a/agents/darkwing/work/queue-56-review/r2/out/node-runs.txt b/agents/darkwing/work/queue-56-review/r2/out/node-runs.txt new file mode 100644 index 00000000..71d47f97 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/out/node-runs.txt @@ -0,0 +1,49 @@ +✔ isRunId accepts the run id shape and nothing else (0.845764ms) +✔ a missing data root or runs directory lists nothing (1.27599ms) +✔ runs as a regular file lists nothing, as before (0.481538ms) +✔ listRunIds keeps r- names only, sorted oldest first (0.620424ms) +✔ listRunRecords returns each result, or null for an incomplete or unreadable one (1.641509ms) +✔ readRunRecord returns documents and artifacts in directory order (0.822114ms) +✔ readRunRecord is null for a missing run, a dangling link or a file (0.561666ms) +✔ readRunRecord and readRunDocument refuse an invalid run id before touching the disk (0.531563ms) +✔ readRunDocument reads only the three run documents (0.427644ms) +✔ a link inside the data root is followed (0.795518ms) +✔ a data root that is itself a link is trusted as configured (0.549674ms) +✔ a run directory linked out of the data root is never read (0.551772ms) +✔ a document linked out of the data root reads as null (0.799823ms) +✔ a runs directory linked out of the data root refuses (0.528601ms) +✔ a relative link that climbs out of the data root refuses (0.359757ms) +✔ a sibling whose name starts with the data root's name is outside it (0.428236ms) +✔ a link loop refuses instead of reading as missing (0.558513ms) +✔ an unreadable runs directory refuses instead of listing nothing (0.397344ms) +✔ an unreadable run directory refuses instead of reading as missing (0.438001ms) +✔ a link to the data root's parent is outside it (0.427799ms) +✔ listRunIds sorts whatever order the directory returns (0.733867ms) +✔ listRunRecords lists an r- name that isn't a valid run id, as before (0.434006ms) +✔ the readers write nothing (1.814734ms) +✔ no pointer is null (1.605828ms) +✔ the pointer release.sh writes reads back (0.95797ms) +✔ a pointer that isn't the version 1 shape refuses with exit 2 (357.065646ms) +✔ a pointer that is a directory refuses with exit 4 (0.599972ms) +✔ a state file linked out of the data root refuses (0.819613ms) +✔ a state directory linked out of the data root refuses (0.470093ms) +✔ a state directory linked out to nothing reads as no release and an empty log (0.414246ms) +✔ a missing log is empty (46.073141ms) +✔ the log reads oldest first and counts malformed lines (1.021399ms) +✔ last must be a positive integer (0.452181ms) +✔ the state readers write nothing (0.734058ms) +✔ list prints each run in the established format (68.62278ms) +✔ show prints the run in the established format (65.989299ms) +✔ show of a missing run and an invalid id exit 4 as before (276.117437ms) +✔ list and show refuse a runs directory linked out of the data root (185.491853ms) +✔ show refuses a run linked out of the data root; list reports it unknown (215.611415ms) +✔ list shows an r- name that isn't a valid run id, as before (100.451058ms) +✔ show refuses an invalid id before reading the config (51.977553ms) +ℹ tests 41 +ℹ suites 0 +ℹ pass 41 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 1017.118046 diff --git a/agents/darkwing/work/queue-56-review/r2/out/probes.txt b/agents/darkwing/work/queue-56-review/r2/out/probes.txt new file mode 100644 index 00000000..410e67c2 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/out/probes.txt @@ -0,0 +1,27 @@ + +== Q1 runs/ linked out of the data root to nothing: list + base: exit 0 + cand: exit 0 + +== Q1 same: show + base: exit 4 + err| mosaic-task: run not found: r-20260101T000000Z-aaaaaa (under /home/jwoltje/darkwing-scratch/r56b/probes/q1/data/runs) + cand: exit 4 + err| mosaic-task: run not found: r-20260101T000000Z-aaaaaa (under /home/jwoltje/darkwing-scratch/r56b/probes/q1/data/runs) + +== Q2 runs/ linked out to an empty directory that exists: list + base: exit 0 + cand: exit 4 + err| mosaic-task: /home/jwoltje/darkwing-scratch/r56b/probes/q2/data/runs resolves outside the data root (/home/jwoltje/darkwing-scratch/r56b/probes/q2/data) + +== Q3 state/ linked out to nothing (candidate module) + readActivePointer: null + readActivationLog: {"entries":[],"malformed":0} + +== Q4 state/ linked out to an empty directory that exists (round 1 P5) + readActivePointer: null + readActivationLog: {"entries":[],"malformed":0} + +== Q4b same, with active.json there + readActivePointer: RunsError 4 /home/jwoltje/darkwing-scratch/r56b/probes/q4/data/state/active.json resolves outside the data root (/home/jwoltje/darkwing-scratch/r56b/probes/q4/data) + readActivationLog: {"entries":[],"malformed":0} diff --git a/agents/darkwing/work/queue-56-review/r2/out/src-against-r1.txt b/agents/darkwing/work/queue-56-review/r2/out/src-against-r1.txt new file mode 100644 index 00000000..364bc018 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/out/src-against-r1.txt @@ -0,0 +1,7 @@ +packages/runs/src/errors.mjs: OK +packages/runs/src/index.mjs: OK +packages/runs/src/paths.mjs: OK +packages/runs/src/runs.mjs: OK +packages/runs/src/state.mjs: FAILED +scripts/mosaic-task.mjs: OK +sha256sum: WARNING: 1 computed checksum did NOT match diff --git a/agents/darkwing/work/queue-56-review/r2/out/src-diff.txt b/agents/darkwing/work/queue-56-review/r2/out/src-diff.txt new file mode 100644 index 00000000..14f03d1c --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/out/src-diff.txt @@ -0,0 +1,12 @@ +diff -r /home/jwoltje/darkwing-scratch/r56b/r1tree/packages/runs/src/state.mjs /home/jwoltje/darkwing-scratch/r56b/cand/packages/runs/src/state.mjs +63,66c63,67 +< // The activation log as { entries, malformed }, oldest first. Lines that +< // aren't a well-formed entry are counted in malformed and skipped, the way +< // release.sh rollback skips them. A missing log is empty. With last, only +< // the newest last well-formed entries are returned. +--- +> // The activation log as { entries, malformed }, oldest first. A line that +> // isn't JSON, or is JSON but not the entry shape release.sh writes, is +> // counted in malformed and skipped. This is stricter than release.sh +> // rollback, which skips only lines that aren't JSON. A missing log is empty. +> // With last, only the newest last well-formed entries are returned. diff --git a/agents/darkwing/work/queue-56-review/r2/out/summary.txt b/agents/darkwing/work/queue-56-review/r2/out/summary.txt new file mode 100644 index 00000000..4469a220 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/out/summary.txt @@ -0,0 +1,13 @@ +start 2026-10-10T17:12:07Z +node-runs exit=0 ℹ pass 41 ℹ 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=1 discord suite: 65 passed, 1 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-10T17:14:22Z +DONE diff --git a/agents/darkwing/work/queue-56-review/r2/out/test-auth.txt b/agents/darkwing/work/queue-56-review/r2/out/test-auth.txt new file mode 100644 index 00000000..ac228760 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/out/test-auth.txt @@ -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 diff --git a/agents/darkwing/work/queue-56-review/r2/out/test-conductor.txt b/agents/darkwing/work/queue-56-review/r2/out/test-conductor.txt new file mode 100644 index 00000000..c68d1f3e --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/out/test-conductor.txt @@ -0,0 +1,55 @@ +Note: switching to '75ab164698176178f196009f14f994e0192048a7'. + +You are in 'detached HEAD' state. You can look around, make experimental +changes and commit them, and you can discard any commits you make in this +state without impacting any branches by switching back to a branch. + +If you want to create a new branch to retain commits you create, you may +do so (now or later) by using -c with the switch command. Example: + + git switch -c + +Or undo this operation with: + + git switch - + +Turn off this advice by setting config variable advice.detachedHead to false + +Not currently on any branch. +nothing to commit, working tree clean +Note: switching to '75ab164698176178f196009f14f994e0192048a7'. + +You are in 'detached HEAD' state. You can look around, make experimental +changes and commit them, and you can discard any commits you make in this +state without impacting any branches by switching back to a branch. + +If you want to create a new branch to retain commits you create, you may +do so (now or later) by using -c with the switch command. Example: + + git switch -c + +Or undo this operation with: + + git switch - + +Turn off this advice by setting config variable advice.detachedHead to false + +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 diff --git a/agents/darkwing/work/queue-56-review/r2/out/test-config.txt b/agents/darkwing/work/queue-56-review/r2/out/test-config.txt new file mode 100644 index 00000000..76c05ef7 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/out/test-config.txt @@ -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 diff --git a/agents/darkwing/work/queue-56-review/r2/out/test-discord-r2.txt b/agents/darkwing/work/queue-56-review/r2/out/test-discord-r2.txt new file mode 100644 index 00000000..b013f9ff --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/out/test-discord-r2.txt @@ -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 diff --git a/agents/darkwing/work/queue-56-review/r2/out/test-discord.txt b/agents/darkwing/work/queue-56-review/r2/out/test-discord.txt new file mode 100644 index 00000000..284fdf6a --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/out/test-discord.txt @@ -0,0 +1,74 @@ +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 +FAIL node --test packages/discord/tests/ (ℹ pass 177) +✖ engine: when pi has not started a timed-out turn by the end of the abort grace, the engine stops pi and fails held prompts (309.121655ms) +✖ failing tests: +✖ engine: when pi has not started a timed-out turn by the end of the abort grace, the engine stops pi and fails held prompts (309.121655ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: +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: 65 passed, 1 failed diff --git a/agents/darkwing/work/queue-56-review/r2/out/test-extension-package.txt b/agents/darkwing/work/queue-56-review/r2/out/test-extension-package.txt new file mode 100644 index 00000000..e35ac8f7 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/out/test-extension-package.txt @@ -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: 1178504 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 diff --git a/agents/darkwing/work/queue-56-review/r2/out/test-foundation.txt b/agents/darkwing/work/queue-56-review/r2/out/test-foundation.txt new file mode 100644 index 00000000..6338e1e6 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/out/test-foundation.txt @@ -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 diff --git a/agents/darkwing/work/queue-56-review/r2/out/test-queue.txt b/agents/darkwing/work/queue-56-review/r2/out/test-queue.txt new file mode 100644 index 00000000..85374ca0 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/out/test-queue.txt @@ -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/r56b/cand) is not the queue's canonical root (/mnt/storage/src/mosaic-stack) + +queue suite: 27 passed, 0 failed diff --git a/agents/darkwing/work/queue-56-review/r2/out/test-release-docker.txt b/agents/darkwing/work/queue-56-review/r2/out/test-release-docker.txt new file mode 100644 index 00000000..7202b85d --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/out/test-release-docker.txt @@ -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 diff --git a/agents/darkwing/work/queue-56-review/r2/out/test-release.txt b/agents/darkwing/work/queue-56-review/r2/out/test-release.txt new file mode 100644 index 00000000..1d6ed050 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/out/test-release.txt @@ -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 diff --git a/agents/darkwing/work/queue-56-review/r2/out/test-task.txt b/agents/darkwing/work/queue-56-review/r2/out/test-task.txt new file mode 100644 index 00000000..cd89fe9b --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/out/test-task.txt @@ -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 diff --git a/agents/darkwing/work/queue-56-review/r2/probes.sh b/agents/darkwing/work/queue-56-review/r2/probes.sh new file mode 100755 index 00000000..b7d66aa6 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/r2/probes.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# Row 56 round 2 probes: the README's link wording for runs/ and state/, base against candidate. +export TMPDIR=~/darkwing-scratch/r56b/tmp +S=~/darkwing-scratch/r56b; W=$S/probes; rm -rf $W; mkdir -p $W +A=r-20260101T000000Z-aaaaaa +root() { mkdir -p "$W/$1/data" "$W/$1/outside"; printf '{"configVersion":1,"environment":"development","dataRoot":"%s","execution":{"backend":"docker","provider":"zai","model":"m"}}\n' "$W/$1/data" > "$W/$1/config.json"; echo "$W/$1/data"; } +run_case() { local name="$1" cfg="$2"; shift 2 + for tree in base cand; do + local rc=0 out + out="$(cd $S/$tree && env -u NODE_TEST_CONTEXT MOSAIC_CONFIG="$cfg" node scripts/mosaic-task.mjs "$@" 2>"$W/$name.$tree.err")" || rc=$? + printf ' %s: exit %s\n' "$tree" "$rc"; [ -z "$out" ] || printf '%s\n' "$out" | sed 's/^/ out| /' + [ -s "$W/$name.$tree.err" ] && head -1 "$W/$name.$tree.err" | sed 's/^/ err| /' + done; } +state_case() { + (cd $S/cand && node -e ' +import("./packages/runs/src/index.mjs").then((m) => { + for (const f of ["readActivePointer", "readActivationLog"]) { + try { console.log(" " + f + ": " + JSON.stringify(m[f](process.argv[1]))); } catch (e) { console.log(" " + f + ": " + e.name + " " + e.exitCode + " " + e.message); } + } +});' "$1"); } +hdr() { printf '\n== %s\n' "$*"; } + +D="$(root q1)"; ln -s "$W/q1/outside/absent" "$D/runs" +hdr "Q1 runs/ linked out of the data root to nothing: list"; run_case q1l "$W/q1/config.json" list +hdr "Q1 same: show"; run_case q1s "$W/q1/config.json" show "$A" + +D="$(root q2)"; ln -s "$W/q2/outside" "$D/runs" +hdr "Q2 runs/ linked out to an empty directory that exists: list"; run_case q2 "$W/q2/config.json" list + +D="$(root q3)"; ln -s "$W/q3/outside/absent" "$D/state" +hdr "Q3 state/ linked out to nothing (candidate module)"; state_case "$D" + +D="$(root q4)"; ln -s "$W/q4/outside" "$D/state" +hdr "Q4 state/ linked out to an empty directory that exists (round 1 P5)"; state_case "$D" +printf '{"pointerVersion":1,"release":"x","imageTag":"y","activatedAt":"z"}\n' > "$W/q4/outside/active.json" +hdr "Q4b same, with active.json there"; state_case "$D" diff --git a/agents/darkwing/work/queue-56-review/review-r2.md b/agents/darkwing/work/queue-56-review/review-r2.md new file mode 100644 index 00000000..29e926c2 --- /dev/null +++ b/agents/darkwing/work/queue-56-review/review-r2.md @@ -0,0 +1,154 @@ +# Row 56, runs and releases reader, round 2 review (Darkwing) + +Issue #1545, request comment 27120, queue revs 350-354. Base `75ab1646`. +Candidate manifest sha256 +`2727198f7e50b935205546a60ea97d8d4f20d87cad2a88e10477148c8d3dc42e`, +`build.patch` sha256 `d2fa5fb7…`. Both match comment 27120, and the +packet manifest checks clean. This is the delta review Sage asked for, +against round 1 (`ed3c5392`, my approval in comment 27115). + +Verdict: **approve**. `src/` and `scripts/mosaic-task.mjs` are the round 1 +bytes apart from one comment in `state.mjs`. D01 (Rocko's M31), D17, D20 +and D22 now die on assertions in the new tests. Every suite is green. The +README fixes for my notes 4b and 4c are right. The fix for 4a is half +right: it covers a `state/` link to nothing, and the sentence above it +still says a `state/` link out refuses, which isn't what happens when the +link points at a directory that exists. That is wording, nothing outside +is read, and I don't think it needs a round 3. + +## Method + +- Detached worktrees at `75ab1646`: `base`, `cand` and `mutwt`, the last + two with `git apply --index build.patch`, then `sha256sum -c` on the + manifest, 15 OK each. `mutwt` still checks 15 OK after the mutant runs + (`r2/mut/manifest-after.txt`). +- A fourth worktree at `dc96f87b` with round 1's `build.patch` applied + (15 OK against `ed3c5392`). `diff -r` of `packages/runs/src` and `cmp` + of `scripts/mosaic-task.mjs` against the round 2 candidate + (`r2/out/src-diff.txt`, `r2/out/src-against-r1.txt`). +- `diff -u` of the three test files, the README and `delta-check.sh` + against round 1. The result matches `out/round2-delta.diff`. +- `r2/gate.sh`: the packages/runs suite, then every `scripts/test-*.sh` + with `DOCKER_HOST=unix:///nonexistent.sock`, 17:12:07Z to 17:14:22Z. +- Round 1's 21 mutants, unchanged (`r2/mut/mutate.py`, `r2/mut/run.sh`), + 17:12:08Z to 17:12:34Z in `mutwt`, alongside the gate. +- Rocko's `byte-check.sh` and `delta-check.sh` from the candidate, base + against candidate, work directories in my scratch. +- Four probes of the README's new link wording (`r2/probes.sh`, output in + `r2/out/probes.txt`). +- `test-release` with Docker, 17:14:45Z to 17:15:08Z. + +Node v26.8.1, `TMPDIR=~/darkwing-scratch/r56b/tmp`. + +## src/ against round 1 + +Five of the six files are byte-identical. `state.mjs` differs only in the +comment above `readActivationLog`: + +``` +// The activation log as { entries, malformed }, oldest first. A line that +// isn't JSON, or is JSON but not the entry shape release.sh writes, is +// counted in malformed and skipped. This is stricter than release.sh +// rollback, which skips only lines that aren't JSON. A missing log is empty. +// With last, only the newest last well-formed entries are returned. +``` + +That matches `release.sh` lines 91-99: rollback drops empty lines, skips +lines `JSON.parse` rejects, and uses the newest `activate` or `rollback` +entry whose `imageTag` is truthy and differs from the current one. + +## Suites + +| Suite | Result | +|---|---| +| packages/runs (node) | 41/0 | +| test-auth | 15/0 | +| test-conductor | 17/0 | +| test-config | 24/0 | +| test-discord | 65/1 in the gate, 66/0 alone (below) | +| test-extension-package | 18/0 | +| test-foundation | 44/0 | +| test-queue | 27/0 | +| test-release | 4/0 without Docker, 14/0 with it | +| test-task, Docker unreachable | 26/0 | +| byte-check.sh | 16 cases identical, data root unchanged | +| delta-check.sh | 13 cases, same as Rocko's apart from scratch paths | + +The test-discord failure in the gate was "engine: when pi has not started +a timed-out turn by the end of the abort grace, the engine stops pi and +fails held prompts", a timing test that ran while the mutants and checks +were loading the machine. The candidate changes nothing under +`packages/discord`. A rerun on its own at 17:14:31Z gave 66/0 +(`r2/out/test-discord-r2.txt`). + +I didn't run test-task with real Docker, because it makes live model +calls. Round 2 doesn't touch `mosaic-task.mjs`, and Rocko's run gave 98/0. + +## Mutants + +20 of 21 killed (`r2/mut/summary.txt`). Only D10 survives, which I said in +round 1 needs no test. + +| Mutant | Round 1 | Round 2, killed by | +|---|---|---| +| D01 (M31) | survived | "show refuses an invalid id before reading the config": exit 3, `configuration problem` | +| D17 | survived | "listRunRecords lists an r- name that isn't a valid run id, as before" and the CLI `list` test: exit 4, `invalid run id: "r-.bad"` | +| D20 | survived | the same two tests: the list comes back empty | +| D22 | survived | "the log reads oldest first and counts malformed lines": the entry with no `imageTag` shows up in `entries` | + +Each is an `AssertionError` from the new assertions, not a load or +reference error. + +## Wording + +| Note | Fixed? | +|---|---| +| 4b, the "like rollback" comparison (Filbert's N1) | yes, in the README and the `state.mjs` comment, and both now match `release.sh` | +| 4c, no delta row for an unreadable run directory | yes: a README row and a `delta-check.sh` case. Base prints two lines and crashes, exit 1; the candidate refuses with EACCES, exit 4 | +| Filbert's N2, `release` as a string | yes: `{ ...good[1], release: 5 }` is now in the malformed lines | +| 4a, `state/` linked out | half: see below | + +The README still says "`runs/` or `state/` resolving outside refuses with a +`RunsError`". The new paragraph after the list says a `state/` link out +"to a path that doesn't exist" reads as no release and an empty log, and +the new test covers that case. My round 1 probe P5 linked `state/` to a +directory that exists, and that case still contradicts the bullet: + +| Probe | Candidate | +|---|---| +| Q1 `runs/` linked out to nothing | `list` prints nothing, exit 0; `show` says `run not found`, exit 4. Base does the same | +| Q2 `runs/` linked out to an empty directory that exists | `list` refuses, exit 4 (base: nothing, exit 0) | +| Q3 `state/` linked out to nothing | pointer `null`, log empty | +| Q4 `state/` linked out to an empty directory that exists | pointer `null`, log empty, no refusal | +| Q4b the same, with `active.json` there | `readActivePointer` refuses, exit 4 | + +The module never resolves `state/` itself, only `state/active.json` and +`state/activation-log.jsonl`. So a `state/` link out refuses only once one +of those files exists behind it. A sentence that says so would fix it, +for example: "`runs/` resolving outside refuses. `state/` isn't resolved +on its own; `active.json` or `activation-log.jsonl` resolving outside +refuses, and while neither exists a `state/` link out reads as no release +and an empty log." The invariant holds either way, because nothing outside +the data root is read. + +## Notes (not blocking) + +1. The 4a wording above. It can ride with the `padEnd` follow-up or any + later change to this README. I don't want a round 3 for it. +2. BUILD.md describes rollback as acting on "any parsed `activate` or + `rollback` entry with a truthy `imageTag`". It also skips the entry + whose `imageTag` equals the current one. The README and the comment + don't make that claim, so only the packet is affected. +3. Correction to my round 1 review: it said "17 of 22 killed". `mutate.py` + defines 21 mutants (there is no D02 or D12), and 16 of them were + killed in round 1. The five survivors I listed were right. + +## Files + +- `r2/candidate-manifest.sha256`: copy of Rocko's. +- `r2/gate.sh`, `r2/out/`: suite runs, `summary.txt`, the test-discord + rerun, byte and delta checks, test-release with Docker, the `src/` + comparison with round 1, and the probe output. +- `r2/mut/`: round 1's mutant definitions and runner, diffs, outputs, + `summary.txt` and the manifest check after the runs. +- `r2/probes.sh`: Q1 to Q4b.