diff --git a/agents/filbert/work/queue-69/r1/review.md b/agents/filbert/work/queue-69/r1/review.md new file mode 100644 index 000000000..0c078298c --- /dev/null +++ b/agents/filbert/work/queue-69/r1/review.md @@ -0,0 +1,11 @@ +# Row 69 round 1 review, in progress + +Candidate c68e65828726b4f15cc0e0f231a26ea30e7dc30789aad145edc15b3995921c4b, four paths, detached base dad20531. Reconstructed under ~/filbert-scratch/r69-review/wt with Darkwing's build.patch applied by git apply --index and node_modules symlinked to the canonical checkout. Manifest 4/4 and no drift on the four paths (static-receipt.json). Candidate diff has no whitespace errors. + +Static review complete. The product changes only the hidden decide box text and App.render's temporary status override, preserving original state.status when the terminal grows. The short way-out line fits the minimum supported 40x10 frame without cutting the No guidance. The new tall-narrow tests check the too-small frame and no decision.resolve on y at eight explicit sizes, then sweep short/long questions over 30-39 columns and 33-60 rows. U+18D08 closes the width-range endpoint gap. The new help/detail cut test checks the retained tail and Esc line. README row counts are correctly examples rather than a universal minimum. No blocking static finding. + +Darkwing's existing help cut pointer issue is a bounded follow-up: it points to mosaic inbox --json for help, whose full text instead needs a taller help screen. It is outside this row's text/status changes. The deciding safety rule is unchanged. + +Remaining verification: sequential cli and queue node suites, then six named mutations (brief's four plus hidden way-out/status). verify.py runs one stage at a time, checks both scratch roots before every test, uses a process group per run with group kill on timeout, restores each mutated source, and checks the manifest. Its syntax was checked; it has not been executed yet. No verdict posted. + +Test ownership: Dewey's row 69 mutants were active at the initial /proc check, then ended at 23:15:24Z. Dewey's row 90 round 2 gate started at 23:15:51Z and has 44 mutants following it; expected scratch-clear around 23:30Z. Dewey reserved the next slot for this review and paused row 94 until I report row 69 tests finished. Sage's order: work row 69 while row 90 round 2 is not requested; finish the current step and switch to row 90 once its request arrives; row 97 static review follows row 69. Preserve those gates rather than overlap tests. diff --git a/agents/filbert/work/queue-69/r1/static-receipt.json b/agents/filbert/work/queue-69/r1/static-receipt.json new file mode 100644 index 000000000..e00744aa5 --- /dev/null +++ b/agents/filbert/work/queue-69/r1/static-receipt.json @@ -0,0 +1,12 @@ +{ + "candidate": "c68e65828726b4f15cc0e0f231a26ea30e7dc30789aad145edc15b3995921c4b", + "base": "dad20531", + "head_at_check": "e2ca558c3b55b6e027cd2a6f1063d8707b7cba68", + "manifest_matches": { + "packages/cli/README.md": true, + "packages/cli/src/app.mjs": true, + "packages/cli/src/screens.mjs": true, + "packages/cli/tests/app.test.mjs": true + }, + "drift_paths": [] +} diff --git a/agents/filbert/work/queue-69/r1/verify.py b/agents/filbert/work/queue-69/r1/verify.py new file mode 100644 index 000000000..b3b93011e --- /dev/null +++ b/agents/filbert/work/queue-69/r1/verify.py @@ -0,0 +1,64 @@ +"""Run one row 69 verification stage after the reserved test slot clears.""" +import os, subprocess, signal, pathlib, json, hashlib, sys +root=pathlib.Path.home()/'filbert-scratch/r69-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') +seats=['darkwing','dewey','rocko','researcher','sage'] +other=[str(pathlib.Path.home()/f'{seat}-scratch') for seat in seats]+[str(pathlib.Path('/mnt/storage/scratch')/seat) for seat in seats] +def 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 active: '+repr(busy)) +def matches(): + m=pathlib.Path('/mnt/storage/src/mosaic-stack/agents/darkwing/work/queue-69/candidate-manifest.sha256') + for line in m.read_text().splitlines(): + sha,path=line.split();assert hashlib.sha256((root/path).read_bytes()).hexdigest()==sha,path +quiet();matches() +def run(cmd,cwd,log): + quiet() + 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=180) + except subprocess.TimeoutExpired: + os.killpg(p.pid,signal.SIGKILL);p.wait();return 'timeout' + return p.returncode +stage=sys.argv[1] +if stage in ['cli','queue']: + cwd=root/'packages'/stage + files=[str(p.relative_to(cwd)) for p in sorted((cwd/'tests').glob('*.test.mjs'))] + rc=run(['node','--test',*files],cwd,out/f'{stage}.log') + stats=[s for s in (out/f'{stage}.log').read_text().splitlines() if s.startswith(('ℹ tests ','ℹ pass ','ℹ fail ','# tests ','# pass ','# fail '))] + row={'suite':stage,'rc':rc,'stats':stats};print(json.dumps(row),flush=True) + (out/f'{stage}-summary.json').write_text(json.dumps(row,indent=2)+'\n') + raise SystemExit(rc!=0) +if stage!='mutants':raise SystemExit('usage: verify.py cli|queue|mutants') +S='packages/cli/src/screens.mjs';A='packages/cli/src/app.mjs' +M=[ + ('shown-no-min-cols',S,'return cols >= MIN_COLS && rows >= MIN_ROWS && o?.kind','return rows >= MIN_ROWS && o?.kind'), + ('r3-shown-no-min',S,'return cols >= MIN_COLS && rows >= MIN_ROWS && o?.kind','return o?.kind'), + ('n9-17000-end-off',S,'(n >= 0x17000 && n <= 0x18d08)','(n >= 0x17000 && n <= 0x18cff)'), + ('cut-drops-choice',S,'const tail = b.slice(-2);','const tail = b.slice(-1);'), + ('hidden-no-way-out',S,', "Resize, or use mosaic decide."]',']'), + ('hidden-status-promises-y',A,'const state = hidden ? {','const state = false ? {'), +] +rows=[] +for name,path,old,new in M: + quiet();p=root/path;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','packages/cli/tests/app.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() +rc=run(['node','--test','packages/cli/tests/app.test.mjs'],root,out/'restored-app.log') +rows.append({'restored_app_rc':rc,'manifest_matches':True}) +(out/'mutant-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)) diff --git a/agents/filbert/work/queue-97/r1/review.md b/agents/filbert/work/queue-97/r1/review.md new file mode 100644 index 000000000..4c64f2836 --- /dev/null +++ b/agents/filbert/work/queue-97/r1/review.md @@ -0,0 +1,11 @@ +# Row 97 round 1 static review, verification pending + +Candidate bdeca38dc8897b711b68f055cf346fc0ba6c04721e22720906c6b8fddc97902a, three paths, detached base 3bd3f85c. Reconstructed under ~/filbert-scratch/r97-review/wt with Researcher's build.patch applied by git apply --index and node_modules symlinked. Manifest 3/3 and no drift (static-receipt.json). No product source change is in the candidate. + +The edge test races the first board request against five seconds, clears the timer, and reaches existing finally cleanup on failure. The held-board test intercepts only 10000 ms poll timers and accelerates them to 150 ms in the redirect test; other timer delays retain their behavior. It records board versus bus timers, checks no board timer with the machine toggle off including Pause/Resume and reload, and checks no new timer after sign-out even through forced Pause/Resume handlers. Those timer observations expose schedule mutants whose downstream guards otherwise suppress the network read. README names all six redirect requests and explains the accelerated ticks. + +Static inspection found no blocking issue. Runtime checks still need to establish failure within 30 seconds, normal browser/server cleanup, timer mutant kills 13 and 27, and passing suites. Researcher's mutant runner kills the process group unconditionally even after normal exit, so an independent toggle-on run should check for leftovers before doing safety cleanup; that distinguishes test cleanup from runner cleanup. Mutant 14 is intentionally not claimed and appears redundant behind api's sign-out guard, subject to runtime confirmation. + +The packet reports test-discord failed because its scratch lacked node_modules. Reconstructing with the standard node_modules symlink permits an independent dependency-complete check; this report does not treat that baseline failure as a candidate defect or claim it passed. + +No browser or webui tests have been run in this review. Sage's priority is row 69, row 90 round 2 once requested, then row 97 and row 98. Other seats have reserved the test machine. Do a /proc cwd busy check across both home scratch and /mnt/storage/scratch before every test, and use process groups with timeout cleanup and source restoration for mutants. No verdict posted. diff --git a/agents/filbert/work/queue-97/r1/static-receipt.json b/agents/filbert/work/queue-97/r1/static-receipt.json new file mode 100644 index 000000000..9f7005b33 --- /dev/null +++ b/agents/filbert/work/queue-97/r1/static-receipt.json @@ -0,0 +1,11 @@ +{ + "candidate": "bdeca38dc8897b711b68f055cf346fc0ba6c04721e22720906c6b8fddc97902a", + "base": "3bd3f85c", + "head_at_check": "291638f839a1d1bdc8fe8d0363bcd6a33bd6fb06", + "manifest_matches": { + "packages/webui/README.md": true, + "packages/webui/tests/board-held.test.mjs": true, + "packages/webui/tests/browser-edge.test.mjs": true + }, + "drift_paths": [] +} diff --git a/agents/filbert/work/queue-97/r1/verify.py b/agents/filbert/work/queue-97/r1/verify.py new file mode 100644 index 000000000..7df8fad24 --- /dev/null +++ b/agents/filbert/work/queue-97/r1/verify.py @@ -0,0 +1,82 @@ +"""Row 97 independent verification. Do not run before its assigned test slot.""" +import os, subprocess, signal, pathlib, json, hashlib, sys, time +root=pathlib.Path.home()/'filbert-scratch/r97-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') +seats=['darkwing','dewey','rocko','researcher','sage'] +other=[str(pathlib.Path.home()/f'{seat}-scratch') for seat in seats]+[str(pathlib.Path('/mnt/storage/scratch')/seat) for seat in seats] +def 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 active: '+repr(busy)) +def matches(): + m=pathlib.Path('/mnt/storage/src/mosaic-stack/agents/researcher/work/queue-97/candidate-manifest.sha256') + for line in m.read_text().splitlines(): + sha,path=line.split();assert hashlib.sha256((root/path).read_bytes()).hexdigest()==sha,path +quiet();matches() +def active_group(group): + found=[] + for d in pathlib.Path('/proc').iterdir(): + if not d.name.isdigit():continue + try: + if os.getpgid(int(d.name))==group: + stat=(d/'stat').read_text().split(') ',1)[1].split()[0] + if stat!='Z':found.append((d.name,(d/'comm').read_text().strip())) + except OSError:pass + return found +def run(cmd,cwd,log,limit=180): + quiet();start=time.monotonic() + 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=limit);rc=p.returncode + except subprocess.TimeoutExpired: + rc='timeout' + try:os.killpg(p.pid,signal.SIGKILL) + except ProcessLookupError:pass + p.wait() + # Record normal cleanup BEFORE safety cleanup. Do not conceal leftover browser processes. + leftovers=active_group(p.pid) + if leftovers: + try:os.killpg(p.pid,signal.SIGKILL) + except ProcessLookupError:pass + return {'rc':rc,'seconds':round(time.monotonic()-start,2),'leftovers_before_safety_cleanup':leftovers} +rows=[];stage=sys.argv[1] +if stage in ['webui','control-board']: + cwd=root/'packages'/stage;r=run(['node','--test','tests/'],cwd,out/f'{stage}.log') + r.update(suite=stage,stats=[s for s in (out/f'{stage}.log').read_text().splitlines() if s.startswith(('ℹ tests ','ℹ pass ','ℹ fail ','# tests ','# pass ','# fail '))]) + (out/f'{stage}-summary.json').write_text(json.dumps(r,indent=2)+'\n');print(json.dumps(r),flush=True) + raise SystemExit(r['rc']!=0 or bool(r['leftovers_before_safety_cleanup'])) +if stage=='shell': + for script in sorted((root/'scripts').glob('test-*.sh')): + r=run(['bash',str(script)],root,out/f'{script.stem}.log');r.update(suite=script.stem,last=(out/f'{script.stem}.log').read_text().splitlines()[-1:]) + rows.append(r);print(json.dumps(r),flush=True) + (out/'shell-summary.json').write_text(json.dumps(rows,indent=2)+'\n') + raise SystemExit(any(r['rc']!=0 or r['leftovers_before_safety_cleanup'] for r in rows)) +if stage!='mutants':raise SystemExit('usage: verify.py webui|control-board|shell|mutants') +A='packages/webui/src/public/app.js';B='packages/webui/src/public/bus.js' +M=[ + ('13 toggle-off schedule',A,'if (!paused && machine && !out()) timer','if (!paused && !out()) timer',['tests/board-held.test.mjs'],120), + ('27 signed-out bus schedule',B,'if (!paused() && !out()) timer','if (!paused()) timer',['tests/board-held.test.mjs'],120), + ('19 toggle on reads nothing',A,'fresh(); refresh(); } else hideMachine();','fresh(); } else hideMachine();',['tests/browser-edge.test.mjs'],30), +] +start={path:hashlib.sha256((root/path).read_bytes()).hexdigest() for path in [A,B]} +for name,path,old,new,tests,limit in M: + quiet();p=root/path;orig=p.read_bytes();src=orig.decode();assert src.count(old)==1,(name,src.count(old)) + try: + p.write_text(src.replace(old,new));log=out/f'mutant-{name.split()[0]}.log' + r=run(['node','--test',*tests],root/'packages/webui',log,limit) + r.update(mutant=name,result='survived' if r['rc']==0 else 'stalled' if r['rc']=='timeout' else 'killed') + if name.startswith('19 '):r['five_second_message_seen']='Show machine sessions made no /api/board request in 5 s' in log.read_text() + rows.append(r);print(json.dumps(r),flush=True) + finally:p.write_bytes(orig) +assert all(hashlib.sha256((root/path).read_bytes()).hexdigest()==sha for path,sha in start.items()) +matches() +r=run(['node','--test','tests/board-held.test.mjs','tests/browser-edge.test.mjs'],root/'packages/webui',out/'restored-tests.log') +r.update(restored_tests=True,manifest_matches=True,product_sources_restored=True);rows.append(r);print(json.dumps(r),flush=True) +(out/'mutant-summary.json').write_text(json.dumps(rows,indent=2)+'\n') +raise SystemExit(r['rc']!=0 or any(x.get('result') in ['survived','stalled'] or x['leftovers_before_safety_cleanup'] or x.get('five_second_message_seen') is False for x in rows)) diff --git a/docs/SESSIONS.md b/docs/SESSIONS.md index 787d9a99d..48035a22c 100644 --- a/docs/SESSIONS.md +++ b/docs/SESSIONS.md @@ -815,3 +815,4 @@ are never rewritten or removed; corrections are new entries. 2026-10-12T23:10:13Z | sage | row 94 review request as jarvis, row 91 re-pin under decision 126, row 63 gate and landing | 94 requested comment 28025 revs 834-835; 91 re-pinned to 844832c3 rev 836 with host git guards (020ad78c); 63 landed b8539480 rev 838, gate tasks 84 harness 65 scripts green, #1556 closed 28035; Mos notified; pushed 2026-10-12T23:16:00Z | researcher | rows 97 (#1591) and 98 (#1592) built on Sonnet 5.5 under decision 124; I1 survey committed 85aa676f | 97: N1 5 s fail-fast (mutant 19 killed in 5.8 s, baseline stalled), N2 150 ms poll timers plus recorded 10 s timers (mutants 13 and 27 killed, 14 equivalent), N3 README names six requests; packet 81c2906c, in-review round 1 rev 843, request failed on credentials, posted by Sage comment 28042. 98: four refusal cases, 8 of 8 mutants killed (baseline 1 of 8), script unchanged; packet 452ea3ca, in-review round 1 rev 848, request op researcher-r98-review-20261012t231549z failed on credentials, Sage to post. Sweep clean, no process under my scratch. 2026-10-12T23:18:05Z | dewey | row 69 round 1 review (#1562) | approve, comment 28048, candidate c68e6582; cli 123, queue 150; 8/11 mutants killed, 3 non-blocking survivors in the resolving state and status style; receipts 47292b57, rev 852 in e9988d26 +2026-10-12T23:20:59Z | filbert | rows 69 (#1562) and 97 (#1591) static reviews | reconstructed manifests 4/4 (c68e6582) and 3/3 (bdeca38d), no drift, no blocking static finding; guarded verification scripts ready and syntax checked, no tests or verdicts; Dewey owns row 90 gate/mutant slot until about 23:30Z, then my row 69; row 90 round 2 takes priority when requested, followed by rows 97 and 98; Darkwing gets direct scratch-clear after my tests