import datetime
import json
import os
from pathlib import Path
import re
import subprocess

os.umask(0o077)
repo=Path('/workspace/contextra-analytics-runtime-lifecycle-refactor')
here=Path(__file__).parent
job='20260920-contextra-awiros-person-head-r01'
out=Path('/tmp/codex/ltb1021/git-closeout')/job
out.mkdir(mode=0o700)
def cmd(args):
    p=subprocess.run(args,capture_output=True,text=True,timeout=90)
    assert p.returncode==0,p.stdout+p.stderr
    return p.stdout
paths=['docs/profiles/ltb1021/topics/runtime-lifecycle/README.ko.md',
       'docs/deployment/AWIROS_PERSON_HEAD_CANDIDATE.ko.md',
       'docs/profiles/ltb1021/topics/runtime-lifecycle/runs/20260920T223620+0900-run-awiros-person-head-candidate.md']
assert not cmd(['git','-C',str(repo),'diff','--cached','--name-only']).strip()
assert set(paths)==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'])
for p in paths:
    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()
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':'신규 RF-DETR-S 사람·머리 ONNX/TensorRT 후보 변환',
 'results':['공식 revision과 업로드 hash/크기 대조, 신규 weight487 tensor 일치 확인',
            '512x512 dynamic ONNX와 A6000 TensorRT FP16입력/FP32출력 batch1/4/4 후보 생성',
            'manifest·도구·원장·사용 가이드 기록; 기존 환경과 컨테이너 보존'],
 'verify':['ONNX checker, engine 역직렬화, batch1~4 shape/dtype/finite PASS',
           '기존 컨테이너 ID/image/StartedAt 불변, root15GiB 보호선 유지, SDK 설치/Runtime 등록 없음'],
 'commits':[],'remaining':['사용자 시각 검증과 군중 시나리오/Runtime 연결 대기','아이서티 GPU 변환 별도']}
rp=here/'report-receipt.json'
with rp.open('x') as f:json.dump(receipt,f,ensure_ascii=False,indent=2)
print(cmd(['codex-report-receipt','--profile','ltb1021','--session-alias','work-session','--receipt',str(rp)]))
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','docs(model): 신규 사람·머리 TensorRT 후보와 변환 근거 기록',
 '--message','Why=군중 시나리오 연결 전에 신규 업로드 weight와 변환 후보를 기존 모델에서 분리한다.',
 '--message','What=공식 revision/hash, 원본487 tensor 일치, 512x512 ONNX/TensorRT 산출물 및 사용 계약을 기록했다.',
 '--message','Impact=기존 exporter/tooling을 읽기 전용 재사용했다. 모델 등록/서비스 반영/카메라/DB/Redis 변경과 새 SDK 설치 없음.',
 '--message','Verify=ONNX checker, TensorRT10.16 역직렬화 및 batch1~4 FP16입력/FP32출력 shape/dtype/finite PASS. 기존 컨테이너 보존, root최저29.18GiB. 정확도·성능 미평가.',
 '--message','Rollback=Runtime 미반영이므로 복구 불필요. 신규 후보와 원본을 보존하며 재변환 시 별도 revision 경로 사용.',
 '--message','Related=신규 Awiros RF-DETR-S 후보; 군중 연결 및 아이서티 변환은 후속',
 '--verify','Official uploaded source hash and 487 tensors match; ONNX checker PASS',
 '--verify','TRT10.16 deserialize and batch1-4 shape/dtype/finite PASS; existing containers preserved',
 '--verify','git diff --check and local Markdown links PASS; accuracy/runtime integration 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]))
