#!/usr/bin/env python3
"""Mandatory combined refinements contracts, native flow, actual inputs/audio.

Every child executes freshly on the exact explicit ROM. Previous reports never
substitute for a run. Screenshots still require separate opened visual review.
"""
from pathlib import Path
from datetime import datetime,timezone
import argparse,hashlib,json,subprocess,sys,time
ap=argparse.ArgumentParser();ap.add_argument('rom',type=Path);ap.add_argument('output',type=Path)
ap.add_argument('--baseline',type=Path,required=True);a=ap.parse_args()
h=Path(__file__).resolve().parent;o=a.output.resolve();o.mkdir(parents=True,exist_ok=True)
rom=a.rom.resolve();baseline=a.baseline.resolve();sha=lambda p:hashlib.sha256(p.read_bytes()).hexdigest();digest=sha(rom)
assert sha(baseline)=='57bfd4e0826286e144643fe0ea12d35953d3b085c067039ad9a6eb23f781f7eb','wrong pre-refinements reference'
assert rom.read_bytes()[0x258000:0x258002]==bytes.fromhex('6000'),'refinements module absent'
report=dict(ROM_sha256=digest,status='running',started=datetime.now(timezone.utc).isoformat(),checks=[])
def save():(o/'results.json').write_text(json.dumps(report,indent=2)+'\n')
def run(name,flags=(),label=None):
    label=label or name;script=h/'testcases'/(name+'.py');out=o/label;started=time.monotonic()
    assert sha(rom)==digest,'candidate changed during refinements checks'
    cmd=[sys.executable,str(script),str(rom),str(out),*map(str,flags)]
    with(o/(label+'.log')).open('w')as log:r=subprocess.run(cmd,stdout=log,stderr=log,timeout=6000)
    report['checks'].append(dict(name=label,returncode=r.returncode,seconds=round(time.monotonic()-started,2),
        ROM_sha256=digest,source_sha256=sha(script),command=cmd));save()
    print(label,'PASS'if r.returncode==0 else'FAIL',flush=True)
    if r.returncode:report['status']='failed';save();raise SystemExit('Refinements release blocked: '+label)
save()
for name in ['scope','native','font','glass','overall','line_pool','menu_contract','footer_contract','PP_frame_contract','momentum_frame']:
    run('refinement_'+name,['--baseline',baseline]if name in ['scope','font']else[])
run('transfer_flow',['--abi'],label='current-native-producer')
producer=o/'current-native-producer/actual-four-pad-game';state=producer/'ready-pregame.state'
run('refinement_momentum_natural',['--producer',producer])
run('refinement_momentum_off',['--state',state])
run('refinement_line_input',['--state',state])
run('refinement_menu_inputs',['--state',state])
live=producer/'period-0-live.state';assert live.is_file(),'missing authentic current-ROM in-play audio state'
# Select the first authentic live first-period human-team skater possession. The
# keeper-owned scene can naturally score before the fixed PP sample;
# it remains the independent real-Y/goal branch, never a filtered success.
pp_candidates=[r for r in json.loads((producer/'captures.json').read_text())if r.get('ROM_sha256')==digest and r.get('state_sha256')and r.get('paired_sram_sha256')and r['context']['period']==0 and 0<r['context']['clock']<300 and r['context']['owner']in range(5)and not(r['context']['flags'][0]&0x1500 or r['context']['flags'][1]&0x8100)]
assert pp_candidates,'missing authenticated human-possession PP fixture; do not relax eight-context admission'
pp_capture=min(pp_candidates,key=lambda r:r['frame']);pp_live=(producer/pp_capture['image']).with_suffix('.state');assert sha(pp_live)==pp_capture['state_sha256']and sha(pp_live.with_suffix('.srm'))==pp_capture['paired_sram_sha256']
(o/'PP-fixture-provenance.json').write_text(json.dumps(dict(ROM_sha256=digest,idle=pp_capture,goal=str(live),selection='Earliest actual live first-period human-team skater possession; fixed settings, no result/audio search or actor/puck/score/RNG writes. Original current-native keeper-owned source retained for separate real-goal branch.'),indent=2)+'\n')
run('refinement_powerplay',['--state',pp_live,'--goal-state',live])
# Alarm timing must not be forced during the opening arena music. Select the
# first authenticated mature live first-period capture near the target clock;
# selection is independent of warning/audio outcomes. All original strict
# four-period/five-pulse/two-voice/18-tick/WAV/negative60 criteria remain intact.
run('refinement_warning_fixture')
warning_producer=o/'refinement_warning_fixture'
warning_captures=json.loads((warning_producer/'captures.json').read_text())
pregame=next(r for r in warning_captures if r['id']=='ready-pregame')
# C3F4 is the native penalty report, not a live/intro flag (HACKING.md).
# Require actual elapsed native frames plus the original mature first-period
# clock and dead/pause/special guards; never select by alarm/audio outcome.
warning_rows=[r for r in warning_captures
 if r.get('ROM_sha256')==digest and r.get('state_sha256')and r.get('paired_sram_sha256')
 and r['context']['period']==0 and 61<=r['context']['clock']<=120 and r['frame']>=pregame['frame']+1800
 and not(r['context']['flags'][0]&0x1500 or r['context']['flags'][1]&0x8100 or r['context']['flags'][2]&0x0500)]
assert warning_rows,'no authentic mature live warning fixture; never fall back to an intro/late-score scene'
warning_capture=min(warning_rows,key=lambda r:r['frame']);warning_live=(warning_producer/warning_capture['image']).with_suffix('.state');warning_sram=warning_live.with_suffix('.srm')
assert sha(warning_live)==warning_capture['state_sha256']and sha(warning_sram)==warning_capture['paired_sram_sha256']
(o/'warning-fixture-provenance.json').write_text(json.dumps(dict(ROM_sha256=digest,capture=warning_capture,selection='Earliest authenticated mature live first-period clock61..120, at least1800 actual emulated frames after authenticated pregame; no stopped/pause/special flags. C3F4 penalty report is recorded but not mistaken for play state. No warning-outcome search or audio/actor/puck/score/RNG writes'),indent=2)+'\n')
run('refinement_warning',['--state',warning_live,'--sram',warning_sram,'--manifest',warning_producer/'captures.json'])
assert sha(rom)==digest
report.update(status='passed',finished=datetime.now(timezone.utc).isoformat());save()
print('PASS all fresh mandatory refinements contracts/flow/actual inputs/audio; opened visual review still required',flush=True)
