#!/usr/bin/env python3
from pathlib import Path
import json,hashlib,datetime,sys
P='gacmai_20260717_184527';R=Path('/data/video-pipeline/GacMaiAudio/project')/P;A=R/'artifacts';story=A/'story_package_candidate_rev3.json';outline=A/'locked_outline_canonical.json';concept=A/'concept_contract.json';receipt=A/'story_assembly_receipt_rev3.json';out=A/'story_release_audit_bundle_rev3.json'
if out.exists():raise SystemExit('audit bundle already exists')
for p in (story,outline,concept,receipt):
 if not p.exists():raise SystemExit(f'missing {p.name}')
def sha(p):return hashlib.sha256(p.read_bytes()).hexdigest()
r=json.loads(receipt.read_text());h=sha(story)
if r.get('status')!='passed' or r.get('story_sha256')!=h:raise SystemExit('assembly receipt mismatch')
bundle={'project_id':P,'bundle_type':'self_contained_full_story_release_audit','story_sha256':h,'outline_sha256':sha(outline),'concept_sha256':sha(concept),'assembly_receipt_sha256':sha(receipt),'parent_story_sha256':'28938e3ddd2dc339ab8e6be8618a05589a4e47a77c7ccadde733355ec38af151','story':json.loads(story.read_text()),'outline':json.loads(outline.read_text()),'concept':json.loads(concept.read_text()),'assembly_receipt':r,'audit_requirements':json.loads((A/'full_story_release_audit_brief.json').read_text()),'created_at':datetime.datetime.now(datetime.timezone.utc).isoformat()};out.write_text(json.dumps(bundle,ensure_ascii=False,indent=2)+'\n');print(json.dumps({'status':'passed','path':str(out),'bundle_sha256':sha(out),'story_sha256':h,'parts':len(bundle['story']['parts']),'paragraphs':sum(len(x['paragraphs']) for x in bundle['story']['parts'])}))
