# Issue 23246 native evidence handoff — 2026-10-22

4/11 matrix rows have before/after interaction recordings (L1, L2, C1, P1). Two additional matrix controls have candidate-only recordings (N1, N2). Five matrix rows remain unverified (C2, P2, N3, E1, E2). This is not a complete matrix pass. Bare `~/` has an additional before/after regression pair outside the original matrix. Android and Windows native behavior are unverified.

## Source and environment

- Baseline source [a50cd989ae](https://git.cafe/pingdotgg/t3code/commit/a50cd989aee06ed0762e26027eadf35933eb52ac), static EAS build `304d5885-7ddc-4830-9f5e-26a7fce0f969`.
- Candidate source [7c0efc9c5e](https://git.cafe/pingdotgg/t3code/commit/7c0efc9c5ee7072568adf9ca52fa29d7b3ee00fe), static EAS build `2dd1fd50-70e3-4011-8480-d16fd070d8b1`. All candidate recordings use this final implementation, not the earlier 1b23 build. The later Windows prefix normalization is included in the artifact but not exercised on iOS.
- Reproducible fixture script committed as [d529a4010b](https://git.cafe/pingdotgg/t3code/commit/d529a4010b), `scripts/fixtures/mobile-existing-project.sh`. This fixture-only commit follows the native artifact source; it changes no native app code. No PR-only assets committed. Worktree clean at handoff.
- EAS cloud iPhone 17, iOS 26.5, portrait/light, logical 402×874; standard recordings 1206×2622. App `com.t3tools.t3code.dev`, Expo SDK 58, version 2.0.0 build 5. Static release builds, no showcase/native fixture controls enabled.
- Real server at port 16391 against isolated `/home/ubuntu/wt/issue-23246/.t3`; copied state, never run against live user database. Backend runtime label fs-03; raw environment ID `5899fd33-a185-4601-a78e-a5739e925516`.
- P `/home/ubuntu/t3-23246-repro/bike-documents`, unique registered ID `13589b3d-c451-425e-9022-3d11be0633b6`, title Bike documents repro. HOME `/home/ubuntu`, ID `5d934fe7-0b43-4fa7-b450-04b9216b6cf4`, title Host HOME fixture. Q `/home/ubuntu/t3-23246-repro/unregistered-local`; R `/home/ubuntu/t3-23246-repro/tracked-clone`.
- Public build metadata and runtime capability: [build-provenance.json](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/070bb072824d67b5/build-provenance.json); [runtime-capability.json](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/a9f406b8e3674e7c/runtime-capability.json).

## Matrix

| Row | Coverage | Actual operation/result | Before recording | After recording |
|---|---|---|---|---|
| L1 | PAIRED PASS | Absolute P/; local Add project button. Before: duplicate alert; after: silent Bike documents draft. | [Before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/a14553b99f5191ce/before-L1.mp4) | [After](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/66d2928dbbb4ee1f/after-L1.mp4) |
| L2 | PAIRED PASS | ~/t3-23246-repro/bike-documents/; keyboard Done. Before: Failed to mutate project; after: silent existing draft. | [Before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/092d1b538804158c/before-L2.mp4) | [After](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/b85dd37b13fc8764/after-L2.mp4) |
| C1 | PAIRED PASS, tracked | Existing P/ Git destination, no prompt. Before tracked clone attempted and failed; after silently reused existing project without clone RPC. | [Before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/46ff003b4471dd92/before-C1.mp4) | [After](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/6e8c788d41061aa2/after-C1.mp4) |
| C2 | UNVERIFIED | No real connected environment advertising projectCloneTracking=false. No legacy native claim. | — | — |
| P1 | PAIRED PASS, tracked | Real prompt/repository link; P/ destination. Before tracked clone failed; after Bike documents draft retained exact Fix the bike. | [Before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/d54685f1d2237f05/before-P1.mp4) | [After](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/e7701032adfcf2eb/after-P1.mp4) |
| P2 | UNVERIFIED | Legacy prompt route: no compatible real legacy environment. | — | — |
| N1 | CANDIDATE ONLY | Unregistered Q via ~/ without trailing slash. Exactly one new registered project; picker then selecting project opens usable draft. Baseline control was not captured before first session expired. | Missing | [Register](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/bc434dc45178f0d2/after-N1.mp4) / [Open draft](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/390693c4580e5782/after-N1-open.mp4) |
| N2 | CANDIDATE ONLY | Fresh tracked clone R from real prompt link. Exactly one project and one tracked clone RPC; real Git checkout, prompt retained, completed draft. Baseline control not recorded. Transient progress spinner not independently sampled. | Missing | [After](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/1d36d32923f5738a/after-N2.mp4) |
| N3 | UNVERIFIED | Legacy fresh clone: no compatible real legacy environment. | — | — |
| E1 | UNVERIFIED | No real filesystem.read-disabled/browse-failure environment was available; normal browse succeeded. No injected harness claimed as native proof. | — | — |
| E2 | UNVERIFIED | Only one isolated connected environment; second-environment same-path control not seeded. | — | — |

## Extra bare-HOME regression

Local folder default `~/`, Add project. Before: Failed to mutate project. After: silent Host HOME fixture draft, empty composer. Before recording recovered as a 20-second excerpt (offset 1565–1585 seconds) from the original EAS whole-session recording; 402×874. Only that credential-free excerpt was uploaded; the whole-session recording remains private. An initial candidate HOME attempt carried the prior prompt; it was discarded and recaptured from a fresh New chat, so the published candidate HOME pair has an empty composer.

[Before HOME recording](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/d9bb1bfc86d708fa/before-HOME-recovered.mp4) · [After HOME recording](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/1b29477eb8ed96c6/after-HOME.mp4)

## Steps and timestamps (UTC, 2026-10-22)

Preparation outside submit-only clips: New chat → Add project → Local folder (L1/L2/HOME), paste or browse the path. Input was confirmed in a fresh accessibility snapshot. C1 baseline used a destination-route injection; candidate used literal UI Add project → Git URL → `https://github.com/octocat/Hello-World.git` → Continue, then P/. P1/N2 used the actual `t3code-dev://new?prompt=Fix%20the%20bike&repo=octocat%2FSpoon-Knife` link, Clone, prompt warning OK, then destination.

| Pair | Before interaction | Candidate interaction |
|---|---|---|
| L1 | Submit 07:59:01; result screenshot 07:59:14; 26.50s video | Recorded 08:20:40–08:20:59; 17.14s video |
| L2 | Folder browsing/focus/keyboard Done about 07:55–07:56; failure screenshot 07:56:41; 63.92s video | Record requested 08:22:07; keyboard command 08:22:12 invalidated XCTest and dismissed keyboard without submitting. Recovery refocus, then literal Done tap 08:23:20; result 08:23:34; stop 08:23:41. 81.50s video includes recovery and final draft. |
| C1 | Submit 08:03:01; server tracked start 08:03:05.722; result 08:03:12; 21.55s video | Normal Git URL flow, submit during 08:32:32–08:32:51; 11.67s video |
| P1 | Real-link dialog from 08:03:48; submit 08:05:11; tracked start 08:05:15.037; result before 08:05:42; 114.49s video | Real-link dialog recorded from 08:33:19; submit 08:34:16; result 08:34:25; stop 08:34:29; 59.79s video |
| HOME | Submit 08:06:30; recovered whole-session excerpt about 08:06:20–08:06:40 | Fresh New chat; record 08:37:02; ambiguous selector was rejected without tapping, then literal Add button tap 08:37:17; result 08:37:26; 14.42s video. |
| N1 | Missing | Register record 08:39:34–08:39:52, then select/open record 08:40:07–08:40:26 |
| N2 | Missing | Real-link dialog/clone record 08:40:51–08:42:12; after completion draft retained Fix the bike. Later fresh snapshot shows branch main and enabled Start task. |

Controller command wall times include transport/export delays; MP4 durations differ. Device status clock is local simulator time, not these UTC timestamps. [video-metadata.json](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/8b994c875d98ba7e/video-metadata.json).

## Actual branch and project identity audit

[baseline-tracked-clone-trace.json](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/29ef56d631ca2ba1/baseline-tracked-clone-trace.json) proves C1 and P1 invoked `ws.rpc.projectClone.start` and `ProjectCloneTracker.start`. The text “cloneRepository failed…Destination path already exists” came from the lower layer inside tracked cloning; these are not legacy-mode captures. Runtime reports `projectCloneTracking=true`.

[project-reuse-audit.json](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f7f90c8a173a4ad3/project-reuse-audit.json) records the isolated projection and trace counts. There were six active projects immediately before candidate reuse checks and six after L1/L2/C1/P1/HOME, with the same unique P and HOME IDs/roots. C1 and P1 add no clone RPC: two historical tracked starts before and after all reuse checks, zero legacy clone RPCs. Native UI shows the unique corresponding project title. This maps the selected title to the existing registered ID; no direct extraction of native navigation-state projectId was performed.

N1 adds exactly one Q project (count 7). N2 adds exactly one R project (count 8), and one additional tracked clone RPC (count 3). R is a real checkout of octocat/Spoon-Knife at `d0dd1f61b33d64e29d8bc1372a94ef6a2fee76a9`; later current native snapshot shows main and enabled Start task. No Start task was pressed.

## Paired sheets and pixel comparison

Each sheet includes full uncropped Before, After, raw absolute RGB difference amplified ×4 (diff0: no tolerance), and red mask where max-channel absolute difference >16/255. No clock masks, alignment warps, or exclusions. Raw screenshot files are 402×874. The L2 before input was extracted/rescaled from the interaction video, so encoder/interpolation noise affects diff0. Threshold 16 is explicitly a tolerance view, not a claim of identical pixels. Metrics: [pixel-diff-metrics.json](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/22d170ba1eb26d98/pixel-diff-metrics.json).

- [C1-input-paired-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/83c223373f7ee23b/C1-input-paired-sheet.png)
- [C1-result-paired-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/637169a7acaeb90b/C1-result-paired-sheet.png)
- [HOME-input-paired-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/a8a5727df84bdd78/HOME-input-paired-sheet.png)
- [HOME-result-paired-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/82da7aad70ca0927/HOME-result-paired-sheet.png)
- [L1-result-paired-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/cb8c7715e2041347/L1-result-paired-sheet.png)
- [L2-input-paired-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f668ae8550a3987a/L2-input-paired-sheet.png)
- [L2-result-paired-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/d5fd691a615f163c/L2-result-paired-sheet.png)
- [P1-input-paired-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/647b29f42eba2e83/P1-input-paired-sheet.png)
- [P1-result-paired-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/4cd85a8d0640e039/P1-result-paired-sheet.png)
- [whole-surface-paired-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/5aa006fafae52b97/whole-surface-paired-sheet.png)

## What else changed / comparison limits

- Status clock is visibly different across captures. The controller settings catalog exposed no status-clock override; it was not frozen. The requested identical/frozen-clock condition is unmet. Whole Threads surface differs at the clock; raw changed pixels are about 0.12%, thresholded about 0.11%. No claim that nothing else changed.
- Before result screens remain on an error form (C1/P1/L2/HOME), while candidate results are drafts; keyboard is present on some before clone failures and dismissed on after drafts. These navigation and keyboard differences are expected consequences of the behavior, not style changes.
- Input caret/horizontal field scroll and focus position differ (long paths scroll their start out of view). Folder lists and keyboard-driven scroll offsets differ. Before/after C1 input headers differ because baseline was destination-route injected and candidate came through the normal Git URL screen. Baseline L1 input contains the previous L2 error banner; it is not a clean paired input state, so only the result is paired.
- Baseline was in the original EAS session; candidate in a restarted session. Server/tunnel were restarted after the interruption, and the tunnel origin changed. New pairing succeeded with a full URL clipboard paste. Same isolated data directory, P root and ID were retained. A raw-environment-ID injected candidate destination became Environment unavailable; this attempt is excluded from passing proof. Ordinary current-client UI resolved the connection and passed. Exact route-ID root cause was not established.
- HOME fixture registration added one project before candidate checks. N1 and N2 intentionally added Q and R after the reuse checks. Prompt drafts may appear as Unsent in the current device list. Whole-surface paired screenshots were taken before these control additions.
- Temporary build-only iOS architecture plugin excluded x86_64 due arm64-only GhosttyKit. Same workaround needed to produce the simulator artifact, no product source changes retained. All temporary app.config/eas/.easignore changes restored/removed. Candidate build includes final Windows-only normalization delta; it has no separately claimed native Windows proof.
- No browser or unit test is presented as native evidence. Supporting web/runtime captures from the lead are supplementary only.

## Reproduction and fixture ownership

Run committed `scripts/fixtures/mobile-existing-project.sh` with the isolated T3 home; it creates P and Q Git directories and registers P through the normal CLI. Register HOME when needed using `node apps/server/src/bin.ts project add /home/ubuntu --base-dir /home/ubuntu/wt/issue-23246/.t3 --title 'Host HOME fixture'` (the registered data and IDs above are authoritative). Keep R absent before N2. Baseline and candidate use real UI and a real connected backend, not an isolated render harness. Fixture script syntax and idempotent seeding were checked; native claims above come from interaction captures.

## Live handoff (left running for primary)

- Candidate EAS session `01a162af-b98d-7077-912e-8987de44d75a`, IN_PROGRESS at final status check. Started 08:18:16 UTC, max duration 75 minutes, approximately expires 09:33 UTC. `.env.eas-simulator` points here; it is secret and was not published. App is on completed tracked-clone draft with Fix the bike; no provider task sent.
- Server exec session **20304**, captured listening PID **604165**, parent **604159**, cwd `/home/ubuntu/wt/issue-23246/apps/server`, port **16391**. Started by this test agent using `vp run dev:server`; private log `/tmp/triage-23246/restarted-server-private.log`.
- Tunnel exec session **1600**, captured PID **603917**, command `/tmp/triage-23246/cloudflared tunnel --url http://127.0.0.1:16391`; private log `/tmp/triage-23246/restarted-tunnel-private.log`. Origin `https://border-innovations-sun-intersection.trycloudflare.com`. Descriptor HTTP200 verified. Keep server and tunnel for primary; lead owns later cleanup. No pattern kills performed.
- Original lead exec sessions 83730/97795/92504 were lost around the interruption; no claim they remain alive. Baseline EAS session `01a1628c-e978-7fc7-8ef6-55d9a3a76011` and failed candidate pairing session `01a162a6-d253-71e2-9872-18b1ca27be48` were stopped. Current session remains running.
- Pairing files, env config, signed build log URLs, and whole-session recordings remain private. No push or PR created.

## FRICTION

- **Build / infrastructure:** GhosttyKit x86_64 linker incompatibility; temporary arm64-only simulator plugin/profile. Transient registry install failure required retry. Device daemons intermittently unavailable/time out during snapshots/record exports; bounded retries and artifact recovery used. Baseline session expired, so N1/N2 lack baseline control recordings.
- **Automation / input:** RN rapid fill raced and corrupted host to h despite a reported 48 characters; full pairing URL clipboard paste with Code empty succeeded. All later path entry used paste and fresh snapshots. XCTest keyboard Enter invalidated once; literal keyboard Done completed L2.
- **Connection / fixture:** Recovered isolated server+tunnel with recorded owned PIDs after interruption. Injected destination route had Environment unavailable; normal Git URL UI worked. No production implementation changes made for it.
- **Coverage / environment:** No real legacy capability-off environment, filesystem-disabled environment, or second connected environment. C2/P2/N3/E1/E2 remain unverified. N1/N2 are candidate-only, not paired passes. Android/Windows native not exercised.
- **Capture conditions:** No exposed clock override; clock, keyboard, caret, scroll, codec, session and fixture differences are disclosed above.

Supplementary lead captures: [web existing-project interaction](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/ccc67f0e65617757/web-existing-project.mp4) · [runtime transcript](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/3245b7509bff532e/runtime.txt). These are not native proof.

![Candidate N2 completed native draft, main branch and retained prompt](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/52361948aac616ae/after-N2-completed.png)
