from pathlib import Path
import json,sys,importlib.util
R=Path(__file__).resolve().parents[1]; checks=[]
def ck(n,v): checks.append((n,bool(v)))
base=json.loads((R/'fixture/baseline-state.json').read_text()); pol=json.loads((R/'fixture/golden-policy.json').read_text()); cases=json.loads((R/'fixture/probe-cases.json').read_text())['cases']
ck('five states',len(base['states'])==5); ck('initial draft',base['initial_state']=='DRAFT'); ck('terminal exact',base['terminal_states']==['APPROVED','REJECTED']); ck('on hold nonterminal','ON_HOLD' not in base['terminal_states']); ck('five transitions',len(base['transitions'])==5); ck('resume edge',any(e['from']=='ON_HOLD' and e['trigger']=='resume' and e['to']=='SUBMITTED' for e in base['transitions'])); ck('approval guard',any(e['from']=='SUBMITTED' and e['trigger']=='approve' and e['guard']=='approver_authorized' for e in base['transitions'])); ck('six probes',len(cases)==6); ck('record field count',len(base['record_fields'])==9); ck('recovery field','Recovery or Resume Rule' in base['record_fields']); ck('policy terminals',pol['terminal_states']==['APPROVED','REJECTED']); ck('policy hold',pol['resumable_holds']==['ON_HOLD']); ck('four forbidden',len(pol['forbidden_conclusions'])==4); ck('fixture source exists',(R/'src/state_machine_fixture.py').exists()); ck('local runner exists',(R/'src/run_local_lab.py').exists()); ck('submission template exists',(R/'submission/decision.template.json').exists()); ck('transfer template exists',(R/'transfer/changed-context.template.json').exists()); ck('evidence template exists',(R/'evidence/Bounded_State_Machine_Decision_Record_v1.template.json').exists())
for c in cases: ck('case has class '+c['id'],bool(c['expected_class']))
for n,v in checks: print(('PASS' if v else 'FAIL'),n)
print(f'{sum(v for _,v in checks)}/{len(checks)} PASS'); sys.exit(0 if all(v for _,v in checks) else 1)
