# Proof audit, pass 1: hidden desktop screenshot capturer

Reviewed [#25978](https://git.cafe/pingdotgg/t3code/pull/25978), source branch `fix/issue-17870`, against the requested merge-base. The GitCafe PR metadata, checked-out HEAD, and local merge-base agree: before [36d4d711b7](https://git.cafe/pingdotgg/t3code/commit/36d4d711b79c73eb33131944f73ea4a8c6156484); after [0f5210654a](https://git.cafe/pingdotgg/t3code/commit/0f5210654a65b5596426b1abe149bae25cb01c90). Scope is the two-file diff, its runtime callers, and evidence design. No app/browser launched, tests rerun, repository edits, pushes, or comments. This is a fixture specification, not a capture report.

## Findings first

1. **Current proof is insufficient for the real-app lifecycle claim.** The [existing Electron harness log](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f5d4f397680932d8/electron-hidden-guest-capture-offset-100000.log) demonstrates a real native capture stalling offscreen and finishing after repositioning. It has no revision identifiers, DesktopBrowserHost painting events, turn end, relay release/reconnect, or viewer detach. It supports the Chromium mechanism, not the application fix. The added/updated test source specifies the host state transitions with a fake debugger; it does not measure a native capturer.
2. **C is a control; the changed races are T, R1, R2, and D.** Normal successful screenshot completion should succeed in both revisions. Demand a before/after difference only when the lifecycle action actually occurs between native screenshot send and settlement. Separate endpoint release from backend reconnect: the latter runs `announceAll` when the new backend subscribes to host events. Closing a random viewer while an agent screenshot runs does not test D; the detached owner must own the pending screenshot.
3. **A movie cannot show the wake lock.** The hidden painted guest remains behind the app at z-index -1. Runtime event recordings/transcripts are decisive. A synchronized screen recording can establish that the real desktop app remained running, the panel stayed closed, and the driver performed the lifecycle action, but identical pixels are expected. No light/dark or narrow/wide screenshot gallery is warranted.
4. **`isBeingCaptured()` is a capturer indicator, not a named OS assertion.** Electron documents a boolean “being captured” API, not a stay-awake classification ([API](https://www.electronjs.org/docs/latest/api/web-contents#contentsisbeingcaptured)). The host code explicitly notes that focus emulation also counts the guest as captured. Chromium's [focus emulation](https://chromium.googlesource.com/chromium/src.git/+/HEAD/content/browser/devtools/protocol/emulation_handler.cc) uses `stay_awake=false`; its [screenshot handler](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/content/browser/devtools/protocol/page_handler.cc) uses `stay_awake=true`. These upstream sources explain the distinction; shipped Electron 44.9.3 still needs runtime observation. Record actual focus enable/disable command settlement and sample the boolean again after focus is off. Do not fail a completed screenshot merely because focus remains enabled for its idle grace period or an active agent turn. Linux proves native capturer release, not a macOS `pmset` assertion.
5. **Pending must mean Chromium pending.** A delayed wrapper promise after native resolution cannot reproduce a native wake-lock leak. A queue entry not yet sent cannot own that screenshot's native capturer. Log native send and native resolution/rejection separately from host completion and RPC/tool response. If the race cannot be reached naturally, identify the precise scheduling/frame gate and label the evidence as an instrumented real-app run or a harness; do not present injected host commands as an ordinary RPC flow.

## Runtime paths and callers

The changed production component is [DesktopBrowserHost](https://git.cafe/pingdotgg/t3code/blob/0f5210654a65b5596426b1abe149bae25cb01c90/apps/desktop/src/preview/DesktopBrowserHost.ts). The other changed file is its [test](https://git.cafe/pingdotgg/t3code/blob/0f5210654a65b5596426b1abe149bae25cb01c90/apps/desktop/src/preview/DesktopBrowserHost.test.ts), not a rendered component.

- Main constructs one host service. [DesktopBackendManager](https://git.cafe/pingdotgg/t3code/blob/0f5210654a65b5596426b1abe149bae25cb01c90/apps/desktop/src/backend/DesktopBackendManager.ts#L888) sends its event stream to backend bootstrap fds and dispatches incoming command lines. Subscribing to `host.events` invokes `announceAll`, clears agent turns, drops old relays, and announces surviving tabs. A reconnect is therefore a separate entry point from a received `release` command.
- [Desktop preview Manager](https://git.cafe/pingdotgg/t3code/blob/0f5210654a65b5596426b1abe149bae25cb01c90/apps/desktop/src/preview/Manager.ts#L2308) attaches a server-owned webview's native WebContents/debugger after registration. Closing/replacing its control tab detaches the host entry. The same manager subscribes to `painting` and maps it to the tab state's `capturing` bit ([consumer](https://git.cafe/pingdotgg/t3code/blob/0f5210654a65b5596426b1abe149bae25cb01c90/apps/desktop/src/preview/Manager.ts#L3247)). Pointer and download helpers also call the host but do not change this painting calculation.
- [usePreviewBridge](https://git.cafe/pingdotgg/t3code/blob/0f5210654a65b5596426b1abe149bae25cb01c90/apps/web/src/components/preview/usePreviewBridge.ts#L30) maps `capturing` to browser-surface activity. [HostedBrowserWebview](https://git.cafe/pingdotgg/t3code/blob/0f5210654a65b5596426b1abe149bae25cb01c90/apps/web/src/browser/HostedBrowserWebview.tsx#L288) renders while `active || backgroundActivity || pictureInPicture || recordingActive`. [Wrapper style](https://git.cafe/pingdotgg/t3code/blob/0f5210654a65b5596426b1abe149bae25cb01c90/apps/web/src/browser/hostedBrowserWebviewStyle.ts#L20) branches: visible active rect; hidden but rendering at (0,0), z-index -1; inactive at (-100000,-100000), z-index -1. macOS keeps the offscreen element CSS-visible; Linux normally hides it. Width/height derive from the visible rect or stored hidden viewport. Positive dimensions affect screenshot bytes, not the new host decision. Null rect behaves as hidden. Settings/config not hydrated means no webview; there is then no attached native guest to test.
- [ServerBrowser](https://git.cafe/pingdotgg/t3code/blob/0f5210654a65b5596426b1abe149bae25cb01c90/apps/server/src/preview/ServerBrowser.ts#L689) connects a server-runtime tab to the desktop through [DesktopBrowserChannel](https://git.cafe/pingdotgg/t3code/blob/0f5210654a65b5596426b1abe149bae25cb01c90/apps/server/src/preview/DesktopBrowserChannel.ts#L137). Endpoint scope finalization sends `release`. ServerBrowser forwards PreviewAgentActivity transitions as `turn` commands. Root turn/owned children settling, or interruption cleanup, ends that activity; an unrelated background process does not keep it active.
- Native CDP screenshot emitters in ServerBrowser are: agent/observer `snapshot` via [ServerBrowserPage.captureViewport](https://git.cafe/pingdotgg/t3code/blob/0f5210654a65b5596426b1abe149bae25cb01c90/apps/server/src/preview/ServerBrowserPage.ts#L449) (PNG); recording startup's first frame (JPEG); and a viewer's initial/settled still (JPEG). All reach the changed `Page.captureScreenshot` branch. User-facing desktop `Manager.captureScreenshot` instead uses Electron `capturePageWithRetry`; that button is not a substitute for exercising this CDP path.
- [CdpRelay](https://git.cafe/pingdotgg/t3code/blob/0f5210654a65b5596426b1abe149bae25cb01c90/apps/desktop/src/preview/CdpRelay.ts#L142) has a main/default owner, generated page owners, browser sessions, and real child session IDs. Generated page sessions flatten to the native page; their IDs identify the owner to detach. `Target.detachFromTarget` on a generated page session calls `dropSessionHolds`. Child session IDs remain native IDs, do not hold the parent page's screencast, and do not share the generated owner's liveness rule. Screenshot accounting wraps every forwarded screenshot, including those with a child sessionId; an invalid child screenshot may just reject.

Before: painting = registered tab AND (screencast count > 0 OR any live *held* queued screenshot OR a pending focus hold tagged screenshot).

After: painting = registered tab AND (screencast count > 0 OR sent-unsettled screenshot count > 0 OR any live queued screenshot).

The required branch inventory is consequently: no attached tab / same attach / replacement; idle vs one or more captures; zero vs live vs stale queued screenshots; `held=true/false`; focus command settled vs pending; current screenshot guard valid vs invalidated; same relay vs released relay; live vs detached generated owner; native resolve vs reject; active vs ended thread turn; new document vs same-document navigation; zero/one/multiple screencasts, start success/refusal, stop last/not-last, page vs child sessions. There are no count-based lists, empty/loading/error cards, text-length, theme, or breakpoint branches in the changed host. Loading a *new document* matters; merely reporting `loading=true`, a navigation error, hash change, or theme change does not call `onNewDocument`.

## Common fixture and measurement contract

Use a fresh isolated T3 home and project/thread, `T3CODE_DEV_SEED=0`, and the real Electron 44.9.3 app under the lead's `headless-desktop` Xvfb/D-Bus launcher. Never use live userdata. The capturer owns launch details; this audit did not validate that launcher. Keep dev single-origin. Use one normal non-minimized desktop window, e.g. 1440x1000, one app theme (dark is sufficient), one guest viewport (e.g. 1280x800), and a deterministic loopback HTML page with a heading, button, and enough scrollable content for D. All backgrounds/other viewers/PiP/recorders must be off except in the explicit control rows. Do not open guest DevTools or install a frame-subscription recorder as the measurement probe: those can change guest rendering/capture activity.

Every run logs revision/Electron/Chromium versions, run ID, threadId, logical tabId, native WebContents ID, relay generation, owner/session ID, monotonic event times, native screenshot command ID + format, native send/resolve/reject, host reply disposition, painting publish AND manager/renderer application, actual wrapper rect/visibility, `isBeingCaptured()` samples, focus command sends/settlements, document events, and guest destruction. No tokens, endpoint secrets, private page data, or image base64 belong in the public transcript. Record response byte length/dimensions instead. A renderer CDP probe can read DOM/style; reading `isBeingCaptured()` requires main-process/Electron access or scratch logging because it is a WebContents API, not page JavaScript.

Notation: `P+`/`P-` = painting active/inactive transition, no initial false event is implied; `N` = native screenshot outstanding; `B` = `webContents.isBeingCaptured()`; `F` = focus emulation. “Final B=false” is measured after actual F=false and with no other capture source. `answered` means native screenshot promise resolved with data, not just the server timed out. A released relay may drop a successfully resolved native reply. The expected traces below are source-derived predictions to verify, not observed results.

All table rows are **recording** because they involve state transitions, interaction, or time. Timestamped event recordings are necessary; stills cannot prove them. Screen videos add provenance/action context, and no direct capturer evidence. None requires a distinct theme or viewport combination.

## Fixture matrix

| Row / status | Data and trigger; real-app seeding vs harness | Before 36d4d711b7: required transcript | After 0f5210654a: required transcript | Affected / capture priority / recording contribution |
| --- | --- | --- | --- | --- |
| I — specified; no runtime capture | One hidden attached server tab; no screenshot, no stream. Send `DOM.enable`/ordinary housekeeping and then end activity. Real app startup/Playwright setup supplies this. | No P+ and N=0. F may enable for the command, then disable on idle. Final B=false. | Same. | Control; include initial/final interval of C. **recording**; screen only establishes hidden panel. |
| C — pending core proof | Hidden tab, one agent PNG snapshot, no concurrent lifecycle action. Repeat with two ordinary sequential/queued screenshots to observe guard draining if a driver can enqueue both. Native JPEG recording-seed and viewer still are emitter aliases, not different painting rules. | P+; native send; N=true, B=true while captured (possibly also F); native answer, N=false; P- after last capture/queue; final F=false, B=false. With queue, only one native screenshot at a time; P stays active across the handoff. | Same completion and final release. P+ moves from focus-hold acquisition to actual native send; do not demand identical sub-millisecond ordering. | Control; **minimum core**, both revisions. **recording**; pixels expected unchanged. |
| T — pending core proof | Hidden agent screenshot native-sent, still pending; end the actual run/last PreviewAgentActivity token before native settlement. Use UI Stop or `orchestration.dispatchCommand` with `type:"run.interrupt"`, threadId, runId, unique commandId. Confirm host receives `turn active:false`. | P+ then P- at turn end; with native request still pending and guest now offscreen, N=true and B=true even after F=false. Record a bounded observation interval, then separately label a rescue by real painting/navigation/close. | No P- merely at turn end. Native capture answers while painting is retained; then P- when no other queue/stream/capture remains. N=false and final B=false after F=false. | Changed; **minimum core**, both revisions. **recording**; screen can show Stop, not the lock. |
| R1 — pending core proof | Native-sent pending screenshot; close the owning server desktop endpoint scope while the guest survives. Normal app path is `ServerBrowser` desktop connection close/drop, whose scope finalizer writes `release`. No public preview MCP tool means “release relay but keep guest.” Scratch service trigger must be labeled. | P- on received release; native N remains true and B remains true after F=false if no new painting source rescues it. Old relay replies are suppressed. | Painting remains active through release until the native screenshot settles; N becomes false, P- then follows. Old relay reply remains suppressed; final B=false. | Changed; **minimum core**, both revisions. **recording**; invisible action unless driver/status annotation is shown. |
| R2 — pending core proof | Native-sent pending screenshot; restart only the isolated app-owned backend while preserving desktop guest/main process. Track spawned backend PID; the next `host.events` subscription runs `announceAll`. Log attached announcement and new relay generation. Do not confuse a network viewer reconnect with this. | announceAll/dropRelay causes P- while N=true; the old screenshot can remain captured/offscreen after F=false. A later *new* screenshot can rescue it, so capture the pre-rescue interval separately. | announceAll drops relay/turn/focus ownership but preserves sent capture painting; old native screenshot answers, old reply is suppressed, P- follows when idle, final B=false. New backend can control the surviving tab and take another screenshot. | Changed; **minimum core**, both revisions; R1 does not cover this entry point. **recording**; video establishes app survives backend restart. |
| D — pending core proof | Hidden tab; **viewer-owned** native JPEG still pending; detach that exact generated page session, with no other active screencast. Real path: `/api/preview-stream/ws?threadId=...&tabId=...&interactive=false` with local authorized auth, trigger a settled still after scroll/motion, then close that viewer socket after native send. Finalizer stops screencast and calls session.detach. | After last stream/session hold is removed, P- although its sent screenshot still has N=true; B remains true after F=false if the guest is offscreen. Log matching owner and actual Target.detachFromTarget. | Session detach removes owner focus/stream but does not discard the sent native capture. P stays active until native answer, then P- and final B=false. Native completion can arrive for a departed viewer; UI delivery is immaterial. | Changed; **minimum core**, both revisions. **recording**; screen adds only viewer connection/closure context. |
| QT — test-source coverage; not rerun | Two screenshots on same tab; first native-sent/pending, second queued/live; then turn end. Fake-debugger test exists (“holds no focus…”). Real native queue is feasible via overlapping requests, but server capture locks serialize many entry points; use existing-relay CDP injection only as a labelled harness if necessary. | Turn end clears held flags: P+ then P-. Native first may stall; after a separately labelled rescue lets it answer, second is sent without a focus/painting hold and can stall too. | Turn end does not stop painting; first answers, second actually sends and answers in order; no overlap, P stays active until final P-. F can be off while second capture still requires painting. Final B=false. | Changed queue branch; targeted harness/control evidence. **recording**; no useful visible difference. |
| QD — test-source coverage; not rerun | First sent capture abandoned at turn end; second queued by generated viewer owner; detach second's session before first answers. Existing “stops painting for a queued screenshot…” test. | P may go +,- at turn end, + for live queue, - on queued owner detach. First can still own B=true. On rescue/first completion, second is rejected unsent. | P stays active for first even when second owner detaches; on first answer, dead queued second is rejected unsent, then P-. Native send count proves only first reached Chromium. Final B=false. | Changed; targeted harness/control evidence. **recording**; no pixel evidence. |
| QR — test-source coverage for relay queue; not rerun | First sent pending; second queued on old relay; release it; optionally third queued on newly established relay. Existing release queue test supplies the dead-relay branch; log exact generations. | Release can P-; old queued second must never send. A new live queue may P+ and rescue first; therefore do not cite that rescued case as an R1 failure reproduction. | P remains active for old sent capture; old queued second drops unsent; new-relay third sends only after first settles (unless a real new-document reset intervenes). P- only when all live work ends. Final B=false. | Changed liveness branch; targeted harness/control evidence. **recording**; invisible. |
| N — test-source coverage; native reset unmeasured | Pending capture, no stream/queue; real top-level reload/new document, then a new screenshot. Optional live queued successor verifies it starts after reset. Use preview_navigate or reload; log actual `did-navigate`, not hash-only navigation. | P- on new document; guard releases old screenshot turn; new screenshot can P+ and complete. Old native promise can remain unanswered, reject, or resolve late; record which. | capturing set clears on did-navigate: P- with no queue; successor gets its own fresh token and normal P+/P-. A live queue can keep P continuously active. Late old completion must not erase a new capture or start overlapping successors. | Reset control/changed set clear; can be recovery appended to T/R/D. **recording**. Source alone does not prove old native B clears: measure B after F=false; report persistent B as a contradiction, not a pass. |
| X — test-source coverage; native destruction unmeasured | Pending capture; close actual hidden tab via `preview.close` RPC `{threadId,tabId}` or UI; separately replace a guest under same key if available. Manager closes/detaches, replacement gets a fresh WebContents ID. | Host detach publishes P-; old host entry/replies no longer active; replacement starts with no pending screenshot. | Same, despite capturing set on old tab. Old settlement cannot paint replacement. | Registered-tab control. **recording**; append to failed before-run recovery. Logical host.detach alone does **not** guarantee native B=false: the old WebContents must actually be destroyed; log destruction and treat B as unavailable thereafter. |
| F1 — source-specified; harness scheduling fixture | Screenshot is first/current but waits for `Emulation.setFocusEmulationEnabled` to settle; owner/relay/document stay valid. Deterministically deferring that native promise requires a labelled debugger harness; normal real app can opportunistically observe it. | P+ before focus finishes/native send. After F settles, send/answer, then P-. | No P+ for this unsent request until focus settles and native send is about to occur. Then ordinary C trace. | Changed pre-send interval. **recording**; fake delay proves host ordering only, never native wake lock. |
| F0 — existing invalidation test sources; not rerun | As F1, invalidate current before native send via owner detach, relay release, or new document. These share rejection predicate but need labelled subcases if captured. Generated owner ID must match; a same-document navigation is a negative control. | May P+ while waiting for focus, then P- at invalidation. When focus eventually settles, native screenshot send count remains zero and host reports stale request error where relay remains deliverable. | No capture-induced P+ or native capture at all; same current/owner rejection. B may transiently reflect F, but after F=false final B=false. | Changed suppression of unsent painting; harness timing fixture. **recording**. No screenshot capturer is asserted for an unsent command. |
| E — source-specified; harness/error control | Native screenshot send rejects (e.g. unsupported/invalid raw capture params). Public preview_snapshot supplies fixed valid PNG params; raw-CDP injection into existing relay is a labelled harness, not a user tool parameter. A fake rejection can cover host finally cleanup only. | P+, rejection, P- with no other work; no leaked focus hold; final B=false after F=false. | Same cleanup through capturing.delete in finally. A subsequent valid screenshot must work. | Error control for new finally. **recording**; no visible error surface required. |
| S — existing test-source coverage; not rerun | Two generated page screencasts; stop/detach one then last. Also refuse a page start, and refuse child-session start while parent page stream survives. Real app: two authorized viewer sockets (or viewer+recording); refusal/child variants are labelled raw-CDP/fake-debugger harness. No screenshots during pure-stream measurement. | P+ for first page stream, remain + when only one of two stops, P- after last stops/detaches. Refused sole page start P+ then P-. Child refusal must not erase parent stream. Native screenshot N=0. | Same steady painting policy; syncPainting now explicitly called on start/stop rather than through holdFocus. Focus releases on idle only after all streams end. Record actual B; pure streaming need not acquire screenshot stay-awake capturer. | Touched screencast bookkeeping; count 2→1→0 collapses all positive counts. **recording**; stream/scroll is visible in a remote viewer, lock is not. |
| V — source control; optional capture | Guest already paintable because visible active rect, PiP, recording activity, or another independent surface activity. Repeat a C or lifecycle race without removing that independent activity. | Host P can fall on lifecycle action, but independent surface rendering can still answer native capture and clear it. A passing native capture here does not reproduce hidden-tab failure. | Native capture answers; host retention differs where applicable. Wrapper stays paintable for the independent activity even after host P-. | Masking control, outside minimum. **recording**; panel/PiP can visibly change, but no extra theme/width coverage needed. |
| M — cannot-verify macos | Same T/R/D sequences on macOS; observe `pmset -g assertions` Capturing/NoDisplaySleepAssertion with process identity, F, native capture state and no unrelated capturers. No Mac available to this capture plan. | Expected assertion retained by stalled screenshot; must be measured before claiming Mac proof. | Expected assertion released once native screenshot answers; must be measured. | Platform extension; **recording**, unavailable here; Linux B evidence cannot be relabelled as pmset proof. |

## Driver recipes and limits

1. **Seed the correct app path.** In an authorized isolated thread MCP session, `preview_open({url:"http://127.0.0.1:<fixture-port>/",open:false,reuseExistingTab:false})`, retain its returned tabId, and use `preview_snapshot({tabId})` (includeImage/save affect presentation/storage, not whether native capture occurs). The server browser host is preferred, but existing broker assignments can pin a different host. Verify runtime=server, desktop fd channel attachment, native WebContents ID, and Page.captureScreenshot in DesktopBrowserHost; absence of these means the test used headless Chromium or an old desktop capturePage path. A fresh tab/agent session and explicit tabId avoid accidental target reuse. `preview_recording_start` first JPEG is another native capture emitter, but continuous recording masks hidden offscreen behavior, so it is not the core reproduction.
2. **End the turn (T).** Start an actual isolated run whose preview activity is active. Driver `preview_snapshot` alone is not proof of an active provider run. After native screenshot send, use Stop/`orchestration.dispatchCommand` run.interrupt or allow a timed-out tool's agent run to finish. Await/log the host's actual active:false command, not just the Stop RPC acknowledgement. Log no remaining owned children/activity token. Sending `{type:"turn",active:false}` straight to the host is a legitimate host harness, but it bypasses run execution and must be labelled accordingly.
3. **Release vs reconnect (R1/R2).** `preview.close` destroys the tab and is X, not R1. Closing a browser viewer socket is D, not R1. R1 requires ServerBrowser's desktop connection scope close and the emitted `{type:"release",threadId,tabId}` while the same WebContents lives. No public RPC exposes just that release. Use a scratch-only service hook to close the real connection scope, or a labelled host-command harness. R2 can use a real restart of only the dev backend the capturer owns; record PID/session, new subscription, announceAll and survivor reattachment. A scratch events-stream resubscription proves the host path but is not full backend reconnection. Do not kill desktop, the shared T3 server, or any process found by a name pattern.
4. **Detach the owner (D).** The real viewer is the server stream WebSocket route above, with auth/ticket handled locally and not logged. AttachViewer makes a generated page CDP session. Its initial idle still can happen *before the WebSocket upgrade completes*, so merely closing a not-yet-open socket may never reach session detach; prefer a settled still after a fully attached viewer scroll/motion. Log viewer sessionId, JPEG native send, finalizer Page.stopScreencast, and matching Target.detachFromTarget before native resolution. The viewer socket's stop must remove the last screencast, or it masks the bug. An agent PNG captured on its own session while a different viewer closes is the wrong D fixture.
5. **Reach the pending window honestly.** For T/R/D accept a run only with `native_send < lifecycle_received < native_settle`, and with the initial screenshot actually held native-side (B sampling helps establish this). Native hidden capture can answer quickly as soon as the app paints it. There is no public “pause screenshot completion” tool. Try the real routes with event-driven dispatch; do not assume a sleep or closing a viewer after a completed tool call creates the race. If scheduling instrumentation is needed, document exactly what is gated. Holding only the JavaScript return promise after native completion is invalid for wake-lock proof. Mutating wrapper position or suppressing painting delivery can demonstrate recovery, but changes the integration under test; label the run instrumented, keep the native completion probe below the gate, and include an ungated C run. Pure fake-debugger captures can show P/queue semantics only; B and OS assertion fields must read “not measurable.” Do not open a second WebSocket connection to the one-client desktop CDP endpoint to inject test traffic; inject through the existing relay/service in a labelled harness instead.

## Minimum capture set and acceptance

- One viewport × one theme × **C, T, R1, R2, D**, before and after = **10 core runtime event recordings**. I is included as the clean idle interval in C. N/X can be labelled recovery tails in the failed before runs. One synchronized screen video per revision may cover all these rows with visible row markers; five separate movies per revision are unnecessary. The video pixels are provenance, and the per-row timestamped transcripts are the proof. If a core race is attainable only through an instrumented real-app driver or only in a host harness, mark that exact level and the remaining end-to-end limitation; do not silently promote it.
- QT/QD/QR/N/X/F0/S already have relevant test source, while F1/E directly exercise newly moved ordering/finally boundaries. These are the complete control matrix for code/harness review; use focused event harness recordings/tests for exact scheduling, not an expanded UI screenshot project. This audit inspected those tests, did not rerun them, and does not independently certify the PR body's reported 34/97 passing counts. An actual backend reconnect is not specifically proven by the new turn/release tests.
- T/R/D before traces require an actual pending capture at the invalidation, P becoming inactive while N stays pending, offscreen wrapper confirmed, and B still true **after F=false**, without another screenshot/viewer/recorder rescuing it. A bounded observed stall is evidence of the failure; it does not prove an hours-long duration. The corresponding after trace must show native answer plus P eventually inactive, offscreen idle wrapper, and final B=false with F=false. R2 additionally proves backend recovery and a new successful screenshot. A native rejection should be reported as rejection; it is cleanup evidence, not a successful screenshot.
- A capture that completes before the lifecycle action covers C, even if the video later shows Stop or viewer closure. An after run with the panel open or another streaming viewer covers V, not the required hidden fixture. P+ without manager/renderer propagation is only host state evidence. A server timeout or discarded relay reply does not establish native completion. Never assert B=false on a destroyed WebContents; destruction is a separate terminal state.
- Theme, text length, viewport breakpoints, provider selection, empty/loading/error UI, web/mobile screenshot galleries, remote transport latency variants, and maximized/minimized OS windows add no required branch coverage to this host diff. The same affected desktop guest may be controlled from web/mobile/remote clients through the stream, and D exercises that route. Pure web/mobile/headless guests without the desktop fd channel bypass this component. Host behavior is provider-independent; actual PreviewAgentActivity end delivery still must be observed for T. Minimized-window compositor policy is outside this targeted matrix and must not be implied verified.
- macOS stays explicitly **cannot-verify macos**. Linux native capturer release plus the code/harness lifecycle evidence can support the fix without claiming direct OS sleep-assertion verification. A screen recording is not a substitute for that missing platform observation.

## Coverage and handoff

Covered: exact requested diff/head/base metadata; entire production host and changed tests; relay owner mapping; desktop manager attachment/painting bridge; renderer activity/style branches; server native screenshot emitters; activity/endpoint/stream lifecycle entry points; original published harness transcript. No runtime capture or diagnostics executed. No code bug is asserted by this proof-design pass. The outstanding blocker is evidence connecting the changed application state paths to actual native screenshot completion/capturer release.

FRICTION:
- tool | web fetch could not open the supplied .log artifact; direct read-only curl succeeded | allow text artifact URLs in web fetch, or use curl as the documented download path.
- tool | initial public readback encountered HTTP 403 and a DNS resolution failure; curl using the captured upload URL then verified identical matrix bytes | use the uploader's returned URL directly and distinguish upload success from download verification.
- brief | R1 has no public release-only preview RPC, and T/R/D require an unguaranteed native pending interval | explicitly distinguish real-app lifecycle runs, scheduling instrumentation, and host-only harness evidence before capture.

VERDICT: INSUFFICIENT C/T/R1/R2/D real-app before/after native lifecycle transcripts; macOS assertions remain cannot-verify macos
