# Rebuild this evidence

Use the unmodified real Expo app. No component harness or provider-status fixture was used. All uploaded state is synthetic. Do not use the machine's live T3 home.

Revisions: before [32ecd717](https://github.com/pingdotgg/t3code/commit/32ecd71726fee16f335484c1f95cbce126d461f6); after [03ec49bf](https://github.com/pingdotgg/t3code/commit/03ec49bf7f1b7722a59db840a5ecb27c3fa94655).

1. Install dependencies with global `vp install` in each pinned checkout. Run only one server/Metro pair at a time. A single native dev-client build serves both JS revisions.
2. Start a fresh server from the owning checkout: `T3CODE_DEV_SEED=0 vp run dev:server --host 0.0.0.0 --port 18787 --home-dir <fresh-home>`. Start Metro from that checkout's `apps/mobile`: `REACT_NATIVE_PACKAGER_HOSTNAME=fs-36.tail131df4.ts.net vp run dev:client --port 8081`. Do not set VITE_HTTP_URL/VITE_WS_URL.
3. Put `seed.mts` in this evidence scratch directory. Its imports resolve using a scratch `node_modules` symlink to the owning checkout's `apps/server/node_modules`. Run `EVIDENCE_HOME=<fresh-home> node seed.mts <checkout> 18787 seed`. It creates the synthetic project and unstarted thread through HTTP/RPC, stars current Claude Opus 5.5, and ensures Opus 4.8 is unhidden and unfavorited. The raw config snapshot it writes is private; upload only the supplied sanitized provider-catalog files.
4. Check Claude is ready and installed with authenticated or unknown auth, and that `claude-opus-4-8` is present with `isLegacy: true`. Actual runs used genuine CLIProxyAPI-backed Claude 2.1.303, ready/installed/authenticated; Codex 0.163.0 was the second eligible provider. The supplied before/after sanitized catalogs match exactly.
5. Prepare before leasing: `vp run mobile:install ios --prepare` (or android). Connect a named pool session, open exact device `iPhone 17 Pro` or `Pixel 9`, then install only via `vp run mobile:install <platform> --session <session>`; Android also used `--metro http://fs-36.tail131df4.ts.net:8081`.
6. Open the dev client with `t3code-dev://expo-development-client/?url=http%3A%2F%2Ffs-36.tail131df4.ts.net%3A8081&disableAutoLaunch=1&disableFab=1`. Pair through the owning checkout's `.agents/skills/test-t3-mobile/scripts/pair-client.sh 18787 <fresh-home> http://fs-36.tail131df4.ts.net:18787 agent-device --session <session>`. Never publish the pairing output.
7. Freeze the app's `Date.now` after each JS reload with `node inspect.mjs simlock 'Date.now=()=>1793610000000; Date.now()'` for iOS or `Google` for Android. This does not freeze the native OS clock. The uploaded iOS stills intentionally retain the live native clock because the screenshot status-bar normalizer produced a charging-icon transient. Android stills normalize its status bar to 9:41. This is a documented capture-condition limitation.
8. Set appearance light/dark with `agent-device settings appearance <theme> --session <session>` and use default font scale 1.0, portrait. Open New chat, choose Model search evidence, set Claude Opus 5.5 with the model picker, save, reopen. Target Opus 4.8 stays unselected. Ensure All providers, Show legacy off, Manage hidden off.
9. `capture.py <label> <session> ios search` records F01–F03; `ios exact` and `android exact` record F02/F03. iPhone light starts with an existing `Opus 4.8` query, clears it, then runs the blank/three-spaces/reset sequence. The exact search order is `Opus 4.8`, `Claude Opus 4.8`, `  cLaUdE oPuS 4.8  `, `claude-opus-4-8`, clear, `Claude`, scroll last/options, clear. iOS clears through the real native Clear text button; whitespace uses three software-keyboard Space taps. The original Android after clip could not clear the offscreen input. The primary Pixel after retake uses `capture-v2.py`, adding scroll-to-top before clear, keyboard dismissal and a final top reset. Its complete final decoded frame is included as the last tile in its sheet; the original incomplete clip remains linked as superseded evidence.
10. `drive.py <group> <session> start`, followed by ordinary agent-device arguments and finally `stop`, records the adaptive regression flows. The uploaded `steps-public.json` beside every clip records every command, timestamps and exit codes. `replay.py <steps-public.json> <session>` replays these commands from the same initial screen, skipping record/screenshot commands. The F05–F07 group starts in the existing-thread picker, returns to Chats, opens a new draft, removes the current model's star, then exercises Favorites, hidden preferences and legacy controls. Every preference mutation in that group is a recorded UI action.
11. F04 starts on the unstarted thread conversation, then opens its composer model control. F08 starts on Chats, enters Settings → Scheduled tasks → New task, selects Model search evidence, and opens Model. Its original model is GPT-6-Astra. Only picker Save is used; the outer unsaved task form is discarded and the ending list says No scheduled tasks yet.
12. iOS active search exposes Close instead of Filter. Close clears the query. F04/F05 therefore change the provider filter with empty search and retype the identical query. F07's direct on→off toggle with query retained is captured on Pixel, including its Catalog → Legacy models alias. iPhone captures blank toggle behavior and search with toggle off, but cannot expose the menu during active search on this native toolbar.
13. Before each retained still, `capture.py` takes two full native screenshots 500 ms apart and keeps the frame only when PIL reports exact RGB equality. `diff.py before.png after.png <output>` produces full-screen absolute RGB difference amplified 32× at zero threshold, plus a magenta overlay for maximum-channel difference >8/255. No registration, crop, masking or status-bar editing was applied to the iOS stills.
14. `sheets.py` makes six-column video contact sheets every three seconds. `review-sheets.py` makes paginated four-column review sheets every six seconds plus the final decoded frame. These are review aids, not replacements for the full-resolution clips. Android screenrecord split its supplementary F07 clip at 180 seconds; both raw chunks are linked.
15. At completion: stop only your tracked server and Metro PIDs/sessions, close every agent-device session, and remove only the baseline worktree you created. This run stopped its sessions and removed `/home/ubuntu/wt/pr-27587-base`. The lead-owned after worktree remains clean.

Timestamp conventions: `capture.py` logs command dispatch times relative to its start; `drive.py` logs command completion times relative to its start. Remote capture startup/encoding can shift these relative to playback. Evidence narration uses the driver clock, with decoded contact sheets as playback-position aids; the public step logs preserve the exact command timeline. Android records only changing frames and may omit the final idle interval.

Retake: the after server reused its isolated evidence home, restored the original favorite/hidden preferences through `retake-preferences.json`, and reported the same sanitized provider catalogs. `retake-artifacts.py` packages its frames and final-frame sheet tile. `upload-retake.py` appends upload results without discarding the first batch. All four Pixel leases and the iPhone lease were closed; server and Metro were stopped after the retake. One Pixel lease contained another session’s recording marker; it was left untouched and a fresh lease succeeded.
