a73x

e032ef40

docs: the split, the first full coverage map, and the race it found

a73x   2026-08-26 18:04

Commit message
docs: the split, the first full coverage map, and the race it found

CLAUDE.md's never-cat figures had drifted on every file; the manifest test's
comment claimed name lengths its names do not have.

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

CLAUDE.md
Old New
@@ -23,10 +23,11 @@ First build after a clean checkout fetches ~30MB of QUIC deps (minutes, once).
23 Files are large and comment-dense (~44% of Zig bytes are `//`). Reading the repo 23 Files are large and comment-dense (~44% of Zig bytes are `//`). Reading the repo
24 costs ~800k tokens; every token stays in context and is re-billed each turn. 24 costs ~800k tokens; every token stays in context and is re-billed each turn.
25 25
26 - **Never `cat` these:** `src/server.zig` (4.0k lines, ~40k tok; its tests are 26 - **Never `cat` these:** `src/server.zig` (3.5k lines, ~35k tok; its tests are
27 siblings, `src/server_test_*.zig`, none over 1.6k), 27 siblings, `src/server_test_*.zig`, none over 1.6k; the agent relay and the
28 `test/e2e.sh` (7.0k), `docs/decisions.md` (4.9k), `src/wallview.zig` (3.0k), 28 session table are `src/server_agent.zig` and `src/server_sessions.zig`),
29 `src/interact.zig` (2.9k). 29 `test/e2e.sh` (9.7k), `docs/decisions.md` (7.0k), `src/wallview.zig` (5.5k),
30 `src/interact.zig` (4.5k).
30 Use `grep -n` for the symbol, then `sed -n 'A,Bp'` for a window. 31 Use `grep -n` for the symbol, then `sed -n 'A,Bp'` for a window.
31 `src/client.zig` is 1.9k now — cheap enough to read. 32 `src/client.zig` is 1.9k now — cheap enough to read.
32 - Every module has a `//!` header stating its contract. `head -12 src/X.zig` 33 - Every module has a `//!` header stating its contract. `head -12 src/X.zig`
docs/decisions.md
Old New
@@ -7015,3 +7015,33 @@ already carries this feature, so the first release with it is the floor. Until
7015 then the same-binary leg (`--allow-same-version`, a flag whose help text says 7015 then the same-binary leg (`--allow-same-version`, a flag whose help text says
7016 it exists for the e2e) is the v1 gate, and the cross-version leg is a documented 7016 it exists for the e2e) is the v1 gate, and the cross-version leg is a documented
7017 gap rather than a test that quietly does not run. 7017 gap rather than a test that quietly does not run.
7018
7019 ## 2026-08-26 — hygiene: server.zig split, coverage that finishes
7020
7021 **server.zig is three files and a test tree.** 12,003 lines → 3,464: the 132
7022 tests moved to nine `src/server_test_*.zig` siblings (bodies byte-identical,
7023 821 unit tests before and after, a build.zig gate on the import list because
7024 a dropped `_ = @import` is a domain of tests that passes by not running); the
7025 agent relay (seven fields touched by thirteen functions and almost nothing
7026 else) and the session table became types in `server_agent.zig` (360) and
7027 `server_sessions.zig` (298), each reaching the daemon through named things
7028 only; `handleFrame`'s 16 arms became methods. The pump stayed: `pumpOnce`,
7029 `serviceObserver`, `drainPending`, `checkAwaits` are the product.
7030
7031 **`make coverage` had never finished the suite.** Six stops, one disease: a
7032 pid the suite holds that under kcov is the tracer's. `endpoint` now runs bare
7033 like `start` (the handoff client kill()s and waits on an ssh child that is
7034 kcov); `softkill` is hardkill's TERM twin (ptrace drops a signal sent to the
7035 tracer); the upgrade candidate is the ELF behind the shim (`MUXD_ELF`);
7036 `real_pid` reads /proc off the tracee; the stop-gone leg names the pid `stop`
7037 waited on. First full map, ReleaseSafe so lines merge: TOTAL 77% of 3,197
7038 instrumented lines, server.zig 80% of 931, quic_server 92%, webhub 88%.
7039 `initFromManifest` reads 0/58 because kcov does not instrument the post-exec
7040 image; its unit tests own it. The map is a worklist, not a score.
7041
7042 **The tracer found a product race.** `muxa send` on a refused attach wrote
7043 input blind after the attach; when the daemon's close beat the write, EPIPE
7044 was reported instead of the refusal. Rare untraced, certain under ptrace
7045 (scenario 75 stopped there every run). Fixed at one owner: a peer-closed
7046 send drains the read side through `awaitFrame`, so the snapshot rule that
7047 tells a refusal from an ending is not copied.
src/server_test_upgrade.zig
Old New
@@ -18,8 +18,8 @@ test "writeManifestTo: every session's own name crosses, not the last one's" {
18 var srv = try Server.init(alloc, .{ .sock_path = sock_path, .shell = "/bin/sh" }); 18 var srv = try Server.init(alloc, .{ .sock_path = sock_path, .shell = "/bin/sh" });
19 defer srv.deinit(); 19 defer srv.deinit();
20 20
21 // Three sessions of DIFFERENT name lengths. One session cannot catch a 21 // Three sessions, each with a name of its own. One session cannot catch
22 // name that aliases its neighbour's buffer, which is how a by-value 22 // a name that aliases its neighbour's buffer, which is how a by-value
23 // `Session` copy in the gather loop shipped every record pointing at 23 // `Session` copy in the gather loop shipped every record pointing at
24 // the last name: right length, wrong bytes. 24 // the last name: right length, wrong bytes.
25 srv.sessions[1] = try Server.createSession(alloc, srv.spawn_plan, "work", 80, 24, null); 25 srv.sessions[1] = try Server.createSession(alloc, srv.spawn_plan, "work", 80, 24, null);