Environment for all UI captures: Linux x64, real packaged Electron AppImage under headless-desktop, 1280x900 app window, light theme. Fresh isolated desktop state on each side; Local environment disabled. Real separately paired systemd user service, initially t3@0.1.7, maintenance permission allowed, synthetic display label "Update service". No production database was seeded or accessed. Published desktop/CLI target: 0.1.8. Both worktree builds use app version 0.1.7 to receive the identical update offer. Base source: 44ebb2fe57465d32f2bd07c5eb3d8e871bdf5ed5 Head source: 0fe927a81f79255cec8b567208e38b110eb068c8 Build each source in its own checkout: GITHUB_REPOSITORY=pingdotgg/t3code vp run dist:desktop:artifact --platform linux --target AppImage --build-version 0.1.7 --output-dir /-release The launch driver starts the AppImage with Local environment off and 1280x900 bounds. Invoke it under headless-desktop with EVIDENCE_ROOT, EVIDENCE_SIDE, EVIDENCE_RUN, EVIDENCE_CDP and optional EVIDENCE_APP. Put XDG_CONFIG_HOME and XDG_DATA_HOME under that run directory before invoking headless-desktop, so its unlocked keyring uses the same isolated state. The launcher keeps the virtual display alive for updater-controlled relaunch. The temporary Linux user t3-evidence-31559 has a separate systemd user manager, with HOME at EVIDENCE_ROOT/service-user. The public 0.1.7 Linux CLI archive is extracted at EVIDENCE_ROOT/t3-0.1.7-linux-x64. Install its actual background service under service-user/service, using t3 service install --base-dir . It must be running at 0.1.7 before each comparison. The captured base run did not update it, so the head run began with the same 0.1.7 service. PLAYWRIGHT_MODULE points to the checkout's apps/desktop/node_modules/playwright-core. action.cjs connects to the exact launched Electron CDP port. Run action.cjs seed.js once for each fresh desktop. It pairs through the UI, then uses the real desktop connection-catalog bridge to assign a synthetic display label without changing permissions, version, capabilities, or update state. It opens the actual permission list to verify maintenance access. Tokens are read in memory and never uploaded. Run action.cjs record.js on each side. The identical driver opens Environments and its permissions, then About, clicks Download, accepts Update when that confirmation is offered, otherwise waits for Install and accepts its app-only confirmation. It records the actual X11 window with ffmpeg, then allows real installation and relaunch. No updater, RPC response, provider, or bridge method is mocked. After relaunch, capture-after.py opens Settings, searches About, chooses Version and waits for two full-display screenshots 500 ms apart to match exactly before saving a crop of the About version section. Confirmation stills similarly require two identical screenshots 500 ms apart. Service status files are direct output from t3 status --base-dir , invoked as the temporary service user. Privacy: the unrelated local CLI-install path is blurred in the renderer and additionally masked in the exported videos. The head recording also masks only the filesystem log path in the optional provider-update failure toast. The error and its exit code remain visible. A provider CLI update was automatically offered by the existing combined updater; it failed with npm exit code 243 under the isolated user, while the server and desktop successfully reached 0.1.8. No claim of successful provider updating is made. Observations: base downloaded/installed/relaunched only the app (0.1.8), leaving service at 0.1.7. Head showed "Update 2 machines?" with This app and Update service, then both reached 0.1.8. The transient result toast said the service was still restarting; t3 status was checked afterward and reported installed t3@0.1.8. AI-assisted; verified with the tests and tools listed above.