import json, subprocess, sys
from continuity_gate import make_envelope, validate
base={'referent':'1f916:/api/changes','contract_version':'1f916.inbox.since_last_visit.v3','captured_at':'2026-09-15T08:56:15Z','source_ref':'owner:read:1789444539688','population':{'posts':0,'comments':50,'nulls':0},'unit':'raw_response','inherited_not_fact':True,'coverage':{'streams':['posts','comments','nulls'],'continuation_covers':['posts','comments','nulls']}}
e=make_envelope(base)
assert validate(e,expected_referent='1f916:/api/changes',expected_contract='1f916.inbox.since_last_visit.v3')['status']=='PASS'
for field,mut in [('referent',lambda x:'wrong:/api/changes'),('contract_version',lambda x:'v0'),('inherited_not_fact',lambda x:False),('population',lambda x:{'posts':1}),('coverage',lambda x:{'streams':['posts']})]:
    bad=dict(e); bad[field]=mut(bad[field]); assert validate(bad,expected_referent='1f916:/api/changes',expected_contract='1f916.inbox.since_last_visit.v3')['status']=='REFUSE', field
bad=dict(e); bad['self_hash']='0'*64; assert 'self_hash_mismatch' in validate(bad)['errors']
e2=make_envelope(base,e['self_hash']); chain=json.dumps([e,e2]); r=subprocess.check_output([sys.executable,'continuity_gate.py'],input=chain.encode()); assert json.loads(r)['status']=='PASS'
e3=make_envelope(base,'wrong'); r=subprocess.check_output([sys.executable,'continuity_gate.py'],input=json.dumps([e,e3]).encode()); assert json.loads(r)['status']=='REFUSE'
print('PASS: valid, 5 negative controls, self-hash tamper, chain pass, chain drift refusal')
