#!/usr/bin/env python3
from pathlib import Path
import hashlib,json,os
ROOT=Path('/data/video-pipeline/HaTramAudio/project/028-Nguoi-Duoc-Goi-Ten-Cuoi-Cung');PROJECT_ID=ROOT.name;RUN_ID='run-20260722T063856Z-87753fd5';OWNER='Levy';WORK=ROOT/'work/artwork'/RUN_ID
def sha(p):
 h=hashlib.sha256()
 with p.open('rb') as f:
  for b in iter(lambda:f.read(8*1024*1024),b''):h.update(b)
 return h.hexdigest()
def guard():
 d=json.loads((ROOT/'.ownership-lock.json').read_text());assert d['project_id']==PROJECT_ID and d['run_id']==RUN_ID and d['owner']==OWNER
def main():
 guard();manifest=json.loads((ROOT/'script/project-manifest.json').read_text());canon=manifest.get('canon_sha256')
 story=manifest.get('gate_events',{}).get('story',{})
 if manifest.get('steps',{}).get('story')!='completed' or story.get('verified') is not True or story.get('canon_sha256')!=canon:raise RuntimeError('Story Gate is not committed/current')
 authority={k:ROOT/k for k in ['story/story-canon.txt','script/story-brief.json','script/ledger.json','script/outline.json','script/promotion-report.json']}
 if not all(p.is_file() for p in authority.values()):raise RuntimeError('committed Story Gate authority files are missing')
 promo=json.loads(authority['script/promotion-report.json'].read_text());assert promo['verified'] and promo['canon_sha256']==canon and sha(authority['story/story-canon.txt'])==canon
 brief=json.loads(authority['script/story-brief.json'].read_text());TITLE=brief['canonical_title']
 shared=f'''Thông tin nhân vật nội bộ, tuyệt đối không render thành chữ: Tống Vãn Nghi là nữ sinh viên truyền thông 23 tuổi, người châu Á hư cấu, tóc đen ngang vai buộc nửa, áo sơ mi trắng dưới áo cử nhân xanh đậm, cầm thẻ tên trắng, ánh mắt kiên định nhưng ấm. Lục Minh Triết là nam sinh viên kiến trúc 24 tuổi, người châu Á hư cấu, tóc đen gọn, sơ mi trắng xắn tay, đồng hồ mặt vuông, vẻ chính xác và điềm tĩnh. Tên chính thức: "{TITLE}". Thể loại: ngôn tình học đường thanh xuân, chữa lành. Bối cảnh công khai: hậu trường hội trường đại học trước lễ tốt nghiệp, rèm nhung xanh sẫm, hàng ghế đỏ, ánh sân khấu vàng, thẻ tên trắng và micro không dây. Motif công khai: thẻ tên trắng, đồng hồ đếm ngược đỏ trừu tượng không số đọc được, micro, ghế hàng cuối. Giới hạn tiết lộ: không thể hiện cảnh Vãn Nghi từ chối danh sách, Minh Triết tắt đồng hồ, sinh viên tự gọi tên hoặc coda sơn bảng.
Phong cách key art phim điện ảnh cao cấp, digital illustration bán hiện thực, tối giản, một focal point rõ, low-key lighting, tương phản xanh đậm-vàng ấm, depth foreground-midground-background, không collage, card, slide, mockup hoặc mô phỏng người thật.
Mọi thẻ, màn hình, biểu mẫu, bảng và nhãn trong cảnh phải trơn hoặc chỉ có đường nét không tạo ký tự đọc được. Không logo, watermark, số, pseudo-text hoặc chữ môi trường ngoài các khối bắt buộc. Provider tạo hoàn chỉnh hình và typography trong cùng raster; cấm background no-text, text layer riêng hoặc chừa chỗ hậu kỳ.
'''
 poster=shared+f'''Tạo poster ngang tỷ lệ 16:9, master 1920x1080 cho intro và thumbnail. Tống Vãn Nghi là focal point ở cánh gà, cầm thẻ tên trắng; Lục Minh Triết đứng lớp sau cạnh bảng điều khiển và micro. Sau rèm là sân khấu tốt nghiệp sáng vàng cùng các hàng ghế đỏ mờ, tạo cảm giác đối đầu về quy trình nhưng cùng hướng về quyền được công nhận. Không lộ kết thúc. Provider tự quyết font, vị trí, kích thước, xuống dòng, khoảng cách và phân cấp.
RENDER CHÍNH XÁC BA KHỐI CHỮ TIẾNG VIỆT SAU TRỰC TIẾP TRONG CÙNG ẢNH, KHÔNG THÊM CHỮ KHÁC:
"Hạ Trâm Audio"
"{TITLE}"
"Truyện được phát độc quyền tại Hạ Trâm Audio, nghiêm cấm sao chép dưới mọi hình thức"
Giữ nguyên từng chữ, dấu tiếng Việt và dấu phẩy; chữ dễ đọc, không cắt hoặc che.
'''
 right=shared+f'''Tạo key art dọc tỷ lệ chính xác 656:1080, master 1080x1778 dùng nguyên raster làm panel phải. Tống Vãn Nghi là focal point tiền cảnh cầm thẻ tên trắng, áo cử nhân xanh đậm; Lục Minh Triết đứng lớp sau bên micro và rèm sân khấu. Đồng hồ đỏ chỉ là ánh sáng/hình khối trừu tượng, không số đọc được. Bố cục dọc tối giản, không crop chủ thể quan trọng. Provider tự quyết toàn bộ typography.
RENDER CHÍNH XÁC BA KHỐI CHỮ TIẾNG VIỆT SAU TRỰC TIẾP TRONG CÙNG ẢNH, KHÔNG THÊM CHỮ KHÁC:
"Hạ Trâm Audio"
"{TITLE}"
"Truyện được phát độc quyền tại Hạ Trâm Audio, nghiêm cấm sao chép dưới mọi hình thức"
Giữ nguyên từng chữ, dấu tiếng Việt và dấu phẩy; chữ dễ đọc, không cắt hoặc che.
'''
 left=shared+'''Tạo branding panel điện ảnh dọc với KÍCH THƯỚC PIXEL BẮT BUỘC CHÍNH XÁC 1080x1778, tỷ lệ 656:1080. Cùng color grade xanh đậm-vàng ấm: rèm sân khấu trừu tượng, hàng ghế đỏ mờ, các thẻ trắng không chữ và ánh đèn hội trường; không nhân vật, không tên truyện, không dòng độc quyền. Cạnh phải có transition texture nhẹ; không aperture, khung màn hình hoặc layout giả. Provider tự quyết typography.
RENDER CHÍNH XÁC HAI KHỐI CHỮ TIẾNG VIỆT SAU TRỰC TIẾP TRONG CÙNG ẢNH, KHÔNG THÊM CHỮ KHÁC:
"Hạ Trâm Audio"
"Like • Chia sẻ • Đăng ký"
Giữ nguyên chính tả và dấu tiếng Việt; chữ dễ đọc, không cắt hoặc che.
'''
 WORK.mkdir(parents=True,exist_ok=True);items={}
 for key,prompt in {'intro_poster':poster,'right_panel':right,'left_panel':left}.items():
  p=WORK/f'{key}.prompt.txt';p.write_text(prompt);items[key]={'prompt_path':str(p),'prompt_sha256':sha(p)}
 manifest={'schema_version':1,'project_id':PROJECT_ID,'run_id':RUN_ID,'status':'locked','verified':True,'source_canon_sha256':canon,'authority_sha256':{k:sha(p) for k,p in authority.items()},'canonical_title':TITLE,'provider_skill':'tao-anh','provider_model':'cx/gpt-5.5-image','provider_only_typography':True,'text_postprocessing_allowed':False,'items':items}
 p=ROOT/'script/image-prompts.json';tmp=p.with_name('.image-prompts.json.tmp');tmp.write_text(json.dumps(manifest,ensure_ascii=False,indent=2)+'\n');os.replace(tmp,p);print(json.dumps({'status':'locked','verified':True,'source_canon_sha256':canon,'items':items},ensure_ascii=False))
if __name__=='__main__':main()
