fix(server): preview snapshots preserve blurred backdrops#24618

merged5
main
takeover/pr-20924
opened19d agobyJJulius Marminge
View on GitHubTwo-way sync enabledPR last imported 18d ago

Preview snapshots capture at full scale and resize the finished PNG, so blurred backdrops show the page as rendered. Fixes #20899.

Other visible effects: at 125% zoom the PNG is now capped at 1280×711 instead of 1600×889, and the old black padding disappears. Wide plain pages preserve their content and layout with text/edge resampling differences. Narrow controls are byte-identical.

Takeover

Rebuilt from @watashiwaaniket’s #20924, which identified Chromium’s scaled-capture defect and the full-capture/canvas-resize approach. The resize runs in the tab’s isolated world instead of opening a scratch page and threading a callback through snapshot inputs. HTML-namespaced canvas creation preserves XML-page snapshots. Replaced the wiring tests with real Chromium tests for blurred, plain, and XML documents. No new dependency or wire change.

Evidence

Supplemental N1 and RM: extended matrix, capture index, and complete reproduction bundle. Supplemental before is merge-base 8bcef34f; after remains b7fddd87.

Linux Xvfb, Electron 44.9.3 / Chromium 152.0.7977.167, genuine Electron webview attached through DesktopBrowserChannel; actual server preview_snapshot outputs. N1 uses 1440×800, scroll 600, zoom 1/DPR 2 and zoom 1.25/DPR 2.5. RM uses real CDP reduced-motion emulation with a running-animation positive control, then stable reduced-motion snapshots. All returned PNGs are 1280×711 and byte-identical to repeats 500 ms later. Independent headed references, two diffs per pair, debugger/attachment/media provenance, ffmpeg X11 recordings and scripts are in the index. Reference resampling leaves edge/text differences; viewer timing is approximate.

Supplemental rowBeforeAfterComparison and two diffs per pair
N1 · native attachment · 100%Before N1 at 100%After N1 at 100%Reference and diffs
N1 · native attachment · 125%Before N1 at 125%After N1 at 125%Reference and diffs
RM · reduced-motion animation fixtureBefore RMAfter RMReference and diffs

Independent supplemental proof audit: SUFFICIENT for N1 and RM. All 18 diff images independently recomputed; public fixtures rebuilt byte-for-byte; a fresh actual-server N1 reproduction at 125% passed. Reproduction evidence. Supplemental capture and both proof audits: GPT-6.1 Sol through Codex/T3 delegation.

Fixture matrix, full evidence index, and reproduction bundle contain the headed references, raw images, metrics, fixture/driver scripts, hashes, and nonsecret service traces. All scripts remain external to the PR.

Actual before: c4fa4629. Actual after: b7fddd87, including main by merge commit. Preview source is identical between the captured baseline and current main 8bcef34f.

Chromium 156.0.8078.70: actual headless server snapshot service at DPR 2 versus a matching headed Chromium reference under Xvfb. Height 800 CSS px, root font 16 px; actual dimensions and zoom metrics are in the index. Every static capture matched a second capture 500 ms later. Threshold-0 RGB differences are amplified ×4; threshold-10 masks mark channel differences >10. A7 comparisons normalize the baseline’s 1600×889 image to 1280×711; raw images remain linked in the index.

Identical interaction script: start recording, scroll to 600, snapshot, zoom to 125%, snapshot, reset zoom, scroll to 0, snapshot, reload/reconnect, stop. Before timestamps; after timestamps. Both revisions show an enlarged page after Reset zoom and a blank reload interval before viewer recovery; these are existing observations, not claimed fixes.

RecordingBeforeAfter
Immediate start/stop: usable first framebefore-C3.mp4after-C3.mp4
Scroll/zoom/snapshot during recordingbefore-A7-C4.mp4after-A7-C4.mp4
Real Browser viewer and reconnectbefore-C4-viewer.mp4after-C4-viewer.mp4

12/12 required rows captured, 13 scenarios including the 640/641 boundary. XML X1 extends the original matrix and succeeds before and after.

