# Task 23: the M3a review fixes Done by the design model directly (2026-09-22): Ornith was under heavy contention, and the fixes are small. The findings are in `docs/implementer-log.md`, "M3a, tasks 01 to 22". Most fixes land with a test that fails without it; the rest are checked by reading, as the last column says. | Finding | Fix | Test | |---|---|---| | 1 | `Writer::open`: a log with no complete record chains from the last line of the file before it, or from zero; no indexing | `brokerd/tests/audit_edges.rs`: one zero-length log file; one with a torn record only | | 2 | One definition of a log file name, `proto::is_audit_log_name`, used by `brokerd` and `bxctl` | `proto/tests/log_names.rs`; `brokerd/tests/audit_edges.rs`: `2026-0x-19.jsonl` is neither verified nor written | | 3 | `brokerd`'s config, directory and socket failures end with `#brokerd-start-failed`; a lost listener or a refused thread with `#brokerd-listener-lost`; both entries are new | `brokerd/tests/serve_pointers.rs` (the listener path by reading) | | 4 | `Writer` no longer unlinks `audit/.lock` | `brokerd/tests/audit_edges.rs` | | 5 | No `unwrap` in `audit.rs`, no `as` in `grants.rs` | gate | | 6 | `serve` starts threads with `thread::Builder`; a refused per-connection thread closes that connection and prints a line; running out of file descriptors or memory pauses the listener (second round) | by reading | | 7 | Every role's `main` reads `args_os`. `brokerd` and `loopd` keep the config path as a path, so one that is not UTF-8 works; `bxctl` and `inferproxy` take text and answer such an argument with their usage | `brokerd/tests/serve_pointers.rs`, `loopd/tests/args_os.rs`, `bxctl/tests/args_os.rs`, `inferproxy/tests/args_os.rs` | | 8 | `BrokerPort` waits at most 24 hours after a pending frame, whatever `expires` says | `loopd/tests/broker_port_cap.rs` | | 9 | `bxctl`'s admin requests time out after 30 s | `bxctl/tests/admin_timeout.rs` | | 10 | `bxctl` escapes `retrying` errors and every `error` detail | `bxctl/tests/escape_details.rs` | | 11 | The `the requester went away` result is recorded at the time it happens | by reading | | 12 | `bxctl`'s usage says what `audit verify` does | `bxctl/tests/cli.rs` (unchanged) | | 13 | `AdminError::Io`, and a failed write is returned at once | by reading | | 14 | Not in this task: `ToolArgs::HttpFetch`'s `url` and `host` become one sealed type in M3b's first task, where the runtime starts reading `url` | — | | 15 | `verify.rs` shares the name rule (2) and names the log-like files it did not check; `MAX_PATH`'s doc; the unused push in `grants.rs`. `find_tool` and `additionalProperties` change the baseline and wait for the next epoch change | — | Also, because the server changed: `crates/loopd/tests/device.rs` keeps the expected server in one constant, `EXPECT`, now four slots over one 262,144-token pool, and `tools/check-m3a-device.sh` matches it. They stay recorded expectations rather than values read from `/props`, which would make the self-test's own check pass by definition. Result: six code commits (`eed0a22` to `f6841f1`), then a second round after an independent review of those (`ba369f8` to `fc8befa`; see the log). Most new tests failed before their fix; two are regression guards that passed before it; `make gate` ok; `make verify-device` 6 of 6 and `tools/check-m3a-device.sh` ok on straylight.