"""Verify transferred mappings and preserve final evidence; no rendering."""
import csv
import hashlib
import json
import pathlib
import sys

ROOT=pathlib.Path(__file__).resolve().parent.parent
OUT=ROOT/'Contextra_User_Segments_20'
sys.path.insert(0,'/data/codex-artifacts/contextra/action-model-eval/2026/2026-10-26_contextra-camera24-prep_r01/helpers')
from remote import run

def digest(p):
    h=hashlib.sha256()
    with p.open('rb') as f:
        for chunk in iter(lambda:f.read(1048576),b''):h.update(chunk)
    return h.hexdigest()

def save(p,v):
    with p.open('x') as f:json.dump(v,f,ensure_ascii=False,indent=2)

m=json.loads((ROOT/'manifest.json').read_text())
checks=json.loads((OUT/'SHA256.json').read_text())
assert len(list((OUT/'Unmarked_Clips').glob('*.mp4')))==20
assert len(list((OUT/'Frame_Review').glob('*.mp4')))==20
for rel,v in checks.items():assert digest(OUT/rel)==v['sha256'] and (OUT/rel).stat().st_size==v['bytes']
for c in m['clips']:
    with (OUT/'Frame_Maps'/f'{c["id"]}.csv').open(encoding='utf-8-sig') as f:rows=list(csv.DictReader(f))
    assert [int(x['clip_frame_1based']) for x in rows]==list(range(1,c['frames']+1))
    assert [int(x['recording_frame_1based']) for x in rows]==list(range(c['first'],c['last']+1))
for cid,s in m['sources'].items():
    root=ROOT.parent/s['run']/f'camera{cid}/inputs'
    assert digest(root/f'camera{cid}_original.mp4')==s['source_sha256']
    assert digest(root/f'camera{cid}_frame_map.csv')==s['source_map_sha256']
save(ROOT/'reports/final_validation.json',dict(clips=20,videos=40,selected_frames=6380,files=len(checks),all_hashes_match=True,inclusive_mappings_exact=True,local_sources_preserved=True,windows_copy_performed=False,temporary_ssh_socket_remaining=pathlib.Path('/tmp/codex/ltb1021/20261102-user20-clips/ssh.sock').exists()))
save(ROOT/'reports/visual_check.json',dict(scope='technical label legibility only; no action/event interpretation',samples=[dict(file='camera06_01_fall_F0362-0722_01.png',clip_frame=1,recording_frame=362,text_fits=True),dict(file='camera11_02_fall_F0603-0963_02.png',clip_frame=361,recording_frame=963,text_fits=True)]))
save(ROOT/'reports/helper_fingerprints.json',{str(p.relative_to(ROOT)):digest(p) for p in (ROOT/'helpers').glob('*.py')})
old=(ROOT/'checkpoint.ko.md').read_text()
new=old.replace('단계: 범위·입력 지문 고정 후 CPU 편집·검증.', '단계:20구간 무표시20본/검토본20본 완료, 양 서버 전송 검증 완료.')+'\n- 검증:6380 선택Frame·양 끝 포함·상대PTS/전체 디코딩·SHA256·표본 표시 확인. 원본 보존. 상세 reports 참조. Windows 실제 복사 미실시.\n'
paths=[p for p in (ROOT/'reports').glob('*.json') if not p.name.endswith('_source_probe.json')]+[ROOT/'helpers/finalize.py']
payload={'old_sha256':hashlib.sha256(old.encode()).hexdigest(),'checkpoint':new,'files':{str(p.relative_to(ROOT)):p.read_text() for p in paths}}
code='''import pathlib,hashlib,json,sys
r=pathlib.Path(sys.argv[1]);d=json.load(sys.stdin)
for rel,s in d['files'].items():
 p=r/rel
 if p.exists():assert p.read_text()==s,rel
 else:p.write_text(s)
p=r/'checkpoint.ko.md';assert hashlib.sha256(p.read_bytes()).hexdigest()==d['old_sha256'];p.write_text(d['checkpoint'])
print('FINAL_EVIDENCE_SYNC_OK')
'''
r=run(['python3','-c',code,'/storage/contextra/experiments/action-model-eval/2026/'+ROOT.name],data=json.dumps(payload).encode(),timeout=120)
assert r.returncode==0,r.stderr.decode(errors='replace')
(ROOT/'checkpoint.ko.md').write_text(new)
print(r.stdout.decode(),flush=True)