Verification log
  • Tests: ServerBrowserPage.test.ts 16→19; ServerBrowser.test.ts 27 unchanged. Final merged head: 46/46 pass. Blur regression fails on baseline; XML regression failed on the intermediate implementation and passes after the namespace fix.
  • Scoped lint/format and server typecheck passed. No repository-wide checks run.
  • Review round 1: A found missing evidence; B found the XML canvas regression. Fixed with namespaced canvas and one regression test. Round 2: both GPT-6.1 Sol and Claude Opus 5.5 returned MERGE; no remaining concrete findings..
  • Independent proof audit: SUFFICIENT: independently rebuilt A1 through a fresh app server and thread-bound MCP; 0/910,080 pixels differ. All 78 diff images independently recomputed..
  • CI: Initial publication read: 11 successful, 16 pending, 0 failing; dispatcher owns monitoring and landing.. No merge performed.
  • Unverified rows: none of N1/RM remain. Evidence covers Linux Xvfb native attachment and reduced-motion media set through the attached guest’s existing CDP debugger; no public reduced-motion configuration API or separate headless-server reduced-motion run is claimed. Physical-monitor and other platform behavior were not tested. All changed files remain server paths.
  • Complexity: base64 conversion O(encoded bytes); raster decode/draw O(pixels). A 3,000-token malformed input rejected in 1.1–2.7 ms; invalid PNG bytes rejected in 3.5–5.1 ms (Chromium 148). Resize measured 85–130 ms at 1280×800/DPR2 and 380–520 ms at 3840×2160/DPR2..
  • Takeover friction log; baseline and scoped-test verification.
  • Models/harnesses: GPT-6.1 Sol via Codex and Claude Opus 5.5 through T3 delegation. Integrated evidence transport used a fresh GPT-6 Astra/Codex provider turn; original author credited above.

Checks

22 successful · 16 skipped
All checks passed
b7fddd8

Added 5 commits

  • chore(server): remove outdated scaled capture comment097dc0d
  • Merge remote-tracking branch 'origin/main' into takeover/pr-20924b7fddd8
  • test(server): takeover tests for #20924 backdrop-filter snapshotscc41db2
  • fix(server): snapshots of XML documents shrink their screenshot againf8587a5
  • fix(server): snapshots of backdrop-filter pages show the page as renderedfbed625
Synced from GitHub

Approvability

Verdict: Approved at b7fddd8

Macroscope's review found this PR approvable — This is a focused server preview fix that captures full-resolution PNGs and downsamples them in-page to avoid Chromium's backdrop-filter mirroring, with regression coverage for blurred, plain, and XML pages. Recording and live still JPEG paths retain full-scale behavior, with no schema, dependency, or configuration changes.

You can add or adjust custom eligibility rules. Learn more.

Synced from GitHub

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire5.0 KiB5.0 KiB−7 B (−0.1%)6.8 KiB✅
CodexThread snapshot wire3.8 KiB3.8 KiB0 B (0.0%)4.9 KiB✅
CodexLive turn WebSocket wire1.2 KiB1.2 KiB−7 B (−0.6%)2.0 KiB✅
CodexLive turn WebSocket decoded20.9 KiB20.9 KiB0 B (0.0%)29.3 KiB✅
CodexLive turn messages220 (0.0%)8✅
ClaudeTotal thread wire5.0 KiB5.0 KiB+7 B (+0.1%)6.8 KiB✅
ClaudeThread snapshot wire3.8 KiB3.8 KiB0 B (0.0%)4.9 KiB✅
ClaudeLive turn WebSocket wire1.2 KiB1.2 KiB+7 B (+0.6%)2.0 KiB✅
ClaudeLive turn WebSocket decoded21.2 KiB21.2 KiB0 B (0.0%)29.3 KiB✅
ClaudeLive turn messages220 (0.0%)8✅

Baseline: 97548db · PR result: b7fddd8 · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

Synced from GitHub

Review in Change Stack →

No actionable comments were generated in the recent review.

External image Recent review info
External image Run configuration
External image Commits

