#!/usr/bin/env python3
"""Compact the accepted evidence, preserving all accepted still and diff links."""
import json,re,sys
from pathlib import Path
root=Path('/tmp/lead-28684-r1/evidence-capture-2');run=root/'2026-11-02T22-50-00Z'
original=Path('/tmp/lead-28684-r1/evidence-capture/evidence.md').read_text()
urls=json.loads((run/'upload-map.json').read_text())
link=lambda name: f'[{name}]({urls[name]})'
old=original.splitlines();out=old[:old.index('**Row 03**')]
out += ['| Row · viewport · theme · state | Before<br>[60aec28a9c](https://github.com/pingdotgg/t3code/commit/60aec28a9c6fdb7417a7382ec094ccc4984d0738) | After<br>[7c0cf8340c](https://github.com/pingdotgg/t3code/commit/7c0cf8340c03829333d4f12eb59d021529283e7f) | Diff0 · [60aec28a9c](https://github.com/pingdotgg/t3code/commit/60aec28a9c6fdb7417a7382ec094ccc4984d0738) → [7c0cf8340c](https://github.com/pingdotgg/t3code/commit/7c0cf8340c03829333d4f12eb59d021529283e7f) | DiffT 16/255 · [60aec28a9c](https://github.com/pingdotgg/t3code/commit/60aec28a9c6fdb7417a7382ec094ccc4984d0738) → [7c0cf8340c](https://github.com/pingdotgg/t3code/commit/7c0cf8340c03829333d4f12eb59d021529283e7f) |','|---|---|---|---|---|']
row=None
for line in old:
 m=re.match(r'\*\*Row (\d+)',line)
 if m:row=m.group(1)
 if line.startswith('| ') and ('![before-' in line or line.startswith('| N/A:')):
  if row=='24':
   images=re.findall(r'!\[[^]]*\]\([^)]+\)',line)
   for label,im in zip(['B starts at four','A resets to four'],images):out.append(f'| 24 · 1440×1000 · dark · {label} | N/A: no paging on base | {im} | N/A | N/A |')
  else:out.append(line.replace('| ',f'| {row} · ',1))
out += ['','Replacement recordings: timestamped lossless PNG capture (≥10 fps), encoded with `libx264 -crf 0 -preset slow -tune stillimage -pix_fmt yuv444p`, 10 fps. Every decoded frame compared with its mapped source PNG; maximum RGB delta below is conversion-only. Accepted stills/diffs above are unchanged. Absent base controls are skipped, never replaced by server clicks.','', '| Recording · rows | Narrated timestamps (seconds) | Max RGB delta | Step contact sheet |','|---|---|---|---|']
for side,scenario,rows in [('before','paging-dark','10/11/12'),('after','paging-dark','10/11/12'),('before','short-dark','13'),('after','short-dark','13'),('before','floating-dark','14'),('after','floating-dark','14'),('after','switch-dark','24')]:
 name=f'{side}-{scenario}';report=json.loads(Path(json.loads((run/'selected-runs.json').read_text())[name],'verification.json').read_text())
 steps=['0s start']
 for step in report['narratedSteps']:
  if step['action'].startswith('request '):steps.append(f"{step['timeMs']/1000:.2f}s {step['action'][8:]}")
 notes='; base remains at ten' if side=='before' and scenario=='paging-dark' else '; base compact, no Servers section' if side=='before' else '; A eight → B four/Show 1 more → A four/Show 4 more' if scenario=='switch-dark' else ''
 out.append(f"| {link(name+'.mp4')} · {rows} | {'; '.join(steps)}{notes} | {report['maxRgbDelta']}/255 | {link(name+'-contact-sheet.png')} |")
out += ['','Verification: '+link('verification-summary.json')+' · '+link('recordings.json')+' · '+link('rebuild-recordings.md')+'.','']
scripts=next(x for x in old if x.startswith('Scripts and provenance:'))
for name in ['rpc-driver.mjs','browser-driver.mjs','control.py','capture-driver.mjs']:
 scripts=re.sub(r'\['+re.escape(name)+r'\]\([^)]+\)',link(name),scripts)
scripts+=' · '+' · '.join(link(x) for x in ['run-redo.py','encode-verify.py','bootstrap.py','build-evidence.py','package-evidence.py'])
out += [scripts]
metadata=next(x for x in old if x.startswith('[Rebuild instructions]'))
metadata=re.sub(r'\[Recording timestamps\]\([^)]+\)',link('recordings.json'),metadata)
out+=[metadata]
text='\n'.join(out)+'\n'
# All existing accepted still/diff image URLs must be retained byte-for-byte.
assert sorted(re.findall(r'!\[[^]]*\]\([^)]+\)',original))==sorted(re.findall(r'!\[[^]]*\]\([^)]+\)',text))
assert len(out)<=60,len(out)
(root/'evidence.md').write_text(text)
print('evidence lines:',len(out))
