import ast
import hashlib
import json
import os
from pathlib import Path
import re
import subprocess
import time

from run import R,REPO,snapshot
os.umask(0o077)
OUT=R/'fire_compare-off_20260914_095725'
assert json.loads((OUT/'status.json').read_text())['status']=='COMPLETED'
assert json.loads((R/'retry.json').read_text())['exit']==0
assert snapshot()==json.loads((R/'before.private.json').read_text())
def sh(args):return subprocess.check_output(args,text=True,timeout=30)
assert not sh(['git','-C',str(REPO),'diff','--cached','--name-only']).strip()
assert sh(['git','-C',str(REPO),'rev-parse','HEAD']).strip()=='97a6be01302634415423c0e3d8aecd692a3c1344'
paths=sorted(set(sh(['git','-C',str(REPO),'diff','--name-only']).splitlines()+sh(['git','-C',str(REPO),'ls-files','--others','--exclude-standard']).splitlines()))
assert len(paths)==12
hashes={}
for name in paths:
    path=REPO/name
    hashes[name]=hashlib.sha256(path.read_bytes()).hexdigest()
    if name.endswith('.py'):ast.parse(path.read_text(),filename=name)
links=0
for path in [REPO/p for p in paths if p.endswith('.md')]+[OUT/'REVIEW.ko.md']:
    for link in re.findall(r'\]\(([^)]+)\)',path.read_text()):
        if link.startswith(('https://','http://','#')):continue
        assert (path.parent/link.split('#')[0]).exists(),(path.name,link)
        links+=1
sh(['git','-C',str(REPO),'diff','--check'])
for p in R.rglob('*'):
    if p.is_file():p.chmod(0o600)
(R/'source-snapshot.json').write_text(json.dumps(dict(head='97a6be01302634415423c0e3d8aecd692a3c1344',files=hashes),indent=2))
ledger=json.loads((R/'ledger.json').read_text())
ledger.update(first_attempt_status=ledger['status'],status='COMPLETED_USER_VISUAL_WAIT',
              correction_failures=1,attempts=2,completed_input_comparisons=1,clips=3,selected_frames=153,
              output=str(OUT),finished_utc=time.strftime('%Y-%m-%dT%H:%M:%SZ',time.gmtime()),service_unchanged=True)
(R/'ledger.json').write_text(json.dumps(ledger,indent=2))
runner='/root/.local/bin/codex-git-closeout'
cmd=[runner,'prepare','--repository',str(REPO),'--output',str(R/'git-manifest.json'),
     '--job-id','contextra-fire-video-20260914-100325','--profile','ltb1021','--session-alias','work-session',
     '--title','feat(fire-video): 반자동 오프라인 비교와 디버그 표시 도구 추가',
     '--message','Why=동일 Fire 모델과 Frame으로 품질을 비교하고 추가 영상에서도 반복 사용할 수 있는 검증 도구가 필요하다.',
     '--message','What=고정 artifact CLI, Reference/FP16 및 필터 제외 후보 비교, PTS 보존 clip, 대표 JSON과 처리량/한글 가이드를 추가했다.',
     '--message','Impact=운영 모델/설정/Stream은 미변경이다. 기존 numerical FAIL을 보존하며 품질 수용과 실제 SDK/서비스 검증은 대기다.',
     '--message','Verify=표적23 tests PASS; Reference CUDA 배치 교정 후153Frame/3clip 정합, 각5.033333초, 기존 서비스 불변 및 자원 회수 확인. Replay dry-run PASS, full replay 미실행.',
     '--message','Rollback=이번 Fire 오프라인 도구와 공통 probe/helper 확장 및 Owner 문서만 되돌린다. 원본 영상/모델/기존 결과는 보존한다.',
     '--verify',f'23 tests PASS; actual3video153Frame/PTS/RGB/clip checks PASS; no deployment; AST/diff and {links} local links PASS; user quality WAIT; FP16 raw numerical FAIL retained']
for path in paths:cmd+=['--path',path]
prepared=json.loads(sh(cmd))
batch=json.loads(sh([runner,'batch-prepare','--output',str(R/'git-batch.json'),'--batch-id','contextra-fire-video-20260914-100325',
     '--profile','ltb1021','--session-alias','work-session','--expected-group-count','1','--repository-label','contextra-analytics',
     '--manifest',str(R/'git-manifest.json'),'--expect-plan-hash',prepared['plan_hash']]))
print(json.dumps(dict(paths=len(paths),links=links,manifest=prepared,batch=batch),indent=2))
