import ast,json,os,subprocess
from pathlib import Path
os.umask(0o077)
R=Path(__file__).parent;runner='/root/.local/bin/codex-git-closeout';job='contextra-intrusion-preparation-20260914-143245'
def run(args):return subprocess.check_output(args,text=True,timeout=45)
def prepare(repo,head,label,title,messages,verify,count):
    assert run(['git','-C',repo,'rev-parse','HEAD']).strip()==head
    assert not run(['git','-C',repo,'diff','--cached','--name-only']).strip()
    paths=sorted(set(run(['git','-C',repo,'diff','--name-only']).splitlines()+run(['git','-C',repo,'ls-files','--others','--exclude-standard']).splitlines()))
    assert len(paths)==count
    run(['git','-C',repo,'diff','--check'])
    for p in paths:
        if p.endswith('.py'):ast.parse((Path(repo)/p).read_text())
    args=[runner,'prepare','--repository',repo,'--output',str(R/(label+'-manifest.json')),'--job-id',job if label=='contextra' else job+'-'+label,'--profile','ltb1021','--session-alias','work-session','--title',title,'--verify',verify]
    for m in messages:args+=['--message',m]
    for p in paths:args+=['--path',p]
    return json.loads(run(args))
source=prepare('/workspace/contextra-analytics-runtime-lifecycle-refactor','a4832fdcd8e009c4d5be326b6060cfdf47700632','contextra',
 'refactor(intrusion): 중복 만료와 queue lock 범위 및 ROI 준비 정리',[
 'Why=판정 의미를 유지하며 실시간 후처리의 중복 순회와 공유 queue 임계구역 안의 계산을 줄인다.',
 'What=만료 검사1회화와 idle/stale lock 밖 정리, 만료 ID 수집, engine-local ROI geometry 준비 및 회귀를 추가했다.',
 'Impact=새 image 유지, 원래 camera 설정과 restart 정책 복원, healthy/Stream stopped. 기존 모델과 비대상 서비스는 보존했다.',
 'Verify=source/image 각17 tests와 이전 판정120Frame씩 비교 PASS. Start1/Stop1의15.202초 구간 결과/Redis9.9988FPS, drop/stale0, cleanup0.259초. 별도 속도 개선 배수는 주장하지 않는다.',
 'Rollback=이번 source 변경만 revert하고 필요한 경우 private CAS 원장의 이전 image로 복원한다. 기존 모델과 산출물은 삭제하지 않는다.'
 ],'source/image tests17 each PASS; baseline decisions/events/state120 frames each equal; build1 Start1 Stop1 failures0; Metadata-only result/Redis9.9988FPS; cleanup PASS; original settings and non-targets preserved; diff/AST PASS',5)
portfolio=prepare('/workspace/users/root/codex-ops-docs','89843b685247df5e8b390080d10a5003ec0550a0','portfolio',
 'docs(portfolio): INTRUSION 상태 소유권과 임계구역 정리 검증 기록',[
 'Why=검증된 상태 정리와 동시성 개선을 기술 성과로 남긴다.',
 'What=INTRUSION 만료와 ROI 준비 개선의 실제 회귀 및 Runtime milestone1건을 안전 append했다.',
 'Impact=해당 Portfolio shard와 track/catalog만 갱신하며 historical evidence와 공용 지침은 보존한다.',
 'Verify=append dry-run/content safety PASS, source와 Runtime evidence 및 변경5파일 대응 확인.',
 'Rollback=해당 신규 entry와 track/catalog 갱신만 기존 안전 절차로 보정하며 application Runtime은 변경하지 않는다.'
 ],'HIGH milestone append dry-run PASS; evidence and source files correspond; observed throughput maintained without isolated speedup claim',3)
args=[runner,'batch-prepare','--output',str(R/'git-batch.json'),'--batch-id',job,'--profile','ltb1021','--session-alias','work-session','--expected-group-count','2']
for label,p in [('contextra',source),('portfolio',portfolio)]:args+=['--repository-label',label,'--manifest',str(R/(label+'-manifest.json')),'--expect-plan-hash',p['plan_hash']]
print(run(args))
