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

os.umask(0o077)
HERE=Path(__file__).parent
REPO=Path('/workspace/contextra-analytics-runtime-lifecycle-refactor')
JOB='20260919-contextra-deployment-kit-r01'
ROOT=Path('/tmp/codex/ltb1021/git-closeout')/JOB
ROOT.mkdir(mode=0o700)
def cmd(args):
    p=subprocess.run(args,text=True,capture_output=True,timeout=90)
    assert p.returncode==0,p.stdout+p.stderr
    return p.stdout
assert cmd(['git','-C',str(REPO),'branch','--show-current']).strip()=='task/runtime-lifecycle-refactor'
assert cmd(['git','-C',str(REPO),'rev-parse','HEAD']).strip()=='80ad438fc80b4793760c7365f4a02d29dfea2715'
assert not cmd(['git','-C',str(REPO),'diff','--cached','--name-only']).strip()
paths=cmd(['git','-C',str(REPO),'diff','--name-only']).splitlines()+cmd(['git','-C',str(REPO),'ls-files','--others','--exclude-standard']).splitlines()
assert len(paths)==48,(len(paths),paths)
cmd(['git','-C',str(REPO),'diff','--check'])
for name in paths:
    f=REPO/name
    if f.suffix=='.md':
        for dest in re.findall(r'\]\(([^)]+)\)',f.read_text()):
            if '://' not in dest and not dest.startswith('#'):
                assert (f.parent/dest.split('#',1)[0]).exists(),(name,dest)
receipt=dict(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='Contextra 배포 도구 통합과 현장 사전 준비',
 results=['배포 후보를 통합하고 첫 설치 실패 재개 소유권, 모델 노출 범위, 출력/진단 및 현장 LAN 옵션을 보완했다.',
          '현장은 읽기 전용으로 확인하고 도구 image, 모델 원본과 private 설정 초안을 준비했다.',
          'FULL export는 daemon staging 공간 위험 전에 중단했고 사용자 선택으로 보류했다. 보호선 완화는 적용하지 않았다.'],
 verify=['Python3.12 표적21개, 실제 Compose 재해석, 세 ONNX CPU 계약, C++ 컴파일/import PASS.',
         '148개 source archive hash/경로 PASS. 기존 Runtime container image/start/PID 보존. 대상 쓰기0.'],
 commits=[],remaining=['FULL 이미지 archive 미완료; 현장 인증/secret 입력과 NVIDIA Docker 연결 및 실제 설치/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=ROOT/'manifest.json'
args=['codex-git-closeout','prepare','--repository',str(REPO),'--output',str(mf),'--job-id',JOB,
 '--profile','ltb1021','--session-alias','work-session',
 '--title','feat(deployment): 배포 도구 통합과 현장 사전 준비 보완',
 '--message','Why=첫 현장 배포 전에 실패 재개와 모델/secret 경계를 실제 환경에 맞춘다.',
 '--message','What=후보 소스를 통합하고 transaction 소유권, 모델 repository 일치, 출력/진단, Compose 재해석, LAN 옵션과 tooling probe를 보완했다.',
 '--message','Impact=현장과 test Runtime은 변경하지 않았다. FULL export는 공간 위험과 사용자 선택으로 보류하고 도구/원본/private 준비를 구분했다.',
 '--message','Verify=Python3.12 표적21개, 실제 Compose config 재해석, 세 ONNX CPU 계약, C++ 컴파일/import 및 source148파일 hash/경로 PASS. 대상 GPU/설치/연동은 미실행.',
 '--message','Rollback=현재 Runtime 반영이 없어 자동 rollback은 수행하지 않았다. 기존 source baseline과 부분 산출물/원장을 보존한다.',
 '--verify','21 targeted tests PASS; real Compose config roundtrip with explicit fixtures PASS; 3 ONNX CPU contracts PASS',
 '--verify','Tooling C++ compilation/import and source archive 148 file hashes PASS; target GPU/runtime/install NOT RUN',
 '--verify','Existing container image/start/PID unchanged; FULL export USER_DEFERRED; git diff --check and Markdown links PASS',
 '--expires-in-seconds','86400']
for name in sorted(paths):args+=['--path',name]
print(cmd(args))
batch=ROOT/'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]))
