a73x

5e7caf2c

docs: the handoff's policy is a table, and a warm miss pays once

a73x   2026-08-29 15:55

Commit message
docs: the handoff's policy is a table, and a warm miss pays once

The README's "one deadline" sentence was true only of a cold attach; it now
says so of both, which is what the row bought.

CLAUDE.md is untouched: nothing it claims about the handoff became false —
`handoff` keeps its layer and its module list, and no invariant there
described the order the driver used to spell inline.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wi2HnuF1EK8HgViU11YLV

README.md
Old New
@@ -204,7 +204,8 @@ fetches the daemon's QUIC port and key once and the session moves onto
204 QUIC, leaving no ssh process behind; the coordinates are cached under 204 QUIC, leaving no ssh process behind; the coordinates are cached under
205 `~/.cache/mux/hosts/`, so later attaches dial QUIC straight away and skip 205 `~/.cache/mux/hosts/`, so later attaches dial QUIC straight away and skip
206 ssh entirely. Where inbound UDP is blocked, the attach lands over ssh one 206 ssh entirely. Where inbound UDP is blocked, the attach lands over ssh one
207 deadline (~2s) later, saying so in a single line, and the session is the 207 deadline (~2s) later — ONE, whether the coordinates came from the cache or
208 from that same ssh — saying so in a single line, and the session is the
208 same session either way. HOST is one argv word handed to `ssh`, never a 209 same session either way. HOST is one argv word handed to `ssh`, never a
209 shell line: `mux` execs ssh itself, so nothing local expands or splits it. 210 shell line: `mux` execs ssh itself, so nothing local expands or splits it.
210 211
docs/decisions.md
Old New
@@ -7525,3 +7525,24 @@ body-capable request that declared no length now closes its connection.
7525 - **What ≤15 remotes read.** Measured against the released v0.0.1-15 tarball: 7525 - **What ≤15 remotes read.** Measured against the released v0.0.1-15 tarball:
7526 rc 2, a usage page on stderr, nothing on stdout — so the asked dial reads 7526 rc 2, a usage page on stderr, nothing on stdout — so the asked dial reads
7527 `[unreachable]`, the same answer the rename already gave them. 7527 `[unreachable]`, the same answer the rename already gave them.
7528
7529 ## 2026-08-29 — the handoff is a step table; a warm miss pays one deadline
7530
7531 - **Policy out of the driver.** Which to try, in what order and when to give
7532 up sat inline between the effects performing it, so a row was reachable
7533 only through a daemon, an ssh shim and a blackholed port. It is
7534 `handoff.next` now, with `Transport.openHandoff` the loop performing what
7535 it names: fifteen mutation-proven rows, seven walks over whole traces.
7536 - **The defect that stood since 2026-08-11.** Where the announced UDP port
7537 cannot be reached, every attach after the first read the cache, spent the
7538 budget on silence, refetched over ssh, was told the SAME port and key, and
7539 spent it AGAIN before using the ssh pipe it had held open throughout:
7540 `Blocked, warm cache 4264ms`, against a criterion of "within one
7541 deadline". `State.failed_on` remembers what went silent, and the table
7542 ends on the pipe: `e2e_04_handoff.sh` leg (e) measures 4068ms with the row
7543 removed, 2137ms with it, against a ceiling of 3500.
7544 - **Equality is port AND key.** A restart takes a fresh ephemeral port, a
7545 re-key keeps the old one, and both are still worth dialling.
7546 - **The `use_pipe` rows are not vestigial.** Through `ssh -J gate box` the
7547 announced port is unreachable by construction — the jump host is the only
7548 route and it carries TCP — so the pipe is that host's only session.