browse: runtime handoff() never engages the Xvfb auto-spawn — headed promotion fails on display-less Linux even with Xvfb installed
- Dominant language
- TypeScript
- Stars
- 133k
- Forks
- 19.9k
- Avg merge
- 18h 46m
- Merged PRs (30d)
- 26
Description
Found while root-causing a local failure of browse/test/handoff.test.ts during the v1.78.0.0 ship.
**The gap:** Xvfb auto-spawn runs only at daemon BOOT (server.ts ~:3113, gated on BROWSE_HEADED=1 via shouldSpawnXvfb). The runtime `handoff()` promotion (headless daemon → headed browser mid-session, browser-manager.ts) launches `launchPersistentContext` headed with NO Xvfb decision. On any Linux box with no running X server, `browse handoff` fails with Playwright's "launched a headed browser without having a XServer running" banner — even when the Xvfb binary is installed (verified live: installing xorg-x11-server-Xvfb alone does not help; the tests only pass under `xvfb-run -a`, which is exactly what free-tests.yml:129 does in CI).
**Why it matters beyond tests:** a user on a headless Linux server who runs `browse handoff` (or any skill that promotes to headed for sign-in/CAPTCHA) hits the same hard failure. The pair-agent/tunnel path would render an Xvfb-backed headed browser visible remotely, so auto-spawn on handoff is useful there; for a purely local display-less box, a headed-under-Xvfb window is invisible to the human, so the right behavior may be spawn + a loud "no local display — the window is only viewable via the extension/tunnel" notice, or a clear refusal naming the fix.
**Suggested shape:** reuse the boot path's exact machinery (shouldSpawnXvfb / pickFreeDisplay / spawnXvfb + the xvfbPid/xvfbStartTime ownership-validated cleanup) inside handoff(), plus a test in the existing headed-xvfb family. Needs the small design call above first — deliberately NOT folded into the v1.78.0.0 wave at ship time (the PR was fully reviewed and green; this changes runtime behavior).
Contributor guide
Research direction
Start with browse/test/handoff.test.ts and browser-manager.ts, then compare the boot path in server.ts around ~3113 and the CI setup in free-tests.yml:129. Resolve whether display-less local handoff should spawn Xvfb with a warning or refuse clearly. Done means the chosen behavior is implemented with ownership-validated cleanup and covered by the existing headed-Xvfb test family.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- linux, playwright, typescript
- Domain
- operating-systems, testing, tooling
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100