# 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 **1568** (1563 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 1568 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 1568; 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`.