filbert: rows 69 and 97 static reviews, verification pending test slot

This commit is contained in:
2026-10-12 18:20:59 -05:00
parent 291638f839
commit e608c233c0
7 changed files with 192 additions and 0 deletions
+11
View File
@@ -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.
@@ -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": []
}
+64
View File
@@ -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))
+11
View File
@@ -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.
@@ -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": []
}
+82
View File
@@ -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))
+1
View File
@@ -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