a73x

d7159783

docs: roadmap banner + the home-screen section; handoff marked historical

a73x   2026-08-20 08:28

Commit message
docs: roadmap banner + the home-screen section; handoff marked historical

The roadmap's header said M1-M15 and M17 complete, tagged v0.0.1-5, in a
file whose own body has an M18 section and whose tags run to v0.0.1-10.
It is also six shipped bodies of work behind: the runtime wall, the
wheel, and the three phases that made `mux` a wall of one tile. The
ranking has not moved since 2026-08-16 and the tracker is the live
order, so the file now says that at the top rather than implying
otherwise for 595 lines.

One new completed section covers 2026-08-18..20 (f9e45eb..180db14): zoom
is a lens rather than a spawn, the wall file is attach history written
on the first state, the wheel belongs to the view, and the two rules the
convergence had to invent about a session ending under a zoom.

Banked item 8's premise was obsolete: it argued that connections-per-host
does not matter "on a four-tile wall", and the wall is now unbounded
attach history. The conclusion may well survive; the argument does not,
so the item now asks for a measurement instead of asserting one.

handoff.md gets a banner and nothing else. It is the design as written
before any code, and what it got wrong — everything it put out of scope
shipped anyway — is exactly the record worth keeping unedited.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

docs/handoff.md
Old New
@@ -1,8 +1,14 @@
1 # Handoff: Linux-only multiplexer prototype 1 # Handoff: Linux-only multiplexer prototype
2 2
3 **Status:** design handoff, no code written yet 3 **Status:** HISTORICAL — the design handoff as written, before any code.
4 **Audience:** whoever picks up implementation 4 Kept unedited on purpose: what it got wrong is the record. M1–M5 below all
5 **Scope:** Linux only. No macOS, no iOS, no web, no network. 5 cleared; everything it declares out of scope (network, auth, TLS,
6 prediction, web) shipped anyway, and where it guessed (GPU/GTK rendering,
7 msgpack, `$XDG_RUNTIME_DIR/muxd.sock`, systemd socket activation) the built
8 thing differs. For what mux is now: `README.md`. For how each of those calls
9 was actually made and measured: `docs/decisions.md`.
10 **Audience:** whoever wants the original reasoning.
11 **Scope (as stated then):** Linux only. No macOS, no iOS, no web, no network.
6 12
7 --- 13 ---
8 14
docs/roadmap.md
Old New
@@ -1,12 +1,16 @@
1 # Roadmap 1 # Roadmap
2 2
3 > This file is the ranked queue as of 2026-08-16 and has not moved since;
4 > the tracker is the live order and `decisions.md` is current. Sections
5 > below marked complete are accurate; the ranking is not.
6
3 The forward view, one item per line, ranked. History and evidence live in 7 The forward view, one item per line, ranked. History and evidence live in
4 `decisions.md` — every item here points back at its entry there. Update 8 `decisions.md` — every item here points back at its entry there. Update
5 this file at each milestone close and whenever the queue reorders; the 9 this file at each milestone close and whenever the queue reorders; the
6 queue's order is set by the user, not by this file. 10 queue's order is set by the user, not by this file.
7 11
8 **Now:** M1–M15 and M17 complete, plus the agent surface; published as a 12 **Now:** M1–M18 complete, plus the agent surface and the wall; published as
9 Linux tarball, tagged through `v0.0.1-5`; in 13 a Linux tarball, tagged through `v0.0.1-10`; in
10 field trial on real VMs, and the trial is now producing the queue. 14 field trial on real VMs, and the trial is now producing the queue.
11 Trial feedback outranks everything below — what actually hurts in use is 15 Trial feedback outranks everything below — what actually hurts in use is
12 better data than any of this ranking, and the proof is that the three 16 better data than any of this ranking, and the proof is that the three
@@ -404,6 +408,56 @@ that understood the name can produce.
404 the M18 block drives it by name and asserts it returns one session's 408 the M18 block drives it by name and asserts it returns one session's
405 grid and not its neighbour's. `--diff-since` is still owed. 409 grid and not its neighbour's. `--diff-since` is still owed.
406 410
411 ## The wall is the home screen — complete
412
413 Shipped 2026-08-18..20 (the runtime wall, the wheel, then `f9e45eb..180db14`).
414 `mux [TARGET]` is now a wall of one tile entered zoomed, and `mux wall` is
415 the same program entered on the wall. There is **one interaction loop in the
416 tree, and it is a tile pump** — `client.zig`'s session loop is gone.
417
418 **Zoom is a lens, not a spawn.** An unzoomed tile claims nothing; zooming
419 resizes that tile's existing connection from 0×0 to the terminal and starts
420 forwarding keystrokes down it, so the client that types is a full-size one
421 claiming under latest-wins like any other. Nothing is dialled, no frame was
422 added, and `server.zig` did not change by one line. Demote is client-local
423 and sends nothing: a 0×0 "relinquish" would be refused by `applySize`
424 anyway, and a tile that is never active again claims nothing under
425 latest-wins. Moving the zoom is therefore a repaint, not a reconnect — every
426 tile's pump keeps running, so every replica is hot and `Ctrl-\` `n`/`p`/`l`
427 land instantly.
428
429 **The wall file became attach history.** Any attach that claims the grid
430 records its own tile, and the seam is inside the pump rather than in
431 `mux_main` — the chord switches re-dial without ever returning to `main`, so
432 a seam up there would have recorded the session you started at and none of
433 the ones you visited. It fires on the first STATE, not on a successful dial:
434 a dial that comes up can still be refused, and a refusal that had already
435 written its line would strand a tile naming a session that never existed.
436 That is why nothing ever needs to un-record. `muxa` and `--via` record
437 nothing; `mux wall`'s argv is a view, not an attach; `muxweb`'s argv ADDS
438 rather than replaces, because the file stopped being "the last wall muxweb
439 was told to show" the moment attaches started writing to it. Forgetting
440 stays explicit: the page's `×`, the wall's `x`, `mux wall rm`.
441
442 **The wheel, and who owns the mouse.** Spinning the wheel used to walk the
443 shell's history, because nothing in mux read the wheel at all: a terminal
444 asked for no mouse reporting answers a notch on the alternate screen by
445 synthesising arrow keys (DEC 1007), and those went to the pty as input. The
446 client now asks for real wheel events (1000 in 1006) and spends them on the
447 scrollback it already had — asking is also what stops the synthesis, so one
448 change removes symptom and cause. An application that wants the mouse still
449 gets every byte of it.
450
451 **What the convergence had to invent.** A session that ends under the zoom
452 ends `mux` with the shell's exit code when it was the wall's only tile — `mux`
453 is what people put in scripts — and drops to the wall when it was not,
454 landing on `[exited]` beside the survivors. `w` unzooms and `d` detaches and
455 leaves; they were the same key while the zoom was still a child-spawn's
456 replacement, and are not any more. `Transport.adopt` carries the dialled
457 connection from the main thread to the pump, legal only while the out-queue
458 is empty — the one moment between `open` and the first frame, asserted
459 because there is no other.
460
407 ## Side-channel passthrough — complete 461 ## Side-channel passthrough — complete
408 462
409 Shipped 2026-08-16. The three discovery issues are now accounted for: 463 Shipped 2026-08-16. The three discovery issues are now accounted for:
@@ -589,7 +643,10 @@ next one that arrives outranks all of it.
589 multiplexed inside ONE connection, which needs QUIC stream surgery 643 multiplexed inside ONE connection, which needs QUIC stream surgery
590 the M18 design deliberately refused (a connection IS a session). 644 the M18 design deliberately refused (a connection IS a session).
591 Worth doing only if the connection count per host ever becomes the 645 Worth doing only if the connection count per host ever becomes the
592 cost, which on a four-tile wall it is not. 646 cost. The wall is now unbounded attach history rather than a fixed
647 handful of tiles, so that count is whatever a user's history grew to —
648 the old "a wall is four tiles, so who cares" argument is dead, and
649 nothing has replaced it with a measurement. Measure before building.
593 9. **Scrollback retention tuning** — policy decided (engine-native 10k 650 9. **Scrollback retention tuning** — policy decided (engine-native 10k
594 ring); making the limit configurable is what remains, and nobody has 651 ring); making the limit configurable is what remains, and nobody has
595 hit the ceiling. 652 hit the ceiling.