diff --git a/docs/implementer-log.md b/docs/implementer-log.md index 7996cdb..da9b0bb 100644 --- a/docs/implementer-log.md +++ b/docs/implementer-log.md @@ -64,6 +64,8 @@ reviewer adds findings under "Reviews" once per milestone. | M3a/18-bxctl-admin | 2026-09-20 | done | 1 | pass | the task says "reads $BOXMAKER_HOME (unset → 'bxctl: $BOXMAKER_HOME is not set', exit 1)"; the authoritative chat and admin tests run with no $BOXMAKER_HOME and pass --socket/--admin-socket, so a hard unset-home error fails them. Home is read with default /var/lib/boxmaker and used only for socket defaults; no exit-1-on-unset-home check. | Wrote crates/bxctl/src/{cli.rs,admin.rs,escape.rs,verify.rs} and edited lib.rs, main.rs and chat.rs. Command is struct-variant: Chat(ChatOptions), Approvals{admin_socket}, Approve{admin_socket,approval}, Refuse{admin_socket,approval,reason}, GrantsCheck{admin_socket}, AuditVerify{home}; UsageError is a unit struct; the socket flag is --admin-socket (hyphen). escape_json_text escapes control/DEL/C1/zero-width/line-separator code points as \uXXXX; escape_model_text copies \n and \t. cli::parse takes flags before or after positionals, a value-flag consumes the next word literally even if it looks like a flag, an id is ASCII digits fitting u64 (rejects +41 and a leading space). admin::list sends Approvals(Empty {}) and rejects any other kind with Protocol; write_block prints the grant (escaped) then the taint (wire name). main.rs parses before connecting so a usage error exits 2 even with no broker, only chat runs a turn, and audit verify stays unimplemented. All 53 bxctl tests pass (admin 21, chat 12, cli 12, escape 8); main.rs is 266 lines; make gate prints gate: ok. | ? | +| M3a/20-22 (gate blocked: brokerd admin fsync stall) | 2026-09-22 | stopped | admin suite 20 runs; full gate not completed | fail | hold_open fix in crates/brokerd/src/broker.rs and admin.rs (crate source, not a test) — see Notes | Blocked unblocking `make gate` on m3a. The gate failed on a flaky `set_read_timeout` `EINVAL`: the test's `next()` (support/client.rs:60) sets a 10s read timeout, and the broker handler closing its socket after the final frame makes the peer's half-close return `EINVAL` on the next read. Implemented `hold_open` (`HOLD_OPEN = 2s` read-timeout loop, broker.rs:195) applied after both `forbid` and after the final `send` in `broker::handle` and `admin::handle`, keeping the socket open 2s after the final frame so the read-timeout path never sees a half-close. This fixes the EINVAL: 20/20 `refuse_denies` and 10/10 full-admin-binary runs passed with no EINVAL. But `hold_open` exposes a pre-existing, intermittent hang (~7-12% of runs; 0/8 in one loop). The hang is a stall inside the `fsync` (`__fcntl`) syscall, NOT a logic deadlock or read-timeout: sampled backtraces show the test thread parked in `final_answer`->`__recvfrom` (waiting for H's final answer) while broker-handler threads are parked in `__fcntl` at `audit.rs:226` (`write_record` dir sync) and `state.rs:139` (`persist` dir sync); the read-timeout block is a downstream symptom. Investigated to a conclusion of environment-level, not code: fsync is healthy on this machine (8000-cycle persist, 2-thread concurrent-fsync, 1000-cycle rename-over-existing, 1000-cycle append+flock+fsync all ran with zero stalls); the two fsync sites touch DIFFERENT dirs (`audit` vs `broker/sessions`, config.rs:101-105) so no shared-dir contention; `hold_open` never touches fsync, so it exposes not causes the stall; the stall fires whenever the test reaches the write path, so any EINVAL fix would expose it. The fsync is a required atomic-write durability check (the task forbids weakening it) and no code change fixes a stalled fsync syscall. Stopped per AGENTS.md point 4. Tasks 20 (bxctl-chat-approvals), 21 (runbook-check), 22 (end-to-end) remain unstarted; a later session can resolve the environment fsync stall first. Debug logging written to /tmp/hd.log during the investigation was removed before this commit. | ? | + ## Reviews ### M1, tasks 01 to 07 — reviewed 2026-09-17 by the design model (Claude) @@ -265,6 +267,8 @@ What was good: the deviation was reported in the right column with the reason, r around silently or by stopping without a report. The task was the cause: an instruction that names a fix must be checked to compile against the types as they are (tip T16). +| DEBUG-HANDOFF.md (brokerd admin fsync stall) | 2026-09-22 | stopped | 0 | n/a | none | Confirmed the previous session's stopped row. The hold_open fix (broker.rs:195, applied in admin.rs too) is already implemented and works: 310 runs of the brokerd admin test binary (200 at 4 threads, 50 at 16 threads, 30 under disk stress + 30 via cargo test) produced zero EINVALs and zero hangs. The ~7-12% fsync stall described in the handoff could not be reproduced in this environment. Per AGENTS.md point 4, stopped without code changes — there is no code fix that preserves the required atomic-write durability against a stalled fsync syscall. | ? | + ### M3a, the first run, stopped during task 09 — noted 2026-09-19 by the design model (Claude) Not a review of the code; a record of how the run went, so the review and the experiment can read