from ops import *
import datetime,re,csv
job='20260926-contextra-batch8-scale-r01'
assert cmd(['git','-C',str(REPO),'rev-parse','HEAD']).strip()=='b2864469dcd1881050f10d70e038420744eb36db'
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)==14
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(),target
image=json.loads((HERE/'image-65294c6b51.json').read_text())
assert inspect('contextra-analytics-1')['Image']==image['id']
for p,h in image['hashes'].items():
    assert hashlib.sha256((REPO/p).read_bytes()).hexdigest()==h
    assert cmd(['docker','exec','contextra-analytics-1','sha256sum','/opt/contextra/'+p]).split()[0]==h
trial=json.loads((HERE/'scale/trial-result.json').read_text())
assert [s['level'] for s in trial['stages'] if s['status']=='PASS']==[1,2,4,8]
assert trial['errors']==[{'type':'RuntimeError','reason':'CHANNEL_ERROR_12'}] and trial['cleanup']['reaped']
assert all(not p['last_cleanup']['forced'] and p['last_cleanup']['child_reaped'] and p['last_cleanup']['diagnostic']['exit_code']==0
    for r in trial['cleanup']['states'].values() for p in r['providers'].values())
for lane in json.loads((HERE/'lanes-v2.json').read_text()):
    assert lane['completed']==lane['accepted'] and not lane['late']
    for d in lane['durations'].values():assert d['count']==sum(d['histogram']) and min(d['histogram'])>=0
batch=json.loads((HERE/'batch-sot.json').read_text())
for row in batch:
    n=row['total_executions'];row['batch_executions']={str(k):row['batch_executions'].get(str(k),0) for k in range(1,9)}
    row['batch_execution_pct']={k:v/n*100 for k,v in row['batch_executions'].items()}
    row['batch_ge4_pct']=row['batch_ge4_executions']/n*100;row['batch_gt4_pct']=row['batch_gt4_executions']/n*100
    assert sum(row['batch_executions'].values())==n
save('batch-distribution.json',batch)
with (HERE/'batch-distribution.csv').open('x',newline='') as f:
    w=csv.DictWriter(f,fieldnames=list(batch[0]));w.writeheader();w.writerows(batch)
final=json.loads((HERE/'final-state.json').read_text());assert final['states']=={'stopped':36} and final['children']==0 and final['wss']
assert final['batch']==8 and final['instances']==8 and final['cooldown_seconds']==10 and final['redis_stream_length']==300
assert all(r['state']=='stopped' and not r.get('cleanup_pending') for r in api('/api/v1/streams')['streams'])
contracts=json.loads((HERE/'model-contract.json').read_text());assert len(contracts)==4
for m,v in contracts.items():assert [c['batch'] for c in v['checks']]==[1,4,8]
code='''import json,urllib.request
out={}
for m in ('RFDETRMedium','RFDETRKeypointPreview','RFDETRFireSmoke','Awiros_person_and_head_detection'):
 c=json.load(urllib.request.urlopen('http://localhost:8000/v2/models/'+m+'/config',timeout=3))
 assert c['max_batch_size']==8 and c['version_policy']['specific']['versions']==[8] and c['dynamic_batching']['preferred_batch_size']==[8]
 assert all(g['count']==8 for g in c['instance_group'])
 out[m]=dict(version=8,max_batch_size=8,preferred_batch_size=[8],instances=8)
print(json.dumps(out))'''
models=json.loads(cmd(['docker','exec','contextra-analytics-1','python3','-B','-c',code],timeout=20))
save('verification.json',dict(python='3.12',targeted_passes=[90,23],overlap=True,new_cooldown_tests=8,
    known_baseline_failure='tests.test_loitering.TemporalTests.test_wrong_model_and_class: same failure on prior image; expectations unchanged',
    stages=[1,2,4,8],stage16='NOT_MEASURED: prior channel Crowd stalled during ninth channel startup',
    reaped_children=27,models=models,final=final,files=paths,source_image_hashes_match=True))
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 batch8/Event cooldown10/Redis300 지속 반영과 복합 부하 측정',
 results=['Crowd batch8 변환,네모델batch1/4/8실행PASS,version8/max·preferred8/instance8유지',
 '새Event발급전monotonic10초gate/현재증거/episode보호,표적90+23PASS(중복),기존LOITERING기대값1실패별도',
 '복합1/2/4/8각30초,16확장중Crowd2초stall로중단;8채널완료4.30/5.68/5.19FPS',
 '자연Artifact192건READY184/FAILED6/EXPIRED2;DBlock재현없으나해결입증아님'],
 verify=['27child exit0/unforced/reap;36stopped/WSS/4모델READY/ArtifactHTTPOn/CAS복귀',
 '코드imagehash/modelconfig/persistent값/diff/link/histogram/batch분모검증'],commits=[],
 remaining=['16채널미측정:Crowd 진행중단원인미분리','renderer실패/대기와송신교체남음','batch증설효과및실제Web수용은사용자판단'])
