# Proof audit, pass 1 — remote editor route selection

PR [#27236](https://git.cafe/pingdotgg/t3code/pull/27236), branch `fix/issue-27203`; reviewed head [194948a4ea](https://github.com/pingdotgg/t3code/commit/194948a4eaa18bd56a19344c39aa230c83d8d0ca), merge-base [dd14848153](https://github.com/pingdotgg/t3code/commit/dd148481531a0a090780a2ade20588566db099a2). Read-only inspection in `/home/ubuntu/wt/pr-27236`. No browser, server, editor, network fixture, tests, edits, pushes, or PR comments were run by this audit. The recipes below are code-derived and have not yet been executed. Every evidence row is unverified until captured.

## Findings first

1. **A picker still cannot prove the fix.** No picker entry is an editor-URL anchor, and no visible picker text contains the selected host or login. Menu labels are editor names. The SSH hint uses the environment label, not the alias. The actual observable is the URL handed to `window.location.assign(url)` (web) or `desktopBridge.openExternal(url)` (desktop), which must be visible in the recording or paired with an exact URL trace tied to the action. Intercepting `window.open` captures nothing: this path does not call it. [Resolver and launch boundary](https://github.com/pingdotgg/t3code/blob/194948a4eaa18bd56a19344c39aa230c83d8d0ca/apps/web/src/remoteOpen.ts#L175), [picker action and rendering](https://github.com/pingdotgg/t3code/blob/194948a4eaa18bd56a19344c39aa230c83d8d0ca/apps/web/src/components/chat/OpenInPicker.tsx#L246).
2. **Plain web offers only VS Code for remote opens.** `remoteCapableEditorsAtom` defaults to `["vscode"]`; only desktop's `probeRemoteEditors` can replace that list, once per page, with a nonempty supported list. Server `availableEditors` does not expand the remote list. Do not claim real-web Zed/Cursor/JetBrains coverage by changing server editor availability. Use actual desktop, or label that expansion a bridge/probe harness. [Editor availability](https://github.com/pingdotgg/t3code/blob/194948a4eaa18bd56a19344c39aa230c83d8d0ca/apps/web/src/remoteOpen.ts#L155).
3. **The PR body overstates direct chat-file-link coverage.** `ChatMarkdown` reads the resolution only to gate host shell actions. Remote mode removes its direct host-editor and reveal actions. A remote text-file link opens the app's file panel, whose compact picker generates the SSH URL. Its HTML `href` is the file target path, not a generated editor URI. Settings/terminal/diff actions using `useOpenInPreferredEditor` still call host shell RPC and do not consume this resolver. [Chat file actions](https://github.com/pingdotgg/t3code/blob/194948a4eaa18bd56a19344c39aa230c83d8d0ca/apps/web/src/components/ChatMarkdown.tsx#L823), [file-link behavior](https://github.com/pingdotgg/t3code/blob/194948a4eaa18bd56a19344c39aa230c83d8d0ca/apps/web/src/components/chat/MarkdownFileLink.tsx#L320), [host editor helper](https://github.com/pingdotgg/t3code/blob/194948a4eaa18bd56a19344c39aa230c83d8d0ca/apps/web/src/editorPreferences.ts#L67).
4. **There is a visible enabled/disabled change beyond the reported wrong hostname.** A non-SSH preferred route with an alternate saved SSH alias and no advertised targets changes from `remote-unavailable` to `remote-links`. Before: disabled primary action and “No SSH route to …”. After: enabled action and editor options. This needs its own row.
5. **A real connected app does not require real SSH or Tailscale.** Persist a secondary `BearerConnectionTarget` with a loopback endpoint and a connection ID without the `local:` prefix; append SSH target/profile records for the same environment. The resolver treats that bearer environment as remote, even though its transport is local. However, `connectionRouteKind` checks loopback before `network: "tailscale"`, so this is a labelled transport substitute, not proof that the UI classifies the route as Tailscale. Real Tailscale HTTPS can be reproduced with a loopback TLS reverse proxy and browser-only hostname mapping; see recipe.

## Fixture matrix

All minimum rows use **1440×1000, dark theme**, with the same font/scale, selected environment, project, and safe fixture path on before/head. No theme or responsive styling changes in this diff justify a Cartesian theme/viewport sweep. A file-picker row must show the compact layout; a project row must show the thread-details panel layout. Narrow/popover and light theme are optional smoke checks. Every action or async transition is a **recording**; stills alone do not satisfy these rows. Multiple rows can be chapters of one continuous recording.

Definitions: `B` = saved bearer/direct route; `S(alias,user)` = SSH target plus SSH profile; `A` = advertised target array. `TS = {kind:"tailscale", host:"sol.tail1234.ts.net", username:"server-user"}`. `MD = {kind:"mdns", host:"sol.local", username:"server-user"}`. Use actual process username instead of `server-user` with the PATH-stub producer recipe. `P` is an actual scratch project directory, `F` is its existing `proof.txt`.

| Row | Named fixture and exact data | Diff effect / observable expectation | Paths and required interaction | Seed / authenticity | Minimum capture and status |
|---|---|---|---|---|---|
| A1 | Preferred direct + saved alias: `[B, S("sol-alias",null)]`, `A=[TS,MD]`, populated project/thread | **Affected.** Before URI uses `server-user@sol.tail1234.ts.net`; head URI uses bare `sol-alias`, with no server username. Picker appearance usually identical. | Thread-details Open-in dropdown → choose VS Code → click primary; favorite shortcut with project targeted; click markdown `[proof](proof.txt)` → file panel → compact picker primary; shortcut while panel is active must target file. Show project and file URLs. | Real web + secondary live local server + IDB seeding. Loopback bearer is a declared transport substitute; TLS/hostname variant gives actual Tailscale-labelled HTTPS route. Advertised config comes from actual producer with fake CLI or config-edge harness. | **Required, pending.** Before/head recording; wide dark. Include file `:1:1`, project without suffix, and that selecting a toolbar option alone does not launch. |
| A2 | Alternate alias, no advertised route: same `[B,S("sol-alias",null)]`, `A=[]` (omitted equivalent) | **Affected.** Before unavailable, primary disabled, menu “No SSH route to Proof remote”; head enabled editor and URI using alias. | Open project picker/menu; attempt before primary/shortcut; after select/open and show URI. | Same real app; config producer must actually return none, or explicitly labelled config-edge harness replacing `remoteOpenTargets` only. See sshd caveat below. | **Required, pending.** Before/head recording; wide dark. |
| A3 | First valid saved SSH route: `[B, S("",null), S("first-alias",null), S("second-alias",null)]`; optionally first SSH target has no profile; `A=[TS]` | **Affected selection branch.** Empty alias/missing profile skipped; first valid wins. Reorder the two valid SSH routes while B stays first; head must switch generated host. Explicit `username:"login-user"` overrides embedded alias user; bare alias does not acquire advertised username. | Settings Connections route order → return to thread → open URI → reorder → open URI again. | Real app with IDB seed; runtime reorder through Settings DnD, which calls `environmentCatalog.reorderRoutes`. Empty/missing-profile records are deliberate malformed-data harness inputs; normal two-valid-alias order is valid saved data. | **Branch extension, pending; not a separate minimum visual row.** Can append to A1 recording. Username cases are already resolver-tested, not separate layout fixtures. |
| R1 | Preferred SSH: `[S("sol-alias",null), B]`, `A=[TS]` | **Unchanged regression.** Alias used before/head, never advertised username. | Project picker and generated URI; show Settings preferred route plus the real desktop connection or explicitly labelled gateway fixture. | Actual desktop SSH route if available. Without SSH, use a **labelled SSH-gateway/bootstrap harness** pointing to the real secondary loopback server. Plain web cannot naturally establish this state: its unsupported SSH failure stops route connection before B fallback. | **Required, pending.** Head recording; wide dark. May be an A1/A3 sequence chapter. |
| R2 | No saved SSH: `[B]`, `A=[TS,MD]` | **Unchanged regression.** URI uses first advertised target including `server-user`; not the connection URL's loopback host. `A=[MD]` is same visual branch with different URL. | Project picker → primary → exact advertised URI. | Same live server + remove SSH records; actual producer or labelled config-edge fixture. | **Required, pending.** Head recording; wide dark. MD-only is optional branch extension. |
| R3 | Local environment: actual primary on loopback; available local VS Code; optionally saved/advertised remote data present | **Unchanged regression.** `local-exec` wins before any saved alias scan. Host shell RPC runs; no editor URI. Chat modifier/context action remains available with operate scope. | Local project picker → primary or favorite shortcut → capture `shell.openInEditor` input or scratch CLI log; local chat file action; include missing-media local toast from M2. | Real web primary. Use a scratch `code` CLI shim so opening is safe and logged. Actual desktop primary (including WSL nonloopback) and `local:` secondary are equivalent early-exit branches, inspected, not additional minimum browser captures. | **Required, pending.** Head recording; wide dark. Assert absence of remote URL alongside positive shell dispatch/log. |
| R4 | Remote unavailable: `[B]`, `A=[]`/omitted | **Unchanged regression.** No usable remote editor; menu unavailable copy and disabled primary; shortcut opens nothing. | Open chooser, show disabled entry, press shortcut and confirm zero launch calls. | Same live app with config-edge empty array if native producer cannot be made empty. | **Required, pending.** Head recording; wide dark. Can be A2-before/R2 cleanup chapter, but must also be shown on head. |
| M1 | Missing remote media: remote B, saved alias allowed, missing absolute media-file reference, error `AssetWorkspaceAssetNotFoundError` with `_tag:"media-file"`, filesystem scope present | **Changed call signature, unchanged output.** Toast “Media unavailable”; detail “The file was not found on Proof remote at …”. Uses prepared target label and checkedPath/path, not editor alias; no editor URL. | Click a missing media file link/fallback that invokes `openMarkdownMedia`; record the failed asset RPC and resulting toast. | Real server with nonexistent media path in a user message or fixture README rendered by FileMarkdownPreview. If link construction fails to reach media-file error, use labelled asset-RPC error harness; do not substitute generic HTTP 404 for the schema error. | **Required, pending.** Head recording; wide dark. One actual ChatMarkdown caller suffices; no need to duplicate every timeline/preview host. |
| M2 | Same missing media on local primary | **Unchanged regression.** Original generic/server error detail retained; no “on Proof remote” decoration. | Same action and toast, with prepared target local. | Real local primary, same markdown and nonexistent path. | **Required, pending; combine with R3.** Head recording; wide dark. |
| E1 | Four editor URL families: A1 data, viewing-machine probe yields `["vscode","cursor","zed","idea"]`; preferred editor changes per action | **Affected generated destination in each URL family.** Alias must survive VS Code/Cursor `ssh-remote+`, Zed `ssh/`, JetBrains `h=`; omitted user stays omitted. Project/file interpretation differs. | Choose each editor then primary. In toolbar/panel chooser only changes preference; if a menu-presentation harness is used, option click launches immediately. | Prefer actual desktop with those CLI probes available, recorded launch boundary. Otherwise **labelled full-app desktop-bridge/probe and external-launch harness** against live server. Plain web cannot naturally provide the latter three choices. Do not modify resolver or URL builder to fabricate results. | **Required, pending for the four-editor claim.** Before/head recording, or expand A1 into four editor chapters using same capture geometry. Include labelled harness status. |
| X1 | Existing picker visibility/control states: missing project/cwd, zero installed local editors, denied host operate scope, unresolved environment; hint already seen/unseen | **No changed UI branch.** Hidden/no-options/disabled/unresolved behavior depends on preexisting guards; remote list is never empty in ordinary web. | No minimum capture. Optional command/permission or hint transition smoke. | Natural real-app states where reachable. Zero remote editors is only a harness state since empty probe result retains VS Code. Unresolved loading may require delayed registry/config harness. | **Source covered, capture exempt.** Do not count a generic loading shot as alias proof. |
| X2 | Existing responsive/platform/presentation states: thread full vs compact/essential/popover, file compact toolbar, unused menu presentation, OS icon labels, light/dark | **No style/layout changes.** Full/compact show project picker; essential or user-hidden Open-in row removes it. File panel has compact icon primary. Background threads disable shortcut marker/listener. | A1 already exercises project panel and file compact layouts; remaining variants optional. `presentation="menu"` has no production caller in this head. | Real app resize/customize/OS for reachable states; menu presentation is component/full-app harness only. | **Source covered, capture exempt beyond A1.** Native mobile has no consumer of the changed web module. |

## Complete changed-path inventory and collapse rationale

### Resolver and its two direct callers

[remoteOpen.ts](https://github.com/pingdotgg/t3code/blob/194948a4eaa18bd56a19344c39aa230c83d8d0ca/apps/web/src/remoteOpen.ts#L55) has these branches:

- Null target → local; Primary target → desktop local regardless of host, or browser local only for parsed loopback hostname; `BearerConnectionTarget` whose ID starts `local:` → local on either renderer. Other primary URLs, bearer IDs, relay, SSH enter remote resolution. Invalid primary URL simply falls through to remote selection.
- Scan `connectionRoutes(entry)` in order: primary/preferred route followed by `alternateRoutes`; ignore absent/non-SSH profiles and zero-length aliases; choose first valid SSH profile. No alias trimming occurs before the length check. Split alias at last `@`; trimmed explicit username wins, otherwise embedded alias user; otherwise omit user. Those username rules are existing behavior now applied to alternate routes too.
- With no valid SSH alias, use advertised element zero (no target host-kind filtering); if missing, remote unavailable. Array length above one changes selection only, not rendering. TS and mDNS have identical picker presentation.
- `remoteOpenResolutionAtom`: no presentation entry → unresolved `{state:local-exec,isResolved:false}`; entry present → resolved. Saved routes may make the URI available even before server config arrives. Equal state/user/host/kind retains object identity on config pushes. No new animation/loading UI is added.
- The other direct caller is ChatMarkdown's missing-media rejection handler, which passes **empty routes and undefined advertised targets** solely to decide local vs remote. Thus a remote target is unavailable there, but only the `mode !== local-exec` predicate matters. Do not seed editor alias into this direct call or expect alias in that toast.

Consumers of the atom are **OpenInPicker**, **OpenInPickerShortcut**, **ChatView** (visibility + fallback shortcut), **FilePreviewPanel** (visibility), and **ChatMarkdown** (shell-action permission gating). `useRemoteOpenState` is a thin projection of the resolution hook; no additional user-visible consumers were found.

### Real picker entry points and interaction shapes

- ChatView → ThreadDetailsPanel → `OpenInPicker(displayMode="panel", cwd=gitCwd, isFile=false)`. Thread details must be visible, density not essential, Open-in row enabled in customization, and project title present. Primary environment always qualifies; nonprimary qualifies when mode is not local-exec. The panel can be inline or popover depending on canvas space; density/visibility only affects reachability, not host selection. [Panel caller](https://github.com/pingdotgg/t3code/blob/194948a4eaa18bd56a19344c39aa230c83d8d0ca/apps/web/src/components/chat/ThreadDetailsPanel.tsx#L150).
- FilePreviewPanel → `OpenInPicker(compact=true, cwd=absolutePath, isFile=file.isFile)`. Requires absolute path and either primary environment or non-local mode. Files add VS Code `:1:1`; folders do not. Attachment-only previews without absolute path have no picker. Content loading/error/media/rendered mode does not change selected host. Wait for real file detection before asserting file suffix; the `isFile` result can settle after mounting. `revealFileManager` only affects local file-manager RPC. [File caller](https://github.com/pingdotgg/t3code/blob/194948a4eaa18bd56a19344c39aa230c83d8d0ca/apps/web/src/components/files/FilePreviewPanel.tsx#L1260).
- Toolbar/panel menu option **sets preferred editor only**; primary click launches. Menu-presentation options launch immediately, but there is no production caller supplying `presentation="menu"` in this revision. Panel uses full “Open in …” label; compact file control hides text. Options depend on effective installed/probed IDs; zero, one, many and preferred-shortcut label are existing presentation branches.
- Favorite command's capture-phase handler clicks the last marked enabled picker primary button (file panel can win over project). If none is enabled/marked, ChatView's bubble listener can open project cwd. To exercise fallback intentionally, hide the Open-in row via Thread Details customization while keeping the project selected, close file panels, and press the configured shortcut; do not assume closing a dropdown tests fallback. Background thread disables both marker and fallback listener. [Shortcut](https://github.com/pingdotgg/t3code/blob/194948a4eaa18bd56a19344c39aa230c83d8d0ca/apps/web/src/components/chat/OpenInPickerShortcut.ts#L18).
- A successful remote open marks hint seen and persists preferred editor. Failure/refusal leaves them unchanged. Probe pending/rejected/empty uses VS Code fallback; nonempty supported result replaces it. Hint unseen/seen changes only instructional row. Local operate scope can disable primary and chooser; remote URLs launch on viewer and do not use that host-operation guard.
- No changed CSS, theme branches, width thresholds, provider adapters, RPC schema, server behavior, mobile renderer, or desktop IPC implementation exists in this diff. Mobile does not import this web module. Other host-shell editor entry points in settings, DiffPanel, GitActionsControl, KeybindingsConfigWarning and ThreadTerminalDrawer do not call this resolver and are outside alias-capture scope.

### ChatMarkdown rendering and media branch

Production caller inventory: TimelineAssistantRows; TimelineUserMessageRow; TimelineWorkEntryRow (two contexts); TimelineWorkGroupRows (two contexts); UserMessageContextChips (two contexts); V2ItemInspector; ComposerPendingUserInputPanel; ProposedPlanCard (expanded/collapsed contexts); WorkflowOpeningBlock; composerContextPresentation; FileMarkdownPreview; NotebookPreview; AttachmentFilePreview; PullRequestMarkdown. All share the same hook/renderer and have no caller-specific alias resolution. [Component source](https://github.com/pingdotgg/t3code/blob/194948a4eaa18bd56a19344c39aa230c83d8d0ca/apps/web/src/components/ChatMarkdown.tsx).

Relevant data shapes are effective environment (`threadRef.environmentId` overrides explicit environment, otherwise null), cwd/imageBaseDir for resolving relative media, threadRef for panel navigation, filesystem/host/preview grants, and error shape. Media success opens image/video gallery or panel; rejection can be ordinary Error (its message), non-Error (generic detail), or the schema-recognized missing media-file error (remote-specific decoration only when an environment and a prepared nonlocal target exist). Missing prepared connection, local target, non-media resource, or unrecognized error retains original detail. Scope changes/unmount invalidate stale successful media-preview results; this is existing lifecycle handling. M1/M2 exercise the changed call's two observable branches. Different markdown lengths, code blocks, tables, raw HTML, streaming, inline mode, math, theme, and task lists never enter the changed resolver line, so they do not warrant a separate capture matrix.

## Seeding a connected real app

### Client catalog: exact storage and data

[Web storage](https://github.com/pingdotgg/t3code/blob/194948a4eaa18bd56a19344c39aa230c83d8d0ca/apps/web/src/connection/storage.ts#L43): IndexedDB database **`t3code:connection-runtime`**, version **4**, object store **`catalog`**, key **`document`**, value a **JSON string**. Do not put an object value there and do not write an old localStorage environment key. Document schema is `{schemaVersion:1, targets:[], profiles:[], credentials:[], remoteDpopTokens:[], disabledEnvironmentIds:[]}` with optional `githubRoutingPermissions`. [Schema and ordering](https://github.com/pingdotgg/t3code/blob/194948a4eaa18bd56a19344c39aa230c83d8d0ca/packages/client-runtime/src/platform/storageDocument.ts#L20).

Routes are not serialized as `alternateRoutes` or Option values: **ordered `targets` records sharing environmentId** become preferred target + alternates at registry load; `profiles` join by connectionId. First matching route order is preserved. [Registry load](https://github.com/pingdotgg/t3code/blob/194948a4eaa18bd56a19344c39aa230c83d8d0ca/packages/client-runtime/src/connection/registry.ts#L225), [connectionRoutes](https://github.com/pingdotgg/t3code/blob/194948a4eaa18bd56a19344c39aa230c83d8d0ca/packages/client-runtime/src/connection/routes.ts#L40).

Example additive records (replace E with the secondary server's **real descriptor environment ID**, retain valid paired B credentials):

```json
{
  "target": {"_tag":"SshConnectionTarget","connectionId":"proof:ssh-1","environmentId":"E","label":"Proof remote"},
  "profile": {
    "_tag":"SshConnectionProfile","connectionId":"proof:ssh-1","environmentId":"E","label":"Proof remote",
    "target":{"alias":"sol-alias","hostname":"sol.tail1234.ts.net","username":null,"port":null}
  }
}
```

Place target after B in `document.targets` and profile in `document.profiles`. B has `_tag:"BearerConnectionTarget"`, ID such as `proof:direct` (never `local:*`), label and environmentId. Its profile has `_tag:"BearerConnectionProfile"`, same IDs/label, `httpBaseUrl`, `wsBaseUrl`, optional `network:"tailscale"`; credential record is `{connectionId,credential:{_tag:"BearerConnectionCredential",token:<real private fixture credential>}}`. Primary targets are platform supplied and not valid persisted-target records.

Seed while the app is quiescent, then **reload**; CatalogStore caches the decoded document in a Ref, so direct IDB writes do not update the running atom. Avoid active writes racing the injection. Use a clean disposable browser profile/origin and retain a private snapshot of the original document. Do not publish its credentials. For runtime reorder use Settings → Connections → saved environment → routes; list is explicitly labelled “preferred first”, supports pointer/keyboard DnD, and invokes `environmentCatalog.reorderRoutes({environmentId,routeIds})`. [Routes UI](https://github.com/pingdotgg/t3code/blob/194948a4eaa18bd56a19344c39aa230c83d8d0ca/apps/web/src/components/settings/EnvironmentRoutesList.tsx#L40).

LocalStorage is relevant only for preference/appearance: `t3code:last-editor` is JSON editor ID, e.g. `"vscode"`; `t3code:remote-open-hint-seen` is JSON boolean. Seed before reload; ordinary direct localStorage writes in the same tab do not notify the app's custom subscription event. Use an otherwise empty disposable profile to get unseen hint, then record it disappearing after successful accepted open.

Desktop uses the same JSON catalog document through `desktopBridge.getConnectionCatalog()` / `setConnectionCatalog(raw)`, not web IDB for that catalog. Desktop persists an encrypted `connection-catalog.json` in its stateDir using Electron safeStorage. Do not hand-edit the encrypted file. Seed only the isolated desktop instance via the bridge and reload. [Desktop backend](https://github.com/pingdotgg/t3code/blob/194948a4eaa18bd56a19344c39aa230c83d8d0ca/apps/web/src/connection/storage.ts#L390), [encrypted store](https://github.com/pingdotgg/t3code/blob/194948a4eaa18bd56a19344c39aa230c83d8d0ca/apps/desktop/src/app/DesktopConnectionCatalogStore.ts).

### Real dev servers and transport choices

1. Run only capturer-owned processes with explicit scratch home directories, e.g. `vp run dev --home-dir /tmp/lead-27236-r1/proof-audit-1/<timestamp>/local-home --no-seed`, and a second instance with another home and `T3CODE_DEV_INSTANCE`. Read actual ports from dev-runner output; do not alter the lead's live state or `.t3`. Keep both VITE origin override variables unset. Wait for any existing worktree setup before installing dependencies. This audit did not start either server.
2. Pair the disposable browser to its primary server through its startup URL. Register the second server as a saved direct environment through the app's pairing/add-environment flow, or use its real descriptor at `/.well-known/t3/environment` and a fixture-only minted credential to build a schema-valid B registration. Creating an environment by inventing E or a bearer string cannot establish a real session. Keep pairing tokens out of recordings/uploads.
3. Make a scratch project directory P with `proof.txt` and README containing `[proof](proof.txt)` plus a missing media-file link; create/select the project and thread in secondary E. This uses actual server state and reads, without contacting an agent. A markdown file preview is a reliable real ChatMarkdown host if a conversational fixture is inconvenient.
4. Add SSH records to the secondary environment's catalog document as above. As long as B works and stays preferred, its saved SSH alias is never used to connect: no SSH config/network is required. A preferred SSH entry needs desktop or a labelled gateway harness for R1. In plain web its SSH gateway returns `unsupported`, which aborts `connectOverRoutes` before trying B; do not promise a natural bearer fallback.
5. A loopback B endpoint with `network:"tailscale"` is sufficient for the resolver but UI route kind remains loopback. For a faithful **Tailscale HTTPS labelled route**, use a scratch TLS reverse proxy to the secondary server with host `proof.tail1234.ts.net`, valid/trusted fixture certificate or explicitly declared certificate harness, and browser process host-resolver mapping to `127.0.0.1`. Pair/register its HTTPS/WSS origin, set `network:"tailscale"`, retain the remote E ID. Forward all HTTP, OAuth/well-known, and WebSocket traffic; configure the app's supported dev-origin/proxy requirements instead of baking origins in Vite. For LAN, use an actual local private address endpoint to the same server. These transport variants do not change resolver host selection and are not separate minimum visual rows. They have not been run here.

### Producing advertised remote-open targets without real Tailscale

[Real producer](https://github.com/pingdotgg/t3code/blob/194948a4eaa18bd56a19344c39aa230c83d8d0ca/apps/server/src/environment/RemoteOpenTargets.ts#L24) checks TCP port 22 on both loopback families, then asks `tailscale status --json`; advertised username comes from `os.userInfo().username`, not the saved SSH profile. With sshd listening: optional Tailscale target first, then `<first hostname label>.local`. Without sshd: only advertise Tailscale when `tailscale debug prefs` says `RunSSH:true` and `WantRunning` is not false. No sshd and no enabled Tailscale SSH → empty targets. Config assembly puts this in server config; it is **not a server setting or arbitrary JSON setting override**. [Config assembly](https://github.com/pingdotgg/t3code/blob/194948a4eaa18bd56a19344c39aa230c83d8d0ca/apps/server/src/ws.ts#L1755).

A scratch executable named `tailscale`, prepended to **only the fixture server's PATH**, can return:

```text
tailscale status --json -> {"Self":{"DNSName":"sol.tail1234.ts.net.","TailscaleIPs":[]}}
tailscale debug prefs   -> {"RunSSH":true,"WantRunning":true}
```

Return a nonzero exit for every other command. Do not enable actual Tailscale Serve/SSH, change tailnet state, or bind fake sshd on port 22. That yields actual config produced by the real app with a **declared fake discovery CLI**, and uses the real server OS username (record that expected user, e.g. `ubuntu`). Its hostname does not need to resolve because this audit stops at URI dispatch.

For an empty target row, a false/failed status + `RunSSH:false` works **only when port 22 has no local listener**. If sshd is already running, mDNS remains advertised; do not stop it. Use a **labelled config-edge harness** to set `remoteOpenTargets:[]`, preserving the rest of the real server config and all real RPCs. WebSocket RPC serialization is JSON; the affected payloads are `server.getConfig` result and `subscribeServerConfig` `type:"snapshot"` event's `config`. Intercept both initial config and subsequent full snapshots, otherwise a push overwrites the fixture. Runtime may persist server config in IDB `server-config`, but editing that cache alone does not override live server responses. A transport/frame mapper must preserve request IDs, arrays, event wrappers and unrelated properties, and only replace this field on recognized config objects. This is proposed harness work, not an executed fixture.

### Preferred-SSH regression without an SSH network

R1 needs a real desktop connection or a labelled gateway harness. At the desktop bridge boundary, `ensureSshEnvironment(target,{issuePairingToken:false})` can return `{target,httpBaseUrl:<live secondary loopback>,wsBaseUrl:<live secondary websocket>,pairingToken:null}`. Supply a valid stored credential for the SSH connectionId; its `fetchSshEnvironmentDescriptor` and `fetchSshSessionState` methods must use the real server and return its actual identity/auth grants. `prepareDesktopSshEnvironment` verifies environment ID and standard scopes, then the real broker authorizes the live session. Preserve those checks. Without a saved credential the provisioning branch needs a genuine fixture pairing credential and `bootstrapSshBearerSession`, so the saved-credential route is simpler. This mocks SSH transport setup only, not catalog/resolver/URL output, and must be labelled accordingly. [SSH bootstrap logic](https://github.com/pingdotgg/t3code/blob/194948a4eaa18bd56a19344c39aa230c83d8d0ca/apps/web/src/connection/platform.ts#L264), [unsupported stops fallback](https://github.com/pingdotgg/t3code/blob/194948a4eaa18bd56a19344c39aa230c83d8d0ca/packages/client-runtime/src/connection/driver.ts#L114).

### Making the URI observable

Best unmodified-web option: record the actual app action and pause at a DevTools breakpoint on the `window.location.assign(url)` line; show the runtime `url` and initiating UI. This proves generated URL without relying on OS editor installation. A debugger can then skip/resume safely using the capturer's tooling. Do not attempt to monkey-patch `window.location.assign`: browser Location members commonly cannot be replaced.

For repeatable in-page recordings, use a **clearly labelled launch-boundary harness** that records the exact `url` argument in a visible fixed `<pre>` overlay and a JSON trace, then suppresses only external dispatch. Instrument `openRemoteEditorUrl`'s final boundary, not `resolveRemoteOpenState`, `connectionRoutes`, `buildRemoteOpenUrl`, or their results. Preserve the success/refusal result deliberately and label it “accepted by capture harness”, not “editor connected”. Vite response transformation or a proper desktop bridge adapter can do this without source edits. A genuine desktop can instead observe its real `openExternal` argument. A browser-only desktop bridge shim must implement catalog/bootstrap methods and probe before first app initialization; a tiny object containing only `openExternal` is not a valid startup bridge and changes platform behavior. If injecting only a post-mount external-launch hook, disclose it and avoid recomputing primary/local semantics through a new bridge.

The visible overlay/trace should identify revision, row, selected environment, preferred and active route IDs, action (project primary/file primary/shortcut), editor ID, path, actual URL, and observed dispatch acceptance. Scrub all auth/session data. Preserve an unmodified raw URL as well as any decoded display. No successfully connected editor or remote SSH session is required; do not claim one.

Expected A1 sample outputs with P=`/work/project` and bare alias:

```text
vscode://vscode-remote/ssh-remote+sol-alias/work/project
cursor://vscode-remote/ssh-remote+sol-alias/work/project
zed://ssh/sol-alias/work/project
jetbrains://gateway/ssh/environment?h=sol-alias&launchIde=true&ideHint=IU&projectHint=%2Fwork%2Fproject
```

Before A1 VS Code: `vscode://vscode-remote/ssh-remote+server-user%40sol.tail1234.ts.net/work/project`; Zed: `zed://ssh/server-user@sol.tail1234.ts.net/work/project`; JetBrains `h=sol.tail1234.ts.net` and `u=server-user`. For actual scratch P, substitute its exact absolute path and let the real builder encode it. File VS Code/Cursor adds `:1:1`; Zed/JetBrains use the real file path without that VS Code suffix. [URL builder](https://github.com/pingdotgg/t3code/blob/194948a4eaa18bd56a19344c39aa230c83d8d0ca/packages/contracts/src/editor.ts#L177).

## Handoff / limits

Minimum pending evidence: A1, A2, R1, R2, R3+M2, R4, M1, E1. These can share recordings; minimum geometry is one wide dark viewport per row. A1 must include both real production picker layouts and both shortcut targeting modes (marked picker and project fallback). E1 may be combined into A1 if captured in desktop or a labelled full-app probe harness. A3, X1, X2 are explicit branch extensions/exemptions, not missing mandatory captures.

Before evidence must run the merge-base implementation with the same fixture and external-boundary observation; do not reconstruct the old output manually or render a fabricated before UI. Head evidence must run reviewed head. Record revision and fixture identity in safe evidence metadata. Keep every run under a new timestamped directory in `/tmp/lead-27236-r1/proof-audit-1/`; do not delete raw logs/evidence before upload. Stop if disk available drops under 5 GB.

Coverage completed: all three diff files; both direct resolver callers; all web hook consumers; actual production picker callers; ChatMarkdown shell/media paths and caller inventory; catalog persistence/registry ordering; desktop bridge persistence; server remote-target discovery/config publication; editor URL families and shortcut dispatch. No runtime seeding/capture was attempted, so recipes remain to be validated by the capturer. Disk had 16 GB available at start.

FRICTION: none

VERDICT: INSUFFICIENT A1, A2, R1, R2, R3+M2, R4, M1, E1 recordings not captured
