a73x

a3765ff8

docs: a unit test on stdout wedges the test runner silently

a73x   2026-08-29 10:01

Commit message
docs: a unit test on stdout wedges the test runner silently

CLAUDE.md
Old New
@@ -30,13 +30,13 @@ costs ~800k tokens; every token stays in context and is re-billed each turn.
30 `docs/decisions.md` (7.4k). `test/e2e.sh` is a 189-line runner now; the 30 `docs/decisions.md` (7.4k). `test/e2e.sh` is a 189-line runner now; the
31 bodies are `test/e2e_NN_*.sh` (`E2E_ONLY=<group>` runs one). 31 bodies are `test/e2e_NN_*.sh` (`E2E_ONLY=<group>` runs one).
32 Use `grep -n` for the symbol, then `sed -n 'A,Bp'` for a window. 32 Use `grep -n` for the symbol, then `sed -n 'A,Bp'` for a window.
33 `src/client/client.zig` is 2.4k now — cheap enough to read, and so is 33 `src/client/client.zig` is 2.7k now — cheap enough to read, and so is
34 every piece of the wall: `wallview.zig` is 2.2k (tiles, focus, births, 34 every piece of the wall: `wallview.zig` is 2.2k (tiles, focus, births,
35 endings, the keyboard loop) with `wall_pump.zig` (1.1k, one tile's 35 endings, the keyboard loop) with `wall_pump.zig` (1.1k, one tile's
36 thread), `wall_host.zig` (0.6k), `wall_picker.zig` (0.5k), 36 thread), `wall_host.zig` (0.6k), `wall_picker.zig` (0.5k),
37 `wall_layout.zig` (0.4k) and its tests in `src/tui/wall_test_*.zig` 37 `wall_layout.zig` (0.4k) and its tests in `src/tui/wall_test_*.zig`
38 (none over 1.2k). 38 (none over 1.2k).
39 Every figure here is `wc -l` on 2026-08-28; re-measure before trusting one. 39 Every figure here is `wc -l` on 2026-08-29; re-measure before trusting one.
40 - Every module has a `//!` header stating its contract. `head -12` on it 40 - Every module has a `//!` header stating its contract. `head -12` on it
41 answers most "what is this" questions for ~200 tokens. 41 answers most "what is this" questions for ~200 tokens.
42 - Pipe Bash output: `| tail -30`, `2>/dev/null`, `grep -c`. `make test` full 42 - Pipe Bash output: `| tail -30`, `2>/dev/null`, `grep -c`. `make test` full
@@ -278,6 +278,12 @@ paths (`src/cli/main.zig` is the daemon). Test fixtures in `test/`:
278 XDG_STATE_HOME=$SCRATCH/state` first, always — and a rig that dials a 278 XDG_STATE_HOME=$SCRATCH/state` first, always — and a rig that dials a
279 default socket needs an isolated `XDG_RUNTIME_DIR` too, or a bare `mux` 279 default socket needs an isolated `XDG_RUNTIME_DIR` too, or a bare `mux`
280 auto-starts against the user's live daemon. 280 auto-starts against the user's live daemon.
281 - **A unit test that writes to stdout wedges `zig build test` silently.** fd 1
282 of a test binary is the build runner's protocol stream; bytes on it hang the
283 runner at 0 CPU with no output. Code under test takes a writer; a test that
284 must exercise a stdout path captures fd 1 into a test-owned pipe
285 (`flags.exitForTo` is the shape). A `zig build test` that prints nothing
286 for minutes is this before it is anything else.
281 - **Never quote a speed number measured in the dev tree.** `zig build` is 287 - **Never quote a speed number measured in the dev tree.** `zig build` is
282 Debug, and Debug builds ghostty with its page-integrity check on — a hash 288 Debug, and Debug builds ghostty with its page-integrity check on — a hash
283 map over every cell per mutation, ~600x on output-heavy work. `make test`, 289 map over every cell per mutation, ~600x on output-heavy work. `make test`,