import datetime
import json
import os
from pathlib import Path
import re
from prepare import HERE,REPO,cmd,save

os.umask(0o077)
job='20260920-contextra-fight-crowd-ready-r01'
out=Path('/tmp/codex/ltb1021/git-closeout')/job;out.mkdir(mode=0o700)
assert cmd(['git','-C',str(REPO),'rev-parse','HEAD']).strip()=='f9cc52f69503221ebf3c0e5f874f9f307da90112'
assert not cmd(['git','-C',str(REPO),'diff','--cached','--name-only']).strip()
paths=sorted(set(cmd(['git','-C',str(REPO),'diff','--name-only']).splitlines()+cmd(['git','-C',str(REPO),'ls-files','--others','--exclude-standard']).splitlines()))
cmd(['git','-C',str(REPO),'diff','--check'])
# Only validate newly authored live guides; candidate handoffs keep their historical links.
for p in ['docs/scenarios/SCENARIO_WEB_READY.ko.md','docs/profiles/ltb1021/topics/runtime-lifecycle/README.ko.md']:
    for link in re.findall(r'\]\(([^)]+)\)',(REPO/p).read_text()):
        if '://' not in link and not link.startswith('#'):
            assert ((REPO/p).parent/link.split('#')[0]).exists(),(p,link)
save('verification.json',dict(python_target='3.12',targeted_tests=152,native_assertions=26,
     official_decoder_parity_rows=200,official_decoder_max_error=4.66980010216389e-10,
     gpu_normalization='512_RGBA_pitch_RGB_NCHW_FP16_PASS',protobuf='PASS',
     actual_camera_start='NOT_RUN',accuracy='NOT_RUN',runtime_first_frame='NOT_RUN'))
receipt={'schema_version':'ltb1021.codex_hub.report_receipt.v1','receipt_id':job,
 'timestamp':datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=9))).isoformat(),
 'session_alias':'work-session','task':'FIGHT 임시 시연·CROWD 모니터링 통합 및 Web 시험 준비',
 'results':['FIGHT latch/gap 최소 보완과 Pose 공유·독립 ROI/pair Event 연결',
            'CROWD 신규512 모델/전처리/native/Settings/publisher 연결; Tracking/Event 없음',
            '대상3서비스 반영, 모델4종 READY/WSS/Artifact On, 22카메라 stopped'],
 'verify':['Python3.12 표적152 PASS, native계약26, 공식 PostProcess200행 일치,512 GPU정규화 PASS',
           'source22 및 native identity 일치, protobuf/nginx PASS, 기존 원장/비대상 컨테이너 보존'],
 'commits':[],'remaining':['사용자 FIGHT/CROWD 브라우저 시험 대기','FIGHT 정확도 보장 없음, FALL 보완/복수 모델/아이서티 반영 보류']}
save('report-receipt.json',receipt)
print(cmd(['codex-report-receipt','--profile','ltb1021','--session-alias','work-session','--receipt',str(HERE/'report-receipt.json')]))
mf=out/'manifest.json'
args=['codex-git-closeout','prepare','--repository',str(REPO),'--output',str(mf),'--job-id',job,
 '--profile','ltb1021','--session-alias','work-session',
 '--title','feat(scenarios): 임시 FIGHT와 CROWD 모니터링 Web 실행 경로 연결',
 '--message','Why=9월 시연용 FIGHT와 신규 사람·머리 CROWD를 기존 Runtime 계약 안에서 최소 연결한다.',
 '--message','What=PR9/10을 통합하고 FIGHT latch/gap/ROI/pair Event, CROWD512 전처리/native/model/Settings/publisher를 연결했다.',
 '--message','Impact=FIGHT는 Pose/Tracking 공유, CROWD는 단독·Tracking/Event 없음. 대상3서비스와 새 모델 mount만 반영하고 22카메라 stopped 및 기존 원장/비대상 서비스를 보존했다.',
 '--message','Verify=Python3.12 표적152, native26, 공식decoder200행 parity,512 GPU normalization, protobuf/nginx/source22 hash PASS. 모델4종 READY/WSS/Artifact On. 카메라Start·정확도·브라우저 수용 미실행.',
 '--message','Rollback=자동 rollback/재Start 없음. 이전 image/env/compose를 private evidence에 보존하며 별도 승인 후 대상 서비스만 정상 Stop/reap하여 복구한다. 원장 삭제/과거Event 재전송 금지.',
 '--message','Related=PR9 4c7e300; PR10 5cd8b34; FIGHT-CROWD-WIRE-01; FALL 보완과 복수모델은 보류',
 '--verify','Python3.12 targeted152 PASS; native26; official PostProcess200 rows parity; GPU512 normalization PASS',
 '--verify','Models4 READY; WSS/Artifact On; 22 stopped; ledger and non-target containers preserved',
 '--verify','Source22/native identity, protobuf/nginx, git diff --check and live guide links PASS; browser test NOT RUN',
 '--expires-in-seconds','86400']
for p in paths:args+=['--path',p]
print(cmd(args))
batch=out/'batch.json'
print(cmd(['codex-git-closeout','batch-prepare','--output',str(batch),'--batch-id',job,'--profile','ltb1021',
 '--session-alias','work-session','--expected-group-count','1','--repository-label','contextra-analytics',
 '--manifest',str(mf),'--expect-plan-hash',json.loads(mf.read_text())['plan_hash'],'--expires-in-seconds','86400']))
h=json.loads(batch.read_text())['plan_hash']
print(cmd(['codex-git-closeout','batch-plan','--batch-manifest',str(batch),'--expect-batch-plan-hash',h]))
print(cmd(['codex-git-closeout','batch-present','--batch-manifest',str(batch),'--expect-batch-plan-hash',h]))
