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='20260920-contextra-model-config-fix-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()=='c44f3f8fd21bf0921320dcb7ccbaa86215596c1b'
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)==7,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=['Triton output 마지막 쉼표를 수정하고 실패 로그를 회수 전에 제한된 크기로 보존한다.',
 '기존 FULL과 엔진을 수정하지 않는 별도 소형 도구와 새 후보 생성 절차를 준비했다.'],
 verify=['표적26개 및 실제 Triton protobuf12설정 PASS, legacy 파싱 오류 재현.',
 '패치 archive16파일 검증 및 별도 도구 help PASS. 대상 SSH 조회는 sudo 제한을 확인했고 쓰기는 하지 않았다.'],
 commits=[],remaining=['사용자 현장 패치 전달과 새 후보 생성, batch1~4 재검증 대기'])
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','fix(deployment): Triton 설정 문법과 실패 진단 보완',
 '--message','Why=변환된 engine이 output 마지막 쉼표로 Triton에 로드되지 않고 실패 로그도 회수 중 사라졌다.',
 '--message','What=pbtxt separator를 교정하고 private bounded stderr 로그를 cleanup 전에 저장한다. 원본 보존형 새후보 config migration과 별도 소형 도구를 준비했다.',
 '--message','Impact=기존 FULL과 원본 후보/engine은 보존한다. target 쓰기, test Runtime 교체, engine 변환 및 image rebuild는 하지 않았다.',
 '--message','Verify=표적26개 PASS; 실제 Triton protobuf12설정 PASS 및 legacy 오류 재현; 소형 archive16파일/standalone help PASS; diff/문서링크 PASS. 현장 sudo 제한으로 원장 직접 조회와 실제 smoke는 대기.',
 '--message','Rollback=자동 rollback 없음. 기존 FULL과 실패후보는 그대로 보존되며 신규 후보와 별도 도구만 사용한다. 실패한 신규 출력도 임의 삭제하지 않는다.',
 '--verify','26 targeted tests PASS; actual ModelConfig protobuf12 profiles PASS; legacy ParseError reproduced',
 '--verify','Small patch16 members and standalone help PASS; no target writes/runtime replacement/build',
 '--verify','git diff --check and Markdown links PASS; target sudo read unavailable, actual target smoke WAIT',
 '--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]))
