# Native mobile reproduction

Run independently against each commit's server and Metro bundle. Use a fresh,
worktree-local database with `T3CODE_DEV_SEED=0`, the same synthetic project and
real provider configuration as web-driver.js. No provider or model identifiers
are included in public artifacts.

1. Prepare and install the checkout's iOS dev client with `vp run mobile:install
   ios --prepare`, then `vp run mobile:install ios --session "$SESSION"`.
2. Run that checkout's Metro bundle, open it in the leased iPhone 17 Pro dev
   client, and pair to that checkout's server through latency-proxy.cjs.
   Keep light appearance and a 402x874 logical viewport on both sides.
3. Start a real thread titled `Mobile queue retry` with the prompt
   `Run sleep 600 in the terminal, then reply done.` Queue exactly one message,
   `Reply with mobile retry received.`, through the app's real startTurn command
   with dispatchMode `queue`.
4. Open that thread and press `Open queue, 1 messages`. Start native recording.
5. Set the proxy's subscription push delay to 60000 ms by requesting
   `/evidence/delay/60000`. Click the same thread's Stop generation in the web
   client, which connects directly to the server. This leaves the mobile queue
   view stale while the real server stops the run.
6. In the native app, press `Send now, queued message 1`. Observe the actual
   promote-to-steer rejection. Base shows no explanation; head shows a native
   `Could not send queued message` alert containing the server's reason.
7. Head only: dismiss the new alert with OK. Restore push delay to zero through
   `/evidence/delay/0`, and let the already-delayed frames arrive. The same queued
   row is still present. When stopped, press its Send now again. Both sides
   accept queued-run.start and display `mobile retry received.` Stop recording.

The proxy forwards requests and responses unchanged. Only subscription pushes
wait; command responses arrive immediately and are logged. This is a
supplemental cross-client stale-view scenario, not a claim that native taps were
30 ms apart. The web recording covers the original Stop/Send timing scenario.

Recordings are scaled to the logical viewport. A small rectangle redacts the
private environment subtitle, and an adjacent diagnostic panel reports actual
RPC outcomes separately from the app UI. Only matching dispatch frames are
exported; unrelated configuration and operational metadata are omitted.

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