from ops import *
import datetime,re
job='20260926-contextra-process-compare-r02'
assert cmd(['git','-C',str(REPO),'rev-parse','HEAD']).strip()=='0714710d300c0f830cecee186ab4c4caa9e25acb'
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()))
assert len(paths)==5
cmd(['git','-C',str(REPO),'diff','--check'])
for p in paths:
    if not p.endswith('.md'):continue
    for target in re.findall(r'\]\(([^)]+)\)',(REPO/p).read_text()):
        if '://' not in target and not target.startswith('#'):assert ((REPO/p).parent/target.split('#')[0]).exists()
for p,h in json.loads((HERE/'build-intent.json').read_text())['hashes'].items():assert hashlib.sha256((REPO/p).read_bytes()).hexdigest()==h
final=json.loads((HERE/'closeout-state.json').read_text())
assert final['wss'] and final['stopped']==36 and not final['active']
runs=[json.loads((HERE/m/'result.json').read_text()) for m in ('A','B','A-confirm')]
assert all(d['measurement']=='PASS' and d['reaped'] and d['slots_released'] for d in runs)
assert all(g['last_cleanup']['completed'] and g['last_cleanup']['diagnostic']['exit_code']==0 for d in runs for g in d['after_stop']['groups'].values())
assert all(runs[0]['triton_before'][m]['config']==d['triton_before'][m]['config'] for d in runs[1:] for m in runs[0]['triton_before'])
save('verification.json',dict(cpu_tests=2,python='3.12',helper_identity_regression=dict(before='ValueError CROWD camera/source mismatch',after='PASS'),
 gpu_phases=['A30s','B30s','A-confirm30s'],same_model_configs=True,all_normal_cleanup=True,
 final=final,files=paths,portfolio='LOW benchmark/helper correction'))
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='시험 helper identity 오류 수정과 provider process A/B/A 비교 완료',
 results=['source_id만 바꾼 helper가 CROWD camera/source guard를 위반했음을 CPU재현하고 camera_id도동일별칭으로수정',
 'B의Pose/Fire/Crowd수락9.11/9.81/9.88FPS;Medium10은A80.20/B65.46/재A86.52FPS',
 '복합channel 분리효과확인,전면운영전환보류;single-decode유지와copy/검증경량화는후속후보'],
 verify=['Python3.12 관련2PASS, GPU각30초A/B/재A와모든child정상회수',
 '36stopped/WSS연결/4모델READY/Artifact HTTP On, source/image와persistent pin일치,원본설정및비대상보존'],
 commits=[],remaining=['process분리정식Metadata/Event통합미실행','결과복사/검증native경량화후보별도승인','16채널90%폐기/장시간안정성과Artifact기존장애미검증'])
save('report-receipt.json',receipt)
print(cmd(['codex-report-receipt','--profile','ltb1021','--session-alias','work-session','--receipt',str(HERE/'report-receipt.json')]))
out=Path('/tmp/codex/ltb1021/git-closeout')/job;out.mkdir(mode=0o700)
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','fix(tools): process 비교 identity 정합과 A/B 결과 확정',
 '--message','Why=격리helper가source_id만변경해CROWD검증에서A가중단됐고provider분리의실제효과를판단할수없었다.',
 '--message','What=camera_id를같은시험별칭으로맞추고실제CROWD처리/Frame snapshot회귀를추가했다.A/B/재A각30초로복합채널개선과Medium저하를기록했다.',
 '--message','Impact=운영모델/instance/batch/FPS/100ms/decoder/Settings불변.변경image는helper1파일수정이며운영process분리default로승격하지않았다.',
 '--message','Verify=CPU오류재현후관련2PASS,GPU3phase정상회수. B수락Pose9.11/Fire9.81/Crowd9.88FPS,Medium합계A80.20/B65.46/재A86.52FPS.최종36stopped/WSS연결/4모델READY/Artifact HTTP On.',
 '--message','Rollback=기존image/config/evidence보존.명시승인시Analytics image pin을이전processdiag로복귀가능.불필요한자동rollback이나카메라재Start는하지않았다.',
 '--verify','Python3.12 targeted2 PASS; helper identity guard reproduced before and passes after; diff check PASS',
 '--verify','GPU A/B/A each30s PASS, identical model configs, all child cleanup PASS,36 stopped/WSS/model ready',
 '--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]))
