# Proof audit pass 1: preview page identity and hidden capture frames

Scope: [#22877](https://github.com/pingdotgg/t3code/pull/22877), [#16901](https://github.com/pingdotgg/t3code/issues/16901), final comparison [e54e71d725](https://github.com/pingdotgg/t3code/commit/e54e71d725b6eef166ee9b85137c09e051cff342) to [e8a30afda4](https://github.com/pingdotgg/t3code/commit/e8a30afda42d34ad8f0627d40b864c260fab7f40). Header reconciled after final fixture commits; source-derived paths and rows are unchanged from pass 1. Final production implementation is the preserved authored fix; later commits merge main and add the evidence fixture. The linked evidence index and pass-2 report give delivered coverage; this pass-1 specification is not a claim that its rows were verified.

Status: fixture specification only. No tests, launches, screenshots, or recordings performed by this auditor. All rows below are UNVERIFIED. The lead's reported runtime results are leads, not independently audited evidence.

## Source-derived branch inventory

- `apps/server/src/preview/ServerBrowser.ts`: desktop available + snapshot not headless waits up to 10 seconds for attachment. Successful attachment uses the native page. Otherwise, while desktop channel is available, `markHeadless` makes server-page ownership durable until session closure. Already-headless sessions bypass attachment. Adopted popup pages also enter the mark-headless branch when a desktop channel is available. Desktop unavailable still creates a server page without newly setting the marker.
- `apps/server/src/preview/Manager.ts`: first mark emits a `resized` event carrying `headless:true`; repeated marking emits nothing. Existing snapshot fields are retained. Verify propagation through existing sessions, not just a newly queried status.
- `apps/web/src/browser/previewRuntime.ts`: native server rendering now requires Electron, server runtime, primary environment equality, and headless absent/false. True selects the streamed path. Missing primary environment, remote environment, and browser clients remain non-native.
- `apps/web/src/browser/ElectronBrowserHost.tsx`: marked server sessions are excluded from hosted webviews. Capture requests match raw server tab and thread IDs only in the primary environment, translate to runtime tab ID, then acquire frame activity. Unknown/remote/headless sessions do not acquire a native hold.
- `apps/web/src/components/preview/PreviewView.tsx`: non-native server tabs ignore stale desktop state. This changes loading, history availability, layout zoom, native PiP indicator, zoom overlay, and native agent cursor. Main content selects `ServerBrowserSurface` instead of `BrowserSurfaceSlot`. Stream pending/first frame, empty, fixed viewport toolbar, failure/download overlays, control acquisition, and PDF are now reachable for fallback Electron sessions.
- `apps/web/src/components/preview/ThreadPreviewMiniPlayer.tsx` is an unchanged CALLER of the changed predicate: fallback selects stream with `followSize:false`, bottom control, stream-reported source size and server PiP, rather than fitted native slot and reconnect overlay. It still reads stale desktop zoom for source size before stream viewport arrives; inspect that transition explicitly.
- `apps/desktop/src/preview/DesktopBrowserHost.ts` -> IPC methods -> preload -> ElectronBrowserHost: `Page.captureScreenshot` publishes the matching key before CDP relay. `captureFrames.ts` retains a single activity lease across repeated requests. Active runtime includes preparing/queued/starting/running/waiting; release at first inactive/missing shell. Initially inactive or missing shell uses 10-second timer; another request resets timer. Rendering is active when visible OR frame hold OR native PiP OR existing recording.

## Capture contract and scope reduction

Use full real-app surfaces and the SAME isolated fixture state in before and after. Pair the exact supplied base and merge head, not contributor screenshots. Record browser/Electron version, Linux/display backend, capture tool, viewport in CSS pixels, inner preview viewport, DPR, device emulation, font scaling, theme, panel width, scroll, fixture ID and SHA. Default no device emulation, DPR 1, font scaling 100%, stable fonts. Set app theme explicitly; fix preview color scheme too where relevant. A 390-wide desktop/browser capture is narrow web layout, not React Native mobile evidence.

`G` below means 1440x900 AND 390x844, each light AND dark (four settings). `P` means 1440x900 light and dark for protocol/lifetime controls with identical geometry; these are not extra layout branches. A row marked `G` requires all four variants. For actual Electron, measure the renderer viewport; if shell minimum width prevents 390, document actual width, capture at its supported minimum, and use web 390 for the corresponding stream layout. Never call a 1440 window with a 390 page inside it a 390 app capture. Missing native 390 remains an explicit platform limitation.

Every interaction/time row is marked **recording**. This means an external full-client recording with before/after checkpoint stills, not enabling T3's built-in preview recorder: that recorder itself keeps native frames alive and would mask the hidden-capture bug. Long blocked-renderer intervals may be condensed only in an additional clearly time-labelled edit; retain the original recording and event transcript.

For each row/variant deliver Before | After | Diff with SHA labels; two still diffs (zero threshold amplified and a stated threshold, e.g. 8/255 per channel), plus matched recordings for flows. Extract stills at event checkpoints rather than an arbitrary elapsed frame. List every visible difference, intended or incidental. Stream JPEG/codec/text rasterization deltas must be explained, not silently thresholded away. No claim of unchanged pixels from thresholded diffs. Missing rows remain unverified in the PR evidence matrix.

## Fixture table

Affected means changed routing/state/lifetime, not a promise of a visible pixel delta. Controls have deliberately unchanged intended behavior.

| ID | Affected/unaffected and exact seeded branch | Client / settings | Seeding and capture procedure; observable acceptance | Evidence |
|---|---|---|---|---|
| H1 late fallback, main | AFFECTED: primary Electron, server runtime, desktop available but no attach within 10s; later renderer recovery, headless true | Real packaged Electron Linux; G | Fresh tab in thread A; execute lead's known sequence: Claude tool sleep 5, immediately stall APP renderer for 45s via CDP busy loop, then Claude `preview_open` with `open:false`, new tab, example.com. Keep main process/server alive. Capture command/event timestamps. Once renderer recovers, operate SAME returned tabId via evaluate to set unmistakable red background and fixed marker. Reveal main preview. Before should reproduce agent red/page panel white split; after must show SAME marker/page, no duplicate hosted server webview and headless snapshot. Repeat evaluation to blue to exclude stale one-frame success. | **recording** + red/blue checkpoint stills + tool/status transcript |
| H2 fallback persistence / reverse path | AFFECTED: headless remains true after desktop catches up; close resets lifecycle | Electron; P | Continue H1, hide/reveal and switch away/back; navigate same tab, confirm identity retained. Close session, create fresh tab with renderer responsive. New tab should attach natively with marker absent (new ID); do not expect old tab to migrate back. Record session and runtime IDs. | **recording** |
| H3 stale main overlay | AFFECTED: non-native server + stale desktopByTabId entry; snapshot wins | Electron; G | Before fallback, get native state through real navigation A->B, zoom 125%, and a guest/controller interaction; then force fallback on a new session that mounts before the attach deadline but cannot finish attaching. Preserve/log actual stale state, do not inject store values. Compare snapshot vs overlay during loading->success, back/forward, zoom and cursor. If race cannot reliably produce all stale fields, use linked supplemental fixture for only those fields and label it synthetic; H1 remains real-app proof. No stale native loading spinner/history, zoom indicator, native PiP state or cursor may override streamed state. | **recording** + loading/settled stills |
| H4 fallback floating | AFFECTED: unchanged BrowserMiniPlayer caller now streams; fixed source aspect and control bottom | Electron; G | From H1 red page, move panel to floating, drag and resize once, return to panel, float again and close/reopen. Check first frame, rounded clipping, source aspect, bottom control and same marker/tab. Include stale 125% desktop zoom from H3 during initial stream viewport arrival to expose transient source-size error. No native reconnect overlay over valid headless stream. | **recording** + initial/settled floating stills |
| H5 streamed control / viewport | AFFECTED newly selected Electron stream path, existing controls | Electron fallback; G | From H1 acquire human control, navigate A->B, back/forward/reload; release control and show agent update. Toggle fill -> fixed 390x700 -> fill; set 125% zoom and reset. Capture disabled/read-only vs human control, device toolbar, first frame and ready states. Fixed inner viewport is distinct from app width. Reuse fixture page; no unrelated feature combinations. | **recording** |
| H6 empty/loading/failure/download | AFFECTED newly selected fallback main path; existing overlays | Electron fallback; G | Fresh fallback tab without URL (Idle/empty); choose fixture URL; hold its response at explicit fixture-server barrier (Loading/pending); release (Success). Then navigate deterministic failing endpoint and attachment endpoint, show unreachable and file-not-shown overlays, reload back to success. Record server snapshot and stale overlay if present. Empty/error overlays must win over stream; no indefinite pending spinner after frame. | **recording** + each state still |
| H7 popup adoption | AFFECTED: adoptedPages bypass desktop attach, desktop available sets headless | Electron; G | Fixture link `window.open` under real permitted click/agent action, opening child with unique POPUP marker. Exercise popup once from main and once from floating (`showPreviewPopup` target differs). Verify child tab streams its actual adopted page, opener unchanged; close child. No duplicate native navigation or lost popup content. | **recording** |
| H8 PDF and separate window | AFFECTED branch reachability through streamed fallback/floating | Electron fallback; G for PDF main/floating; P for popout | Serve fixed tiny PDF. Main then floating must render document; floating PDF must not offer unsupported server popout. Return to HTML; open/close separate server preview window only if `supportsServerPictureInPicture()` is true in that actual runtime. Unsupported means capture button absence and report capability, not fake support. | **recording** |
| N1 attached main native | UNAFFECTED routing control: primary Electron, server runtime, headless absent/false, timely attach | Electron; G | Fresh responsive renderer, open fixture page; show native surface, history, zoom 125%/reset and agent pointer. Do not force headless. Confirm same page used by automation; loading/history remain driven by native overlay. Explicit false and omitted marker are equivalent predicate cases; no separate cosmetic capture needed. | **recording** |
| N2 attached floating native | UNAFFECTED routing control; shared predicate still true | Electron; G | N1 panel->floating->panel, resize once. Native fitted surface and reconnect overlay only during actual missing webContents; confirm marker intact. Contrast H4 without creating another data fixture. | **recording** |
| C1 hidden native active turn | AFFECTED capture activity: native attached tab, panel closed AND other thread selected; runtime active | Electron; P | Attach A natively while visible, then close panel, select B. Keep A's real agent turn active. Request `preview_screenshot` on A (actual server CDP capture), verify returned PNG contains marker/red content without manually revealing A. Request twice and mutate marker between captures. While turn active past 10s frames must stay available; end turn and observe rendering activity return to suspended when no other lease exists. Record full client and returned image, status transitions and `data-preview-rendering`. | **recording**, screenshot artifacts also required |
| C2 hidden native inactive/missing shell | AFFECTED timer path and repeated request replacement | Electron; P | A attached but hidden, no active turn; use supported automation request on same tab from audit client. Capture, repeat at approximately 6s, check no suspension at original 10s, then release at 10s from latest capture; recapture wakes it again. Pair with missing shell only if reachable through supported real app lifecycle; otherwise label supplementary store-level fixture, not runtime proof. Observe timer events externally; no test sleeps manufactured. | **recording** + screenshot artifacts |
| C3 already visible / other activity | AFFECTED notification but intended unchanged pixels; OR branches prevent premature suspension | Electron; G for visible native shot; P for lease controls | Capture visible N1; hide with native PiP or existing built-in recording as a separate control, capture, let hold expire/end turn. Existing PiP/recording must continue painting; closing it then allows suspension. Include screenshot request after ending a turn to cover active->idle->new timer hold. Built-in recording enabled ONLY for this control. | **recording** + screenshot artifact |
| C4 routing isolation | AFFECTED new capture-key matching; unchanged unrelated tabs | Electron; P | Two threads A/B and two tabs in A with distinct markers. Capture hidden A/tab2 while B visible. Only intended runtime ID gets hold; wrong/closed key and non-capture CDP (`DOM.enable`) do not wake unrelated tab. If environment IDs collide in raw tab IDs, primary matching must remain scoped. Use actual known IDs; synthetic malformed-key injection only supplementary. | **recording** + screenshot artifact and ID transcript |
| W1 browser/server stream | UNAFFECTED predicate (Electron false); no desktop channel means no new marker needed | Web dev real browser; G | Open same seeded server tab, main->floating->main, screenshot, fixed viewport, control and failure. Desktop host absent. Stream page and screenshot marker must agree. Repeat server-only tab already open BEFORE desktop channel later connects as protocol control: note marker absence and check identity on Electron reveal; this is a boundary risk, not established fixed behavior. | **recording** + screenshot artifact |
| R1 remote environment | UNAFFECTED predicate: Electron + non-primary environment always streams; overlay ignore is AFFECTED if stale overlay exists | Electron remote and browser; G stream layout can reuse W1; P for routing | Connect isolated second environment, open its server tab; main/floating and screenshot must agree. Local desktop capture event must not wake remote/native unrelated tab. Exercise one direct remote route; relay/tunnel use same serialized snapshot and stream and need one transport smoke if available, not every fixture repeated per transport. | **recording** |
| D1 desktop-runtime tab | UNAFFECTED: runtime desktop/legacy absent, independent of server headless | Electron; G | Open on this computer through existing UI, panel/floating, native shot and cursor/zoom. `runtime !== server` remains hosted; new server capture notifications should not change it. Browser viewing desktop-only tab retains existing desktop-app message. | **recording** |

## Platform decisions / exclusions

Actual Electron on Linux under headless-desktop is explicitly authorized by the task and overrides EVIDENCE.md's older blanket VM prohibition. libsecret-dev is reportedly installed; capture runner must still record actual packaged build and launch success. Do not downgrade H1/C1 to a Chromium mock or fabricated desktopBridge. Web proof alone cannot exercise IPC, native guest visibility, hidden frame wakeup or native/server page identity.

macOS has a distinct `keepPaintableWhenInactive` path in HostedBrowserWebview because Electron 43 visibility hiding can permanently blank guests. Linux proves this fix on Linux only. Require a targeted macOS C1->turn end->reveal and H1/H4 recapture before claiming cross-platform native verification; Windows needs the same focused hidden/reveal smoke if claiming it verified. No platform-specific code changed here, so full G multiplication across OSes is unwarranted; list unavailable OS proof honestly. Linux actual Electron evidence is valid, not automatically needs-Julius just because of old ops guidance.

React Native iOS/Android UI files are unchanged and are not callers of these web components. No EAS mock build required for this focused diff. Contracts add optional boolean, so old snapshots remain compatible; any mobile preview client that consumes server snapshots should receive a targeted stream/status compatibility smoke if available, not a claim that 390 web is mobile-native proof. DeviceMiniPlayer and device streams, provider account counts, long provider names, usage settings, and unrelated scheduling/annotation combinations are unaffected and excluded. Claude is the known trigger for H1; the fix is transport/runtime-shaped, not adapter-shaped, so multiplying six providers is unnecessary. Explicit scheduled-task adapter matrices would not isolate this change.

Other unchanged conditions are controls rather than new fixtures: null snapshot renders no floating browser; absent/false headless are equivalent; non-server runtime ignores headless; missing primary environment cannot be native. Runtime active statuses all share the same hold branch; exercise running->waiting->idle in C1 if practical, and use focused existing logic coverage for preparing/queued/starting rather than manufacturing six identical videos.

## Minimal reproducible seeding artifact (implementation/capture agent work, NOT done by auditor)

Commit one narrowly scoped runner, suggested `scripts/evidence/issue-16901.mjs`, with fixture HTML/PDF embedded as literals (no separate framework, test suite, database dump or checked-in screenshots). Alternatively link the exact script/data revision from PR body if maintainers choose the linked-artifact exception in EVIDENCE.md; a committed runner makes the requested rebuild from SHA simplest. This is a runnable fixture, not implementation-plan documentation.

Runner responsibilities:

1. Serve deterministic loopback HTML with A/B history links, `window.open` popup, fixed PDF, attachment response, deliberate failed navigation, and a response gate released by the driver. Page uses a fixed layout, no clocks/animations/network dependencies; unique visible page/token/step and solid red/blue update markers, plus stable title. Reuse one page for every row. For remote server, bind within that isolated environment and use its reachable address; don't hard-code localhost into client bundles.
2. Use isolated T3 home/user-data and stable project/thread A/B creation through supported app APIs/CLI. Real copied dev data may supply surrounding history, but record exact sanitization and seed runner input; never commit private DB contents, credentials or startup pairing URLs. No direct writes to live userdata, and no DB fabrication for ephemeral preview sessions: create sessions via real preview operations and retain actual IDs in a local manifest.
3. Expose scenario arguments such as `late-attach`, `native-hidden`, `idle-capture`, and `stream-states`, with output manifest for SHA, client build, fixture URL, thread/server/runtime IDs, themes and viewports. Use event/status barriers for page creation, first frame, response gate and turn end. The explicit 45s renderer block is the race stimulus, not a generic readiness sleep. Script must target ONLY the spawned APP renderer, never Electron main, guest renderer or agent; record target selection. Do not change production attach timeout for evidence.
4. H1 exact known reproduction remains the first acceptance gate: example.com + Claude sleep 5 + 45s app-renderer CDP busy loop + new `preview_open open:false`. Afterwards replace page body/style using same-tab evaluation with fixed marker. A fully local fixture can replace example.com only after demonstrating equivalent base failure/head success. Literal sleep45 and merely selecting another thread already reportedly pass: preserve as a small unaffected control, never substitute them for H1.
5. Native C1 seeding must complete native attachment BEFORE hiding tab, and verify marker is absent/headless false before capture. H1 must verify fallback occurred and marker true after. These are mutually distinct fixtures; a headless screenshot cannot prove native hidden painting. Use actual `preview_screenshot` tool for server/CDP path, not just PreviewView's native menu screenshot or an external screen grab.
6. Capture external screen recordings and tool transcripts; emit checkpoint notifications so capture driver can take SHA-labelled before/after frames. Endpoints/gates should acknowledge explicit events. Seed/Capture runner may use real elapsed observation for the 10s product timer; no new production sleeps, test polling, mocked captures or self-certified success. Clean up only resources/PIDs created by that run.

## Pass-2 acceptance / audit risks

Must inspect the returned screenshot content as well as client frame: a tool success without marker identity does not prove a correct page. Conversely a red panel alone does not prove agent screenshot completion. H1 and C1 are separate hard gates. Verify H3's stale fields actually existed; if not, report that fixture unseeded. Check H4 first-frame aspect when stale desktop zoom exists. Check popup adoption marker, streamed error overlays and headless lifetime from event/status transcript. Headless mark is conditional on desktop channel availability at creation; desktop connecting after an unmarked headless page is created remains a boundary requiring W1 control, not an assumption of correctness.

Existing added tests cover one marker distinction, native CDP notification and two hold lifetimes, but no test was run/read as proof of runtime behavior. Do not create mirror UI tests to satisfy this evidence audit. Do not report pass until recordings and pairs have been reviewed against this table. No PR body/comment writes were authorized for this audit; lead can link this artifact under Evidence matrix.

## FRICTION

- `/home/ubuntu/t3code-ops/AGENTS.md` does not exist; read worktree AGENTS.md and supplied global/project instructions, and read `/home/ubuntu/t3code-ops/docs/EVIDENCE.md`.
- Old ops desktop-VM prohibition conflicts with explicit current authorization; current task wins. No runtime was launched by this auditor.
- `PreviewMiniPlayer.tsx` guess was absent; resolved committed tree to `ThreadPreviewMiniPlayer.tsx`. All implementation inspection used git show/diff of immutable commits, not mutable source files.
- Native 390 width, server PiP capability, stale-overlay race, missing-shell runtime reachability, and macOS/Windows availability must be recorded by capture agent. None was silently assumed available.
- This is an unverified pass-1 matrix, not evidence or a merge recommendation. Script/data still need implementation and commit/link by capture owner; no tests or captures were manufactured.
