# Real-app Cursor catalog proof

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

## Environment

Linux, real Node T3 server and Vite web client, Chromium in T3's Browser panel; light theme; viewport 1280x800 CSS pixels, device scale 2. Full 2560x1600 raw frames were uniformly downsampled to 1280x800, with no crop, masking, compositing, or content edits. Before each still, two raw screenshots at least 500 ms apart had identical SHA-256. Original captures were inspected before upload.

Base c90b67859a6d85fc957f9ffe25ba95113c6479d3; head 74be63fe48a6f8483e32e5c4e7502b053a7ed067. Each checkout was installed with `vp i` and ran its own fresh T3 home with `T3CODE_DEV_SEED=0`; no live database was copied. Application sources were unmodified.

This is a controlled HTTP-boundary reproduction, not an actual switch between two paid Cursor accounts. `CURSOR_BACKEND_URL` points the real Cursor catalog reader at the uploaded synthetic service. `/v1/me` and `/v1/models` use the real response schemas. Generic synthetic names deliberately replace account/model identities. Discovery, provider registry merging, durable catalog cache, WebSocket delivery, Settings and composer picker are all real app code. No replay turn or paid provider turn was needed. The scenario guide excludes provider-specific behavior, so this used the manual path.

## Setup

Choose an empty scratch directory as `$EVIDENCE_ROOT` and use one checkout per commit.

```sh
python3 seed-isolated-homes.py "$EVIDENCE_ROOT"
printf large > "$EVIDENCE_ROOT/mode"
python3 synthetic-catalog.py "$EVIDENCE_ROOT"
```

In each checkout start the app, replacing `SIDE` by `base` or `head` and `OFFSET` by 901 or 900:

```sh
T3CODE_DEV_SEED=0 T3CODE_AUTO_BOOTSTRAP_PROJECT_FROM_CWD=0 \
CURSOR_BACKEND_URL=http://127.0.0.1:18999 CURSOR_API_KEY=synthetic-large \
T3CODE_PORT_OFFSET=OFFSET PATH="$EVIDENCE_ROOT/SIDE/bin:$PATH" \
vp run dev --home-dir "$EVIDENCE_ROOT/SIDE" --no-seed
```

Pair a browser with the startup URL. The hostname command shim in each isolated home labels the synthetic environment `Evidence`. Add an empty git repository titled `Catalog demo` with `t3 project add --base-dir "$EVIDENCE_ROOT/SIDE" --title 'Catalog demo' <demo-repository>`; no messages or model turns are needed. The composer opens as a new draft.

## Identical reproduction on both commits

1. Open Settings > Providers, select Cursor. Allow the initial five-model discovery to complete: Current A, Current B, Previous C, Previous D, Previous E. A fresh synthetic key may be entered in the Cursor API key field, then Tab to commit. Capture the initial five-model state.
2. Set the synthetic service's `mode` file to `small`. Enter a different synthetic key in the Cursor API key input and press Tab (changing keys represents changing accounts and avoids the per-key catalog cache). Click **Refresh provider status**. Wait for authenticated/ready discovery. Capture Settings, close Settings and open the composer model button **Current A**; capture the Cursor model picker.
3. Start a separate restart recording. Close the model picker. Find the server listener PID and confirm its cwd belongs to this side's checkout; terminate that exact PID with SIGTERM. Capture the real **Evidence is reconnecting** state and confirm the listener is absent. Restart `vp run dev:server` using the same environment and same home, keeping the synthetic service in `small` mode. The replacement process reads the same durable cache. Wait for its listening/recovery markers and reconnection. Navigate the browser afresh to `/settings/providers`, select Cursor, capture Settings, close it, and reopen/capture the model picker. Both Settings and picker restart captures are newly acquired, not reused. Restart videos show the disconnect, recovery, fresh navigation, Settings and picker.
4. On that same cached inventory, open Settings > Providers > Cursor. Set service mode `failed`, enter another fresh synthetic key, Tab, click Refresh provider status. The model endpoint returns HTTP 503 and Cursor becomes unavailable; capture that the cached inventory remains (base five; head two).
5. Set mode `empty`, enter another fresh synthetic key, Tab, click Refresh provider status. The endpoint returns a successful JSON response with zero models; Cursor reports needs attention, and the same cached inventory remains. Capture it. The paired incomplete-discovery videos cover steps 4 and 5.

The head refresh/restart was captured again after a framing check. Earlier head failure/empty captures use the same two-model inventory reached by the same steps. The service transcript includes preparatory and repeated runs; it is not a claim of one uninterrupted take.

## Browser operations

All interactions used T3 `preview_*` tools, not patched UI state or mocked WebSocket responses. The selectors below identify the exact controls driven:

- Navigate `/settings/providers`.
- Click `button[aria-label='Select Cursor']`.
- Type synthetic key into `input[aria-label='Cursor API key']`, clear old value, press Tab.
- Click `button:has-text('Refresh provider status')`.
- Click `button[aria-label='Close']`.
- Click `button:has-text('Current A')` to open the actual model picker; Escape closes it.

For Settings captures the outer `.topbar-scroll-fade` scroll offset is 60; the provider list is at zero; the provider detail scroll area is scrolled to its bottom. The shorter two-model detail has a smaller maximum scroll offset, so its Models heading naturally sits lower. The provider list/Claude row and full viewport stay aligned on both sides. There are no cropped picker captures. `capture-manifest.json` records dimensions, acquisition file times and checksums, including distinct refresh/restart Settings images. Capture timestamps plus the restart videos and process transcript establish fresh acquisition after a genuine restart.

## Limits

Actual Cursor OAuth/account entitlement behavior, desktop-shell relaunch, and the timeout-specific discovery branch were not exercised. The HTTP 503 and empty-success branches were exercised visually. The web client and real server were restarted/reloaded as described; this is not an Electron-shell test. Tests were not used as evidence.
