from pathlib import Path
import json
import re

root=Path('/tmp/issue-lead-26950-r1/evidence-capture-2')
out=root/'deliverables'
original=Path('/tmp/issue-lead-26950-r1/evidence-capture/evidence.md').read_text()
uploads=json.loads((root/'upload-map.json').read_text())
data=json.loads((out/'comparison-manifest.json').read_text())
def md(name): return uploads[name]['markdown']
def link(name,label=None): return f'[{label or name}]({uploads[name]["url"]})'
def section(text,fixture):
    return re.search(r'^### '+fixture+r' — .*?(?=^### F[1-6] — |^Captured by |\Z)',text,re.M|re.S).group()
before='[6d450a4284](https://git.cafe/pingdotgg/t3code/commit/6d450a4284)'
after='[5c1c8b0004](https://git.cafe/pingdotgg/t3code/commit/5c1c8b0004ee52542418bfc9f22c3a6f07f57b56)'
environment='**Rendering for every capture in this row:** Linux x86_64; T3 preview headless Chrome 156.0.0.0; no device emulation; 1440×900 CSS px; DPR 2; 16px / 100% font scaling; dark; scroll top; default merge-readiness sort; browser Date frozen at 2026-10-29T13:30:00Z. Full-surface PNG 1280×800, original MP4 2880×1800. Main sidebar collapsed on both sides; pointer parked at CSS (1400,850), no hovered controls, body focus. Whole toolbar has the same identity compositor transform on both sides. Reduced-motion emulation is unavailable and remains false.'
notes={f:section(original,f).split('\n\n')[1] for f in ['F2','F4']}
notes['F2']+=' The main after frame and returned frame are now pixel-identical at zero threshold. The independent fresh-database rebuild below also matches at zero threshold.'
notes['F4']+=' The new Diff0 contains **0 Sort/toolbar pixels** and **0 pixels outside the eligible-row and replaced-empty-state areas**. The compositor normalization removes the unrelated paint difference; none is excused by DiffT.'
text=original.replace('[index.md](', '[Original first-round index](', 1).replace('[uploads.md](', '[Original first-round uploads](', 1)
text=re.sub(r'\*\*Additional pixel difference outside the intended list contents:\*\*.*?\n\n', '**F2/F4 recapture:** the main sidebar is collapsed on both sides to remove relative thread ages. The pointer is physically parked at CSS (1400,850) and verified away from every control before each still. The entire toolbar receives the same identity `translateZ(0)` compositor transform on both sides: this removes the four content-dependent Sort-arrow antialias pixels without moving or restyling the control. This is disclosed capture-harness rendering normalization. F1/F3/F5/F6 below are preserved verbatim.\n\n',text,count=1,flags=re.S)
text=text.replace('The after-only returned snapshot also clears the prior Refresh-button hover shading (803 pixels, maximum channel delta 9); the main before/after list pair has matching hover state.', 'At zero threshold, mixed versus returned is **0 pixels**, and the independent fresh-database rebuild is **0 pixels**. No other pixels change outside the count and added-row areas.')
text=text.replace('the four low-level Sort-control pixels are disclosed above.', 'Sort and the entire toolbar are **0 pixels** different at zero threshold; no other pixels change outside the eligible-row and replaced-empty-state areas.')
text=text.replace('No other changed pixels occur outside the listed result/empty-state areas in F1/F2/F5/F6.', 'No other changed pixels occur outside the listed result/empty-state areas in F1/F2/F4/F5/F6.')
text=text.replace('**Reproduction and scripts**', '**Original reproduction and scripts for preserved F1/F3/F5/F6**')
text=text.replace('[Combined capture, RPC and pixel comparison manifest]', '[Original round capture, RPC and pixel comparison manifest]')
for fixture in ['F2','F4']:
    oldsheet=re.search(r'\['+fixture+r'\]\((https://[^)]+)\)',text).group()
    text=text.replace(oldsheet,link(fixture+'-sheet.png',fixture),1)
