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

repo=Path('/workspace/contextra-analytics-runtime-lifecycle-refactor')
run=Path(__file__).parent
out=Path('/data/codex-artifacts/contextra/field-maintenance/2026/2026-10-07_ai2-vscode-safety_r01')
out.mkdir(mode=0o700)
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()=='f2443b6f2976496cc67e5e57f4fe3b4c829d48bb'
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)==5,paths
for name in paths:
    if name.endswith('.py'):ast.parse((repo/name).read_text())
subprocess.run(['git','-C',str(repo),'diff','--check'],check=True,timeout=15)
manifest={p:hashlib.sha256((repo/p).read_bytes()).hexdigest() for p in paths}
(out/'source.json').write_text(json.dumps(dict(head=git('rev-parse','HEAD').strip(),files=manifest),indent=2)+'\n')
(out/'tracked.diff').write_text(git('diff','--binary'))
with tarfile.open(out/'source.tar.gz','w:gz') as archive:
    for name in paths:archive.add(repo/name,arcname=name)
for p in run.iterdir():
    if p.is_file() and p.suffix in ('.py','.log','.json'):shutil.copyfile(p,out/p.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-ai2-vscode-safety-r01',timestamp=datetime.now().astimezone().isoformat(timespec='seconds'),session_alias='contextra-vscode-safety',task='원격 VSCode 탐색 자원 보호',results=['미적용 npm 자동 탐색 보호를 적용하고 대용량 경로 검색 제외를 보완','사용자 저장 승인 뒤 확장 호스트만 회수, 사용자 재시작과 화면 정상 확인'],verify=['설정 복구와 PID 보호 등 표적8사례PASS','설치 지문 및 persistent 설정 확인; 마지막15초 과부하 탐색 없음','확장 호스트 RSS 약12GiB에서224MiB로 감소; 기존 서비스 상태 보존'],commits=[],remaining=['실제 재부팅 및 장시간 무재발 미시험'])
p=run/'report-receipt.json';p.write_text(json.dumps(receipt,ensure_ascii=False,indent=2)+'\n');p.chmod(0o600)
args=['/root/.local/bin/codex-git-closeout','prepare','--repository',str(repo),'--output',str(run/'closeout.json'),'--job-id','20261007-ai2-vscode-safety-r01','--profile','ltb1021','--session-alias','contextra-vscode-safety','--title','fix(ct-vscode): 서버별 대용량 탐색 보호와 설정 복구 검증 보완']
for path in paths:args+=['--path',path]
for message in ['Why=원격 기본 npm 탐색과 대용량 경로가 과부하를 유발해 기존 보호 설정을 실제 설치본에 적용한다.','What=storage 검색·watcher 제외 및 설정 보존/복구 표적 검사를 추가하고 운영 기록을 갱신했다.','Impact=원격 operator 설정과 ct helper만 변경. 파일 접근·SSH·터미널·Contextra 상태 보존.','Verify=설정/복구 및 PID/timeout 표적8사례PASS; source/설치 hash 일치; 사용자 확장 호스트 재시작/화면 정상;15초 rg0.','Rollback=ct vscode restore로 관리 키만 복구; 설치 helper는 보존 백업과 지문 검토 후 복구.']:args+=['--message',message]
args+=['--verify','Targeted8PASS; source syntax/git diff check PASS; operator settings and tool readback PASS; user UI PASS; reboot/long-run NOT TESTED']
subprocess.run(args,check=True,timeout=60)
print('PRESERVED',out)
