# PR comment link evidence, second pass

AI-assisted; verified with the tests and tools listed above.

The capture functions are helpers for the T3 Browser panel tool runtime, not a standalone Node program. `tools`, `store`, and `load` are supplied by that runtime. `preview-driver.mjs` contains the shared capture function; `preview-rows.mjs` adds the plain/non-comment and wheel steps. The evidence section records the actual UTC invocation times for each run.

Use detached checkouts at the requested base and head. Install dependencies with `vp install`. Start only one server at a time with `T3CODE_DEV_SEED=0 vp run dev`. Wait for Listening/authentication readiness before `seed.sh`; invoke the script once per fresh database. The Replay fixture contains only synthetic conversation content and public links. No installed T3 database is a seed. If rerunning, retain only the database created by that revision's own server or start fresh and seed again.

Pair an owned Browser panel tab using the server's startup URL; never publish that URL or token. Resize to 1440 by 900 CSS pixels and verify `innerWidth`, `innerHeight`, `devicePixelRatio`, and the theme class. Expand the synthetic prompt and close thread details. Use Settings > Appearance > Light or Dark; confirm the document class is empty for light or `dark` for dark. Default theme, interface 16 px, monospace 13 px. Move the pointer into blank conversation space before recording.

Warm the public PR Summary once and wait for the host refresh to finish. Close the PR tab before F07, F02, F01, and F29. For F17, start with no selected comment, Summary open, wheel down 220 from the top and verify scrollTop 142 after the header compacts. For F16, start from that same neutral panel state and choose Code; leave all three file rows collapsed. The PR panel is 540 CSS pixels wide.

All recorded link activations use the conversation anchor's DOM `.click()` through its existing React handler. This avoids the hover preview popover that obscured discarded pointer-click takes. This is handler-path evidence, not proof of trusted pointer targeting. F29 uses a Browser panel wheel action on the Summary scroller. Do not modify CSS, content, or data to force the result.

Set `tab`, `runBefore`, and `runAfter` in the tool runtime store. Call the capture helper with row, side, and the appropriate conversation anchor selector. The helper records, activates, waits, probes focus/geometry/scroll/theme, takes two stills separated by at least 500 ms, and saves to a new timestamped directory. F29 also saves a stable pre-wheel pair as `-baseline-a.png` and `-baseline-b.png` alongside its take. Originals remain private. Inspect all decoded frames; reject transient previews, loading spinners, skeletons, overlays, wrong theme/size, and ghosting. Warm immediately before the dark take to avoid a stale-cache refresh during recording.

`process.py` uses Pillow and ffmpeg. It asserts original still-pair pixel equality before applying privacy masks. F02 masks CSS (915,195)-(1440,539); F01/F16 mask (915,550)-(1440,900), identically on both sides and throughout each recording. These opaque gray rectangles suppress a neighboring public comment's private operational attribution; they also cover some unrelated content. The target cards stay visible. No other visual content is edited. Videos preserve frame timestamps and counts. Diff0 is absolute RGB difference with gain 8 and threshold 0; DiffT is white where the maximum raw channel difference exceeds 16/255, black elsewhere. F29 diffs compare pre-wheel/post-wheel on the head only.

Review every current contact-sheet frame listed in capture-metadata.json and all final stills/diffs. `upload.py` uploads only its explicit public manifest with `ghdrop upload -m`, preserves stdout verbatim, and archives current frame sheets. It excludes rejected takes, private source recordings, pairing material, databases, and server logs. `report.py` builds Evidence.md from those immutable upload links. Upload Evidence.md separately after review. Stop tracked server sessions, close owned preview tabs, remove the two capture checkouts, then remove the literal scratch directory after uploads succeed. Nothing is committed.