updated=['**Updated F2/F4 reproduction and scripts**','',*[md(n) for n in ['reproduce.md','seed.sh','start-servers.py','bootstrap-page.js','setup-page.js','instrument.js','harness.js','driver.js','package-evidence.py','compare-rebuild.py','upload-evidence.py','build-index.py']], '',link('comparison-manifest.json','New F2/F4 capture, RPC and pixel comparison manifest'),link('reproducibility-manifest.json','Independent rebuild and unchanged-area pixel audit'),'', '**F2/F4 settling:** fonts and relevant successful RPC replies were awaited; the driver observes fetch/resource inactivity for at least 500ms and pending fetch count zero (the preview API has no global network-idle primitive). Each accepted still has two pixel-identical screenshots at least 500ms apart, no hovered controls and no active animations. All final stills/diffs and recording filmstrips were opened for inspection. The identity toolbar transform changes only the compositor context; no content is hidden, cropped, masked, aligned or repaired in the screenshots.','', '**Independent rebuild:** original after server stopped; a new empty T3 home/database, new paired tab and new synthetic project were created at the same fix SHA. Running bootstrap, setup and driver again rebuilt F2-after-mixed with **0 differing pixels**, maximum channel delta 0. Original and rebuild RGB pixel SHA-256 both `aafccd91ac359b69c4ab059ee61cf7fb67e1feb029fc04c1f1ac9249701fc0d9`. Mixed versus returned is also **0 pixels**.','', '**Diagnostic uploads:** filenames beginning `diagnostic-` preserve rejected candidates and the Sort rendering investigation, separate from the final pairs. All use the same browser/viewport/DPR/font/theme/clock; the earliest F4 candidate has an expanded sidebar and is rejected. `resize`, `sort-cycle` and `cache-reset` candidates retained four toolbar pixels; `isolated-raster` and `toolbar-layer` candidates removed them. The accepted pair uses the latter normalization applied to the whole toolbar before recording.','']
anchor='The timestamps below are seconds from the monotonic sample'
pos=text.index(anchor)
text=text[:pos]+'\n'.join(updated)+'\n'+text[pos:]
for fixture,item in data.items():
    oldsection=section(text,fixture)
    title=oldsection.splitlines()[0]
    lines=[title,'',notes[fixture],'',environment,'','**Scripted steps and timestamps (before | after), above the capture pair:**','', '| Step | Before (s) | After (s) |','| --- | ---: | ---: |']
    actions={side:item['manifests'][side]['final']['actions'] for side in ['before','after']}
    labels=list(dict.fromkeys(a['label'] for side in ['before','after'] for a in actions[side]))
    for label in labels:
        times=[]
        for side in ['before','after']:
            d=item['manifests'][side];found=next((a for a in actions[side] if a['label']==label),None)
            times.append(f'{(found["t"]-d["final"]["recordOffset"])/1000:.1f}' if found else 'unavailable')
        lines.append('| '+label+' | '+' | '.join(times)+' |')
    lines+=['','**Completed query replies:**','','| Side | Time (s) | Query / filters | Answer count |','| --- | ---: | --- | ---: |']
    for side in ['before','after']:
        d=item['manifests'][side];off=d['final']['recordOffset']
        for h in d['host']:
            event=next(e for e in d['final']['log'] if e.get('event')=='response' and abs(e['t']-h['t'])<.01)
            inp=event['input'];desc='`'+inp.get('query','')+'`'+(' / `'+json.dumps(inp['filters'],separators=(',',':'))+'`' if inp.get('filters') else '')
            lines.append(f'| {side} | {(h["t"]-off)/1000:.1f} | {desc} | {h["count"]} |')
    lines+=['',md(fixture+'-before.mp4'),md(fixture+'-after.mp4'),'',link(fixture+'-before-manifest.json','Before RPC/action manifest')+' · '+link(fixture+'-after-manifest.json','After RPC/action manifest'),'','| Checkpoint — web 1440×900, dark | Before | After | Diff0 | DiffT (>16/255) |','| --- | --- | --- | --- | --- |']
    for pair in item['pairs']:
        name=pair['label']
        lines.append(f'| {name} | '+md(f'{fixture}-before-{name}.png')+'<br>'+before+' | '+md(f'{fixture}-after-{name}.png')+'<br>'+after+' | '+md(f'{fixture}-{name}-Diff0.png')+f'<br>{before} → {after}<br>{pair["Diff0"]["pixels"]} pixels | '+md(f'{fixture}-{name}-DiffT.png')+f'<br>{before} → {after}<br>{pair["DiffT"]["pixels"]} pixels |')
    lines+=['',md(fixture+'-sheet.png'),'']
    if fixture=='F2':
        lines+=['**After-only selection checkpoints** (B3 is absent before):','',md('F2-after-detail.png'),'',md('F2-after-returned.png'),'', '**Returned versus main after still:** 0 pixels at zero threshold.','',md('F2-returned-versus-mixed-Diff0.png'),'',md('F2-returned-versus-mixed-DiffT.png'),'','**Independent rebuild — same scripted interaction from a fresh database:**','', '| Step | Rebuilt after (s) |','| --- | ---: |']
        rebuilt=json.loads((out/'rebuild-F2-after-manifest.json').read_text())
        for a in rebuilt['final']['actions']:
            lines.append(f'| {a["label"]} | {(a["t"]-rebuilt["final"]["recordOffset"])/1000:.1f} |')
        lines+=['',md('rebuild-F2-after.mp4'),'',link('rebuild-F2-after-manifest.json','Rebuilt after RPC/action manifest'),'','| Original after | Independently rebuilt after | Diff0 — 0 pixels | DiffT (>16/255) — 0 pixels |','| --- | --- | --- | --- |','| '+md('F2-after-mixed.png')+' | '+md('rebuild-F2-after-mixed.png')+' | '+md('F2-independent-rebuild-Diff0.png')+' | '+md('F2-independent-rebuild-DiffT.png')+' |','']
    lines+=[link(fixture+'-before-filmstrip.png','Before recording inspection sheet')+' · '+link(fixture+'-after-filmstrip.png','After recording inspection sheet'),'','']
    text=text.replace(oldsection,'\n'.join(lines),1)
for fixture in ['F1','F3','F5','F6']:
    assert section(original,fixture)==section(text,fixture),fixture+' was changed'
(root/'evidence.md').write_text(text)
(out/'index.md').write_text(text)
print('Wrote full evidence; preserved F1/F3/F5/F6 verbatim:',len(text),'characters')
