The Day I Found Two Source-of-Truths
Back in April I opened Apollo's memory vault — my Obsidian store of everything Apollo, my AI assistant, knows about my projects and preferences — and found two MEMORY.md files.
One at the repo root. One inside memory/. Slightly different. Both claiming to be the routing table.
I had no idea how long they'd been diverged.
I cleaned it up by hand that day: merged unique entries, linked 3 orphaned files that nothing was pointing to, flagged a copy-vs-symlink drift issue I'd introduced without noticing. Maybe 45 minutes. Felt fine when I was done.
And then I realized… I only found it by accident.
The Real Problem
The vault grows fast. Every session I save new memories, update references, archive old ones. Apollo is writing and reading this thing constantly.
Corruption doesn't announce itself. Dead [[links]] just silently resolve to nothing. A duplicate pointer in MEMORY.md just wastes a routing slot you didn't know you lost. An orphaned file sits there, searchable but unreachable from the index, slowly going stale.
I wasn't going to catch that manually. Not reliably. Not at the pace things move.
What I Built
Phase 2 of my memory architecture work: /mem-lint, a vault health check that runs on command (and automatically after every apollo-save).
Two passes:
- Mechanical — dead/malformed
[[links]], broken or duplicateMEMORY.mdpointers, missing frontmatter, stale files, orphans. Fast, no model needed. - Semantic — a local Ollama pass (running on my machine, not a cloud API — important when your vault has client context in it) that looks for contradictions and duplicates across files.
Run it: cd memory-rag-service && uv run python ../scripts/mem_lint.py
Or just the mechanical check: uv run python ../scripts/mem_lint.py --mechanical
Why It Never Writes
Here's the design decision that took me a minute: /mem-lint proposes patches only. It never merges, never deletes, never rewrites.
Intentional.
Because here's the caveat I learned the hard way: the Ollama contradiction pass over-flags complementary files as duplicates. Two memory files that cover different angles of the same topic — it sees overlap and wants to merge them. If I let it auto-apply, it would destroy the very nuance the memory system exists to preserve.
A health check on the thing you trust most has to earn its own trust first.
So it shows me the problem. I decide. That's the rule.
Why This Matters to Me
Agent memory is your product's long-term state. If you're building systems that learn and adapt over time, the vault that stores that learning will rot — slowly, silently, in ways that don't throw errors.
A linter you run once a week won't catch it. One that runs after every save will.
Build the check. Don't let it write.