#!/usr/bin/env python3
import json,hashlib,sys,datetime,os
from pathlib import Path
PROJECT='gacmai_20260718_091744';ROOT=Path('/data/video-pipeline/GacMaiAudio/project')/PROJECT;A=ROOT/'artifacts'
def sha(p):return hashlib.sha256(Path(p).read_bytes()).hexdigest()
def atomic(p,d):
 t=p.with_suffix(p.suffix+'.tmp');t.write_text(json.dumps(d,ensure_ascii=False,indent=2)+'\n');os.replace(t,p)
def main():
 if len(sys.argv)!=4:raise SystemExit('usage: promote_outline.py OUTLINE VALIDATION AUDIT')
 op,vp,ap=map(Path,sys.argv[1:]);o=json.loads(op.read_text());v=json.loads(vp.read_text());a=json.loads(ap.read_text());oh=sha(op);concept=A/'concept_selected.json';assert concept.exists();ch=sha(concept)
 assert o['project_id']==PROJECT and o['source_concept_sha256']==ch
 assert v.get('status')=='passed' and v.get('source_sha256')==oh and v.get('concept_sha256')==ch and v.get('parts')==12 and v.get('beats')==144 and v.get('errors')==[]
 assert a.get('verdict')=='pass' and a.get('outline_sha256')==oh and a.get('all_144_read') is True and a.get('blocking_findings')==[]
 dst=A/'outline_selected.json';assert not dst.exists();dst.write_bytes(op.read_bytes());assert sha(dst)==oh;now=datetime.datetime.now(datetime.timezone.utc).isoformat();rec={'status':'passed','project_id':PROJECT,'concept_sha256':ch,'outline_sha256':oh,'validation_sha256':sha(vp),'audit_sha256':sha(ap),'coverage':{'parts':12,'beats':144},'promoted_at':now};atomic(A/'outline_promotion_receipt.json',rec)
 for fn in ('project.json','status.json'):
  p=ROOT/fn;d=json.loads(p.read_text());d.update({'stage':'story_generation','canonical_outline_sha256':oh,'outline_locked':True,'story_locked':True,'tts_locked':True,'visual_spend_locked':True,'updated_at':now});atomic(p,d)
 print(json.dumps({'status':'promoted','concept_sha256':ch,'outline_sha256':oh,'audit_sha256':sha(ap)}))
if __name__=='__main__':main()
