diff --git a/agents/dewey/work/queue-94-review/r2/mutants.py b/agents/dewey/work/queue-94-review/r2/mutants.py new file mode 100644 index 000000000..9a32e6f86 --- /dev/null +++ b/agents/dewey/work/queue-94-review/r2/mutants.py @@ -0,0 +1,38 @@ +# Row 94 round 2 review mutants (Dewey): my eight round 1 sites, rerun on the round 2 candidate. Each swaps one +# exact string in a scratch worktree of the candidate, runs the touched package's whole node suite in its own +# process group (killed after 400 s, which counts as a kill), and restores the file. +import subprocess, sys, os, signal +M = os.path.expanduser('~/dewey-scratch/r94mut') +env = dict(os.environ, TMPDIR=os.path.expanduser('~/dewey-scratch/tmp')) +B = 'packages/bus/src/broker.mjs'; C = 'packages/cli/src/cli.mjs'; W = 'packages/webui/src/public/bus.js' +muts = [ + ('bus: read means delivered', B, "d.op='read') AS read FROM", "d.op IN ('delivered','read')) AS read FROM", 'bus'), + ('bus: unread excludes delivered', B, "d.op='read')),0) AS unread", "d.op IN ('delivered','read'))),0) AS unread", 'bus'), + ('cli: text inbox lists read messages', C, 'messages.push(...page.messages.filter(m => !m.read));', 'messages.push(...page.messages);', 'cli'), + ('cli: plain talk takes Ctrl-C', C, 'if (follow) process.on("SIGINT", stop);', 'process.on("SIGINT", stop);', 'cli'), + ('webui: count read only on Messages', W, "if (path !== '/messages') {", 'if (false) {', 'webui'), + ('webui: refusal keeps message count', W, 'inboxCount = null; messageCount = null; }', 'inboxCount = null; }', 'webui'), + ('webui: board ignores message count', W, "if (messages.status === 'fulfilled' && !refused) messageCount = messages.value.unread;", '', 'webui'), + ('webui: pre-read swallows 403', W, "if (err.status === 403 || err.code === 'signed-out') throw err;", "if (err.code === 'signed-out') throw err;", 'webui'), +] +only = sys.argv[1:] +for name, f, old, new, pkg in muts: + if only and not any(o in name for o in only): continue + p = os.path.join(M, f); src = open(p).read() + n = src.count(old) + if n != 1: print(f'BAD-ANCHOR ({n}) {name}', flush=True); continue + open(p, 'w').write(src.replace(old, new)) + d = os.path.join(M, 'packages', pkg) + tests = sorted('tests/' + t for t in os.listdir(os.path.join(d, 'tests')) if t.endswith('.test.mjs')) + proc = subprocess.Popen(['node', '--test', *tests], cwd=d, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, start_new_session=True) + try: + out, _ = proc.communicate(timeout=400) + except subprocess.TimeoutExpired: + os.killpg(proc.pid, signal.SIGKILL); proc.communicate() + out = None + finally: + open(p, 'w').write(src) + if out is None: + print(f'killed {name} (hung: killed after 400 s)', flush=True); continue + fails = [l for l in out.splitlines() if l.startswith('not ok')] + print(('killed ' if proc.returncode else 'SURVIVED') + f' {name}' + (f' ({len(fails)} failing: ' + ' | '.join(l[7:100] for l in fails) + ')' if fails else ''), flush=True) diff --git a/agents/dewey/work/queue-94-review/r2/mutants.txt b/agents/dewey/work/queue-94-review/r2/mutants.txt new file mode 100644 index 000000000..aa1b977fd --- /dev/null +++ b/agents/dewey/work/queue-94-review/r2/mutants.txt @@ -0,0 +1,8 @@ +killed bus: read means delivered +killed bus: unread excludes delivered +killed cli: text inbox lists read messages +killed cli: plain talk takes Ctrl-C +killed webui: count read only on Messages +killed webui: refusal keeps message count +killed webui: board ignores message count +killed webui: pre-read swallows 403 diff --git a/agents/dewey/work/queue-94-review/r2/run.sh b/agents/dewey/work/queue-94-review/r2/run.sh new file mode 100755 index 000000000..4d03ccd9e --- /dev/null +++ b/agents/dewey/work/queue-94-review/r2/run.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# Row 94 round 2 review run (Dewey), started after Researcher's "slot clear": the full gate on the candidate +# (build.patch on e918a915 in ~/dewey-scratch/r94), each package's node suite and every scripts/test-*.sh, +# sequential, output kept per suite; then my eight mutants in ~/dewey-scratch/r94mut and its manifest check. +O=$HOME/dewey-scratch/r94r2-out; M=$HOME/dewey-scratch/r94r2-packet/candidate-manifest.sha256 +export TMPDIR=$HOME/dewey-scratch/tmp +busy(){ for p in $(pgrep -f -- --test) $(pgrep -f "scripts/test-"); do [ "$p" = "$$" ] && continue; c=$(readlink /proc/$p/cwd 2>/dev/null) || continue; case "$(cat /proc/$p/comm 2>/dev/null)" in node*|bash) ;; *) continue;; esac; case "$c" in $HOME/dewey-scratch/*) ;; *) return 0;; esac; done; return 1; } +while busy || { sleep 15; busy; }; do sleep 15; done +cd $HOME/dewey-scratch/r94 || exit 9 +S=$O/summary.txt +echo "start $(date -u +%Y-%m-%dT%H:%M:%SZ) base $(git rev-parse HEAD)" > $S +echo "manifest $(sha256sum -c $M 2>&1 | grep -c ': OK$')/$(wc -l < $M) OK" >> $S +for p in tasks bus harness webui cli business seat control-board; do + case $p in seat|webui) a=(tests/);; *) a=(tests/*.test.mjs);; esac + (cd packages/$p && node --test "${a[@]}") > $O/gate/node-$p.log 2>&1; rc=$? + echo "node $p rc=$rc $(grep -E '^ℹ (tests|pass|fail)' $O/gate/node-$p.log | tr '\n' ' ')" >> $S +done +for f in scripts/test-*.sh; do + n=$(basename $f .sh) + DOCKER_HOST=unix:///nonexistent.sock bash $f > $O/gate/$n.log 2>&1; rc=$? + echo "$n rc=$rc $(tail -1 $O/gate/$n.log | cut -c1-120)" >> $S +done +echo "suites end $(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $S +python3 -I $O/mutants.py > $O/mutants.txt 2>&1; echo "mutants rc=$? end $(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $S +(cd $HOME/dewey-scratch/r94mut && sha256sum -c --quiet $M && echo "mut copy restored, manifest OK" >> $S) +echo "done $(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $S diff --git a/agents/dewey/work/queue-94-review/r2/summary.txt b/agents/dewey/work/queue-94-review/r2/summary.txt new file mode 100644 index 000000000..461cca832 --- /dev/null +++ b/agents/dewey/work/queue-94-review/r2/summary.txt @@ -0,0 +1,24 @@ +start 2026-10-13T12:39:18Z base e918a915a8b0fab0befe171f069b3f3204d758ed +manifest 16/16 OK +node tasks rc=0 ℹ tests 89 ℹ pass 89 ℹ fail 0 +node bus rc=0 ℹ tests 115 ℹ pass 115 ℹ fail 0 +node harness rc=0 ℹ tests 66 ℹ pass 66 ℹ fail 0 +node webui rc=0 ℹ tests 104 ℹ pass 104 ℹ fail 0 +node cli rc=0 ℹ tests 129 ℹ pass 129 ℹ fail 0 +node business rc=0 ℹ tests 60 ℹ pass 60 ℹ fail 0 +node seat rc=0 ℹ tests 33 ℹ pass 33 ℹ fail 0 +node control-board rc=0 ℹ tests 124 ℹ pass 124 ℹ fail 0 +test-auth rc=0 selftest: 15 passed, 0 failed +test-conductor rc=0 selftest: 17 passed, 0 failed +test-config rc=0 selftest: 24 passed, 0 failed +test-discord rc=0 discord suite: 66 passed, 0 failed +test-extension-package rc=0 extension package selftest: 18 passed, 0 failed +test-foundation rc=0 selftest: 44 passed, 0 failed +test-queue rc=0 queue suite: 27 passed, 0 failed +test-release rc=0 selftest: 4 passed, 0 failed +test-task rc=0 selftest: 26 passed, 0 failed +suites end 2026-10-13T12:42:46Z +mutants rc=0 end 2026-10-13T12:47:17Z +mut copy restored, manifest OK +done 2026-10-13T12:47:17Z +test-release (docker) rc=0 selftest: 14 passed, 0 failed end 12:47:32Z diff --git a/agents/dewey/work/queue-94-review/r2/verdict.md b/agents/dewey/work/queue-94-review/r2/verdict.md new file mode 100644 index 000000000..b9dc99ee8 --- /dev/null +++ b/agents/dewey/work/queue-94-review/r2/verdict.md @@ -0,0 +1,42 @@ +**Dewey: approve, round 2, candidate manifest `53b01ea9f65d8ec5812111701425e7c5c60bc31f36af2b42b541ae22a82cc1ad`** + +All five round 1 asks are in and tested, the gate is green on `e918a915`, and all eight of my round 1 mutants, seven of which survived round 1, are now killed. + +**What I checked** + +- `build.patch` from your packet `agents/rocko/work/queue-94/r2/` (its `packet-manifest` checks from the repo root), applied with `git apply --index` to a detached worktree of `e918a915` (row 90's landing), checks 16/16 and matches `files.txt`. None of the sixteen paths changed between `e918a915` and `refactor` HEAD. +- Round 1 to round 2, the product files carry the same added and removed lines; the rebase moved hunks only. The changes are the three test files and the broker comment. +- My five round 1 asks: + 1. `bus/tests/messages.test.mjs` asserts a message delivered without a read receipt stays `read: false`. + 2. The cli text-inbox test receives, then reads the first delivered message, and asserts `messages: 204 unread`, that the read one is gone, that unsolicited-1 and unsolicited-204 are listed, and that `inbox --json` is still the decision array. + 3. and 4. The new webui test checks the Messages count while on Tasks (2 to 3) and on the Board (3 to 4). It checks that a `human-required` refusal on the Board clears the count and shows refused. It also checks that a messages 403 refuses Queue, Business and Settings without a local read, and that each page recovers. `human-required` is what `webui/src/bus.mjs:86` maps to 403, so this is the real refusal path. + 5. `case 'messages'` now sits under its own comment, above row 81's replies comment. +- You also added 'plain talk leaves the process SIGINT handlers unchanged', which pins the `if (follow)` guard around the Ctrl-C handler. +- On the candidate, sequentially, 12:39:18-12:42:46Z, all rc=0: + - node suites: tasks 89, bus 115, harness 66, webui 104, cli 129, business 60, seat 33, control-board 124; + - every `scripts/test-*.sh`: auth 15, conductor 17, config 24, discord 66, extension-package 18, foundation 44, queue 27, task 26, release 14. + - My first pass had `DOCKER_HOST` at a dead socket for every script, so release ran 4 cases. I reran it with Docker at 12:47:32Z and got 14. + - bus, cli and webui match your counts. + +**Mutants** + +`mutants.py` and `mutants.txt` here. These are my eight round 1 sites, rerun unchanged; each anchor matches once in the round 2 candidate. Each mutant runs in a scratch worktree of the candidate against the touched package's whole node suite, in its own process group with a 400 s limit. A kill is judged by exit status. 12:42:46-12:47:17Z: **8 of 8 killed**, none hung; round 1 had 7 survivors. Afterwards the worktree matches the manifest again. + +| Mutant | Round 1 | Round 2 | +|---|---|---| +| bus: `read` counts delivered | survived | killed | +| bus: `unread` excludes delivered | killed | killed | +| cli: text inbox lists read messages | survived | killed | +| cli: plain `talk` takes Ctrl-C | survived | killed | +| webui: count read only on Messages | survived | killed | +| webui: refusal keeps the message count | survived | killed | +| webui: Board ignores the message count | survived | killed | +| webui: messages pre-read swallows 403 | survived | killed | + +Your BUILD.md reports 35/35 with focused tests, mine included as 28-35. This run uses whole package suites. + +**Non-blocking notes** + +Round 1's notes 6 to 10 (comment 28075) stand as written, as your BUILD.md says: the `spawnSync` Ctrl-C window in note 6 and notes 7 to 10 stay follow-ups, because round 2 doesn't change the product code they describe. None blocks. + +**Landing:** row 94 changes `packages/webui/src/public/bus.css` and `bus.js`, so decision 123 applies: the landing waits for Mos's go. bus, cli and webui are live in the canonical checkout (decision 109), so Mos hears before the landing.