# D01 desktop capture reproduction

Use before 7171fdd7716b05dc1b4be40c26ac78e8bb35f80c and after 4a337eb0fce6f4bfdbe84ca465a4982613c5d421 in separate checkouts. Do not edit tracked files.

Install dependencies with `vp install`. In each checkout's `apps/desktop`, run `node node_modules/electron/install.js` and `vp pack`. In `apps/server`, run `vp pack`. Direct packing avoids the full desktop build's web production build dependency. The standard desktop dev watcher invokes pattern-based cleanup; direct launch avoids that.

Allocate a fresh timestamped run directory under `/tmp/lead-33038-r1/capture-3/`. Set T3CODE_HOME to its `home` directory, T3CODE_DEV_SEED=0, and isolated XDG_CONFIG_HOME/XDG_DATA_HOME directories. No live data is copied. Before launching, create `home/userdata/settings.json` with a `devReplay` acpRegistry provider instance: displayName `Replay (dev)`, config source `local`, commandPath the installed Node binary, commandArgs containing the checkout's `apps/server/scripts/dev-replay-agent.ts`.

Run `vp dev --host 127.0.0.1 --port <web-port> --strictPort` from apps/web, with PORT set to web-port. Run the checkout's Electron binary under `headless-desktop`, with `--no-sandbox --disable-gpu --remote-debugging-port=<debug-port>` and the absolute `apps/desktop/dist-electron/main.cjs` entry. Set VITE_DEV_SERVER_URL to the web origin and T3CODE_PORT to a separate backend port. Unset ELECTRON_RUN_AS_NODE, VITE_HTTP_URL, VITE_WS_URL, T3_SERVICE_LAUNCHER_CONTEXT, and T3_BOOT_SERVICE_UNIT. Capture every spawned PID. Use distinct ports per side.

Seed using `bash seed.sh <checkout> <home> <run-dir>`. This uses project/thread CLI commands and the free Replay multi-turn scenario for all nine turns. No DOM message injection or paid agent turn.

Connect playwright-core chromium.connectOverCDP to the debug port. The renderer URL is t3code-dev://app/. Close/hide auto-opened Developer Tools windows. Read environmentId from the backend's /.well-known/t3/environment endpoint; navigate the renderer hash to /<environmentId>/<threadId>. Use the app's useTheme module to select light appearance. Close the main sidebar, close the right surface panel, and leave the thread details card as captured. Resize the real Electron window with xdotool to 1440x900 at 0,0. Electron does not implement Browser.getWindowForTarget.

The retained capture-clean.cjs uses the app's actual right panel store to close it, freezes the renderer clock, blurs the composer, awaits fonts, positions the actual scroll container at bottom, and sends CDP pointer motion to the Next button center. Its process configuration JSON holds each side's CDP port, run directory, and Xvfb DISPLAY/XAUTHORITY; read DISPLAY/XAUTHORITY from the owned desktop child's environment. It creates a new timestamped capture directory each run.

Capture with ImageMagick import -window root, twice at least 500ms apart. The helper initially starts Xvfb at 1920x1080; the final root framebuffer captures are 1440x900, matching the Electron window without cropping or scaling. Retained pair has 0 changed pixels per settle comparison. diffs.py creates Diff0 (absolute RGB difference times 255, saturated) and DiffT8 (grayscale difference >8/255). Inspect all retained frames and diffs before uploading.

Reject exploratory frames with Developer Tools or the wrong active panel. Stop only captured processes/process groups, verify all six owned ports are closed, and remove only the temporary before worktree. No tracked edits or PR-body changes.
