Verdict comment 26778, queue rev 156. Within-role citations never reach the authority check or the grant event; other sends keep S2b. 58/58 on Node 24 and 26, seven of seven mutants killed. Co-Authored-By: Claude Opus 5.5 <[email protected]>
32 lines
2.1 KiB
Python
32 lines
2.1 KiB
Python
#!/usr/bin/env python3
|
|
# S2c round 1: Darkwing's mutants, repository layout, each compared to a clean baseline.
|
|
import pathlib,tempfile,shutil,subprocess,json,re,sys
|
|
cases=[
|
|
('citation-as-authority','broker.mjs',"decision: withinRole ? null : (a.decision ?? null),","decision: a.decision ?? null,"),
|
|
('always-within-role','broker.mjs',"this.#classification(s, 'message.send') === 'within-role'","true"),
|
|
('never-within-role','broker.mjs',"this.#classification(s, 'message.send') === 'within-role'","false"),
|
|
('caller-class-decides','broker.mjs',"this.#classification(s, 'message.send') === 'within-role'","a.class === 'DECISION'"),
|
|
('drop-existence-check','broker.mjs',"if (a.decision) this.#decision(s, a.decision);",""),
|
|
('drop-consumed-check','broker.mjs',"fail('decision-consumed');",";"),
|
|
('drop-class-match','broker.mjs',"d.class !== cls ||",""),
|
|
]
|
|
source=pathlib.Path(sys.argv[1])
|
|
def run(dest):
|
|
r=subprocess.run(['node','--test',*[str(p) for p in sorted((dest/'tests').glob('*.test.mjs'))]],capture_output=True,text=True,timeout=300)
|
|
tests=set(l[2:].rsplit(' (',1)[0] for l in r.stdout.splitlines() if l.startswith('✖ ') and not l.startswith('✖ failing tests'))
|
|
return r.returncode,tests
|
|
with tempfile.TemporaryDirectory(prefix='dw-s2c-mut-') as root:
|
|
dest=pathlib.Path(root)/'packages'/'bus';shutil.copytree(source,dest,ignore=shutil.ignore_patterns('dw'))
|
|
code,base=run(dest);print(json.dumps({'baseline_exit':code,'baseline_failures':sorted(base)}),flush=True)
|
|
code,f=run(dest);print(json.dumps({'mutation':'no-op','exit':code,'killed':bool(f-base)}),flush=True)
|
|
out=[]
|
|
for name,file,old,new in cases:
|
|
p=dest/'src'/file;b=p.read_text();pat=r'\s*'.join(re.escape(c) for c in old if not c.isspace());n=len(re.findall(pat,b))
|
|
if n!=1: print(json.dumps({'mutation':name,'error':f'{n} matches'}),flush=True);continue
|
|
p.write_text(re.sub(pat,lambda m:new,b,count=1))
|
|
try: code,f=run(dest)
|
|
finally: p.write_text(b)
|
|
x=sorted(f-base);out.append({'mutation':name,'exit':code,'killed':bool(x),'new_failures':x})
|
|
print(json.dumps(out[-1]),flush=True)
|
|
print('killed',sum(x['killed'] for x in out),'of',len(out))
|