# OpenCode cold-probe reproduction

The application is unmodified on both revisions. Use independent worktrees and fresh T3 homes, with T3CODE_DEV_SEED=0. Install dependencies with vp i.

Install the real OpenCode 2.3.0 binary into a scratch directory with:

```
npm install --prefix ./opencode @opencode/cli@2.3.0
```

Place opencode-wrapper.py beside that directory. The wrapper executes that binary unchanged, throttling only `serve` using SIGSTOP/SIGCONT on its own child. All version checks run normally; it does not synthesize or alter API responses.

1. Write `1` to the wrapper's `duty` file. Enable the OpenCode provider in each T3 home's userdata/settings.json, configuring binaryPath to the wrapper, and leave serverUrl blank (managed server).
2. Start `T3CODE_DEV_SEED=0 vp run dev` in each checkout. Wait until caches/opencode.json reports status ready and 119 models.
3. Stop both complete dev stacks using the terminal sessions that started them.
4. Write `0.05` to `duty` and create an empty file named `staged` beside the wrapper, then restart each stack. The wrapper allows a 5% duty cycle for the first 25 seconds and reduces it to 0.5% afterward, keeping the managed startup viable while slowing cold plugin activation beyond the discovery budget. Wait for the installed OpenCode 2 warning (not a startup error). Do not refresh the provider; that could discover a now-warm catalog.
5. Read each persisted caches/opencode.json. In the real web client, open Settings → Providers, select OpenCode, and scroll its detail pane to Models. Compare the warning status and model inventory.
6. Stop both stacks, remove the `staged` file and remove the throttle by writing `1`, and restart. Verify successful discovery replaces the warning and lists 119 models again.

Browser: Chromium, Linux, light theme, 1440×1000 CSS viewport, device scale factor 2. Captures are cropped to provider inventory content to omit the environment label and binary-path configuration.

Observed on both sides: managed discovery logged phase=models, outcome=empty, version=2.3.0. Base persisted warning with 0 models; head persisted warning with exactly the same 119 model objects as its warm inventory. Both returned to ready with 119 models after an unthrottled restart.

The recordings show the live warning transition, trimmed to their first 25 seconds. The environment label is cropped away; the binary-path field that becomes visible on base after the inventory disappears is masked. Before saving the stills, two screenshots more than 500 ms apart were byte-identical in decoded RGB pixels.
