docs: M5d-1 and M5d-2 implementation plans for Ornith
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>
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user