import datetime,hashlib,json,os,pathlib,subprocess
os.umask(0o077)
repo=pathlib.Path('/workspace/contextra-analytics-runtime-lifecycle-refactor')
here=pathlib.Path(__file__).parent
job='20260921-contextra-video-clip-r01'
def cmd(args):return subprocess.check_output(args,text=True,timeout=60)
assert cmd(['git','-C',str(repo),'rev-parse','HEAD']).strip()=='b0513a024677fe0e6b39ca3eb6647b5f1a85aa8a'
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)==7,paths
assert not list(pathlib.Path('/sys/fs/cgroup').glob('contextra-video-clip-*'))
verify={'python':'3.12','ffmpeg':'6.1.1','unit_safety':26,'actual_ffmpeg_tests':2,
    'synthetic_source_seconds':4,'copy_executions':1,'reencode_executions':1,
    'cgroup_limits':{'cpu_max':'200000 100000','memory_max':2147483648,'memory_swap_max':0,'pids_max':64},
    'cleanup':'PASS','runtime_changed':False,'actual_user_video':'NOT_RUN','nvenc':'NOT_RUN','rtsp':'NOT_RUN',
    'source_hashes':{p:hashlib.sha256((repo/p).read_bytes()).hexdigest() for p in paths}}
(here/'verification.json').write_text(json.dumps(verify,indent=2))
receipt={'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':'PR11 단일 영상 클립 CLI 통합과 공유 서버 보호 보완',
 'results':['기본CPU H.264 reencode, clips 하위폴더 및 output-dir 지원',
            '원자적 덮어쓰기 방지와 cgroup CPU/RAM 제한, 잠금/timeout/취소 회수',
            '운영 실패 fallback 금지와 최소 사용 가이드 준비'],
 'verify':['Python3.12 표적28 PASS; synthetic copy/reencode 각1회',
           '자식 cgroup 편입/실제 제한 readback/후손 회수와 파일 보호 확인; Runtime 변경0'],
 'commits':[],'remaining':['사용자 원본 영상 변환 대기','H.265/NVENC 실제 실행 및 RTSP URI 생성/송출은 후속']}
(here/'report-receipt.json').write_text(json.dumps(receipt,ensure_ascii=False,indent=2))
print(cmd(['codex-report-receipt','--profile','ltb1021','--session-alias','work-session','--receipt',str(here/'report-receipt.json')]))
out=pathlib.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(tools): 안전한 단일 영상 클립 제작 CLI 준비',
 '--message','Why=RTSP 시험용 클립을 AI Runtime과 분리해 제작하면서 공유 서버 자원과 기존 파일을 보호한다.',
 '--message','What=PR11을 통합하고 기본 reencode/clips/output-dir, atomic no-clobber, root single-job flock, cgroup CPU/RAM/swap/PID 제한과 bounded timeout/log/disk/취소 회수를 보완했다.',
 '--message','Impact=독립 호스트CLI와 문서만 변경. 원본 보존, 명시 overwrite만 교체, 운영 실패 fallback 금지. AI Runtime/미디어 서비스/아이서티 변경 없음.',
 '--message','Verify=Python3.12 표적28 PASS: Unit/보호26, 실제 synthetic H.264 copy/reencode 각1회. 자식 cgroup 편입/제한 readback와 회수 확인. 사용자 영상/H.265/NVENC/RTSP는 미실행.',
 '--message','Rollback=도구 사용을 중단하고 해당 source 변경을 검토해 복구한다. AI Runtime 복구 작업은 없다. 사용자 원본/출력을 자동 삭제하지 않으며 실행 중 잠금 파일을 unlink하지 않는다.',
 '--message','Related=PR11 48440043; VIDEO-CLIP-01; RTSP URI 생성/송출은 후속',
 '--verify','Python3.12 unit/safety26 PASS; synthetic FFmpeg6.1.1 copy1/reencode1 PASS',
 '--verify','cgroup readback/membership, lock, timeout/descendant reap, SIGTERM, disk/log safeguards PASS; no remaining job cgroup',
 '--verify','Syntax/whitespace/doc links and CLI help PASS; no Runtime/RTSP/user-video execution',
 '--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]))
