from ops import *
import datetime
import re

job='20260921-contextra-demo-pr12-r01'
assert cmd(['git','-C',str(REPO),'rev-parse','HEAD']).strip()=='640acd4254191e3449f086868563379937d8a006'
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)==15
cmd(['git','-C',str(REPO),'diff','--check'])
for path in paths:
    if not path.endswith('.md'):continue
    for target in re.findall(r'\]\(([^)]+)\)',(REPO/path).read_text()):
        if '://' in target or target.startswith('#'):continue
        assert ((REPO/path).parent/target.split('#')[0]).exists(),(path,target)
save('verification.json',dict(python='3.12',targeted_tests=199,elapsed_seconds=2.194,
    provenance='Actual isolated approved-image unittest execution in this task; no reused predev PASS',
    test_style='CPU synthetic and mocks; no actual Event POST',
    checks=['On/Off, direct cooldown and per-episode UUID','temporal/fallback and camera/scenario isolation',
      'Settings CAS/no-op/save-failure and explicit site/camera Off',
      'current objectRef, Artifact duplicate admission and maximum-two delivery retry'],
    source_hashes={p:hashlib.sha256((REPO/p).read_bytes()).hexdigest() for p in paths},
    reflection='STOPPED_GATE_AFTER_GATEWAY_REOPEN',camera_start_sent=False,real_video='NOT_RUN',
    icerti='NOT_TOUCHED',doc_links=True,whitespace=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='PR12 FALL/FIGHT 시연 기본값 통합 및 test 전환 중단 기록',
    results=['FALL direct-down On/FIGHT fallback Off 및2초PTS cooldown, Runtime demo defaults 반영',
     '동일episode UUID/Artifact 중복 방지 보완 검증; 기존FALL6/FIGHT2 CAS migration',
     '기존image위offline4파일image 생성,4모델 readiness/24설정확인후stopped Gate 실패로대상정상회수'],
    verify=['Python3.12 최종표적199 PASS; 실제영상/시연정확도NOT RUN',
     '전체Compose image+5env변경만확인; 명시적skipOff5보존',
     '기존Event원장불변/비대상16컨테이너보존; Analytics/Gateway exit0'],commits=[],
    remaining=['Web동시요청정지확인후기존image로서비스재개필요; 현재Start-ready아님',
     '사용자브라우저영상수용과아이서티추가배포는별도승인'])
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','feat(scenarios): FALL/FIGHT 시연 기본값과 episode 보호 통합',
 '--message','Why=9월 시연의 Event 발생 조건을 완화하면서 같은 episode의 중복 Event/Artifact 생성을 방지한다.',
 '--message','What=PR12 direct-down/PTS cooldown/FIGHT 완화와 Runtime 기본값을 통합하고 explicit Off, UUID/Artifact 접수 경계 테스트와 적용/복귀 가이드를 보완했다.',
 '--message','Impact=FALL은 초기 DOWN도 허용해 의미가 확장된다. FIGHT fallback은Off. 모델/Tracking/public schema는불변. test 저장FALL6/FIGHT2 migration, 아이서티는미반영.',
 '--message','Verify=Python3.12 표적199 PASS. offline4파일image hash/4모델ready/24설정확인. Gateway재개후동시Web요청정황과stopped Gate실패로Analytics/Gateway exit0회수. 비대상16개/원장보존. 영상과Start-ready는미수용.',
 '--message','Rollback=사용자명시승인뒤baseline threshold만CAS복귀하고보존된이전image/전체Compose를대조한다. 자동rollback/원장삭제/카메라재Start없음. 현재서비스재개는별도필요.',
 '--message','Related=PR12 d20aca8; DEMO-SENSITIVITY-12; 아이서티배포와실제영상은후속',
 '--verify','Python3.12 199 targeted tests PASS; explicit Off/CAS/no-op/Artifact dedupe/delivery retry',
 '--verify','Source hash and rendered Compose exact match; four models readiness PASS before maintenance failure',
 '--verify','Final Analytics/Gateway stopped exit0; Event ledger unchanged; 16 non-target containers preserved; no actual video test',
 '--expires-in-seconds','86400']
for path in paths:args+=['--path',path]
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]))
