# Issue 23246 — proof audit pass 1

Read-only source audit: base a50cd989ae → head e4b036ee6178f1263f702568ce6f5dd8c66329e3. Complete diff: AddProjectScreen.tsx and its test only. No layout/style changes. This is a capture plan, not executed native verification. No server, simulator, app, tests, repository edits, push, or comments performed.

## Minimum fixture matrix

All listed interactions require recordings (before AND after where affected); stills cannot prove navigation, absence of an intervening alert, prompt preservation, or clone bypass. Use one iOS phone viewport, portrait, the same dimensions and one theme throughout. No second viewport/theme is necessary for this behavior-only change. Show starting destination/path, submit, and settled draft/error; dismiss keyboard to show the composer. Keep a project-list/count or service-log check alongside the recording to substantiate no duplicate creation/clone; pixels alone do not prove RPC absence.

| ID | Affected | Fixture / real entry | Record action and expected result | Minimum capture |
|---|---|---|---|---|
| L1 | Yes | Registered absolute root P; Add project → local folder; type P/ | Tap Add project → existing project draft with its custom title; no duplicate alert or mutation. Before shows redundant alert. | Before/after iOS, one theme |
| L2 | Yes | Same P under host HOME; type ~/repro/bike-documents/ | Keyboard Done → same existing draft; successful host browse expands tilde before lookup. Before may show mutate failure. | Before/after iOS |
| C1 | Yes | Tracking=true; registered P; Git URL → destination P; no prompt | Tap Clone project → existing draft immediately, no clone progress/error and no clone RPC. | Before/after iOS |
| C2 | Yes | Tracking=false on compatible legacy environment; registered P; provider repository lookup → destination ~/repro/bike-documents | Submit → existing draft, no attempted clone into occupied folder. Exercises repository-title card and host expansion. | Before/after iOS |
| P1 | Yes | Tracking=true; real prompt link → choose clone → destination P; prompt “Fix the bike” | Submit → existing project draft containing exact prompt; no cloning flag/progress. Choose a link that actually offers clone, rather than resolving directly to existing project. | Before/after iOS |
| P2 | Yes, route contract | Tracking=false; AddProjectDestination params include prompt and existing destination | Submit → exact prompt retained in existing draft. Real prompt-link caller deliberately omits prompt in this mode; label route injection as such. | After iOS route-level recording; unavailable if no supported route injection |
| N1 | Control | Unregistered local directory Q (distinct root); local folder | Submit → one new project and draft, no accidental reuse of P; use tilde without trailing slash to cover parent+leaf recomposition. | After iOS |
| N2 | Control | Tracking=true; fresh absent clone destination R; prompt link | Submit → new project draft with clone progress and prompt; successful completion remains usable. | After iOS |
| N3 | Control | Tracking=false; fresh absent clone destination S; Git URL | Submit → legacy clone completes then newly registered project draft. No prompt expected from real legacy prompt-link caller. | After iOS |
| E1 | Changed resolver fallback | Connected environment without filesystem.read, or browse failure; tilde path | Record submit and actual fallback result; resolver returns original tilde, so duplicate reuse is NOT guaranteed. Absolute duplicate still reuses existing project when create scopes exist. Do not claim fallback fixes tilde duplicates. | After iOS; source proof can cover unavailable permission/failure injection |
| E2 | Shared helper control | Same path registered only in another environment; selected environment writable | Submit → selected environment owns new project; never opens other environment’s draft. | After iOS if two environments available; otherwise source-only |

C1/C2 cover both clone-tracking branches; P1/P2 distinguish truthy prompt from absent prompt. Empty prompt collapses with absent. Local button/keyboard callbacks are shared; L1/L2 cover both without duplicating the full matrix. Browser-selected absolute paths collapse with L1, but begin L1 through folder selection if possible. Trailing-separator normalization and non-trailing parent+leaf rebuilding are covered by L2/N1. No provider-adapter matrix: Git URL and provider lookup converge on the same destination component; provider lookup is represented by C2. Repository-title present/absent only changes an unchanged card, so no separate capture is justified.

## Complete changed-path/conditional inventory

