writeonce/docs/plan/exploration/zen-browser/00-zen-browser-parity.md
shoney.arickathil 8bcd24969e docs(lang42): story, spec and plan for bounded subprocess
- claim the lang42 prefix; iteration 42 story (readiness: ready), approved
  spec, and the 11-task implementation plan
- board: pending row for 42; graph: node 42 with green edges (11, 24)
- graph: porch track section added (same sweep)
- parity studies that motivated 42: alacritty, tmux, zen-browser under
  docs/plan/exploration/ — staged path, gap lists, refused routes

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-01 22:19:25 +02:00

86 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Zen Browser parity — what a browser-class application actually asks of a language
Source: [`.dev/reference/zen-browser/`](../../../../.dev/reference/zen-browser/)
(shallow clone of zen-browser/desktop, surveyed 2026-09-01). Third study in the
series after [`alacritty`](../alacritty/00-alacritty-parity.md) and
[`tmux`](../tmux/00-tmux-parity.md) — and the one whose answer is different in
kind, which is why it is worth having.
## What Zen actually is (measured)
Zen is not a browser codebase. It is a **Firefox overlay**: `surfer.json` pins
`product: firefox, version: 154.0.1`, `npm run download` fetches the Firefox
source into `engine/` at build time, and the repo contributes **256 patch
files** plus a 33 MB `src/` tree that is copied over it — ~246,000 lines
counting JS/MJS/CSS/XHTML/patches (616 `.js` files, 568 Fluent localization
files, 48 CSS). There is no rendering, layout, JS-engine, or networking code
in the repository at all; Gecko (tens of millions of lines of C++/Rust)
arrives as a downloaded dependency and is built with Mozilla's own `mach`.
Zen's value-add lives in `src/zen/`: workspaces ("spaces"), split view,
compact mode, glance, folders, session store, sync — all UI composition and
state, written in JavaScript **because the engine ships a JavaScript host and
Zen's code runs inside it**. The engine is also the app platform.
## The lesson, stated plainly
Nobody — including a successful, well-staffed browser project — writes a
browser. They skin an engine. So "mature the language until it can build an
application such as this" resolves to three different questions, and only one
of them is real work for writeonce:
1. **Build the engine in `.wo`?** Not a maturity path, a decades-long refusal.
The gap list it produces ("general FFI, C++ interop, a GPU pipeline, a JS
VM…") is the alacritty study's stage-E fork multiplied by a thousand, with
no intermediate shippable stage. Rejected as a driving workload — it cannot
drive, only sink.
2. **Embed an engine (CEF/WebKitGTK) behind FFI?** The heaviest possible FFI
consumer. Same fork as alacritty item 7, and this study deliberately does
not promote it: an embedded engine's API surface is enormous and unstable,
the worst first FFI customer imaginable.
3. **Drive an engine out-of-process.** Chromium and Firefox both expose a
remote-debugging protocol (CDP; Firefox now speaks it too) over a local
socket or a stdio pipe. A writeonce program that spawns a browser, connects,
and drives it — kiosk shells, scrapers, site-acceptance drivers of the kind
`site-accept.sh` fakes with curl today — is the browser-class workload that
is actually reachable, and it is exactly the actor/protocol shape the
runtime is built around. This is Playwright's architecture, minus the
Node.js.
## What route 3 needs — mostly the existing list, one genuinely new gap
- **Bounded subprocess with stdio transport** — spawning the browser with a
pipe transport is the third consumer of iteration 28's named gap (after the
alacritty and tmux studies' PTY stages; this one does not even need a PTY).
- **`net.connect`** — iteration 38, already named, for the debugging socket.
- **NEW — WebSocket CLIENT.** CDP speaks WebSocket; iteration 24 landed the
server side (`ws_accept`, frames) but nothing performs an outbound upgrade
handshake. Small — the frame code is the hard half and already exists.
- **JSON both ways** — exists. Actor-per-session/per-tab supervision, timeouts
(`time.after`), graceful teardown — all landed in iteration 24.
Notably absent: nothing graphical, no terminfo, no termios, no fd passing.
Route 3 is *closer* than the tmux stage.
## What Zen's own feature layer says about writeonce
Zen's ~250k-line overlay is session stores, workspace state, sync, and
declarative UI — in writeonce terms: `@table` rows (durable by declaration
since databasev2 2), and wo-html components. The project's existing bet —
that the browser is the *client* and the application lives server-side in
porch — already covers the useful half of what Zen builds. The other half of
Zen's lesson is about hosting: Gecko wins as a platform because it embeds a
scripting language with capability boundaries, which is iteration 28's
skillhost direction (writeonce as the confined host, not the confined guest).
## Verdict for the maturity path
The browser study adds **one builtin-sized gap** (WebSocket client) and
**one workload** to the staged path from the alacritty study — call it
**stage C′, the browser driver**, parallel to stage C (it needs subprocess +
`net.connect` + ws-client, none of stage C's tty machinery). Proof when it
lands: replace a curl leg of `site-accept.sh` with a `.wo` driver that opens
writeonce.de in a real browser, asserts the rendered chapter list, and tears
the browser down cleanly — the site gate exercising the language's own
browser-automation story end to end. Engine-building and engine-embedding
stay refused, by name, with this study as the reason.