## Evidence

Observed product behavior changes stay within trusting Expo's create for admission. No additional product behavior change was found in these captures. R2 and R3 demonstrate that refusal recovery still works after the gate pre-check is removed.

PR [#29490](https://git.cafe/pingdotgg/t3code/pull/29490), mirrored as [#29490](https://github.com/pingdotgg/t3code/pull/29490). **4/4 affected matrix rows captured**: R1, R2, R3, T1. Six runtime transcripts include both revisions for every runtime row. Unverified required rows: **none**. C1–C7 remain waived/N/A as specified in the [auditor's matrix](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/44ff7790a4885fb9/matrix.md).

**harness: real EasDeviceHost + ExpoApi against fake Expo HTTP; no live Expo**

Environment: Node **v26.12.1**, **Linux 6.1.102 x86_64**, machine `fs-21`. Before checkout `/home/ubuntu/wt/pr-29490-base`, SHA [8657eecb28](https://git.cafe/pingdotgg/t3code/commit/8657eecb28bc8c767510cc6b9d852b628047c604). After checkout `/home/ubuntu/wt/pr-29490`, SHA [f655799258](https://git.cafe/pingdotgg/t3code/commit/f6557992585aa5e711cc5b6eb9b4d14e0610619a). The after SHA is local and unpushed; the commit link records provenance and may not resolve on the forge yet.

Server only: no screenshots, viewports, themes, browser, dev server, native client, or paid Expo session. The driver imports production modules from the selected checkout and injects only `HttpClient`. It uses synthetic saved credentials and isolated real ledger files under this evidence directory, validates create inputs and ledger-before-create, rejects unexpected HTTP origins, and records every GraphQL request/response, caller result, and ledger snapshots. Endpoint tokens are omitted from transcript responses. No live database or credentials were read.

### R1 — gate off, create admits

| Before | After |
| --- | --- |
| [8657eecb28](https://git.cafe/pingdotgg/t3code/commit/8657eecb28bc8c767510cc6b9d852b628047c604) | [f655799258](https://git.cafe/pingdotgg/t3code/commit/f6557992585aa5e711cc5b6eb9b4d14e0610619a) |
| [Runtime transcript](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/3396a3b6f5e0890c/R1-base.txt): valid owner `fixture-owner`, gate false. One availability query; zero creates. Caller receives `EAS Simulator is unavailable: EAS Simulator is not enabled for the fixture-owner Expo account.` Ledger stays absent/empty. No session stopped. Exit 0. | [Runtime transcript](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/30a9c5bf44ccf4d2/R1-head.txt): zero availability queries. Ledger entry exists before the single create (app UUID, IOS, AGENT_DEVICE, 25-minute maximum, 5-minute idle). Boot returns `session-1`; `/api` supplies `UDID-fixture-1`; list includes the running session. Scope close stops `session-1` and leaves `[]`. Exit 0. |

### R2 — refused create, no matching session, restart frees capacity

| Before | After |
| --- | --- |
| [8657eecb28](https://git.cafe/pingdotgg/t3code/commit/8657eecb28bc8c767510cc6b9d852b628047c604) | [f655799258](https://git.cafe/pingdotgg/t3code/commit/f6557992585aa5e711cc5b6eb9b4d14e0610619a) |
| [Runtime transcript](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/3684628a7ab3bc53/R2-base.txt): gate **on** to reach create. One availability query per boot. Expo's USER/null-data refusal reaches the caller verbatim inside the host wrapper. Ledger immediately shows `refused:true`; no booted session and no stop. Restart reuses that ledger with capacity 1, active-list HTTP 502, and admitted create. It becomes ready and is stopped on close; only the refused record remains. Exit 0. | [Runtime transcript](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/422f75a33053beba/R2-head.txt): gate-off-capable fake, zero availability queries. Same exact refusal message, refused ledger, empty running list, successful restart despite active-list HTTP 502, and stop of only `session-1`. Refused record remains for the reaper and consumes no slot. Exit 0. |

Exact R2/R3 caller message: `EAS Simulator is unavailable: Expo could not start a simulator session: Device run sessions are not enabled for this account.` The fake response is HTTP 200, `data:null`, with `extensions.errorType:"USER"`.

### R3 — refused create with matching orphan

| Before | After |
| --- | --- |
| [8657eecb28](https://git.cafe/pingdotgg/t3code/commit/8657eecb28bc8c767510cc6b9d852b628047c604) | [f655799258](https://git.cafe/pingdotgg/t3code/commit/f6557992585aa5e711cc5b6eb9b4d14e0610619a) |
| [Runtime transcript](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/a33c42a01232451e/R3-base.txt): gate **on**, one availability query, one refused create. Active list includes `orphan` with the exact submitted name and unrelated `someone-else` with a different name. Only `orphan` is stopped. Caller gets the exact Expo refusal wrapper; ledger is `[]` before scope close. No booted device. Exit 0. | [Runtime transcript](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/6f155ca9ba309fad/R3-head.txt): zero availability queries; otherwise the same refusal, one matching-orphan stop, empty ledger before close, no registered running device, and unrelated session untouched. Exit 0. |

### T1 — failing regression on base, focused files pass on head

| Before | After |
| --- | --- |
| [8657eecb28](https://git.cafe/pingdotgg/t3code/commit/8657eecb28bc8c767510cc6b9d852b628047c604) | [f655799258](https://git.cafe/pingdotgg/t3code/commit/f6557992585aa5e711cc5b6eb9b4d14e0610619a) |
| [Test receipt](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/4fd0d6a77baf1a9b/T1-test-receipt.txt): the head test `leaves admission to Expo's create although the account's gate is off` was replayed from scratch against base production imports. Only relative import paths were rewritten; the fake and test bodies are unchanged. The valid gate-off fixture is the test's static `pingdotgg` owner. **1 failed, 14 name-filtered skips, exit 1**, specifically `DeviceHostUnavailableError: EAS Simulator is unavailable: EAS Simulator is not enabled for the pingdotgg Expo account.` Stack points to the old host admission check, not fake decoding. | Same receipt records `vp test run apps/server/src/device/EasDeviceHost.test.ts apps/server/src/device/ExpoApi.test.ts --reporter=verbose` from the head checkout: **2 files, 22 tests passed, exit 0** (15 host, 7 API). The new regression is explicitly listed passing. The requested command without verbose reporting also passed first; it was repeated to capture all test names. |

### What else changed

- R1's operation sequence changes from availability only to create → session status → preview `/api` → session status during listing → stop on scope close. This removes the owner-gate error, adds the successful boot result and running device, and changes ledger observations from absent throughout to written-before-create → retained while ready → `[]` after stop. The host initially exposes the same two catalog devices on both revisions.
- R2 removes two availability queries (first boot and restarted boot); R3 removes one. For those baseline captures the fixture deliberately supplies gate **on** so base can reach refusal, while the head fixture is gate off and never queried. The create payloads, exact refusal messages, cleanup targets, running-device results, retained/cleared ledgers, restart success with failed listing, and capacity behavior otherwise agree.
- Transcript metadata differs by checkout/SHA/path, UTC timestamps, randomly generated six-digit session-name suffixes, and ledger `recordedAt` values. R2's first and restarted host intentionally use different names while sharing the same ledger. These fixture/runtime differences are visible but are not product behavior changes.
- T1 changes from the single expected gate-rejection failure on base to a passing regression on head. Base's 14 skips are solely the `-t` filter; head runs all 22 tests. Reporting detail and duration differ between the initial concise head run and the verbose evidence run.

### Reproduce and artifacts

Create the base checkout at the recorded SHA and run `vp install` there. Run the uploaded `run-captures.mjs` with a new absolute scratch run directory; it runs the **same** `capture.mjs` against both checkouts and every runtime row. Alternatively, from each checkout's `apps/server`, run `node <capture.mjs> <checkout> <new-isolated-output-directory> <R1|R2|R3>`. The driver logs its exact invocation and environment. `replay-test.mjs` takes head checkout, base checkout, and a new scratch directory, generates the uploaded replay/config, and runs the name-filtered regression against base. All tools and generated test/config files are uploaded below.

All six runtime processes and the head test process exited 0; the base regression process exited the expected 1. Every host scope was closed. No persistent server or simulator was started. The head checkout remained clean at the supplied SHA; no commit or push was made. The created base worktree was removed with the requested literal-path command. Scratch artifacts are retained rather than deleted.

Unverified: **none of the required rows**. These captures prove T3's admission/ledger/error behavior against scripted Expo responses, not live Expo policy or billing.

FRICTION: none
[R1-base.txt](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/3396a3b6f5e0890c/R1-base.txt)
[R1-head.txt](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/30a9c5bf44ccf4d2/R1-head.txt)
[R2-base.txt](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/3684628a7ab3bc53/R2-base.txt)
[R2-head.txt](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/422f75a33053beba/R2-head.txt)
[R3-base.txt](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/a33c42a01232451e/R3-base.txt)
[R3-head.txt](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/6f155ca9ba309fad/R3-head.txt)
[T1-test-receipt.txt](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/4fd0d6a77baf1a9b/T1-test-receipt.txt)
[capture.mjs](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/ae19ce30230a99f3/capture.mjs)
[run-captures.mjs](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/0471faeaf20f852f/run-captures.mjs)
[replay-test.mjs](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/429cd2e05d24fffc/replay-test.mjs)
[test-receipt.mjs](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/4b3439667c9ac88b/test-receipt.mjs)
[EasDeviceHost.replay.test.ts](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/30074c06b17c7639/EasDeviceHost.replay.test.ts)
[replay.vite.config.ts](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/53820a138e123538/replay.vite.config.ts)
