# Desktop wheel evidence

Environment: Linux x86_64, Electron 44.10.1 under headless-desktop/Xvfb, 1280×900, light theme. Each commit was installed, built and run from its own worktree using `T3CODE_DEV_SEED=0 vp run dev:desktop`, with independent fresh worktree databases and independent `XDG_CONFIG_HOME` profiles in scratch. No live database or imported history was used. The desktop launcher selected --no-sandbox. Wheel input is actual X11 input via xdotool, not dispatched DOM WheelEvents. No physical mouse or trackpad was attached.

Before: d313b2aff31991ab94c8ac80cdc38a54dd575604.
After: 59391014313b83838ce9e0a1424f54125dbf39a9.

The main seed adds an empty synthetic Git project, enters Draft A, creates Draft B, saves both drafts by switching between them, and explicitly closes the details panel. Main starting PNGs are byte-identical (SHA256 5b04090667e6328399f11b032fab7aabc92f3df95ef63ef90efd706bcec3301c). Both recordings execute driver.cjs capture.

Main sequence:
- Start Draft B, 100% zoom; vertical wheel ×4 over chat.
- Horizontal left wheel ×1 over chat, reset B, then ×1 over sidebar.
- Reset B, use the app's Back button to A, then horizontal right wheel ×1 over chat.
- Reset B and increase actual Electron zoom to 120% with two native Ctrl+Plus steps. Horizontal left wheel ×2 over chat, reset B, then ×2 over sidebar.
- Reset zoom and B, then inject back and forward continuous scrolls using Chromium's Input.synthesizeScrollGesture (gestureSourceType mouse, distance 200, speed 65, preventFling true). These produce trusted fine-grained wheel events and Electron scroll begin/end events; they are trackpad-style simulation, not physical trackpad proof.
- Return B and close details. Initial and final PNGs are taken only after two captures 500ms apart match exactly.

At 100%, X11 wheel notches produce deltaX ±120 and legacy wheelDeltaX ∓120. At 120%, they produce deltaX ±100 and legacy wheelDeltaX ∓99. Base navigates; head keeps the current draft. Both builds navigate and show the arrow during the injected continuous back/forward scrolls. Vertical wheel input keeps the draft on both.

Edge fixture: fixture.cjs adds and commits synthetic wide.txt with eight long rows, then changes sample data to updated data. edge-seed.js creates a stopped server thread via the app's authenticated RPC, without starting a provider or agent. Its model-selection placeholder is synthetic and never executed. The app's real Changes diff is opened, expanded and unwrapped. edge-capture.js uses xdotool over the actual shadow-root CODE scroller. Each reset explicitly restores expanded, unwrapped state.

Edge sequence:
- At 100%, start offset 240: one left notch →120; a second →0; a third at the edge.
- Restore the Wide diff thread, expand and unwrap; set actual zoom 120%, offset 200: two left notches →0, then two more at the edge.
- Base stays in the diff while scrolling inside it, then navigates to Draft B at either edge. Head scrolls normally inside the diff and stays in Wide diff at either edge.

Edge starting PNGs are byte-identical (SHA256 37c0b8c45bcbbb147d4c0841471479f2c841decde5354c158b0f20c382e09c8c).

Capture annotations show environment, scripted input and observed wheel deltas. The model selector is hidden for privacy on both builds; relative sidebar timestamps are also hidden in the edge pair. No navigation, scroll or gesture logic is patched. Input samples and actual destinations are included in observations.json. Recordings were inspected using extracted full-frame contact sheets; selected frame sequences were reviewed for the transitions and arrow.

## Driver invocation

Set EVIDENCE_DIR to a private scratch directory. Set CHECKOUT to the worktree under inspection, SIDE to base or head, and CDP to its Electron debugging port (9334 for base, 9333 for head). Start each app with a separate XDG_CONFIG_HOME. Inside the headless-desktop session, save DISPLAY and XAUTHORITY to `$EVIDENCE_DIR/$SIDE-display` and `$EVIDENCE_DIR/$SIDE-xauth` so xdotool and ffmpeg target the correct app.

With the fresh app on its welcome page:

```
node driver.cjs seed
node driver.cjs capture
```

After both main captures, run fixture.cjs once for the shared synthetic project, then on each side:

```
node action.cjs edge-seed.js
node action.cjs edge-capture.js
```

All driver output directories are timestamped. No tests are used as evidence.

Unverified: macOS, physical MX Master/Logitech thumb-wheel behavior, physical two-finger trackpad swipes and momentum, and zoom levels other than 100% and 120%. The VM has no macOS or physical input devices and remote machines were outside this task's authorized environment. The injected continuous-scroll recordings establish the app path only; they do not establish physical macOS behavior.

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