# Visual proof procedure

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

Environment for every capture: Linux web development client in the shared preview Chromium browser, CSS viewport 1280x800, light theme. Separate checkouts at the recorded base and head commits; each server creates its own fresh migration-compatible database with T3CODE_DEV_SEED=0. No production database is seeded or opened.

## Cursor absent from the instance catalog

Run proxy.mjs separately for each server on separate loopback ports. Set CURSOR_BACKEND_URL to that proxy for the server process. The first discovery response contains the first six real catalog entries; subsequent SDK discovery and execution traffic goes to the real Cursor services. This makes an authentic runnable model absent from the app instance's catalog without mocking turns. The proxy also replaces the account label with Evidence.

Create a synthetic project through the CLI/RPC, rooted in a fresh git repository owned by this checkout. Enable the Cursor provider using server.updateSettings. Pass installProof({projectId, storedModel}) the project id and a privately obtained, runnable Cursor catalog identifier outside the six retained entries, with medium effort support. Runtime identifiers and credentials are intentionally absent from this public seed.

Evaluate driver.js in the authenticated application page, call installProof with those private inputs, then seedPrimary(). The thread.create command uses agent/MCP creation metadata and stores medium effort.

Using the real browser pointer and keyboard: open Cursor stored selection in the sidebar; close thread details; open the composer model picker without entering search text; capture. Dismiss with Escape. Type `Reply with exactly: Selection preserved. Do not use tools.` and press Enter. Wait for the real turn to complete, then capture the completed conversation and composer. Open the model picker, click the checked displayed model, and inspect the persisted thread using proofRead(primaryId).

On both sides the provider turn completed. The base stored a replacement model with no effort options. The head retained the original model and [{id: effort, value: medium}]. A later catalog refresh exposed the full live catalog; this does not change the persisted selection comparison.

For the reopening capture, restart each server and its discovery proxy with the same six-entry fixture, reopen the completed thread, open the full unfiltered picker, capture, and re-pick the checked row. The completed conversation and unavailable stored selection are visible together on the head; the base remains Auto with No effort levels. This restart is an explicit additional persistence check, not a hidden continuation of the original recording.

## Available model re-picking

Enable Codex, Claude, Cursor, OpenCode, Grok and Pi through the settings RPC. Run installProof again after catalog discovery, then seedProviderRepicks(). Each thread stores a real catalog model with a nondefault option: medium for Cursor, high for the others. For each thread, use a real pointer to open its model picker, capture the initial trait checkmark, click the already-checked model row, reopen the picker, and capture the trait checkmark again. Read the persisted selection with proofRead. This is an independent initial state for the re-pick defect; it does not inherit effort lost while opening an unavailable model.

Base: Cursor medium -> default high; Codex high -> default low; Claude high -> default medium; OpenCode high -> no selected variant / Unknown; Grok high -> default low; Pi high -> no selected thinking level. Persisted options were absent for all six. Head: every stored option and model was retained. Each comparison image stacks the initial and re-picked full application screenshots with labels. Recordings show the same interaction sequence on both commits.

The extra native-agent and Kiro picker attempts exposed no selectable model row and therefore do not verify that handler. Antigravity and Muse had no catalog entries. Replay has no model options and was not substituted for the required real Cursor execution.

## Failed save retry

On the head, create a Codex thread with high effort. Run failNextModelSave(). Pick a different catalog model with the real pointer. The first outgoing model-save request is changed to a synthetic nonexistent thread id, causing a real server failure and the app's Could not apply model selection toast. The displayed draft remains selected. Reopen the picker and click that checked draft model again. Exactly two model-save requests were observed: one injected failure and one successful retry; proofRead confirmed that the new model was persisted. Restore WebSocket.prototype.send=realSend. The recording captures the error and re-pick. This is fault injection for the generic save path, not a claim of a separate base regression.

## Capture handling

All stills were accepted only after two screenshots 500 ms apart compared byte-identical. Model names are replaced in presentation with neutral labels by a MutationObserver; underlying selections, requests, and provider execution are untouched. Neutral catalog numbering reflects list position. The stored identifier is shown as Stored model where applicable. The recorded machine/account label is synthetic Evidence. Full application images are otherwise unchanged; comparison images only add headers and stack frames.

Every uploaded image and recording was opened for visual inspection (recordings inspected through sampled frames). No tests serve as evidence.
