#!/usr/bin/env python3
from pathlib import Path
import json,hashlib,datetime
ROOT=Path('/data/video-pipeline/HaTramAudio/project/018-Hon-Uoc-Khong-Duoc-Phep-Yeu');PROJECT=ROOT.name;RUN='run-20260721T040505Z-cd9f944a';CANON='d12e1733f81bf173b5db789b0028a0be478d0d2e565c05a91e236c95cd33bd78';TTS='1f78d70445770dea08b5690880a53bdff83cdeb7ca0e735f93510ad6edd0de79';UPLOAD='bbadb5780a1565038d7df378cb0bfffa75a2cac07020ab1764c5d89f3cba47ae';META='2b12350b71dab64af7b92820f1db14c331e240d4eed15c512c68b83aef59c662'
def load(rel):return json.loads((ROOT/rel).read_text())
def sha(rel):
 h=hashlib.sha256()
 with (ROOT/rel).open('rb') as f:
  for b in iter(lambda:f.read(8*1024*1024),b''):h.update(b)
 return h.hexdigest()
def main():
 lock=load('.ownership-lock.json');assert (lock['project_id'],lock['run_id'],lock['owner'],lock['status'])==(PROJECT,RUN,'zoro','main_session_pipeline')
 assert sha('story/story-canon.txt')==sha('story/spoken-narration.txt')==CANON
 story=load('script/story-manifest.json');assert story['status']=='completed' and story['verified'] and story['canon_sha256']==CANON and story['spoken_narration_sha256']==CANON
 qa=load('log/story-qa.json');assert qa['verified'] and qa['gates']['family_main_payoff']=='passed' and qa['gates']['family_secondary_payoff']=='passed' and qa['gates']['third_family_drift']=='absent' and qa['family_gate']['main']=='3.2 Hào môn / tổng tài / liên hôn' and qa['family_gate']['secondary']=='3.3 Cưới trước yêu sau / hôn ước từ bé' and all(qa['family_gate']['checks'].values())
 tts=load('script/tts-manifest.json');ta=load('log/tts-independent-audit.json');assert tts['status']=='completed' and tts['verified'] and tts['output_sha256']==TTS and ta['verified'] and sha('audio/story-full.wav')==TTS
 art=load('image/layout-manifest.json');assert art['status']=='completed' and art['verified'] and art['source_canon_sha256']==CANON and art['source_tts_sha256']==TTS
 intro=load('log/intro-render.json');assert intro['status']=='completed' and intro['verified'] and sha('output/intro/intro.mp4')==intro['output_sha256']
 footage=load('log/footage-render.json');assert footage['status']=='completed' and footage['verified'] and footage['source_canon_sha256']==CANON and footage['source_audio_sha256']==TTS and footage['mirror_applied'] is True and footage['source_audio_discarded'] is True and sha('output/footage/footage.mp4')==footage['output_sha256']
 final=load('log/final-render.json');assert final['status']=='completed' and final['verified'] and final['technical_verified'] and final['visual_qa']['verified'] and sha('output/final.mp4')==final['output_sha256']
 trans=load('log/transcode-upload.json');assert trans['status']=='completed' and trans['verified'] and trans['technical_verified'] and trans['visual_qa']['verified'] and trans['source_final_sha256']==final['output_sha256'] and trans['under_one_gb'] is True
 up=ROOT/'output/final-upload.mp4';assert sha('output/final-upload.mp4')==trans['output_sha256']==UPLOAD and up.stat().st_size==trans['output_bytes']<1_000_000_000
 md=load('log/metadata.json');assert md['status']=='completed' and md['verified'] and md['source_canon_sha256']==CANON and sha('output/info.txt')==md['metadata_sha256']==META
 blockers=['log/postiz-partial-failure.json','log/schedule-verification-failure.json'];assert all(not (ROOT/x).exists() for x in blockers)
 checks={'ownership':True,'story_family_compliance':True,'canon':True,'tts':True,'artwork':True,'intro':True,'footage_hflip':True,'final_visual_qa':True,'upload_copy_visual_qa':True,'under_one_gb':True,'metadata':True,'no_partial_publish_marker':True}
 receipt={'schema_version':1,'project_id':PROJECT,'run_id':RUN,'status':'ready','verified':True,'source_canon_sha256':CANON,'upload_copy_path':str(up),'upload_copy_sha256':UPLOAD,'upload_copy_bytes':up.stat().st_size,'metadata_path':str(ROOT/'output/info.txt'),'metadata_sha256':META,'checks':checks,'credential':'[REDACTED]','created_at':datetime.datetime.now(datetime.timezone.utc).isoformat().replace('+00:00','Z')};(ROOT/'log/publish-ready.json').write_text(json.dumps(receipt,ensure_ascii=False,indent=2)+'\n');print(json.dumps({'status':'ready','verified':True,'upload_copy_bytes':up.stat().st_size}))
if __name__=='__main__':main()
