Files
stack/agents/darkwing/work/queue-112/r1/mutants.py
T
jason.woltjeandClaude Opus 5.5 dbf72a2a3e darkwing: row 112 round 1 packet, decision.raise recommendation fix (#1606)
Candidate on 96656dd21: broker split refuses invalid-recommendation after the
option checks, raise_decision text asks for one key and names the yes default,
bus README codes table, broker and tools tests. Mutants m1 (old shared line)
and m2 (order swapped) killed; full gate passed 15:42:03-15:47:36Z.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 10:48:10 -05:00

55 lines
2.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
# Row 112 (#1606): mutants on the decision.raise choice checks in broker.mjs.
# m1 restores the old shared line, so a recommendation miss refuses
# invalid-options again (the brief's required mutant).
# m2 checks the recommendation before duplicate keys, so a bad option list
# with a missing recommendation reports invalid-recommendation.
# Each runs the FULL bus suite (node --test tests/*.test.mjs in packages/bus)
# and restores broker.mjs from the .orig copy whatever happens.
# Usage: mutants.py <worktree> <log dir>
import os, shutil, subprocess, sys, signal
WT, LOGS = sys.argv[1], sys.argv[2]
SRC = os.path.join(WT, 'packages/bus/src/broker.mjs')
CUR = (" if (new Set(choices).size !== choices.length) fail('invalid-options');\n"
" if (!choices.includes(a.recommendation)) fail('invalid-recommendation');\n")
MUTANTS = {
'm1': (" if (new Set(choices).size !== choices.length || !choices.includes(a.recommendation))\n"
" fail('invalid-options');\n"),
'm2': (" if (!choices.includes(a.recommendation)) fail('invalid-recommendation');\n"
" if (new Set(choices).size !== choices.length) fail('invalid-options');\n"),
}
os.makedirs(LOGS, exist_ok=True)
text = open(SRC).read()
if text.count(CUR) != 1:
sys.exit('STOP the choice checks in broker.mjs are not unique or have moved')
if os.path.exists(SRC + '.orig'):
sys.exit('STOP broker.mjs.orig already exists')
env = dict(os.environ, TMPDIR=os.path.expanduser('~/darkwing-scratch/r112/tmp'))
for name, new in MUTANTS.items():
log_path = os.path.join(LOGS, f'mutant-{name}.log')
shutil.copy2(SRC, SRC + '.orig')
try:
open(SRC, 'w').write(text.replace(CUR, new))
with open(log_path, 'w') as out:
p = subprocess.Popen('node --test tests/*.test.mjs', shell=True, cwd=os.path.join(WT, 'packages/bus'),
stdout=out, stderr=subprocess.STDOUT, env=env, start_new_session=True)
try:
rc = p.wait(timeout=600)
except subprocess.TimeoutExpired:
os.killpg(p.pid, signal.SIGKILL)
p.wait()
rc = 'timeout'
finally:
shutil.move(SRC + '.orig', SRC)
restored = open(SRC).read() == text
log = open(log_path).read()
counts = [l for l in log.splitlines() if l.startswith(('ℹ pass', 'ℹ fail', 'ℹ skipped'))]
failed = [l.strip() for l in log.splitlines() if l.lstrip().startswith('✖') and 'failing tests' not in l]
print(f'mutant {name} rc={rc} {" ".join(counts)} restored={restored}')
for f in sorted(set(failed)):
print(' ' + f)
print('KILLED' if rc != 0 else 'SURVIVED')
if not restored:
sys.exit('STOP broker.mjs was not restored')