**Proof audit, pass 1 — findings first.** Reviewed [#26975](https://git.cafe/pingdotgg/t3code/pull/26975), branch `t3/scratch-auto-balance`, fixed head [52314e7ca2](https://git.cafe/pingdotgg/t3code/commit/52314e7ca2bd205d65e41961ad36426363259439) against merge-base [20497e4890](https://git.cafe/pingdotgg/t3code/commit/20497e48907c2ddbbd9a2ab3c3ef74024f9e4a74). Scope: code-derived fixture design; no captures, browser sessions, servers, tests, edits, pushes or comments were performed. `git diff --check` passed. Existing earlier-revision screenshots and comments are not evidence for this pass.

1. **Proof blocker: every affected visual row A01–A32 is missing.** A success still or two-machine menu alone cannot establish the preparation, failure recovery, manual-over-Auto, stale-completion or machine-pin claims. All affected rows involve an interaction or time and require recordings; keyframes may supplement them.
2. **The busy-state copy needs an intentional hover.** `Preparing machine` is the Send button's accessible name and tooltip, not a text label on the circular button. Preparation alone does not make that button spin (`isSendBusy` controls the spinner). Capture the send wrapper tooltip and the transition to ready, together with an RPC/draft-state transcript identifying the destination. [ChatView.tsx:3502](https://git.cafe/pingdotgg/t3code/blob/52314e7ca2bd205d65e41961ad36426363259439/apps/web/src/components/ChatView.tsx#L3502), [ComposerPrimaryActions.tsx:285](https://git.cafe/pingdotgg/t3code/blob/52314e7ca2bd205d65e41961ad36426363259439/apps/web/src/components/chat/ComposerPrimaryActions.tsx#L285).
3. **Two isolated servers suffice for ordinary real routing, not for all evidence.** They cover scratch missing/existing, manual override, contexts, attachments, project routing and app-driven triage. Precise races/errors require controlled responses; three-way pick replacement and many-machine layout need labelled harness data. Browser bridge mocks cannot establish native Electron handoff. Mobile has no Auto balance and is excluded, but narrow web remains in scope.
4. **Failure UI has two materially different endpoints.** A host-resource query failure can show `Auto balance unavailable`; zero eligible candidates with no failed query still shows `Auto balance`. A scratch-open failure shows its error toast, then unresolved Auto uses the generic resource warning on Send. Capture these separately; do not expect an automatic retry. This last limitation is already acknowledged by the PR description. [useDraftEnvironmentRouting.ts:157](https://git.cafe/pingdotgg/t3code/blob/52314e7ca2bd205d65e41961ad36426363259439/apps/web/src/components/chat/useDraftEnvironmentRouting.ts#L157), [composerSend.logic.ts:15](https://git.cafe/pingdotgg/t3code/blob/52314e7ca2bd205d65e41961ad36426363259439/apps/web/src/components/chat/composerSend.logic.ts#L15).
5. **No new implementation bug is asserted by this proof-design pass.** No runtime verification was attempted. At the metadata snapshot the forge reported a merge conflict against a newer main and two pending checks; those are separate from this fixed-head proof verdict. The model-carry claim in the PR description is not an additional implementation in this nine-file diff; preserve chosen model as a regression check, not as an invented new picker API.

**Render/caller inventory and equivalence rules.** Inventory follows the changed outputs and their reachable descendants. Unchanged timeline/file-preview/approval contents are not multiplied into a Cartesian product of chat states.

- **ChatView** has one production component caller, `ThreadRouteView`, with three JSX paths: existing draft (`draftId`, routeKind draft, environment/thread from session, `forceExpandedMobileComposer` true); promoted draft redirect (same key, routeKind server); ordinary ready/server-shell-loading thread (routeKind server). No `ChatView` renders for a missing draft without redirect, an unlisted server still loading, or a confirmed missing thread. `_chat` retains the same view inert behind Settings/Usage modal pages. The other props (`onDiffPanelOpen`, `reserveTitleBarControlInset`) have no alternative supplied caller values here. The draft route is `/draft/$draftId`; the server route is `/$environmentId/$threadId`. [ThreadRouteView.tsx:106](https://git.cafe/pingdotgg/t3code/blob/52314e7ca2bd205d65e41961ad36426363259439/apps/web/src/components/ThreadRouteView.tsx#L106), [_chat.tsx:19](https://git.cafe/pingdotgg/t3code/blob/52314e7ca2bd205d65e41961ad36426363259439/apps/web/src/routes/_chat.tsx#L19).
- **Changed ChatView gates:** active project absent vs scratch vs ordinary; logical environment counts 0, 1, >=2; settings unhydrated/off/on; draft vs server/promoted; envLocked from messages/runtime; manual/auto/unset selection; unresolved vs cached `loadBalancedEnvironmentId`; attachments absent/present before or after cached pick; branch absent/present (branch allowed only with explicit auto); worktree absent/present. Those determine label/callback/picker availability, not just whether a settings toggle exists. The two changed callback props reach (1) composer `BranchToolbar` when context strip shows and (2) `ThreadDetailsPanel` → panel BranchToolbar. `canChangeEnvironment` additionally rejects promoted/no-draft states. [ChatView.tsx:1158](https://git.cafe/pingdotgg/t3code/blob/52314e7ca2bd205d65e41961ad36426363259439/apps/web/src/components/ChatView.tsx#L1158), [ChatView.tsx:1222](https://git.cafe/pingdotgg/t3code/blob/52314e7ca2bd205d65e41961ad36426363259439/apps/web/src/components/ChatView.tsx#L1222).
- **Toolbar rendering:** scratch root is normally non-git, so the settled strip uses standalone `BranchToolbarEnvironmentSelector` at every width. Git-status initially unknown defaults true and can transiently expose the git toolbar shape; A24/A25 cover its visual forms, A05 should record the loading transition. Git projects use separate selectors when composer container >=`3xl` and combined `RunContextSelector` below it. This is a container breakpoint, not simply window width. Panel layout always uses `RunContextSelector` with `displayMode=panel`, `panelSection=workspace`. Indicator can be a scale or machine glyph; labels are Auto/Checking/unavailable or machine/fallback; locked control is a span/tooltip. Menu rows map the whole environment array (primary first, remaining labels sorted), short/long labels can truncate, label overflow compacts the strip to icons. Machine kinds change icons only. Workspace label is current checkout/new worktree/current worktree, with extra previous-worktree option if available; grouped projects can also show Add to another machine. These inherited rows are represented in A24–A29/C04, not separate new features. [BranchToolbar.tsx:167](https://git.cafe/pingdotgg/t3code/blob/52314e7ca2bd205d65e41961ad36426363259439/apps/web/src/components/BranchToolbar.tsx#L167), [BranchToolbar.tsx:677](https://git.cafe/pingdotgg/t3code/blob/52314e7ca2bd205d65e41961ad36426363259439/apps/web/src/components/BranchToolbar.tsx#L677), [BranchToolbarEnvironmentSelector.tsx:38](https://git.cafe/pingdotgg/t3code/blob/52314e7ca2bd205d65e41961ad36426363259439/apps/web/src/components/BranchToolbarEnvironmentSelector.tsx#L38).
- **Details surface:** inline vs popover derives from measured canvas placement; full/compact/essential derives from available height and measured content. Only full density plus environment visibility renders the changed environment row. Closed/compact/essential/visibility-off are absent-row controls. Menus open downward in the panel, upward in compact toolbar; standalone uses SelectPopup. Details menu also has Workspace options; standalone does not. [ThreadDetailsPanel.tsx:147](https://git.cafe/pingdotgg/t3code/blob/52314e7ca2bd205d65e41961ad36426363259439/apps/web/src/components/chat/ThreadDetailsPanel.tsx#L147), [ThreadDetailsCard.tsx:44](https://git.cafe/pingdotgg/t3code/blob/52314e7ca2bd205d65e41961ad36426363259439/apps/web/src/components/chat/ThreadDetailsCard.tsx#L44).
- **Send surface:** current preparation request scope gives Preparing machine; permission block takes precedence in ChatView, disconnected status takes precedence in the primary-action tooltip. Other ChatView reasons (rewind, feedback, messages, worktree, clone) follow preparation. Both expanded and compact composer action rows receive the reason. Draft route forces expanded mobile composer in hero state; collapsed mobile started-thread, running/stop/resume, question/approval and provider-subagent modes cannot normally start this routing and are controls, not new Auto fixtures. Submit handlers also reject pending request refs and unresolved load balancing, including keyboard submission. First send/draft promotion must retain the correct machine and remove pickers. [useComposerSend.ts:430](https://git.cafe/pingdotgg/t3code/blob/52314e7ca2bd205d65e41961ad36426363259439/apps/web/src/components/chat/useComposerSend.ts#L430).
- **useDraftEnvironmentRouting** has one production hook caller (`ChatView`) and a dedicated browser-test `Harness` caller (scratch true/default or false); `useComposerSend` additionally imports its return type and consumes `readPendingEnvironmentChange`. It renders nothing itself. Candidate filters are connection connected; weight >0 (default 50); every referenced thread context on candidate; selected instance match or null; driver match; project-level enabled/default provider enabled; installed; status not error; auth not unauthenticated; availability not unavailable. Resource states are initial/pending, success-fresh, success-unusable/stale, failure, and mixed failures with a still-usable winner (collapse to normal winner). Candidates 0/1/many collapse to no choice/current/peer outcomes; missing provider map, all disabled/excluded, or resource pressure share A08. Deleted inline context text means orphan thread-context records no longer constrain routing. [useDraftEnvironmentRouting.ts:82](https://git.cafe/pingdotgg/t3code/blob/52314e7ca2bd205d65e41961ad36426363259439/apps/web/src/components/chat/useDraftEnvironmentRouting.ts#L82), [useLoadBalancedEnvironment.ts](https://git.cafe/pingdotgg/t3code/blob/52314e7ca2bd205d65e41961ad36426363259439/apps/web/src/hooks/useLoadBalancedEnvironment.ts), [load-balancing.ts](https://git.cafe/pingdotgg/t3code/blob/52314e7ca2bd205d65e41961ad36426363259439/packages/client-runtime/src/load-balancing.ts).
- **Routing interactions:** choose Auto (attachments warn, otherwise cancel/refetch/generation increment/reset branch and worktree); manual machine; selected-row Auto retry through both onValueChange/onClick implementations; existing project direct retarget vs missing scratch async open; scratch remap through logical-key store vs ordinary project set-context. Guards reject locked/no draft/sending/no current draft/promoted/missing target, stale identity/scope, changed original environment/project, and external manual pin. Current/old request completion, failures, unmount/scope changes, pick loss or new pick, manual request in flight, cached pick, repeated renders and send in flight all matter. A06 and A13–A18/A31–A32 exercise these; identical pixel outcomes may share clips but need a transcript for each controlled ordering. There is no automatic retry loop after a failed attempt; Auto retry or new pick re-arms it.
- **useHandleNewThread / useNewThreadHandler** return handlers and render nothing. Direct `useNewThreadHandler` consumers: `_chat.index`, `welcome`, `useThreadActions`, `useScratchProject`, `useThreadActionMenu`, `useStartTriage`, `useNewProject`, `AddProjectToMachineDialog`, `ProjectCloneToastCoordinator`, `ChatView`, `DraftHeroHeadline`, `useComposerSend`, `DesktopAppActivationCoordinator`, `DesktopWebLinkCoordinator`, `NewThreadLinkView`, `PullRequestDetailPanel`, `usePullRequestActions`; `useHandleNewThread` itself. The latter wrapper is consumed by Sidebar, CommandPalette, SnapShotCoordinator and useActiveProjectTarget (file picker/search target only, not new creation); chatRouteCommands directly calls createNewThreadHandler. `chatThreadActions` and ChatView.logic accept it as callback helpers. Tests call both hook/factory. Only triage and desktop web-link startThread newly pass `environmentSelection:manual`; others retain ordinary behavior. Every changed store write is covered: indexed empty stored draft (already open vs not open, explicit workspace vs awaited defaults), active empty matching logical-key fallback, late raced draft, fresh draft. Previously promoted/server-backed draft not reused; invested text preserved; navigation/project removal during awaits aborts. Pin before route/display and preserve playbook/user text; A31 covers special state shapes. [useHandleNewThread.ts:72](https://git.cafe/pingdotgg/t3code/blob/52314e7ca2bd205d65e41961ad36426363259439/apps/web/src/hooks/useHandleNewThread.ts#L72).
- **Ordinary scratch entry callers:** `NoProjectsHero` (also rendered by welcome), command palette direct New thread without a project and New thread in… → No project, `chat.newWithoutProject` keybinding, headline or start without a project, plus prompt-link scratch fallback (`NewThreadLinkView`). Project/Sidebar new-thread actions can also return to current scratch through contextual handler; onboarding/add/clone/PR/branch/worktree/fork/SnapShot paths use the same handler without new manual option. Equivalent creation entry points share the A01/A04/A05 render fixture; each entry gets a short route/draft-state trace, not a redundant image matrix.
- **useStartTriage** has one production caller, CommandPalette. It renders no JSX; visible effects are delayed loading toast (>400ms), preparation/open errors and Copy command action, interrupted/route-changed silent exit, then scratch hero/playbook. No scratch capability fails before prepare; machine is chosen by command context. Its new pin affects fresh and reused success paths A19/A20; failure paths C06 are unchanged. [useStartTriage.ts:68](https://git.cafe/pingdotgg/t3code/blob/52314e7ca2bd205d65e41961ad36426363259439/apps/web/src/hooks/useStartTriage.ts#L68).
- **DesktopWebLinkCoordinator** is mounted by `__root` only after primary authenticated or local disabled, under FirstRunGate. It returns null; webLinks bridge readiness, queued OS delivery, external links and preview/router/toasts are its output. It subscribes only when bridge exists and local-disabled or connected primary+config. Pairing link (confirm, duplicate guard, success/failure), prompt link navigation, and handled change-request links return before changed startThread; handled PR links alone may wait for shell discovery. HTTP vs file differ in required httpBaseUrl/asset creation/local-only reuse. Active eligible browser thread is reused; otherwise startThread resolves scratch environment, opens project, calls handler with manual pin, maximizes panel. Null scratch target/open/draft and preview errors produce existing failure states. Local disabled can choose a unique compatible remote scratch target for HTTP. A21–A23 cover changed success/reuse; C05 inventories bypass/failure outcomes. Dedicated browser tests mount a mock desktop bridge, which is a harness, not Electron. [DesktopWebLinkCoordinator.tsx:148](https://git.cafe/pingdotgg/t3code/blob/52314e7ca2bd205d65e41961ad36426363259439/apps/web/src/components/desktop/DesktopWebLinkCoordinator.tsx#L148).
- **Docs/tests:** both modified Markdown paragraphs explicitly include no-project Auto on web/desktop and keep mobile's current-machine behavior. Source prose reviewed; no new documentation layout/component exists to capture. New hook browser tests contain only Ready/Preparing paragraphs and Auto/manual buttons, so their render cannot substitute for actual toolbar/composer proof. The changed handler unit tests verify machine pin on fresh/existing fixtures. No mobile/provider/server/contracts implementation was changed; provider kinds are eligibility data, not a separate rendering matrix.

**Seeding and capture contract.** These are instructions for the subsequent capturer, not actions performed in pass 1.

- **S / REAL-2:** two isolated dev server instances A and B, each with fresh own home/DB and `T3CODE_DEV_SEED=0`; never use the live userdata DB. Pair B as a second saved environment in A using Settings → Environments (`/settings/connections`); keep both switched on and connected. No separate physical machine is needed for client/server-routing proof, but this does not prove physical host-load scoring, relay/tunnel, or native desktop integration. Use the same actually selectable provider driver and instance ID on A and B (prefer free Replay (dev)); installed/enabled/auth/availability must pass candidate filters. Enable Automatically balance load in the load-balancing section. To force B, make A Manual only (0), B Normal (50); inverse for A. The settings section's >=2 threshold counts enabled, supported registered machines; routing additionally needs scratch-compatible option count >1 and connected candidates. Capture each server identity without auth URLs/tokens.
- **E / entry recipes:** start without project in NoProjectsHero; command palette direct action; New thread in… → No project; `mod+alt+n`; from a real project draft use heading's or start without a project. For prompt-link fallback use an ordinary prompt-link launch offering No project. All land at `/draft/<id>`. Record the route and client draft environment before/after. Existing UI documentation mentions a No project heading-menu entry, but at this head the concrete heading fallback action is the visible or start without a project link; do not invent an unobserved picker item.
- **Scratch data:** source draft creation opens A scratch. For A05 keep B fresh and do not open a draft on B. For A04 seed B through its app or `projectEnvironment.openScratch` (wire method `projects.ensureScratch`, input `{}`) and wait for its project projection in A. A DB project alone is insufficient if the client has not loaded it. `openScratch` resolves only after the project atom arrives (10-second missing-projection timeout); it is not just filesystem directory creation.
- **Client data:** drafts, selection, attachments and inline context references live in client draft store. Server project/thread RPCs do not seed these by themselves. Prefer app interactions; a dev-only driver can import existing Vite modules and use store actions (`setLogicalProjectDraftThreadId`, `setDraftThreadContext`, `setPrompt`, model/context actions) before mounting/navigating the actual UI. Record that as driver-seeded real client when no production dependency is mocked. Mocked catalog/status/project responses or hook returns are explicitly HARNESS. Never edit source just to force a pixel result without labelling it.
- **HARNESS:** create an isolated full-UI fixture with actual ChatView/toolbar/details/toast host and real draft store/router as practical; inject only required catalog/project/resource/open promises and release them using explicit deferred milestones. The existing hook Harness gives a starting state/ordering model, but its paragraphs are not a product capture. Label each output HARNESS, its mocked boundary and environment count. Race-only input guards can use focused state transcripts with the representative UI clip; an identical image for each guard is not additional visual proof. No live two-server setup is needed for harness-only rows.
- **Viewports/themes:** W=1440×1000 web; T=1680×1100 web for inline full details; P=900×900 web for popover full details; N=390×844 narrow web (not React Native); Q=900×320 short web; E=1440×1000 actual Electron content/shell. `dark`/`light` mean explicit resolved themes. Verify DOM layout state/container width; resize if sidebar/panels prevent required form, documenting actual dimensions. Use default motion, then reduced motion only if a motion issue appears; no changed continuous animation warrants a separate theme/motion product cross product.
- **Minimum set:** every A row's listed viewport × theme must appear in a recording. Compatible rows can share one continuous recording with timestamps: A01/A03/A04/A05/A09/A10/A12/A30; A06/A15/A16; A13/A14/A17–A19; A24–A28 are natural groups. This is a coverage set, not a demand for 32 separate files. The listed additional subcases require separate ordered segments; all other equivalent filter/guard inputs use assertions/transcripts. C rows are unaffected controls; C01 is minimum regression/baseline, C02–C06 need no extra images unless their state is exercised or contradicted during capture. A01 requires matched base/head menu keyframes or recordings; new transient behaviors on base are unreachable as Auto scratch states, so compare the original entry/outcome instead of pretending the base could show them.
- **Per recording:** show initial state, user input, pending state if any, final machine/route and late completion/recovery where relevant. On Preparing machine show the disabled tooltip by hovering its outer span and show ready afterward. Include Send click/Enter rejection before readiness in a state/RPC transcript. Keep pairing URLs, credentials and private prompts out of evidence. Recordings are required for every A row; stills alone are insufficient.

**Affected fixture matrix.** A=diff reaches this fixture (including new guards and shared-hook regressions); every A status is MISSING in pass 1. REAL-2 means two actual server environments needed. Gated/harness supplements are distinguished above.

| Row | Named fixture / required data and observable result | Seed path; are two isolated servers needed? | Minimum viewport × theme × evidence | Status |
|---|---|---|---|---|
| A01 | Scratch Auto menu and all ordinary entry points — Scratch on A; two connected, scratch-capable environments; Auto on; empty and one-line prompt variants. Open toolbar menu: Auto plus A/B, correct selection and scale glyph. Also cover keyboard opening/dismissal. | REAL-2; entry recipe E; B may already have scratch. Exercise each E entry once; reuse A04/A05 clips for destinations. | W-dark + N-light; recording; same menu before/after at base/head. | MISSING |
| A02 | Checking machines — Unresolved automatic scratch draft; at least one eligible host-resources request pending. Label is Checking machines…; attempting Send yields Checking machine resources warning, never a turn. | HARNESS; hold server.getHostResources query results with a deferred. Real-2 can traverse it, but its natural duration is not deterministic. | W-dark; recording through settle; include open menu and send warning. | MISSING |
| A03 | Auto chooses current machine — A/B connected; A scratch already loaded; A weight 50, B 0. Pick A synchronously without scratch RPC; settled Auto label remains. Empty prompt then type text. | REAL-2; S; set weights in /settings/connections. | W-dark; recording; identify A in details/audit state because label remains Auto. | MISSING |
| A04 | Auto chooses peer with scratch already loaded — A/B scratch projects exist; A 0, B 50. Preserve typed prompt, chosen model and draft ID while moving to B; no preparation wait. | REAL-2; S; pre-create B via projects.ensureScratch / projectEnvironment.openScratch and await its projection before opening draft on A. | W-dark; recording; open both source and destination menus/details. | MISSING |
| A05 | Auto creates peer scratch; preparation then handoff — B has scratch capability but no project (projectId:null); A 0/B 50; nonempty prompt. Disabled send tooltip/aria says Preparing machine, then B scratch arrives and sending becomes available. | REAL-2 REQUIRED; S with fresh B DB; do not open No project on B beforehand. Record from before opening draft; if the wait cannot be seen, use an explicitly labelled gated-RPC harness supplement. | W-dark + N-light; recording, including hover on send wrapper; pair with A01 baseline. | MISSING |
| A06 | Scratch-open failure and explicit retry — B picked, no scratch; ensureScratch fails or scratch projection never loads. Error toast Could not switch machine; busy clears; draft stays on A, unresolved Auto still blocks actual send. Auto again retries; also exercise manual override recovery. | HARNESS; fail projects.ensureScratch or return a project ID without a projection (10-second failure path). Reject once then succeed; render actual toast host and composer, not hook paragraphs. Real servers optional, not sufficient for deterministic injection. | W-light; recording failure, misleading generic send warning, retry and ready state. | MISSING |
| A07 | Resource lookup fails — Eligible B query fails, with no usable resource snapshot on any positive-weight candidate. Settled label Auto balance unavailable; send warns to choose a machine. | HARNESS; reject server.getHostResources for the only eligible machine; keep connection and provider otherwise healthy. Real servers not required. | W-dark; recording; manual recovery to A. | MISSING |
| A08 | No eligible machine without query error — Two machines visible, both weights 0. Label stays Auto balance, not Auto balance unavailable; Send warns No eligible machine has available resources; manual selection works. Provider-ineligible and overloaded-success variants have the same output. | REAL-2; S; set both Manual only. For equivalent filter variants use provider settings or HARNESS resource snapshots (CPU >=95%, memory <=5%, null/invalid/stale resources). | W-dark; recording through warning and manual override. One representative clip; equivalent filters get state assertions. | MISSING |
| A09 | One machine can read attached thread context — Scratch draft references a real thread from B in its prompt; threadContexts contains that contextId; both weights positive. Candidates narrow to B, chip stays visible, Auto moves draft to B. | REAL-2; S; create an ordinary stopped thread on B, attach via app thread-context picker. Record actually referenced chip, not only an orphan store record. | W-dark; recording attach, pick, move. | MISSING |
| A10 | Conflicting attached thread contexts — Prompt references one A thread and one B thread. No candidate can satisfy every context; Send warning explicitly says No machine can read every attached thread. | REAL-2; S; create one thread per server and attach both in the app. Remove one and retry Auto as recovery. | W-light; recording; warning and recovery. | MISSING |
| A11 | Attachments before selection or during pending Auto — Scratch on A with one image/file and no balanced ID. Auto label absent; Auto option is still offered. Choosing it warns Keep attachments on this machine. If added during an Auto open, the old completion cannot move the draft. | REAL-2 for attachment + warning; upload a harmless local file in A draft; remove then choose Auto. HARNESS deferred open required for repeatable attach-during-open variant; show actual chip and late completion. | N-light; recording; include removal/retry and deferred variant. | MISSING |
| A12 | Attachments after resolved Auto — Auto already settled on B (loadBalancedEnvironmentId:B), then attach on B. Auto label remains and attachment stays on B; choosing Auto again warns rather than relocating the upload. | REAL-2; continue A04/A05, attach in the settled draft. | W-dark; recording; selected Auto plus attachment chip and warning. | MISSING |
| A13 | Manual current-machine selection beats an Auto open — Auto opens B; manually choose already-existing A while it waits. Label becomes A, busy clears; late B result never moves draft or changes pin. | REAL-2 plus gated-RPC supplement for reliable ordering; S; B fresh. Click A in toolbar; repeat equivalent action in details menu in A27/A28. | W-dark; recording; show late B completion as well as manual click. | MISSING |
| A14 | Older open settles while newer manual open is busy — Two overlapping opens to unregistered peer B: initial Auto B, then manual B. Resolve old one while new manual request is pending. Preparing machine must remain until the newer one finishes; final mode manual. | HARNESS; deferred projects/openScratch actions with two request identities. Two logical environments suffice; no second live server required. Three environments are only needed if choosing a different new peer. | W-dark; recording both settlements and busy tooltip. | MISSING |
| A15 | Choose Auto again while a manual/Auto open is pending — Begin a manual peer open, then choose Auto; also reselect the already-selected Auto row. Old request must not clear or overwrite the new Auto request; refresh clears branch/worktree and advances generation. | HARNESS deferred opens/resources; run selected-row click in standalone Select and RunContext Menu, since they use separate onClick/onValueChange handlers. | W-light; recording per selector implementation; share A27/A28 recordings. | MISSING |
| A16 | New Auto pick supersedes old pick — A scratch; B and C have no scratch. Pick B, then C before B resolves. Complete B late; it must not move draft or clear C busy. Complete C successfully; additionally fail C and ensure B cannot win afterward. | HARNESS with three environment records and controlled pick/open promises. The two-server arrangement alone cannot represent three distinct IDs; no live third server needed. | W-dark; recording success and failure endings; failure can share A06. | MISSING |
| A17 | Auto loses eligibility while opening — B opening; disable Auto in settings while background ChatView stays mounted. Busy and Auto label clear; late B cannot retarget. Equivalent loss-of-pick variants: resources refresh becomes pending/null, provider disabled, weight/candidate changes. | REAL-2 plus gated open; /settings/connections switch off, return to draft, release B. HARNESS for query/pick/provider transitions; attachment and external pin have their own A11/A19 rows. | W-dark; recording settings overlay, return and late result. | MISSING |
| A18 | Leave draft or choose a project during open — B opening; navigate to another thread, or use headline to choose ordinary project P with typed text still in draft. Old completion cannot pull route back or remap P. Empty-draft project choice may open/reuse a different draft; textful choice remaps current one. | REAL-2 plus gated open; add local fixture project P via app, use project heading and sidebar. Run empty and textful variants; route-change variant can share an existing server-thread control. | W-dark; recording each differing headline/route ending. | MISSING |
| A19 | Triage reuses an empty Auto draft and pins it in flight — Existing empty scratch draft on A, Auto B still pending; start Triage on A. Same draft is pinned manual before display/seed, triage hero and playbook refer to A; late B is ignored. | REAL-2 with gated B open; command palette Triage an issue. If triage preparation cannot be delivered in the isolated app, HARNESS prepareTriage response with a valid TRIAGE_PROMPT_FILE_NAME markdown link and label it. | W-dark; recording pin, hero, pending completion. | MISSING |
| A20 | Fresh triage is machine-bound — No stored A scratch draft; Auto favors B. Triage on A produces manual A draft with playbook link and triage hero; no Auto relocation. Auto remains an explicit user option. | REAL-2; command palette Triage an issue, allow server.prepareTriage and ensureScratch to complete. No paid provider turn needed. Use a seeded successful response only as labelled harness if source preparation unavailable. | W-light; recording command launch through settled hero. | MISSING |
| A21 | Desktop HTTP link creates pinned scratch draft — Desktop bridge ready; no active thread already showing preview; Auto favors B. OS web link launches draft on A with manual selection and maximized preview; preview and draft stay on A. | REAL-2 + actual Electron required for real desktop proof. Deliver external web link through desktop bridge/OS entry. VM web-only alternative is HARNESS using test-style webLinks bridge; must be labelled, not desktop verification. | E-dark; recording handover through preview ready. | MISSING |
| A22 | Desktop file link creates pinned local draft — Same as A21 but file: URL for a harmless HTML file served by A. A httpBaseUrl exists; preview and draft must remain A although Auto favors B. | REAL-2 + Electron; deliver local fixture file through supported external-link path. HARNESS bridge fallback explicitly labelled. Do not expose private filesystem data. | E-light; recording with loaded file content and machine. | MISSING |
| A23 | Desktop link reuses empty Auto draft — Empty A draft exists without active preview; Auto B pending. New desktop link calls startThread, pins reused A draft before preview creation; late B never moves draft away from its preview tabs. | REAL-2 + Electron + controlled B open for deterministic timing; HARNESS bridge and deferred-open fallback. Also cover idle existing empty draft without pending B. | E-dark; recording old completion and continued preview use. | MISSING |
| A24 | Grouped project Auto: wide toolbar — Ordinary git project P has copies on A/B under same logical key; Auto selects B. This changed hook must still retarget existing P directly without opening scratch; wide strip has separate machine/workspace/branch selectors. | REAL-2; register two paths for same disposable repository and group in app; A 0/B 50. This uses setDraftThreadContext instead of scratch setLogicalProjectDraftThreadId. | W-dark; recording; verify composer container >=3xl breakpoint. | MISSING |
| A25 | Grouped project Auto: combined compact selector — Same P; narrow composer (<3xl container) uses combined RunContextSelector with Run on and Workspace sections. Auto item, selected value and manual/Auto actions must match standalone selector. | REAL-2; reuse A24 and resize/collapse layout; native mobile is irrelevant. | N-light; recording resize/open menu/manual/Auto. | MISSING |
| A26 | Pinned workspace explicitly returns to Auto — Ordinary draft has explicit branch/current checkout, then existing worktree variant. Neither auto-moves. Choose Auto to clear branch and worktree and select eligible B; workspace controls and labels update. | REAL-2 grouped disposable git project; choose branch/worktree in app, then Auto in both selector forms. HARNESS only if precise branch-selection store shape cannot be reached. | W-dark + N-light; recording; two workspace endings must appear. | MISSING |
| A27 | Details card full density inline — Scratch draft on A/B; thread-details environment item visible, card full density and inline. RunContext panel menu opens downward, shows Auto and machines plus Workspace, manual/Auto work. | REAL-2; open details control and widen available chat canvas until [data-thread-details-panel=inline], [data-density=full]; do not assume screen size alone forces it. | T-dark; recording open menu, select manual, reselect Auto. | MISSING |
| A28 | Details card full density popover — Same scratch fixture but details appears as popover; environment row visible. Menu anchored to full-width panel control; selecting Auto closes menu and routing still works. | REAL-2; reduce canvas width until [data-thread-details-panel=popover], keep enough height for full density. | P-light; recording open card/menu, select and dismiss. | MISSING |
| A29 | Many machines, long labels, compact strip and mixed icons — Eight logical environments, 64-character labels, one primary first, others alphabetic; mixed server/cloud/linux/desktop/laptop/mac-mini/mac-studio kinds. Positive eligible B plus excluded/offline records. Overflowing list and compact icon-only strip must retain usable Auto item/tooltip. | HARNESS full UI with eight environment records; two live servers cannot supply eight IDs. Narrow/expand to exercise label-overflow hysteresis; underlying icon variants unchanged. | N-light + W-dark; recording resize, scroll, Auto/manual and tooltip. | MISSING |
| A30 | Send finalizes draft on chosen machine; locked reverse state — Settled automatic scratch draft on B; send one free Replay (dev) turn through composer. Draft /draft/id promotes to /environmentId/threadId; Auto affordance disappears, machine becomes locked, text and model remain coherent. | REAL-2; continue A05 with same selectable Replay instance/model on both; use composer Send. Do not use window.t3dev.replay(), which creates a different server thread. Include one revisit from sidebar. | W-dark; recording through route handoff and locked control. | MISSING |
| A31 | Pin option survives every new-thread reuse branch — manual option applied to: fresh draft; indexed empty stored draft already open; indexed empty draft opened from elsewhere; active empty draft with missing logical-key index; raced draft registered during default-workspace await. Existing text acquired during wait is not overwritten. | REAL-2 covers normal fresh/stored paths via A19-A23. HARNESS required for deliberately missing index and deterministic race, using real draft store + handler and a small driver, then actual ChatView. These have same layouts but distinct timing prerequisites. | W-dark; recording each race/reuse subcase, state transcript proving manual before route/render. | MISSING |
| A32 | Abandoned/promoted/send-in-flight or missing target — While opening B, promote/remove/remap original draft or set send-in-flight before resolution; stale result does not retarget. Scope changes or unmounts cannot leave Preparing machine on next draft. A selected project ID absent from project list does not open scratch or move draft. | HARNESS; controlled store changes and Deferred completions, actual composer/router. Missing target/no original/promoted/locked guards collapse to unchanged-draft outcome, not separate pixel states. Live servers unnecessary. | W-dark; recording original preparation, stale completion and clean next view; attach state transcript for guard-only variants. | MISSING |

**Unaffected controls, inventoried separately.**

| Row | Named fixture / required data and observable result | Seed path; are two isolated servers needed? | Minimum viewport × theme × evidence | Status |
|---|---|---|---|---|
| C01 | Auto off, two machines — Scratch on A, setting off; A/B manual menu has no Auto entry; normal send works. | REAL-2; S with loadBalancingEnabled:false. | W-dark; recording baseline/control. | CONTROL—NOT CAPTURED |
| C02 | Zero/one compatible scratch environment — No active project => no options/strip; primary-only scratch => no picker; remote-only scratch => locked remote label. Disconnected or scratch-unsupported peers are excluded; section setting alone cannot enable Auto. | REAL-1 for primary-only; REAL-2 then disable/disconnect peer for exclusion; HARNESS for null project/config and remote-only primary-disabled shapes. | W-dark; static seeded views; optional control captures. | CONTROL—NOT CAPTURED |
| C03 | Hydration, permission and other send blocks — Client settings unhydrated => Auto not active yet. Read-only connection shows This connection cannot change threads ahead of Preparing machine; disconnected active environment masks tooltip with Environment disconnected. Rewind/feedback/messages/worktree/clone reasons are lower priority than machine preparation. | HARNESS for hydration and simultaneous reason priority; real scoped pairing can cover read-only. Other pending approval/running/subagent composer forms require started threads and cannot begin normal Auto routing. | W-dark; recording only hydration/permission transitions if captured; no full unrelated composer cross product. | CONTROL—NOT CAPTURED |
| C04 | Details density/visibility and persistent strip — Compact/essential card density or environment visibility preference off removes panel environment row. Closed card also absent. Started-thread strip can be off/on through persistComposerContextStrip; draft hero always shows strip with active project. | REAL-2; A27 resize height, toggle visibility in details personalization, close/reopen; use started thread from A30. | P-light + short-height Q-dark; recording if exercised. | CONTROL—NOT CAPTURED |
| C05 | Desktop bypass, readiness and failure branches — Web/no bridge returns null. Wait for primary connection/config unless local disabled. Active preview reuses eligible thread without startThread; file preview only on A. Pairing/prompt/handled PR links bypass startThread. No scratch target/open failure/null handler, missing file httpBaseUrl and preview failure produce existing errors. Local-disabled HTTP link may use a unique compatible remote; file cannot. | HARNESS bridge delivery to real root/coordinator for exact branches, or actual Electron + REAL-2. Remote-only eligible target can use B when local disabled. A mocked bridge is never native desktop proof. | E-dark or labelled harness W-dark; recording each visually distinct error/reuse outcome if captured. | CONTROL—NOT CAPTURED |
| C06 | Triage startup/error/cancellation — Before success: no scratch capability error with Copy command; delayed preparation >400ms Starting triage… toast; prepare/open failure yields Could not start triage; interrupted command quiet; route change prevents reopening. | HARNESS deferred prepare/open results and toast host, or REAL-2 app. Show CLI copy only on error; no provider turn. | W-light; recording loading/error/cancel if captured. | CONTROL—NOT CAPTURED |

**Coverage and limits.** Complete nine-file diff read; all changed production components/hooks and affected visual descendants/callers traced, including creation entry points, desktop bridge, client settings, candidate/resource logic, scratch-project projection wait, store pin propagation, send gating, route promotion, docs and tests. No browsers, dev servers, provider turns, tests or live data mutations. `git diff --check` passed; worktree status remained clean. During the audit another actor advanced its HEAD to [a34c854b5f](https://git.cafe/pingdotgg/t3code/commit/a34c854b5f819d59051b4bf15637013a344a31c3), changing only `docs/user/thread-sidebar.md`; no reviewed production component/hook differed. This report and saved diff remain pinned to requested [52314e7ca2](https://git.cafe/pingdotgg/t3code/commit/52314e7ca2bd205d65e41961ad36426363259439). Started long-running processes: none. Every written artifact stays in `/tmp/lead-26975-r1/proof-audit-1/`; no deletion performed. Earlier PR artifacts were not evaluated for this no-capture pass.

FRICTION:
- infra | The shared review worktree advanced to a later commit during this read-only pass. The delta was documentation only; the requested fixed-head diff was preserved and code equivalence verified. | A lead-provided immutable snapshot, or notify reviewers before changing HEAD.
- tool | A few guessed component filenames did not exist, and early combined reads exceeded output limits; targeted `rg` discovery and smaller reads recovered the needed source. | Discover filenames with `rg --files` before reading; cap batched output.

VERDICT: INSUFFICIENT A01–A32
