feat(recall): budgeted context pack β --pack on CLI, HTTP, and MCP (#1281 Phase 1) - #1284
Merged
Merged
Conversation
β¦1281 Phase 1) Adds a selection primitive over unified recall: rank-order preserving greedy fill of a caller-supplied character budget. - uteke-core: new pack_mode module (pack_context + ContextPack envelope {selected, skipped, budget_used, budget_chars}); Uteke:: recall_unified_packed wraps recall_unified. Skip reasons: excluded (caller-supplied memory IDs already injected this turn) and budget (no longer fits). Char-counted (multibyte-safe), per-item overhead constant. Ranking untouched β fusion stays the default strategy; deterministic, LLM-free. 5 unit tests. - CLI: recall --pack / --budget <chars> / --exclude-ids <ids> with human + --json output. Entity/category filters are honoured; the packed path loudly rejects --at/--related/--where instead of silently dropping them. - HTTP: POST /recall accepts pack, budget_chars, exclude_ids; pack honours the caller's search_type with the same 400 validation as the plain path; integration test covers envelope shape, exclusion reporting, and an impossible budget. - MCP: uteke_recall accepts pack/budget_chars/exclude_ids; tool schema updated. - Docs: cli-reference.md flags + examples, mcp.md tool description, CHANGELOG [Unreleased]. Phase 2 (MMR diversity) intentionally NOT included β experiment gated on LongMemEval + redundancy benchmarks per #1281. Testing: pack_mode 5/5; uteke-server 37 live tests green incl. the new pack API test; workspace suite green before test additions. Live E2E against a scratch UTEKE_HOME with real ONNX embeddings: remember x3, --pack human + JSON envelope (3 selected, 235/4000 chars), --exclude-ids reports reason=excluded for the right IDs, --budget 120 fills 1 item at 60 chars and skips 2 as budget.
| if req_data.pack { | ||
| let parsed_search_type = match req_data.search_type.as_deref() { | ||
| Some("memory") => uteke_core::SearchType::Memory, | ||
| Some("doc") => uteke_core::SearchType::Document, |
π Cora AI Code Reviewβ No issues found. Code looks good! Review powered by cora-code Β· BYOK Β· MIT |
CodeCora review on #1284 flagged that the pack branch validated only search_type: a request with pack+at silently returned non-time-travel results while the plain path honours the filters (and the CLI pack path already rejects --at loudly). - POST /recall with pack + at/after/before now returns the same 400 as the CLI contract; integration test extended. - docs/api-reference.md regenerated via docgen for the new public recall_unified_packed surface (API Docs Fresh gate).
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.
What
New
packmode on all recall surfaces: returns a{selected, skipped, budget_used, budget_chars}envelope instead of a bare ranked list β rank-order preserving greedy fill of a caller-supplied character budget, with per-item skip reasons.pack_modemodule (pack_context+ContextPack);Uteke::recall_unified_packedwrapsrecall_unified. Multibyte-safe char counting; constant per-item overhead. Ranking is untouched β fusion stays the default strategy. Deterministic, LLM-free.uteke recall --pack [--budget <chars>] [--exclude-ids <ids>], human +--jsonoutput. Entity/category filters honoured;--at/--related/--whereare rejected loudly on the packed path (no silent drop).POST /recallfieldspack,budget_chars,exclude_ids; pack honours the caller'ssearch_typewith identical 400 validation.uteke_recallparamspack,budget_chars,exclude_ids; tool schema updated.Skip reasons:
excluded(memory IDs already injected this turn β the caller owns turn state, Uteke stays pull-based) andbudget(no longer fits; cheaper lower-ranked items may still fill residual space).Why
Closes #1281 (Phase 1). Three independent users on the launch threads asked for exactly this: "the layer that decides what deserves to be present for this turn" (@roscherveniak), "dumps too much into context or misses the one note that mattered" (@0xhashlol), "retrieval that trusts it blindly" (@Synorb). Per the issue: Phase 1 = budget pack (this PR); Phase 2 = MMR diversity, an experiment gated on LongMemEval + redundancy benchmarks β intentionally NOT included here.
Testing
--packhuman output lists selected items with scores; JSON envelope 3 selected / 235 of 4000 chars;--exclude-idsreports exactly the excluded IDs withreason=excluded;--budget 120selects 1 item (60 chars) and skips 2 as budget.