Domain: Retrieval
Canonical rule: Unified retrieval is `retrieveEvidence`. `searchThoughts` is a thin wrapper. MCP retrieve_thoughts, HTTP search, and composeAnswer all use the same path.
Embeddings boundary: Query embeddings are computed in-process for SQL distance only; retrieval outputs are text + scores, never stored thought vectors. See embeddings-db-only-boundary.md.
Query-time baseline: No live Apache AGE reads. Graph relationships used at retrieval time come from precomputed thought_neighbor, entity_top_thoughts, and community_bundle rows materialized at enrich/consolidation.
Memory tiers and retrieval
| Tier | Recall at query time |
|---|---|
| 1 — Hot | FTS on lexical_text (+ cues[] after tier 2) |
| 2 — Enrich | pgvector ANN on thought.embedding; thought_entity, thought_neighbor |
| 3 — Consolidation | community_summary ANN (L1) + community_bundle.top_thought_ids; salience / recency features |
Query time (retrieveEvidence): embed query once → parallel ANN + FTS + community ANN → bundle/key fetch → weighted merge → LLM listwise rerank → return top K. No live AGE reads.
Apache AGE remains for ingest writes and /memory graph visualization only.
CompetingSystems
- None: one merge path in
retrieveEvidence.
Key files (scan-first)
[`src/lib/server/retrieval/retrieve-evidence.ts`](../../src/lib/server/retrieval/retrieve-evidence.ts)
- Purpose: Unified retrieval for all surfaces.
- PublicSymbols:
retrieveEvidence. - DependsOn:
lexicalSearch,community_bundle,entity_top_thoughts,thought_neighbor,rerankCandidates, pgvector HNSW indexes. - FailureMode: Propagates DB/LLM/rerank errors; reranker hard-fails (no silent reorder).
[`src/lib/server/retrieval/service.ts`](../../src/lib/server/retrieval/service.ts)
- Purpose: Back-compat wrapper delegating to
retrieveEvidence. - PublicSymbols:
searchThoughts,RetrievalResult.
[`src/lib/server/mcp/tools.ts`](../../src/lib/server/mcp/tools.ts)
- Purpose:
runRetrieveThoughtsTool(MCP nameretrieve_thoughts) wrapsretrieveEvidencewith MCP arg validation. Supports search (query+order=relevance) and browse (order=created_at, optional cursors).
[`src/lib/server/qa/compose-answer.ts`](../../src/lib/server/qa/compose-answer.ts)
- Purpose: Grounded QA for in-app chat: retrieve then compose natural-language answer. Not exposed as HTTP MCP
answer_question— chat agent callsretrieve_thoughtsand composes inline. - Owns: Prompting / composition policy; citation integrity (answer
[id]citations must ⊆ retrieved ids).
[`src/lib/server/retrieval/reranker.ts`](../../src/lib/server/retrieval/reranker.ts)
- Purpose: LLM listwise reranker over top-60 weighted-merge candidates.
- Status: Wired in
retrieveEvidencefor all callers.
[`src/lib/server/retrieval/materialize-links.ts`](../../src/lib/server/retrieval/materialize-links.ts)
- Purpose: Populate
thought_entity,thought_neighbor,entity_top_thoughtsat enrich/consolidation. Replaces live AGE graph reads at retrieval time.
[`src/routes/api/retrieval/search/+server.ts`](../../src/routes/api/retrieval/search/+server.ts)
- Purpose: Authenticated POST
{ query, topK }; same engine as MCPretrieve_thoughts.
Global retrieval (deferred)
Broad “what are my main themes?” corpus-wide synthesis remains deferred. composeAnswer and MCP use retrieveEvidence, which handles local/relational questions via hybrid search + rerank.
Eval / test harness
- Retrieval weight sweeps for evals live in `evals/harness/retrieval-sweep.ts`; product search uses `src/routes/api/retrieval/search/` — keep behavior aligned with
retrieveEvidence.