from pathlib import Path
import json,sys,re
ROOT=Path(__file__).resolve().parents[1]; checks=[]
def ck(n,v): checks.append((n,bool(v)))
base=json.loads((ROOT/'fixture/baseline-state.json').read_text()); cases=json.loads((ROOT/'fixture/probe-cases.json').read_text())['cases']; pol=json.loads((ROOT/'fixture/golden-policy.json').read_text()); req=json.loads((ROOT/'requirements.json').read_text()); tool=json.loads((ROOT/'toolchain-policy.json').read_text()); dec=json.loads((ROOT/'submission/decision.template.json').read_text()); status=json.loads((ROOT/'evidence/validation-status.json').read_text()); run=(ROOT/'src/run_local_lab.py').read_text(); fix=(ROOT/'src/event_fixture.py').read_text()
ids=['baseline_first_delivery','duplicate_redelivery_new_transport_id','non_atomic_crash_window','stale_lower_version','evidence_field_removed']
ck('initial stock 100',base['consumer']['initial_stock']==100); ck('initial version 0',base['consumer']['initial_version']==0); ck('stable event key',base['first_event']['event_key']==base['duplicate_delivery']['event_key']); ck('delivery id changes',base['first_event']['delivery_id']!=base['duplicate_delivery']['delivery_id']); ck('first version 10',base['first_event']['version']==10); ck('stale version 9',base['stale_event']['version']==9); ck('stale key distinct',base['stale_event']['event_key']!=base['first_event']['event_key'])
ck('duplicate entity parity',base['first_event']['business_entity']==base['duplicate_delivery']['business_entity']); ck('duplicate version parity',base['first_event']['version']==base['duplicate_delivery']['version']); ck('duplicate delta parity',base['first_event']['stock_delta']==base['duplicate_delivery']['stock_delta']); ck('five exact cases',[c['id'] for c in cases]==ids); ck('expected classes exact',pol.get('required_case_semantics')=={c['id']:c['expected_class'] for c in cases})
ck('five dimensions',req['critical_dimensions']==['event_boundary','stable_receipt_key','idempotent_effect','atomic_receipt','ordering_limit']); ck('seven evidence items',len(req['required_evidence'])==7); ck('local-only runtime','External network, broker, cloud service, production data, and production behavior are out of scope.' in req.get('runtime_rule','')); ck('collision rule present','idempotency-key collision' in req.get('stable_key_payload_rule',''))
ck('external network forbidden',tool['external_network_forbidden'] is True); ck('external service forbidden',tool['external_service_forbidden'] is True); ck('broker runtime false',tool['broker_runtime_claimed'] is False); ck('production runtime false',tool['production_runtime_claimed'] is False); ck('runner v2',tool.get('runner_contract_version')=='DAT017-RUNNER-CONTRACT-v2'); ck('expected ids exact',tool.get('expected_case_ids')==ids); ck('prediction ids exact',tool.get('required_prediction_ids')==ids); ck('eight provenance keys',len(tool.get('runtime_input_hashes_required',[]))==8); ck('bounded evidence scope',tool.get('evidence_scope')=='BOUNDED_LOCAL_FIXTURE_ONLY')
ck('five blank predictions',list(dec.get('predictions',{}).keys())==ids and all(v is None for v in dec['predictions'].values())); ck('authoring runtime unclaimed',status.get('runtime_observations_claimed') is False); ck('authoring final decision unclaimed',status.get('final_reliability_decision_claimed') is False); ck('authoring broker false',status.get('broker_runtime_claimed') is False); ck('authoring production false',status.get('production_runtime_claimed') is False)
ck('confirmation executable gate',"if not args.confirm_local:" in run and 'if False' not in run); ck('runner exact expected execution',"obs=[run_probe(cid) for cid in expected]" in run); ck('runner exact prediction keys',"list(d.get('predictions',{}).keys()) != expected" in run); ck('runner provenance has policy',"'golden_policy_sha256':'fixture/golden-policy.json'" in run); ck('runner provenance has decision',"'learner_decision_sha256':'submission/decision.json'" in run); ck('collision guard executable',"IDEMPOTENCY_KEY_COLLISION_REJECTED" in fix and 'prior_fp' in fix); ck('crash first stock computed',"first_broken_stock=BASE['consumer']['initial_stock']+int(first['stock_delta'])" in fix and "'stock_after_first_broken_attempt':first_broken_stock" in fix); ck('no network imports',not any(x in fix for x in ['requests','urllib','socket.connect','http://','https://'])); ck('six forbidden claims',len(pol['forbidden_conclusions'])==6); ck('broker suppression forbidden',any('broker duplicate suppression' in x.lower() for x in pol['forbidden_conclusions'])); ck('payload alias forbidden',any('divergent business payload' in x.lower() for x in pol['forbidden_conclusions']))
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)
