DEV Community

Cover image for AI Agent Memory Rots Silently — Audit Yours in One Command
Second Brain Starter
Second Brain Starter

Posted on

AI Agent Memory Rots Silently — Audit Yours in One Command

Last week I published Verified Memory Vault — a free Obsidian vault that gives Claude Code, Codex or Gemini CLI persistent memory through a plain CLAUDE.md boot file and an append-only MEMORY.md. It works. But after running it for a few weeks, something became obvious:

Memory systems don't fail loudly. They rot silently.

Nobody deletes your agent's brain in one dramatic afternoon. Instead:

  • A note gets renamed and three [[wikilinks]] die — nobody notices for weeks.
  • Someone (you, or the agent during a "cleanup") rewrites a memory line without its date. That line is now unauditable: you can no longer tell what the agent knew when it made that decision last Tuesday.
  • The inbox folder grows to 40 unsorted files because capturing is easy and sorting is work. The agent reads the junk into its context every session.
  • And then there is the dramatic version anyway: an over-eager cleanup command runs git rm over half of MEMORY.md, the commit goes through, and the knowledge is gone. This is not hypothetical — it is the documented way agent setups die.

A folder structure that can't detect any of this isn't a memory system. It's a landfill with good intentions.

Two scripts, zero dependencies

So the vault ships with two small Python tools. No pip install, no Node, no plugins — if you have Python 3, you're done.

1. memory_check.py — the honest report

python3 tools/memory_check.py
Enter fullscreen mode Exit fullscreen mode

It scores the vault's health out of 100 across four dimensions:

  • Protocol violations — undated lines in MEMORY.md, missing daily notes for active days
  • Dead links — every [[wikilink]] gets resolved against actual filenames
  • Inbox pressure — how much uncaptured junk has piled up in 00_Inbox
  • BloatMEMORY.md growing without consolidation

The output is a score, a list of concrete problems with file names, and an exit code (0 healthy, 1 degraded). That exit code matters more than it sounds: you can wire the check into CI, a cron job, or the end of your agent's session loop, so the system audits itself instead of relying on you remembering to care.

Here's what a degraded run looks like:

memory_check: 80/100 (DEGRADED)
  [links]   DEAD: [[weekly-review]] -> no such note (referenced in 01_Daily/2026-08-21.md)
  [protocol] MEMORY.md line 14: entry without date prefix
exit code: 1
Enter fullscreen mode Exit fullscreen mode

Eighty points sounds fine until you realize each deduction is a fact your agent will misremember or miss.

2. memory_guard.py — the seatbelt

If you keep the vault in git (you should), this becomes a pre-commit hook:

ln -s ../../tools/memory_guard.py .git/hooks/pre-commit
Enter fullscreen mode Exit fullscreen mode

From then on, any commit that deletes a large share of MEMORY.md gets refused:

memory_guard: REFUSED
  MEMORY.md: 31 of 44 lines deleted (70%)
  Mass deletion of the memory file looks like an accident.
  If it really is intentional, split it into smaller commits
  with an explicit reason in the message.
Enter fullscreen mode Exit fullscreen mode

The guard doesn't make deletion impossible — it makes it deliberate. Legitimate restructuring still works; you just can't lose six weeks of agent memory to one fat-fingered command anymore.

Why not just use a vector database?

You can, and for some workloads you should. But most agents' persistent memory needs are smaller than the industry pretends: dozens of durable facts, not millions. Plain Markdown wins at that scale because

  • it's auditable — the agent's memory is readable in ten minutes by a human,
  • it's diffable — every change to what your agent "believes" is in git history,
  • it's portable — no lock-in, no export problem, works with Claude Code, Codex, Gemini CLI or anything else that reads a boot file,

and now, with these two tools, it's checkable — which plain text normally isn't.

Get it

The vault is free, licensed CC BY 4.0 (use it commercially, attribution only), and sets up in about ten minutes: download, open as an Obsidian vault, point your agent at CLAUDE.md.

Download Verified Memory Vault v0.9 (ZIP)
Source and updates: github.com/secondbrainstarter/verified-memory-vault

If you want a starter system for your own notes rather than your agent's, the companion project Second Brain Starter uses the same philosophy — three folders, no plugin zoo, working in ten minutes.

Question, feedback or an idea? Write to geld.hamster@gmx.net — every mail is read.

Top comments (2)

Collapse
 
secondbrainstarter profile image
Second Brain Starter

Good point — and it is actually covered: the cap is absolute, not proportional. The guard refuses a commit once more than a fixed number of lines are removed from any memory file in one commit (max-deleted-lines flag, default 10), on top of the whole-file deletion count. The 31-of-44 example in the post trips both at once; in a 12-line MEMORY.md the same change would already be refused at the absolute limit, so small vaults do not slip under a percentage threshold.

The exit-code-as-contract framing is exactly how it is wired: memory_check.py returns 0 healthy / 1 degraded, so a shutdown hook or CI step gates on the code while the score itself stays informational.

Different defects mapping to different risk is a fair refinement though — right now a dead link and a line-budget breach both degrade to non-zero, and treating provenance defects (undated entries) as a separate, stricter class would be a cheap improvement.

Collapse
 
marcusykim profile image
Marcus Kim

An 80/100 score that still contains a dead [[weekly-review]] link and an undated MEMORY.md entry makes the failure mode very concrete: the system looks healthy while provenance is already slipping. I'd treat the score as a dashboard but make the degraded exit code the real contract for CI and session shutdown, since different defects carry very different operational risk. The 31-of-44-line pre-commit refusal is a useful seatbelt, though an absolute deletion cap would also catch smaller memory files where a damaging change never crosses the percentage threshold.