# Pass 1: code-derived proof matrix for PR 20924

Read-only audit in `/home/ubuntu/wt/pr-20924`. No browser, tests, server, checkout, push, review comment, or watch started. Only external handoff artifacts written under `/tmp/ev-20924`. This is a capture specification, not visual approval.

Original [#20924](https://git.cafe/pingdotgg/t3code/pulls/20924), also [#20924](https://github.com/pingdotgg/t3code/pull/20924), fork [watashiwaaniket/t3code](https://github.com/watashiwaaniket/t3code), branch `fix/preview-snapshot-backdrop-filter`, original [5afb4d04](https://github.com/watashiwaaniket/t3code/commit/5afb4d04daaf16553b94e2c33e7732ddbb88ce20).
Replacement `takeover/pr-20924` [097dc0d6](https://git.cafe/pingdotgg/t3code/commit/097dc0d6c0e8441d1b2aa085d011a0e509ef26d9). Verified HEAD equals supplied SHA. Read full `git diff origin/main...HEAD`: 4 files, 138 insertions, 48 deletions. `origin/main` and merge base both [c4fa4629](https://git.cafe/pingdotgg/t3code/commit/c4fa4629eb645b95aae2beef56c70f705b736049).

## Changed paths and code basis

- [ServerBrowserPage.ts](https://git.cafe/pingdotgg/t3code/blob/097dc0d6c0e8441d1b2aa085d011a0e509ef26d9/apps/server/src/preview/ServerBrowserPage.ts): removes clip/offset/scale from captureViewport; snapshots now capture full PNG then shrink via createImageBitmap/canvas in isolated world when scale < 1. Also removes offset from readPageMetrics/renderingOf. Width cap 1280; scale=min(1,1280/(viewport.width*renderScale)). Native display branch retains ratio/zoom metrics calculation.
- [ServerBrowser.ts](https://git.cafe/pingdotgg/t3code/blob/097dc0d6c0e8441d1b2aa085d011a0e509ef26d9/apps/server/src/preview/ServerBrowser.ts): recording first JPEG (1482) and viewer pushStill JPEG (2350) call signature changes; prior scale=1 already omitted clip, so CDP screenshot options remain equivalent. Snapshot caller (1975) retains screencast pause and uses fixed RENDER_SCALE for server pages, display for attached native pages. Recording encoder and live screencast algorithm unchanged.
- [ServerBrowserPage.test.ts](https://git.cafe/pingdotgg/t3code/blob/097dc0d6c0e8441d1b2aa085d011a0e509ef26d9/apps/server/src/preview/ServerBrowserPage.test.ts): adds real Chromium helper-level 1280x800 DPR2 tests, three coarse color probes for blur and plain. These do not establish real-app integration, actual blur quality, themes, scroll, zoom, recording, or viewer recovery.
- [ServerBrowser.test.ts](https://git.cafe/pingdotgg/t3code/blob/097dc0d6c0e8441d1b2aa085d011a0e509ef26d9/apps/server/src/preview/ServerBrowser.test.ts): mock response for Runtime.callFunctionOn. No visual proof.

Surface classification: **server only**, all changed paths are under apps/server. Web Browser panel is the client used to exercise that server path; do not claim a desktop surface change merely from server native-display support. No mobile, contracts, client-runtime, or desktop files changed.

## Minimal capture matrix

Every static row: BEFORE main, AFTER replacement, independent headed Chromium/Xvfb REFERENCE. Use same Chromium build, content, geometry, media, scroll, zoom. Default height 800; scroll 0, zoom 1, server DPR2 unless overridden. Width means configured server viewport, not outer browser window. Capture returned PNG dimensions and actual innerWidth/innerHeight/devicePixelRatio/scroll coordinates in manifest. Expected dimensions below assume DPR2 native PNG dimensions match configured viewport. Values are expectations to verify, not observations.

| ID | Fixture / width / theme | Classification and expected branch | Artifact | Required judgement |
|---|---|---|---|---|
| A1 | blur / 1440 / light | Affected must capture; shrink 4/9; expected 1280x711 | Static triplet | Actual soft blur through glass, blue left/red right, no mirrored or duplicated content; geometry matches reference |
| A2 | blur / 1440 / dark | Affected must capture; same branch, different compositing | Static triplet | Dark translucent compositing and blur preserved; no mirrored duplicate |
| A3 | blur / 390 / light | Unshrunk regression control, not a claimed fix; expected 780x1600 | Static triplet | Narrow composition and blur unchanged |
| A4 | blur / 390 / dark | Unshrunk regression control | Static triplet | Narrow dark composition unchanged |
| A5 | blur / 1280 / light | Affected must capture; scale .5; expected 1280x800 | Static triplet | Exact test/reproduction width. Retain even if A1 reproduces: establishes original 1280 case |
| A6 | blur / 640 then 641 / light | 640 unshrunk control (1280x1600); 641 affected shrink (~1280x1598) | Two static triplets, settled independently | Boundary is meaningful because RENDER_SCALE=2; no sudden mirrored duplicate above threshold |
| A7 | blur / 1440 / dark; scroll 0→600, then zoom 1→1.25→1 | Affected must capture; removed document clip offsets + existing server zoom emulation | Recording plus final static PNG triplets at scroll600/zoom1.25 | Fixed glass stays anchored; document labels move correctly; no stale/wrong document region, duplicate, or zoom displacement. Record actual layout dimensions, DPR and screenshot dimensions; do not assume zoom changes configured page.viewportSize |
| C1 | plain / 1440 / light | Regression control, changed shrink implementation; expected 1280x711 | Static triplet | No geometry/color/content regression; allow resampling differences, not blind byte equality |
| C2 | plain / 390 / dark | Regression control, unshrunk | Static triplet | Content placement and dimensions unchanged |
| C3 | blur / 1440 / dark; recording start then immediate stop on idle page | Unaffected CDP options; changed recording-seed caller | Recording (before/after playable outputs, plus reference state) | First frame exists and matches page, dimensions/aspect sane; immediate stop remains encodable |
| C4 | blur / 1440 / dark; viewer attached, snapshot during recording, scroll and settle/reconnect | Unaffected full-size JPEG caller; pause/resume and viewer still control | External recording of Browser panel before/after; retain internal recording too | No flash/mirror frame introduced to viewers, playback resumes, settled viewer frame is correct. Internal recording alone cannot prove viewer behavior |
| N1 | native attached page / measured display DPR and zoom | Conditional server path; display ratio/zoom and removed offset touched | NOT required in this server-only pass; record as unverified | Server-owned headless page cannot exercise renderScale='display'. A genuine native attachment is needed, not pretending numeric scale=display or inferring desktop coverage |

No Cartesian product of all themes, widths, zooms, scroll offsets and callers: A1-A6 cover visible branch/theme/width distinctions, A7 covers interactions, C1-C4 cover regressions. No separate color picker state: RGB bands, white/yellow high-frequency features, translucent light/dark background cover color and actual blur. Each width/theme settles before static capture; any demonstrated transition or timing claim requires a recording. A7/C4 can share one controlled interaction session but retain their distinct assertions and artifacts. An unchanged before image at a control row is expected, not a failed reproduction.

## Capturer route: actual app, fresh synthetic state

1. Use only authorized worktree and supplied revisions. Auditor has not switched it. Capturer must stop only its own retained PIDs before switching. Capture main c4fa4629 first, then 097dc0d6. No edits to source to force a launch mode or inject a component harness.
2. Start actual dev server with `T3CODE_DEV_SEED=0 vp run dev --home-dir /tmp/ev-20924 --no-seed`. Database must be fresh per revision. Store before userdata in a capturer-owned archive and create fresh after state; preserve evidence files. Do not read/copy/write `~/.t3/userdata`; do not run migrate-dev-db. Read actual ports from dev-runner. Do not set VITE_HTTP_URL/VITE_WS_URL. Never publish pairing links, cookies, tokens, profiles, or private app data.
3. Seed through actual app: pair a headed Chromium/Xvfb client using this dev server's startup URL, create a synthetic project pointing at `/tmp/ev-20924/pages`, then a stopped empty thread via app UI. This invokes production project/thread services with no provider turn required. This is the simplest viable route from a fresh DB; no DB transplant needed. RPC alternative uses real project service and `thread.create` command, followed by preview.open/preview.navigate and preview.resize/preview.adjust; payloads must follow this revision's contracts and authenticated RPC transport. Do not invent a WebSocket JSON protocol.
4. Run the public fixture generator into `/tmp/ev-20924/pages`, serve its directory via a separate capturer-owned loopback HTTP server, and navigate the thread's real Browser panel to `/blur.html` or `/plain.html`. This is an external website fixture, not an isolated component harness. The actual server ServerBrowser must own the tab. Use fixed viewport settings and explicit preview colorScheme. ServerBrowserContexts deliberately launches its capture Chromium headless with DPR2; leave this production behavior intact.
5. Obtain PNG through this new dev server's real preview automation snapshot service (the Browser screenshot shown by a separate automation browser is not sufficient). A valid thread-bound MCP invocation can call preview_status/open/navigate/resize/set_appearance/snapshot(save=true); credentials/session must belong to the fresh dev server, not this audit's live environment. Concrete supported MCP route: start a tightly scoped provider turn in that synthetic thread from the paired client, instruct it to capture only these local fixture pages, and let the real provider launch issue its thread-bound MCP registry credential. The child then calls the fresh server preview tools. This is later capturer work, not delegation performed by this audit. An empty stopped thread alone does not issue this credential; a generic OAuth MCP client also lacks the required thread scope (McpInvocationContext.requireThreadMcpCapability). Provider access is therefore a prerequisite for this supported route; if unavailable, mark capture blocked rather than inventing a credential or assuming preview.open RPC provides snapshot RPC. The transport and auth prerequisite must be resolved, not bypassed by directly importing ServerBrowserPage.snapshot. A stale MCP connection to another running server invalidates the evidence.
6. Reference: separate **headed** Chromium on Xvfb, same fixture, browser build, viewport/layout, media, effective DPR/zoom and scroll. Take an unscaled native capture (no CDP clip.scale<1), then if needed normalize offline to the returned snapshot dimensions. Preserve original reference PNG and normalization command. Compare the actual backdrop blur over stripe edges, not just the three coarse RGB samples. Server browser being headless and reference being headed is intentional. Record Xvfb size/depth and versions.
7. Save manifest containing revision SHA, fixture script URL+hash, page hash, server command/ports with credentials redacted, snapshot route, dimensions, media, scroll, zoom, DPR, and reference command. Upload PNGs and videos with ghdrop. Label BEFORE / AFTER / REFERENCE. No visual claim is approved until reviewed.

If step 5 cannot create valid fresh app automation scope, report integration capture blocked; helper-level tests or a standalone Playwright call to ServerBrowserPage are not substitutes. If headed Xvfb/Chromium is unavailable, record the reference gap. N1 is explicitly not captured by this setup. No screenshots or recordings produced in pass1.

## Test status and later independent audit

Tests/main red is confirmed input to this pass and remains outstanding, **not superseded** by the matrix, new tests, or an eventual visual pass. Auditor did not rerun tests and makes no claim about which checks or failures were observed. Preserve exact failure logs from the owner separately. This pass does not grant merge readiness.

Pass2 must be a new delegated audit. Rebuild one chosen row from the publicly uploaded external fixture script, independently verify script hash and resulting page, and follow the actual dev-server route. Scratch scripts stay under /tmp, never committed even if another brief requests a committed reproducer.

## FRICTION

| category | event | prevention |
|---|---|---|
| Scope | Four server files can be mistaken for a desktop UI change | Classify from changed paths; N1 remains a conditional server path, no inferred desktop claim |
| Coverage | 390 does not enter the new shrink path; 640 is exact threshold | Retain 390 as control and 640/641 boundary, explicitly mark affected rows |
| Proof | RGB probes detect gross mirroring but not actual blur | Compare detailed stripe edges to headed reference and preserve full images |
| Integration | Existing live MCP could silently capture a different server | Bind fresh project/thread and credentials to logged dev ports and revision |
| State | Default dev seeding could access real userdata | Explicit home, --no-seed and T3CODE_DEV_SEED=0; never migrate/copy live state |
| Timing | Static PNG cannot prove recording seed or viewer recovery | C3/C4 and interaction A7 require recordings |
| Reproducibility | Committed scratch script conflicts with user instruction | Publish synthetic generator from /tmp via ghdrop; record hash; pass2 rebuilds independently |
| Validation | Visual evidence might be treated as clearing red tests | Carry tests/main red forward as unresolved, with original logs retained separately |

Public synthetic generator: [fixture-20924.py](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/49cbb14fa7a8aab3/fixture-20924.py). SHA-256 `1abdeee1085e1e3bd5b5280b756bb2f67d9e370410bb374442c36cb86c4eb82d`. Generator does not launch anything. Auditor did not execute it.
