Skip to content

feat(mcp): find sessions that cover several concepts at once - #2557

Open
mariusvniekerk wants to merge 1 commit into
mainfrom
feat/multi-concept-semantic-recall
Open

mariusvniekerk wants to merge 1 commit into
mainfrom
feat/multi-concept-semantic-recall

Conversation

@mariusvniekerk

Copy link
Copy Markdown
Collaborator

When an assistant recalls past work, it often needs the one session that discussed two or more things, such as an auth change and the retry policy it needed. A single semantic query blends those ideas and favors passages that mention them together. It misses a session that covered them in different exchanges.

search_content (MCP and GET /api/v1/search/content) now accepts concepts: two to five ideas in place of pattern. Each concept runs as its own semantic search with the request's filters, and only sessions that every search found come back. Each result carries concept_evidence, the best passage per concept with its snippet, score, ordinal_range, and transcript revision, so the assistant can open each piece of evidence with get_messages.

This replaces #1876. That PR proposed the feature before the shared search contract (#1875) and kit's group fusion (kenn-io/kit#118) landed. Its terms mode and exact session and branch filters are already on main, so this keeps only the concepts part and rebuilds the intersection on rrf.FuseGroupsEvery.

Limits and tradeoffs

  • Results rank by the mean of each concept's best raw score, not by reciprocal rank. All concepts use one vector generation, so their scores are comparable. Equal means keep the reciprocal-rank order.
  • Each concept search reads five times the limit, at most 250 candidates. A session that one concept ranks below that window drops out of the intersection. candidate_truncated reports when a window filled or the limit cut the result.
  • Concept searches do not page. cursor, a non-semantic mode, and pattern alongside concepts are rejected as input errors. Over HTTP, concepts need the semantic search-intent header, like semantic and hybrid modes.
  • pattern is no longer a required parameter in the OpenAPI spec or the MCP tool schema. The transports return "pattern or concepts required" when both are missing.
  • revision_bound is true only when every piece of concept evidence also carries a revision. Each concept is a separate query, so evidence for one session can show different revisions if the session changed between the queries.

Where to look

  • internal/service/search_concepts.go: validation, the per-concept searches, fusion, and ranking. PostgreSQL and ClickHouse serve through the same service path, so no backend-specific code changed.
  • internal/server/huma_routes_search.go and internal/mcp/tools.go: the transport checks run before the service, so a rejected request never reaches the store.
  • The bundled memory skill does not mention concepts yet. Teaching it is a separate change.

Created with Claude Opus 5.5 in Claude Code.

An assistant recalling past work often needs one session that discussed
two or more ideas, such as an auth change and the retry policy it
needed. A single semantic query blends those ideas into one vector and
favors passages that mention both together. It misses a session that
covered them in different exchanges.

search_content now accepts two to five concepts in place of a pattern.
Each concept runs as its own semantic search with the same filters, and
only sessions that every search found are kept. Each result lists the
best passage for every concept, so the assistant can cite and open each
piece of evidence.

The intersection uses kit's group fusion, which was built for this
caller. Results rank by the mean of each concept's best score, because
all concepts use one vector generation and their scores are comparable.
Equal means keep the per-concept ranking order. Each concept search
reads at most 250 candidates. A session ranked below that window drops
out of the intersection, so the response reports candidate_truncated
when a window fills or the limit cuts the result.

This replaces #1876, which first proposed the feature before the shared
search contract and kit's fusion helpers landed.

Co-authored-by: salmonumbrella <182032677+salmonumbrella@users.noreply.github.com>
@roborev-ci

roborev-ci Bot commented Oct 30, 2026

Copy link
Copy Markdown

roborev: Combined Review (21e3427)

Verdict: Changes require fixes for 1 finding.

Medium

  • internal/service/search_concepts.go:93: candidate_truncated can remain false while matching sessions are omitted. Filtering or chunk rollup can produce fewer than the requested matches without exhausting the vector index, and semantic pages never set NextCursor.

    Fix: Propagate semantic candidate exhaustion or truncation through ContentSearchPage and combine that signal across concepts. Add behavioral coverage for short, non-exhausted pages caused by filtering or chunk rollup.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 12s | Total: 6m16s

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant