A memory system makes three decisions: what to store, what to retrieve, and what to forget. Most projects build the first two and treat the third as deletion. The forget gate is where the damage is, because a memory that is wrong does not stay wrong in one place. It gets retrieved, repeated, and eventually treated as context.
The useful design is a set of typed gates rather than one memory store. Each gate is a small judgment with a threshold, and each threshold should match what a mistake costs.
The write gate
The basic memory cookbook adds a Noul after the answer: does this request state a lasting fact about the customer, such as an edition, plan, or contract? At P(yes) of 0.5 or more, the request and answer are saved. Lasting facts scored 0.91–0.92 in the example; airport and holiday small talk scored 0.07–0.10.
The wrapper only changes the state. ask_with_memory() takes the same state and questions as ask(), adds the customer's saved tickets under one key, and appends a new memory after the gate approves. Six later messages reached the expected teams with memory against two without, because the same message routes differently per customer. The gate runs after the answer because it judges the request together with the answer, so each call makes two sequential requests.
Two caveats are worth carrying into production. The store is a plain Python dict that disappears when the process exits, and memory only grows: there is no size limit, relevance check, or expiry. A saved answer can also reinforce a mistake, because once it is in memory its answer goes into every later call for that customer. The page's own suggestions are the fix: a database keyed by customer ID, a relevance question to choose which memories to include, and a question asking whether a new memory replaces an older one.
Retrieval is a second gate
Storing less is only half the problem. zerikai_memory is a local MCP memory server that indexes code with tree-sitter into ChromaDB and retrieves file-and-line context. Its optional Jev layer scores each retrieved passage for relevance, evidence, contradiction, and prompt injection, orders passages better than keyword rerank, and drops injection attempts before they reach the LLM.
The layer is off by default and fail-open: with ENABLE_JEV=false behavior is byte-identical, and an unavailable Jev falls back to the normal pipeline. That is the right default for a developer tool, but it also means the layer's value depends on a retrieval policy you control. The README gives no accuracy numbers for the layer. Treat it as an example of the shape (a memory gate at retrieval time) rather than evidence that the gate works.
Forgetting is the hard gate
The most useful paper in this area is about retirement, not storage. Suggested Is Not Superseded evaluates Jev as a memory-retirement gate on 500 labeled pairs from STALE. Of 179 pairs the dataset marks as changed, only 72 meet the paper's bar for an established change. The rest are suggestions: a hint that something may have changed, not a confirmed replacement.
A binary gate never retired a claim across 141 same-conversation non-changes, which sounds good until the other number: it retired 39.2% of claims whose change was only suggested. That is premature retirement. A three-way contract (SUPERSEDED, NEEDS-CONFIRMATION, COMPATIBLE) cut premature retirement to 15.5%, but imposed a 15.3-point detection cost, missing the pre-registered 10-point budget. A development-selected escalation cascade was indistinguishable from simply raising the threshold.
The paper is a preprint, and its gold labels come from LLM annotators with two human adjudicators, one an author. The held-out evidence is a single vault scored against a second annotator. Those limits matter, but the design lesson is robust: do not wire a binary score to deletion. Route suggested changes to pending evidence, where a later confirmation can promote them.
Project memory in the coding loop
jevmem applies the gate to project memory for Claude Code, Cursor, and Codex. Jev decides whether a turn is a decision, rule, bug, constraint, to-do, dead end, or injection; code writes or supersedes a line in JEVMEM.md. Secrets are scrubbed on the machine. A saved line is at most 200 characters, and a replaced line stays in the file tagged superseded, kept for history but never sent back to the agent.
On 66 author-written turns, jevmem scored 98.5% on save/skip and 95.5% on save-plus-kind, at 300 ms p50 and $0.000127. A 44-line poisoning set blocked 20 of 22 planted lines with zero false blocks. The Stop hook exits in 12–14 ms, and the Jev decision is recorded 0.26–0.28 seconds after it starts.
The caveats are the reason to read the numbers as a field report. Every eval set was written by the author, GPT-6 Astra and Claude Opus 5.5 scored higher on save-plus-kind, automatic capture is Claude Code only, and the poisoning gate missed 2 of 22 planted lines. On the author's own A/B run, a hand-written CLAUDE.md followed the project's decisions 67 of 72 times against 66 for jevmem. Rules every task must follow still belong in that file.
What the research architecture changes
Jev-Mem moves the same idea into the memory architecture itself. It divides the system into a System One control plane, a structured multi-relational memory plane, and a System Two reasoning plane. System One handles memory typing and relational organization during construction, then query routing, retrieval-budget allocation, graph traversal, candidate scoring, and adaptive stopping during retrieval. System Two is invoked only for complex reasoning and answer synthesis.
On LoCoMo it reports an overall LLM-as-a-Judge score of 0.777, an 11.0% relative improvement over the strongest baseline, with construction at 158 seconds (6.6× faster than the fastest competing system) and average query latency of 0.93 seconds (36.7% lower). The preprint names no code release, and LLM-as-a-Judge scoring is not an audited end-task suite. The architectural claim is still useful: keep control decisions off the expensive generation path, and let the slow model do only the work that needs it.
Working memory is not storage
Passage is a teaching aid, not a memory server. It reviews English instructional passages and estimates how many ideas a learner must hold at once, comparing that demand against a 1–5 slot budget. Jev makes bounded choices about familiarity, grouping, and relationships while a local parser proposes reading steps and exact source occurrences.
Each decision batch is sampled PASSAGE_JEV_SAMPLES times (default 2, range 1–5) and averaged because Jev answers are not deterministic. Confidence labels are Low, Moderate, or Unavailable, not calibrated percentages, and the project says its slot estimates are not validated measurements of memory. That honesty is the point: working memory is a model of the task, not a store of facts.
Batch the gate and tune the threshold
The parallel questions cookbook shows the batching arithmetic: 13 questions over a 54,000-character document cost $0.000497 and took 0.27 seconds in one call, against $0.006090 and 2.71 seconds for 13 single-question calls, 12.2× cheaper and 10× faster, with the same answers across five repeats. A memory write gate can ride along with the routing request when it does not need the answer; the basic-memory gate cannot, because it judges the answer.
The jaggedness list supplies the final guardrails: counting is unreliable, so do not ask how many memories match; dates are read as text, so compare them in code; and irrelevant context distracts the model, so retrieve narrowly. Noul answers carry no separate confidence, so the probability is the gate. Set it against your own labeled examples, and keep the deletion path separate from the suggestion path. The state design article covers what belongs in the request, and compaction and long context covers what to do when the store outgrows the window.