writeonce/docs/stories/wmux/01-wmux.md
shoney.arickathil ab8ef64cd9 docs(rt2): runtime-v2 track — the runtime beyond sockets
- five stories under docs/stories/runtime-v2/: 1 streaming subprocess
  (42's follow-up; five forks incl. the mailbox-cap collision), 2 PTY,
  3 signals-as-events (signalfd lean), 4 termios adoption, 5 SCM_RIGHTS
  fd passing; 00-story states the arc — the plane learned sockets in
  8/11/35, files in 6, this adds processes/terminals/signals
- build order 1 -> 2 -> 3; 4 and 5 startable alone; all readiness:
  refine, brainstormed on demand
- board: Five tracks; "▸ runtime-v2" pending section; wmux section now
  points at it; graph section 6 nodes carry runtime-v2 numbers + links
- wmux stories re-reference the track; prefix `rt2` claimed
- linkcheck: 0 broken

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit e0451cb4889bb3d03429c0276d03c090269a5ced)
2026-09-15 01:15:30 +02:00

108 lines
5.5 KiB
Markdown
Raw Permalink 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.

---
track: wmux
iteration: "1"
was_language_iteration: "43"
status: pending
readiness: refine
---
# wmux 1 — the terminal multiplexer, writeonce's tmux alternative
> Part of [Story — wmux, the writeonce terminal multiplexer](00-story.md).
> The product the [tmux study](../../plan/exploration/tmux/00-tmux-parity.md)
> scoped and iteration
> [42](../language-runtime-database/42-bounded-subprocess.md) unblocked
> first —
> a terminal multiplexer in pure `.wo`, driving every remaining
> native-workload gap into the open the way log-watcher drove the
> language and chat drove the actors.
>
> **Why this workload.** tmux is ~112k lines of C with two dependencies,
> but its multiplexer kernel is ~27k and a third of the rest is a
> hand-rolled command/format/options DSL that dissolves into writeonce
> language features. Its architecture — one server owning sessions and
> PTYs, thin clients over a unix socket — is the actor tree writeonce
> already has, with the concurrency written down instead of locked. And
> wmux can give the one demo tmux cannot: sessions, layout and
> scrollback in `durable: true` tables, so **reattaching after a server
> restart replays everything from the WAL**.
## The dependency remap (graph section 6 carries the edges)
Iteration 42 (bounded subprocess) is DONE and was the first domino. The
runtime seams now live as the [`runtime-v2/`](../runtime-v2/00-story.md)
track, each brainstormed on demand — the order below is the build order:
1. **[Streaming subprocess](../runtime-v2/01-streaming-subprocess.md)**
(runtime-v2 1) — 42's named follow-up: a long-lived child whose
output arrives as mailbox messages in the owning actor; stdin
transport. The registry/pidfd/cap machinery is already built.
2. **[PTY allocation](../runtime-v2/02-pty.md)** (runtime-v2 2) —
openpty, the child on the slave as its controlling terminal, resize
ioctls. Extends the same `wo_child` slot; `.dev/reference/tmux`
`spawn.c`/`compat/fdforkpty.c` are the reading.
3. **[Signals as events](../runtime-v2/03-signals-as-events.md)**
(runtime-v2 3) — SIGWINCH (and SIGCHLD beyond the pidfd path) as
mailbox messages; the seam iteration 42 deliberately deferred to its
real consumer. This is that consumer.
4. **[termios adoption](../runtime-v2/04-termios.md)** (runtime-v2 4) —
the CLIENT puts its own tty into raw mode and restores it on exit.
Creating terminals is gap 2; adopting one you were given is this.
Startable alone.
5. **[SCM_RIGHTS fd passing](../runtime-v2/05-fd-passing.md)**
(runtime-v2 5) — the client hands its tty fd to the server over the
unix socket; detach/attach is built on it. Startable alone.
6. **VTE grid in pure `.wo`** — the escape parser and cell grid, pinned
by replaying recorded sessions against the reference `input.c`/
`grid.c` behaviour. Needs **unicode width tables** in the stdlib.
This one is wmux's own, not runtime work.
7. **wmux itself** — server (session/window/pane actors, durable
tables), client (thin: raw mode, fd handover, restore), the gate.
Not on the critical path, recorded: `time.mono`'s return (status-line
clock, repaint pacing — v2), and the terminfo fork below.
## Info — the forks (open; why this is `refine`)
- **Terminfo.** Answer "what does the client's terminal speak" by
parsing the compiled terminfo database in pure `.wo` (a documented
binary format — a parser, not a linked library) versus emitting a
fixed xterm-256color profile and refusing exotic terminals by name.
The tmux study leans fixed-first with a named refusal; confirm at
brainstorm.
- **v1 surface.** Sessions + one window each, no split panes (tmux's
`layout.c` is 2,022 lines of split-tree bookkeeping) versus splits in
v1. Lean: no splits — detach/attach + durability IS the product's
proof; splits are v2.
- **Scrollback residency.** Scrollback rows in a `resident: keys` table
(the 120 GB-audit-table machinery, databasev2 2) versus resident with
a row cap. Real fork: scrollback is append-mostly and read-rarely —
keys-resident's exact profile.
- **Command surface.** tmux's 63 `cmd-*.c` + yacc grammar versus wmux
taking commands as... writeonce source? a tiny line protocol? The DSL
third of tmux should dissolve, not be rebuilt — decide what into.
- **Verb shape of the streaming form** (gap 1's own brainstorm): one
`proc.spawn` returning an actor-addressable handle, versus spawn
options on `proc.run_dl`.
## Acceptance sketch (firmed when the last gap lands)
- Given a wmux server with one session running a shell, when the client
detaches and its process is killed, then the shell keeps running and a
NEW client attaches from a different terminal with the screen intact.
- Given a server stopped with SIGTERM and restarted against the same
`WO_DATA`, when a client reattaches, then sessions, layout and
scrollback are replayed from the WAL — the beyond-tmux leg.
- Given SIGTERM with live shells, then every child is gone before exit
(iteration 40 + 42's guarantee, now with PTYs).
- Given a `vttest`/asciinema replay corpus, then the grid matches the
reference implementation's final state (stage B's pin, kept green).
- Gate: `scripts/wmux-accept.sh` + `just wmux`, log to `/tmp/wmux.log`.
## Consumers and siblings
The alacritty study's stages A–C become wmux's gaps 1–6 verbatim; its
stage D (Wayland shm terminal) reuses gaps 5 and 6. The zen study's CDP
driver shares gap 1 only. skillhost (28) consumes gap 1's stdin
transport. Every remaining item in 28's old fan-out except fs-metadata
and FFI-vs-out-of-process now has wmux as its driving workload.