# Rebuild the typography evidence

These scratch drivers capture the real app; no production files are modified. All data is synthetic. No existing T3 database is used. Original comparison: before be5a887b939dadf74e62a477bbe2c805d561fe9e, after ab17d3b8b1295170213b7537dddcf00dadee7708.

1. Place the current drivers together in `/tmp/lead-27909-r1/capture/`. `common.cjs` defines checkout paths, origins, the exact D sample, and fixed client clock. Adapt paths/ports there if needed. Downloaded `*-prior.cjs` files are provenance only; do not execute them.
2. Create the base worktree with `git -C /home/ubuntu/t3code worktree add --detach /home/ubuntu/wt/pr-27909-base be5a887b939dadf74e62a477bbe2c805d561fe9e` and run `vp install` in it. The after worktree must be at the stated head with dependencies installed.
3. In each checkout launch `T3CODE_DEV_SEED=0 vp run dev`, retaining the exact spawned PID. Save its output to `before.log` or `after.log` in the scratch directory. Read actual web ports from the dev-runner output and update `common.cjs` origins (this run: before 6636, after 6236). Never seed from the live install, set VITE origins, or reuse another build's database. Use fresh client profiles/preferences for B.
4. Run `node fixture.cjs`, then `node seed.cjs before` and `node seed.cjs after`. These choose the available Replay model from each running instance, create deferred synthetic messages via RPC, and stop them before execution. Run `node reseed.cjs` once with both servers ready to create the final matched `*-r1` threads. Concurrent creation keeps the visible narrow-screen message timestamp in the same minute. Check timestamps in frames; retake if they differ.
5. Run `node capture.cjs before` and `node capture.cjs after`. B runs first on untouched font preferences; subsequent rows use explicit Inter and Q separate fonts. Real Markdown clipboard paste creates D. The driver expands D's sent control, captures top/bottom scroll positions, and anchors Q typography consistently. `supplement.cjs` supports targeted D/Q retakes (`SUPPLEMENT_MODE=D` or `Q`); `RECAPTURE=1` avoids replacing B after preferences have changed. Every still requires network idle, loaded fonts, reduced motion, and two pixel-identical frames 500 ms apart. Captures are in new timestamped directories.
6. Run `node record.cjs before` and `node record.cjs after`. The recording thread must have only its original stopped sent message. The driver records both ASCII arrow sequences, eight left-arrow caret moves, one-hyphen selection, replacement/deletion/restoration, copy and Enter send. Clipboard and sent text are asserted exactly. It captures ~10 fps full surfaces and encodes H.264 MP4 with ffmpeg. Timing JSON records actual action and frame timestamps; Replay is stopped immediately after sending.
7. Build desktop separately in each checkout with `vp run --filter @t3tools/desktop build`; in each `apps/desktop`, run `node node_modules/electron/install.js` if Electron has not been fetched. Run `headless-desktop node /tmp/lead-27909-r1/capture/desktop.cjs before` and the matching after invocation. Each launches that checkout's Electron app/bundled backend with fresh timestamped XDG/T3 homes, seeds its own server via RPC, and captures the whole 1440×1000 window using ImageMagick import on Xvfb. The app is closed in finally. Default fonts are required; explicit Inter via Settings is optional and its failure is recorded. `inspect-desktop.cjs` is a diagnostic only, not a capture prerequisite.
8. Run `python3 diff.py`, then `python3 assemble.py` and `python3 review.py`. `diff.py` selects latest valid row captures (preserving first untouched B), emits raw pair paths in `pairs.json`, full-surface zero/16-channel-threshold diffs, and SHA-labelled sheets. Verify selected inputs before accepting output. `assemble.py` makes additional D crops, collates environment metadata, and rejects any changed pixel outside the composer/preview. `review.py` makes recording contact sheets and ffprobe metadata. Inspect every retained raw image, diff, sheet and recording; discard or retake visibly unsettled/mismatched frames.
9. `upload.py` uploads only explicitly selected synthetic assets/scripts using `ghdrop upload -m`. It excludes auth, runtime databases, app logs, rejected captures and private PR data, retaining stdout verbatim in `uploads.md` and a filename/URL map in `upload-map.json`. `evidence-builder.py` builds the compact PR-body section from that map. Upload the resulting evidence and manifest separately. Do not edit the PR body automatically.
10. Stop the tracked web processes, verify your ports are no longer listening, and remove only the extra base checkout with `git -C /home/ubuntu/t3code worktree remove --force /home/ubuntu/wt/pr-27909-base`. Leave the lead-owned after checkout and scratch evidence in place. Never kill by pattern.

Run-specific notes: Ubuntu 24.04.5 x86_64; Playwright 1.60.0 / Chromium 148.0.7778.96; Electron 44.10.0 / Chromium 152.0.7977.169. DPR/zoom/font scaling 1/100%/100%. Browser narrow rows use mobile+touch emulation, not native mobile. Desktop uses `--no-sandbox --disable-gpu --force-device-scale-factor=1`. Client clock is fixed to 2026-11-03T04:00:00Z after desktop bootstrap to avoid auth proof clock skew. D's skill source remains literal under Replay; the stock P/Q previews supply the resolved skill chip. Code font is Liberation Mono, not a ligating code-font sentinel.
