Files
stack/agents/filbert/work/queue-63/r2/verify.py
T

69 lines
4.3 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.
"""Filbert's row 63 round 2 verification. Run only after the booked test slot clears."""
import os, subprocess, signal, pathlib, json, hashlib
root=pathlib.Path(os.environ.get('MOSAIC_REVIEW_ROOT',str(pathlib.Path.home()/'filbert-scratch/r63-review/wt')))
out=root.parent/'verification'; out.mkdir(exist_ok=True)
env=dict(os.environ,TMPDIR=str(pathlib.Path.home()/'filbert-scratch/tmp'),DOCKER_HOST='unix:///nonexistent.sock')
# Do not route around another seat's test ownership.
seats=['darkwing','dewey','rocko','researcher','sage']
other=[str(pathlib.Path.home()/f'{seat}-scratch') for seat in seats]
other += [str(pathlib.Path('/mnt/storage/scratch')/seat) for seat in seats]
def require_quiet():
busy=[]
for p in pathlib.Path('/proc').iterdir():
if not p.name.isdigit(): continue
try:
cwd=str((p/'cwd').resolve(strict=True))
if any(cwd==x or cwd.startswith(x+'/') for x in other):busy.append((p.name,cwd))
except (OSError,RuntimeError):pass
if busy:raise SystemExit('Other scratch processes still active: '+repr(busy))
require_quiet()
manifest=pathlib.Path('/mnt/storage/src/mosaic-stack/agents/darkwing/work/queue-63/r2/candidate-manifest.sha256')
def matches():
for line in manifest.read_text().splitlines():
sha,path=line.split();assert hashlib.sha256((root/path).read_bytes()).hexdigest()==sha,path
matches()
def run(cmd,cwd,log):
with log.open('w') as f:
p=subprocess.Popen(cmd,cwd=cwd,env=env,stdout=f,stderr=subprocess.STDOUT,start_new_session=True)
try:p.wait(timeout=120)
except subprocess.TimeoutExpired:
os.killpg(p.pid,signal.SIGKILL);p.wait();return 'timeout'
return p.returncode
rows=[]
for package in ['tasks','harness']:
cwd=root/'packages'/package
files=[str(p.relative_to(cwd)) for p in sorted((cwd/'tests').glob('*.test.mjs'))]
log=out/f'{package}.log';rc=run(['node','--test',*files],cwd,log)
stats=[s for s in log.read_text().splitlines() if s.startswith(('ℹ tests ','ℹ pass ','ℹ fail ','# tests ','# pass ','# fail '))]
row={'suite':package,'rc':rc,'stats':stats};rows.append(row);print(json.dumps(row),flush=True)
if rc!=0:(out/'summary.json').write_text(json.dumps(rows,indent=2)+'\n');raise SystemExit('Baseline suite failed')
R='{ ...at, project: ctx.project, view: ctx.view }'
mutants=[
('located-first-only','for (const r of list) {','for (const r of list.slice(0, 1)) {'),
('step-reread-root','after = await read(at);\n } catch {\n // the re-read failed too',f'after = await read({R});\n }} catch {{\n // the re-read failed too'),
('handle-final-root','after = await read(at);\n } catch {\n // handled below: a failed',f'after = await read({R});\n }} catch {{\n // handled below: a failed'),
('create-final-root','after = await read(at);\n } catch {\n // handled below, as in handle()',f'after = await read({R});\n }} catch {{\n // handled below, as in handle()'),
('create-fallback-root-todo','taskFields(r.json, at.view.ids.todo)','taskFields(r.json, ctx.view.ids.todo)'),
('read-done-root','let bucket = at.view.done;','let bucket = ctx.view.done;'),
('close-done-root','(a) => a.task.done && a.bucket === view.done,','(a) => a.task.done && a.bucket === ctx.view.done,'),
]
pattern='a verb and a create in the child|a create in the child whose final read fails|a lost answer in the child|every related task is read before authority'
p=root/'packages/tasks/src/verbs.mjs'
for name,old,new in mutants:
require_quiet()
src=p.read_text();assert src.count(old)==1,(name,src.count(old))
try:
p.write_text(src.replace(old,new));log=out/f'mutant-{name}.log'
rc=run(['node','--test','--test-name-pattern='+pattern,'packages/tasks/tests/verbs.test.mjs'],root,log)
failures=[s for s in log.read_text().splitlines() if s.startswith(('✖','not ok'))]
row={'mutant':name,'rc':rc,'result':'survived' if rc==0 else 'timeout' if rc=='timeout' else 'killed','failures':failures[:4]}
rows.append(row);print(json.dumps(row),flush=True)
finally:p.write_text(src)
matches()
# Fresh passing run after restoration of all mutations.
rc=run(['node','--test','--test-name-pattern='+pattern,'packages/tasks/tests/verbs.test.mjs'],root,out/'restored-proof-tests.log')
rows.append({'restored_proof_tests_rc':rc,'manifest_matches':True})
(out/'summary.json').write_text(json.dumps(rows,indent=2)+'\n')
print(json.dumps(rows[-1]),flush=True)
raise SystemExit(rc!=0 or any(r.get('result') in ['survived','timeout'] for r in rows))