Files
jason.woltjeandClaude Opus 5.5 ebbbf62dac docs: Dewey row 133 round 1 packet (#1627, decision closes and messaging lists)
Validator refuses a messaging-limited arbiter; decision.raise refuses a route
that can't message the raiser (decision-route-refused). Candidate on e6e5b41bf,
manifest sha256 edb43aed. Targeted gate green, 5/5 mutants killed.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 12:33:27 -05:00

46 lines
3.1 KiB
Python
Executable File

#!/usr/bin/env python3
"""Row 133 (#1627): one fault per check. Sequential process groups; whole-group timeout cleanup.
--dry checks every mutation site matches and changes source, and runs nothing.
A control run first runs each distinct test set on the unmutated source; any failure stops the run."""
import json,os,pathlib,signal,subprocess,sys
args=[a for a in sys.argv[1:] if a!='--dry'];DRY='--dry' in sys.argv
ROOT=pathlib.Path(args[0] if args else os.path.expanduser('~/dewey-scratch/r133/wt'))
OUT=pathlib.Path(__file__).resolve().parent/'mutants'
AT='packages/business/tests/assistant.test.mjs';RT='packages/bus/tests/decision-route.test.mjs'
cases=[]
def add(id,path,old,new,test):cases.append(dict(id=id,path=path,old=old,new=new,test=test if isinstance(test,list) else [test]))
add('01-validator-check','packages/business/src/business.mjs','if (definitions[definition].messaging) {','if (false) {',AT)
p='packages/bus/src/broker.mjs'
RAISE="if (cls !== 'within-role') this.#checkMessaging(s.business, route, s.role, 'decision-route-refused');"
add('02-raise-check',p,RAISE,'/* no route check */',RT)
add('03-raise-direction',p,RAISE,"if (cls !== 'within-role') this.#checkMessaging(s.business, s.role, route, 'decision-route-refused');",RT)
add('04-within-role-exempt',p,RAISE,"this.#checkMessaging(s.business, route, s.role, 'decision-route-refused');",RT)
add('05-raise-own-code',p,RAISE,"if (cls !== 'within-role') this.#checkMessaging(s.business, route, s.role);",RT)
def run(name,test):
env={**os.environ,'DOCKER_HOST':'unix:///nonexistent.sock'}
with (OUT/(name+'.log')).open('w') as log:
p=subprocess.Popen(['node','--test',*test],cwd=ROOT,env=env,stdout=log,stderr=subprocess.STDOUT,start_new_session=True)
try:return p.wait(timeout=300)
except subprocess.TimeoutExpired:os.killpg(p.pid,signal.SIGKILL);p.wait();return 'timeout'
results=[];control=[]
if not DRY:
OUT.mkdir(exist_ok=True)
sets=[];[sets.append(c['test']) for c in cases if c['test'] not in sets]
for i,t in enumerate(sets):
rc=run('control-%02d'%(i+1),t);control.append(dict(id='control-%02d'%(i+1),test=t,exit=rc));print('control-%02d'%(i+1),' '.join(t),'PASS' if rc==0 else 'FAIL',rc,flush=True)
if rc!=0:(OUT/'control.json').write_text(json.dumps(control,indent=2)+'\n');sys.exit('control failed: unmutated source fails '+' '.join(t))
(OUT/'control.json').write_text(json.dumps(control,indent=2)+'\n')
for c in cases:
file=ROOT/c['path'];before=file.read_text();matches=before.count(c['old'])
if not matches:raise RuntimeError('missing mutation site '+c['id'])
after=before.replace(c['old'],c['new'])
if after==before:raise RuntimeError('no change '+c['id'])
if DRY:print(c['id'],'sites',matches,flush=True);continue
file.write_text(after)
try:
rc=run(c['id'],c['test'])
verdict='KILLED' if isinstance(rc,int) and rc!=0 else 'SURVIVED' if rc==0 else 'TIMEOUT'
row={k:c[k] for k in ['id','path','test']};row.update(result=verdict,exit=rc,sites=matches);results.append(row);print(c['id'],verdict,rc,flush=True)
finally:file.write_text(before)
if not DRY:(OUT/'results.json').write_text(json.dumps(results,indent=2)+'\n')