# Reproduce the captures

Run seed.sh only when the two named evidence worktrees do not exist. It creates fresh databases at each revision's migration level with T3CODE_DEV_SEED=0. It never reads the live database. Its startup logs are private and must not be uploaded.

Use T3 Code Preview with two new tabs, reuseExistingTab=false, one environment-port target for each web port printed in the respective [dev-runner] line. Pair through the input on /pair using private tokens as described in seed.sh. Select the existing server / New thread. Select Replay (dev) and Showcase in the composer before recording; do not start a provider turn. No custom database rows or provider output are needed.

Run the JavaScript drivers inside functions.exec, whose tools/load/store globals they use. Set beforeTab, afterTab and beforeThreadPath/afterThreadPath to your own tabs and paths. Save the driver.js source in store('driver', source); save stabilize.js source in store('stabilize', source). Use the same Linux browser, en-US locale, UTC timezone, DPR 2 and 100% zoom. Native device emulation is off. The original passing rows use the page clock frozen at 2026-11-10T12:00Z. The replacement F01 stills and B/calendar-detail recordings use the seed-relative clock below; timers run normally. No system time was changed: a local fixed-system-time wrapper was unavailable.

For a reproducible full viewport, read the fresh synthetic thread's `updated_at` after setup using seed-clock.py (read-only access to the two isolated databases). This stopped thread has no messages or runs, so the sidebar activity timestamp is `updated_at`, initially set during seed creation. Store its seed-clock.json output as `seedClocks`. Compute each side's frozen page time as `ceil(Date.parse(updatedAt)/60000)*60000 + 4*3600000`. This is seed activity time plus 4h and at most one minute; the sidebar must show **4h** on both sides. The delivered replacements used before updatedAt 2026-11-10T08:21:56.280Z / frozen 2026-11-10T12:22:00Z, after updatedAt 2026-11-10T08:22:05.471Z / frozen 2026-11-10T12:23:00Z. An absolute noon freeze against a later seed can instead show 3h and change the blurred label.

Run f01.js with the original driver and motion shim loaded. It substitutes the computed frozen time into stabilize.js, waits for the sidebar's minute clock to refresh and visibly show 4h (up to one minute), opens and closes the dialog once through the UI, reopens it, and explicitly sets the complete native time to **13:00**. Retain Nov 10, 2026, Mono16, dark, 1280×800 CSS px / DPR2. A seed on another day must select Nov 10, 2026 explicitly as the dialog date for this historical artifact. Do not change database timestamps or alter the sidebar text. Fonts/network quiet plus pixel-identical samples are still required. Both fresh replacement F01 images match their prior delivered images exactly over the full viewport; the head dialog region and full viewport deltas are both zero.

For the narrow fix round, copy the accepted original recording-timelines.json into store('recordingTimelines') and replay only sessions B and A-calendar-detail on each side. sessions.js retains the same interaction sequence; it logs existing keyframe states instead of recapturing passing stills, pauses at the Settings destination, and waits 2200ms after the final settle following Cancel. It then checks that no custom dialog exists, moves the pointer across empty page space with a further 1.8s hold and 0.6s final hold, and stops. These pointer moves force fresh encoder paints during the idle dismissed state; they do not change app state. The final B clips include a 1.6s destination hold. The replacements' initial date-mode time follows their frozen clocks (13:22 before / 13:23 after); F01 is explicitly 13:00 and calendar-detail sets 15:30. The retained F07/F08/F05 stills remain the earlier accepted captures. Run review-recordings.py followed by final-checks.py; open every new final frame and set visuallyInspected only after inspection. The old calibration A clips are retained only as historical aids and are not dismissal evidence. Preview has no native reduced-motion switch, so stabilize.js supplies a matchMedia page shim plus zero animation/transition CSS and hides carets. It does not override dialog dimensions. Apply it before opening either dialog. Reapply after a full page navigation.

The capture driver creates a new timestamped run directory when captureRunDir has not been set; for this fix round set it to the timestamped capture-2 run directory. Clear that store key between runs. A fresh Python virtual environment with Pillow must be available at the original capture/pyenv/bin/python (python3 -m venv, then pip install Pillow). The session driver replays the successful before-side UI path for both revisions; recording-timelines.json holds the actual individual before/after timestamps captured in this run. Original recordings contain pauses for metadata inspection, so they are not frame-synchronized. Each state is reached by the same UI actions; compare settled stills rather than aligned video timecodes. Time fields use the native value setter plus input/change events, not a claim of simulated physical keystrokes.

capture() waits for loaded fonts and 500ms without new resource entries, takes whole-viewport PNGs 500ms apart, and accepts only pixel-identical pairs. Persistent WebSocket connections are not treated as unfinished navigation. It stores the two original samples, accepted frame and geometry/environment JSON. No masks, crops, width overrides or image retouching are used.

Run diff.py with the new run directory as argument to regenerate zero-threshold and >16/255 max RGB-channel difference masks. All changed pixels are amplified to solid magenta, unchanged pixels black. review-recordings.py decodes every clip and samples timestamps into contact sheets; its root currently names this evidence run and can be changed for a new one.

Run seed.sh in a retained terminal session; its final wait keeps the captured background server processes alive. Read only the [dev-runner] port lines from private logs. After review, close your two tabs. Stop only your captured processes or verified port owners after checking /proc/<pid>/cwd lies in your checkout. The wrapper PID may exit without stopping its children; check the actual ports. Remove only the two worktrees you created. Do not upload private startup logs, pairing tokens, real userdata, or runtime model identifiers.

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