fix(agent): stop silent black X11 capture fallback on Wayland (VA-80) #84

Merged
David merged 1 commit from fix/VA-80-wayland-capture into main 2026-06-29 03:53:19 +02:00
Owner

What

VA-80 root cause: on a Wayland session the agent's capture paths tried the Wayland backend and, on NotAvailable, silently fell back to X11 root capture. Under XWayland the X11 root has no composited content, so it returns all-black frames - the remote desktop rendered solid black with no error (the browser was correctly decoding/blitting black tiles, confirmed via a canvas pixel probe).

This PR (capture-behaviour half of VA-80)

Refuse the X11 fallback on a Wayland session and surface the real reason instead, via a shared wayland::unavailable_no_x11_fallback helper, at all three sites: stream::capture_raw_frame, capture::capture_primary, capture::capture_display. The error names the fix (build with the wayland-portal feature + grant the screencast portal). X11 sessions are unaffected (the fallback only applied under is_wayland_session()).

Turns the silent black screen into a clear, actionable error (NEVER HIDE ERRORS).

Held for a decision (not in this PR)

Enabling the wayland-portal capture path in the released build is the half that actually makes Wayland capture work. It is held because it makes the universal agent binary hard-link libpipewire-0.3 (the pipewire crate is a -sys binding; the release Dockerfile exports a scratch image with only the binary, which then needs libpipewire-0.3.so.0 + libspa-0.2 at runtime). That would break the agent on headless hosts lacking PipeWire (the binary won't exec), even for terminal/files/MCP. The build approach is a deployment decision tracked on VA-80.

Testing

just pre-commit green (Docker; default build without the feature, which is the config these call sites must compile under).

Part of VA-80.

🤖 Generated with Claude Code

## What VA-80 root cause: on a Wayland session the agent's capture paths tried the Wayland backend and, on `NotAvailable`, silently fell back to X11 root capture. Under XWayland the X11 root has no composited content, so it returns all-black frames - the remote desktop rendered solid black with no error (the browser was correctly decoding/blitting black tiles, confirmed via a canvas pixel probe). ## This PR (capture-behaviour half of VA-80) Refuse the X11 fallback on a Wayland session and surface the real reason instead, via a shared `wayland::unavailable_no_x11_fallback` helper, at all three sites: `stream::capture_raw_frame`, `capture::capture_primary`, `capture::capture_display`. The error names the fix (build with the `wayland-portal` feature + grant the screencast portal). X11 sessions are unaffected (the fallback only applied under `is_wayland_session()`). Turns the silent black screen into a clear, actionable error (NEVER HIDE ERRORS). ## Held for a decision (not in this PR) Enabling the `wayland-portal` capture path in the released build is the half that actually makes Wayland capture work. It is held because it makes the **universal agent binary hard-link `libpipewire-0.3`** (the `pipewire` crate is a -sys binding; the release Dockerfile exports a scratch image with only the binary, which then needs `libpipewire-0.3.so.0` + `libspa-0.2` at runtime). That would break the agent on headless hosts lacking PipeWire (the binary won't exec), even for terminal/files/MCP. The build approach is a deployment decision tracked on VA-80. ## Testing `just pre-commit` green (Docker; default build without the feature, which is the config these call sites must compile under). Part of VA-80. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(agent): stop silent black X11 capture fallback on Wayland
All checks were successful
Check / fmt + clippy + tests (pull_request) Successful in 16m14s
Create release / Create release from merged PR (pull_request) Has been skipped
2a7e436986
On a Wayland session the screen-capture paths (stream::capture_raw_frame, capture::capture_primary, capture::capture_display) tried the Wayland backend and, on NotAvailable, silently fell back to X11 root capture. Under XWayland the X11 root has no composited content, so that fallback returns all-black frames: the remote desktop rendered solid black with no error (the browser was decoding and blitting black tiles correctly). This is the VA-80 root cause on a GNOME/Wayland host.

Refuse the X11 fallback on a Wayland session and surface the real reason via a shared wayland::unavailable_no_x11_fallback helper, pointing at the fix (build with the wayland-portal feature + grant the screencast portal). X11 sessions are unaffected (the fallback only applied when is_wayland_session()). This turns the silent black screen into a clear, actionable error (NEVER HIDE ERRORS).

This is the capture-behaviour half of VA-80. Enabling the wayland-portal capture path in the released build is held separately because it makes the universal agent binary hard-link libpipewire (a runtime dependency that would break headless hosts), which is a deployment decision to settle first.

#VA-80
David scheduled this pull request to auto merge when all checks succeed 2026-06-29 03:38:51 +02:00
David merged commit 041492af01 into main 2026-06-29 03:53:19 +02:00
David deleted branch fix/VA-80-wayland-capture 2026-06-29 03:53:19 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/vervain-agent!84
No description provided.