# M1 — round 2 native: Failed feed and long-press copy

Additional differences outside the changed error text: iOS composer shadows differ at low levels in Diff0, absent at Diff16. Android’s existing user-message bubble and its timestamp/copy icon have a small vertical/rasterization difference, visible in Diff16. This is disclosed separately from the PR’s failure-text change.

Captured from before [d1c4b52b7c](https://github.com/pingdotgg/t3code/commit/d1c4b52b7c7c7e1b7637ec47e4c959ff0c2d8d99) and after [652e9c18ce](https://github.com/pingdotgg/t3code/commit/652e9c18cee800df7e255916365967ba211097ae) for [#26086](https://git.cafe/pingdotgg/t3code/pull/26086).

**Environment — dark:** iPhone 17 Pro simulator · iOS 27.2 · 402×874 logical · DPR 3 · font scale 1.0 (OS text-size large) · portrait · PNG 402×874, recording 1206×2622. Status-only mask: PNG rows **0–61**, recording rows **0–185** (inclusive).

**Environment — light:** Pixel 9 emulator · Android 16 / API 36 · 411.428571×923.428571 logical · DPR 2.625 · font scale 1.0 (OS text-size large) · portrait · PNG/recording 1080×2424. Status-only mask: rows **0–62** (inclusive).

Real T3 native development client, JavaScript from each side’s own checkout and one Metro on port 8081 at a time. Separate fresh servers, created with `T3CODE_DEV_SEED=0`; data inserted through real app RPC, no copied database and no component harness. Claude’s real SDK runs the auth-free fixture executable, which emits a partial reply then terminates by SIGABRT or exit 7. The SDK/adapter/orchestrator create the actual persisted failures.

Both sides use identical capture-only Date instrumentation in `apps/mobile/index.ts` and a server Date preload: **2026-10-27T12:00:00.000Z**; real timers continue normally. This freezes app-relative dates without altering rendering components or injecting error payloads. No instrumentation was committed. The same cached native binary serves both sides: iOS fingerprint `e416a21c6a355b943ac5530d1cc2f8f2d446aa0e`; Android `f2adc10370e29967253ba5e4fa64d66a88ee3798`.

`--normalize-status-bar` exists, but simulator clock/battery pixels revert between commands and within recordings. Only the exact top status rows stated below are excluded from settle/diffs and blacked out in comparison recordings. No other region is masked or cropped. Stills retain their full original screen; raw recordings are linked too.

Before each submitted still, the driver takes two full screenshots with a 500 ms pause between screenshot commands and accepts them only if pixel-identical outside that status strip. The uploaded `*-settle.png` and `*-settled.json` preserve the second frame and check. All primary stills and both diffs were opened and inspected. Recordings were reviewed through frame contact sheets.

**Diff algorithm:** max absolute RGB-channel difference per pixel; Diff0 highlights every nonzero difference in saturated pink (including a one-level change). Diff16 highlights pixels with a channel difference **>16/255** in orange. Unchanged pixels are gray; excluded status rows dark gray. No registration, scaling, cropping, blur, or non-status exclusion is applied before comparison.

| Fixture | Before<br>[d1c4b52b7c](https://github.com/pingdotgg/t3code/commit/d1c4b52b7c7c7e1b7637ec47e4c959ff0c2d8d99) | After<br>[652e9c18ce](https://github.com/pingdotgg/t3code/commit/652e9c18cee800df7e255916365967ba211097ae) | Diff0<br>[d1c4b52b7c](https://github.com/pingdotgg/t3code/commit/d1c4b52b7c7c7e1b7637ec47e4c959ff0c2d8d99) → [652e9c18ce](https://github.com/pingdotgg/t3code/commit/652e9c18cee800df7e255916365967ba211097ae) | Diff16<br>[d1c4b52b7c](https://github.com/pingdotgg/t3code/commit/d1c4b52b7c7c7e1b7637ec47e4c959ff0c2d8d99) → [652e9c18ce](https://github.com/pingdotgg/t3code/commit/652e9c18cee800df7e255916365967ba211097ae) |
|---|---|---|---|---|
| M1 · iPhone 17 Pro · dark · SIGABRT failed feed | ![M1-ios-before.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/db25a8f0d75570d2/M1-ios-before.png) | ![M1-ios-after.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/3fa7e9c571f03f1b/M1-ios-after.png) | ![M1-ios-diff0.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/2156e9e65f11fd6b/M1-ios-diff0.png) | ![M1-ios-diff16.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/b2fb6300ebee43ea/M1-ios-diff16.png) |
| M1 · Pixel 9 · light · exit 7 failed feed | ![M1-android-before.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/604cd846544e3602/M1-android-before.png) | ![M1-android-after.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/00562ef438a214d0/M1-android-after.png) | ![M1-android-diff0.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/b84d0392e428c914/M1-android-diff0.png) | ![M1-android-diff16.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/ca8dc11ca3cb4329/M1-android-diff16.png) |

## M1 · iPhone 17 Pro · dark · SIGABRT failed feed — recording steps

At 0 s the complete failed feed is visible. At ~1 s the driver starts a long press on the accessible `Provider error: <sentence>` row; **Copied** appears around 2–4 s. It then reads the simulator clipboard and confirms the expected sentence; no content is pasted or sent. The clip ends around 8 s.

Command completion timestamps below are seconds from the driver’s recording-start return; device RPC/encoder latency means they are approximate video timestamps. The interaction order and explicit 1-second pauses are identical.

| Step | Before seconds | After seconds |
|---|---:|---:|
| longpress failure row | 3.16 | 3.12 |
| clipboard clipboard value | 8.85 | 8.36 |

| Before recording | After recording |
|---|---|
| [M1-ios-before.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/e2904eca45d31bff/M1-ios-before.mp4) | [M1-ios-after.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/25a9dfa01ad50823/M1-ios-after.mp4) |

Raw, unmasked originals: [M1-ios-before-raw.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f3b8a53098deb981/M1-ios-before-raw.mp4), [M1-ios-after-raw.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/281029e4733dc7ee/M1-ios-after-raw.mp4).

Copied-content verification: [M1-ios-before-clipboard.txt](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f4c0801006daa1d8/M1-ios-before-clipboard.txt), [M1-ios-after-clipboard.txt](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/3c317c6b0ab0d6b9/M1-ios-after-clipboard.txt). The copied value includes title, message, and serialized item JSON. After includes `process_killed_by_signal` (iOS) or `process_exited_nonzero` (Android); before has a null code.

## M1 · Pixel 9 · light · exit 7 failed feed — recording steps

At 0 s the complete failed feed is visible. At ~1 s the driver starts a long press on the accessible `Provider error: <sentence>` row; **Copied** appears around 2–4 s. Android also displays its native clipboard preview. At ~10–12 s the driver long-presses the empty composer, chooses **Paste** around 13–14 s, and verifies the pasted serialized error contains the expected sentence. The pasted value is never sent; the driver clears it after recording. The clip ends around 17 s.

Command completion timestamps below are seconds from the driver’s recording-start return; device RPC/encoder latency means they are approximate video timestamps. The interaction order and explicit 1-second pauses are identical.

| Step | Before seconds | After seconds |
|---|---:|---:|
| longpress failure row | 2.78 | 2.63 |
| longpress composer | 12.14 | 10.34 |
| press Paste | 14.17 | 12.96 |
| get clipboard value | 15.47 | 14.34 |

| Before recording | After recording |
|---|---|
| [M1-android-before.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/ea5c0b9e220ee9c5/M1-android-before.mp4) | [M1-android-after.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/d5351b557b66b772/M1-android-after.mp4) |

Raw, unmasked originals: [M1-android-before-raw.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/9fa44e2f079a2e0c/M1-android-before-raw.mp4), [M1-android-after-raw.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/8f64721572a5b752/M1-android-after-raw.mp4).

Copied-content verification: [M1-android-before-paste-verification.txt](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/e48f8822fbf008e5/M1-android-before-paste-verification.txt), [M1-android-after-paste-verification.txt](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/4609d1bf16268c00/M1-android-after-paste-verification.txt). The copied value includes title, message, and serialized item JSON. After includes `process_killed_by_signal` (iOS) or `process_exited_nonzero` (Android); before has a null code.

## What else changed

- `Provider turn failed.` becomes `Claude Code process terminated by signal SIGABRT.` / `Claude Code process exited with code 7.`.
- Feed title/time and partial assistant reply remain. No Retry or code badge appears. Long-press copies the changed sentence and failure code in the serialized error item. Android clipboard preview/Paste overlays are part of the recorded interaction.
- Additional differences outside the changed error text: iOS composer shadows differ at low levels in Diff0, absent at Diff16. Android’s existing user-message bubble and its timestamp/copy icon have a small vertical/rasterization difference, visible in Diff16. This is disclosed separately from the PR’s failure-text change.
- Raw status clock/battery/network pixels vary; only the explicitly stated status strip is excluded. No claim that nothing else changed is made.

## Reproduction, drivers, and checks

[native-drivers-and-seeds.zip](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f1cef19f1de3dd23/native-drivers-and-seeds.zip)

[reproduce-round2-native.md](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/fc09bc3cda158e06/reproduce-round2-native.md)

Core scripts: [seed.mjs](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f1d2807703fa900d/seed.mjs), [rpc.mjs](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/b446c9101836e3d6/rpc.mjs), [pair-native.mjs](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/e1744a7ab6bf28b3/pair-native.mjs), [capture-native.py](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/16fb6df751bb938f/capture-native.py), [claude-exit-stub.mjs](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/0588a101aba1faea/claude-exit-stub.mjs), [frozen-clock.mjs](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/bbb87d170f5688c6/frozen-clock.mjs), [install-native-clock.py](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/ca8d2f1b2829c2b5/install-native-clock.py), [clean-native-list-v2.mjs](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/91c229fbd7ce4731/clean-native-list-v2.mjs), [start-servers-reviewed.py](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/abce3c80437a49e5/start-servers-reviewed.py), [build-delivery.py](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/ad77de880f459f3d/build-delivery.py).

Actual app projection / environment telemetry: [fixture-transcript.json](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/bfa2450ccbe5085b/fixture-transcript.json), [native-environments.json](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/ba1ca8c293cdacd9/native-environments.json).

The transcript records one failed run and one error item per fixture, the retained partial answer, unsettled metadata, exact failure message/code, and absence of the nonsecret stderr sentinel in the failure. This supplements the captures; it does not replace them.

Settle partners, individual check results, and sanitized command logs:

- ![M1-ios-before-settle.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f2add2cf19f96285/M1-ios-before-settle.png) [M1-ios-before-settled.json](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f1690d78a53f44ae/M1-ios-before-settled.json)
- ![M1-ios-after-settle.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/fad5d58dcb01d42f/M1-ios-after-settle.png) [M1-ios-after-settled.json](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/ed1d367e44cf2627/M1-ios-after-settled.json)
- ![M1-android-before-settle.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/0544e0da771e07de/M1-android-before-settle.png) [M1-android-before-settled.json](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/16f81542f9635c67/M1-android-before-settled.json)
- ![M1-android-after-settle.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/0c7324db2ebf64cb/M1-android-after-settle.png) [M1-android-after-settled.json](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/bc43439363c16e70/M1-android-after-settled.json)
- [M1-ios-before-steps.json](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/0f4aa7dd469020e5/M1-ios-before-steps.json)
- [M1-ios-after-steps.json](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/19202de9e1c4f7cf/M1-ios-after-steps.json)
- [M1-android-before-steps.json](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f7ee2fb1997866a6/M1-android-before-steps.json)
- [M1-android-after-steps.json](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/e6041da87dc73d64/M1-android-after-steps.json)

**Unverified assigned variants:** none. This sheet covers M1 only; it makes no claim about the other capturer’s web/desktop or delegated-child rows.
