import hashlib,json,os,re,subprocess
from pathlib import Path
os.umask(0o077)
R=Path(__file__).parent;repo=Path('/workspace/contextra-analytics-runtime-lifecycle-refactor')
source=json.loads((R/'source.json').read_text())
docs=['docs/profiles/ltb1021/topics/runtime-lifecycle/README.ko.md','docs/profiles/ltb1021/topics/runtime-lifecycle/runs/20260912T172837+0900-run-rtp-loader-flow-stall.md']
paths=list(source['hashes'])+docs
def git(*args):return subprocess.check_output(['git','-C',str(repo),*args],text=True).strip()
assert git('rev-parse','HEAD')==source['base']
assert not git('diff','--cached','--name-only')
assert set(git('diff','--name-only').splitlines())|set(git('ls-files','--others','--exclude-standard').splitlines())==set(paths)
for p,h in source['hashes'].items():assert hashlib.sha256((repo/p).read_bytes()).hexdigest()==h
for path in docs:
    text=(repo/path).read_text();assert not re.search(r'192\.168\.\d+\.\d+',text)
    for target in re.findall(r'\]\(([^)]+)\)',text):
        if '://' not in target and not target.startswith('#'):assert ((repo/path).parent/target.split('#')[0]).exists()
subprocess.run(['git','-C',str(repo),'diff','--check'],check=True)
for p in R.iterdir():
    if p.is_file():os.chmod(p,0o600)
args=['/root/.local/bin/codex-git-closeout','prepare','--repository',str(repo),'--output',str(R/'git-manifest.json'),'--job-id','ltb1021-rtp-loader-20260912','--profile','ltb1021','--session-alias','work-session',
'--title','fix(rtp-loader): plugin SDK 검색 경로 교정과 실제 Flow 중단 기록',
'--message','Why=격리 검증의 추가 SDK 경로가 실제 서비스의 library 로딩 실패를 가렸으므로 plugin 자체 경로와 동등 환경 검증이 필요했다.',
'--message','What=plugin-local RUNPATH와 fresh scanner/명시 load/factory attach 회귀를 추가하고 source/image SDK copy를 확인했다.',
'--message','Impact=전역 loader 환경과 SDK를 변경하지 않는다. 실제 loader 오류는 해소됐지만 Flow/API 중단이 남아 기존 image/설정으로 복원했다.',
'--message','Verify=source/image loader 및 CPU SDK PASS. build1/live1에서 plugin 초기화·로딩 오류0, Start202 이후 API timeout. 최종 healthy/stopped·표시0.25·모델/인증/비대상 보존.',
'--message','Rollback=이번 배포는 private CAS 원장으로 복원 완료했다. 후보 image는 보존하고 다음 Flow 경계 확인 전에 같은 live를 반복하지 않는다.',
'--verify','loader/source/image SDK PASS; actual Flow stall and rollback verified; source hashes/docs links/diff check PASS','--expires-in-seconds','604800']
for p in paths:args+=['--path',p]
subprocess.run(args,check=True)
