from pathlib import Path
import argparse,json,hashlib,sys
ROOT=Path(__file__).resolve().parents[1]
def h(p): return hashlib.sha256(p.read_bytes()).hexdigest()
def main():
    ap=argparse.ArgumentParser(); ap.add_argument('--confirm-local',action='store_true'); args=ap.parse_args()
    sub=ROOT/'submission/decision.json'; status=ROOT/'evidence/validation-status.json'
    if not sub.exists():
        status.write_text(json.dumps({'status':'NOT_RUN_INCOMPLETE_SUBMISSION','runner_executed':False,'runtime_observations_claimed':False},indent=2)+'\n'); return 2
    d=json.loads(sub.read_text()); pol=json.loads((ROOT/'toolchain-policy.json').read_text())
    req=['selected_rpc_shape','deadline_policy_ms','read_write_discipline','application_queue_bound','admission_rule','residual_risk','transfer_decision']
    expected=pol['required_prediction_ids']; preds=d.get('predictions',{})
    complete=(d.get('status')=='LEARNER_COMPLETE' and all(d.get(k) not in (None,'','LEARNER_TODO') for k in req) and set(preds)==set(expected) and all(preds[k] not in (None,'','LEARNER_TODO') for k in expected))
    if not complete:
        status.write_text(json.dumps({'status':'NOT_RUN_INCOMPLETE_SUBMISSION','runner_executed':False,'runtime_observations_claimed':False},indent=2)+'\n'); return 2
    if not args.confirm_local:
        status.write_text(json.dumps({'status':'NOT_RUN_CONFIRMATION_REQUIRED','runner_executed':False,'runtime_observations_claimed':False},indent=2)+'\n'); return 2
    if pol.get('loopback_host')!='127.0.0.1' or pol.get('external_network_forbidden') is not True or pol.get('external_service_forbidden') is not True: raise SystemExit('FAIL_CLOSED_POLICY')
    from runtime_fixture import run_stream_case,deadlock_risk_simulation
    cfg=json.loads((ROOT/'fixture/service-contract.json').read_text()); cases=json.loads((ROOT/'fixture/probe-cases.json').read_text())['cases']
    expected_ids=pol['expected_case_ids']
    if [c['id'] for c in cases] != expected_ids: raise SystemExit('FAIL_CLOSED_CASE_SET')
    obs=[]
    for c in cases:
        r=deadlock_risk_simulation(cfg) if c['id']=='write_heavy_no_read_guard' else run_stream_case(cfg,c['deadline_ms'],c['receiver_delay_ms'])
        obs.append({'case_id':c['id'],'expected_class':c['expected_class'],'observation':r})
    inputs={'service_contract_sha256':'fixture/service-contract.json','probe_cases_sha256':'fixture/probe-cases.json','golden_policy_sha256':'fixture/golden-policy.json','requirements_sha256':'requirements.json','toolchain_policy_sha256':'toolchain-policy.json','runtime_fixture_sha256':'src/runtime_fixture.py','static_preflight_sha256':'src/static_preflight.py','learner_decision_sha256':'submission/decision.json'}
    prov={k:h(ROOT/v) for k,v in inputs.items()}
    out={'status':'RAN_BOUNDED_LOCAL_FIXTURE','runner_executed':True,'runtime_observations_claimed':True,'final_reliability_decision_claimed':False,'production_runtime_claimed':False,'observations':obs,'provenance':prov,'claim_boundary':'BOUNDED_LOCAL_FIXTURE_ONLY'}
    status.write_text(json.dumps(out,indent=2)+'\n'); print(json.dumps(out,indent=2)); return 0
if __name__=='__main__': sys.exit(main())
