# Desktop update poll proof

Build each commit in its own checkout after `vp i`:

```sh
vp run dist:desktop:artifact --platform linux --target dir --arch x64 --mock-updates --mock-update-server-port 19354
```

Place the uploaded `clock.cjs`, `instrument.cjs`, and `driver.cjs` together in a scratch directory. For each checkout, once, instrument the built package and run it:

```sh
node instrument.cjs "$CHECKOUT" "$CHECKOUT/release-mock/linux-unpacked/t3code"
headless-desktop node driver.cjs "$CHECKOUT" "$CHECKOUT/release-mock/linux-unpacked/t3code" base
```

Use `head` as the last argument for the fixed checkout. Run sequentially because the fixture owns port 19354. Add `actions` after the side label to exercise additional desktop IPC requests during delayed polls.

The instrumentation prepends a clock hook to the packaged boot file. It intercepts only the actual 14,400,000 ms background timer, advances Date.now by that amount, and invokes its stored callback. It does not call the check method or alter updater state. All short timers, network requests, updater events, downloads, IPC and renderer behavior stay real. Both commits get the same hook.

The driver starts the real packaged Linux Electron app on Xvfb, with a fresh T3 home, fresh OS home/config/cache, and an empty database. It skips onboarding, waits for the real 15-second startup check, then records the same interaction at 1200×820 in light theme with reduced motion. No agent turn is required. A local HTTP server supplies latest-linux.yml and a tiny synthetic AppImage payload with a matching SHA-512 checksum. APPIMAGE points to a synthetic current payload so the packaged Linux updater is enabled; no real installation is performed.

Sequence: offer 0.2.0; delay manifests eight seconds; release the four-hour timer; capture Download during the poll; finish the poll; click Download; release the next four-hour timer; capture Install during the poll; finish the poll; change the offered version to 0.3.0; release the next timer; capture the new offer after the response. Each still is saved only after two screenshots 500 ms apart match exactly.

The optional actions run then requests Download through the real desktop bridge during another 0.3.0 poll, and requests Install without an expected version during a poll returning 0.4.0. It records whether each promise is pending during the feed delay and its result after the response. These are IPC requests rather than native confirmation-dialog clicks.

`runtime-evidence.json` records the UI's accessible button label and aria-disabled state, updater status, broadcast deltas, synthetic feed requests, and updater log messages. It excludes startup logs and private environment details. `disabled` is the HTML property; this UI uses `ariaDisabled` for interaction availability.
