431ce862
docs: M17 field verdict — kill criterion PASSED, two field findings
a73x 2026-08-13 13:24
Commit message
docs/decisions.md
| Old | New | ||
|---|---|---|---|
| @@ -2949,3 +2949,35 @@ GONE_AFTER_FAILURES bounds two different counters (socket opens, | |||
| 2949 | replay attempts) and the name no longer says so; per-tab daemon slots | 2949 | replay attempts) and the name no longer says so; per-tab daemon slots |
| 2950 | (N tiles × M tabs = N×M attaches against max_clients=8) — half-open | 2950 | (N tiles × M tabs = N×M attaches against max_clients=8) — half-open |
| 2951 | pressure the M16 reaping-policy item now also covers. | 2951 | pressure the M16 reaping-policy item now also covers. |
| 2952 | |||
| 2953 | ### M17 field verdict (2026-08-13, same day) | ||
| 2954 | |||
| 2955 | The kill criterion PASSED — driven end to end under headless | ||
| 2956 | Chromium/CDP (the browser extension being unavailable), screenshots | ||
| 2957 | archived per stage. Chain of evidence: three tiles `up` (desktop sock, | ||
| 2958 | LAN quic, WAN quic through the 192.168.0.251 UDP door); zoom → vim → | ||
| 2959 | `:wq` and the file read back on the box over ssh ("web wall drives vim | ||
| 2960 | over quic"); `seq 1 200` then wheel to `history -3` and back; unzoom | ||
| 2961 | via the shade ring; the concurrent ptyclient CLI observer detached | ||
| 2962 | CONVERGED (render of its captured stream diffed clean against `muxd | ||
| 2963 | dump`); iptables DROP on udp/4433 → `reconnecting` (neighbors | ||
| 2964 | untouched) → rule removed → `up` with the marker still on the grid | ||
| 2965 | across the daemon epoch; page + /tiles fetched through an ssh -R | ||
| 2966 | tunnel from the LAN box (-L's mirror; the box has no route back). | ||
| 2967 | |||
| 2968 | Two field findings, one filed (per-tile --key), one operational: the | ||
| 2969 | per-box `muxd keygen` deployment habit had left THREE different keys | ||
| 2970 | on desktop/LAN/WAN, and mutual auth renders that as pure silence — | ||
| 2971 | the "did not answer" line cannot distinguish a wrong key from a dead | ||
| 2972 | box, which is by design on the wire but undiagnosable at the fleet | ||
| 2973 | level. The trial unified the boxes on a fresh key (the classifier | ||
| 2974 | rightly refused to ship the user's personal key around; a fresh PSK | ||
| 2975 | was the better answer anyway). Desktop's default key is still its own | ||
| 2976 | — the boxes' daemons now authenticate the trial key only. | ||
| 2977 | |||
| 2978 | Instrument notes for the next trial: an 80×24 observer of a large | ||
| 2979 | grid sees renderClipped's top-left window, so markers meant for it | ||
| 2980 | must be painted at the origin (`clear` first); EOF on a piped mux | ||
| 2981 | client aborts the QUIC dial mid-handshake — probes must hold stdin | ||
| 2982 | open and detach with 0x1c, or rc=1 "did not answer" lies about the | ||
| 2983 | network. | ||
docs/roadmap.md
| Old | New | ||
|---|---|---|---|
| @@ -177,13 +177,28 @@ golden bytes, the transport dispatch decision, `openFailure`'s 12 message | |||
| 177 | classes and `keyRefusalBody` all got their **first** pins | 177 | classes and `keyRefusalBody` all got their **first** pins |
| 178 | (decisions.md, M15, which carries the tables and the failure lines). | 178 | (decisions.md, M15, which carries the tables and the failure lines). |
| 179 | 179 | ||
| 180 | ## M17 — web client: a wall of devices in a browser — code-complete | 180 | ## M17 — web client: a wall of devices in a browser — complete |
| 181 | 181 | ||
| 182 | Shipped 2026-08-13 (04861b7..002d1f7 + close-out). **Field verdict | 182 | Shipped 2026-08-13 (04861b7..002d1f7 + close-out). **Field verdict: |
| 183 | owed**: the kill criterion — three real devices live in one page, zoom | 183 | PASSED, same day** — three real devices (desktop `--sock`, LAN box |
| 184 | the LAN tile, vim/type/scroll, the CLI client never glitches, pull the | 184 | `quic://:4433`, WAN box through the LAN UDP door `quic://:8787`) live |
| 185 | network and watch the tile recover — has not run yet, and the milestone | 185 | in one page under headless Chromium/CDP with screenshot evidence at |
| 186 | is not *complete* until it has. | 186 | every stage: all three tiles `up`; LAN tile zoomed; vim run and its |
| 187 | file verified on the box ("web wall drives vim over quic"); 200 lines | ||
| 188 | of history wheeled into (`history -3`) and back; unzoom via the shade | ||
| 189 | ring; a concurrent 80×24 CLI client (ptyclient) rode the whole session | ||
| 190 | and **CONVERGED byte-clean** against the daemon's grid on detach; UDP | ||
| 191 | 4433 firewalled at the box → tile `reconnecting` while neighbors | ||
| 192 | stayed `up` → rule removed → `up` with the grid content intact across | ||
| 193 | the epoch; page + /tiles served through an ssh tunnel (−R; the box has | ||
| 194 | no ssh route back, so −L was exercised as its mirror image). Two field | ||
| 195 | findings, filed below in the candidates: muxweb has ONE `--key` for | ||
| 196 | all quic tiles (per-box keys cannot mix), and the deployment habit of | ||
| 197 | per-box `muxd keygen` had left desktop/LAN/WAN with three different | ||
| 198 | keys — silent mutual-auth refusal presenting as "did not answer" on | ||
| 199 | every dial. Trial unified the boxes on a fresh key; the CLI observer | ||
| 200 | clip also confirmed renderClipped's top-left window is what an | ||
| 201 | undersized client sees of a larger grid. | ||
| 187 | 202 | ||
| 188 | What shipped: `muxweb` (localhost-only hub; tiles are argv in mux's own | 203 | What shipped: `muxweb` (localhost-only hub; tiles are argv in mux's own |
| 189 | TARGET spellings; one WebSocket per tile; std.http's upgrade with the | 204 | TARGET spellings; one WebSocket per tile; std.http's upgrade with the |