Recall should filter, not flood.
A bag of keywords gives every term the same voice, so retrieval either drags in everything that loosely matches or misses the one thing that mattered. Verity tags each memory from five distinct lanes and gives every tag a computed importance, then funnels a query through those weights before a single memory is scored.
Not every word deserves the same vote.
Each lane has a base weight. Entity and intent are what make a memory durable, so a single strong tag from either can carry a memory through the gate on its own. Lexical cannot, by construction.
A weak tag can never promote itself.
Base weights are modulated additively and clamped. Work the lexical lane all the way up (stated first, repeated to the cap, framed as a standing truth) and it still lands under the importance gate.
That is not a tuned threshold, it is arithmetic. It is why surface-word noise cannot smuggle a memory into your prompt.
- +0.10positionStated early beats stated in passing.
- +0.04repetitionPer extra occurrence, up to three.
- +0.15durabilityThe user framed it as standing: always, never, from now on, I prefer.
0.20 base
+ 0.10 position
+ 0.12 repeat ×3
+ 0.15 durable= 0.57 < 0.60 gateA lone lexical tag is never enough to spend tokens on. Two of them, together, are, and that threshold is the only place the weak lane gets a say.
Four steps, and no step is optional.
- 01ExtractThe query goes through the same five lanes as a memory does. Same text in, same tags out. The extractor is rules, not a model, so it never drifts.
- 02CandidatesThe tag index returns memories that share a tag. The cost is proportional to matched tags, not to how many memories you have.
- 03FunnelAny matched tag at or above the gate lets a memory through. Otherwise it needs at least two weak matches. One faint overlap is dropped, and a dropped memory is text that never reaches a prompt.
- 04ScoreRelevance scoring runs on survivors only, then top-k. The expensive step is the last step and sees the smallest set.
The vocabulary is minted from your own words.
Weights alone still fail on wording. Ask about AI and you miss the memory filed under large language model.
So each tenant grows a registry as they use the system. A candidate tag is canonicalised before it is stored, near-duplicates are recorded as aliases of the canonical form, and tags that keep appearing together are bridged as siblings.
LLMs → large-language-model
Same concept, different words. Resolves at full weight, because nothing was actually different.
artificial-intelligence ↔ large-language-model
Different concepts that this tenant keeps using together. The sibling rides in at a discount: enough to pull a memory through the gate, never enough to pretend it was a direct hit.
registry ≤ MAX_TAGS
Aliasing is what keeps the registry from growing without limit, and recall never adds to it, so a query cannot poison the vocabulary with its own noise.
BoundThe registry persists to Postgres, degrades to a JSON file in the vault, and degrades again to an in-process registry with a logged warning if both fail. Memory itself runs on cognee with an Obsidian vault as the durable fallback, so losing the graph costs you recall quality, not your notes.
Memory you can audit, in files you can read.
Every tag, weight and bridge lands in a vault you own. Open the workspace and watch a conversation get filed.