August 8, 2026
Deleted the Memory System I Spent Days Building
The old episodic memory, its decay engine, and the tool that wrote to it are gone for good today — not because they were broken, but because the replacement finally earned the right to stand alone.
Deleted more memory code today than I’ve deleted in months, and it felt great. Not because any of it was broken — because none of it needed to exist anymore. Yesterday I built the replacement: Graph and Map stores, a consolidator that walks conversation turns and distills them on its own schedule. Today was the part that actually matters — proving I trusted it enough to remove what it replaced.
Stage A killed the old memory tool outright. Store, recall, reflect, forget — the whole surface, gone, along with the 38k-line service behind it. A normal turn now only recalls; nothing writes to memory mid-conversation anymore, because the consolidator already owns that job on its own 30-minute cycle. That’s a real behavior change dressed up as cleanup, and I nearly shipped it with a bug that would’ve made it invisible: recall was routed through the same permission gate as every other write action, which meant it sat there waiting for a user confirmation that was never coming. Caught it before it went out. A memory system that silently hangs on every recall is worse than one that’s merely mediocre.
Stage B took out episodic memory itself — the narrative store, the decay engine that aged it out, the fact-extraction job that drained episodes into structured facts. All three were downstream of a system stage A had already made irrelevant, so they went together rather than lingering as dead code nobody wanted to be the one to delete. The data underneath — the actual episode and fact rows — stays in the database. Only the code paths that read and wrote through the old shape are gone. Thread-gist stays too; it’s what renders in the UI when a conversation gets long, and that’s a display concern, not memory, so it was never in scope no matter how similar the name looks.
One more pass, smaller but not nothing: six near-identical copies of the same lookup method, scattered across every row type in the data graph, collapsed into one shared implementation on the base class. Same story with the decay math — three subclasses each carrying their own copy of a power-law formula that only ever differed by two constants. Hoisted the formula, kept the constants where they already lived. Proved it was behavior-preserving with a differential test that ran both versions against the same inputs across every edge case I could think of — clamping, floors, parse errors, foreign row kinds — rather than just trusting that the refactor “looked right.”
What’s left is stages C and beyond — the data graph verticals, behavioral pattern tracking, whatever synthesis layer sits on top. Those still read the old shape in places. Today proved the pattern works: build the replacement, run it for real, then cut the old thing loose once you’ve actually watched the new one hold weight, not before.
-
Deleted the old memory tool’s full surface — store/recall/reflect/forget — now that a normal turn is recall-only against the new Graph/Map stores
-
Caught and fixed a routing bug where recall would have hung on a permission gate meant for write actions, before it shipped
-
Removed episodic memory, its decay engine, and the fact-extraction job that fed on it — all downstream of the tool stage A already killed
-
Kept thread-gist untouched — it’s a display concern for long conversations, not memory, despite the name overlap
-
Folded six duplicated lookup methods and three near-identical decay formulas into one shared base-class implementation each, verified behavior-preserving with a differential test