From d277234237463f5e4c76ef47131c1362d0db9be9 Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Sat, 10 Oct 2026 14:05:29 -0500 Subject: [PATCH] review(53): Darkwing round 2, request changes (#1542 comment 27165) Co-Authored-By: Claude Opus 5.5 --- .../r2/candidate-manifest.sha256 | 16 + .../darkwing/work/queue-53-review/r2/gate.sh | 18 + .../work/queue-53-review/r2/mut/M01.diff | 13 + .../work/queue-53-review/r2/mut/M01.txt | 47 +++ .../work/queue-53-review/r2/mut/M02.diff | 13 + .../work/queue-53-review/r2/mut/M02.txt | 59 +++ .../work/queue-53-review/r2/mut/M03.diff | 13 + .../work/queue-53-review/r2/mut/M03.txt | 56 +++ .../work/queue-53-review/r2/mut/M04.diff | 13 + .../work/queue-53-review/r2/mut/M04.txt | 58 +++ .../work/queue-53-review/r2/mut/M05.diff | 13 + .../work/queue-53-review/r2/mut/M05.txt | 89 ++++ .../work/queue-53-review/r2/mut/M06.diff | 13 + .../work/queue-53-review/r2/mut/M06.txt | 56 +++ .../work/queue-53-review/r2/mut/M07.diff | 13 + .../work/queue-53-review/r2/mut/M07.txt | 36 ++ .../work/queue-53-review/r2/mut/M08.diff | 13 + .../work/queue-53-review/r2/mut/M08.txt | 56 +++ .../work/queue-53-review/r2/mut/M09.diff | 13 + .../work/queue-53-review/r2/mut/M09.txt | 56 +++ .../work/queue-53-review/r2/mut/M10.diff | 13 + .../work/queue-53-review/r2/mut/M10.txt | 53 +++ .../work/queue-53-review/r2/mut/M11.diff | 13 + .../work/queue-53-review/r2/mut/M11.txt | 56 +++ .../work/queue-53-review/r2/mut/M12.diff | 13 + .../work/queue-53-review/r2/mut/M12.txt | 56 +++ .../work/queue-53-review/r2/mut/M13.diff | 12 + .../work/queue-53-review/r2/mut/M13.txt | 55 +++ .../work/queue-53-review/r2/mut/M14.diff | 13 + .../work/queue-53-review/r2/mut/M14.txt | 56 +++ .../work/queue-53-review/r2/mut/M15.diff | 13 + .../work/queue-53-review/r2/mut/M15.txt | 53 +++ .../work/queue-53-review/r2/mut/M16.diff | 13 + .../work/queue-53-review/r2/mut/M16.txt | 58 +++ .../work/queue-53-review/r2/mut/M17.diff | 13 + .../work/queue-53-review/r2/mut/M17.txt | 48 +++ .../work/queue-53-review/r2/mut/M18.diff | 13 + .../work/queue-53-review/r2/mut/M18.txt | 56 +++ .../work/queue-53-review/r2/mut/M19.diff | 13 + .../work/queue-53-review/r2/mut/M19.txt | 56 +++ .../work/queue-53-review/r2/mut/M20.diff | 13 + .../work/queue-53-review/r2/mut/M20.txt | 59 +++ .../work/queue-53-review/r2/mut/M21.diff | 13 + .../work/queue-53-review/r2/mut/M21.txt | 56 +++ .../work/queue-53-review/r2/mut/M22.diff | 13 + .../work/queue-53-review/r2/mut/M22.txt | 47 +++ .../work/queue-53-review/r2/mut/M23.diff | 12 + .../work/queue-53-review/r2/mut/M23.txt | 56 +++ .../work/queue-53-review/r2/mut/M24.diff | 13 + .../work/queue-53-review/r2/mut/M24.txt | 47 +++ .../work/queue-53-review/r2/mut/M25.diff | 13 + .../work/queue-53-review/r2/mut/M25.txt | 56 +++ .../work/queue-53-review/r2/mut/M26.diff | 13 + .../work/queue-53-review/r2/mut/M26.txt | 59 +++ .../work/queue-53-review/r2/mut/M27.diff | 12 + .../work/queue-53-review/r2/mut/M27.txt | 58 +++ .../work/queue-53-review/r2/mut/M28.diff | 12 + .../work/queue-53-review/r2/mut/M28.txt | 56 +++ .../work/queue-53-review/r2/mut/M29.diff | 12 + .../work/queue-53-review/r2/mut/M29.txt | 56 +++ .../work/queue-53-review/r2/mut/M30.diff | 12 + .../work/queue-53-review/r2/mut/M30.txt | 36 ++ .../work/queue-53-review/r2/mut/M31.diff | 13 + .../work/queue-53-review/r2/mut/M31.txt | 80 ++++ .../work/queue-53-review/r2/mut/M32.diff | 13 + .../work/queue-53-review/r2/mut/M32.txt | 63 +++ .../work/queue-53-review/r2/mut/M33.diff | 13 + .../work/queue-53-review/r2/mut/M33.txt | 56 +++ .../work/queue-53-review/r2/mut/M34.diff | 13 + .../work/queue-53-review/r2/mut/M34.txt | 65 +++ .../work/queue-53-review/r2/mut/M35.diff | 13 + .../work/queue-53-review/r2/mut/M35.txt | 56 +++ .../work/queue-53-review/r2/mut/M36.diff | 13 + .../work/queue-53-review/r2/mut/M36.txt | 53 +++ .../work/queue-53-review/r2/mut/M37.diff | 13 + .../work/queue-53-review/r2/mut/M37.txt | 56 +++ .../queue-53-review/r2/mut/manifest-after.txt | 16 + .../work/queue-53-review/r2/mut/mutate.py | 48 +++ .../work/queue-53-review/r2/mut/run.sh | 15 + .../work/queue-53-review/r2/mut/summary.txt | 40 ++ .../queue-53-review/r2/out/build-tokens.txt | 1 + .../queue-53-review/r2/out/node-webui.txt | 36 ++ .../work/queue-53-review/r2/out/r1-to-r2.diff | 391 ++++++++++++++++++ .../work/queue-53-review/r2/out/s5-rep-1.txt | 9 + .../work/queue-53-review/r2/out/s5-rep-2.txt | 9 + .../work/queue-53-review/r2/out/s5-rep-3.txt | 9 + .../work/queue-53-review/r2/out/summary.txt | 14 + .../work/queue-53-review/r2/out/test-auth.txt | 17 + .../queue-53-review/r2/out/test-conductor.txt | 55 +++ .../queue-53-review/r2/out/test-config.txt | 26 ++ .../queue-53-review/r2/out/test-discord.txt | 70 ++++ .../r2/out/test-extension-package.txt | 21 + .../r2/out/test-foundation.txt | 53 +++ .../queue-53-review/r2/out/test-queue.txt | 35 ++ .../r2/out/test-release-docker.txt | 16 + .../queue-53-review/r2/out/test-release.txt | 7 + .../work/queue-53-review/r2/out/test-task.txt | 32 ++ .../queue-53-review/r2/probes/probe2.test.mjs | 118 ++++++ .../queue-53-review/r2/probes/probes-cand.txt | 36 ++ .../work/queue-53-review/review-r2.md | 236 +++++++++++ 100 files changed, 3894 insertions(+) create mode 100644 agents/darkwing/work/queue-53-review/r2/candidate-manifest.sha256 create mode 100755 agents/darkwing/work/queue-53-review/r2/gate.sh create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M01.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M01.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M02.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M02.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M03.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M03.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M04.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M04.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M05.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M05.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M06.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M06.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M07.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M07.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M08.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M08.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M09.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M09.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M10.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M10.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M11.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M11.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M12.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M12.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M13.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M13.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M14.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M14.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M15.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M15.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M16.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M16.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M17.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M17.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M18.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M18.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M19.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M19.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M20.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M20.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M21.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M21.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M22.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M22.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M23.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M23.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M24.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M24.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M25.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M25.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M26.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M26.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M27.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M27.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M28.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M28.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M29.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M29.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M30.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M30.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M31.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M31.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M32.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M32.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M33.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M33.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M34.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M34.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M35.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M35.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M36.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M36.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M37.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/M37.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/manifest-after.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/mutate.py create mode 100755 agents/darkwing/work/queue-53-review/r2/mut/run.sh create mode 100644 agents/darkwing/work/queue-53-review/r2/mut/summary.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/out/build-tokens.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/out/node-webui.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/out/r1-to-r2.diff create mode 100644 agents/darkwing/work/queue-53-review/r2/out/s5-rep-1.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/out/s5-rep-2.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/out/s5-rep-3.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/out/summary.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/out/test-auth.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/out/test-conductor.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/out/test-config.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/out/test-discord.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/out/test-extension-package.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/out/test-foundation.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/out/test-queue.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/out/test-release-docker.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/out/test-release.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/out/test-task.txt create mode 100644 agents/darkwing/work/queue-53-review/r2/probes/probe2.test.mjs create mode 100644 agents/darkwing/work/queue-53-review/r2/probes/probes-cand.txt create mode 100644 agents/darkwing/work/queue-53-review/review-r2.md diff --git a/agents/darkwing/work/queue-53-review/r2/candidate-manifest.sha256 b/agents/darkwing/work/queue-53-review/r2/candidate-manifest.sha256 new file mode 100644 index 00000000..afc1bf3d --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/candidate-manifest.sha256 @@ -0,0 +1,16 @@ +2c1c65b477f03a9474ca13022eb511363ffef0b75b932d404a0098b7f838594a packages/webui/README.md +02bbcb68335e80f8822aeea44bc8be49532cd702b325c1ea09ffe95b361a121c packages/webui/src/public/app.js +a9cb1cd82332b23a47e3a1239d25d13c86d16c4220695e34b243effa999f45f2 packages/webui/src/public/assets/fonts/jetbrains-mono-400.woff2 +086c48dfbea9ddaff1320f7e09399b8e2924e88ce67453721255db3bdbb5a353 packages/webui/src/public/assets/fonts/jetbrains-mono-500.woff2 +c503cc5ec5f8b2c7666b7ecda1adf44bd45f2e6579b2eba0fc292150416588a2 packages/webui/src/public/assets/fonts/jetbrains-mono-700.woff2 +30f0c136e3c88e422d0791acd97238870f9054a9729bc34cf2ff0d4ed8cac4ad packages/webui/src/public/assets/fonts/jetbrains-mono-OFL.txt +f6f89aaaa6a02e9a16020de26fb6a664f1da152e0b0413248da2d9f6b68395cc packages/webui/src/public/assets/fonts/jetbrains-mono-sources.txt +d8bc0fc7ad10fa188a6f68b925449476af4ca56ba343b24b089fb48cca296295 packages/webui/src/public/bus.js +01b456c1ca685e69e2974d66a615b7b8736abbd51aef7a3f014bca3783710430 packages/webui/src/public/icons.svg +fbbb51e5669a1f559015e0fdebf6f450b63383070472d2461f0bce9b9723d890 packages/webui/src/public/index.html +d7b4d0ca32f07a63265d89131847cbb72c7e532101e693b31b0f38839b22f7e6 packages/webui/src/public/shell.css +4fdb72ec24c7245584c89280415e10113dba1c4cb03d98f5570ac745ba2e95cb packages/webui/src/public/tokens.css +5a65fea95e6225f812c196b0199f3f6562a60e523da685b255f749f63b480c64 packages/webui/src/serve.mjs +6f68f67e99d5e832c0ba219911201b8adf08505e234647f2d9eac7292d55f50f packages/webui/tests/browser.mjs +713c86bd6b1d1b27949bbae071f1bdf1f7d744f84b723ad5a1bdbd1e8adc5fb6 packages/webui/tests/serve.test.mjs +c68acea3c81c1ac67347bae8139632c13dbcfe91207645aa545caa848887be05 packages/webui/tests/shell.test.mjs diff --git a/agents/darkwing/work/queue-53-review/r2/gate.sh b/agents/darkwing/work/queue-53-review/r2/gate.sh new file mode 100755 index 00000000..15b079c6 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/gate.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# Row 53 gate: packages/webui node suite, build-tokens --check, then every scripts/test-*.sh with Docker unreachable. +export TMPDIR=~/darkwing-scratch/r53b/tmp DOCKER_HOST=unix:///nonexistent.sock +cd ~/darkwing-scratch/r53b/cand +O=~/darkwing-scratch/r53b/out +: > $O/summary.txt +echo "start $(date -u +%FT%TZ)" >> $O/summary.txt +(cd packages/webui && env -u NODE_TEST_CONTEXT node --test 'tests/*.test.mjs') > $O/node-webui.txt 2>&1; e=$? +echo "node-webui exit=$e $(grep -E '^ℹ (pass|fail)' $O/node-webui.txt | tr '\n' ' ')" >> $O/summary.txt +node docs/design/tools/build-tokens.mjs --check > $O/build-tokens.txt 2>&1; e=$? +echo "build-tokens --check exit=$e $(tail -1 $O/build-tokens.txt)" >> $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-53-review/r2/mut/M01.diff b/agents/darkwing/work/queue-53-review/r2/mut/M01.diff new file mode 100644 index 00000000..d6f5cb5f --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M01.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/bus.js b/packages/webui/src/public/bus.js +index 93df4371..f0261468 100644 +--- a/packages/webui/src/public/bus.js ++++ b/packages/webui/src/public/bus.js +@@ -368,7 +368,7 @@ + } + const failTitle = err => err.status === 403 ? 'Bus refused the read' : ['not-configured', 'no-bus-host'].includes(err.code) ? 'No bus to read' : 'The read failed'; + // A refusal fails closed: no kept data, the code in mono. Any other failure keeps the last read, labelled with its time. +- const refusal = err => err.status === 403 || ['not-configured', 'no-bus-host'].includes(err.code); ++ const refusal = err => err.status === 403; + // After a refusal nothing read before is shown anywhere: not in a view, the palette or the Inbox count. + function forget() { last.clear(); inboxCount = null; } + const failedView = err => `${head(failTitle(err))}${empty('Nothing to show.', refusal(err) ? 'The view stays empty until the problem above is fixed.' : 'Read again, or come back when the bus answers.')}`; diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M01.txt b/agents/darkwing/work/queue-53-review/r2/mut/M01.txt new file mode 100644 index 00000000..766082c6 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M01.txt @@ -0,0 +1,47 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (5795.443344ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (6268.860495ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (8228.406461ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (1675.044775ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (122.850827ms) +✔ bus refusals map to statuses and never carry a path or a stack (41.87758ms) +✔ humanCall speaks the human transport protocol without blocking the server (1966.703581ms) +✔ busReader takes --business, else the live bus host, else refuses (202.62174ms) +✔ humanCall kills a transport that runs past its timeout (529.245643ms) +✔ serve refuses a --business value that is not a business id (191.893201ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (4996.198675ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (3473.451013ms) +✔ conversation view: a newer session with no readable history keeps the marker (2317.799437ms) +✔ conversation view: seats without history say so and offer no reply (1821.002855ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (5805.992267ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (56174.229792ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (4942.660505ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (23675.677859ms) +✔ loopback host and board origin fail closed (10.046586ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (124.822555ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (172.437494ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1879.898ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.519064ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.976932ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (4.470229ms) +✔ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (7510.926876ms) +✖ five states on Board, Inbox, Tasks, Agents and Trail (7040.739548ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 56775.652439 + +✖ failing tests: + +test at tests/shell.test.mjs:316:1 +✖ five states on Board, Inbox, Tasks, Agents and Trail (7040.739548ms) + Error: Uncaught (in promise) Error: Condition timed out: !!document.querySelector("#bus-view .banner.ref"): undefined + at Object.evaluate (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/browser.mjs:44:35) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:378:9) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M02.diff b/agents/darkwing/work/queue-53-review/r2/mut/M02.diff new file mode 100644 index 00000000..c4ce288b --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M02.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/app.js b/packages/webui/src/public/app.js +index 2084ff63..836dfbc2 100644 +--- a/packages/webui/src/public/app.js ++++ b/packages/webui/src/public/app.js +@@ -304,7 +304,7 @@ + // everything drawn from it: the inspector, the project tree, the counts and the footer. Any other + // failure keeps the last data with its scan time. + function error(err) { +- const refused = err.status === 403; ++ const refused = false; + failed = refused ? 'refused' : true; $('error').hidden = false; + if (refused) { + data = null; selected = null; project = null; diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M02.txt b/agents/darkwing/work/queue-53-review/r2/mut/M02.txt new file mode 100644 index 00000000..a4896323 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M02.txt @@ -0,0 +1,59 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (5097.83917ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (5306.446774ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (7791.246228ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (398.914569ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (470.407043ms) +✔ bus refusals map to statuses and never carry a path or a stack (175.165999ms) +✔ humanCall speaks the human transport protocol without blocking the server (1816.384458ms) +✔ busReader takes --business, else the live bus host, else refuses (186.59124ms) +✔ humanCall kills a transport that runs past its timeout (528.932291ms) +✔ serve refuses a --business value that is not a business id (174.235634ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (5245.016323ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (3422.707286ms) +✔ conversation view: a newer session with no readable history keeps the marker (4796.44785ms) +✔ conversation view: seats without history say so and offer no reply (5298.920714ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (5290.556185ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (55325.794121ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (4859.496965ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (25971.502398ms) +✔ loopback host and board origin fail closed (10.250345ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (134.111283ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (108.160287ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1137.333748ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.13576ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.175629ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.598383ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (4929.714237ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (3800.054159ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 55800.902436 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (4929.714237ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + + actual - expected + + + 'banner err' + - 'banner ref' + ^ + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:148:12) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: 'banner err', + expected: 'banner ref', + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M03.diff b/agents/darkwing/work/queue-53-review/r2/mut/M03.diff new file mode 100644 index 00000000..46924d34 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M03.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/app.js b/packages/webui/src/public/app.js +index 2084ff63..4f2b2625 100644 +--- a/packages/webui/src/public/app.js ++++ b/packages/webui/src/public/app.js +@@ -315,7 +315,7 @@ + inspect(); convForm(); + } + $('error').className = refused ? 'banner ref' : 'banner err'; +- $('board-refused').hidden = !refused; document.body.classList.toggle('board-refused', refused); ++ $('board-refused').hidden = !refused; + $('error').innerHTML = refused + ? `

The board refused the read. refused: ${esc(err.message)} Board: ${esc(board)}. Console shows nothing rather than a guess. Use Refresh to try again.

` + : `

${esc(err.message)} Board: ${esc(board)}. ${data ? `Showing last known data.${data.generatedAt ? ` Scanned ${esc(data.generatedAt)}.` : ''}` : 'No board data loaded.'} Use Refresh to try again.

`; diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M03.txt b/agents/darkwing/work/queue-53-review/r2/mut/M03.txt new file mode 100644 index 00000000..d4169108 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M03.txt @@ -0,0 +1,56 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (5712.8413ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (6470.833098ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (7936.181163ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (301.533225ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (494.643207ms) +✔ bus refusals map to statuses and never carry a path or a stack (231.746191ms) +✔ humanCall speaks the human transport protocol without blocking the server (2469.733966ms) +✔ busReader takes --business, else the live bus host, else refuses (652.021248ms) +✔ humanCall kills a transport that runs past its timeout (530.392475ms) +✔ serve refuses a --business value that is not a business id (165.143296ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (6095.538773ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (2939.706831ms) +✔ conversation view: a newer session with no readable history keeps the marker (1245.419871ms) +✔ conversation view: seats without history say so and offer no reply (1025.221336ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (6516.684216ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (56090.939503ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (6486.190874ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (23562.619035ms) +✔ loopback host and board origin fail closed (9.883696ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (126.346727ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (111.624361ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1913.882882ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.422763ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.680236ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.722365ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (6346.854574ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (3733.402259ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 56623.460421 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (6346.854574ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + + 'block' !== 'none' + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:150:12) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: 'block', + expected: 'none', + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M04.diff b/agents/darkwing/work/queue-53-review/r2/mut/M04.diff new file mode 100644 index 00000000..df5eb969 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M04.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/bus.js b/packages/webui/src/public/bus.js +index 93df4371..9bd147b6 100644 +--- a/packages/webui/src/public/bus.js ++++ b/packages/webui/src/public/bus.js +@@ -371,7 +371,7 @@ + const refusal = err => err.status === 403 || ['not-configured', 'no-bus-host'].includes(err.code); + // After a refusal nothing read before is shown anywhere: not in a view, the palette or the Inbox count. + function forget() { last.clear(); inboxCount = null; } +- const failedView = err => `${head(failTitle(err))}${empty('Nothing to show.', refusal(err) ? 'The view stays empty until the problem above is fixed.' : 'Read again, or come back when the bus answers.')}`; ++ const failedView = err => `${head(failTitle(err))}${empty('Nothing to show.', refusal(err) ? 'The view stays empty until the problem above is fixed.' : 'Read again, or come back when the bus answers.')}`; + const staleBanner = err => ``; + // Freshness line in the command bar for bus pages. + const stamp = iso => { const t = Date.parse(iso); return Number.isFinite(t) ? `${new Date(t).toISOString().slice(11, 19)} UTC` : 'unknown'; }; diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M04.txt b/agents/darkwing/work/queue-53-review/r2/mut/M04.txt new file mode 100644 index 00000000..c3cfb181 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M04.txt @@ -0,0 +1,58 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (5462.633703ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (6016.227844ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (7161.229825ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (459.662074ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (198.328355ms) +✔ bus refusals map to statuses and never carry a path or a stack (128.375723ms) +✔ humanCall speaks the human transport protocol without blocking the server (2011.124303ms) +✔ busReader takes --business, else the live bus host, else refuses (330.452814ms) +✔ humanCall kills a transport that runs past its timeout (529.363963ms) +✔ serve refuses a --business value that is not a business id (257.002802ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (5921.250904ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (2583.408385ms) +✔ conversation view: a newer session with no readable history keeps the marker (1776.121129ms) +✔ conversation view: seats without history say so and offer no reply (842.197628ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (5884.809548ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (56135.561582ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (4993.429078ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (24999.455651ms) +✔ loopback host and board origin fail closed (8.987038ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (151.065885ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (150.806081ms) +✔ unreachable board reports URL; CLI rejects unsupported options (858.291021ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.308606ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.824401ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.562959ms) +✔ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (8401.194007ms) +✖ five states on Board, Inbox, Tasks, Agents and Trail (1483.639423ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 56554.628294 + +✖ failing tests: + +test at tests/shell.test.mjs:316:1 +✖ five states on Board, Inbox, Tasks, Agents and Trail (1483.639423ms) + AssertionError [ERR_ASSERTION]: #/inbox + + actual - expected + + + '--business' + - 'no-bus-host' + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:379:16) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: false, + code: 'ERR_ASSERTION', + actual: '--business', + expected: 'no-bus-host', + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M05.diff b/agents/darkwing/work/queue-53-review/r2/mut/M05.diff new file mode 100644 index 00000000..46127d5f --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M05.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/bus.js b/packages/webui/src/public/bus.js +index 93df4371..0737320a 100644 +--- a/packages/webui/src/public/bus.js ++++ b/packages/webui/src/public/bus.js +@@ -377,7 +377,7 @@ + const stamp = iso => { const t = Date.parse(iso); return Number.isFinite(t) ? `${new Date(t).toISOString().slice(11, 19)} UTC` : 'unknown'; }; + function freshBus(state) { + $('fresh-bus').innerHTML = state === 'refused' ? 'Bus not read: refused' : state === 'failed' ? 'Bus not read: the read failed' +- : `Bus read ${esc(stamp(readAt))}${readAt ? ` (${esc(ago(readAt))})` : ''}${state === 'stale' ? ' · stale: the last read failed' : ''}`; ++ : `Bus read ${esc(stamp(readAt))}${readAt ? ` (${esc(ago(readAt))})` : ''}`; + } + + // ---------------------------------------------------------------- router diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M05.txt b/agents/darkwing/work/queue-53-review/r2/mut/M05.txt new file mode 100644 index 00000000..f738fe3e --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M05.txt @@ -0,0 +1,89 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (8079.031307ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (95685.374707ms) +✖ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (39939.301906ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (399.29347ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (107.942253ms) +✔ bus refusals map to statuses and never carry a path or a stack (183.540352ms) +✔ humanCall speaks the human transport protocol without blocking the server (2475.56703ms) +✔ busReader takes --business, else the live bus host, else refuses (210.045959ms) +✔ humanCall kills a transport that runs past its timeout (528.605198ms) +✔ serve refuses a --business value that is not a business id (196.905686ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (64786.967758ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (27245.695481ms) +✔ conversation view: a newer session with no readable history keeps the marker (6126.989522ms) +✔ conversation view: seats without history say so and offer no reply (5118.460015ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (9195.480901ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (88101.20953ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (16229.53364ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (46498.641699ms) +✔ loopback host and board origin fail closed (9.766364ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (204.824833ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (368.503988ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1135.758555ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.436508ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.838218ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.916424ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (25445.008415ms) +✖ five states on Board, Inbox, Tasks, Agents and Trail (12241.439812ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 24 +ℹ fail 3 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 103416.270276 + +✖ failing tests: + +test at tests/bus-browser.test.mjs:68:1 +✖ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (39939.301906ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + + 'BODY' !== 'H1' + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/bus-browser.test.mjs:124:12) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: 'BODY', + expected: 'H1', + operator: 'strictEqual', + diff: 'simple' + } + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (25445.008415ms) + AssertionError [ERR_ASSERTION]: The input did not match the regular expression /stale: the last read failed/. Input: + + 'Bus read 18:29:18 UTC (1 s ago)' + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:221:12) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: 'Bus read 18:29:18 UTC (1 s ago)', + expected: /stale: the last read failed/, + operator: 'match', + diff: 'simple' + } + +test at tests/shell.test.mjs:316:1 +✖ five states on Board, Inbox, Tasks, Agents and Trail (12241.439812ms) + AssertionError [ERR_ASSERTION]: #/inbox + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:372:14) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: false, + code: 'ERR_ASSERTION', + actual: 'Bus read 18:29:28 UTC (1 s ago)', + expected: /stale: the last read failed/, + operator: 'match', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M06.diff b/agents/darkwing/work/queue-53-review/r2/mut/M06.diff new file mode 100644 index 00000000..1fe16936 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M06.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/app.js b/packages/webui/src/public/app.js +index 2084ff63..7c8f15db 100644 +--- a/packages/webui/src/public/app.js ++++ b/packages/webui/src/public/app.js +@@ -41,7 +41,7 @@ + palette = p.id; + if (!['system', 'light', 'dim', 'dark'].includes(mode)) mode = 'system'; + document.documentElement.dataset.palette = palette; +- if (mode === 'system') delete document.documentElement.dataset.mode; else document.documentElement.dataset.mode = mode; ++ document.documentElement.dataset.mode = mode; + $('palette').value = palette; $('mode').value = mode; + try { localStorage.setItem('mosaic-console-appearance', JSON.stringify({ palette, mode })); } catch {} + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M06.txt b/agents/darkwing/work/queue-53-review/r2/mut/M06.txt new file mode 100644 index 00000000..faafd41e --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M06.txt @@ -0,0 +1,56 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (15272.623465ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (31722.087198ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (30330.451829ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (2416.562027ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (37.29549ms) +✔ bus refusals map to statuses and never carry a path or a stack (18.416107ms) +✔ humanCall speaks the human transport protocol without blocking the server (1676.411784ms) +✔ busReader takes --business, else the live bus host, else refuses (250.959993ms) +✔ humanCall kills a transport that runs past its timeout (527.099896ms) +✔ serve refuses a --business value that is not a business id (180.793544ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (28900.406029ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (4313.697934ms) +✔ conversation view: a newer session with no readable history keeps the marker (2351.575056ms) +✔ conversation view: seats without history say so and offer no reply (2446.325824ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (10421.525061ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (73032.592659ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (12366.957176ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (33923.140487ms) +✔ loopback host and board origin fail closed (8.196194ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (445.360351ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (152.315148ms) +✔ unreachable board reports URL; CLI rejects unsupported options (923.203685ms) +✔ tokens.css and icons.svg are byte copies of docs/design (0.929341ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.043473ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.771135ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (5708.723686ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (19111.162225ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 73383.749377 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (5708.723686ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + + true !== false + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:108:12) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: true, + expected: false, + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M07.diff b/agents/darkwing/work/queue-53-review/r2/mut/M07.diff new file mode 100644 index 00000000..4044ff4a --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M07.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/bus.js b/packages/webui/src/public/bus.js +index 93df4371..c6273452 100644 +--- a/packages/webui/src/public/bus.js ++++ b/packages/webui/src/public/bus.js +@@ -481,7 +481,7 @@ + const t = $('toast'); clearTimeout(toastTimer); + if (text === null) { t.className = 'toast'; t.textContent = ''; return; } + t.className = `toast on${error ? ' err' : ''}`; +- t.innerHTML = `${esc(text)}${error ? '' : ''}`; ++ t.innerHTML = `${text}${error ? '' : ''}`; + if (!error) toastTimer = setTimeout(() => toast(null), 2600); + } + diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M07.txt b/agents/darkwing/work/queue-53-review/r2/mut/M07.txt new file mode 100644 index 00000000..917705d6 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M07.txt @@ -0,0 +1,36 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (9677.560125ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (5238.868632ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (11020.061708ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (412.713989ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (210.605785ms) +✔ bus refusals map to statuses and never carry a path or a stack (68.144102ms) +✔ humanCall speaks the human transport protocol without blocking the server (2938.448863ms) +✔ busReader takes --business, else the live bus host, else refuses (506.983539ms) +✔ humanCall kills a transport that runs past its timeout (567.330888ms) +✔ serve refuses a --business value that is not a business id (810.105696ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (7229.729607ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (8811.289186ms) +✔ conversation view: a newer session with no readable history keeps the marker (4399.608573ms) +✔ conversation view: seats without history say so and offer no reply (1755.37456ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (7441.830627ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (58785.923958ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (9615.513932ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (24892.390944ms) +✔ loopback host and board origin fail closed (12.008815ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (182.542287ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (212.873578ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1994.917068ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.662111ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.799647ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (3.174412ms) +✔ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (13373.047364ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (6417.896432ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 27 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 59334.66732 diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M08.diff b/agents/darkwing/work/queue-53-review/r2/mut/M08.diff new file mode 100644 index 00000000..0bd2c5d4 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M08.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/bus.js b/packages/webui/src/public/bus.js +index 93df4371..846b6f36 100644 +--- a/packages/webui/src/public/bus.js ++++ b/packages/webui/src/public/bus.js +@@ -500,7 +500,7 @@ + const q = $('cmdk-input').value.trim().toLowerCase(); + pkShown = pkAll.filter(i => !q || `${i.label} ${i.group}`.toLowerCase().includes(q)).slice(0, 50); + pkAt = Math.min(pkAt, Math.max(0, pkShown.length - 1)); +- $('cmdk-list').innerHTML = pkShown.length ? pkShown.map((i, n) => `
  • ${txt(i.label)}${txt(i.group)}
  • `).join('') ++ $('cmdk-list').innerHTML = pkShown.length ? pkShown.map((i, n) => `
  • ${i.label}${txt(i.group)}
  • `).join('') + : '
  • No view, decision or task matches.
  • '; + if (pkShown.length) { $('cmdk-input').setAttribute('aria-activedescendant', `cmdk-opt-${pkAt}`); $(`cmdk-opt-${pkAt}`)?.scrollIntoView({ block: 'nearest' }); } + else $('cmdk-input').removeAttribute('aria-activedescendant'); diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M08.txt b/agents/darkwing/work/queue-53-review/r2/mut/M08.txt new file mode 100644 index 00000000..f7aa7672 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M08.txt @@ -0,0 +1,56 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (6262.461685ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (8323.877976ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (11564.402673ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (2264.208911ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (86.487989ms) +✔ bus refusals map to statuses and never carry a path or a stack (69.631861ms) +✔ humanCall speaks the human transport protocol without blocking the server (3169.117616ms) +✔ busReader takes --business, else the live bus host, else refuses (343.785283ms) +✔ humanCall kills a transport that runs past its timeout (532.902486ms) +✔ serve refuses a --business value that is not a business id (400.71332ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (6321.331007ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (4518.74495ms) +✔ conversation view: a newer session with no readable history keeps the marker (2848.536998ms) +✔ conversation view: seats without history say so and offer no reply (1705.987269ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (6589.386693ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (60212.056998ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (5627.527147ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (24935.535973ms) +✔ loopback host and board origin fail closed (10.838303ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (707.851249ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (335.465899ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1717.022266ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.259551ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.791564ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (3.433592ms) +✔ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (9944.951011ms) +✖ five states on Board, Inbox, Tasks, Agents and Trail (3695.850599ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 60869.027066 + +✖ failing tests: + +test at tests/shell.test.mjs:316:1 +✖ five states on Board, Inbox, Tasks, Agents and Trail (3695.850599ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + + 2 !== 0 + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:413:12) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: 2, + expected: 0, + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M09.diff b/agents/darkwing/work/queue-53-review/r2/mut/M09.diff new file mode 100644 index 00000000..08f8b7a0 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M09.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/shell.css b/packages/webui/src/public/shell.css +index ed6d2d96..099ad74c 100644 +--- a/packages/webui/src/public/shell.css ++++ b/packages/webui/src/public/shell.css +@@ -18,7 +18,7 @@ body{font:400 14px/1.5 var(--font);color:var(--text);background:var(--canvas)} + code,kbd,pre,.mono{font-family:var(--mono);font-size:12.5px} + kbd{border:1px solid var(--line);border-bottom-width:2px;border-radius:4px;padding:0 .35em;background:var(--surface);color:var(--strong);white-space:nowrap;font-size:11.5px} + .count,td,.s1-twhen,time,.fresh,.kv dd{font-variant-numeric:tabular-nums} +-:focus-visible{outline:2px solid var(--focus);outline-offset:2px} ++:focus-visible{outline:2px solid var(--focus);outline-offset:0} + table.sessions tbody tr:focus-visible,table.s1-table tbody tr:focus-visible{outline:2px solid var(--focus);outline-offset:-2px} + svg.i{width:18px;height:18px;flex:none;fill:none;stroke:currentColor;stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round} + diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M09.txt b/agents/darkwing/work/queue-53-review/r2/mut/M09.txt new file mode 100644 index 00000000..9b19dade --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M09.txt @@ -0,0 +1,56 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (7609.074415ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (11452.724025ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (12309.820512ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (2304.099495ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (94.109243ms) +✔ bus refusals map to statuses and never carry a path or a stack (42.272421ms) +✔ humanCall speaks the human transport protocol without blocking the server (2371.801182ms) +✔ busReader takes --business, else the live bus host, else refuses (410.928224ms) +✔ humanCall kills a transport that runs past its timeout (531.203001ms) +✔ serve refuses a --business value that is not a business id (306.449847ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (7788.383155ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (4662.276458ms) +✔ conversation view: a newer session with no readable history keeps the marker (1912.219392ms) +✔ conversation view: seats without history say so and offer no reply (1496.764289ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (8619.000837ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (59599.785751ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (7467.265369ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (25221.11973ms) +✔ loopback host and board origin fail closed (11.544617ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (1719.852203ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (185.65663ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1065.79537ms) +✔ tokens.css and icons.svg are byte copies of docs/design (6.317784ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (14.868056ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (5.161292ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (5535.667757ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (6509.811784ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 60160.369576 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (5535.667757ms) + AssertionError [ERR_ASSERTION]: #cmdk outline offset + + 0 !== 2 + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:181:125) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: false, + code: 'ERR_ASSERTION', + actual: 0, + expected: 2, + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M10.diff b/agents/darkwing/work/queue-53-review/r2/mut/M10.diff new file mode 100644 index 00000000..f4667afe --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M10.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/shell.css b/packages/webui/src/public/shell.css +index ed6d2d96..cc401c3b 100644 +--- a/packages/webui/src/public/shell.css ++++ b/packages/webui/src/public/shell.css +@@ -18,7 +18,7 @@ body{font:400 14px/1.5 var(--font);color:var(--text);background:var(--canvas)} + code,kbd,pre,.mono{font-family:var(--mono);font-size:12.5px} + kbd{border:1px solid var(--line);border-bottom-width:2px;border-radius:4px;padding:0 .35em;background:var(--surface);color:var(--strong);white-space:nowrap;font-size:11.5px} + .count,td,.s1-twhen,time,.fresh,.kv dd{font-variant-numeric:tabular-nums} +-:focus-visible{outline:2px solid var(--focus);outline-offset:2px} ++:focus-visible{outline:1px solid var(--focus);outline-offset:2px} + table.sessions tbody tr:focus-visible,table.s1-table tbody tr:focus-visible{outline:2px solid var(--focus);outline-offset:-2px} + svg.i{width:18px;height:18px;flex:none;fill:none;stroke:currentColor;stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round} + diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M10.txt b/agents/darkwing/work/queue-53-review/r2/mut/M10.txt new file mode 100644 index 00000000..4cd24e41 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M10.txt @@ -0,0 +1,53 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (10029.216ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (11567.747539ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (12394.616919ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (2135.731454ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (106.029912ms) +✔ bus refusals map to statuses and never carry a path or a stack (43.317817ms) +✔ humanCall speaks the human transport protocol without blocking the server (2315.691295ms) +✔ busReader takes --business, else the live bus host, else refuses (428.29625ms) +✔ humanCall kills a transport that runs past its timeout (532.121068ms) +✔ serve refuses a --business value that is not a business id (200.505373ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (10797.128621ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (3575.186349ms) +✔ conversation view: a newer session with no readable history keeps the marker (1850.44415ms) +✔ conversation view: seats without history say so and offer no reply (1664.190106ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (8184.327825ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (59155.373445ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (9016.166527ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (27198.316759ms) +✔ loopback host and board origin fail closed (10.638221ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (1333.045642ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (516.069031ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1227.942831ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.552045ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.997839ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (3.263111ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (8865.020042ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (5262.681363ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 59903.296319 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (8865.020042ms) + AssertionError [ERR_ASSERTION]: #cmdk outline 1px + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:181:69) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: false, + code: 'ERR_ASSERTION', + actual: false, + expected: true, + operator: '==', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M11.diff b/agents/darkwing/work/queue-53-review/r2/mut/M11.diff new file mode 100644 index 00000000..4f7eeb70 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M11.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/shell.css b/packages/webui/src/public/shell.css +index ed6d2d96..a07327e6 100644 +--- a/packages/webui/src/public/shell.css ++++ b/packages/webui/src/public/shell.css +@@ -166,7 +166,7 @@ body.on-bus #board-refused{display:none} + .cmd-right label{flex:1 1 0;min-width:0} + .cmd-right .btn{flex:none} + /* The section list is one strip that scrolls inside itself (IMPLEMENTING.md), so more sections never add rows. */ +- .s1-sections{display:flex;flex-wrap:nowrap;overflow-x:auto;flex-basis:100%;min-width:0;max-width:100%;gap:2px;padding-bottom:2px;scrollbar-width:thin} ++ .s1-sections{display:flex;flex-wrap:wrap;overflow-x:visible;flex-basis:100%;min-width:0;max-width:100%;gap:2px;padding-bottom:2px;scrollbar-width:thin} + .s1-sections>li{flex:none} + .s1-section{border-radius:var(--r);padding:5px 8px;white-space:nowrap;flex:none} + .inspector{inset:0;top:0;width:100%;z-index:40;box-shadow:none} diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M11.txt b/agents/darkwing/work/queue-53-review/r2/mut/M11.txt new file mode 100644 index 00000000..9270080f --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M11.txt @@ -0,0 +1,56 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (6072.849226ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (7648.73759ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (10575.99292ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (2314.72617ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (71.737636ms) +✔ bus refusals map to statuses and never carry a path or a stack (26.592189ms) +✔ humanCall speaks the human transport protocol without blocking the server (1969.155253ms) +✔ busReader takes --business, else the live bus host, else refuses (346.614032ms) +✔ humanCall kills a transport that runs past its timeout (529.001693ms) +✔ serve refuses a --business value that is not a business id (204.313294ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (5650.641432ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (4927.264395ms) +✔ conversation view: a newer session with no readable history keeps the marker (3456.642762ms) +✔ conversation view: seats without history say so and offer no reply (3245.69597ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (6179.814923ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (56099.101119ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (6232.410476ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (24265.087834ms) +✔ loopback host and board origin fail closed (11.345162ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (383.542915ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (858.113627ms) +✔ unreachable board reports URL; CLI rejects unsupported options (926.123488ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.490977ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (3.558934ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (4.898223ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (6025.485868ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (5394.399273ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 56657.087449 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (6025.485868ms) + AssertionError [ERR_ASSERTION]: one row at 360px + + 2 !== 1 + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:204:14) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: false, + code: 'ERR_ASSERTION', + actual: 2, + expected: 1, + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M12.diff b/agents/darkwing/work/queue-53-review/r2/mut/M12.diff new file mode 100644 index 00000000..47605e35 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M12.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/bus.js b/packages/webui/src/public/bus.js +index 93df4371..046ff49e 100644 +--- a/packages/webui/src/public/bus.js ++++ b/packages/webui/src/public/bus.js +@@ -209,7 +209,7 @@ + const items = [['/', 'Board', '', 'board'], ['/inbox', 'Inbox', inboxCount ? `${inboxCount.open}${inboxCount.blocking ? ` ${blockChip(`${inboxCount.blocking} blocking`)}` : ''}` : '', 'inbox'], ['/tasks', 'Tasks', '', 'tasks'], ['/agents', 'Agents', '', 'agents']]; + $('sections').innerHTML = items.map(([h, l, extra, icon]) => { + const cur = h === '/' ? route === '/' : route.startsWith(h) || (h === '/tasks' && route.startsWith('/trail/task')) || (h === '/inbox' && route.startsWith('/trail/decision')); +- return `
  • ${l}${extra ? ` ${extra}` : ''}
  • `; ++ return `
  • ${l}${extra ? ` ${extra}` : ''}
  • `; + }).join(''); + } + function countInbox(rows) { inboxCount = { open: rows.length, blocking: rows.filter(d => d.blocking).length }; } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M12.txt b/agents/darkwing/work/queue-53-review/r2/mut/M12.txt new file mode 100644 index 00000000..b9f697ef --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M12.txt @@ -0,0 +1,56 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (5401.316742ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (5276.112592ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (8044.16258ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (1584.166767ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (105.247657ms) +✔ bus refusals map to statuses and never carry a path or a stack (53.793812ms) +✔ humanCall speaks the human transport protocol without blocking the server (2250.629516ms) +✔ busReader takes --business, else the live bus host, else refuses (269.127594ms) +✔ humanCall kills a transport that runs past its timeout (530.269905ms) +✔ serve refuses a --business value that is not a business id (219.283891ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (4958.475554ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (3630.443988ms) +✔ conversation view: a newer session with no readable history keeps the marker (1294.07507ms) +✔ conversation view: seats without history say so and offer no reply (1115.599978ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (5574.722064ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (56570.885372ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (5176.575671ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (23510.05973ms) +✔ loopback host and board origin fail closed (10.17656ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (137.753736ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (88.553236ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1859.386694ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.686138ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.846105ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (4.440777ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (5245.349397ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (3503.212069ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 57151.799923 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (5245.349397ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + + 0 !== 4 + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:196:12) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: 0, + expected: 4, + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M13.diff b/agents/darkwing/work/queue-53-review/r2/mut/M13.diff new file mode 100644 index 00000000..a3389152 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M13.diff @@ -0,0 +1,12 @@ +diff --git a/packages/webui/src/public/app.js b/packages/webui/src/public/app.js +index 2084ff63..39477043 100644 +--- a/packages/webui/src/public/app.js ++++ b/packages/webui/src/public/app.js +@@ -296,7 +296,6 @@ + function accept(value) { + if (!value || !Array.isArray(value.sessions) || value.sessions.some(r => !r || typeof r.project !== 'string' || typeof r.agent !== 'string')) throw new Error('Invalid board session data'); + data = value; failed = false; $('error').hidden = true; $('error').className = 'banner err'; +- $('board-refused').hidden = true; document.body.classList.remove('board-refused'); + for (const id of awaiting.keys()) { const r = row(id); if (r && !pending(r)) awaiting.delete(id); } + render(); + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M13.txt b/agents/darkwing/work/queue-53-review/r2/mut/M13.txt new file mode 100644 index 00000000..b1b05b2e --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M13.txt @@ -0,0 +1,55 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (5471.314194ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (7878.85227ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (8907.311012ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (944.751298ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (84.28557ms) +✔ bus refusals map to statuses and never carry a path or a stack (63.12128ms) +✔ humanCall speaks the human transport protocol without blocking the server (2026.814322ms) +✔ busReader takes --business, else the live bus host, else refuses (240.833469ms) +✔ humanCall kills a transport that runs past its timeout (527.244614ms) +✔ serve refuses a --business value that is not a business id (169.201231ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (5690.430019ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (3845.901684ms) +✔ conversation view: a newer session with no readable history keeps the marker (1522.881981ms) +✔ conversation view: seats without history say so and offer no reply (957.590092ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (5842.696786ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (56214.274595ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (5702.561978ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (26371.006181ms) +✔ loopback host and board origin fail closed (7.080199ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (125.853509ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (99.128202ms) +✔ unreachable board reports URL; CLI rejects unsupported options (957.323889ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.322481ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.617784ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.454045ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (5828.413235ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (5116.480007ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 56613.263322 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (5828.413235ms) + AssertionError [ERR_ASSERTION]: Expected "actual" to be strictly unequal to: + + 'none' + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:161:12) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: 'none', + expected: 'none', + operator: 'notStrictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M14.diff b/agents/darkwing/work/queue-53-review/r2/mut/M14.diff new file mode 100644 index 00000000..1ec5e1bf --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M14.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/bus.js b/packages/webui/src/public/bus.js +index 93df4371..4eb91e82 100644 +--- a/packages/webui/src/public/bus.js ++++ b/packages/webui/src/public/bus.js +@@ -532,7 +532,7 @@ + const a = e.target.closest?.('#bus-view table.s1-table td.s1-title a'); + if (!a || (e.key !== 'ArrowDown' && e.key !== 'ArrowUp')) return; + const links = [...a.closest('table').querySelectorAll('td.s1-title a')], i = links.indexOf(a); +- e.preventDefault(); links[i + (e.key === 'ArrowDown' ? 1 : -1)]?.focus(); ++ e.preventDefault(); links[i + (e.key === 'ArrowDown' ? -1 : 1)]?.focus(); + }); + window.addEventListener('hashchange', () => render(true)); + $('refresh').addEventListener('click', () => render(false)); diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M14.txt b/agents/darkwing/work/queue-53-review/r2/mut/M14.txt new file mode 100644 index 00000000..e114542e --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M14.txt @@ -0,0 +1,56 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (6928.118795ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (8209.259569ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (12049.913654ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (2984.527328ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (45.725005ms) +✔ bus refusals map to statuses and never carry a path or a stack (25.241585ms) +✔ humanCall speaks the human transport protocol without blocking the server (1825.996919ms) +✔ busReader takes --business, else the live bus host, else refuses (694.772009ms) +✔ humanCall kills a transport that runs past its timeout (528.374368ms) +✔ serve refuses a --business value that is not a business id (184.930858ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (7523.995068ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (4770.585661ms) +✔ conversation view: a newer session with no readable history keeps the marker (1243.339041ms) +✔ conversation view: seats without history say so and offer no reply (1088.351142ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (7949.559455ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (56700.906036ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (7259.807748ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (23891.089464ms) +✔ loopback host and board origin fail closed (7.728754ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (866.179772ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (126.918795ms) +✔ unreachable board reports URL; CLI rejects unsupported options (575.777593ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.024718ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (1.983577ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.447936ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (7103.550163ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (5312.733709ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 57103.536658 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (7103.550163ms) + AssertionError [ERR_ASSERTION]: The input did not match the regular expression /Second task/. Input: + + '#7 Kept task' + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:224:38) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: '#7 Kept task', + expected: /Second task/, + operator: 'match', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M15.diff b/agents/darkwing/work/queue-53-review/r2/mut/M15.diff new file mode 100644 index 00000000..e145410e --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M15.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/serve.mjs b/packages/webui/src/serve.mjs +index 280a228f..93a1958f 100644 +--- a/packages/webui/src/serve.mjs ++++ b/packages/webui/src/serve.mjs +@@ -22,7 +22,7 @@ const files = new Map([ + ['/', ['index.html', 'text/html; charset=utf-8']], + ...['app.js', 'brand.js', 'bus.js'].map(f => ['/' + f, [f, 'text/javascript; charset=utf-8']]), + ...['shared/app.css', 'tokens.css', 'console.css', 'live.css', 'bus.css', 'shell.css'].map(f => ['/' + f, [f, 'text/css; charset=utf-8']]), +- ['/icons.svg', ['icons.svg', 'image/svg+xml']], ++ ['/icons.svg', ['icons.svg', 'text/plain']], + ...[400, 500, 600, 700].map(w => [`/assets/fonts/manrope-${w}.woff2`, [`assets/fonts/manrope-${w}.woff2`, 'font/woff2']]), + ...[400, 500, 700].map(w => [`/assets/fonts/jetbrains-mono-${w}.woff2`, [`assets/fonts/jetbrains-mono-${w}.woff2`, 'font/woff2']]), + ]); diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M15.txt b/agents/darkwing/work/queue-53-review/r2/mut/M15.txt new file mode 100644 index 00000000..68b9bf41 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M15.txt @@ -0,0 +1,53 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (5776.919786ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (5899.647375ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (7817.95423ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (304.00469ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (92.68169ms) +✔ bus refusals map to statuses and never carry a path or a stack (59.725948ms) +✔ humanCall speaks the human transport protocol without blocking the server (2162.640231ms) +✔ busReader takes --business, else the live bus host, else refuses (417.956067ms) +✔ humanCall kills a transport that runs past its timeout (529.93184ms) +✔ serve refuses a --business value that is not a business id (154.497633ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (5253.517004ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (3024.904581ms) +✔ conversation view: a newer session with no readable history keeps the marker (1715.174597ms) +✔ conversation view: seats without history say so and offer no reply (1329.071054ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (5838.646156ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (56097.068788ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (5288.871253ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (24117.940082ms) +✔ loopback host and board origin fail closed (9.101418ms) +✖ real board fixture passes through WebUI; assets and isolated seen/reply work (100.398615ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (96.109877ms) +✔ unreachable board reports URL; CLI rejects unsupported options (879.497882ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.300521ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.702869ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.21885ms) +✔ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (8260.236526ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (3414.935311ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 56499.507114 + +✖ failing tests: + +test at tests/serve.test.mjs:22:1 +✖ real board fixture passes through WebUI; assets and isolated seen/reply work (100.398615ms) + AssertionError [ERR_ASSERTION]: /icons.svg + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/serve.test.mjs:41:101) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: false, + code: 'ERR_ASSERTION', + actual: false, + expected: true, + operator: '==', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M16.diff b/agents/darkwing/work/queue-53-review/r2/mut/M16.diff new file mode 100644 index 00000000..7ac1ec1a --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M16.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/shell.css b/packages/webui/src/public/shell.css +index ed6d2d96..7fb39c59 100644 +--- a/packages/webui/src/public/shell.css ++++ b/packages/webui/src/public/shell.css +@@ -17,7 +17,7 @@ body{font:400 14px/1.5 var(--font);color:var(--text);background:var(--canvas)} + .tree-title,.label{font:700 11px/1.3 var(--font);letter-spacing:.06em;text-transform:uppercase;color:var(--muted)} + code,kbd,pre,.mono{font-family:var(--mono);font-size:12.5px} + kbd{border:1px solid var(--line);border-bottom-width:2px;border-radius:4px;padding:0 .35em;background:var(--surface);color:var(--strong);white-space:nowrap;font-size:11.5px} +-.count,td,.s1-twhen,time,.fresh,.kv dd{font-variant-numeric:tabular-nums} ++ + :focus-visible{outline:2px solid var(--focus);outline-offset:2px} + table.sessions tbody tr:focus-visible,table.s1-table tbody tr:focus-visible{outline:2px solid var(--focus);outline-offset:-2px} + svg.i{width:18px;height:18px;flex:none;fill:none;stroke:currentColor;stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round} diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M16.txt b/agents/darkwing/work/queue-53-review/r2/mut/M16.txt new file mode 100644 index 00000000..6f0fb147 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M16.txt @@ -0,0 +1,58 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (7032.157582ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (5974.415759ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (8270.130573ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (480.132084ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (215.284099ms) +✔ bus refusals map to statuses and never carry a path or a stack (202.050789ms) +✔ humanCall speaks the human transport protocol without blocking the server (2541.451512ms) +✔ busReader takes --business, else the live bus host, else refuses (286.306148ms) +✔ humanCall kills a transport that runs past its timeout (528.640541ms) +✔ serve refuses a --business value that is not a business id (250.072087ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (5934.362349ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (3261.510465ms) +✔ conversation view: a newer session with no readable history keeps the marker (1883.827199ms) +✔ conversation view: seats without history say so and offer no reply (1497.152757ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (6942.276403ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (57525.879316ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (6010.051378ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (22782.377069ms) +✔ loopback host and board origin fail closed (9.765723ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (126.74125ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (141.695296ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1790.575205ms) +✔ tokens.css and icons.svg are byte copies of docs/design (0.988386ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.255569ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.41268ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (6915.352548ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (3708.441788ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 58096.23649 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (6915.352548ms) + AssertionError [ERR_ASSERTION]: #fresh + + actual - expected + + + 'normal' + - 'tabular-nums' + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:197:60) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: false, + code: 'ERR_ASSERTION', + actual: 'normal', + expected: 'tabular-nums', + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M17.diff b/agents/darkwing/work/queue-53-review/r2/mut/M17.diff new file mode 100644 index 00000000..062e474b --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M17.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/app.js b/packages/webui/src/public/app.js +index 2084ff63..8ccceb1f 100644 +--- a/packages/webui/src/public/app.js ++++ b/packages/webui/src/public/app.js +@@ -43,7 +43,7 @@ + document.documentElement.dataset.palette = palette; + if (mode === 'system') delete document.documentElement.dataset.mode; else document.documentElement.dataset.mode = mode; + $('palette').value = palette; $('mode').value = mode; +- try { localStorage.setItem('mosaic-console-appearance', JSON.stringify({ palette, mode })); } catch {} ++ try { localStorage.setItem('mosaic-console-look', JSON.stringify({ palette, mode })); } catch {} + } + $('palette').innerHTML = Brand.palettes.map(p => ``).join(''); + try { const saved = JSON.parse(localStorage.getItem('mosaic-console-appearance')); if (saved) { palette = saved.palette; mode = saved.mode; } } catch {} diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M17.txt b/agents/darkwing/work/queue-53-review/r2/mut/M17.txt new file mode 100644 index 00000000..19cad8ce --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M17.txt @@ -0,0 +1,48 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (7219.196692ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (7659.592024ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (8632.286954ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (282.571341ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (122.635688ms) +✔ bus refusals map to statuses and never carry a path or a stack (75.618193ms) +✔ humanCall speaks the human transport protocol without blocking the server (2211.018612ms) +✔ busReader takes --business, else the live bus host, else refuses (397.540081ms) +✔ humanCall kills a transport that runs past its timeout (566.728797ms) +✔ serve refuses a --business value that is not a business id (174.980802ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (7757.890315ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (2813.782157ms) +✔ conversation view: a newer session with no readable history keeps the marker (1649.062025ms) +✔ conversation view: seats without history say so and offer no reply (1061.913097ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (7800.58257ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (57377.700776ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (7773.93166ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (25903.694289ms) +✔ loopback host and board origin fail closed (10.020241ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (131.068377ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (140.661963ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1249.439995ms) +✔ tokens.css and icons.svg are byte copies of docs/design (2.059447ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.730261ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.702814ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (7911.76887ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (3765.63761ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 57861.215013 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (7911.76887ms) + Error: Uncaught: TypeError: Cannot read properties of null (reading 'mode') + at :1:62 + at Object.evaluate (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/browser.mjs:44:35) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:121:18) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M18.diff b/agents/darkwing/work/queue-53-review/r2/mut/M18.diff new file mode 100644 index 00000000..c511cead --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M18.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/shell.css b/packages/webui/src/public/shell.css +index ed6d2d96..9b515c06 100644 +--- a/packages/webui/src/public/shell.css ++++ b/packages/webui/src/public/shell.css +@@ -97,7 +97,7 @@ table.s1-table td code{font-size:12.5px;white-space:nowrap} + .skel{display:block;height:12px;border-radius:4px;background:var(--raised);animation:skel 1.4s ease-in-out infinite} + .skel:nth-child(odd){width:82%} + @keyframes skel{50%{opacity:.45}} +-body.board-refused #board-view{display:none} ++ + body.on-bus #board-refused{display:none} + + /* Toast: one line, polite, bottom centre. */ diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M18.txt b/agents/darkwing/work/queue-53-review/r2/mut/M18.txt new file mode 100644 index 00000000..f8e4e68b --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M18.txt @@ -0,0 +1,56 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (3927.278203ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (4657.75327ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (5524.823411ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (257.569233ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (197.475849ms) +✔ bus refusals map to statuses and never carry a path or a stack (62.384222ms) +✔ humanCall speaks the human transport protocol without blocking the server (2352.562117ms) +✔ busReader takes --business, else the live bus host, else refuses (180.530201ms) +✔ humanCall kills a transport that runs past its timeout (533.606041ms) +✔ serve refuses a --business value that is not a business id (165.095593ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (4242.583993ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (2828.148222ms) +✔ conversation view: a newer session with no readable history keeps the marker (1663.099588ms) +✔ conversation view: seats without history say so and offer no reply (1125.53899ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (4488.22519ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (53962.334042ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (4220.745217ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (23229.025406ms) +✔ loopback host and board origin fail closed (11.407687ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (184.096852ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (295.763247ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1230.782963ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.468688ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (3.116895ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (4.445183ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (4761.914043ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (3437.488223ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 54409.271455 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (4761.914043ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + + 'block' !== 'none' + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:150:12) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: 'block', + expected: 'none', + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M19.diff b/agents/darkwing/work/queue-53-review/r2/mut/M19.diff new file mode 100644 index 00000000..26813879 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M19.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/bus.js b/packages/webui/src/public/bus.js +index 93df4371..de1a56b8 100644 +--- a/packages/webui/src/public/bus.js ++++ b/packages/webui/src/public/bus.js +@@ -433,7 +433,7 @@ + try { html = await view(live, path, new URLSearchParams(query)); readAt = live.oldest(); } + catch (err) { + const kept = reader(false); +- try { if (refusal(err)) throw err; html = await view(kept, path, new URLSearchParams(query)); readAt = kept.oldest(); html = staleBanner(err) + html; state = 'stale'; } ++ try { html = await view(kept, path, new URLSearchParams(query)); readAt = kept.oldest(); html = staleBanner(err) + html; state = 'stale'; } + catch { html = failedView(err); state = refusal(err) ? 'refused' : 'failed'; } + if (refusal(err)) forget(); + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M19.txt b/agents/darkwing/work/queue-53-review/r2/mut/M19.txt new file mode 100644 index 00000000..766b1372 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M19.txt @@ -0,0 +1,56 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (4453.411945ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (5264.477386ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (6343.176422ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (555.570309ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (154.111616ms) +✔ bus refusals map to statuses and never carry a path or a stack (80.416177ms) +✔ humanCall speaks the human transport protocol without blocking the server (2073.643449ms) +✔ busReader takes --business, else the live bus host, else refuses (267.731498ms) +✔ humanCall kills a transport that runs past its timeout (530.094794ms) +✔ serve refuses a --business value that is not a business id (169.493923ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (4369.121592ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (2242.808825ms) +✔ conversation view: a newer session with no readable history keeps the marker (1227.780012ms) +✔ conversation view: seats without history say so and offer no reply (917.943994ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (4861.316701ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (55068.800905ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (4414.74079ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (22879.258682ms) +✔ loopback host and board origin fail closed (8.430657ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (122.99485ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (126.993216ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1042.823066ms) +✔ tokens.css and icons.svg are byte copies of docs/design (0.949745ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.846898ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.237079ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (8600.36373ms) +✖ five states on Board, Inbox, Tasks, Agents and Trail (5870.56617ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 25 +ℹ fail 2 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 55530.663629 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (8600.36373ms) + Error: Uncaught (in promise) Error: Condition timed out: !!document.querySelector("#bus-view .banner.ref"): undefined + at Object.evaluate (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/browser.mjs:44:35) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:230:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) + +test at tests/shell.test.mjs:316:1 +✖ five states on Board, Inbox, Tasks, Agents and Trail (5870.56617ms) + Error: Uncaught (in promise) Error: Condition timed out: !!document.querySelector("#bus-view .banner.ref"): undefined + at Object.evaluate (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/browser.mjs:44:35) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:378:9) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M20.diff b/agents/darkwing/work/queue-53-review/r2/mut/M20.diff new file mode 100644 index 00000000..e3b7754c --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M20.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/app.js b/packages/webui/src/public/app.js +index 2084ff63..e9f550a1 100644 +--- a/packages/webui/src/public/app.js ++++ b/packages/webui/src/public/app.js +@@ -314,7 +314,7 @@ + $('status').textContent = 'Not read: the board refused the read'; + inspect(); convForm(); + } +- $('error').className = refused ? 'banner ref' : 'banner err'; ++ $('error').className = 'banner err'; + $('board-refused').hidden = !refused; document.body.classList.toggle('board-refused', refused); + $('error').innerHTML = refused + ? `

    The board refused the read. refused: ${esc(err.message)} Board: ${esc(board)}. Console shows nothing rather than a guess. Use Refresh to try again.

    ` diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M20.txt b/agents/darkwing/work/queue-53-review/r2/mut/M20.txt new file mode 100644 index 00000000..01c59928 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M20.txt @@ -0,0 +1,59 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (3790.126485ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (4070.339367ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (6162.782857ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (326.590311ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (396.862759ms) +✔ bus refusals map to statuses and never carry a path or a stack (110.608731ms) +✔ humanCall speaks the human transport protocol without blocking the server (2385.844223ms) +✔ busReader takes --business, else the live bus host, else refuses (254.94543ms) +✔ humanCall kills a transport that runs past its timeout (529.223498ms) +✔ serve refuses a --business value that is not a business id (220.172057ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (4138.868392ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (2853.917903ms) +✔ conversation view: a newer session with no readable history keeps the marker (1258.099466ms) +✔ conversation view: seats without history say so and offer no reply (812.16505ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (4183.301896ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (54639.801943ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (4094.058594ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (23424.360921ms) +✔ loopback host and board origin fail closed (16.59858ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (188.870931ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (278.788458ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1419.616783ms) +✔ tokens.css and icons.svg are byte copies of docs/design (4.12186ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (3.602968ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (5.209893ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (4052.812383ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (2860.652705ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 55419.923852 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (4052.812383ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + + actual - expected + + + 'banner err' + - 'banner ref' + ^ + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:148:12) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: 'banner err', + expected: 'banner ref', + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M21.diff b/agents/darkwing/work/queue-53-review/r2/mut/M21.diff new file mode 100644 index 00000000..197c1c19 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M21.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/bus.js b/packages/webui/src/public/bus.js +index 93df4371..dc273736 100644 +--- a/packages/webui/src/public/bus.js ++++ b/packages/webui/src/public/bus.js +@@ -370,7 +370,7 @@ + // A refusal fails closed: no kept data, the code in mono. Any other failure keeps the last read, labelled with its time. + const refusal = err => err.status === 403 || ['not-configured', 'no-bus-host'].includes(err.code); + // After a refusal nothing read before is shown anywhere: not in a view, the palette or the Inbox count. +- function forget() { last.clear(); inboxCount = null; } ++ function forget() {} + const failedView = err => `${head(failTitle(err))}${empty('Nothing to show.', refusal(err) ? 'The view stays empty until the problem above is fixed.' : 'Read again, or come back when the bus answers.')}`; + const staleBanner = err => ``; + // Freshness line in the command bar for bus pages. diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M21.txt b/agents/darkwing/work/queue-53-review/r2/mut/M21.txt new file mode 100644 index 00000000..182963e6 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M21.txt @@ -0,0 +1,56 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (3567.402844ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (4006.199314ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (5272.110688ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (304.233276ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (107.385725ms) +✔ bus refusals map to statuses and never carry a path or a stack (58.355469ms) +✔ humanCall speaks the human transport protocol without blocking the server (2413.175616ms) +✔ busReader takes --business, else the live bus host, else refuses (143.018572ms) +✔ humanCall kills a transport that runs past its timeout (529.454661ms) +✔ serve refuses a --business value that is not a business id (225.520972ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (3440.64227ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (2063.812556ms) +✔ conversation view: a newer session with no readable history keeps the marker (1146.976215ms) +✔ conversation view: seats without history say so and offer no reply (996.933872ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (3432.385645ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (53753.61663ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (3517.316598ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (22592.030121ms) +✔ loopback host and board origin fail closed (9.548699ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (116.171793ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (100.990811ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1426.440429ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.085029ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (1.918929ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.183322ms) +✔ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (6763.556991ms) +✖ five states on Board, Inbox, Tasks, Agents and Trail (1226.800369ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 54139.811347 + +✖ failing tests: + +test at tests/shell.test.mjs:316:1 +✖ five states on Board, Inbox, Tasks, Agents and Trail (1226.800369ms) + AssertionError [ERR_ASSERTION]: #/inbox drops the Inbox count on a human-required refusal + + 2 !== 0 + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:383:16) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: false, + code: 'ERR_ASSERTION', + actual: 2, + expected: 0, + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M22.diff b/agents/darkwing/work/queue-53-review/r2/mut/M22.diff new file mode 100644 index 00000000..544410e2 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M22.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/bus.js b/packages/webui/src/public/bus.js +index 93df4371..ac5ee574 100644 +--- a/packages/webui/src/public/bus.js ++++ b/packages/webui/src/public/bus.js +@@ -423,7 +423,7 @@ + // The board page keeps its own title; the Inbox count still follows the bus. + if (shown !== null) { shown = null; $('bus-view').innerHTML = ''; document.title = 'Mosaic Console'; if (navigated) $('main').focus(); } + try { const r = await fetchRead('inbox'); last.set('inbox', r); if (g === gen) { countInbox(r.rows); sections(path); } } +- catch (err) { if (refusal(err)) { forget(); if (g === gen) sections(path); } } ++ catch {} + if (g === gen) schedule(); + return; + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M22.txt b/agents/darkwing/work/queue-53-review/r2/mut/M22.txt new file mode 100644 index 00000000..d6ea9083 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M22.txt @@ -0,0 +1,47 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (3839.150823ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (4398.773937ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (5161.938687ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (257.233571ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (75.691859ms) +✔ bus refusals map to statuses and never carry a path or a stack (70.807746ms) +✔ humanCall speaks the human transport protocol without blocking the server (2116.92695ms) +✔ busReader takes --business, else the live bus host, else refuses (193.29717ms) +✔ humanCall kills a transport that runs past its timeout (549.215635ms) +✔ serve refuses a --business value that is not a business id (175.964255ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (4205.85625ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (2062.291696ms) +✔ conversation view: a newer session with no readable history keeps the marker (1227.269696ms) +✔ conversation view: seats without history say so and offer no reply (1221.050447ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (4210.391938ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (53870.242716ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (3848.544339ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (22700.192342ms) +✔ loopback host and board origin fail closed (8.406871ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (124.60245ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (103.540624ms) +✔ unreachable board reports URL; CLI rejects unsupported options (893.165438ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.457484ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.707206ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.687255ms) +✔ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (7388.987757ms) +✖ five states on Board, Inbox, Tasks, Agents and Trail (7624.873854ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 54287.706116 + +✖ failing tests: + +test at tests/shell.test.mjs:316:1 +✖ five states on Board, Inbox, Tasks, Agents and Trail (7624.873854ms) + Error: Uncaught (in promise) Error: Condition timed out: !document.querySelector("#sections .count"): undefined + at Object.evaluate (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/browser.mjs:44:35) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:418:68) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M23.diff b/agents/darkwing/work/queue-53-review/r2/mut/M23.diff new file mode 100644 index 00000000..19ee3de5 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M23.diff @@ -0,0 +1,12 @@ +diff --git a/packages/webui/src/public/bus.js b/packages/webui/src/public/bus.js +index 93df4371..76758e26 100644 +--- a/packages/webui/src/public/bus.js ++++ b/packages/webui/src/public/bus.js +@@ -435,7 +435,6 @@ + const kept = reader(false); + try { if (refusal(err)) throw err; html = await view(kept, path, new URLSearchParams(query)); readAt = kept.oldest(); html = staleBanner(err) + html; state = 'stale'; } + catch { html = failedView(err); state = refusal(err) ? 'refused' : 'failed'; } +- if (refusal(err)) forget(); + } + if (g !== gen) return; + freshBus(state); diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M23.txt b/agents/darkwing/work/queue-53-review/r2/mut/M23.txt new file mode 100644 index 00000000..661aab18 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M23.txt @@ -0,0 +1,56 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (3690.442184ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (3849.350418ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (5179.717435ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (231.525972ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (137.616984ms) +✔ bus refusals map to statuses and never carry a path or a stack (62.325904ms) +✔ humanCall speaks the human transport protocol without blocking the server (2171.007692ms) +✔ busReader takes --business, else the live bus host, else refuses (141.854219ms) +✔ humanCall kills a transport that runs past its timeout (528.99615ms) +✔ serve refuses a --business value that is not a business id (160.592221ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (3644.327268ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (2456.357644ms) +✔ conversation view: a newer session with no readable history keeps the marker (1296.77647ms) +✔ conversation view: seats without history say so and offer no reply (1069.763404ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (3612.07748ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (53490.878162ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (3605.370048ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (22582.383388ms) +✔ loopback host and board origin fail closed (9.211601ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (128.119652ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (107.85881ms) +✔ unreachable board reports URL; CLI rejects unsupported options (995.745599ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.903771ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.53098ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.427432ms) +✔ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (7142.657614ms) +✖ five states on Board, Inbox, Tasks, Agents and Trail (1130.262824ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 53881.267549 + +✖ failing tests: + +test at tests/shell.test.mjs:316:1 +✖ five states on Board, Inbox, Tasks, Agents and Trail (1130.262824ms) + AssertionError [ERR_ASSERTION]: #/inbox drops the Inbox count on a human-required refusal + + 2 !== 0 + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:383:16) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: false, + code: 'ERR_ASSERTION', + actual: 2, + expected: 0, + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M24.diff b/agents/darkwing/work/queue-53-review/r2/mut/M24.diff new file mode 100644 index 00000000..8b08aa4a --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M24.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/bus.js b/packages/webui/src/public/bus.js +index 93df4371..49e54847 100644 +--- a/packages/webui/src/public/bus.js ++++ b/packages/webui/src/public/bus.js +@@ -511,7 +511,7 @@ + pkBack = document.activeElement; pkAt = 0; $('cmdk-input').value = ''; + pkItems(); pkFill(); d.showModal(); $('cmdk-input').focus(); + Promise.allSettled(['inbox', 'tasks'].map(async v => last.set(v, await fetchRead(v)))).then(rs => { +- if (rs.some(r => r.status === 'rejected' && refusal(r.reason))) { forget(); sections(routeOf().split('?')[0]); } ++ + if (d.open) { pkItems(); pkFill(); } + }); + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M24.txt b/agents/darkwing/work/queue-53-review/r2/mut/M24.txt new file mode 100644 index 00000000..dac5d831 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M24.txt @@ -0,0 +1,47 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (3094.868838ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (4479.963024ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (5207.878049ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (253.189333ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (166.673421ms) +✔ bus refusals map to statuses and never carry a path or a stack (250.543874ms) +✔ humanCall speaks the human transport protocol without blocking the server (2711.339811ms) +✔ busReader takes --business, else the live bus host, else refuses (124.064744ms) +✔ humanCall kills a transport that runs past its timeout (528.361869ms) +✔ serve refuses a --business value that is not a business id (179.900947ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (2787.993908ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (2713.629338ms) +✔ conversation view: a newer session with no readable history keeps the marker (1517.334847ms) +✔ conversation view: seats without history say so and offer no reply (1262.349937ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (2789.431642ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (53580.275598ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (2782.596251ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (22064.392292ms) +✔ loopback host and board origin fail closed (7.027509ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (107.473266ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (83.115149ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1860.131739ms) +✔ tokens.css and icons.svg are byte copies of docs/design (0.88699ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (1.960146ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (1.992866ms) +✔ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (6498.656891ms) +✖ five states on Board, Inbox, Tasks, Agents and Trail (7332.608632ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 54368.682085 + +✖ failing tests: + +test at tests/shell.test.mjs:316:1 +✖ five states on Board, Inbox, Tasks, Agents and Trail (7332.608632ms) + Error: Uncaught (in promise) Error: Condition timed out: document.querySelector("#cmdk-dialog").open && [...document.querySelectorAll("#cmdk-list [data-href]")].map(e=>e.dataset.href).length===4 && !document.querySelector("#sections .count"): undefined + at Object.evaluate (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/browser.mjs:44:35) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:405:34) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M25.diff b/agents/darkwing/work/queue-53-review/r2/mut/M25.diff new file mode 100644 index 00000000..99cf7a15 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M25.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/app.js b/packages/webui/src/public/app.js +index 2084ff63..510aea43 100644 +--- a/packages/webui/src/public/app.js ++++ b/packages/webui/src/public/app.js +@@ -307,7 +307,7 @@ + const refused = err.status === 403; + failed = refused ? 'refused' : true; $('error').hidden = false; + if (refused) { +- data = null; selected = null; project = null; ++ data = null; project = null; + $('projects').innerHTML = '

    Not read: the board refused the read.

    '; + for (const id of ['waiting-count', 'seen-count', 'session-count']) $(id).textContent = '–'; + $('footer').textContent = 'Board not read: refused'; diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M25.txt b/agents/darkwing/work/queue-53-review/r2/mut/M25.txt new file mode 100644 index 00000000..8b80cd93 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M25.txt @@ -0,0 +1,56 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (3086.813365ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (3278.687202ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (5638.664355ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (239.637465ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (197.053056ms) +✔ bus refusals map to statuses and never carry a path or a stack (168.899142ms) +✔ humanCall speaks the human transport protocol without blocking the server (2952.702683ms) +✔ busReader takes --business, else the live bus host, else refuses (114.932507ms) +✔ humanCall kills a transport that runs past its timeout (528.008507ms) +✔ serve refuses a --business value that is not a business id (168.452683ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (3069.725175ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (2812.549981ms) +✔ conversation view: a newer session with no readable history keeps the marker (1122.606966ms) +✔ conversation view: seats without history say so and offer no reply (769.203298ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (2877.518379ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (53655.195021ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (2938.919633ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (22116.008047ms) +✔ loopback host and board origin fail closed (6.758241ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (112.880418ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (110.760082ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1924.942791ms) +✔ tokens.css and icons.svg are byte copies of docs/design (0.902975ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (1.804197ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.006071ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (2930.528977ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (3482.984298ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 54060.857983 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (2930.528977ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + + false !== true + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:152:12) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: false, + expected: true, + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M26.diff b/agents/darkwing/work/queue-53-review/r2/mut/M26.diff new file mode 100644 index 00000000..0b0edd2a --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M26.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/app.js b/packages/webui/src/public/app.js +index 2084ff63..2de73dc9 100644 +--- a/packages/webui/src/public/app.js ++++ b/packages/webui/src/public/app.js +@@ -282,7 +282,7 @@ + // Freshness line in the command bar: when the board last scanned, and warning words when the last refresh failed. + function fresh() { + const at = Date.parse(data?.generatedAt), ago = Number.isFinite(at) ? age(Math.max(0, Math.round((Date.now() - at) / 1000))) : null; +- if (!data) { $('fresh-board').innerHTML = failed === 'refused' ? 'Board not read: refused' : failed ? 'Board not read: the read failed' : 'Board not read yet'; return; } ++ if (!data) { $('fresh-board').innerHTML = failed ? 'Board not read: the read failed' : 'Board not read yet'; return; } + const scan = `Board scanned ${esc(Number.isFinite(at) ? `${new Date(at).toISOString().slice(11, 19)} UTC` : 'unknown')}${ago ? ` (${ago} ago)` : ''}`; + $('fresh-board').innerHTML = failed ? `${scan} · stale: the last refresh failed` : scan; + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M26.txt b/agents/darkwing/work/queue-53-review/r2/mut/M26.txt new file mode 100644 index 00000000..d63603fc --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M26.txt @@ -0,0 +1,59 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (2968.889817ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (3226.573849ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (5700.168779ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (266.368346ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (289.193528ms) +✔ bus refusals map to statuses and never carry a path or a stack (576.468911ms) +✔ humanCall speaks the human transport protocol without blocking the server (2511.116714ms) +✔ busReader takes --business, else the live bus host, else refuses (430.389135ms) +✔ humanCall kills a transport that runs past its timeout (528.253433ms) +✔ serve refuses a --business value that is not a business id (190.157217ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (2961.036578ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (2837.798308ms) +✔ conversation view: a newer session with no readable history keeps the marker (1272.634327ms) +✔ conversation view: seats without history say so and offer no reply (831.966075ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (2864.021743ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (53178.274663ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (2862.922541ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (22346.280842ms) +✔ loopback host and board origin fail closed (7.233985ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (103.43982ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (83.580754ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1875.027395ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.192019ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.359592ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.448547ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (2864.793151ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (3930.695527ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 53561.128538 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (2864.793151ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + + actual - expected + + + 'Board not read: the read failed' + - 'Board not read: refused' + ^ + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:156:12) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: 'Board not read: the read failed', + expected: 'Board not read: refused', + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M27.diff b/agents/darkwing/work/queue-53-review/r2/mut/M27.diff new file mode 100644 index 00000000..7244863d --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M27.diff @@ -0,0 +1,12 @@ +diff --git a/packages/webui/src/public/app.js b/packages/webui/src/public/app.js +index 2084ff63..e34ee5fd 100644 +--- a/packages/webui/src/public/app.js ++++ b/packages/webui/src/public/app.js +@@ -310,7 +310,6 @@ + data = null; selected = null; project = null; + $('projects').innerHTML = '

    Not read: the board refused the read.

    '; + for (const id of ['waiting-count', 'seen-count', 'session-count']) $(id).textContent = '–'; +- $('footer').textContent = 'Board not read: refused'; + $('status').textContent = 'Not read: the board refused the read'; + inspect(); convForm(); + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M27.txt b/agents/darkwing/work/queue-53-review/r2/mut/M27.txt new file mode 100644 index 00000000..79f9fbc0 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M27.txt @@ -0,0 +1,58 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (3246.245856ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (3674.93145ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (5179.540346ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (239.681337ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (196.812069ms) +✔ bus refusals map to statuses and never carry a path or a stack (44.758167ms) +✔ humanCall speaks the human transport protocol without blocking the server (2933.216401ms) +✔ busReader takes --business, else the live bus host, else refuses (107.108112ms) +✔ humanCall kills a transport that runs past its timeout (529.400306ms) +✔ serve refuses a --business value that is not a business id (161.249002ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (3218.875059ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (2575.330787ms) +✔ conversation view: a newer session with no readable history keeps the marker (1147.311364ms) +✔ conversation view: seats without history say so and offer no reply (804.925523ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (2689.75633ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (53854.571559ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (2860.421809ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (22255.535822ms) +✔ loopback host and board origin fail closed (8.336514ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (118.861441ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (95.830197ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1834.666373ms) +✔ tokens.css and icons.svg are byte copies of docs/design (0.986879ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (1.98463ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.208649ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (2883.477769ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (2756.953859ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 54274.036903 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (2883.477769ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + + actual - expected + + + 'waiting 1 · working 1' + - 'Board not read: refused' + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:155:12) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: 'waiting 1 · working 1', + expected: 'Board not read: refused', + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M28.diff b/agents/darkwing/work/queue-53-review/r2/mut/M28.diff new file mode 100644 index 00000000..35ab963c --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M28.diff @@ -0,0 +1,12 @@ +diff --git a/packages/webui/src/public/app.js b/packages/webui/src/public/app.js +index 2084ff63..169e8e0c 100644 +--- a/packages/webui/src/public/app.js ++++ b/packages/webui/src/public/app.js +@@ -311,7 +311,6 @@ + $('projects').innerHTML = '

    Not read: the board refused the read.

    '; + for (const id of ['waiting-count', 'seen-count', 'session-count']) $(id).textContent = '–'; + $('footer').textContent = 'Board not read: refused'; +- $('status').textContent = 'Not read: the board refused the read'; + inspect(); convForm(); + } + $('error').className = refused ? 'banner ref' : 'banner err'; diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M28.txt b/agents/darkwing/work/queue-53-review/r2/mut/M28.txt new file mode 100644 index 00000000..4a4bd93b --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M28.txt @@ -0,0 +1,56 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (3550.51874ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (5312.307526ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (5616.759717ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (260.854664ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (91.58931ms) +✔ bus refusals map to statuses and never carry a path or a stack (159.936555ms) +✔ humanCall speaks the human transport protocol without blocking the server (2972.254326ms) +✔ busReader takes --business, else the live bus host, else refuses (165.485236ms) +✔ humanCall kills a transport that runs past its timeout (547.85034ms) +✔ serve refuses a --business value that is not a business id (162.092336ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (3539.736538ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (3160.834001ms) +✔ conversation view: a newer session with no readable history keeps the marker (1301.74645ms) +✔ conversation view: seats without history say so and offer no reply (826.83122ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (2888.780959ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (54197.380733ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (3020.912636ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (22115.319317ms) +✔ loopback host and board origin fail closed (9.401662ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (119.854295ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (321.466276ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1709.391542ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.258316ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.899559ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.650272ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (2910.736129ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (4240.183759ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 54846.778865 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (2910.736129ms) + AssertionError [ERR_ASSERTION]: The input was expected to not match the regular expression /Scanned/. Input: + + 'Scanned 2026-10-10T18:51:40.678Z · refresh every 10s' + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:157:12) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: 'Scanned 2026-10-10T18:51:40.678Z · refresh every 10s', + expected: /Scanned/, + operator: 'doesNotMatch', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M29.diff b/agents/darkwing/work/queue-53-review/r2/mut/M29.diff new file mode 100644 index 00000000..0b73bd01 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M29.diff @@ -0,0 +1,12 @@ +diff --git a/packages/webui/src/public/app.js b/packages/webui/src/public/app.js +index 2084ff63..9a94ec51 100644 +--- a/packages/webui/src/public/app.js ++++ b/packages/webui/src/public/app.js +@@ -308,7 +308,6 @@ + failed = refused ? 'refused' : true; $('error').hidden = false; + if (refused) { + data = null; selected = null; project = null; +- $('projects').innerHTML = '

    Not read: the board refused the read.

    '; + for (const id of ['waiting-count', 'seen-count', 'session-count']) $(id).textContent = '–'; + $('footer').textContent = 'Board not read: refused'; + $('status').textContent = 'Not read: the board refused the read'; diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M29.txt b/agents/darkwing/work/queue-53-review/r2/mut/M29.txt new file mode 100644 index 00000000..52f34252 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M29.txt @@ -0,0 +1,56 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (3943.764665ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (4161.06461ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (5544.885357ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (621.447301ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (179.59438ms) +✔ bus refusals map to statuses and never carry a path or a stack (130.608711ms) +✔ humanCall speaks the human transport protocol without blocking the server (2724.299629ms) +✔ busReader takes --business, else the live bus host, else refuses (110.308126ms) +✔ humanCall kills a transport that runs past its timeout (528.747596ms) +✔ serve refuses a --business value that is not a business id (188.683838ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (3892.153976ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (2405.469187ms) +✔ conversation view: a newer session with no readable history keeps the marker (1162.017836ms) +✔ conversation view: seats without history say so and offer no reply (811.669296ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (2843.374378ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (54334.298298ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (2861.443553ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (22345.735665ms) +✔ loopback host and board origin fail closed (6.544532ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (105.279642ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (306.595913ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1904.82471ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.160351ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.292111ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.341858ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (2793.054072ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (3257.19315ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 54777.426057 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (2793.054072ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + + 4 !== 0 + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:154:12) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: 4, + expected: 0, + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M30.diff b/agents/darkwing/work/queue-53-review/r2/mut/M30.diff new file mode 100644 index 00000000..e77b2706 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M30.diff @@ -0,0 +1,12 @@ +diff --git a/packages/webui/src/public/app.js b/packages/webui/src/public/app.js +index 2084ff63..33702149 100644 +--- a/packages/webui/src/public/app.js ++++ b/packages/webui/src/public/app.js +@@ -309,7 +309,6 @@ + if (refused) { + data = null; selected = null; project = null; + $('projects').innerHTML = '

    Not read: the board refused the read.

    '; +- for (const id of ['waiting-count', 'seen-count', 'session-count']) $(id).textContent = '–'; + $('footer').textContent = 'Board not read: refused'; + $('status').textContent = 'Not read: the board refused the read'; + inspect(); convForm(); diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M30.txt b/agents/darkwing/work/queue-53-review/r2/mut/M30.txt new file mode 100644 index 00000000..056b0667 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M30.txt @@ -0,0 +1,36 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (4287.251342ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (4257.078572ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (4787.813726ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (248.673864ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (108.850367ms) +✔ bus refusals map to statuses and never carry a path or a stack (57.034728ms) +✔ humanCall speaks the human transport protocol without blocking the server (2123.171508ms) +✔ busReader takes --business, else the live bus host, else refuses (181.909869ms) +✔ humanCall kills a transport that runs past its timeout (528.763166ms) +✔ serve refuses a --business value that is not a business id (158.778448ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (4196.796291ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (1947.944484ms) +✔ conversation view: a newer session with no readable history keeps the marker (1219.575356ms) +✔ conversation view: seats without history say so and offer no reply (966.856189ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (4154.261341ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (53503.07169ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (3990.479246ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (22660.736326ms) +✔ loopback host and board origin fail closed (8.965093ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (126.518024ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (104.109094ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1039.219515ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.241848ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.50003ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.17149ms) +✔ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (6799.567456ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (2563.79395ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 27 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 53936.307319 diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M31.diff b/agents/darkwing/work/queue-53-review/r2/mut/M31.diff new file mode 100644 index 00000000..4ea44ad5 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M31.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/bus.js b/packages/webui/src/public/bus.js +index 93df4371..bfe9075b 100644 +--- a/packages/webui/src/public/bus.js ++++ b/packages/webui/src/public/bus.js +@@ -376,7 +376,7 @@ + // Freshness line in the command bar for bus pages. + const stamp = iso => { const t = Date.parse(iso); return Number.isFinite(t) ? `${new Date(t).toISOString().slice(11, 19)} UTC` : 'unknown'; }; + function freshBus(state) { +- $('fresh-bus').innerHTML = state === 'refused' ? 'Bus not read: refused' : state === 'failed' ? 'Bus not read: the read failed' ++ $('fresh-bus').innerHTML = state === 'failed' ? 'Bus not read: the read failed' + : `Bus read ${esc(stamp(readAt))}${readAt ? ` (${esc(ago(readAt))})` : ''}${state === 'stale' ? ' · stale: the last read failed' : ''}`; + } + diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M31.txt b/agents/darkwing/work/queue-53-review/r2/mut/M31.txt new file mode 100644 index 00000000..bae57695 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M31.txt @@ -0,0 +1,80 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (4019.454985ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (4218.465523ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (5722.957436ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (288.58676ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (146.939199ms) +✔ bus refusals map to statuses and never carry a path or a stack (263.376856ms) +✔ humanCall speaks the human transport protocol without blocking the server (2922.82782ms) +✔ busReader takes --business, else the live bus host, else refuses (244.943803ms) +✔ humanCall kills a transport that runs past its timeout (530.490728ms) +✔ serve refuses a --business value that is not a business id (308.685115ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (4008.930441ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (2357.061135ms) +✔ conversation view: a newer session with no readable history keeps the marker (1100.14734ms) +✔ conversation view: seats without history say so and offer no reply (799.501081ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (2671.451659ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (53877.624865ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (2890.013136ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (22280.584605ms) +✔ loopback host and board origin fail closed (9.459608ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (150.74983ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (98.568173ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1760.354168ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.048301ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (1.876693ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.620976ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (4024.870689ms) +✖ five states on Board, Inbox, Tasks, Agents and Trail (2076.962299ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 25 +ℹ fail 2 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 54355.140712 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (4024.870689ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + + actual - expected + + + 'Bus read 18:54:25 UTC (0 s ago)' + - 'Bus not read: refused' + ^ + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:234:12) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: 'Bus read 18:54:25 UTC (0 s ago)', + expected: 'Bus not read: refused', + operator: 'strictEqual', + diff: 'simple' + } + +test at tests/shell.test.mjs:316:1 +✖ five states on Board, Inbox, Tasks, Agents and Trail (2076.962299ms) + AssertionError [ERR_ASSERTION]: #/inbox + + actual - expected + + + 'Bus read 18:54:28 UTC (0 s ago)' + - 'Bus not read: refused' + ^ + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:382:16) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: false, + code: 'ERR_ASSERTION', + actual: 'Bus read 18:54:28 UTC (0 s ago)', + expected: 'Bus not read: refused', + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M32.diff b/agents/darkwing/work/queue-53-review/r2/mut/M32.diff new file mode 100644 index 00000000..6884168b --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M32.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/shell.css b/packages/webui/src/public/shell.css +index ed6d2d96..14821b7b 100644 +--- a/packages/webui/src/public/shell.css ++++ b/packages/webui/src/public/shell.css +@@ -103,7 +103,7 @@ body.on-bus #board-refused{display:none} + /* Toast: one line, polite, bottom centre. */ + .toast{position:fixed;left:50%;bottom:16px;transform:translateX(-50%);display:flex;align-items:center;gap:10px;background:var(--strong);color:var(--surface);padding:6px 8px 6px 14px;border-radius:var(--r);font-size:13px;z-index:60;max-width:calc(100% - 24px);box-shadow:var(--shadow)} + /* Off, the toast stays in the accessibility tree, empty and visually hidden, so the first copy is announced. */ +-.toast:not(.on){width:1px;height:1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;box-shadow:none} ++.toast:not(.on){display:none} + .toast span{min-width:0;overflow-wrap:anywhere} + .toast.err{background:var(--danger)} + .toast button{font:inherit;font-weight:600;border:1px solid currentColor;background:none;color:inherit;border-radius:4px;padding:1px 8px;cursor:pointer} diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M32.txt b/agents/darkwing/work/queue-53-review/r2/mut/M32.txt new file mode 100644 index 00000000..6ad67b23 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M32.txt @@ -0,0 +1,63 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (3328.993527ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (3531.78405ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (5447.140363ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (269.185034ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (125.783547ms) +✔ bus refusals map to statuses and never carry a path or a stack (145.763412ms) +✔ humanCall speaks the human transport protocol without blocking the server (2793.230461ms) +✔ busReader takes --business, else the live bus host, else refuses (120.744303ms) +✔ humanCall kills a transport that runs past its timeout (588.228776ms) +✔ serve refuses a --business value that is not a business id (158.710131ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (3282.87396ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (2349.879429ms) +✔ conversation view: a newer session with no readable history keeps the marker (1255.661234ms) +✔ conversation view: seats without history say so and offer no reply (834.227184ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (2771.824123ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (53870.749227ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (3156.662852ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (22133.981151ms) +✔ loopback host and board origin fail closed (8.165648ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (133.174467ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (104.076118ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1812.887702ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.313076ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.501953ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.280554ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (3339.870267ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (3129.879391ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 54285.916301 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (3339.870267ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: + + actual - expected + + [ + + false, + - true, + 'visible', + '', + true + ] + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:199:12) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: [ false, 'visible', '', true ], + expected: [ true, 'visible', '', true ], + operator: 'deepStrictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M33.diff b/agents/darkwing/work/queue-53-review/r2/mut/M33.diff new file mode 100644 index 00000000..75d13d7f --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M33.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/bus.js b/packages/webui/src/public/bus.js +index 93df4371..4ceace5b 100644 +--- a/packages/webui/src/public/bus.js ++++ b/packages/webui/src/public/bus.js +@@ -370,7 +370,7 @@ + // A refusal fails closed: no kept data, the code in mono. Any other failure keeps the last read, labelled with its time. + const refusal = err => err.status === 403 || ['not-configured', 'no-bus-host'].includes(err.code); + // After a refusal nothing read before is shown anywhere: not in a view, the palette or the Inbox count. +- function forget() { last.clear(); inboxCount = null; } ++ function forget() { last.clear(); } + const failedView = err => `${head(failTitle(err))}${empty('Nothing to show.', refusal(err) ? 'The view stays empty until the problem above is fixed.' : 'Read again, or come back when the bus answers.')}`; + const staleBanner = err => ``; + // Freshness line in the command bar for bus pages. diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M33.txt b/agents/darkwing/work/queue-53-review/r2/mut/M33.txt new file mode 100644 index 00000000..6a5921a3 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M33.txt @@ -0,0 +1,56 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (3126.358489ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (4118.593367ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (5006.994875ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (293.322998ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (179.622323ms) +✔ bus refusals map to statuses and never carry a path or a stack (244.651528ms) +✔ humanCall speaks the human transport protocol without blocking the server (2463.711647ms) +✔ busReader takes --business, else the live bus host, else refuses (126.115149ms) +✔ humanCall kills a transport that runs past its timeout (528.077583ms) +✔ serve refuses a --business value that is not a business id (153.121325ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (2776.188695ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (2558.872677ms) +✔ conversation view: a newer session with no readable history keeps the marker (1138.046042ms) +✔ conversation view: seats without history say so and offer no reply (1204.449823ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (2668.08359ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (53852.495895ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (2670.260808ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (22057.59907ms) +✔ loopback host and board origin fail closed (8.782534ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (130.541717ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (140.203928ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1610.160969ms) +✔ tokens.css and icons.svg are byte copies of docs/design (0.884644ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (1.761476ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (1.839968ms) +✔ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (6358.781073ms) +✖ five states on Board, Inbox, Tasks, Agents and Trail (1322.190764ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 54329.286857 + +✖ failing tests: + +test at tests/shell.test.mjs:316:1 +✖ five states on Board, Inbox, Tasks, Agents and Trail (1322.190764ms) + AssertionError [ERR_ASSERTION]: #/inbox drops the Inbox count on a human-required refusal + + 2 !== 0 + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:383:16) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: false, + code: 'ERR_ASSERTION', + actual: 2, + expected: 0, + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M34.diff b/agents/darkwing/work/queue-53-review/r2/mut/M34.diff new file mode 100644 index 00000000..b7cff8e9 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M34.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/bus.js b/packages/webui/src/public/bus.js +index 93df4371..c2eacbe1 100644 +--- a/packages/webui/src/public/bus.js ++++ b/packages/webui/src/public/bus.js +@@ -370,7 +370,7 @@ + // A refusal fails closed: no kept data, the code in mono. Any other failure keeps the last read, labelled with its time. + const refusal = err => err.status === 403 || ['not-configured', 'no-bus-host'].includes(err.code); + // After a refusal nothing read before is shown anywhere: not in a view, the palette or the Inbox count. +- function forget() { last.clear(); inboxCount = null; } ++ function forget() { inboxCount = null; } + const failedView = err => `${head(failTitle(err))}${empty('Nothing to show.', refusal(err) ? 'The view stays empty until the problem above is fixed.' : 'Read again, or come back when the bus answers.')}`; + const staleBanner = err => ``; + // Freshness line in the command bar for bus pages. diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M34.txt b/agents/darkwing/work/queue-53-review/r2/mut/M34.txt new file mode 100644 index 00000000..e5dc99f7 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M34.txt @@ -0,0 +1,65 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (3007.173261ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (3855.294086ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (5615.842981ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (261.282923ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (93.524702ms) +✔ bus refusals map to statuses and never carry a path or a stack (152.594397ms) +✔ humanCall speaks the human transport protocol without blocking the server (3222.083926ms) +✔ busReader takes --business, else the live bus host, else refuses (80.345244ms) +✔ humanCall kills a transport that runs past its timeout (575.740134ms) +✔ serve refuses a --business value that is not a business id (190.165655ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (2882.103601ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (2486.2508ms) +✔ conversation view: a newer session with no readable history keeps the marker (1177.664134ms) +✔ conversation view: seats without history say so and offer no reply (1284.697782ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (2706.579171ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (53381.0835ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (2781.75392ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (22306.183997ms) +✔ loopback host and board origin fail closed (7.394334ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (107.914025ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (97.224984ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1885.353532ms) +✔ tokens.css and icons.svg are byte copies of docs/design (0.899596ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (1.989552ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (1.889945ms) +✔ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (6673.23278ms) +✖ five states on Board, Inbox, Tasks, Agents and Trail (2369.587424ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 53793.045051 + +✖ failing tests: + +test at tests/shell.test.mjs:316:1 +✖ five states on Board, Inbox, Tasks, Agents and Trail (2369.587424ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: + + actual - expected + + [ + '#/', + '#/inbox', + '#/tasks', + '#/agents', + + '#/inbox/dddddddddddddddddddddddddddddddd', + + '#/tasks/vikunja%3A32%2F7', + + '#/tasks/vikunja%3A32%2F8' + ] + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:397:12) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: [ '#/', '#/inbox', '#/tasks', '#/agents', '#/inbox/dddddddddddddddddddddddddddddddd', '#/tasks/vikunja%3A32%2F7', '#/tasks/vikunja%3A32%2F8' ], + expected: [ '#/', '#/inbox', '#/tasks', '#/agents' ], + operator: 'deepStrictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M35.diff b/agents/darkwing/work/queue-53-review/r2/mut/M35.diff new file mode 100644 index 00000000..3576879d --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M35.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/app.js b/packages/webui/src/public/app.js +index 2084ff63..5ca3d420 100644 +--- a/packages/webui/src/public/app.js ++++ b/packages/webui/src/public/app.js +@@ -283,7 +283,7 @@ + function fresh() { + const at = Date.parse(data?.generatedAt), ago = Number.isFinite(at) ? age(Math.max(0, Math.round((Date.now() - at) / 1000))) : null; + if (!data) { $('fresh-board').innerHTML = failed === 'refused' ? 'Board not read: refused' : failed ? 'Board not read: the read failed' : 'Board not read yet'; return; } +- const scan = `Board scanned ${esc(Number.isFinite(at) ? `${new Date(at).toISOString().slice(11, 19)} UTC` : 'unknown')}${ago ? ` (${ago} ago)` : ''}`; ++ const scan = `Board scanned ${esc(Number.isFinite(at) ? new Date(at).toLocaleTimeString([], { hour12: false }) : 'unknown')}${ago ? ` (${ago} ago)` : ''}`; + $('fresh-board').innerHTML = failed ? `${scan} · stale: the last refresh failed` : scan; + } + setInterval(() => { if (data) fresh(); }, 5000); diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M35.txt b/agents/darkwing/work/queue-53-review/r2/mut/M35.txt new file mode 100644 index 00000000..d81e925d --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M35.txt @@ -0,0 +1,56 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (3672.88716ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (3626.292542ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (6049.955031ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (298.139781ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (384.361372ms) +✔ bus refusals map to statuses and never carry a path or a stack (95.057268ms) +✔ humanCall speaks the human transport protocol without blocking the server (2630.859361ms) +✔ busReader takes --business, else the live bus host, else refuses (153.24859ms) +✔ humanCall kills a transport that runs past its timeout (530.057319ms) +✔ serve refuses a --business value that is not a business id (149.60264ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (3646.12638ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (2657.957896ms) +✔ conversation view: a newer session with no readable history keeps the marker (1187.981349ms) +✔ conversation view: seats without history say so and offer no reply (824.394033ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (3514.633496ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (54861.537569ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (3495.154258ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (22156.108066ms) +✔ loopback host and board origin fail closed (6.632866ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (109.752328ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (116.522219ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1874.392891ms) +✔ tokens.css and icons.svg are byte copies of docs/design (0.924477ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (1.681684ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.146795ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (3244.793375ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (3494.281686ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 55222.326952 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (3244.793375ms) + AssertionError [ERR_ASSERTION]: The input did not match the regular expression /^Board scanned \d\d:\d\d:\d\d UTC/. Input: + + 'Board scanned 13:57:59 (2s ago)' + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:128:12) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: 'Board scanned 13:57:59 (2s ago)', + expected: /^Board scanned \d\d:\d\d:\d\d UTC/, + operator: 'match', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M36.diff b/agents/darkwing/work/queue-53-review/r2/mut/M36.diff new file mode 100644 index 00000000..93520848 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M36.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/shell.css b/packages/webui/src/public/shell.css +index ed6d2d96..c3c3d718 100644 +--- a/packages/webui/src/public/shell.css ++++ b/packages/webui/src/public/shell.css +@@ -166,7 +166,7 @@ body.on-bus #board-refused{display:none} + .cmd-right label{flex:1 1 0;min-width:0} + .cmd-right .btn{flex:none} + /* The section list is one strip that scrolls inside itself (IMPLEMENTING.md), so more sections never add rows. */ +- .s1-sections{display:flex;flex-wrap:nowrap;overflow-x:auto;flex-basis:100%;min-width:0;max-width:100%;gap:2px;padding-bottom:2px;scrollbar-width:thin} ++ .s1-sections{display:flex;flex-wrap:nowrap;overflow-x:visible;flex-basis:100%;min-width:0;max-width:100%;gap:2px;padding-bottom:2px;scrollbar-width:thin} + .s1-sections>li{flex:none} + .s1-section{border-radius:var(--r);padding:5px 8px;white-space:nowrap;flex:none} + .inspector{inset:0;top:0;width:100%;z-index:40;box-shadow:none} diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M36.txt b/agents/darkwing/work/queue-53-review/r2/mut/M36.txt new file mode 100644 index 00000000..85c9e3a8 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M36.txt @@ -0,0 +1,53 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (5211.322674ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (5406.834792ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (7967.747109ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (291.194633ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (167.355846ms) +✔ bus refusals map to statuses and never carry a path or a stack (301.032325ms) +✔ humanCall speaks the human transport protocol without blocking the server (2370.843823ms) +✔ busReader takes --business, else the live bus host, else refuses (511.36435ms) +✔ humanCall kills a transport that runs past its timeout (528.862393ms) +✔ serve refuses a --business value that is not a business id (163.431821ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (5370.262527ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (4365.992749ms) +✔ conversation view: a newer session with no readable history keeps the marker (2791.289399ms) +✔ conversation view: seats without history say so and offer no reply (1223.433429ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (5354.865178ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (56830.63505ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (5434.62527ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (22694.896098ms) +✔ loopback host and board origin fail closed (9.937835ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (137.366904ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (141.117982ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1498.910339ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.431161ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.986511ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.729744ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (5309.354326ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (6092.066387ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 57366.349902 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (5309.354326ms) + AssertionError [ERR_ASSERTION]: strip scrolls at 360px + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:205:14) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: false, + code: 'ERR_ASSERTION', + actual: 'visible', + expected: /^(auto|scroll)$/, + operator: 'match', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M37.diff b/agents/darkwing/work/queue-53-review/r2/mut/M37.diff new file mode 100644 index 00000000..57fd4d52 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M37.diff @@ -0,0 +1,13 @@ +diff --git a/packages/webui/src/public/shell.css b/packages/webui/src/public/shell.css +index ed6d2d96..77fc8ff8 100644 +--- a/packages/webui/src/public/shell.css ++++ b/packages/webui/src/public/shell.css +@@ -166,7 +166,7 @@ body.on-bus #board-refused{display:none} + .cmd-right label{flex:1 1 0;min-width:0} + .cmd-right .btn{flex:none} + /* The section list is one strip that scrolls inside itself (IMPLEMENTING.md), so more sections never add rows. */ +- .s1-sections{display:flex;flex-wrap:nowrap;overflow-x:auto;flex-basis:100%;min-width:0;max-width:100%;gap:2px;padding-bottom:2px;scrollbar-width:thin} ++ .s1-sections{display:flex;flex-wrap:wrap;overflow-x:auto;flex-basis:100%;min-width:0;max-width:100%;gap:2px;padding-bottom:2px;scrollbar-width:thin} + .s1-sections>li{flex:none} + .s1-section{border-radius:var(--r);padding:5px 8px;white-space:nowrap;flex:none} + .inspector{inset:0;top:0;width:100%;z-index:40;box-shadow:none} diff --git a/agents/darkwing/work/queue-53-review/r2/mut/M37.txt b/agents/darkwing/work/queue-53-review/r2/mut/M37.txt new file mode 100644 index 00000000..47e08341 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/M37.txt @@ -0,0 +1,56 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (5754.769823ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (5803.927596ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (8809.823038ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (355.250288ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (113.044848ms) +✔ bus refusals map to statuses and never carry a path or a stack (74.932958ms) +✔ humanCall speaks the human transport protocol without blocking the server (2169.690829ms) +✔ busReader takes --business, else the live bus host, else refuses (700.614062ms) +✔ humanCall kills a transport that runs past its timeout (529.626355ms) +✔ serve refuses a --business value that is not a business id (157.707334ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (5687.132751ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (4440.235802ms) +✔ conversation view: a newer session with no readable history keeps the marker (2682.046974ms) +✔ conversation view: seats without history say so and offer no reply (2581.852312ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (5716.272685ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (57961.778739ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (5798.600313ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (23168.713365ms) +✔ loopback host and board origin fail closed (10.029846ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (119.87584ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (116.102285ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1062.369733ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.26065ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.576684ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.555527ms) +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (5642.483696ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (5046.143675ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 26 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 58384.246613 + +✖ failing tests: + +test at tests/shell.test.mjs:88:1 +✖ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (5642.483696ms) + AssertionError [ERR_ASSERTION]: one row at 360px + + 2 !== 1 + + at TestContext. (file:///home/jwoltje/darkwing-scratch/r53b/mutwt/packages/webui/tests/shell.test.mjs:204:14) + at process.processTicksAndRejections (node:internal/process/task_queues:104:5) + at async Test.run (node:internal/test_runner/test:1409:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) { + generatedMessage: false, + code: 'ERR_ASSERTION', + actual: 2, + expected: 1, + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/darkwing/work/queue-53-review/r2/mut/manifest-after.txt b/agents/darkwing/work/queue-53-review/r2/mut/manifest-after.txt new file mode 100644 index 00000000..5f69a82a --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/manifest-after.txt @@ -0,0 +1,16 @@ +packages/webui/README.md: OK +packages/webui/src/public/app.js: OK +packages/webui/src/public/assets/fonts/jetbrains-mono-400.woff2: OK +packages/webui/src/public/assets/fonts/jetbrains-mono-500.woff2: OK +packages/webui/src/public/assets/fonts/jetbrains-mono-700.woff2: OK +packages/webui/src/public/assets/fonts/jetbrains-mono-OFL.txt: OK +packages/webui/src/public/assets/fonts/jetbrains-mono-sources.txt: OK +packages/webui/src/public/bus.js: OK +packages/webui/src/public/icons.svg: OK +packages/webui/src/public/index.html: OK +packages/webui/src/public/shell.css: OK +packages/webui/src/public/tokens.css: OK +packages/webui/src/serve.mjs: OK +packages/webui/tests/browser.mjs: OK +packages/webui/tests/serve.test.mjs: OK +packages/webui/tests/shell.test.mjs: OK diff --git a/agents/darkwing/work/queue-53-review/r2/mut/mutate.py b/agents/darkwing/work/queue-53-review/r2/mut/mutate.py new file mode 100644 index 00000000..0a1506f1 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/mutate.py @@ -0,0 +1,48 @@ +# mutate.py : apply one named mutant to the candidate (exact text, must match once). Run from the tree root. +import sys +B, A, C, S, H = "packages/webui/src/public/bus.js", "packages/webui/src/public/app.js", "packages/webui/src/public/shell.css", "packages/webui/src/serve.mjs", "packages/webui/src/public/index.html" +M = { + "M01": [(B, "err.status === 403 || ['not-configured', 'no-bus-host'].includes(err.code);", "err.status === 403;")], + "M02": [(A, "const refused = err.status === 403;", "const refused = false;")], + "M03": [(A, "document.body.classList.toggle('board-refused', refused);", "")], + "M04": [(B, "refused: ${txt(err.code)}. ", "refused: ${txt(err.code)}. ")], + "M05": [(B, "${state === 'stale' ? ' · stale: the last read failed' : ''}", "")], + "M06": [(A, "if (mode === 'system') delete document.documentElement.dataset.mode; else document.documentElement.dataset.mode = mode;", "document.documentElement.dataset.mode = mode;")], + "M07": [(B, "t.innerHTML = `${esc(text)}", "t.innerHTML = `${text}")], + "M08": [(B, "${txt(i.label)}", "${i.label}")], + "M09": [(C, ":focus-visible{outline:2px solid var(--focus);outline-offset:2px}", ":focus-visible{outline:2px solid var(--focus);outline-offset:0}")], + "M10": [(C, ":focus-visible{outline:2px solid var(--focus);outline-offset:2px}", ":focus-visible{outline:1px solid var(--focus);outline-offset:2px}")], + "M11": [(C, " .s1-sections{display:flex;flex-wrap:nowrap;overflow-x:auto;", " .s1-sections{display:flex;flex-wrap:wrap;overflow-x:visible;")], + "M21": [(B, "function forget() { last.clear(); inboxCount = null; }", "function forget() {}")], + "M22": [(B, "catch (err) { if (refusal(err)) { forget(); if (g === gen) sections(path); } }", "catch {}")], + "M23": [(B, " if (refusal(err)) forget();\n", "")], + "M24": [(B, "if (rs.some(r => r.status === 'rejected' && refusal(r.reason))) { forget(); sections(routeOf().split('?')[0]); }", "")], + "M25": [(A, "data = null; selected = null; project = null;", "data = null; project = null;")], + "M26": [(A, "failed === 'refused' ? 'Board not read: refused' : ", "")], + "M27": [(A, " $('footer').textContent = 'Board not read: refused';\n", "")], + "M28": [(A, " $('status').textContent = 'Not read: the board refused the read';\n", "")], + "M29": [(A, " $('projects').innerHTML = '

    Not read: the board refused the read.

    ';\n", "")], + "M30": [(A, " for (const id of ['waiting-count', 'seen-count', 'session-count']) $(id).textContent = '–';\n", "")], + "M31": [(B, "state === 'refused' ? 'Bus not read: refused' : ", "")], + "M32": [(C, ".toast:not(.on){width:1px;height:1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;box-shadow:none}", ".toast:not(.on){display:none}")], + "M33": [(B, "function forget() { last.clear(); inboxCount = null; }", "function forget() { last.clear(); }")], + "M34": [(B, "function forget() { last.clear(); inboxCount = null; }", "function forget() { inboxCount = null; }")], + "M35": [(A, "`${new Date(at).toISOString().slice(11, 19)} UTC`", "new Date(at).toLocaleTimeString([], { hour12: false })")], + "M36": [(C, " .s1-sections{display:flex;flex-wrap:nowrap;overflow-x:auto;", " .s1-sections{display:flex;flex-wrap:nowrap;overflow-x:visible;")], + "M37": [(C, " .s1-sections{display:flex;flex-wrap:nowrap;overflow-x:auto;", " .s1-sections{display:flex;flex-wrap:wrap;overflow-x:auto;")], + "M12": [(B, "", "")], + "M13": [(A, " $('board-refused').hidden = true; document.body.classList.remove('board-refused');\n", "")], + "M14": [(B, "links[i + (e.key === 'ArrowDown' ? 1 : -1)]?.focus();", "links[i + (e.key === 'ArrowDown' ? -1 : 1)]?.focus();")], + "M15": [(S, "['/icons.svg', ['icons.svg', 'image/svg+xml']],", "['/icons.svg', ['icons.svg', 'text/plain']],")], + "M16": [(C, ".count,td,.s1-twhen,time,.fresh,.kv dd{font-variant-numeric:tabular-nums}", "")], + "M17": [(A, "try { localStorage.setItem('mosaic-console-appearance',", "try { localStorage.setItem('mosaic-console-look',")], + "M18": [(C, "body.board-refused #board-view{display:none}", "")], + "M19": [(B, "if (refusal(err)) throw err; html = await view(kept,", "html = await view(kept,")], + "M20": [(A, "$('error').className = refused ? 'banner ref' : 'banner err';", "$('error').className = 'banner err';")], +} +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-53-review/r2/mut/run.sh b/agents/darkwing/work/queue-53-review/r2/mut/run.sh new file mode 100755 index 00000000..017f041d --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/run.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# Each mutant against the packages/webui suite in a candidate worktree, then restores from the index. +export TMPDIR=~/darkwing-scratch/r53b/tmp +S=~/darkwing-scratch/r53b; 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"\"(M\d\d)\"", open("'$M'/mutate.py").read())))))'); do + (cd $W && git checkout -q -- packages/webui && python3 $M/mutate.py $v > /dev/null && git diff > $M/$v.diff) || { echo "$v APPLY-FAILED" >> $M/summary.txt; continue; } + (cd $W/packages/webui && env -u NODE_TEST_CONTEXT node --test '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/webui && 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-53-review/r2/mut/summary.txt b/agents/darkwing/work/queue-53-review/r2/mut/summary.txt new file mode 100644 index 00000000..fd7a2db1 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/mut/summary.txt @@ -0,0 +1,40 @@ +start 2026-10-10T18:25:08Z +M01 killed exit=1 ℹ pass 26 ℹ fail 1 +M02 killed exit=1 ℹ pass 26 ℹ fail 1 +M03 killed exit=1 ℹ pass 26 ℹ fail 1 +M04 killed exit=1 ℹ pass 26 ℹ fail 1 +M05 killed exit=1 ℹ pass 24 ℹ fail 3 +M06 killed exit=1 ℹ pass 26 ℹ fail 1 +M07 SURVIVED exit=0 ℹ pass 27 ℹ fail 0 +M08 killed exit=1 ℹ pass 26 ℹ fail 1 +M09 killed exit=1 ℹ pass 26 ℹ fail 1 +M10 killed exit=1 ℹ pass 26 ℹ fail 1 +M11 killed exit=1 ℹ pass 26 ℹ fail 1 +M12 killed exit=1 ℹ pass 26 ℹ fail 1 +M13 killed exit=1 ℹ pass 26 ℹ fail 1 +M14 killed exit=1 ℹ pass 26 ℹ fail 1 +M15 killed exit=1 ℹ pass 26 ℹ fail 1 +M16 killed exit=1 ℹ pass 26 ℹ fail 1 +M17 killed exit=1 ℹ pass 26 ℹ fail 1 +M18 killed exit=1 ℹ pass 26 ℹ fail 1 +M19 killed exit=1 ℹ pass 25 ℹ fail 2 +M20 killed exit=1 ℹ pass 26 ℹ fail 1 +M21 killed exit=1 ℹ pass 26 ℹ fail 1 +M22 killed exit=1 ℹ pass 26 ℹ fail 1 +M23 killed exit=1 ℹ pass 26 ℹ fail 1 +M24 killed exit=1 ℹ pass 26 ℹ fail 1 +M25 killed exit=1 ℹ pass 26 ℹ fail 1 +M26 killed exit=1 ℹ pass 26 ℹ fail 1 +M27 killed exit=1 ℹ pass 26 ℹ fail 1 +M28 killed exit=1 ℹ pass 26 ℹ fail 1 +M29 killed exit=1 ℹ pass 26 ℹ fail 1 +M30 SURVIVED exit=0 ℹ pass 27 ℹ fail 0 +M31 killed exit=1 ℹ pass 25 ℹ fail 2 +M32 killed exit=1 ℹ pass 26 ℹ fail 1 +M33 killed exit=1 ℹ pass 26 ℹ fail 1 +M34 killed exit=1 ℹ pass 26 ℹ fail 1 +M35 killed exit=1 ℹ pass 26 ℹ fail 1 +M36 killed exit=1 ℹ pass 26 ℹ fail 1 +M37 killed exit=1 ℹ pass 26 ℹ fail 1 +end 2026-10-10T19:00:50Z +DONE diff --git a/agents/darkwing/work/queue-53-review/r2/out/build-tokens.txt b/agents/darkwing/work/queue-53-review/r2/out/build-tokens.txt new file mode 100644 index 00000000..20cb200f --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/out/build-tokens.txt @@ -0,0 +1 @@ +tokens.css is current diff --git a/agents/darkwing/work/queue-53-review/r2/out/node-webui.txt b/agents/darkwing/work/queue-53-review/r2/out/node-webui.txt new file mode 100644 index 00000000..80b7ed23 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/out/node-webui.txt @@ -0,0 +1,36 @@ +✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (5523.436991ms) +Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286} +✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (8766.561351ms) +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (8827.954235ms) +✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (277.316884ms) +✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (201.217171ms) +✔ bus refusals map to statuses and never carry a path or a stack (73.461855ms) +✔ humanCall speaks the human transport protocol without blocking the server (2813.609766ms) +✔ busReader takes --business, else the live bus host, else refuses (175.887468ms) +✔ humanCall kills a transport that runs past its timeout (529.046089ms) +✔ serve refuses a --business value that is not a business id (197.251891ms) +✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (6431.465011ms) +✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (3853.631876ms) +✔ conversation view: a newer session with no readable history keeps the marker (3922.98223ms) +✔ conversation view: seats without history say so and offer no reply (3482.629009ms) +✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (5496.850194ms) +✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (58053.664671ms) +✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (5499.821805ms) +✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (25062.757457ms) +✔ loopback host and board origin fail closed (9.306713ms) +✔ real board fixture passes through WebUI; assets and isolated seen/reply work (134.500699ms) +✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (127.67224ms) +✔ unreachable board reports URL; CLI rejects unsupported options (1474.550223ms) +✔ tokens.css and icons.svg are byte copies of docs/design (1.345771ms) +✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.627495ms) +✔ shipped strings are unchanged, and the web keeps its write boundary (2.591051ms) +✔ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (8724.52559ms) +✔ five states on Board, Inbox, Tasks, Agents and Trail (7349.679734ms) +ℹ tests 27 +ℹ suites 0 +ℹ pass 27 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 58535.525593 diff --git a/agents/darkwing/work/queue-53-review/r2/out/r1-to-r2.diff b/agents/darkwing/work/queue-53-review/r2/out/r1-to-r2.diff new file mode 100644 index 00000000..fdb52aa3 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/out/r1-to-r2.diff @@ -0,0 +1,391 @@ +diff -ru /home/jwoltje/darkwing-scratch/r53a/snap/packages/webui/README.md packages/webui/README.md +--- /home/jwoltje/darkwing-scratch/r53a/snap/packages/webui/README.md 2026-10-10 12:23:48.000000000 -0500 ++++ packages/webui/README.md 2026-10-10 13:15:05.000000000 -0500 +@@ -91,7 +91,9 @@ + open sections and the copy status survive a refresh. + - A failed read keeps the last good answer for that read and says it is old, + with the time it was read. A refusal (403, `not-configured` or `no-bus-host`) +- never shows kept rows (row 53). A page never read, or refused, shows the failure instead, ++ never shows kept rows (row 53), and it drops every kept bus read: the Inbox ++ count and the palette's decisions and tasks go too, until a read succeeds. ++ A page never read, or refused, shows the failure instead, + titled "Bus refused the read" (403: the bus refused the Console's read, for + example `human-required` from a Console started inside an agent run), "No bus to read" (no system + config, or no bus host and no `--business`) or "The read failed". +@@ -120,12 +122,16 @@ + and tasks; arrows move, Enter opens, Esc closes and returns focus. Arrow + keys also move between task links in the bus tables. + - Copy reports in a toast. If the clipboard is unavailable, the toast stays +- until dismissed and the command is selected for Ctrl+C. +-- The command bar shows when the board was scanned and the bus read, and +- says when the last attempt failed. A board refusal hides the board rather +- than showing the last scan. ++ until dismissed and the command is selected for Ctrl+C. When no toast shows, ++ the toast is an empty live region, visually hidden but still in the ++ accessibility tree, so the first copy is announced. ++- The command bar shows, in UTC, when the board was scanned and the bus read, ++ and says when the last attempt failed. A board refusal drops the last scan ++ and everything drawn from it: the table, the inspector, the project tree, ++ the counts, the footer and the scan line all say the board was not read. + - From 760px the footer is a one-line status bar and the side column fits +- between it and the command bar. Below 760px the section list wraps. ++ between it and the command bar. Below 760px the section list is one strip ++ that scrolls inside itself. + + ## Data and boundaries + +@@ -204,11 +210,15 @@ + + Shell tests (`shell.test.mjs`) check the copies, the font hashes and the kept + strings, and in the browser at 400px: System mode under an emulated dark and +-light OS, the empty, stale and refused states of the board and the bus views, +-not found, the palette, the toast, keyboard and visible focus, no sideways ++light OS, the empty, stale and refused states of the board and the bus views ++(a board refusal with the inspector open), not found, the palette, the toast, ++keyboard and visible focus, the section strip at 360 and 400px, no sideways + scroll, no script error and no request other than GET. A second test walks + the Board, Inbox, Tasks, Agents and a decision trail through loading (a held +-read), normal, a failed read over kept rows, and a refusal. ++read), normal, a failed read over kept rows, and a refusal by the bus ++(`human-required`) and for want of one (`no-bus-host`). It then checks that a ++refusal empties the palette and the Inbox count, from a view, from the ++palette's own reads and from the board page, and that palette labels are text. + + No root CI workflow is configured for this package. These local tests are not a + claim of CI, deployment, live-seat delivery or user acceptance. +diff -ru /home/jwoltje/darkwing-scratch/r53a/snap/packages/webui/src/public/app.js packages/webui/src/public/app.js +--- /home/jwoltje/darkwing-scratch/r53a/snap/packages/webui/src/public/app.js 2026-10-10 12:03:18.000000000 -0500 ++++ packages/webui/src/public/app.js 2026-10-10 13:15:05.000000000 -0500 +@@ -282,8 +282,8 @@ + // Freshness line in the command bar: when the board last scanned, and warning words when the last refresh failed. + function fresh() { + const at = Date.parse(data?.generatedAt), ago = Number.isFinite(at) ? age(Math.max(0, Math.round((Date.now() - at) / 1000))) : null; +- if (!data) { $('fresh-board').innerHTML = failed ? 'Board not read: the read failed' : 'Board not read yet'; return; } +- const scan = `Board scanned ${esc(Number.isFinite(at) ? new Date(at).toLocaleTimeString([], { hour12: false }) : 'unknown')}${ago ? ` (${ago} ago)` : ''}`; ++ if (!data) { $('fresh-board').innerHTML = failed === 'refused' ? 'Board not read: refused' : failed ? 'Board not read: the read failed' : 'Board not read yet'; return; } ++ const scan = `Board scanned ${esc(Number.isFinite(at) ? `${new Date(at).toISOString().slice(11, 19)} UTC` : 'unknown')}${ago ? ` (${ago} ago)` : ''}`; + $('fresh-board').innerHTML = failed ? `${scan} · stale: the last refresh failed` : scan; + } + setInterval(() => { if (data) fresh(); }, 5000); +@@ -300,10 +300,20 @@ + for (const id of awaiting.keys()) { const r = row(id); if (r && !pending(r)) awaiting.delete(id); } + render(); + } +- // A refusal (403) fails closed: the last data is hidden, not shown as current. Any other failure keeps the last data with its scan time. ++ // A refusal (403) fails closed: the last data is dropped, not kept or shown as current, and so is ++ // everything drawn from it: the inspector, the project tree, the counts and the footer. Any other ++ // failure keeps the last data with its scan time. + function error(err) { +- failed = true; $('error').hidden = false; + const refused = err.status === 403; ++ failed = refused ? 'refused' : true; $('error').hidden = false; ++ if (refused) { ++ data = null; selected = null; project = null; ++ $('projects').innerHTML = '

    Not read: the board refused the read.

    '; ++ for (const id of ['waiting-count', 'seen-count', 'session-count']) $(id).textContent = '–'; ++ $('footer').textContent = 'Board not read: refused'; ++ $('status').textContent = 'Not read: the board refused the read'; ++ inspect(); convForm(); ++ } + $('error').className = refused ? 'banner ref' : 'banner err'; + $('board-refused').hidden = !refused; document.body.classList.toggle('board-refused', refused); + $('error').innerHTML = refused +diff -ru /home/jwoltje/darkwing-scratch/r53a/snap/packages/webui/src/public/bus.js packages/webui/src/public/bus.js +--- /home/jwoltje/darkwing-scratch/r53a/snap/packages/webui/src/public/bus.js 2026-10-10 11:58:46.000000000 -0500 ++++ packages/webui/src/public/bus.js 2026-10-10 13:15:05.000000000 -0500 +@@ -369,12 +369,14 @@ + const failTitle = err => err.status === 403 ? 'Bus refused the read' : ['not-configured', 'no-bus-host'].includes(err.code) ? 'No bus to read' : 'The read failed'; + // A refusal fails closed: no kept data, the code in mono. Any other failure keeps the last read, labelled with its time. + const refusal = err => err.status === 403 || ['not-configured', 'no-bus-host'].includes(err.code); ++ // After a refusal nothing read before is shown anywhere: not in a view, the palette or the Inbox count. ++ function forget() { last.clear(); inboxCount = null; } + const failedView = err => `${head(failTitle(err))}${empty('Nothing to show.', refusal(err) ? 'The view stays empty until the problem above is fixed.' : 'Read again, or come back when the bus answers.')}`; + const staleBanner = err => ``; + // Freshness line in the command bar for bus pages. + const stamp = iso => { const t = Date.parse(iso); return Number.isFinite(t) ? `${new Date(t).toISOString().slice(11, 19)} UTC` : 'unknown'; }; + function freshBus(state) { +- $('fresh-bus').innerHTML = state === 'failed' ? 'Bus not read: the read failed' ++ $('fresh-bus').innerHTML = state === 'refused' ? 'Bus not read: refused' : state === 'failed' ? 'Bus not read: the read failed' + : `Bus read ${esc(stamp(readAt))}${readAt ? ` (${esc(ago(readAt))})` : ''}${state === 'stale' ? ' · stale: the last read failed' : ''}`; + } + +@@ -420,7 +422,8 @@ + if (board) { + // The board page keeps its own title; the Inbox count still follows the bus. + if (shown !== null) { shown = null; $('bus-view').innerHTML = ''; document.title = 'Mosaic Console'; if (navigated) $('main').focus(); } +- try { const r = await fetchRead('inbox'); last.set('inbox', r); if (g === gen) { countInbox(r.rows); sections(path); } } catch {} ++ try { const r = await fetchRead('inbox'); last.set('inbox', r); if (g === gen) { countInbox(r.rows); sections(path); } } ++ catch (err) { if (refusal(err)) { forget(); if (g === gen) sections(path); } } + if (g === gen) schedule(); + return; + } +@@ -431,7 +434,8 @@ + catch (err) { + const kept = reader(false); + try { if (refusal(err)) throw err; html = await view(kept, path, new URLSearchParams(query)); readAt = kept.oldest(); html = staleBanner(err) + html; state = 'stale'; } +- catch { html = failedView(err); state = 'failed'; } ++ catch { html = failedView(err); state = refusal(err) ? 'refused' : 'failed'; } ++ if (refusal(err)) forget(); + } + if (g !== gen) return; + freshBus(state); +@@ -506,7 +510,10 @@ + if (d.open) return; + pkBack = document.activeElement; pkAt = 0; $('cmdk-input').value = ''; + pkItems(); pkFill(); d.showModal(); $('cmdk-input').focus(); +- Promise.allSettled(['inbox', 'tasks'].map(async v => last.set(v, await fetchRead(v)))).then(() => { if (d.open) { pkItems(); pkFill(); } }); ++ Promise.allSettled(['inbox', 'tasks'].map(async v => last.set(v, await fetchRead(v)))).then(rs => { ++ if (rs.some(r => r.status === 'rejected' && refusal(r.reason))) { forget(); sections(routeOf().split('?')[0]); } ++ if (d.open) { pkItems(); pkFill(); } ++ }); + } + function pkGo(href) { + pkBack = null; $('cmdk-dialog').close(); +diff -ru /home/jwoltje/darkwing-scratch/r53a/snap/packages/webui/src/public/shell.css packages/webui/src/public/shell.css +--- /home/jwoltje/darkwing-scratch/r53a/snap/packages/webui/src/public/shell.css 2026-10-10 12:14:49.000000000 -0500 ++++ packages/webui/src/public/shell.css 2026-10-10 13:15:05.000000000 -0500 +@@ -101,8 +101,9 @@ + body.on-bus #board-refused{display:none} + + /* Toast: one line, polite, bottom centre. */ +-.toast{position:fixed;left:50%;bottom:16px;transform:translateX(-50%);display:none;align-items:center;gap:10px;background:var(--strong);color:var(--surface);padding:6px 8px 6px 14px;border-radius:var(--r);font-size:13px;z-index:60;max-width:calc(100% - 24px);box-shadow:var(--shadow)} +-.toast.on{display:flex} ++.toast{position:fixed;left:50%;bottom:16px;transform:translateX(-50%);display:flex;align-items:center;gap:10px;background:var(--strong);color:var(--surface);padding:6px 8px 6px 14px;border-radius:var(--r);font-size:13px;z-index:60;max-width:calc(100% - 24px);box-shadow:var(--shadow)} ++/* Off, the toast stays in the accessibility tree, empty and visually hidden, so the first copy is announced. */ ++.toast:not(.on){width:1px;height:1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;box-shadow:none} + .toast span{min-width:0;overflow-wrap:anywhere} + .toast.err{background:var(--danger)} + .toast button{font:inherit;font-weight:600;border:1px solid currentColor;background:none;color:inherit;border-radius:4px;padding:1px 8px;cursor:pointer} +@@ -164,8 +165,9 @@ + .cmd-right{margin-left:0;flex:1 1 100%;flex-wrap:nowrap;min-width:0} + .cmd-right label{flex:1 1 0;min-width:0} + .cmd-right .btn{flex:none} +- /* The section list wraps rather than scrolling, so a blocking count never hides a section. */ +- .s1-sections{display:flex;flex-wrap:wrap;overflow-x:visible;flex-basis:100%;gap:2px;padding-bottom:2px} ++ /* The section list is one strip that scrolls inside itself (IMPLEMENTING.md), so more sections never add rows. */ ++ .s1-sections{display:flex;flex-wrap:nowrap;overflow-x:auto;flex-basis:100%;min-width:0;max-width:100%;gap:2px;padding-bottom:2px;scrollbar-width:thin} ++ .s1-sections>li{flex:none} + .s1-section{border-radius:var(--r);padding:5px 8px;white-space:nowrap;flex:none} + .inspector{inset:0;top:0;width:100%;z-index:40;box-shadow:none} + } +diff -ru /home/jwoltje/darkwing-scratch/r53a/snap/packages/webui/tests/shell.test.mjs packages/webui/tests/shell.test.mjs +--- /home/jwoltje/darkwing-scratch/r53a/snap/packages/webui/tests/shell.test.mjs 2026-10-10 12:23:48.000000000 -0500 ++++ packages/webui/tests/shell.test.mjs 2026-10-10 13:15:05.000000000 -0500 +@@ -35,17 +35,21 @@ + }); + + test('shipped strings are unchanged, and the web keeps its write boundary', () => { +- // Markup in the source (, ) is not part of the string. ++ // Markup in the source (, ) is not part of the string. Each string is counted in the ++ // file that ships it, so dropping one of two copies fails too. + const src = ['app.js', 'bus.js', 'index.html'].map(f => read(f).toString()).join('\n'); +- const plain = src.replace(/<\/?(code|b)>/g, ''); +- for (const s of [ +- 'Copied: ${text}', +- 'The clipboard is unavailable. The command is selected; press Ctrl+C to copy it.', +- 'Decisions are answered in a terminal with mosaic decide; Console only shows them.', +- 'No task ${txt(ref)} in this business.', 'No decision with id ${txt(id)}.', '${txt(b)} is not a decision id.', '${txt(b)} is not a task reference.', +- 'No page at this address.', 'Nothing is waiting on you.', 'No tasks in this business yet.', 'Tasks appear after the PM creates them or the poller reads them from Vikunja.', +- 'No open tasks.', 'No role is held right now.', 'Nothing of this kind in the trail.', 'Console shows nothing rather than a guess. Nothing was written.', +- ]) assert.ok(plain.includes(s), s); ++ const plain = Object.fromEntries(['app.js', 'bus.js'].map(f => [f, read(f).toString().replace(/<\/?(code|b)>/g, '')])); ++ for (const [file, s, n = 1] of [ ++ ['bus.js', 'Copied: ${text}'], ++ ['bus.js', 'The clipboard is unavailable. The command is selected; press Ctrl+C to copy it.'], ++ ['bus.js', 'Decisions are answered in a terminal with mosaic decide; Console only shows them.'], ++ ['bus.js', 'No task ${txt(ref)} in this business.', 2], ['bus.js', 'No decision with id ${txt(id)}.'], ++ ['bus.js', '${txt(b)} is not a decision id.'], ['bus.js', '${txt(b)} is not a task reference.'], ++ ['bus.js', 'No page at this address.'], ['app.js', 'Nothing is waiting on you.'], ['bus.js', 'Nothing is waiting on you.'], ++ ['bus.js', 'No tasks in this business yet.'], ['bus.js', 'Tasks appear after the PM creates them or the poller reads them from Vikunja.'], ++ ['bus.js', 'No open tasks.'], ['bus.js', 'No role is held right now.'], ['bus.js', 'Nothing of this kind in the trail.'], ++ ['bus.js', 'Console shows nothing rather than a guess. Nothing was written.'], ++ ]) assert.equal(plain[file].split(s).length - 1, n, `${file}: ${s}`); + // No Resolve control and no bus write: the only POSTs are the board's Seen and reply. + assert.doesNotMatch(src, /]*>[^<]*(Resolve|Decide|Approve)/i); + assert.doesNotMatch(read('bus.js').toString(), /method:\s*['"](POST|PUT|PATCH|DELETE)/); +@@ -121,7 +125,7 @@ + // Board, empty: what would appear and where it comes from. + assert.match(await text('#sessions .empty'), /No sessions match these filters\.Sessions appear here when the board scan finds/); + assert.match(await text('#waiting .empty'), /Nothing is waiting on you\./); +- assert.match(await text('#fresh-board'), /^Board scanned \d\d:\d\d:\d\d/); ++ assert.match(await text('#fresh-board'), /^Board scanned \d\d:\d\d:\d\d UTC/); + await flat(); await shot('board-empty-400'); + + // Board, a failed read over kept data: the data stays, labelled with its scan time, and the bar says stale. +@@ -135,16 +139,30 @@ + assert.match(await text('#fresh-board'), /stale: the last refresh failed/); + await flat(); await shot('board-stale-400'); + +- // Board, a refusal: fails closed, the kept rows are hidden, not shown as current. ++ // Board, a refusal: fails closed. The kept rows are hidden, and so is everything drawn from ++ // them: the open inspector, the project tree's counts and the footer. ++ await b.evaluate('document.querySelector("table.sessions [data-open]").click()'); await wait('!document.querySelector("#inspector").hidden'); ++ assert.equal(await text('#footer'), 'waiting 1 · working 1'); ++ assert.equal(await b.evaluate('document.querySelectorAll("#projects .count").length'), 2); + brd.refuse(); await refresh(); + assert.equal(await b.evaluate('document.querySelector("#error").className'), 'banner ref'); + assert.match(await text('#error'), /The board refused the read\. refused: board-refused/); + assert.equal(await b.evaluate('getComputedStyle(document.querySelector("#board-view")).display'), 'none'); + assert.equal(await b.evaluate('document.querySelector("#board-refused").hidden'), false); ++ assert.equal(await b.evaluate('document.querySelector("#inspector").hidden'), true); ++ assert.equal(await b.evaluate('document.body.classList.contains("has-inspector")'), false); ++ assert.equal(await b.evaluate('document.querySelectorAll("#projects .count, #projects [data-project]").length'), 0); ++ assert.equal(await text('#footer'), 'Board not read: refused'); ++ assert.equal(await text('#fresh-board'), 'Board not read: refused'); ++ assert.doesNotMatch(await text('#status'), /Scanned/); + await flat(); await shot('board-refused-400'); + brd.one(); await refresh(); + assert.equal(await b.evaluate('document.querySelector("#error").hidden'), true); + assert.notEqual(await b.evaluate('getComputedStyle(document.querySelector("#board-view")).display'), 'none'); ++ assert.equal(await text('#footer'), 'waiting 1 · working 1'); ++ // A good read after a failed one drops the stale words. ++ brd.fail(); await refresh(); assert.match(await text('#fresh-board'), /stale/); ++ brd.one(); await refresh(); assert.match(await text('#fresh-board'), /^Board scanned \d\d:\d\d:\d\d UTC/); assert.doesNotMatch(await text('#fresh-board'), /stale/); + + // Keyboard on the board: down moves between rows, Enter opens, Esc closes and returns focus. + await b.evaluate('document.querySelector("table.sessions [data-open]").focus()'); +@@ -159,12 +177,16 @@ + await b.evaluate('document.querySelector(".skip").focus();document.querySelector(".skip").blur()'); + for (const sel of ['#cmdk', '#sections a', '#refresh']) { + await b.evaluate(`document.querySelector(${JSON.stringify(sel)}).focus()`); +- const ring = await b.evaluate(`(()=>{const c=getComputedStyle(document.activeElement);return [c.outlineStyle, parseFloat(c.outlineWidth)]})()`); +- assert.notEqual(ring[0], 'none', `${sel} focus ring`); assert.ok(ring[1] >= 2, `${sel} outline ${ring[1]}px`); ++ const ring = await b.evaluate(`(()=>{const c=getComputedStyle(document.activeElement);return [c.outlineStyle, parseFloat(c.outlineWidth), parseFloat(c.outlineOffset)]})()`); ++ assert.notEqual(ring[0], 'none', `${sel} focus ring`); assert.ok(ring[1] >= 2, `${sel} outline ${ring[1]}px`); assert.equal(ring[2], 2, `${sel} outline offset`); + } + + // Bus pages, empty: each says what would appear and where it comes from. +- for (const [hash, h1, words] of [['#/inbox', 'Inbox', /Nothing is waiting on you\./], ['#/tasks', 'Tasks', /No tasks in this business yet\./], ['#/agents', 'Agents', /No role is held right now\./]]) { ++ for (const [hash, h1, words] of [ ++ ['#/inbox', 'Inbox', /^Nothing is waiting on you\.A decision shows here when an agent raises one routed to you through the bus\.$/], ++ ['#/tasks', 'Tasks', /^No tasks in this business yet\.Tasks appear after the PM creates them or the poller reads them from Vikunja\.$/], ++ ['#/agents', 'Agents', /^No role is held right now\.A role shows here while a run holds its claim on the bus\.$/], ++ ]) { + await go(hash, h1); + assert.match(await text('#bus-view .empty'), words, hash); + assert.match(await text('#fresh-bus'), /^Bus read \d\d:\d\d:\d\d UTC/, hash); +@@ -172,11 +194,23 @@ + } + assert.equal(await b.evaluate('getComputedStyle(document.querySelector("#fresh-board")).display'), 'none'); + assert.equal(await b.evaluate('document.querySelectorAll("#sections svg use").length'), 4); ++ for (const sel of ['#fresh', '#session-count']) assert.equal(await b.evaluate(`getComputedStyle(document.querySelector(${JSON.stringify(sel)})).fontVariantNumeric`), 'tabular-nums', sel); ++ // Before any copy the toast is an empty live region still in the accessibility tree, out of sight. ++ assert.deepEqual(await b.evaluate('(()=>{const t=document.querySelector("#toast"),c=getComputedStyle(t),r=t.getBoundingClientRect();return [c.display!=="none",c.visibility,t.textContent,r.width<=1&&r.height<=1]})()'), [true, 'visible', '', true]); ++ // Below 760px the section list is one strip that scrolls inside itself: every link on one ++ // line, no label wrapped, and still no sideways scroll on the page. 360px, then back to 400px. ++ for (const w of [360, 400]) { ++ await b.viewport(w, 900); ++ assert.equal(await b.evaluate('new Set([...document.querySelectorAll("#sections a")].map(a=>a.offsetTop)).size'), 1, `one row at ${w}px`); ++ assert.match(await b.evaluate('getComputedStyle(document.querySelector("#sections")).overflowX'), /^(auto|scroll)$/, `strip scrolls at ${w}px`); ++ assert.deepEqual(await b.evaluate('[...document.querySelectorAll("#sections a")].filter(a=>a.getClientRects().length>1||a.scrollWidth>a.clientWidth+1).map(a=>a.textContent)'), [], `no wrapped label at ${w}px`); ++ await flat(); ++ } + + // Bus, a failed read over kept data: the kept rows stay under a stale banner; the bar says stale. + s.rows.tasks = [{ task_ref: 'vikunja:32/7', fields: { title: 'Kept task', bucket: 2, done: false, assignees: [] }, source: 'self' }, { task_ref: 'vikunja:32/8', fields: { title: 'Second task', bucket: 2, done: false, assignees: [] }, source: 'self' }]; + await go('#/trail/task/vikunja%3A32%2F7', 'Trail for task #7'); +- assert.match(await text('#bus-view .empty'), /Nothing of this kind in the trail\./); ++ assert.match(await text('#bus-view .empty'), /^Nothing of this kind in the trail\.Every step the stack takes on this subject writes a trail row\.$/); + await flat(); await shot('bus-empty-trail-400'); + await go('#/tasks', 'Tasks'); + assert.equal(await b.evaluate('document.querySelectorAll("#bus-view td.s1-title a").length'), 2); +@@ -197,7 +231,7 @@ + assert.equal(await b.evaluate('document.querySelector("#bus-view .banner.ref code").textContent'), 'human-required'); + assert.equal(await b.evaluate('document.querySelectorAll("#bus-view td.s1-title a").length'), 0); + assert.match(await text('#bus-view .empty'), /Nothing to show\./); +- assert.match(await text('#fresh-bus'), /not read: the read failed/); ++ assert.equal(await text('#fresh-bus'), 'Bus not read: refused'); + await flat(); await shot('bus-refused-400'); + s.fail(null); + +@@ -209,6 +243,8 @@ + // Ctrl+K: opens on the views and the kept tasks, filters, Enter goes, Esc restores focus. + await go('#/inbox', 'Inbox'); + await b.evaluate('document.querySelector("#refresh").focus()'); ++ await b.key('k', 'KeyK', 3); await new Promise(r => setTimeout(r, 200)); ++ assert.equal(await b.evaluate('document.querySelector("#cmdk-dialog").open'), false, 'Ctrl+Alt+K opens nothing'); + await b.key('k', 'KeyK', 2); await wait('document.querySelector("#cmdk-dialog").open'); + assert.equal(await b.evaluate('document.activeElement.id'), 'cmdk-input'); + await wait('[...document.querySelectorAll("#cmdk-list [data-href]")].some(e=>e.dataset.href==="#/tasks/vikunja%3A32%2F7")'); +@@ -251,6 +287,8 @@ + await wait('document.querySelector("#toast").classList.contains("err")'); + assert.equal(await text('#toast span'), 'The clipboard is unavailable. The command is selected; press Ctrl+C to copy it.'); + assert.equal(await b.evaluate('getSelection().toString()'), `mosaic decide ${'d'.repeat(32)} yes`); ++ await new Promise(r => setTimeout(r, 3000)); ++ assert.equal(await b.evaluate('document.querySelector("#toast").className'), 'toast on err', 'the error toast stays until dismissed'); + await b.evaluate('document.querySelector("#toast [data-dismiss]").click()'); + assert.equal(await b.evaluate('document.querySelector("#toast").classList.contains("on")'), false); + +@@ -293,6 +331,7 @@ + const count = sel => b.evaluate(`document.querySelectorAll(${JSON.stringify(sel)}).length`); + const flat = async () => assert.equal(await b.evaluate('document.documentElement.scrollWidth<=document.documentElement.clientWidth'), true, 'sideways scroll at 400px'); + const refresh = async () => { await b.evaluate('document.querySelector("#refresh").click()'); await wait('!document.querySelector("#refresh").disabled'); }; ++ const go = async (hash, h1) => { await b.evaluate(`location.hash=${JSON.stringify(hash)}`); await wait(`document.querySelector("#bus-view h1")?.textContent.startsWith(${JSON.stringify(h1)}) && !document.querySelector("#bus-view [aria-busy]")`); }; + try { + await b.call('Page.addScriptToEvaluateOnNewDocument', { source: 'window.errors=[];addEventListener("error",e=>errors.push(e.message));addEventListener("unhandledrejection",e=>errors.push(String(e.reason)));window.requests=[];const f=window.fetch;window.fetch=(u,o={})=>{requests.push([(o.method||"GET").toUpperCase(),String(u)]);return f(u,o)};' }); + await b.viewport(400, 900); +@@ -332,17 +371,55 @@ + assert.equal(await count(rows), n, `${hash} keeps its rows`); + assert.match(await text('#fresh-bus'), /stale: the last read failed/, hash); + await flat(); await shot(`${name}-stale-400`); +- // A refusal: no kept rows, the code shown, nothing current. +- s.fail('human-required'); await refresh(); +- await wait('!!document.querySelector("#bus-view .banner.ref")'); +- assert.equal(await text('#bus-view .banner.ref code'), 'human-required', hash); +- assert.equal(await count(rows), 0, `${hash} hides kept rows on a refusal`); +- assert.match(await text('#bus-view .empty'), /Nothing to show\./, hash); +- await flat(); await shot(`${name}-refused-400`); +- s.fail(null); await refresh(); +- await wait(`!document.querySelector("#bus-view .banner") && document.querySelectorAll(${JSON.stringify(rows)}).length===${n}`); ++ // A refusal, by the bus (403) or for want of one (no-bus-host): no kept rows, the code ++ // shown, nothing current, and no count in the section list. ++ for (const code of ['human-required', 'no-bus-host']) { ++ s.fail(code); await refresh(); ++ await wait('!!document.querySelector("#bus-view .banner.ref")'); ++ assert.equal(await text('#bus-view .banner.ref code'), code, hash); ++ assert.equal(await count(rows), 0, `${hash} hides kept rows on a ${code} refusal`); ++ assert.match(await text('#bus-view .empty'), /Nothing to show\./, hash); ++ assert.equal(await text('#fresh-bus'), 'Bus not read: refused', hash); ++ assert.equal(await count('#sections .count, #sections .tag-block'), 0, `${hash} drops the Inbox count on a ${code} refusal`); ++ if (code === 'human-required') { await flat(); await shot(`${name}-refused-400`); } ++ s.fail(null); await refresh(); ++ await wait(`!document.querySelector("#bus-view .banner") && document.querySelectorAll(${JSON.stringify(rows)}).length===${n}`); ++ } + } + ++ // After a refusal the palette lists only the views: no kept decision or task. ++ const views = ['#/', '#/inbox', '#/tasks', '#/agents']; ++ const palette = '[...document.querySelectorAll("#cmdk-list [data-href]")].map(e=>e.dataset.href)'; ++ await b.evaluate('location.hash="#/inbox"'); await wait('document.querySelectorAll("#sections .count").length===1'); ++ assert.match(await text('#sections'), /Inbox 1 1 blocking/); ++ s.fail('human-required'); await refresh(); await wait('!!document.querySelector("#bus-view .banner.ref")'); ++ await b.key('k', 'KeyK', 2); await wait('document.querySelector("#cmdk-dialog").open'); ++ assert.deepEqual(await b.evaluate(palette), views); ++ await b.key('Escape'); await wait('!document.querySelector("#cmdk-dialog").open'); ++ s.fail(null); ++ // The palette's own reads: kept rows show until a refused refetch, then go, with the count. ++ await go('#/tasks', 'Tasks'); await b.evaluate('location.hash="#/inbox"'); await wait('document.querySelectorAll("#sections .count").length===1'); ++ await b.key('k', 'KeyK', 2); await wait(`${palette}.some(h=>h.startsWith("#/tasks/"))`); ++ await b.key('Escape'); await wait('!document.querySelector("#cmdk-dialog").open'); ++ s.fail('human-required'); ++ await b.key('k', 'KeyK', 2); await wait(`document.querySelector("#cmdk-dialog").open && ${palette}.length===${views.length} && !document.querySelector("#sections .count")`); ++ assert.deepEqual(await b.evaluate(palette), views); ++ await b.key('Escape'); await wait('!document.querySelector("#cmdk-dialog").open'); ++ // Palette labels are bus text: markup in a question or a task title shows as text. ++ s.fail(null); ++ s.rows.inbox = [{ ...s.rows.inbox[0], question: 'Push?' }]; ++ s.rows.tasks = [{ ...s.rows.tasks[0], fields: { ...s.rows.tasks[0].fields, title: 'Bold task' } }, s.rows.tasks[1]]; ++ await b.key('k', 'KeyK', 2); await wait(`${palette}.length===${views.length + 3}`); ++ assert.equal(await count('#cmdk-list #pk-q, #cmdk-list #pk-t, #cmdk-list img, #cmdk-list b'), 0); ++ assert.deepEqual(await b.evaluate('[...document.querySelectorAll("#cmdk-list [data-href] span:first-child")].slice(4).map(e=>e.textContent)'), ['Push?', '#7 Bold task', '#8 Second task']); ++ await b.key('Escape'); await wait('!document.querySelector("#cmdk-dialog").open'); ++ // The board page's Inbox read: a refusal there drops the count too. ++ s.fail(null); await refresh(); await wait('document.querySelectorAll("#sections .count").length===1'); ++ s.fail('no-bus-host'); await b.evaluate('location.hash="#/"'); await wait('!document.querySelector("#sections .count")'); ++ await b.key('k', 'KeyK', 2); await wait('document.querySelector("#cmdk-dialog").open'); ++ assert.deepEqual(await b.evaluate(palette), views); ++ await b.key('Escape'); s.fail(null); ++ + assert.deepEqual(await b.evaluate('window.errors'), []); + assert.deepEqual(await b.evaluate('window.requests.filter(([m])=>m!=="GET")'), []); + } finally { await b.close(); await close(web); await close(brd.server); } diff --git a/agents/darkwing/work/queue-53-review/r2/out/s5-rep-1.txt b/agents/darkwing/work/queue-53-review/r2/out/s5-rep-1.txt new file mode 100644 index 00000000..e9049bf7 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/out/s5-rep-1.txt @@ -0,0 +1,9 @@ +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (2559.882854ms) +ℹ tests 1 +ℹ suites 0 +ℹ pass 1 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 2631.856328 diff --git a/agents/darkwing/work/queue-53-review/r2/out/s5-rep-2.txt b/agents/darkwing/work/queue-53-review/r2/out/s5-rep-2.txt new file mode 100644 index 00000000..acf6e7f8 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/out/s5-rep-2.txt @@ -0,0 +1,9 @@ +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (2599.851202ms) +ℹ tests 1 +ℹ suites 0 +ℹ pass 1 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 2668.022259 diff --git a/agents/darkwing/work/queue-53-review/r2/out/s5-rep-3.txt b/agents/darkwing/work/queue-53-review/r2/out/s5-rep-3.txt new file mode 100644 index 00000000..0383634b --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/out/s5-rep-3.txt @@ -0,0 +1,9 @@ +✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (2438.997108ms) +ℹ tests 1 +ℹ suites 0 +ℹ pass 1 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 2506.864306 diff --git a/agents/darkwing/work/queue-53-review/r2/out/summary.txt b/agents/darkwing/work/queue-53-review/r2/out/summary.txt new file mode 100644 index 00000000..65b08399 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/out/summary.txt @@ -0,0 +1,14 @@ +start 2026-10-10T18:21:44Z +node-webui exit=0 ℹ pass 27 ℹ fail 0 +build-tokens --check exit=0 tokens.css is current +test-auth exit=0 selftest: 15 passed, 0 failed +test-conductor exit=0 selftest: 17 passed, 0 failed +test-config exit=0 selftest: 24 passed, 0 failed +test-discord exit=0 discord suite: 66 passed, 0 failed +test-extension-package exit=0 extension package selftest: 18 passed, 0 failed +test-foundation exit=0 selftest: 44 passed, 0 failed +test-queue exit=0 queue suite: 27 passed, 0 failed +test-release exit=0 selftest: 4 passed, 0 failed +test-task exit=0 selftest: 26 passed, 0 failed +end 2026-10-10T18:24:57Z +DONE diff --git a/agents/darkwing/work/queue-53-review/r2/out/test-auth.txt b/agents/darkwing/work/queue-53-review/r2/out/test-auth.txt new file mode 100644 index 00000000..ac228760 --- /dev/null +++ b/agents/darkwing/work/queue-53-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-53-review/r2/out/test-conductor.txt b/agents/darkwing/work/queue-53-review/r2/out/test-conductor.txt new file mode 100644 index 00000000..897d14d7 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/out/test-conductor.txt @@ -0,0 +1,55 @@ +Note: switching to '2d4d4e7dbc65767b1e65426ca5fadb9136a8be5b'. + +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 '2d4d4e7dbc65767b1e65426ca5fadb9136a8be5b'. + +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-53-review/r2/out/test-config.txt b/agents/darkwing/work/queue-53-review/r2/out/test-config.txt new file mode 100644 index 00000000..76c05ef7 --- /dev/null +++ b/agents/darkwing/work/queue-53-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-53-review/r2/out/test-discord.txt b/agents/darkwing/work/queue-53-review/r2/out/test-discord.txt new file mode 100644 index 00000000..b013f9ff --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/out/test-discord.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-53-review/r2/out/test-extension-package.txt b/agents/darkwing/work/queue-53-review/r2/out/test-extension-package.txt new file mode 100644 index 00000000..7a52cf58 --- /dev/null +++ b/agents/darkwing/work/queue-53-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: 2558265 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-53-review/r2/out/test-foundation.txt b/agents/darkwing/work/queue-53-review/r2/out/test-foundation.txt new file mode 100644 index 00000000..6338e1e6 --- /dev/null +++ b/agents/darkwing/work/queue-53-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-53-review/r2/out/test-queue.txt b/agents/darkwing/work/queue-53-review/r2/out/test-queue.txt new file mode 100644 index 00000000..233ebb3f --- /dev/null +++ b/agents/darkwing/work/queue-53-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/r53b/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-53-review/r2/out/test-release-docker.txt b/agents/darkwing/work/queue-53-review/r2/out/test-release-docker.txt new file mode 100644 index 00000000..7202b85d --- /dev/null +++ b/agents/darkwing/work/queue-53-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-53-review/r2/out/test-release.txt b/agents/darkwing/work/queue-53-review/r2/out/test-release.txt new file mode 100644 index 00000000..1d6ed050 --- /dev/null +++ b/agents/darkwing/work/queue-53-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-53-review/r2/out/test-task.txt b/agents/darkwing/work/queue-53-review/r2/out/test-task.txt new file mode 100644 index 00000000..cd89fe9b --- /dev/null +++ b/agents/darkwing/work/queue-53-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-53-review/r2/probes/probe2.test.mjs b/agents/darkwing/work/queue-53-review/r2/probes/probe2.test.mjs new file mode 100644 index 00000000..4a26b150 --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/probes/probe2.test.mjs @@ -0,0 +1,118 @@ +// Darkwing row 53 round 2 probes: the round 1 probes again, then a board 403 followed by another +// failure (P9), and a board 403 with a conversation open (P10). +// Run from a worktree's packages/webui: node --test with WT set to that worktree. +import { test } from 'node:test'; +import assert from 'node:assert/strict'; +import { createServer, request } from 'node:http'; +import { pathToFileURL } from 'node:url'; +const WT = process.env.WT; +const u = p => pathToFileURL(`${WT}/packages/webui/${p}`).href; +const { browser } = await import(u('tests/browser.mjs')); +const { close } = await import(u('tests/fixture.mjs')); +const { startServer } = await import(u('src/serve.mjs')); +const { BusReadError } = await import(u('src/bus.mjs')); +const H = await import(u('tests/history-fixture.mjs')); +const out = []; +const note = (k, v) => { out.push(`${k}: ${JSON.stringify(v)}`); }; + +test('probes, fake board and bus', { timeout: 120000 }, async () => { + let reply = null; + const one = { agent: 'agent1', project: 'secretproj', state: 'waiting', waitingOnYou: true, task: 'Kept fixture task', lastActivity: '2026-10-10T00:00:00Z', lastAssistantText: 'Input needed: kept text', registered: null }; + const ok = () => { reply = { status: 200, body: { sessions: [one, { ...one, agent: 'agent2', state: 'working', waitingOnYou: false }], counts: { waiting: 1, working: 1 }, generatedAt: new Date().toISOString() } }; }; + ok(); + const brd = createServer(async (req, res) => { for await (const c of req) void c; res.writeHead(reply.status, { 'content-type': 'application/json' }); res.end(JSON.stringify(reply.body)); }); + await new Promise(r => brd.listen(0, '127.0.0.1', r)); + const rows = { inbox: [{ id: 'd'.repeat(32), question: 'Kept question?', class: 'gated', action: 'git.push.protected', blocking: true, options: [{ key: 'yes', text: 'Yes' }], at: new Date().toISOString(), raised_by: 'coder' }], tasks: [{ task_ref: 'vikunja:32/7', fields: { title: 'Kept task title', bucket: 2, done: false, assignees: [] }, source: 'self' }], agents: [], trail: [] }; + let fail = null; + const verb = n => async () => { if (fail) throw new BusReadError(fail, `fixture ${fail}`); return structuredClone(rows[n]); }; + const web = await startServer({ port: 0, board: `http://127.0.0.1:${brd.address().port}`, bus: { inbox: verb('inbox'), tasks: verb('tasks'), agents: verb('agents'), trail: verb('trail') } }); + const base = `http://127.0.0.1:${web.address().port}/`, b = await browser(); + const wait = expr => b.evaluate(`(async()=>{for(let i=0;i<100;i++){if(${expr})return true;await new Promise(r=>setTimeout(r,50))}throw new Error('timed out: '+${JSON.stringify(expr)})})()`); + const vis = sel => b.evaluate(`(()=>{const e=document.querySelector(${JSON.stringify(sel)});if(!e)return null;return {shown:!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)&&!e.closest('[hidden]'),text:e.innerText.slice(0,200)}})()`); + const refresh = async () => { await b.evaluate('document.querySelector("#refresh").click()'); await wait('!document.querySelector("#refresh").disabled'); }; + try { + await b.viewport(1440, 900); + await b.navigate(base); await wait('document.querySelectorAll("table.sessions tbody tr").length===2'); + await b.evaluate('document.querySelector("table.sessions [data-open]").click()'); + await wait('document.querySelector("#inspector-title")?.textContent==="agent1"'); + reply = { status: 403, body: { error: 'non-local Host refused' } }; + await refresh(); + await wait('document.querySelector("#error").className==="banner ref"'); + note('P1 board refused: board-view display', await b.evaluate('getComputedStyle(document.querySelector("#board-view")).display')); + note('P1 board refused: inspector', await vis('#inspector')); + note('P2 board refused: projects tree', await vis('#projects')); + note('P2 board refused: footer', await vis('#footer')); + note('P2 board refused: #status', await vis('#status')); + note('P2 board refused: #fresh-board', await vis('#fresh-board')); + // P9: still no good read, now a 500. Do the rows from before the refusal come back? + reply = { status: 500, body: { error: 'scan failed' } }; + await refresh(); await wait('document.querySelector("#error").className==="banner err"'); + note('P9 403 then 500: board-view display', await b.evaluate('getComputedStyle(document.querySelector("#board-view")).display')); + note('P9 403 then 500: session rows in the DOM and shown', await b.evaluate('[document.querySelectorAll("table.sessions tbody tr").length, !!document.querySelector("table.sessions")?.offsetHeight]')); + note('P9 403 then 500: #waiting', await vis('#waiting')); + note('P9 403 then 500: #sessions', await vis('#sessions')); + note('P9 403 then 500: projects, footer, status, fresh', [await vis('#projects'), await vis('#footer'), await vis('#status'), await vis('#fresh-board')]); + note('P9 403 then 500: banner', await vis('#error')); + ok(); await refresh(); await wait('document.querySelector("#error").hidden'); + note('P9b recovered: rows, footer', [await b.evaluate('document.querySelectorAll("table.sessions tbody tr").length'), await vis('#footer')]); + // P3/P4: bus pages read once, then the bus refuses. + await b.evaluate('location.hash="#/tasks"'); await wait('document.querySelectorAll("#bus-view td.s1-title a").length===1'); + await b.evaluate('location.hash="#/inbox"'); await wait('!!document.querySelector("#bus-view .s1-dec-open")'); + fail = 'human-required'; await refresh(); await wait('!!document.querySelector("#bus-view .banner.ref")'); + note('P4 bus refused: section list', await vis('#sections')); + await b.evaluate('document.querySelector("#cmdk").click()'); await wait('document.querySelector("#cmdk-dialog").open'); + await new Promise(r => setTimeout(r, 500)); + note('P3 bus refused: palette list', await b.evaluate('[...document.querySelectorAll("#cmdk-list li")].map(l=>l.innerText.replace(/\\n/g," | "))')); + await b.key('Escape'); + await b.evaluate('location.hash="#/"'); await wait('document.querySelectorAll("table.sessions tbody tr").length===2'); + await new Promise(r => setTimeout(r, 500)); + note('P4b board page, bus refused: section list', await vis('#sections')); + fail = 'not-configured'; await b.evaluate('location.hash="#/tasks"'); await wait('!!document.querySelector("#bus-view .banner")'); + note('P6 not-configured: banner class, task links', await b.evaluate('[document.querySelector("#bus-view .banner").className, document.querySelectorAll("#bus-view td.s1-title a").length]')); + fail = 'outcome-unknown'; await refresh(); await wait('!!document.querySelector("#bus-view .banner")'); + note('P7 refusal then outcome-unknown: banner class, task links, banner text', await b.evaluate('[document.querySelector("#bus-view .banner").className, document.querySelectorAll("#bus-view td.s1-title a").length, document.querySelector("#bus-view .banner").innerText.slice(0,160)]')); + const ax = await b.call('Accessibility.getFullAXTree', {}); + note('P8 status/live nodes before any toast', ax.nodes.filter(n => ['status'].includes(n.role?.value)).map(n => n.name?.value ?? '')); + note('P8 toast display, rect', await b.evaluate('(()=>{const t=document.querySelector("#toast"),r=t.getBoundingClientRect();return [getComputedStyle(t).display,r.width,r.height,t.querySelectorAll("button").length]})()')); + note('errors', await b.evaluate('window.errors||null')); + } finally { + await b.close(); await close(web); await new Promise(r => brd.close(r)); + } +}); + +test('probe P10, a conversation open when the board refuses', { timeout: 120000 }, async () => { + const fx = await H.historyFixture(); + const s = H.session(`${fx.sessionsDir}/2026-10-10T00-00-00-000Z_sess-1.jsonl`, fx.projectRoot); + s.add(H.user('Secret question from before the refusal')); s.add(H.assistant('Secret answer from before the refusal')); + // A proxy in front of the real board that can refuse every read with 403, as control-board's Host check does. + let refuse = false; + const up = new URL(`http://127.0.0.1:${fx.board.address().port}`); + const proxy = createServer((req, res) => { + if (refuse) { for (const _ of []) void _; res.writeHead(403, { 'content-type': 'application/json' }); res.end(JSON.stringify({ error: 'non-local Host refused' })); req.resume(); return; } + const p = request({ host: up.hostname, port: up.port, path: req.url, method: req.method, headers: { ...req.headers, host: up.host } }, r => { res.writeHead(r.statusCode, r.headers); r.pipe(res); }); + req.pipe(p); + }); + await new Promise(r => proxy.listen(0, '127.0.0.1', r)); + const web = await startServer({ port: 0, board: `http://127.0.0.1:${proxy.address().port}` }); + const b = await browser(), wait = H.waiter(b); + const vis = sel => b.evaluate(`(()=>{const e=document.querySelector(${JSON.stringify(sel)});if(!e)return null;return {shown:!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)&&!e.closest('[hidden]'),text:e.innerText.slice(0,200)}})()`); + try { + await b.viewport(1440, 900); + await b.navigate(`http://127.0.0.1:${web.address().port}/`); + await wait('!!document.querySelector("[data-history]")'); + await b.evaluate('document.querySelector("[data-history]").click()'); + await wait('document.querySelector("#conv-log")?.textContent.includes("Secret answer")'); + refuse = true; + await b.evaluate('document.querySelector("#refresh").click()'); await wait('!document.querySelector("#refresh").disabled'); + await wait('document.querySelector("#error").className==="banner ref"'); + await new Promise(r => setTimeout(r, 500)); + note('P10 conversation section', await vis('#conversation')); + note('P10 conv-log', await vis('#conv-log')); + note('P10 conv-meta, conv-title, conv-status', [await vis('#conv-meta'), await vis('#conv-title'), await vis('#conv-status')]); + note('P10 board-refused empty state', await vis('#board-refused')); + note('P10 conv-no-reply', await vis('#conv-no-reply')); + } finally { + console.log(out.join('\n')); + await b.close(); await close(web); await new Promise(r => proxy.close(r)); await fx.close(); + } +}); diff --git a/agents/darkwing/work/queue-53-review/r2/probes/probes-cand.txt b/agents/darkwing/work/queue-53-review/r2/probes/probes-cand.txt new file mode 100644 index 00000000..98ea9efc --- /dev/null +++ b/agents/darkwing/work/queue-53-review/r2/probes/probes-cand.txt @@ -0,0 +1,36 @@ +✔ probes, fake board and bus (2848.393287ms) +P1 board refused: board-view display: "none" +P1 board refused: inspector: {"shown":false,"text":"agent1CloseStatewaitingProjectsecretprojTaskKept fixture taskTask sourceunknownTask set bynot applicable (task is not from a registration)Active projectunknownWorkspaceunknownModelunknownRegisteredNo "} +P2 board refused: projects tree: {"shown":true,"text":"Not read: the board refused the read."} +P2 board refused: footer: {"shown":true,"text":"Board not read: refused"} +P2 board refused: #status: {"shown":true,"text":"Not read: the board refused the read"} +P2 board refused: #fresh-board: {"shown":true,"text":"Board not read: refused"} +P9 403 then 500: board-view display: "block" +P9 403 then 500: session rows in the DOM and shown: [2,true] +P9 403 then 500: #waiting: {"shown":true,"text":"agent1\nwaiting\n\nsecretproj · unknown\n\nKept fixture task\n\nInput needed: kept text\n\nLast activity 2026-10-10T00:00:00Z\nHistorySeen"} +P9 403 then 500: #sessions: {"shown":true,"text":"AGENT\tSTATE\tTASK\tACTIVE PROJECT\tWORKSPACE\tMODEL\tREGISTERED\tLAST ACTIVITY\nagent1\nsecretproj\nHistory\twaiting\tKept fixture task\tunknown\tunknown\tunknown\n\tno\t2026-10-10T00:00:00Z\nagent2\nsecretproj\nHistory\t"} +P9 403 then 500: projects, footer, status, fresh: [{"shown":true,"text":"Not read: the board refused the read."},{"shown":true,"text":"Board not read: refused"},{"shown":true,"text":"Not read: the board refused the read"},{"shown":true,"text":"Board not read: the read failed"}] +P9 403 then 500: banner: {"shown":true,"text":"scan failed Board: http://127.0.0.1:46259. No board data loaded. Use Refresh to try again."} +P9b recovered: rows, footer: [2,{"shown":true,"text":"waiting 1 · working 1"}] +P4 bus refused: section list: {"shown":true,"text":"Board\nInbox\nTasks\nAgents"} +P3 bus refused: palette list: ["Board | view","Inbox | view","Tasks | view","Agents | view"] +P4b board page, bus refused: section list: {"shown":true,"text":"Board\nInbox\nTasks\nAgents"} +P6 not-configured: banner class, task links: ["banner ref",0] +P7 refusal then outcome-unknown: banner class, task links, banner text: ["banner err",0,"The bus did not answer in time. (outcome-unknown) Console shows nothing rather than a guess. Nothing was written.\n\nRead again"] +P8 status/live nodes before any toast: [""] +P8 toast display, rect: ["flex",1,1,0] +errors: null +P10 conversation section: {"shown":true,"text":"fixture conversation\n\nrepo · Secret question from before the refusal · started 2026-10-10T18:14:21.736Z\n\nSession\nSecret question from before the refusal · 2026-10-10T18:24:21.736Z\nBack to board\n\nHisto"} +P10 conv-log: {"shown":true,"text":"USER\n2026-10-10T18:24:21.736Z\nSecret question from before the refusal\nASSISTANT\n2026-10-10T18:24:21.736Z\nSecret answer from before the refusal"} +P10 conv-meta, conv-title, conv-status: [{"shown":true,"text":"repo · Secret question from before the refusal · started 2026-10-10T18:14:21.736Z"},{"shown":true,"text":"fixture conversation"},{"shown":true,"text":"History unavailable: non-local Host refused."}] +P10 board-refused empty state: {"shown":true,"text":"Nothing to show.\n\nThe board refused the read, so Console shows nothing rather than a guess. The reason is above."} +P10 conv-no-reply: {"shown":true,"text":"This session is no longer in the board scan."} +✔ probe P10, a conversation open when the board refuses (1888.587489ms) +ℹ tests 2 +ℹ suites 0 +ℹ pass 2 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 4949.888449 diff --git a/agents/darkwing/work/queue-53-review/review-r2.md b/agents/darkwing/work/queue-53-review/review-r2.md new file mode 100644 index 00000000..a855af5c --- /dev/null +++ b/agents/darkwing/work/queue-53-review/review-r2.md @@ -0,0 +1,236 @@ +# Row 53, console tokens and shell restyle, round 2 review (Darkwing) + +Issue #1542, request comment 27156, packet comment 27157, queue revs +362-364. Base `2d4d4e7d`. Candidate manifest sha256 +`78c3aef963b7e35500c9f8afa6341057f1a6372ced70915d175e507b5fac8406`, the +same 16 files under `packages/webui`. The packet manifest and my snapshot +of the checkout both check 16 OK. `round2.patch` applied to my round 1 +snapshot gives the round 2 files byte for byte, so the delta is those five +files and nothing else. + +Verdict: **request changes**. All five of my round 1 items are fixed for +the cases I listed, and Sage's strip test is there and works. Every suite +is green and 35 of 37 mutants die. Two refusal gaps are left, and both +show data from before a board refusal: + +- A board 403 followed by any other failed read brings the refused + session table and the "Waiting on you" card back on screen. Filbert + found the same thing (their C4, comment 27163). +- A board 403 while a conversation is open leaves the conversation and + its history on screen. I should have caught this in round 1. My probes + then never opened History, so they didn't. + +Both fixes are a few lines each. + +## Method + +- Detached worktrees at `2d4d4e7d`, `cand` and `mutwt`, each with the 16 + candidate files staged and checking 16 OK. `mutwt` still checks 16 OK + after the mutant runs (`r2/mut/manifest-after.txt`). +- `r2/gate.sh`: the `packages/webui` suite, `build-tokens.mjs --check`, + then every `scripts/test-*.sh` with `DOCKER_HOST=unix:///nonexistent.sock`, + 18:21:44Z to 18:24:57Z. +- 37 mutants (`r2/mut/mutate.py`, `r2/mut/run.sh`), each against the full + webui suite, 18:25:08Z to 19:00:50Z. M01 to M20 are round 1's, with M11 + rewritten for the strip. M21 to M37 are new and aim at the round 2 code. +- `test-release` with Docker, finished 19:01:30Z. Then the S5 browser test + three times on the unmutated candidate (`r2/out/s5-rep-*.txt`), see + note 3. +- Probes in Chromium through the candidate's `tests/browser.mjs` + (`r2/probes/probe2.test.mjs`, output `r2/probes/probes-cand.txt`). The + first test is my round 1 probe set again, a fake board and fake bus + verbs, plus P9. The second, P10, runs the real control-board from the + candidate's `tests/history-fixture.mjs` behind a small proxy that can + answer every request with 403, the way control-board's Host check does. + No tracker request. +- Read the five changed files against round 1's required list, Filbert's + comment 27143 and `IMPLEMENTING.md`. + +Node v26.8.1, `TMPDIR=~/darkwing-scratch/r53b/tmp`. + +## Suites + +| Suite | Result | +|---|---| +| packages/webui (node) | 27/0 | +| build-tokens --check | rc 0, "tokens.css is current" | +| test-auth | 15/0 | +| test-conductor | 17/0 | +| test-config | 24/0 | +| test-discord | 66/0 | +| test-extension-package | 18/0 | +| test-foundation | 44/0 | +| test-queue | 27/0 | +| test-release | 4/0 without Docker, 14/0 with it | +| test-task, Docker unreachable | 26/0 | + +As in round 1, I didn't run test-task with real Docker because it makes +live model calls. Dewey's run gave 98/0. Filbert's gate also ran the other +node packages, all green. + +## Round 1 items + +| Item | Result | +|---|---| +| Required 1, board refusal | Fixed for a single refusal. The inspector closes, the tree reads "Not read: the board refused the read.", the counts show "–", and the footer, `#status` and `#fresh-board` all say not read (P1, P2) | +| Required 2, bus refusal | Fixed. `forget()` clears `last` and the Inbox count from a view, from the board route and from `pkOpen`. The palette lists only the four views and the section list has no counts (P3, P4, P4b). P7 now shows no task rows | +| Required 3, tests | Done for the inspector. Not for an open conversation, see Required 2 below | +| Required 4, M01 | Done. `no-bus-host` runs over kept rows and M01 dies | +| Required 5, M08 | Done. Markup in a question and a task title, and M08 dies | +| Filbert C3 | Done. "Board not read: refused" | + +The notes: the strip is now one row below 760px (note 1). The toast stays +in the accessibility tree while off, at 1×1 with `clip-path` (note 4, P8). +M09 and M16 are tested and die. Note 2 (freshness hidden below 760px) and +note 5 (Seen 403 wording) are unchanged, and that's fine. + +## The strip test + +Sage asked me to check it. `shell.test.mjs` sets 360px and then 400px and +asserts four things at each width: + +- every `#sections a` has the same `offsetTop`; +- the list's computed `overflow-x` is `auto` or `scroll`; +- no label wraps (one client rect, `scrollWidth` within the box); +- the page doesn't scroll sideways. + +All three of Sage's properties are pinned. Three mutants confirm it: M11 +(back to wrap and visible) fails "one row at 360px", M37 (wrap with +`overflow-x:auto`) fails the same, and M36 (one row with +`overflow-x:visible`) fails "strip scrolls at 360px". M36 is caught only +by the computed-style check, because the fixture's labels fit at 360px +and the page never overflows. That check is the right one to have. + +## Probes + +Fixture as in round 1: one board with two sessions (project `secretproj`, +task "Kept fixture task"), one inbox decision and one task. P10 uses the +control-board fixture's session, whose history holds "Secret question from +before the refusal" and "Secret answer from before the refusal". + +| Probe | Candidate | +|---|---| +| P1 board 403 with the inspector open | `#board-view` `display:none`, inspector hidden. Fixed | +| P2 board 403 | tree, footer, `#status` and `#fresh-board` say not read. Fixed | +| P3 bus `human-required` after a read | the palette lists only Board, Inbox, Tasks and Agents. Fixed | +| P4, P4b the same refusal | no Inbox count or BLOCKING chip, on a bus view and on the board page. Fixed | +| P6 `not-configured` after a good read | `banner ref`, no task rows | +| P7 refusal, then `outcome-unknown` | `banner err`, no task rows | +| P8 the toast before any copy | `display:flex`, 1×1, empty, in the tree | +| **P9** good read, board 403, then a 500 | `#board-view` is `display:block` again with both session rows and the waiting card ("agent1 … secretproj … Kept fixture task … Input needed: kept text"). The banner says "No board data loaded", `#fresh-board` "the read failed", the footer still "refused" | +| P9b then a good read | 2 rows, footer "waiting 1 · working 1". Recovery works | +| **P10** History open, then every board request 403 | `#conversation` stays shown with the title, the meta line and both secret messages in `#conv-log`. Beside it, `#board-refused` says "Nothing to show. The board refused the read, so Console shows nothing rather than a guess." | + +P9: on a 403, `error()` sets `data = null` but leaves the markup in +`#sessions`, `#waiting` and `#seen`, and `render()` returns at once when +`!data`. The table hides only through `body.board-refused #board-view`. +The next `error()` that isn't a 403 removes that class and the old markup +shows again. The README line "A board refusal drops the last scan and +everything drawn from it" is not true after that second failure. + +P10: `#conversation` sits outside `#board-view` (`index.html` line 17), +so the `board-refused` rule doesn't reach it. `convForm()` runs and the +reply form says "This session is no longer in the board scan", but the +history read before the refusal stays on screen. Filbert's T7 predicts +this from the code; P10 shows it with the real control-board. + +## Mutants + +35 of 37 killed (`r2/mut/summary.txt`). Every kill is an assertion or a +wait timeout, not a load error. + +| Mutant | Change | Result | +|---|---|---| +| M01 | `refusal()` drops `not-configured` and `no-bus-host` | killed (was survived) | +| M02 | `error()`: `refused = false` | killed | +| M03 | no `body.board-refused` toggle | killed | +| M04 | the `refused:` code not in `` | killed (was survived) | +| M05 | no stale words in the bus freshness line | killed | +| M06 | System sets `data-mode` | killed | +| M07 | toast text not escaped | **survived** | +| M08 | palette label not escaped | killed (was survived) | +| M09 | `:focus-visible` offset 0 | killed (was survived) | +| M10 | focus outline 1px | killed | +| M11 | strip back to wrap, `overflow-x` visible | killed (was survived) | +| M12 | no section icons | killed | +| M13 | `accept()` doesn't clear `board-refused` | killed | +| M14 | task-link ↑/↓ reversed | killed | +| M15 | `/icons.svg` served as `text/plain` | killed | +| M16 | no `tabular-nums` | killed (was survived) | +| M17 | storage key changed | killed | +| M18 | no `body.board-refused #board-view` rule | killed | +| M19 | refusal shows kept rows | killed | +| M20 | board refusal uses `banner err` | killed | +| M21 | `forget()` does nothing | killed | +| M22 | the board route's inbox read swallows a refusal | killed | +| M23 | a view's refusal doesn't call `forget()` | killed | +| M24 | `pkOpen` ignores a refused refetch | killed | +| M25 | a board 403 keeps `selected` | killed | +| M26 | `fresh()` loses the "refused" wording | killed | +| M27 | a board 403 keeps the footer | killed | +| M28 | a board 403 keeps `#status` | killed | +| M29 | a board 403 keeps the project tree | killed | +| M30 | a board 403 keeps the three heading counts | **survived** | +| M31 | `freshBus` loses the refused state | killed | +| M32 | `.toast:not(.on)` is `display:none` again | killed | +| M33 | `forget()` keeps the Inbox count | killed | +| M34 | `forget()` keeps `last` | killed | +| M35 | board freshness in local time | killed | +| M36 | strip one row, `overflow-x:visible` | killed | +| M37 | strip wraps, `overflow-x:auto` | killed | + +M07 survives as in round 1. The toast text comes from validated refs, and +Dewey declined it with a reason. I accept that. + +M30 survives because the three counts sit inside `#board-view`, which is +hidden while refused. Today that makes it close to equivalent. After P9 +it isn't: the counts come back into view with the rows. Filbert's T7 asks +for the same assertion. A P9 test that checks the counts kills it. + +## Required + +1. **P9, Filbert's C4.** After a board 403, a later failure that isn't a + 403 must not show the refused scan. Clear `#sessions`, `#waiting` and + `#seen` in `error()` on a refusal, or hide `#board-view` whenever + `data` is null. Test: a good read, a 403, then a 500, and assert no + session row, no waiting card and the three counts not numeric. +2. **P10.** A board 403 closes an open conversation, or hides + `#conversation` under `body.board-refused`. Closing is cleaner, + because the history then leaves the DOM. Test: open History, refuse + the board, and assert `#conversation` is hidden and `#conv-log` is + empty or hidden. `history-fixture.mjs` already gives you the + conversation; a proxy that answers 403 is about 20 lines (mine is in + `r2/probes/probe2.test.mjs`). + +Then fix the README line on refusals if the wording no longer matches. + +## Notes (not blocking) + +1. I agree with Filbert's N4 to N7. N6 (a bus read in flight when + `forget()` runs puts its rows back) is real by the code, and it only + restores a read that succeeded, so it can wait. +2. P1 hides the inspector, but its text stays in the DOM. With the + inspector hidden that is fine; if you take the "clear on refusal" + route for Required 1, clearing it too costs one line. +3. In the M05 run, S5 also failed at `bus-browser.test.mjs` line 124 + ("BODY" !== "H1"). M05 only changes the bus freshness words, so that + failure isn't the mutant's doing. S5 passed in the gate, in the 36 + other mutant runs and three times alone afterwards. The cause is a + race in `render()` that base `2d4d4e7d` has too. The 10 s refresh + timer isn't cleared when a navigation starts. If it fires during a + navigated read, the refresh (`navigated = false`) takes `gen`, the + navigation's own render returns early, and nobody focuses the new + `h1` or announces it. Under the mutant load a read took long enough + to hit that window. Not this row's regression and not blocking. + `clearTimeout(timer)` at the top of `render()`, or carrying + `navigated` into the next render, would close it. Worth its own small + row. + +## Files + +- `r2/candidate-manifest.sha256`: copy of Dewey's. +- `r2/gate.sh`, `r2/out/`: suite runs, `summary.txt`, + `test-release-docker.txt`, the S5 repeats and `r1-to-r2.diff`. +- `r2/mut/`: mutant definitions, runner, diffs, outputs, `summary.txt` and + the manifest check after the runs. +- `r2/probes/`: the probe test and its output.