- useBrowsePathInput adds resolveHomePath. Absolute/non-home path returns unchanged. Tilde expansion requires selected environment, filesystem.read and connected runtime; success with value recombines browse parentPath and leaf, failure/null returns original path. Both local and clone screens call it; the shared browse-navigation behavior is otherwise unchanged.
- useOpenExistingProject filters by environment and existing normalized path. No environment/no match returns false; match resets stack to NewTaskDraft using registered ID/title. Truthy prompt creates a draft; draft setup rejection falls back to a draft without prompt. That rejection branch is source-only unless a supported failure fixture exists; it must not be represented as prompt-preservation success.
- useCreateProject retains connection/operate guards before lookup, removes the duplicate alert, and accepts an independent lookupPath. Local submit supplies resolved absolute lookup but preserves original submitted path for new creation. Legacy successful clone still calls createProject(cwd), now using the shared silent existing-project navigation. New-folder creation uses a separate implementation, not this hook.
- Clone submit retains environment/scope/remote URL/browse/submitting/validation guards. New preflight happens before BOTH tracking and legacy RPCs. Match resets submitting and exits. Miss preserves tracked create/wait/project-not-arrived/clone-error and legacy clone/create-error paths. Existing loading/disabled/error/empty-environment render branches are unchanged; no separate snapshots needed.
- Calls into destination: Git URL normalization, provider repository lookup, and prompt-link clone. Prompt-link caller forwards prompt only for tracking=true and no pull request; legacy mode explicitly asks user to reopen link after clone. Unit test supplying prompt with tracking=false does not prove the real legacy link flow preserves it.
- Existing new-project flow and web/desktop are unchanged; no new UI entry points, contracts, adapters, or styles. Android shares mobile code but remains unverified; no native claims derive from mocked component tests.

## Real-app fixtures and routes

Lead should seed only its isolated environment through normal project creation / t3_project_create (absolute workspaceRoot), not SQL edits or live userdata. Create a small git checkout at host HOME/repro/bike-documents; register P with distinctive title “Bike documents”; ensure it is visible in the mobile client store. Record the environment ID, registered project ID and host-expanded HOME. Keep separate unregistered local Q and absent clone R/S destinations; use a harmless accessible small repository. Inspect project IDs/counts and clone calls to distinguish reuse from new creation. Never send a task from the resulting draft.

Real navigation routes in Stack.tsx: add-project; add-project/local (environmentId); add-project/repository (environmentId, source); add-project/destination (environmentId, remoteUrl, repositoryName, optional repositoryTitle/prompt); resulting draft route. Native schemes vary by build: t3code-dev, t3code-preview, t3code. Prefer ordinary UI navigation; do not assume a scheme without checking installed build. Destination route is only sufficient for P2 if actual navigation parses/passes its query params. Prompt-link flow lives in usePromptLinkResolver.ts; existing-project links may bypass clone selection, so use the resolver’s real clone choice or document route-level coverage explicitly.

Current server advertises projectCloneTracking=true. Legacy=false requires an actually compatible older environment or a supported capability fixture; do not hand-edit production configuration or pretend the current server exercises that branch. Permission loss, disconnected runtime, browse failure/null, draft failure, invalid input, clone failure and project synchronization timeout are source-reviewed branches, not mandatory separate visual fixtures for this narrowly scoped fix. Capture E1 if practical; report any unexecuted branch honestly.

## Availability / handoff

Provided baseline EAS native build: 304d5885-7ddc-4830-9f5e-26a7fce0f969. Lead-provided ready session: 01a1628c-e978-7fc7-8ef6-55d9a3a76011, currently pairing. Neither was opened or verified by this audit. Confirm baseline bundle corresponds to base and candidate bundle to head before labeling recordings. Android cannot be verified. User permits a fix PR with unavailable surfaces explicitly unverified; this audit does not create a PR.

FRICTION
- /home/ubuntu/t3code-ops/docs/EVIDENCE.md is absent; no evidence protocol was available there.
- Real legacy prompt-link caller drops the prompt; P2 needs explicit route-level coverage and cannot be substituted for real-link proof.
- Legacy tracking mode, fault injection and second-environment fixtures may be unavailable; report source-only coverage instead of native verification.
- No recordings captured in this read-only audit; all matrix rows remain pending runtime evidence.

Verdict: matrix derived from the complete diff; native behavioral proof remains pending.
