#!/usr/bin/env python3
from pathlib import Path
import hashlib,json,subprocess,datetime
ROOT=Path('/home/hermes');P='gacmai_20260716_233054'
outline=ROOT/f'{P}_locked_outline_canonical.json'
batch_sources=[ROOT/f'{P}_batch_1_4.json',ROOT/f'{P}_batch_5_8.json',ROOT/f'{P}_batch_9_12.json']

def sha(p):return hashlib.sha256(p.read_bytes()).hexdigest()
def run(cmd,out):
 cp=subprocess.run(cmd,text=True,capture_output=True)
 if cp.returncode:raise SystemExit(f"failed {' '.join(cmd)}\n{cp.stdout}\n{cp.stderr}")
 d=json.loads(cp.stdout);Path(out).write_text(json.dumps(d,ensure_ascii=False,indent=2)+'\n');return d
if sha(outline)!='5779dcb66c18b6d254ff7a657b099a81d93d030708a9a13bb2d3eafe3a815e30':raise SystemExit('canonical outline SHA mismatch')
snaps=[];batch_receipts=[]
for src in batch_sources:
 if not src.exists():raise SystemExit(f'missing completion-final source {src}')
 raw=src.read_bytes();data=json.loads(raw);h=hashlib.sha256(raw).hexdigest();label=f"{data['part_range'][0]}_{data['part_range'][1]}";snap=ROOT/f'{P}_batch_{label}_completion_final_{h[:12]}.json';snap.write_bytes(raw)
 if sha(snap)!=h:raise SystemExit('snapshot mismatch')
 rec=run(['python3',str(ROOT/f'validate_{P}_batch.py'),str(snap)],ROOT/f'{P}_batch_{label}_validation.json')
 if sha(snap)!=h:raise SystemExit('snapshot mutated during validation')
 snaps.append(snap);batch_receipts.append(rec)
story=ROOT/f'{P}_story_package_release.json'
assembly=run(['python3',str(ROOT/f'assemble_{P}_story.py'),str(outline),*(str(x) for x in snaps),str(story)],ROOT/f'{P}_assembly_receipt.json')
story_sha=sha(story)
val=run(['python3',str(ROOT/f'validate_{P}_story.py'),str(story),str(outline)],ROOT/f'{P}_story_validation.json')
dup=run(['python3',str(ROOT/f'audit_{P}_duplicates.py'),str(story)],ROOT/f'{P}_duplication_audit.json')
eva=run(['python3',str(ROOT/f'audit_{P}_evidence_authority.py'),str(story),str(outline)],ROOT/f'{P}_evidence_authority_audit.json')
for d in (val,dup,eva):
 if d.get('status')!='passed' or d.get('story_sha256')!=story_sha:raise SystemExit('gate receipt mismatch')
receipt={'status':'passed','project_id':P,'completed_at':datetime.datetime.now(datetime.timezone.utc).isoformat(),'outline_sha256':sha(outline),'story_path':str(story),'story_sha256':story_sha,'snapshots':[{'path':str(x),'sha256':sha(x)} for x in snaps],'batch_validations':batch_receipts,'assembly':assembly,'gates':{'story_validation':str(ROOT/f'{P}_story_validation.json'),'duplication':str(ROOT/f'{P}_duplication_audit.json'),'evidence_authority':str(ROOT/f'{P}_evidence_authority_audit.json')}}
(ROOT/f'{P}_deterministic_release_candidate_receipt.json').write_text(json.dumps(receipt,ensure_ascii=False,indent=2)+'\n');print(json.dumps(receipt,ensure_ascii=False))
