# Gap capture reproduction

Extends the [round-one guide](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/e2ade6adee0a4040/REPRODUCE.md). Synthetic data only; no live userdata. AI-assisted; verified with the tests and tools listed above.

Use the uploaded seed, seed-agent, RPC, freeze-clock, pairing and capture scripts from this round. ROOT defaults to the directory containing each JS script, overridable by EVIDENCE_ROOT. EVIDENCE_AFTER_PORT and EVIDENCE_BEFORE_PORT override 7856 and 8524; the pairing helper also accepts EVIDENCE_WEB_PORT. Check the actual dev-runner ports. Playwright 1.60.0 imports from the after checkout's installed dependency.

1. Create the before worktree at the supplied merge base and run `vp install` there. Confirm the after checkout is the supplied head and has no pre-existing `.t3` before creating isolated state.
2. Start each checkout with `T3CODE_DEV_SEED=0 NODE_OPTIONS=--import=<scratch>/freeze-clock.mjs vp run dev`, capturing its launch PID and private startup log `server-<side>-fixed.log`. No VITE origin overrides; no migration or live data copying.
3. Run `node pair-bootstrap.mjs <side>` and then `node seed.mjs <side>`. The seed uses side-specific thread IDs to avoid cross-environment process-scope collisions; user/assistant text, role and createdAt are identical. Run seed sequentially. Keep startup logs and auth JSON private.
4. Run `node capture.mjs before R04bottom,R04assistant,R07,R13pointer,R05a,R05b` and the same after. Each run gets a timestamped directory. The canonical retained files are named by selected-manifest.json.
5. R04bottom starts turn-1's user element 4px outside the scroll viewport bottom, wheels +8/-8/+8, then Next and Previous. A text-only observation overlay states actual coordinates, current/neighbor selections, ticks and distance to max; it reads the current React tree without changing app state. The bottom edge lies under the composer, which is retained. No claim is made that the covered user bubble is visually readable.
6. R04assistant places the view 350px after aligned turn-1, with only assistant text visible. It presses Next, restores the same start, then presses Previous. R07 preselects penultimate turn-3 during setup using the rail's keyboard selection, then recording contains Next only, including a disabled attempt. It never wheels to reveal the terminal message. Its endpoint remains 180px before maximum scroll on both revisions.
7. R13pointer pointer-clicks pair-a's tick (index 3/6), then presses Next twice and Previous twice. R05 keeps round one's explicitly labelled fractional list-state/DPR2 harness; only the badge border radius changes to zero, identically on both sides, to eliminate the unrelated raster pixels. The 25.5px pair must be byte/pixel identical.
8. Use the scratch venv's Python with Pillow: `verify-seed.py`, `assemble.py`, `audit-captures.py`, `narrate.py`, `review-videos.py`. Assemble selects the latest complete pair for each scene. Diff0 is ImageMagick AE/fuzz0%, every changed pixel amplified red; DiffT uses fuzz2%. Raw screenshots remain full 1440x900, screenshot scale CSS; the app renders at DPR1 except the preserved DPR2 boundary harness.
9. Narrated videos retain the full viewport and add a 100px caption band below it (encoded 1440x1000). Speech is synthetic local libflite narration; captions show exact settled-observation timestamps and state. Raw recordings and exact clock/interaction files are retained too. Narration does not expose any operational runtime model identifiers.
10. Upload selected captures, masks, recordings and changed scripts with `ghdrop upload -m`. Keep auth states/startup logs out of uploads. Stop tracked launch PIDs and descendants, verify port owners' cwd before stopping leftovers, remove the before worktree and the after `.t3` created by this task. No PR body edit.
