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>
70 lines
2.8 KiB
Markdown
70 lines
2.8 KiB
Markdown
# 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:
|
|
|
|
```rust
|
|
// `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:
|
|
|
|
```rust
|
|
// 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`.
|