Summary
A dead semantic tier (Ollama down → embeddings = 0 rows) degrades memory_hybrid_search to keyword-only. The degradation is reported at every layer — and is still invisible to the human, because nothing escalates it. The result is a memory system that confidently answers "No results found" for memories it holds, indefinitely, with no alarm.
This was found in the wild on a live install. It cost real trust in Recall.
Evidence (measured 2026-07-15, live install)
| Check |
Value |
embeddings table |
0 rows |
vec_embeddings_rowids |
0 rows |
| Ollama binary |
installed (/opt/homebrew/bin/ollama) |
| Ollama service |
DOWN (11434 refused) |
recall doctor verdict |
[WARN] — same severity as two false alarms |
User-visible failure:
$ recall search "do you remember when we decided how to handle graphs"
No results found.
$ recall search "CodeGraph"
Found 20 result(s)
The matching record (decision #2892) exists and is important enough to be injected into L1 at every SessionStart. The memory was never lost — the retrieval path to it was dead.
Traced path: memory_search → 0 keyword hits → shouldFallbackToHybrid (src/lib/search-fallback.ts:44) → hybrid → no embeddings → empty → "No results found" (search-fallback.ts:93).
Root cause: this is an escalation failure, not a silence failure
The system tells the truth at every layer:
- CLI:
Error: Embedding service not available at http://localhost:11434 / Falling back to keyword-only search...
- MCP:
Found 1 results (keyword-only: embeddings unavailable; semantic backend: none)
The signal reaches the agent on every single search. The agent reads it, answers from degraded results, and never tells the human. The information dies in the agent's context. No prose in a guide fixes this — the guides already say "memory first" in four places.
Contributing defects
1. recall doctor has no FAIL tier, so the real signal is buried in noise. Three same-severity WARNs; two are false alarms:
- "CLAUDECODE env var set (will block extraction)" — factually wrong. Every spawn path already clears it:
RecallExtract.ts:1034, extract-model.ts:129/:226, RecallInSession.ts:94, RecallClearExtract.ts:190. It flags the parent env, which is irrelevant.
- "messages stale 2.8d" — near-vestigial; structured extraction (decisions/LoA) flows daily.
A dead semantic tier and a bogus env warning cannot share a severity level.
2. The hybrid benchmark is an invalid instrument. The 23.5ms p50 @100k SLO (#217, #146) passes because the vec index is empty — it is fast because it searches nothing. A green benchmark over 0 rows is how this stayed invisible. The benchmark must fail on an empty index.
3. Negative relevance scores on the fallback path. src/lib/search-fallback.ts:63 and src/mcp-server.ts:531 do (r.score * 100).toFixed(1), but FTS5 bm25() returns negative scores (more negative = better). Renders as -1121.0%. This is on the fallback path — i.e. it only shows up while already degraded, compounding the trust loss.
4. Semantic dedup is silently non-functional in this state. dedup.ts:52 (DEFAULT_SEMANTIC_THRESHOLD = 0.95) reads embeddings, which are empty — and has no automatic caller.
Relationship to #226
#226 item 3 predicted this exact failure, verbatim:
recall doctor has no vec checks — extension loaded, index row count vs embeddings count, index format version. A silently-degraded vec tier is currently invisible outside stderr logs.
It sits unstarted in Phase 3 Todo. The failure mode was correctly diagnosed and filed, then deprioritized, then hit in production. This issue is the field report that should pull #226 item 3 forward.
Proposed fix
Detection
Escalation (the actual gap)
Instrument integrity
Recovery UX
Acceptance criteria
- With Ollama stopped,
recall doctor exits non-zero with a FAIL naming the dead semantic tier — and no CLAUDECODE warning.
- With
embeddings = 0, the hybrid benchmark fails.
- With the tier degraded, an agent using
memory_hybrid_search receives a signal it cannot answer past without surfacing to the user.
- No search output renders a negative percentage.
Notes
- Diagnosed via 3-agent RedTeam ParallelAnalysis. Full plan:
.agents/atlas/plans/2026-07-15-recall-confidence-diagnosis-and-remediation.md (local, gitignored). Recall learning #720.
- Capture was never at fault — decisions 3004, LoA 910, learnings 717, breadcrumbs 4244, same-day writes. Retrieval was the whole defect.
Refs #226, #217, #146.
Summary
A dead semantic tier (Ollama down →
embeddings= 0 rows) degradesmemory_hybrid_searchto keyword-only. The degradation is reported at every layer — and is still invisible to the human, because nothing escalates it. The result is a memory system that confidently answers "No results found" for memories it holds, indefinitely, with no alarm.This was found in the wild on a live install. It cost real trust in Recall.
Evidence (measured 2026-07-15, live install)
embeddingstablevec_embeddings_rowids/opt/homebrew/bin/ollama)recall doctorverdict[WARN]— same severity as two false alarmsUser-visible failure:
The matching record (decision #2892) exists and is important enough to be injected into L1 at every SessionStart. The memory was never lost — the retrieval path to it was dead.
Traced path:
memory_search→ 0 keyword hits →shouldFallbackToHybrid(src/lib/search-fallback.ts:44) → hybrid → no embeddings → empty →"No results found"(search-fallback.ts:93).Root cause: this is an escalation failure, not a silence failure
The system tells the truth at every layer:
Error: Embedding service not available at http://localhost:11434 / Falling back to keyword-only search...Found 1 results (keyword-only: embeddings unavailable; semantic backend: none)The signal reaches the agent on every single search. The agent reads it, answers from degraded results, and never tells the human. The information dies in the agent's context. No prose in a guide fixes this — the guides already say "memory first" in four places.
Contributing defects
1.
recall doctorhas no FAIL tier, so the real signal is buried in noise. Three same-severityWARNs; two are false alarms:RecallExtract.ts:1034,extract-model.ts:129/:226,RecallInSession.ts:94,RecallClearExtract.ts:190. It flags the parent env, which is irrelevant.A dead semantic tier and a bogus env warning cannot share a severity level.
2. The hybrid benchmark is an invalid instrument. The 23.5ms p50 @100k SLO (#217, #146) passes because the vec index is empty — it is fast because it searches nothing. A green benchmark over 0 rows is how this stayed invisible. The benchmark must fail on an empty index.
3. Negative relevance scores on the fallback path.
src/lib/search-fallback.ts:63andsrc/mcp-server.ts:531do(r.score * 100).toFixed(1), but FTS5bm25()returns negative scores (more negative = better). Renders as-1121.0%. This is on the fallback path — i.e. it only shows up while already degraded, compounding the trust loss.4. Semantic dedup is silently non-functional in this state.
dedup.ts:52(DEFAULT_SEMANTIC_THRESHOLD = 0.95) reads embeddings, which are empty — and has no automatic caller.Relationship to #226
#226 item 3 predicted this exact failure, verbatim:
It sits unstarted in Phase 3 Todo. The failure mode was correctly diagnosed and filed, then deprioritized, then hit in production. This issue is the field report that should pull #226 item 3 forward.
Proposed fix
Detection
recall doctor(Harden vec index: zero-vector guard, index-format version stamp, doctor/stats vec observability #226 item 3): extension loaded,embeddingscount, index rowid count vs embeddings count, index format version, embedding backend reachableFAILseverity distinct fromWARN. Dead/empty semantic tier =FAIL, non-zero exitmessagesstaleness checkEscalation (the actual gap)
memory_hybrid_searchreturn a top-leveldegraded: truethe guide requires escalatingFOR_CLAUDE.md: if a tier reports degradation, surface it to the user that turn — never answer from degraded results silentlyInstrument integrity
-1121.0%— normalize BM25 or drop the%unitRecovery UX
ollama serve→recall embed backfill→recall embed statsAcceptance criteria
recall doctorexits non-zero with aFAILnaming the dead semantic tier — and no CLAUDECODE warning.embeddings= 0, the hybrid benchmark fails.memory_hybrid_searchreceives a signal it cannot answer past without surfacing to the user.Notes
.agents/atlas/plans/2026-07-15-recall-confidence-diagnosis-and-remediation.md(local, gitignored). Recall learning #720.Refs #226, #217, #146.