Files
boxmaker/docs/plans/M3b/17-toolkit-nits.md
T
kyleandClaude Opus 5.5 a57a1305e7 M3b plan: follow-up tasks 14 to 17 for the review's lower findings
14 moves the pipe handling out of container.rs (a pure move, replayed on its
own); 15 starts threads with Builder and bounds output collection with a 2 s
grace period; 16 escapes container errors in the log and fixes two texts; 17
fixes toolkit's thread start, casts and the egress-proxy form. Each checked
against a reference, which is not kept. Tips T24 to T26 from this run.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-23 15:33:23 -07:00

2.8 KiB

M3b task 17: three small fixes in toolkit

Branch: m3b (run git switch m3b; git status --short must be empty, otherwise stop) Commit subject: toolkit: no thread panic in http_fetch, no casts, exact egress-proxy form

Goal

Three findings from the M3b review (3 and 7), all small:

  1. fetch.rs starts its standard-error reader with std::thread::spawn, which panics when the system cannot make a thread. Use std::thread::Builder.
  2. input.rs and files.rs compute a byte limit with an as u64 cast, which AGENTS forbids.
  3. toolkit egress-proxy --socket <path> --allow <list> extra is taken as the proxy form and listens. The form is exactly five words; anything longer is not it.

Files

  • Copy: crates/toolkit/tests/egress_form.rs
  • Modify: crates/toolkit/src/fetch.rs, crates/toolkit/src/input.rs, crates/toolkit/src/files.rs, crates/toolkit/src/main.rs, docs/implementer-log.md

The changes, exactly

1. fetch.rs. Replace let stderr_handle = std::thread::spawn(move || read_capped(stderr_reader)); with:

// `Builder`, not `spawn`, which panics when the system refuses a thread.
let stderr_handle = match std::thread::Builder::new().spawn(move || read_capped(stderr_reader)) {
    Ok(handle) => handle,
    Err(e) => {
        let _ = child.kill();
        let _ = child.wait();
        return Outcome::tool_error(format!("http_fetch: cannot start a thread: {e}"));
    }
};

2. input.rs and files.rs. Replace .take(MAX_INPUT as u64 + 1) with .take(u64::try_from(MAX_INPUT).map_or(u64::MAX, |n| n.saturating_add(1))), and the same for MAX_READ in files.rs.

3. main.rs. In parse_egress_proxy, the first check becomes:

// Exactly five words: a longer list is not this form, and goes to the tool form (exit 2).
if args.len() != 5 || args.first()?.as_bytes() != b"egress-proxy" {
    return None;
}

Steps

  • 1. Copy. git switch m3b, then cp docs/plans/M3b/files/crates/toolkit/tests/egress_form.rs crates/toolkit/tests/
  • 2. See it fail. cargo test -p toolkit --test egress_form. Expected: 1 fails after about 3 s ("it is listening").
  • 3. Make the three changes. Run cargo fmt --all.
  • 4. See it pass. cargo test -p toolkit. Expected: every suite passes; egress_form 1 passed quickly.
  • 5. Check. grep -n "thread::spawn\| as u64" crates/toolkit/src/ prints nothing.
  • 6. Run the gate. make gate. Expected last line: gate: ok, with about 649 tests.
  • 7. Log and commit. git add crates/toolkit docs/implementer-log.md Cargo.lock && git commit

This is the last follow-up task of M3b. Stop after the commit.

Done when

  • cargo test -p toolkit passes; the grep prints nothing; make gate prints gate: ok.