Eight closed tasks for epochs and compaction, then ten for the scheduler, ToolSummary, and tiers. Given tests first. Gate 1456 → 1507 → 1572. Co-Authored-By: Grok 4.6 <noreply@x.ai>
166 lines
6.0 KiB
Markdown
166 lines
6.0 KiB
Markdown
# M5d-2 task 02: `LogRecord::ToolSummary`
|
|
|
|
**Branch:** `m5d2`. Check it: `git branch --show-current` prints `m5d2` and `git status --short`
|
|
is empty; otherwise stop. Never switch branch.
|
|
**Commit subject:** `bxcore: ToolSummary log record; messages ignore it`
|
|
**Log row:** the Task cell is `M5d2/02-bxcore-tool-summary`.
|
|
|
|
## Goal
|
|
|
|
A tool that opts in gets a second record, for the index only (spec 4.3):
|
|
|
|
```text
|
|
LogRecord::ToolSummary { time, call, tool_call_id, content, class, untrusted }
|
|
```
|
|
|
|
JSON type `tool_summary`. `messages()` / `messages_with_carry` ignore it, so the epoch's prefix
|
|
does not change. `support/turn.rs` `types` names it (T19: this task ships its own copy).
|
|
|
|
Nothing summarises yet. That is task 08.
|
|
|
|
## Every place that changes
|
|
|
|
| Place | What happens there |
|
|
|---|---|
|
|
| `crates/bxcore/src/log.rs` | the variant, after `ToolResult` (edit L1) |
|
|
| `crates/loopd/src/baseline.rs` | ignore arm (edit B1) |
|
|
| `crates/loopd/tests/support/turn.rs` | replaced, given |
|
|
| `crates/bxcore/tests/tool_summary.rs` | new, given |
|
|
| `crates/loopd/tests/tool_summary_messages.rs` | new, given |
|
|
| everything else | **no change**: not `index.rs` (task 09), not `turn.rs` |
|
|
|
|
`memoryd/src/index.rs` `index_record` already has `_ => {}`. It compiles. Summaries are skipped
|
|
until task 09.
|
|
|
|
## Files
|
|
|
|
- Copy, from `docs/plans/M5d2/files/` (the same path under it): the new tests
|
|
`crates/bxcore/tests/tool_summary.rs` and
|
|
`crates/loopd/tests/tool_summary_messages.rs`, and the replacement
|
|
`crates/loopd/tests/support/turn.rs`.
|
|
- Modify: `crates/bxcore/src/log.rs`, `crates/loopd/src/baseline.rs`,
|
|
`docs/implementer-log.md`.
|
|
- Do not touch: any other file.
|
|
|
|
## Facts you need
|
|
|
|
- **Field order is the wire format.** `time`, `call`, `tool_call_id`, `content`, `class`,
|
|
`untrusted`. No `truncated`: a summary is already capped.
|
|
- **Unknown fields are errors**, as on every `LogRecord` variant (`deny_unknown_fields` is on
|
|
the enum).
|
|
- **`types` is exhaustive.** Adding the variant without the replacement `support/turn.rs` fails
|
|
to compile `turn` / `limits` tests. Copy the given file over the existing one. The only
|
|
intended change is the `ToolSummary => "tool_summary"` arm. `Setup::turn` still returns
|
|
`(Result<TurnOutcome, TurnError>, Vec<TurnEvent>)`.
|
|
- **`messages` names every variant.** The new arm is empty, like `Usage` / `CacheLoss` /
|
|
`EpochEnd`.
|
|
- The items the edits use. This table is complete.
|
|
|
|
| Item | What it does |
|
|
|---|---|
|
|
| `CallId` | already imported in `log.rs` |
|
|
| `DataClass` | already imported in `log.rs` |
|
|
|
|
## The edits, exactly
|
|
|
|
Each quoted "before" block occurs exactly once after task 01.
|
|
|
|
### `crates/bxcore/src/log.rs`
|
|
|
|
**L1.** After the `ToolResult` variant (the lines)
|
|
|
|
```rust
|
|
truncated: bool,
|
|
},
|
|
Usage {
|
|
```
|
|
|
|
become
|
|
|
|
```rust
|
|
truncated: bool,
|
|
},
|
|
ToolSummary {
|
|
time: Timestamp,
|
|
call: CallId,
|
|
tool_call_id: String,
|
|
content: String,
|
|
class: DataClass,
|
|
untrusted: bool,
|
|
},
|
|
Usage {
|
|
```
|
|
|
|
Keep the fields in that order.
|
|
|
|
### `crates/loopd/src/baseline.rs`
|
|
|
|
**B1.** After the `ToolResult` arm (the lines)
|
|
|
|
```rust
|
|
} => out.push(ChatMessage::Tool {
|
|
tool_call_id: tool_call_id.clone(),
|
|
content: content.clone(),
|
|
}),
|
|
LogRecord::Usage { .. } => {}
|
|
```
|
|
|
|
become
|
|
|
|
```rust
|
|
} => out.push(ChatMessage::Tool {
|
|
tool_call_id: tool_call_id.clone(),
|
|
content: content.clone(),
|
|
}),
|
|
LogRecord::ToolSummary { .. } => {}
|
|
LogRecord::Usage { .. } => {}
|
|
```
|
|
|
|
## Steps
|
|
|
|
- [ ] **1. Copy the given files.** From the repository root:
|
|
|
|
```sh
|
|
cp docs/plans/M5d2/files/crates/bxcore/tests/tool_summary.rs crates/bxcore/tests/
|
|
cp docs/plans/M5d2/files/crates/loopd/tests/tool_summary_messages.rs crates/loopd/tests/
|
|
cp docs/plans/M5d2/files/crates/loopd/tests/support/turn.rs crates/loopd/tests/support/turn.rs
|
|
```
|
|
|
|
- [ ] **2. See them fail.** `cargo build --tests --keep-going -p bxcore -p loopd`, timeout
|
|
600000 ms: `tool_summary` and `tool_summary_messages` do not compile (`E0599` no variant
|
|
`ToolSummary`). `support/turn.rs` does not compile for the same reason until L1. After L1
|
|
and before B1, `baseline.rs` fails (`non-exhaustive patterns`). Do L1 then B1 in step 3;
|
|
this step is the first `cargo build` against the given tests only, which is E0599.
|
|
- [ ] **3. The edits.** Make L1 then B1. `cargo check -p bxcore -p loopd` prints no error and
|
|
no warning.
|
|
- [ ] **4. The tests.** `cargo test -p bxcore --test tool_summary --test records` and
|
|
`cargo test -p loopd --test tool_summary_messages --test turn --test baseline --test
|
|
session_slot`: every test passes, 3 in `tool_summary`, 3 in `tool_summary_messages`.
|
|
- [ ] **5. Check.** `git diff --stat` lists `crates/bxcore/src/log.rs`,
|
|
`crates/loopd/src/baseline.rs`, `crates/loopd/tests/support/turn.rs`.
|
|
- [ ] **6. Run the gate.** `cargo fmt --all`, then `make gate`, timeout 600000 ms. Last line
|
|
`gate: ok`. Test count **1517** (1511 before, plus 6).
|
|
- [ ] **7. Log and commit.** Task cell `M5d2/02-bxcore-tool-summary`. Stage with
|
|
`git add crates/bxcore crates/loopd docs/implementer-log.md Cargo.lock`, then commit as
|
|
`AGENTS.md` says.
|
|
|
|
## Done when
|
|
|
|
- `make gate` prints `gate: ok` with 1517 tests.
|
|
- `git diff HEAD~1 --stat` lists only `crates/bxcore/src/log.rs`,
|
|
`crates/bxcore/tests/tool_summary.rs`, `crates/loopd/src/baseline.rs`,
|
|
`crates/loopd/tests/tool_summary_messages.rs`, `crates/loopd/tests/support/turn.rs` and the
|
|
log.
|
|
|
|
## Stop and report if
|
|
|
|
- The branch check fails; a "before" block is not found exactly once; step 2 differs; `cargo
|
|
check` warns; a test fails; the gate count is not 1517; you replay a summary as a `User` or
|
|
`Tool` message; you add `truncated`; you change `Setup::turn`'s return type.
|
|
|
|
## What the given tests pin
|
|
|
|
JSON type is `tool_summary`; unknown fields are refused; field order is the struct order;
|
|
`messages()` with and without a summary are equal; a summary is not a tool message; inserting a
|
|
summary between a result and a later user does not break prefix extension.
|