import ast
import hashlib
import json
import os
from pathlib import Path
import re
import subprocess

os.umask(0o077)
root = Path(__file__).parent
repo = Path('/workspace/contextra-analytics-runtime-lifecycle-refactor')
job = 'ltb1021-contextra-metadata-connect-20260911'
paths = ['.dockerignore', 'app/api/streams.py', 'app/application/streams.py',
         'app/contracts/visualization.py', 'app/det_result_path.py', 'app/main.py',
         'app/metadata_publisher.py', 'app/metadata_samples.py', 'app/metadata_runtime.py',
         'app/metadata_visual.py', 'app/multi_pipeline.py', 'app/stream_manager.py',
         'app/stream_settings.py', 'tests/sdk_frame_identity_probe.py',
         'tests/test_composition_architecture.py', 'tests/test_stream_apply.py',
         'tests/test_metadata_build_context.py', 'tests/test_metadata_connection.py',
         'docs/profiles/ltb1021/topics/runtime-lifecycle/README.ko.md',
         'docs/profiles/ltb1021/topics/runtime-lifecycle/decision/20260911T155808+0900-decision-frame-result-display-sharing.md',
         'docs/profiles/ltb1021/topics/runtime-lifecycle/validation/20260911T155808+0900-validation-metadata-transport-visual-source.md']

def git(*args):
    return subprocess.check_output(['git', '-C', str(repo), *args], text=True).strip()

assert git('rev-parse', 'HEAD') == 'bd5ed86f9f95f28143d2f7bd09c0843e4726fcb6'
assert git('branch', '--show-current') == 'task/runtime-lifecycle-refactor'
assert not git('diff', '--cached', '--name-only')
changed = set(git('diff', '--name-only').splitlines()) | set(git('ls-files', '--others', '--exclude-standard').splitlines())
assert changed == set(paths), (changed - set(paths), set(paths) - changed)
links = 0
for path in paths:
    content = (repo/path).read_text()
    if path.endswith('.py'):
        ast.parse(content)
    if path.endswith('.md'):
        for target in re.findall(r'\]\(([^)]+)\)', content):
            if '://' in target or target.startswith('#'):
                continue
            resolved = (repo/path).parent / target.split('#', 1)[0]
            assert resolved.exists(), (path, target)
            links += 1
subprocess.run(['git', '-C', str(repo), 'diff', '--check'], check=True)
hashes = {path: hashlib.sha256((repo/path).read_bytes()).hexdigest() for path in paths}
(root/'source-hashes.json').write_text(json.dumps(hashes, indent=2))
(root/'static-validation.json').write_text(json.dumps(dict(paths=len(paths), links=links, syntax='PASS',
                                                          diff_check='PASS', ownership='exact_clean_baseline')))
prepare = ['/root/.local/bin/codex-git-closeout', 'prepare', '--repository', str(repo),
           '--output', str(root/'git-manifest.json'), '--job-id', job, '--profile', 'ltb1021',
           '--session-alias', 'work-session', '--title', 'feat(metadata): Redis·동일 Frame 시각 확인 source 연결',
           '--message', 'Why=9월 AI Metadata 제공을 위해 내부 후보 보존과 외부 표시·송신을 분리한다.',
           '--message', 'What=불변 FrameResult, bounded transport composition, 표시 설정 CAS, opt-in JPEG와 동일 JSON, build context를 준비했다.',
           '--message', 'Impact=source와 관련 test/Owner만 변경했다. image·운영 Redis·모델·Runtime은 미반영이며 표시0.1은 다음 시험에서 명시 적용한다.',
           '--message', 'Verify=관련97 tests와 후속20 tests PASS. SDK Frame wrapper list 보관 오류를 교정하고 실제 CPU SDK→fake sink PASS. 실제 Redis/GPU pixel/배포는 WAIT.',
           '--message', 'Rollback=이 변경을 되돌릴 수 있다. 실제 적용값 변경0이며 다음 배포의 image/env/settings/Redis CAS 복원 범위를 Owner에 기록했다.',
           '--verify', 'isolated 97 tests PASS; final 20 tests and SDK fake sink PASS; source syntax/links/diff checks PASS; no deployment',
           '--expires-in-seconds', '604800']
for path in paths:
    prepare += ['--path', path]
subprocess.run(prepare, check=True)
