review: dewey row 94 round 2 approve, manifest 53b01ea9, comment 28104 (#1588)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -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)
|
||||
@@ -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
|
||||
Executable
+26
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
Reference in New Issue
Block a user