#!/usr/bin/env python3
from pathlib import Path
import datetime as dt,hashlib,json,os,stat,subprocess
ROOT=Path('/data/video-pipeline/HaTramAudio/project/021-Ngay-Toi-Bi-Gach-Ten-Khoi-Gia-Pha');RUN='run-20260721T131911Z-ac5d64d1';CANON='bb80e97d9adcb0427ea3828449858445323db228cca38f37cdf0446fffefdd6f';SCRIPT=Path.home()/'.hermes/skills/content-creation/tao-anh/scripts/generate_image.py';OUT=ROOT/'image/provider/left-panel-provider.png';RECEIPT=ROOT/'log/artwork-left-v2.json'
def now():return dt.datetime.now(dt.timezone.utc).isoformat().replace('+00:00','Z')
def sha(p):
 h=hashlib.sha256()
 with open(p,'rb') as f:
  while b:=f.read(8*1024*1024):h.update(b)
 return h.hexdigest()
def atomic(p,o):
 t=p.with_suffix(p.suffix+'.tmp');t.write_text(json.dumps(o,ensure_ascii=False,indent=2)+'\n');t.replace(p)
def env():
 e=os.environ.copy();p=Path.home()/'.hermes/.env'
 if not all(e.get(k) for k in ('TAO_ANH_API_KEY','TAO_ANH_API_URL')):
  assert p.exists() and stat.S_IMODE(p.stat().st_mode)==0o600
  for line in p.read_text().splitlines():
   if '=' in line and not line.lstrip().startswith('#'):
    k,v=line.split('=',1);e.setdefault(k.strip(),v.strip().strip('"').strip("'"))
 assert all(e.get(k) for k in ('TAO_ANH_API_KEY','TAO_ANH_API_URL'));return e
def main():
 r=json.loads((ROOT/'work/artwork/left-revision-v2.json').read_text());lock=json.loads((ROOT/'.ownership-lock.json').read_text());assert lock['run_id']==RUN and lock['owner']=='zoro' and lock['status']=='main_session_pipeline';assert sha(ROOT/'story/story-canon.txt')==CANON
 assert sha(ROOT/'image/provider/intro-poster-provider.png')==r['reuse_locked']['intro_sha256'];assert sha(ROOT/'image/provider/right-panel-provider.png')==r['reuse_locked']['right_sha256'];assert sha(Path(r['rejected_v1']['path']))==r['rejected_v1']['sha256']
 intent={'schema_version':1,'project_id':ROOT.name,'run_id':RUN,'revision':2,'status':'creating','verified':False,'prompt_sha256':r['prompt_sha256'],'source_canon_sha256':CANON,'output_path':str(OUT),'credential':'[REDACTED]','created_at':now()};atomic(RECEIPT,intent)
 cp=subprocess.run(['python3',str(SCRIPT),'--prompt',r['prompt'],'--output',str(OUT),'--timeout','600'],env=env(),capture_output=True,text=True)
 if cp.returncode!=0:intent.update({'status':'failed','failure':'provider command failed; stderr redacted','failed_at':now()});atomic(RECEIPT,intent);raise RuntimeError('provider failed')
 assert OUT.exists() and OUT.read_bytes()[:8]==b'\x89PNG\r\n\x1a\n';intent.update({'status':'completed','technical_verified':True,'verified':False,'awaiting_visual_qa':True,'artifact_sha256':sha(OUT),'size_bytes':OUT.stat().st_size,'completed_at':now()});atomic(RECEIPT,intent);print(json.dumps({'status':'left_v2_generated','path':str(OUT),'sha256':sha(OUT),'bytes':OUT.stat().st_size},ensure_ascii=False))
if __name__=='__main__':main()
