feat: R2 — honest retrieval metadata on every recall - #182
Merged
Conversation
…n every envelope
The silent shape this removes: embeddings configured, sqlite-vec missing
or the provider down → recall silently served keyword-only results with
nothing in the response saying so, and a limit-full window was
indistinguishable from a complete answer.
Every recall envelope (MCP, HTTP, CLI --json) now carries
`retrieval: { mode, degraded, truncated }`:
- mode: 'hybrid' when the vector supplement actually ran, 'fts' when the
answer is keyword-only (by configuration, or no searchable query).
- degraded: true = embeddings ARE configured but the vector side could
not run right now — supplementWithVectors reports its outcome
('used' | 'unconfigured' | 'degraded') instead of returning void with
a silent catch. Unconfigured keyword-only is NOT degraded: that is the
configured behaviour.
- truncated: true = results filled `limit`; more may exist. A small hit
count is a window, not a graph-wide count.
recallEnhanced returns {entities, retrieval} (two test files updated to
the new shape); recallWithConflicts threads it through, so the three
transports cannot drift. CLI human output prints a degraded warning and
a "(limit reached — more may exist)" note; CLI --json now always prints
the object envelope {entities, retrieval, conflicts?} — the bimodal
bare-array-or-object shape MCP and HTTP already abandoned.
Docs: API_REFERENCE recall section documents the block; AGENTS.md and
the memesh skill teach agents to read it instead of guessing; CHANGELOG
notes the CLI --json shape change. Audit baseline: 4 pure line-shift
re-keys (statements verified unchanged).
Verification (this session):
- vitest recall-retrieval-meta + tools + http + cli/recall-presentation
+ recall-hits-instrumentation + recall-quality: 119 passed, exit 0
- npm run typecheck exit 0; npm run build exit 0
- check-doc-claims exit 0; verification-audit exit 0
…skills manifest The full-suite run caught the one bare-array consumer the survey missed (tests/cli/flag-validation.test.ts merge-strategy pin), and verify:release caught dist/skills-manifest.json lagging the memesh SKILL.md edit — the manifest hashes skill files, not only hooks. [Verified-By: npx vitest run tests/cli/flag-validation.test.ts exit=0 — 'Tests 15 passed (15)'; npm run build exit=0]
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.
R2 — honest retrieval metadata
Every recall now says how it was answered. The silent shape this removes: embeddings configured, sqlite-vec missing or the provider down → recall silently served keyword-only results with nothing in the response saying so; and a
limit-full window was indistinguishable from a complete answer.The
retrievalblockCarried on every recall envelope — MCP, HTTP and
memesh recall --jsonalike:{ "entities": [...], "retrieval": { "mode": "hybrid", "degraded": false, "truncated": false } }mode—hybridwhen the vector supplement actually ran;ftswhen the answer is keyword-only (by configuration, or no searchable query).degraded—truemeans embeddings ARE configured but the vector side could not run right now (provider failure or missing sqlite-vec). Keyword-only-by-configuration is NOT degraded — that distinction is the point.truncated—truemeans results filledlimit; more may exist. The difference between "that is all" and "that is all I was allowed to return".Mechanics:
supplementWithVectorsreports its outcome (used/unconfigured/degraded) instead of returning void with a silent catch;recallEnhancedreturns{entities, retrieval}andrecallWithConflictsthreads it through, so the three transports cannot drift.Surface changes
memesh doctor) and a(limit reached — more may exist)note.memesh recall --jsonnow always prints the object envelope{entities, retrieval, conflicts?}— previously a bare array normally and an object only when conflicts existed. MCP and HTTP abandoned that bimodal shape in v4.5.x (it broke Gemini CLI); the CLI now matches. Called out in the CHANGELOG. Repo-wide grep found no programmatic consumer of the bare-array shape (docs examples feed LLMs, not parsers).retrievalinstead of guessing — the natural counterpart of the anti-hallucination clauses shipped in docs(agents): what an agent must never invent #180.Verification (run in this session, verdicts by exit code)
Break-test against the committed baseline: mutating the vector-failure catch back to the old silent swallow (
return 'used') turnstests/recall-retrieval-meta.test.tsred (1 failed, exit 1); restoring turns it green (6 passed, exit 0).The first full-suite run itself caught two real gaps, both fixed in the last commit: the one remaining bare-array consumer of
recall --json(flag-validation's merge-strategy pin), anddist/skills-manifest.jsonlagging the SKILL.md edit (the manifest hashes skill files, not only hooks).