**Proof audit, pass 1 — fixture matrix for [#29023](https://git.cafe/pingdotgg/t3code/pull/29023)**

Reviewed head [fdd40f40bd](https://git.cafe/pingdotgg/t3code/commit/fdd40f40bd90c7503b23387c59d451c2354548a1), branch `fix/issue-29009`, against main / merge-base [cefb544af3](https://git.cafe/pingdotgg/t3code/commit/cefb544af3c98224874419198c0359b652ca3c94). Read-only audit in `/home/ubuntu/wt/pr-29023`. No captures, browsers, servers, code changes, pushes, or forge comments in this pass. This is a capture specification, not a claim of runtime verification.

**Findings and limits**

1. **Current-head proof is missing.** The previous recordings belong to [6c09b17dc2](https://git.cafe/pingdotgg/t3code/commit/6c09b17dc27bae64154c1db5e0a6eda800ea6595). The new head is a merge with parents that head and current main. Both PR diffs have stable patch ID `3d0263f8c9ae3d7afce0ad28025e04da4702065f`; they change the same four desktop preview files. That establishes identical PR changes, not equivalent runtime evidence. Use current main as Before and the reviewed head as After; the old baseline would confound 155 merged main commits.
2. **The person's-input preservation claim needs a streamed-client check.** Server viewer mouse input becomes `Input.dispatchMouseEvent`, is wrapped as desktop `type: cdp`, and updates `agentInputAt` just like agent input. A streamed person's click need not focus the host's native guest frame. Consequently the new condition can classify it as background. R1 must distinguish that path from native OS input. This is a concrete coverage risk, not a claim that a user-visible regression has already been reproduced. Do not describe the local OS H2 result as proving all human input paths.
3. **There are no changed rendered components.** The production changes are services: `Manager` classifies a new-tab event and consumes the renamed `DesktopBrowserHost` predicate. Tests supply the other two changed files. The affected visual output is selected tabs, panel content/open state, keyboard focus, composer text, and consequent chat reflow. Every capture row below is `recording`; final stills alone cannot prove any row.
4. **The download refactor is equivalent on its reachable path.** `placeDownload(source,item) === true` requires an attached tab, download directory, and pending guid. On that path old `humanStartedDownload = age > 5000`, and new `!agentActedRecently = !(age <= 5000)` agree, including exactly 5000 ms. For an untracked source the predicates differ, but `placeDownload` is false and the handler exits in both versions. Completed downloads alone are copied/revealed; incomplete/error states still exit. D1 needs code proof rather than a new visual fixture. No changed save path, completion handler, or copy behavior was found.
5. **Time is part of the contract.** The condition is recent input at window-open time, not proof of the actor who caused it. Delayed agent popups after 5 seconds retain foreground behavior. T1 records this limit. DOM inspection through the agent's `Runtime.evaluate` / `Runtime.callFunctionOn` can refresh the timestamp; send no such commands while measuring expiry or a cold-person fixture.

**Render and call-path inventory**

- [Manager.ts](https://git.cafe/pingdotgg/t3code/blob/fdd40f40bd90c7503b23387c59d451c2354548a1/apps/desktop/src/preview/Manager.ts#L1540): `registerWebview` → `registerWebviewUnlocked` → `attachListeners` installs the one changed `setWindowOpenHandler` on each eligible main-window webview. The handler has four paths: deny invalid/in-place-denied protocols; allow an HTTP(S) `new-window` as a real popup; emit an HTTP(S), body-free foreground/background new-tab link; otherwise navigate in place (including form POST and non-HTTP schemes). Only the new-tab path changes. Popups, denied links, POSTs, same-tab navigation, and nested popups never evaluate the added condition and need no new capture.
- That new-tab event has exactly three layout-relevant fields: source `tabId`, destination `url`, and `background`. `background-tab` always stays background. For `foreground-tab`, an attached source with input age <=5000 ms and `focusedFrame === null` now becomes background. Recent + focused, stale/never-used + unfocused, stale/never-used + focused, and untracked sources stay foreground. The return is still Electron `deny`: T3 creates the destination tab instead of allowing a second unmanaged native window. Representative captures are A1, H2, T1, H1, B1; U1 is code-covered.
- [DesktopBrowserHost.ts](https://git.cafe/pingdotgg/t3code/blob/fdd40f40bd90c7503b23387c59d451c2354548a1/apps/desktop/src/preview/DesktopBrowserHost.ts#L461): the renamed predicate has only two production callers, the above new-tab handler and `placeServerDownloads`' session `will-download` listener. Per-source tab lookup is by exact webContents identity. Attach starts at negative infinity; detach removes it. Recognized CDP input is `Input.*`, `Page.navigate`, `Runtime.evaluate`, or `Runtime.callFunctionOn`; DOM reads do not qualify. `pointer`, `turn`, `release`, invalid messages, and absent tabs do not refresh this timestamp. Different CDP input methods do not introduce different layouts; use normal MCP click as representative agent input. Streamed human input is the materially different caller class, R1.
- [GuestInput.ts](https://git.cafe/pingdotgg/t3code/blob/fdd40f40bd90c7503b23387c59d451c2354548a1/apps/desktop/src/preview/GuestInput.ts#L97): a native pointer press saves host focus and restores it after the press if the guest took it. If the guest already has a focused frame, it sends directly. This creates the native-focus distinction the PR relies on; H2 must use OS input, not direct debugger input. A1 covers the restore-to-composer path; the hidden guest in A2 has no user frame focus.
- [IPC forwarding](https://git.cafe/pingdotgg/t3code/blob/fdd40f40bd90c7503b23387c59d451c2354548a1/apps/desktop/src/ipc/methods/preview.ts#L56) → preload `preview.onOpenLink` → the sole app-lifetime consumer [ElectronBrowserHost.openLinkInPreview](https://git.cafe/pingdotgg/t3code/blob/fdd40f40bd90c7503b23387c59d451c2354548a1/apps/web/src/browser/ElectronBrowserHost.tsx#L97). It resolves the originating hosted session, preserves its thread/environment and profile, and ignores a missing source. It is not a Settings/palette/keybinding-specific action; all links from that guest share this handler.
- [openUrlInPreview](https://git.cafe/pingdotgg/t3code/blob/fdd40f40bd90c7503b23387c59d451c2354548a1/apps/web/src/browser/openFileInPreview.ts#L57) maps side-chat panel ownership before awaiting browser defaults and the open RPC. Settings-read failure returns failure before opening. RPC failure does not run success mapping. Background success inserts/updates the destination snapshot; it restores the previous active preview only when there was one, the newly opened tab is still active, and the selected surface has not changed. Foreground success applies the destination snapshot and calls `openBrowser`. S4 covers deliberate selection during the await; A1 covers the ordinary active-tab restoration. A source guest necessarily supplies an existing session, so a zero-source/empty-session layout is not a meaningful new-tab fixture.
- The visible surface classes are Browser, another open panel such as Files, and no panel; the displayed thread may be the source or a different thread. A1/S1/S2 are the three source-thread outcomes (tab switch / panel replacement / panel opening and chat reflow); A2 is the hidden-source cross-thread focus leak. Cross-thread closed A3 and cross-thread Browser S3 are listed below but do not add another predicate or consumer branch to those four captures.
- Destination nav state may be Idle, Loading, loaded, or LoadFailed. Page text, long URL/title, tab count/overflow, empty Files, provider model, light/dark/system theme, fixed/fill viewport, zoom/DPR, and inline/overlay/maximized panel appearance do not select a changed branch. Use short distinct titles and successful immediate HTTP destinations; do not multiply the matrix for unchanged styling. S4 alone needs >1 selectable Browser tab. Loading/error destinations do not change the open-link classification; do not use navigation errors to infer that no tab opened.
- Native hosting is Electron-only. Primary-environment, non-headless `runtime: server` tabs are native hosted guests and have the tracked server-tab key. Desktop-runtime guests are also hosted but untracked by this timestamp. Pure web/mobile clients and remote/headless server browsers do not themselves run this desktop handler. A web/mobile viewer of a desktop-hosted server tab can still enter it (R1). Providers and scheduled tasks share the server automation/MCP path; no per-provider fixture is needed. Permissions/config hydration failures prevent hosting and do not render this changed path.
- The predicate has no OS branch. Linux/Xvfb proves Linux only. macOS has a distinct existing keep-paintable-inactive webview strategy; macOS and Windows native `focusedFrame` and window activation remain unverified unless the lead adds native A1/A2/H2 runs. State this limit explicitly; neither theme nor viewport captures substitute for native platform evidence.

**Merged main changes**

- [f80be8e037](https://git.cafe/pingdotgg/t3code/commit/f80be8e0374d75dc74f0e4c5011d93a6e2e170f8) changes the streamed viewer input queue: adjacent waiting wheel inputs coalesce and clicks no longer sit behind a wheel burst. It does not change MCP/agent click dispatch or local OS clicks. No old row acquires a new branch from this commit. It does affect the R1 viewer path; a normal click there suffices for this PR, with no wheel-flood benchmark needed.
- [10f365703a](https://git.cafe/pingdotgg/t3code/commit/10f365703af1c2755745a1ebf986826f4948f4b8) wraps server `clickTarget` and names the target after a timeout. The successful target click and native host classification are unchanged. It can affect error reporting in agent rows, not their expected focus result. A click may happen before timeout; never automatically retry a timed-out capture action or count an error response as proof that no tab exists. Use a fast fixture and inspect the actual event/outcome.
- The only change to these production desktop files between the old evidenced head and the reviewed head is the merged Effect crypto API migration in `Manager` (screenshot UUID creation); `DesktopBrowserHost`, `GuestInput`, and `CdpRelay` are unchanged. Web host, `openUrlInPreview`, and preview store are also unchanged. No extra visual row follows from that import/API migration.

**Common seed and capture contract**

Use a fresh isolated desktop app/database at each pinned revision, synthetic project + threads A/B, and a local HTTP fixture. Source `/` has `<a id="agent-link" target="_blank" href="/agent-target">Agent target</a>` plus an independently named person target `/person-target`. Give both destinations stable distinct headings/titles. The delayed source has an agent-link click handler that calls `window.open('/delayed-target','_blank')` 6500 ms later. Keep destinations immediate so click timeouts do not become a second variable.

Create project/threads through normal app RPC (`projectEnvironment.create`, `threadEnvironment.create`), set `browserAutoShowFloatingPreview:false`, and choose dark theme. Open the source through the normal scoped `preview_open` MCP tool; use a legitimate running free Replay/dev or existing deterministic provider-scope fixture so `preview_act` has its real thread scope. A deterministic provider protocol fixture that only holds caller scope is acceptable; it must not implement preview behavior. Do not use paid agent turns for generic UI verification. Navigate to `/#/<environmentId>/<threadId>` in the desktop renderer (its `t3code-dev://app/` origin is checkout-specific).

For ordinary setup, panel/tab selections may be made through the app UI or its existing renderer stores/RPC. The actions under test must be production `preview_act` or genuine OS input, never assigned `background`, patched `focusedFrame`, emitted synthetic native open-link events, or stubbed consumers. Use native OS typing after the action without refocusing. Only S4 has an allowed, labelled result-delay harness.

Existing public [reproduction guide](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/9f85aa20defedbeb/REPRODUCE.md), [seed](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/117539ba02efaa42/seed-reproduction.js), and [driver](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/bac9fb6176c58ea8/capture.mjs) are starting points, not evidence at this head. Replace old revision, ports, scratch roots, and fixed auth-file paths; do not reuse private credentials or upload them. Driver startup must attest the checkout SHA and real Electron binary. Avoid the old A1 dependency on B's leftover A3 draft: reset all drafts per row and publish the seed actually used.

Minimum viewport × theme: **1440×1000 CSS app viewport × dark × each retained row**, DPR 1, 100% zoom/font scaling, same Linux desktop/Electron environment on both sides. A capture can include a timestamp/focus sidebar outside that viewport. Record actual host renderer active element, selected surface/tab and thread, native open-link `{source,url,background}`, and OS input timing. Freeze only display/host renderer clocks if desired, never Electron main's monotonic clock used by the heuristic. Treat a transient webview focus during the press separately from lasting focus theft after the new tab opens.

Record from the initial settled state through the action, destination event, unassisted suffix typing where specified, and settled outcome. Inspect hidden/new destination tabs only **after** recording that outcome, in a clearly separate segment/clip. Capture final stills as aids, not replacements for recordings. Use the same synthetic seed for Before/After; a reviewer should see the new tab exists, not infer it from preserved focus alone. For T1/cold fixtures there must be no intervening agent CDP input; timing/focus logs must establish the relevant native age and frame state.

**Fixture table**

`PENDING` means no current-head recording exists in this pass. Every retained row is in the minimum proof set; rows marked supplementary have a specific regression risk. “Changed” describes the expected PR branch/outcome, not an observation.

| ID / fixture | Status and minimum artifact | Diff affects? / branch | Synthetic state, action and expected visible result | How to seed / drive |
|---|---|---|---|---|
| A1 — source thread, Browser visible | **PENDING · required · recording · Before + After** | Yes: recent + no guest frame, foreground disposition | A source selected; A composer focused with `Sentinel A1`. Agent clicks `_blank`; then OS types unique suffix without refocus. After: source stays selected, composer retains suffix; new destination exists. Before is expected to select destination and redirect typing. | Common seed; show A/source via Browser panel, focus composer; thread-A scoped `preview_act {action:"click",tabId,selector:"#agent-link"}`. Separate destination inspection. |
| A2 — hidden source, another thread's Files visible | **PENDING · required · recording · Before + After** | Yes: same native condition; cross-thread/global focus consumer | A owns source; display B with Files and focused B composer. Agent clicks in A, OS types suffix. After: B stays selected, Files remains selected, suffix remains in B composer; destination is in A. | Common seed; open B's Files through UI, navigate B; keep A source alive as hosted hidden guest. Drive A MCP. Inspect A only after outcome clip. |
| S1 — source thread, Files selected over source Browser | **PENDING · required · recording · Before + After** | Yes: foreground would replace a different panel surface | Display A/Files, source guest hidden, A composer focused. Agent link opens; After retains Files and composer; new Browser destination exists. | Common seed; open A Files after opening source; same MCP click/suffix and separate inspection. |
| S2 — source thread, panel closed | **PENDING · required · recording · Before + After** | Yes: foreground would open panel and reflow chat | A source guest alive; close A panel, focus composer. After agent click the panel stays closed, chat width is stable, composer gets suffix; destination exists. | Common seed; close panel through UI, same MCP click/suffix; inspect destination only afterwards. |
| H1 — cold local person click | **PENDING · required preservation · recording · Before + After** | Added condition false: no recent input, real focused guest frame | Quiet source (>5s since last qualifying command); real OS left-click person `_blank`. Both revisions should select the person's destination in foreground. | Common seed; stop agent input, wait with native elapsed-time log; OS pointer click visible person link. Read renderer focus without sending agent commands to guest. |
| H2 — local person takes over inside recent-input window | **PENDING · required preservation · recording · After only** | Recent true but guest frame focused by local person, so added term false | Agent first opens background destination, then real OS left-click a different person link <5s after last agent input. Person destination must open foreground, agent destination remains a separate tab. | A1 seed/action, no manual source reselection or synthetic focus mutation; real OS click source/person-link promptly. Log native event times, `focusedFrame` at handler, destination selection and typing. Before optional, not minimum. |
| B1 — explicit person background click | **PENDING · required preservation · recording · Before + After** | Existing `disposition === background-tab` short-circuits | OS middle-click person link; both keep source selected and create destination without foreground activation. This checks intentional background operation independent of heuristic. | Common seed; quiet source; real OS middle-click. Confirm native background disposition and later inspect destination. |
| T1 — agent-triggered popup after input expiry | **PENDING · supplementary timing guard · recording · Before + After** | Added condition false: age >5000, frame null | A composer focused; delayed source schedules new-tab 6500ms after agent click. With no intervening CDP input, both retain prior foreground behavior after expiry. Do not label this as protected agent focus. | Open delayed fixture; MCP click once; log handler time/last input and observe full wait. Renderer/OS monitoring only during expiry. Exact 5000ms boundary is code proof, not a wall-clock capture target. |
| S4 — deliberate sibling selection during pending open | **PENDING · supplementary race guard · recording · Before + After · LABELLED HARNESS** | Yes: new background path must honor selected-surface/active-tab guards | A has source plus selectable sibling-A. Agent triggers destination; person selects sibling while open result is withheld. After must keep sibling selection/content/URL consistent when completion arrives; it must not restore source or select destination over the person. | Use common seed + second real Browser tab. Delay only renderer open-command result delivery by 2000ms, after real RPC resolves. Click sibling with OS input while pending; release result. Label harness in footage and manifest. Never stub open event/background/focus/tab state. Natural deterministic RPC-delay injection was not found; this row cannot honestly be called an unmodified integrated capture. |
| R1 — person through streamed web client to desktop guest | **PENDING · supplementary input-origin guard · recording · Before + After** | Potentially yes: viewer CDP input also refreshes timestamp; native guest may be unfocused | Same real desktop host/source; a second authenticated web client views that same server tab and takes control. Keep desktop composer focused. Person clicks `_blank` through streamed surface. Record both clients: destination presence, controlling client's selection, host tab/focus, native `background` and focused frame. Compare with main; do not assume remote person equals local OS H2. | Common host seed; second real client at same isolated server, route A, select server/source and take control using actual UI. Ordinary viewer pointer interaction; no MCP agent click for this row. Two-client screen recording or synchronized recordings. Preserve any baseline limitation separately; if foreground selection already fails on main, report pre-existing behavior rather than inventing a PR regression. |
| A3 — other thread, panel closed | **COLLAPSED · no separate minimum capture** (would be recording) | Native event changes but B has no focusable panel | Hidden-source classification is A2; absent-panel/no-reflow behavior is S2. An unchanged B final frame does not prove the destination is background. | If retained optionally, use old A3 seed but inspect A's destination AND source selection, not just B's final frame. |
| S3 — other thread, Browser visible | **COLLAPSED · no separate minimum capture** (would be recording) | Same changed hidden-source event | Repeats A2's cross-thread delivery and A1's Browser focus sink; no additional changed branch. | Optional common seed with independent B Browser tab; not needed for minimum. |
| U1 — untracked desktop-runtime source | **CODE-COVERED · no separate minimum capture** (would be recording) | Added condition always false for source absent from host map | `agentActedRecently` matches exact source; recent input in a different tracked tab cannot affect this source. Same foreground result as existing behavior. | Optional real `preview.open` with `runtime:"desktop"` then OS click; native desktop source, not a server guest. No stub needed, but no distinct changed branch to prove. |
| D1 — tracked/untracked downloads | **CODE-COVERED · no capture** | Predicate renamed/inverted; reachable behavior equivalent | `placeDownload` true implies tracked tab; see finding 4. Recent agent, old/cold human, absent guid/path, untracked source, completed and noncompleted all retain behavior. | No visual fixture required for this unchanged path. Existing focused unit coverage is supplementary; this pass did not run tests. |

Minimum set: **10 fixtures, 19 revision/fixture recordings** (nine Before+After pairs and H2 After-only), plus clearly separate destination inspections where needed. One viewport/theme; no mandatory light/narrow duplicates. Nine fixtures come from the old matrix; three old rows collapse; R1 adds one input-origin risk. If runtime investigation shows R1 has no PR-specific visible difference and both clients retain baseline behavior, its preservation recording still closes the concrete caller-path uncertainty. It is not permission to expand into streamed browser redesign.

The old capture package has been read only as input. No old recording is credited to the reviewed head. macOS/Windows native activation and arbitrary delayed agent popups remain explicitly outside the Linux proof claim. No broad test/check suite was run in this pass.

FRICTION: none

VERDICT: INSUFFICIENT A1, A2, S1, S2, H1, H2, B1, T1, S4, R1 recordings at current revisions
