feat: digest a session without a query, with sketch - #124
Merged
Conversation
`funes sketch <session_id>` selects the passages most distinctive within one session, from the vectors already stored — the read for an open-ended judgement about a session, where what answers it is usually what does not belong in it. The selector is ported unchanged, with its tests, from `feat/guided-curation`, where it fed a preview pane: pivoted Gram-Schmidt over the stored vectors, centring each passage on the session's own mean and taking the largest residual. Left behind are the picker's context neighbours, the per-turn refresh hook, the ANSI preview, and the cache-outcome reporting, none of which has a caller here. Agent-facing, it takes only what a caller has a basis for choosing: `units`, `max_chars`, and a `from`/`to` window. The bounds clamp the output instead of validating arguments against each other — 40 places, 40,000 characters, a floor of 240 per place, and no passage may take more than its share — and every clamp and elision is stated. A whole-session digest is cached: 13,281 turns, 1.78s to 0.15s. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a new query-independent “session digest” read path (funes sketch) that selects the most distinctive passages within a session from stored embeddings, renders them in the agent contract format (with → get drill-down hints), and wires the command through CLI + MCP, with docs and integration coverage.
Changes:
- Introduces
session_sketchdeterministic selector + caching and exposes it viafunes sketch. - Adds agent-format rendering for sketches and integrates the command into CLI and MCP tooling.
- Updates docs/agent contract plus adds integration test assertions for sketch behavior.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/index_recall.rs | Adds integration assertions for sketch formatting, clamping reporting, and missing-session error behavior. |
| src/ui/render.rs | Implements the byte-stable agent rendering for sketch output, including clamp notes and → get hint lines. |
| src/session_sketch.rs | Adds the core session sketch selection logic, budgeting/clamping rules, caching support, and unit tests. |
| src/main.rs | Wires the new Sketch subcommand into the CLI with flags (--units, --max-chars, --from, --to). |
| src/lib.rs | Exposes the new session_sketch module publicly. |
| src/commands/sketch.rs | Implements the funes sketch command, including clamp reporting and cached whole-session sketches. |
| src/commands/recall.rs | Makes is_scaffolding visible to the sketch selector so scaffolding can be excluded consistently. |
| src/commands/mcp.rs | Adds the sketch MCP tool + request schema and routes calls to the command implementation. |
| src/commands.rs | Registers the new sketch command module. |
| docs/recall.md | Documents CLI usage, output shape, defaults/clamps, and intended use-cases for sketch. |
| AGENTS.md | Extends the published agent read-contract to include the new sketch verb and MCP tool list. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+127
to
+131
| sketch <session_id> — <n> of <units> places · <chars> of <max-chars> chars · <k> eligible units | ||
| (units clamped to <n>) | ||
| [<ts>] <role> <block_type> seq<N> · shortened | ||
| → get <session_id> --from <seq> --to <seq> --memory <label> | ||
| <the passage> |
Comment on lines
+1395
to
+1401
| let head_len = limit * 7 / 10; | ||
| let tail_len = limit.saturating_sub(head_len); | ||
| let head: String = unit.text.chars().take(head_len).collect(); | ||
| let mut tail: Vec<char> = unit.text.chars().rev().take(tail_len).collect(); | ||
| tail.reverse(); | ||
| let tail: String = tail.into_iter().collect(); | ||
| (format!("{head}\n\n[… shortened by session-sketch …]\n\n{tail}"), true) |
display_text split head and tail at the full limit and then added the elision marker, so a shortened passage rendered past its share of the character budget. Take the marker out of the same limit. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
funes sketch <session_id>selects the passages most distinctive within one session, from the vectors already stored — the read for an open-ended judgement about a session, where what answers it is usually what does not belong in it.The selector is ported unchanged, with its tests, from
feat/guided-curation, where it fed a preview pane: pivoted Gram-Schmidt over the stored vectors, centring each passage on the session's own mean and taking the largest residual. Left behind are the picker's context neighbours, the per-turn refresh hook, the ANSI preview, and the cache-outcome reporting, none of which has a caller here.Agent-facing, it takes only what a caller has a basis for choosing:
units,max_chars, and afrom/towindow. The bounds clamp the output instead of validating arguments against each other — 40 places, 40,000 characters, a floor of 240 per place, and no passage may take more than its share — and every clamp and elision is stated. A whole-session digest is cached: 13,281 turns, 1.78s to 0.15s.