save('report-receipt.json',receipt)
print(cmd(['codex-report-receipt','--profile','ltb1021','--session-alias','work-session','--receipt',str(HERE/'report-receipt.json')]))
print(cmd(['python3','/workspace/users/root/codex-ops-docs/servers/test/users/ltb1021/portfolio_logs/scripts/create_portfolio_candidate.py',
 '--run-dir',str(HERE),'--confidence','MEDIUM','--repo','contextra-analytics',
 '--track-key','contextra-analytics:pipeline:runtime:gpu-first-inference','--closeout-job',job,
 '--evidence-state','runtime_validated','--confidentiality','internal',
 '--reason','Event 발급 제한과 확장 batch 실행은 검증했지만 목표 확장은 stall로 미완료이며 전체 성능 개선은 미확정',
 '--verify','표적90 및 추가23 PASS 중복포함; 네 모델 batch 실행; 복합 단계 측정과 강제 종료 없는 회수']))
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','feat(runtime): Event cooldown과 batch8 복합 부하 검증 추가',
 '--message','Why=반복영상의Event/Artifact부하를제한하고확장batch의실제분포와복합처리량을판단할근거가필요했다.',
 '--message','What=run/scenario monotonic10초Event발급gate와현재증거/episode보호를추가했다.Crowd batch8변환및네모델version8/max·preferred8/instance8과Redis300을test persistent반영했다.',
 '--message','Impact=B/freshnessOff유지,Web/Redis키/TTL/인증/전송계약과모델threshold보존.공통Stream300은provider별100개가아니다.원장/원본변경이나자동rollback재Start없음.',
 '--message','Verify=Python3.12표적90PASS+추가23PASS(중복),기존LOITERING기대값1실패는이전image도동일.네모델batch1/4/8입출력PASS.복합1/2/4/8측정,16확장Crowd stall중단.27child exit0/unforced/reap,36stopped/WSS/모델READY/ArtifactHTTPOn.',
 '--message','Rollback=이전image/model/config/privateCompose보존.시험채널설정만CAS복귀하고batch8/instance8,BOff,cooldown10,Redis300유지.명시적원복시Stop/reap뒤전체조합을맞춘다.16성능/renderer문제해결/Web수용은미완료.',
 '--verify','90 targeted PASS plus 23 followup PASS (overlap); 1 baseline test expectation failure unchanged',
 '--verify','4 models batch1/4/8 actual execution; 1/2/4/8 measured; 16 blocked by Crowd stall; safe reap/config/WSS verified',
 '--expires-in-seconds','86400']
for p in paths:args+=['--path',p]
print(cmd(args));bp=out/'batch.json'
print(cmd(['codex-git-closeout','batch-prepare','--output',str(bp),'--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(bp.read_text())['plan_hash']
print(cmd(['codex-git-closeout','batch-plan','--batch-manifest',str(bp),'--expect-batch-plan-hash',h]))
print(cmd(['codex-git-closeout','batch-present','--batch-manifest',str(bp),'--expect-batch-plan-hash',h]))
