import ast
from datetime import datetime
import hashlib
import json
from pathlib import Path
import re
import shutil
import subprocess
import tarfile

repo=Path('/workspace/contextra-analytics-runtime-lifecycle-refactor')
run=Path('/tmp/codex/ltb1021/2026-10-07_ct-storage-maintenance_r01')
out=Path('/data/codex-artifacts/contextra/field-maintenance/2026/2026-10-07_ct-storage-maintenance_r01')
def git(*args):return subprocess.check_output(['git','-C',str(repo),*args],text=True,timeout=15)
assert git('branch','--show-current').strip()=='task/runtime-lifecycle-refactor'
assert git('rev-parse','HEAD').strip()=='654c35d1994318d401408319b62fc100c2ce45fe'
assert not git('diff','--cached','--name-only').strip()
paths=sorted(set(git('diff','--name-only').splitlines()+git('ls-files','--others','--exclude-standard').splitlines()))
assert len(paths)==27,(len(paths),paths)
for name in paths:
    p=repo/name
    if p.suffix=='.py':ast.parse(p.read_text(),filename=name)
    if p.suffix=='.md' and ('CT_DATA_MAINTENANCE' in name or '20261007T114000' in name):
        for link in re.findall(r'\]\(([^)]+)\)',p.read_text()):
            if not link.startswith(('http','#')):assert (p.parent/link).exists(),(name,link)
manifest={name:hashlib.sha256((repo/name).read_bytes()).hexdigest() for name in paths}
(out/'source-final.json').write_text(json.dumps(dict(head=git('rev-parse','HEAD').strip(),files=manifest),indent=2)+'\n')
(out/'tracked-final.diff').write_text(git('diff','--binary'))
with tarfile.open(out/'source-final.tar.gz','w:gz') as archive:
    for name in paths:archive.add(repo/name,arcname=name)
for p in run.glob('*.log'):shutil.copyfile(p,out/p.name)
for name in ('final_readback.py','run_fixtures.py','preserve_final.py'):
    shutil.copyfile(run/name,out/name)
for p in out.iterdir():
    if p.is_file():p.chmod(0o600)
receipt=dict(schema_version='ltb1021.codex_hub.report_receipt.v1',receipt_id='20261007-ct-storage-maintenance-r01',timestamp=datetime.now().astimezone().isoformat(timespec='seconds'),session_alias='contextra-ct-storage',task='공통 ct 권한 및 자료 관리 구현',results=['정리·초기화·보관 정책과 선택 UI 구현; 두 설치본 도구 반영','작은 APP 패치는 다음 명시적 기동 대상만 준비, 실제 자료 삭제 없음'],verify=['maintenance116PASS 및 격리DB/Redis4사례PASS','Runtime 표적12사례 및 launcher/회수 보완검사PASS','실제 operator 메뉴 및 두 설치본13파일 지문 일치'],commits=[],remaining=['실자료 삭제·사용자 수용·새 APP Runtime 활성화 보류'])
p=run/'report-receipt.json';p.write_text(json.dumps(receipt,ensure_ascii=False,indent=2)+'\n');p.chmod(0o600)
print(json.dumps(dict(files=len(paths),syntax_and_doc_links='PASS',snapshot_sha256=hashlib.sha256((out/'source-final.tar.gz').read_bytes()).hexdigest())))
