from pathlib import Path
import json,math,hashlib
load=lambda p:json.loads(Path(p).read_text())
checkpoint=load('client/server-plugin/phase6-verification.json');p=load('client/build/phase6-final-plugin-evidence.json');p['serverLog']=Path('client/build/logs/phase6-paper-final.log').read_text()
checkpoint['refined_verification']='COMPLETE: final client, both fighters ON; two ready-started rounds, real projectile frag and timer draw, guest spectator return.'
checkpoint['final']={k:p[k] for k in ['status','startedAt','endedAt','commands']}
checkpoint['final']['events']=[{'label':x['label'],'at':x.get('at'),**({'before':x['before'],'after':x['after']['matchHealth']} if 'before' in x else {}),'a':x.get('a',{}).get('matchHealth'),'b':x.get('b',{}).get('matchHealth')} for x in p['events']]
checkpoint['final']['server_evidence']=[l for l in p['serverLog'].splitlines() if any(t in l for t in ['Countdown','LIVE —','Winner:','Draw:','state=LOBBY','state=ROUND_END','RESPAWN','Ready '])]
checkpoint['final']['log_correction']=p.get('logCorrection')
checkpoint['spectator']={k:v for k,v in load('client/build/phase6-spectator.json').items() if k!='logs'}
Path('client/server-plugin/phase6-verification.json').write_text(json.dumps(checkpoint,indent=2)+'\n')
tracks=load('client/build/phase6-music-tracks.json');music=[]
for label,path in [('in-game / disconnect / rejoin','client/build/phase6-music-final.json'),('fresh menu and natural switch','client/build/phase6-music-menu-final-state.json')]:
 e=load(path);sources=[s for s in e['audio']['starts'] if s['duration']>10]
 for s in sources:
  s['tracks_matching_encoded_bytes']=[t for t in tracks if t['bytes']==s['decode']['bytes']]
 music.append({'label':label,'at':e['at'],'source_start_count':len(e['audio']['starts']),'pcm_buffer_count':len(e['audio']['buffers']),'decodes':e['audio']['decodes'],'music_sources':sources,'decode_errors':e['audio']['errors'],'contexts':e.get('contexts'),'browser_errors':e.get('errors'),'resource_reload_logs':[l for l in e['logs'] if 'Reloading ResourceManager:' in l],'audio_error_logs':[l for l in e['logs'] if 'JOrbis' in l or 'decodeAudioData failed' in l]})
sp=load('client/build/phase6-sp-course-gameplay-evidence.json');h=[s for k,v in sp.items() for s in (v if isinstance(v,list) and k.endswith('History') else [])]
summary={'artifacts':load('client/build/phase6-artifacts.json'),'render':load('client/build/phase6-render-summary.json'),'server_agreement':load('client/build/phase6-position-agreement.json'),'menu':{str(port):load(f'client/build/phase6-menu-{port}.json') for port in [9224,9225]},'menu_initial_fresh_a':load('client/build/phase6-menu-initial-9224.json')['fresh'],'music':music,'singleplayer':{'status':sp['status'],'apexes':[j['apexBlocks'] for j in sp['jumps']],'wall':sp['wall']['position'],'stairs':sp['stairs']['position'],'drop':sp['drop']['position'],'punch_action':sp['punch']['state']['action'],'health':sp['drop']['state']['health'],'match_authority':sp['drop']['matchHealth'],'all_sampled_origin_y_32':all(s['origin'][1]==32 for s in h),'history_samples':len(h),'rebase_generation_pairs':[[sp[k]['before']['generation'],sp[k]['after']['generation']] for k in ['rebase-run','rebase-jump']],'final':load('client/build/phase6-sp-final.json')},'off':load('client/build/phase6-off.json'),'observed_failures':['Parent-directory AGENTS search crossed project boundary; stopped with exit143. No content reads by find; cannot certify no home metadata access.','Plugin online-player wildcard collection compile error; corrected to var.','Unavailable EditBox.setFilter compile error; changed JOIN validation.','Reused profile join coordinates needed correction.','Audio pre-document probe initially absent; direct evaluation fixed instrumentation.','Original full music ZIP exceeded 250 MiB cap. Raised importer cap to512 MiB only.','Menu reload click happened under startup overlay; increased navigation/UI wait; retry passed.','One reload CDP evaluation got target navigated/closed; join-only retry passed.','Initial render timestamps retained burst jitter; JS fixed-index timeline; same linked client.','OFF first movement fixture stayed in arena; corrected to overworld, real server movement confirmed.','Music harness awaited a performance-only log despite real successful import; activation reload proved success.','Final match harness first attached checkpoint server log; corrected to actual final log, original saved.','SP harness initially reused Phase3c ignored raw JSON filename, overwriting that ignored capture; renamed Phase6 and fixed harness. Original SP profile and committed Phase3c summary unchanged.','Repeated frame hook stacked wrappers; reducer groups actual render timestamps; harness now retains one original mesh getter.']}
Path('client/mario/phase6-verification-summary.json').write_text(json.dumps(summary,indent=2)+'\n')
print('Summary saved',len(json.dumps(summary)),'chars; music tracks',[t['name'] for g in music for s in g['music_sources'] for t in s['tracks_matching_encoded_bytes']]);print('SP PASS; invariant hashes checked; agreement',[x['error_blocks'] for x in summary['server_agreement']])
