# PASS1 refresh — minimal proof matrix

Source audit complete; runtime proof NOT RUN. This is a capture handoff, not a visual PASS or merge verdict.

Scope: [#21113 GitCafe](https://git.cafe/pingdotgg/t3code/pulls/21113), [#21113 GitHub](https://github.com/pingdotgg/t3code/pull/21113). Inspected clean `/home/ubuntu/wt/pr-21113`, branch `fix/takeover-21113`. BEFORE [eea9895](https://github.com/pingdotgg/t3code/commit/eea989536849e5b5049987ee24318b5a77326542); AFTER [fe552d7](https://github.com/pingdotgg/t3code/commit/fe552d7d57bef4c4b5a04dbc34628b3a1c2dd830). Local origin/main and HEAD verified at those full SHAs. Both direct and three-dot comparisons have seven files, 179 insertions, 19 deletions. Entire diff and production callers/failure paths reviewed, including both test files; no test execution.

Supplied original provenance: LetZico/t3code `fix/no-project-machine-selection`, [073902d](https://github.com/LetZico/t3code/commit/073902d2df4ae573067252e4b97e9cd1c2dad6b9). Caution: the locally resolved object at that SHA is authored by Julius and titled “fix(desktop): native file links stay on the machine that owns them”; it already contains sole-eligible fallback. This audit does not verify the supplied fork/branch attribution. Proof compares the explicit BEFORE/AFTER above, not that object.

## Complete affected-source inventory

- `useScratchProject.ts`: eligible = connected with a non-null scratch root. Preserve eligible current; otherwise choose exactly one eligible machine, else null. New null-start error toast differentiates several eligible machines from none. Explicit-target `openScratchProject` is unchanged.
- `DraftHeroHeadline.tsx`: fallback enables subtitle/CTA for an unavailable active machine; classify active project using its own available root, never fallback machine's root. Empty draft opens destination draft; contentful draft retargets and preserves text. Existing model-default and stale-response guards remain. Normal/project/unresolved/no-project heading branches share this component.
- `CommandPalette.tsx` (unchanged caller): global “New thread without a project” and nested “New thread in...” → “No project” gain visibility and destination via shared fallback. Null target still hides both. Preferred environment = active server thread, active draft, primary.
- `routes/_chat.tsx`: shortcut now always consumes a recognized `chat.newWithoutProject` event and invokes start even for null target. Null means toast, no creation/navigation; prior silent no-op is fixed. Palette-open/defaultPrevented and terminal-focus guards remain.
- `NoProjectsHero.tsx` (unchanged caller): null/non-null target changes description and Start button; mounted on bootstrapped empty `/` and beneath `/welcome` wizard.
- `NewThreadLinkView.tsx`: no-repo auto-launch and missing-repository “Use without project” share scratch dispatch. Null now renders the precise unavailable reason. RPC returning null now renders “This machine could not start a thread without a project.” BEFORE already chose a sole alternative through its second resolver call; do not claim successful prompt fallback is newly fixed.
- `DesktopWebLinkCoordinator.tsx`: HTTP(S) with no reusable visible preview gains sole-remote fallback. Native file creation is explicitly primary-only, preserving prior behavior when primary lacks scratch. Existing primary preview reuse bypasses creation. Root mount is authenticated and bridge/connected-primary/config gated. Minimal injected webLinks delivery is HARNESS evidence, never native OS proof.
- Tests: new hook browser tests cover fallback/current/ambiguity and ambiguity toast; coordinator tests add remote HTTP attempt and native-file refusal. They mock dependencies and do not prove successful real RPC/preview. Zero-target toast and prompt failure rendering still need the matrix proof below.

No shared contracts, server, desktop-native integration, mobile-native UI, provider adapters, or explicit machine-routing implementation changed. Web desktop widths and responsive web at 390 are the affected render surface; Electron uses the same web tree. No multiplication by providers, OSes, MCP, schedules, or connection transports is required. No provider turn is needed.

## Capture contract

Every required row below runs on BOTH pinned revisions at **1440×900 and 390×844, light AND dark**, CSS viewport, DPR 1. Record actual viewport and image dimensions. Match browser, zoom/fonts, geometry/sidebar, data, selected environment/model, and checkpoint across revisions. Explicit theme setting; 390 is responsive web, not native mobile.

Every interaction is marked **RECORDING**. One continuous labeled recording may cover redundant entry paths, with fixture reset between actions that alter preference/draft state. Record before input (including real B shutdown where specified) through settled outcome. Use ffmpeg X11/Xvfb capture for those recordings; do not silently substitute preview recorder. Keep recorder/driver/seed scripts outside repo and publish sanitized scripts with evidence.

For EACH compared checkpoint (e.g. CTA availability, open palette, resulting draft, toast or failure page):

1. Independently establish within-version stability: retain two lossless samples 500 ms apart on BEFORE and two on AFTER, and compare decoded pixels for equality. This is a stability check, not either before/after diff. A timer alone is not proof. Capture toast checkpoints while visible and stable; retain recording of arrival/disappearance.
2. Compare the SAME checkpoint's stable BEFORE frame against its stable AFTER frame. Publish **TWO BEFORE-vs-AFTER DIFF IMAGES for that same pair**: `diff-zero-amplified` at threshold 0 (any changed channel), amplified for visibility; and `diff-threshold-16` with stated threshold 16/255 on maximum absolute RGB-channel difference. State amplification method/gain and output changed-pixel counts at both thresholds. Preserve raw lossless inputs; do not amplify inputs before measuring. These are not start-state versus end-state diffs. If both start and result need comparison, EACH pair gets its own two diff images.
3. Match crop/geometry exactly. Retain full-frame inputs/recording. Predeclare any identical crop needed for live reconnect animation; disclose it and excluded pixels. Never hide dynamic UI to manufacture equality. Report unstable proof as blocked rather than pass.

Each result records row/checkpoint, full SHA, theme/viewport, actual root/environment IDs (no credentials), action, expected/actual destination and mutation outcome, REAL versus HARNESS, stability and diff counts, pass/fail. Upload all evidence and sanitized reproduction/seed/driver scripts with `ghdrop upload -m`. Never upload pairing links, tokens, auth DBs, browser profiles, or private logs.

## Exact seed guidance for a later authorized capture

No servers or browser are authorized in THIS pass. Later captures use exactly **two real loopback T3 dev-server slots**, primary A and paired B; no live install, live-data seeding, T3 Connect, sharing, or submitted agent turns. Homes and all artifacts under `/tmp/ev-21113/`, outside any checkout. Start each pinned revision sequentially; do not change or overwrite a running home. Use the same absolute home/workspace paths across revisions, restoring stopped isolated snapshots (including draft localStorage/IndexedDB), so path differences do not contaminate pixels.

Per slot: `T3CODE_DEV_SEED=0 T3CODE_DEV_INSTANCE=<distinct-slot-number> vp run dev --no-seed --home-dir <isolated-home> --host 127.0.0.1 --no-auto-bootstrap-project-from-cwd`. No `--share`, `--browser`, VITE_HTTP_URL or VITE_WS_URL. Read actual ports from runner output; verify loopback listeners. Capture spawned process identities/backend PID; stop only owned captured PIDs, confirm backend port closed. Never kill by name/path pattern. Revision switching requires a later authorized workspace plan; this pass makes none.

Pair B through A Settings → Connections using B's private startup pairing URL. Verify real connected snapshots/config and mutation grants. Record RA/RB from published `scratchWorkspaceRoot`, not inferred layout. Unavailable means disconnected/reconnecting OR absent root, not missing providers. Seed ordinary projects through Add project into empty `/tmp` directories; use draft sessions only. Reset to equivalent stopped snapshot before each preference-changing action.

Seeds (same labels in matrix):

- **D — disconnected remembered remote:** A/B normal, distinct RA/RB; ordinary B draft “Remote work” active, A ordinary “Local work”. Stop captured B backend, retain saved B and cached draft. Wait observable offline/reconnecting and shell-discovery settlement. A is sole eligible. Record actual shutdown on both revisions. For contentful headline variant use unsent “Keep this draft”; ensure hero actually renders, with no setup/timeline/work state suppressing it.
- **M — ambiguous, three identities/two slots:** pair B1, create active B1 draft, stop B1. Start B2 in remote slot from different fresh home/identity, pair it. A+B2 eligible, remembered B1 unavailable. Confirm IDs differ; no third simultaneous server. Two eligible machines with an eligible current is NOT this seed.
- **Z — zero targets:** before A startup, `git init --quiet <A-home>` under /tmp. The cached repository probe removes A scratch root; verify actual config. Pair normal B, create remembered B draft, stop B. A connected/root absent; B unavailable. Fresh A process required after changing repository membership.
- **E — empty hero / primary lacks root:** A as Z; B normal connected/root present. No projects in either shell and bootstrap settled. `/` shows hero rather than automatic project landing.
- **C — own-root collision:** normal A/B with RA != RB. Add RA as an ORDINARY B project named “Remote collision”, open its empty draft, stop B. Own available B root becomes null. Both revisions must keep ordinary heading; AFTER enables fallback CTA. Comparing against fallback RA would falsely classify this B project as scratch. The pinned BEFORE does not have that misclassification.
- **L — bridge fallback:** A lacks root as Z, B normal connected. No active visible preview. Inject ONLY minimal `window.desktopBridge.webLinks` before root mount, queue URL delivery until `setReady(true)`. Keep config, connection, routing, RPC, draft creation and preview real. Controlled loopback HTTP HTML and harmless `/tmp` HTML file URL; static fixture server is not a third T3 server. Confirm preview capability. Missing capability blocks successful preview claim, not a reason to stub it and call it real.
- **R — real scratch-open failure:** normal connected A with published RA, no existing scratch project. With A stopped, place a regular file at RA (not directory), then start A. Config still advertises RA; recursive scratch-directory creation fails. Verify real RPC failure and no draft launch. Use only disposable fixture home; restore stopped snapshot after. This distinguishes selected-machine operation failure from target unavailability without mocking business logic.

Prompt `/new` preference comes from latest persisted thread shell updatedAt, else primary; active draft alone is insufficient. For M prompt case create a real stopped B1 thread with no initial message/provider turn through supported thread-launch RPC, verify latest updatedAt, then stop B1. Publish sanitized exact driver. If unavailable, mark only this preference subcase HARNESS/UNVERIFIED; do not pretend a draft seeds it. Z can use rootless primary with no latest thread, avoiding unnecessary persisted-thread seeding. For shared unchanged seed mechanics, see the [prior handoff](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/54ac933737e4198f/ev-21113-pass1-matrix.md); this refresh overrides its SHA, mandatory-control claims, null behavior, and incorrect diff definitions.

## Required affected matrix

All rows: BOTH revisions × both widths × both themes; RECORDING + stable paired checkpoints + the TWO diff images per pair above. Related rows/actions may share labeled recordings, not erase affected states.

| ID | Seed / affected render path | Actions and acceptance checkpoints |
|---|---|---|
| A | D: draft hero + both palette entries + shortcut | Record B shutdown and newly offered CTA; click headline on empty draft, reset and repeat with contentful draft (preserve text). Show ordinary heading → actual A scratch draft. On reset seed exercise palette global action, nested No project, and mod+alt+n in same labeled sequence: AFTER selects A, BEFORE actions absent/shortcut silent. Verify environment/route and real RPC outcome, not label alone. Picker after transition provides reverse ordinary-project selection; no separate search/menu-style matrix. |
| B | C: headline classification guard directly changed | Ordinary “Remote collision” heading remains on both; AFTER offers CTA and opens A scratch. Include open selector checkpoint retaining ordinary collision project. This checks own-root classification alongside availability, not a fictitious BEFORE classification bug. Can share A recording. |
| C | E: NoProjectsHero on `/`, shared `/welcome` rendering | Compare description/Start button (BEFORE absent, AFTER present); click → B draft. Include `/welcome` wizard-over-hero checkpoint in same sequence because it mounts the affected hero; do not operate wizard/setup merely for coverage. |
| D | M and Z: shortcut toast | From unavailable remembered current, trigger mod+alt+n with palette closed and non-terminal focus. BEFORE silently leaves draft; AFTER consumes shortcut, leaves destination/data unchanged and displays “Could not start without a project”. M description: “Several of your machines can start a thread without a project. Open a thread on the one you want first.” Z: “None of your machines can start a thread without a project right now.” No scratch RPC/create. CTA and both palette actions remain absent; capture absence within same flow, no separate mandatory control recording. |
| E | M and Z: prompt-link unavailable page | Navigate `/new?prompt=Proof%2021113` and reset-equivalent missing-repo link `/new?prompt=Proof%2021113&repo=proof-fixture/missing` → Use without project. Also missing-PR route `/new?pr=proof-fixture/missing%231&prompt=Proof%2021113` → same action; no clone/checkout. M AFTER reason = Several… rather than BEFORE None…; Z None… remains equal (required zero branch of changed failure dispatch, not a separate broad control suite). No launch. Combine entry routes in one recording per seed. |
| F | R: prompt-link selected machine failure | Same three scratch entry routes as E may share one reset-aware recording. BEFORE generic None…; AFTER “This machine could not start a thread without a project.” Retain actual scratch RPC error toast and failure-page checkpoint; no successful draft or provider turn. |
| G | L: bridge HTTP fallback / native-file guard | HARNESS bridge delivery only, real two-server execution. Deliver HTTP: AFTER creates B scratch draft and opens/maximizes real preview; BEFORE errors with primary root absent. Reset, deliver file: both error “Could not open the link”; no B scratch creation or asset request. File refusal is a necessary guard for the newly generalized resolver, not native OS association proof. |

Unchanged controls are OPTIONAL: eligible-current preference, ordinary successful prompt fallback, current-preview reuse, native-file success on eligible primary, stale continuation, picker search/no-matches/long titles, malformed links/clone/checkout, discovery ordering, explicit machine switch. Fold useful controls into recordings above; do not make all prior F/X rows mandatory. No mandatory server-thread/draft cross product: they share preference expression; persisted-thread seed is needed specifically for M prompt preference. No new CSS or theme branch was introduced.

## Limits / friction

No fetch, forge metadata/review/CI read, tests, server, browser, code edit, push, comment or watch. PR linked to this thread; only this outside-repo report and its authorized public upload are audit outputs. No runtime claim is established by inspection. Stop/mark the precise row unverified if real seed or preview cannot be established; injected native bridge is always labeled HARNESS.

FRICTION brief|happened: prior matrix mislabeled start/end diffs and made unchanged controls mandatory|prevention: same-checkpoint before/after zero-amplified plus stated-threshold images; separate 500ms stability; affected-only rows.

FRICTION runbook|happened: ambiguity requires three identities, prompt preference requires a persisted thread, and native delivery needs a bridge driver|prevention: reuse two slots; publish exact no-turn seed/bridge drivers; preserve REAL/HARNESS distinctions.

FRICTION other|happened: supplied original attribution differs from local commit metadata|prevention: disclose provenance limit and pin proof exclusively to verified BEFORE/AFTER SHAs.
