Merge m3a: brokerd's decision path (M3a)
Tasks 01 to 22, the review, and task 23 (the review fixes, with a second, independent review of them). The one conflict, docs/implementer-lessons.md, had the same T18 and T19 on both sides; m3a's T20 to T22 follow them. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
# 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.
|
||||
@@ -53,11 +53,13 @@ pub fn open(
|
||||
client
|
||||
}
|
||||
|
||||
/// The next frame, waiting at most ten seconds.
|
||||
/// The next frame, waiting at most ten seconds. Once the handler has closed its end, macOS
|
||||
/// refuses the timeout with EINVAL (22); the frame is buffered by then and the read cannot block.
|
||||
pub fn next(stream: &mut UnixStream) -> Envelope {
|
||||
stream
|
||||
.set_read_timeout(Some(Duration::from_secs(10)))
|
||||
.unwrap();
|
||||
if let Err(e) = stream.set_read_timeout(Some(Duration::from_secs(10))) {
|
||||
let peer_closed = cfg!(target_vendor = "apple") && e.raw_os_error() == Some(22);
|
||||
assert!(peer_closed, "set_read_timeout: {e}");
|
||||
}
|
||||
proto::read_frame(stream).unwrap()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user