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>
206 lines
7.1 KiB
Markdown
206 lines
7.1 KiB
Markdown
# 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`.
|