Files
boxmaker/docs/plans/M6b/02-loopd-consult-wait.md
T
kyleandGrok 4.6 50e9cc2037 docs: M6b implementation plan
Six closed tasks for consult: registry, CONSULT_WAIT, [consult]/[secrets],
ToolName and grants, Decision body, loopback HTTP. Reference is the git bundle
~/boxmaker-refs/m6b-ref.bundle at 5fb05f0. Gate after task 06 is 1611.

Co-Authored-By: Grok 4.6 <noreply@x.ai>
2026-10-03 21:39:31 -07:00

206 lines
7.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# M6b task 02: `CONSULT_WAIT` through `timeout_for`
**Branch:** `m6b`. Check it: `git branch --show-current` prints `m6b` and `git status --short`
is empty; otherwise stop. Never switch branch.
**Commit subject:** `loopd: consult waits one hundred and eighty seconds`
**Log row:** the Task cell is `M6b/02-loopd-consult-wait`.
**First action.** Run this before any Read of crate source. Do not `ls` `crates/loopd/tests/`.
Do not Read `tests/support/`, `config.rs`, `docs/implementer-log.md` (except the first 12
lines at the log step). Do not edit `crates/loopd/tests/broker_port_ask_wait.rs` or
`crates/loopd/src/config.rs`. The quoted blocks are the only edits.
```sh
cp docs/plans/M6b/files/crates/loopd/tests/broker_port_consult_wait.rs crates/loopd/tests/
```
## Goal
`BrokerPort::timeout_for("consult")` is 180 s, or `[broker] timeout_ms` if that is longer
(spec 4.3). The default `[broker] timeout_ms` stays 120_000. `ask_memory` is unchanged.
No test sleeps (T27). This task does not talk to `brokerd`.
## Every place that changes
| Place | What happens there |
|---|---|
| `crates/loopd/src/broker_port.rs` | `CONSULT_WAIT`; `consult_timeout` on `new` and `with_log`; `timeout_for` arm |
| `crates/loopd/tests/broker_port_consult_wait.rs` | new, given |
| everything else | **no change**: not `config.rs`, not `broker_port_ask_wait.rs` |
## Files
- Copy, from `docs/plans/M6b/files/` (the same path under it): the new test
`crates/loopd/tests/broker_port_consult_wait.rs`.
- Modify: `crates/loopd/src/broker_port.rs`, `docs/implementer-log.md`.
- Do not touch: any other file. Do not edit `crates/loopd/tests/broker_port_ask_wait.rs`
(`the_wait_for_each_tool` does not list `consult`; leaving it unedited is required).
Do not change the default `timeout_ms: 120_000` in `crates/loopd/src/config.rs`.
## Facts you need
- **Floor, not a replacement.** `timeout_for("consult")` is
`self.timeout.max(self.consult_timeout)`. A configured 300 s wait stays 300 s.
- **Both constructors.** `new` and `with_log` each name `consult_timeout: CONSULT_WAIT`.
`with_ask_wait` and `with_pending_cap` use `..self` and need no edit.
- **`ASK_MEMORY_WAIT` stays.** Do not change its value or its arm.
- The items the edits use. This table is complete.
| Item | Signature |
|---|---|
| `BrokerPort::new` | `new(socket: PathBuf, timeout: Duration) -> BrokerPort` |
| `BrokerPort::with_log` | `with_log(socket: PathBuf, timeout: Duration, log: Box<dyn Fn(&str) + Send + Sync>) -> BrokerPort` |
| `BrokerPort::timeout_for` | `timeout_for(&self, tool: &str) -> Duration` |
| `crate::consult::CONSULT` | `&str`, `"consult"` (task 01) |
| `crate::memory::ASK_MEMORY` | `&str`, `"ask_memory"` |
## The edits, exactly
Each quoted "before" block occurs exactly once after task 01.
### `crates/loopd/src/broker_port.rs`
**W1.** After `pub const ASK_MEMORY_WAIT: Duration = Duration::from_secs(180);` add:
```rust
/// The longest `BrokerPort` waits for a `consult` answer, unless `[broker] timeout_ms` is
/// longer: `brokerd`'s `[consult] timeout_ms` defaults to 180 s (M6 spec, section 4.3).
pub const CONSULT_WAIT: Duration = Duration::from_secs(180);
```
**W2.** The struct fields
```rust
socket: PathBuf,
timeout: Duration,
ask_timeout: Duration,
pending_cap: Duration,
log: Box<dyn Fn(&str) + Send + Sync>,
```
become
```rust
socket: PathBuf,
timeout: Duration,
ask_timeout: Duration,
consult_timeout: Duration,
pending_cap: Duration,
log: Box<dyn Fn(&str) + Send + Sync>,
```
**W3.** Inside `new`, the fields
```rust
socket,
timeout,
ask_timeout: ASK_MEMORY_WAIT,
pending_cap: MAX_PENDING_WAIT,
log: Box::new(|l| eprintln!("{l}")),
```
become
```rust
socket,
timeout,
ask_timeout: ASK_MEMORY_WAIT,
consult_timeout: CONSULT_WAIT,
pending_cap: MAX_PENDING_WAIT,
log: Box::new(|l| eprintln!("{l}")),
```
**W4.** The comment and body of `timeout_for`
```rust
/// The wait for one call of `tool`, used wherever the port waits for that call: the timeout,
/// or for `ask_memory` the longer of the timeout and its own wait.
pub fn timeout_for(&self, tool: &str) -> Duration {
if tool == crate::memory::ASK_MEMORY {
self.timeout.max(self.ask_timeout)
} else {
self.timeout
}
}
```
become
```rust
/// The wait for one call of `tool`, used wherever the port waits for that call: the timeout,
/// or for `ask_memory` and `consult` the longer of the timeout and that tool's own wait.
pub fn timeout_for(&self, tool: &str) -> Duration {
if tool == crate::memory::ASK_MEMORY {
self.timeout.max(self.ask_timeout)
} else if tool == crate::consult::CONSULT {
self.timeout.max(self.consult_timeout)
} else {
self.timeout
}
}
```
**W5.** Inside `with_log`, the fields
```rust
socket,
timeout,
ask_timeout: ASK_MEMORY_WAIT,
pending_cap: MAX_PENDING_WAIT,
log,
```
become
```rust
socket,
timeout,
ask_timeout: ASK_MEMORY_WAIT,
consult_timeout: CONSULT_WAIT,
pending_cap: MAX_PENDING_WAIT,
log,
```
## Steps
- [ ] **1. Copy the given test.**
```sh
cp docs/plans/M6b/files/crates/loopd/tests/broker_port_consult_wait.rs crates/loopd/tests/
```
- [ ] **2. See it fail.** `cargo test -p loopd --test broker_port_consult_wait`, timeout
600000 ms: the test target does not compile (`E0432` unresolved `CONSULT_WAIT`).
- [ ] **3. The edits.** W1–W5. `cargo check -p loopd` prints no error and no warning.
`wc -l crates/loopd/src/broker_port.rs` ≤ 500.
- [ ] **4. The tests.** `cargo test -p loopd --test broker_port_consult_wait --test
broker_port_ask_wait`: every test passes, 1 in `broker_port_consult_wait`.
`the_wait_for_each_tool` still passes.
- [ ] **5. Run the gate.** `cargo fmt --all`, then `make gate`, timeout 600000 ms. Last
line `gate: ok`. Test count **1593** (1592 before, plus 1). After `gate: ok`, do not add
up `test result:` lines.
- [ ] **6. Log and commit.** Task cell `M6b/02-loopd-consult-wait`. Read only the first 12
lines of `docs/implementer-log.md`; insert the row under the header. Stage with
`git add crates/loopd docs/implementer-log.md Cargo.lock`, then commit as `AGENTS.md`
says.
## Done when
- `make gate` prints `gate: ok` with 1593 tests.
- `git diff HEAD~1 --stat` lists only `crates/loopd/src/broker_port.rs`,
`crates/loopd/tests/broker_port_consult_wait.rs` and the log.
## Stop and report if
- The branch check fails; a "before" block is missing or duplicated; step 2 compiles; you
edit `broker_port_ask_wait.rs` or `config.rs`; `cargo check` warns; `the_wait_for_each_tool`
fails; a test outside the named files fails in the gate (`git stash -u`, rerun,
`git stash pop`, report both).
## What the given tests pin
`CONSULT_WAIT` is 180 s. `timeout_for("consult")` is 180 s when the port timeout is 120 s,
and 300 s when the port timeout is 300 s. `timeout_for("recall")` stays the port timeout.
`with_log` matches `new`.