swayfx-mosaic/tooling/probes/step20c-static-nested-grab/collect.py

92 lines
8.9 KiB
Python

#!/usr/bin/env python3
"""Seal retained one-run observations without manufacturing missing evidence.
CONTRACT: runtime failures and real IPC codes stay immutable. No graphical replay.
INVARIANT: source/evidence manifests are created once and checked read-only.
"""
import argparse
import json
from pathlib import Path
import re
from PIL import Image
from support import OWNER,sha,save,verify,inventory
from predicates import protocol,mapped,geometry,popup_pixels,paint,pair,dismissal,root_clip,equal
from ipc_predicates import nodes,workspace,validate_outputs,validate_reference,scene_from_log
from geometry_audit import diagnose
p=argparse.ArgumentParser();p.add_argument('lab',type=Path);lab=p.parse_args().lab.resolve()
assert OWNER.read_text().strip()==str(lab)
assert not (lab/'results/evidence-sha256.txt').exists(),'already sealed'
verify(lab/'results/fixture-freeze-sha256.txt')
def read(n):return json.loads((lab/'results'/(n+'.json')).read_text())
run=lab/'run';runtime=read('runtime');terminal=read('terminal-exit');cleanup=read('cleanup')
protected=read('protected-before');assert all(sha(p)==h for p,h in protected.items()),'protected source/system change'
save(lab,'protected-after',dict(status='PASS',hashes=protected))
assert cleanup['runtime_removed'] and not Path(cleanup['runtime']).exists()
assert all(not Path('/proc',str(p['pid'])).exists() for p in cleanup['owned_processes'])
text=(run/'compositor.log').read_text();events=[json.loads(s) for s in (run/'events.jsonl').read_text().splitlines()]
full=runtime['status']=='PASS' and runtime['measurements_completed'] and terminal['scientific_cleanup_pass']
independent={}
if not full and runtime['stage']=='E1-open-A':
diagnostic=diagnose(lab);save(lab,'geometry-fixture-diagnostic',diagnostic)
save(lab,'applied-owner-geometry',dict(status='PARTIAL',E1=diagnostic['applied_owner'],painted_content_origin=diagnostic['painted_content_origin'],SHM_size=diagnostic['SHM_size'],assigned_content=diagnostic['assigned_content'],painted=diagnostic['painted_TOPLEVEL'],popups='NOT TESTED'))
save(lab,'applied-clips',dict(status='PARTIAL',tiled=diagnostic['tiled_clip'],root='NOT TESTED',child='NOT TESTED'))
save(lab,'mosaic-pixels',dict(status='PARTIAL',toplevel_H1=diagnostic['painted_TOPLEVEL'],H2=diagnostic['H2'],root='NOT TESTED',nested='NOT TESTED'))
if full:
baseline=Image.open(run/'H2-reference-1.png').convert('RGB')
owners=read('applied-owner-geometry');clips=read('applied-clips');grab_serials=[]
for name in ['E1','E2']:
client=(run/(name+'.log')).read_text();cut=client.index('POPUP_B MAP ');prefix=client[:client.index('\n',cut)+1]
pr=protocol(prefix);grab_serials += [g['serial'] for g in pr['grabs']]
g=geometry(prefix,owners[name]['content_origin'])
independent[name]=dict(protocol=pr,geometry=g,pixels=popup_pixels(Image.open(run/(name+'-mosaic-H1.png')).convert('RGB'),Image.open(run/(name+'-mosaic-H2.png')).convert('RGB'),g,True,baseline))
assert clips[name]['root']['raw'] in text
root_clip(clips[name]['root']['raw'],owners[name]['content_origin'],True)
assert len(set(grab_serials))==4 and grab_serials==sorted(grab_serials)
for file in ['H2-reference-2.png','E1-mosaic-H2.png','E1-dismissed-H2.png','E2-mosaic-H2.png','final-H2.png']:
assert equal(baseline,Image.open(run/file).convert('RGB'))['equal'],('full H2',file)
returns=read('standard-return');assert returns['root_clip']['raw'] in text
root_clip(returns['root_clip']['raw'],returns['geometry']['origin'],False)
stdsnap=read('standard-snapshot');ws=workspace(stdsnap['tree'],'1');assert ws['id']==owners['E2']['workspace'] and ws['layout']=='splith'
validate_reference(stdsnap,read('reference-stability')['reference']['con_id'],read('reference-stability')['reference']['pid'])
std=popup_pixels(Image.open(run/'standard-H1.png').convert('RGB'),Image.open(run/'standard-H2.png').convert('RGB'),returns['geometry'],False,baseline)
client=(run/'E2.log').read_text();cut=next(e['ns'] for e in events if e['kind']=='measurements-completed')
# Delivery must exist in actual retained recipient logs, not just summary JSON.
for row in read('clicks'):
for name,lines in row['events'].items():
actual=(run/(name+'.log')).read_text()
assert all(line in actual for line in lines)
for name,target in [('E1-visible-B','POPUP_B'),('E2-standard-B','POPUP_B'),('E2-standard-A','POPUP_A')]:
row=next(r for r in read('clicks') if r['tag']==name);who='E1' if name.startswith('E1') else 'E2'
pair(row['events'][who],target)
assert not row['events']['reference'] and not row['events']['filler']
forbidden=read('forbidden-input');dismissal((run/'E1.log').read_text(),forbidden['popup_events'])
assert client.index('POPUP_B DESTROY ')<client.index('COMMAND close_b DONE')<client.index('POPUP_A DESTROY ')
assert not re.search(r'wl_display[^\n]*\.error\(|protocol error',client,re.I)
assert runtime['duration_seconds']<=150 and not runtime['rescue_cleanup']
independent['standard']=std
save(lab,'independent-validation',dict(status='PASS',historical_status_unchanged=True,actual=independent,serials=grab_serials))
# Trace extents + capture diffs are retained as partial damage observations.
damage=[s for s in text.splitlines() if 'TEMPORAL_DAMAGE' in s]
save(lab,'damage-analysis',dict(status='PARTIAL',trace_count=len(damage),raw_extents=damage,
capture_windows=[e for e in events if e['kind']=='capture'],
changed_regions={n:independent[n]['pixels'] for n in ['E1','E2'] if n in independent},
limitations=['not every intermediate frame','not minimal damage','no native buffer/PNG identity','no exhaustive GPU lifetime']))
source=Path('/home/fy59/swayfx-mosaic-static-runtime-hm5kbdkt/mosaic-source/sway/desktop/xdg_shell.c')
save(lab,'scene-parentage',dict(status='PASS source-backed' if full else 'NOT TESTED runtime',source=str(source),source_sha256=sha(source),root='global popup layer; positioned from applied view content tree',nested='B wrapper under A xdg_surface_tree; same view',direct_child_trace='NOT AVAILABLE in immutable binary',runtime_XDG=read('xdg-protocol-order') if (lab/'results/xdg-protocol-order.json').exists() else None))
required=['applied-owner-geometry','popup-root-geometry','popup-nested-geometry','grab-serials','xdg-protocol-order','applied-clips','mosaic-pixels','mosaic-input','forbidden-input','dismissal','standard-return','standard-popup-pixels','standard-popup-input','reference-stability']
for n in required:
if not (lab/'results'/(n+'.json')).exists():save(lab,n,dict(status='NOT TESTED',stopping_stage=runtime['stage'],reason=runtime['failure']))
verdict='FEASIBLE' if full else (runtime.get('failure') or {}).get('verdict','INCONCLUSIVE')
architecture='STATIC_NESTED_VALID_GRAB_FEASIBLE_FOR_TESTED_MATRIX' if full else 'STATIC_NESTED_VALID_GRAB_REQUIRES_REDESIGN' if verdict=='BLOCKED' else 'UNDECIDED'
matrix={n:'PASS' if full else 'NOT TESTED: inspect individual retained observations' for n in required}
if not full:
matrix.update(binary_identity='PASS',loaded_libraries='PASS',client_provenance='PASS',C17='PASS',outputs='PASS',H1_focus='PASS',applied_camera='PASS relative -320, 480 to 160',H2_reference='PASS whole RGB; before any popup',tiled_clip='PASS global [-800,0,800,600]',toplevel_paint='PASS measured 182214 pixels; no popup',root_grab='NOT TESTED',nested_grab='NOT TESTED',E2='NOT TESTED',terminal_IPC='FAIL actual exit1; completed=false, no scientific exception',compositor_exit='PASS actual code0',cleanup='PASS no rescue',offline_gate='PASS recorded tests; INSUFFICIENT assertion audit, see diagnostic')
matrix.update(damage='PARTIAL',direct_child_clip_trace='NOT AVAILABLE; runtime NOT TESTED' if not full else 'NOT AVAILABLE; inherited source + pixels/input',hidden_owner='NOT TESTED',scale='NOT TESTED',rotation='NOT TESTED',output_migration='NOT TESTED',saved_buffer='NOT TESTED',effects='NOT TESTED',atomic_generation='NOT PROVEN',exhaustive_ABI='NOT TESTED',new_pristine='NOT RUN; historical controls only')
save(lab,'matrix',matrix)
save(lab,'summary',dict(verdict=verdict,architecture=architecture,runtime=runtime,terminal=terminal,budget=read('budget'),marker='SWAYFX_MOSAIC_STATIC_NESTED_VALID_GRAB_PROBE='+verdict,STEP20C='NEXT',production_multi_output='NOT YET SUPPORTED',new_Mosaic_builds=0,new_SceneFX_builds=0,pristine_runs=0))
sources=[p for root in ['fixture','preflight-correction','postrun-fixture','client-source','historical-source'] for p in (lab/root).rglob('*') if p.is_file()]+[lab/'protocol-before-run.md']
evidence=[p for root in ['raw','run','results'] for p in (lab/root).rglob('*') if p.is_file()]+[lab/n for n in ['swayfx-mosaic','nested-client','static-reference','pointer-daemon','campaign-owner']]
# Both lists fixed before writing either manifest, avoiding circular digests.
for name,paths in [('source',sources),('evidence',evidence)]:
print(name,inventory(lab/'results'/(name+'-sha256.txt'),paths))
print('SWAYFX_MOSAIC_STATIC_NESTED_VALID_GRAB_PROBE='+verdict)