# Real app proof: model preferences row rendering

Base: 1a12c4afae998925b4a29417f2dc436c0ccd0969
Head: 3bcdb1f880f6def901d54f19cfddb0735cee6c55

Surface: unthrottled Linux Chromium web dev app, CSS viewport 1366x768, dark theme, DPR 2. OpenCode 1.19.5 reports 493 models on both sides. Fresh isolated databases; no live application data was copied. No provider turn was run.

The scenario guide explicitly excludes timing/performance regressions. This proof uses two real dev servers and the shared preview browser instead.

## Setup
Install dependencies with vp i in each worktree. Start each with:
T3CODE_DEV_SEED=0 OPENROUTER_API_KEY=dummy OPENCODE_DISABLE_MODELS_FETCH=1 OPENCODE_MODELS_PATH=<absolute location of models.json> vp run dev

models.json is a frozen public OpenCode model catalog, required because the live catalog changed between initial launches. It is not a database or account credential file.
Pair each browser with its own server's startup pairing URL. Open /settings/providers, then Add provider > OpenCode (radio) > Next > Next > Add instance.

Inject the exact same probe.js through a script src="/row-proof.js" in the HTML head before React initializes. Place probe.js at apps/web/public/row-proof.js. No application component or behavior code is edited.

## Instrumentation
probe.js implements the standard React DevTools global commit hook. It traverses committed fibers named ProviderModelRow with PerformedWork and actualStartTime at or after the root render start. This excludes stale flags on reused bailout fibers. It shallow-compares committed props against alternate.memoizedProps, with Object.is. It counts committed row renders, not development-mode function calls. A row can occur in more than one commit.

The same page also records browser PerformanceObserver Long Tasks. Raw profiles contain per-row changed prop names, root render durations, model catalog, clicked controls/timestamps, and final model order. Root durations in these files cover only commits containing rendered model rows; zero row commits does not imply no parent or DOM work.

*.trace.json contains the observed interaction windows, React render durations, and Long Tasks in Chrome Trace Event format. It is a derived observation timeline, not a complete Chrome engine CPU trace. All original measurements are in *-profile.json.

driver.js installs prepareRowProof and runRowProof in the paired page. The temporary evidence panel displays observed counters; it is not product UI. Browser automation evaluates this script and records the tab. Call prepareRowProof("Before"/"After", sha), start the tab recording, call runRowProof(), wait for its Completed panel, stop recording.

## Identical scripted interaction
The model filter stays empty.
1. Hide Gemini 3.7 Flash (initial row 101).
2. Star Qwen3.5 35B-A3B (initial row 441).
3. Move Gemini 4 Argon down (initial row 102).
4. Hide GLM Flash Latest, GLM Latest, GLM-4.5-Air, GLM-4.5V, GLM-4.6 in rapid succession (150ms requested spacing; actual timestamps are recorded).

Initial catalog order is identical across the two recorded runs, as is final order. No hidden or favorite models were present at recording start. An earlier reset left Qwen3.5 27B at the front of the saved order on BOTH sides; this shared ordering is recorded in the raw profiles.

## Observed
Committed rows per action: base 493 / 493 / 493 / 2465; head 1 / 1 / 0 / 6.
Unchanged-prop committed rows: base 492 / 492 / 493 / 2459; head 0 throughout.
An interior move changes keyed DOM order without changing row props, so zero row renders is expected on head.

Largest Long Task per action (ms): base 88 / 228 / 0 / 87; head 71 / 237 / 57 / 90. These are single unthrottled samples, not a benchmark. The fix eliminates unchanged row renders; it does not establish a general latency improvement. Favoriting still incurs list-reordering work.

Both stills were checked for stability with identical SHA-256 hashes across captures taken over 500ms apart. Both recordings and stills were visually inspected. The left-hand profile panel fits completely; no private machine name, paths, or credentials appear.

## Limits
The reported Windows 10 Pro desktop crash and Not Responding dialog were not reproduced. The provided Windows pool runs Server 2025, not Windows 10. Linux web captures establish the memoization behavior only.