Reviewing files that changed from the base of the PR and between 97548db62dd68a1859dd15fabb957e3ae746f65f and b7fddd87a69bb9f868bfd54928aaf4ae881c9432.

External image Files selected for processing: 4
  • apps/server/src/preview/ServerBrowser.test.ts
  • apps/server/src/preview/ServerBrowser.ts
  • apps/server/src/preview/ServerBrowserPage.test.ts
  • apps/server/src/preview/ServerBrowserPage.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 1 remain after this review.

Walkthrough

Viewport screenshots now capture the full viewport before resizing the PNG when needed. Recording and viewer still-frame capture use the simplified capture API. New tests cover blurred backdrops, plain pages, and XML documents.

Changes: Screenshot capture

Layer / File(s)Summary
Full-viewport capture and PNG resizing
apps/server/src/preview/ServerBrowserPage.ts, apps/server/src/preview/ServerBrowserPage.test.ts
Capture no longer uses scaled clips or page offsets. When the calculated scale is below one, the captured PNG is resized in an isolated world. Tests check image dimensions and sampled colors.
Recording and viewer capture callers
apps/server/src/preview/ServerBrowser.ts, apps/server/src/preview/ServerBrowser.test.ts
Recording initialization and viewer still-frame capture use the simplified capture API. The test session mock handles the Runtime.callFunctionOn response.

Priority: External image Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix · Severity of issue fixed: Medium

Possibly related PRs

  • pingdotgg/t3code#24523: Adds locking and deadlines to preview capture paths that call ServerBrowserPage.captureViewport.

Suggested labels: bugfix, size:M

Suggested reviewers: scottn-pv

Merge Risk: External image Minimal · up to b7fdd

No actionable merge-blocking issue is established for the snapshot change; merge after normal checks.

Pre-merge checks: Passed 3 · Failed 1

Failed Failed checks: 1 warning

Check nameStatusExplanationResolution
Description checkWarningThe description provides detailed problem context, implementation changes, evidence, verification results, limitations, and agent attribution. However, it omits the required Problem, Change, Scope and…Restructure the description using all required template headings. Under Scope and approval, link the triaged issue or approved discussion and include the specific maintainer approval comment, or explain why this focused fix qualifies for an…
Passed Passed checks: 3 passed
Check nameStatusExplanation
Title checkPassedThe title clearly and concisely identifies the main change: preserving blurred backdrops in server preview snapshots.
Linked Issues checkPassedIssue #20899 requires correct preview_snapshot rendering for blurred backdrops at desktop width in apps/server. The reviewed change captures the full viewport without a scaled clip, then resizes o…
Out of Scope Changes checkPassedThe changed files remain in the server preview capture path and its tests. The ServerBrowser call-site updates adapt recording and viewer capture to the new capture API. These changes support the ca…
Full details: Linked Issues check

Explanation

Issue #20899 requires correct preview_snapshot rendering for blurred backdrops at desktop width in apps/server. The reviewed change captures the full viewport without a scaled clip, then resizes oversized PNG output in the tab isolated world. The added Chromium test covers a 1280×800 backdrop-filter page and verifies blue-left/red-right pixels instead of mirrored content. The added plain-page and XML tests cover the related resize paths. The PR evidence reports the required desktop fixture matrix and passing final tests.

Full details: Out of Scope Changes check

Explanation

The changed files remain in the server preview capture path and its tests. The ServerBrowser call-site updates adapt recording and viewer capture to the new capture API. These changes support the capture implementation and do not establish unrelated behavior changes, dependencies, or wire changes.

Full details: Description check

Explanation

The description provides detailed problem context, implementation changes, evidence, verification results, limitations, and agent attribution. However, it omits the required Problem, Change, Scope and approval, and Verification headings. It also does not include explicit maintainer approval for the direction and scope; model review results do not satisfy that requirement.

Resolution

Restructure the description using all required template headings. Under Scope and approval, link the triaged issue or approved discussion and include the specific maintainer approval comment, or explain why this focused fix qualifies for an exemption. Keep the existing verification details under Verification and state any checks that were not run.

Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.