Files
boxmaker/docs/plans/M5d2/09-memoryd-summary-index.md
T
kyleandGrok 4.6 3726ae585f 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>
2026-10-02 21:54:37 -07:00

142 lines
5.5 KiB
Markdown

# M5d-2 task 09: index `ToolSummary` as kind `summary`
**Branch:** `m5d2`. Check it: `git branch --show-current` prints `m5d2` and `git status --short`
is empty; otherwise stop. Never switch branch.
**Commit subject:** `memoryd: index ToolSummary as kind summary`
**Log row:** the Task cell is `M5d2/09-memoryd-summary-index`.
## Goal
`memoryd` indexes `LogRecord::ToolSummary` content as kind `summary`, with that record's
`class` and `untrusted` (spec 4.3, P26). `recall` finds it and tags `memory` or
`memory-tainted` as for any other session hit. Raw `ToolResult` bodies stay unindexed.
`index_record` today has `_ => {}`. It compiles. This task adds the arm.
## Every place that changes
| Place | What happens there |
|---|---|
| `crates/memoryd/src/index.rs` | `ToolSummary` arm (edit I1); module doc |
| `crates/memoryd/tests/tool_summary_index.rs` | new, given |
| everything else | **no change**: not `recall.rs` headers (role `"summary"` uses the existing "the assistant said" branch) |
## Files
- Copy, from `docs/plans/M5d2/files/` (the same path under it): the new test
`crates/memoryd/tests/tool_summary_index.rs`.
- Modify: `crates/memoryd/src/index.rs`, `docs/implementer-log.md`.
- Do not touch: any other file. Do not edit `tests/support/logs.rs`.
## Facts you need
- **Kind `summary`.** Set `kind: "summary".to_string()` on the `Source`, not the log's
`"session"`. Role `"summary"`. Time from the record. `class` / `untrusted` from the
`ToolSummary`, not from `base` (the rolling session label). Skip when
`summary.class > self.max_class`, even if `base.class` is still `Private`. Skip when
`content.trim()` is empty.
- **The existing `if base.class > self.max_class` stays.** A secret `ToolResult` raises the
rolling label before the next record, so a following secret summary is also skipped that
way. Still check the summary's own class.
- **Do not add `ToolSummary` to the rolling-label update** in `index_log` (that loop still
looks at `ToolResult` only). The result already carried the same labels.
- **Recall headers.** `kind` `"summary"` is not `moved` / `dropped` / `noted`, so the tag is
`memory` or `memory-tainted`. Role `"summary"` is not `owner` or `call`, so the line says
`the assistant said`. The given tests look for `memory · session mm-a` and
`memory-tainted`.
- The items the edits use. This table is complete.
| Item | What it does |
|---|---|
| `self.add` | FTS row plus `sources` |
| `Source` | kind / role / class / untrusted |
## The edits, exactly
Each quoted "before" block occurs exactly once.
### `crates/memoryd/src/index.rs`
**I1.** After the `Assistant` arm, before `_ => {}`. The lines
```rust
}
_ => {}
}
Ok(())
}
```
become
```rust
}
LogRecord::ToolSummary {
time,
content,
class,
untrusted,
..
} if !content.trim().is_empty() && *class <= self.max_class => {
let src = Source {
kind: "summary".to_string(),
time: time.to_rfc3339(),
role: "summary".to_string(),
class: *class,
untrusted: *untrusted,
..base.clone()
};
self.add(content, &src)?;
}
_ => {}
}
Ok(())
}
```
`DataClass` already implements `Ord` (`Public < Private < Secret`). If `<=` does not
compile, stop.
Optionally update the module doc "never a tool's result" to say summaries of opted-in
results are indexed. A comment that does not fit its code: stop.
## Steps
- [ ] **1. Copy the given test.**
```sh
cp docs/plans/M5d2/files/crates/memoryd/tests/tool_summary_index.rs crates/memoryd/tests/
```
- [ ] **2. See it fail.** `cargo test -p memoryd --test tool_summary_index`, timeout 600000
ms: the tests compile (`ToolSummary` exists) and `a_tool_summary_is_found_as_kind_summary`
fails: `(no matches for "tea")` or the unique phrase is missing. `the_raw_tool_result_is_still_not_indexed`
may pass (results were already unindexed).
- [ ] **3. The edit.** I1. `cargo check -p memoryd` prints no error and no warning.
- [ ] **4. The tests.** `cargo test -p memoryd --test tool_summary_index --test recall`: every
test passes, 5 in `tool_summary_index`.
- [ ] **5. Check.** `git diff --stat` lists exactly `crates/memoryd/src/index.rs`.
- [ ] **6. Run the gate.** `cargo fmt --all`, then `make gate`, timeout 600000 ms. Last line
`gate: ok`. Test count **1566** (1561 before, plus 5).
- [ ] **7. Log and commit.** Task cell `M5d2/09-memoryd-summary-index`. Stage with
`git add crates/memoryd docs/implementer-log.md Cargo.lock`, then commit as `AGENTS.md`
says.
## Done when
- `make gate` prints `gate: ok` with 1566 tests.
- `git diff HEAD~1 --stat` lists only `crates/memoryd/src/index.rs`,
`crates/memoryd/tests/tool_summary_index.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 1566; you index `ToolResult` content; you
leave `kind` as `"session"`; a secret summary is searchable on a private index.
## What the given tests pin
A summary's content is found and tagged `memory · session …`; the raw tool body is not; an
untrusted summary taints the recall (`memory-tainted`); a trusted summary does not taint; a
secret summary is skipped when `max_class` is `Private`.