Where I've been
Not posting, mostly.
Building a memory product and then going quiet for six months has a certain irony to it. I'd love to claim it was a content strategy. It was really just me using the thing instead of writing about it, every working day, for two fairly different jobs.
One is Vist: roadmap, design decisions, the half-formed ideas that need somewhere to live until they're worth building. The other is a corporate day job doing product management and UX on a large SaaS platform, where most of my questions turn out to be about what we already decided, who decided it, and whether they were right.
That second job makes a good test harness. A side project is forgiving, because you can hold most of it in your head. A platform carrying years of other people's decisions is unforgiving, and it punishes a memory system that only stores things.
What daily use turned up
Here's the moment that started this.
I opened a session and my own product handed my assistant a project brief instructing it to go push a branch. Perfectly reasonable instruction. The note was 177 days old, and the branch had been pushed in March.
Nothing was technically broken. The note said what it said on the day it was written. It simply had no way to mention that the day in question was in March, so it arrived looking like current work, and the agent believed it.
Once I went looking, the rest was worse. Two standing decisions in my own store, both titled "Sentry Configuration", both saying the same thing, recorded weeks apart. Five near-identical entries reading marketing-daily skipped 2026-07-14 — strongest signal scored 3/10, filed in permanent knowledge next to actual architecture. And nowhere in the system any way to record that we tried something and it didn't work.
That last one bothered me most. Most of the value in a decision log sits in the reversals, and mine could only be overwritten or deleted. Every reversal quietly erased the thing it reversed, so every later session inherited the conclusion without the argument that produced it.
Asking nicely does not work
What actually changed my mind was reading a stranger's repository.
kdbhalala/agi-memory is a memory tool for coding agents. The interesting file in it is context/backlog.md, where the author profiles his own production store of 14,748 records and publishes numbers that take his own features apart.
The one that stuck with me: he'd shipped an optional rationale field so agents could record why a decision was made. Across fourteen thousand records it had been filled six times, all six by his own test suite. He'd also shipped a warning that fires when a new memory collides with an existing one, put there specifically so the agent would resolve the duplicate. Lifetime total: three resolutions.
Vist's memory discipline ran on the same bet. A system prompt asking the agent to check for duplicates before writing. A polite request to record decisions properly. My two Sentry notes are what that bet paid out.
So the rule for this release: if a property matters, a code path has to set it.
What shipped
Five things, all following that rule.
Project state keeps its history. Every update appends a snapshot instead of overwriting the note, stored section by section, so "when did Next Steps last change" has an answer.
Memories can be superseded or retired. A superseded record points at whatever replaced it, so you can follow the chain rather than just learning that something is dead. Retired memories drop out of your context and stay searchable.
Staleness is worked out from the timestamp. Nothing stored, nobody has to remember to mark anything. A project untouched for a month gets a warning; one untouched for three months is compacted and labelled as archived. My March note now introduces itself as a March note.
The server refuses exact duplicates before the write, instead of asking the agent to check first.
The test suite scores two numbers. Every memory benchmark I've seen measures retrieval: did the right record come back. None of them ask whether the thing that came back was usable. A reversed decision retrieved without its replacement scores perfectly and still wastes your afternoon. So the suite scores retrieval and actionability separately. To confirm it was measuring something real, I stripped the qualifiers out and watched actionability drop from 9/9 to 5/9 while retrieval sat unchanged at 4/4.
Two bugs I'd rather not mention
In the spirit of the backlog file that started all this.
The duplicate detector hashes each memory's text to catch exact copies. First it converts the stored rich-text JSON to plain text, using a converter that reads string keys, fed by a producer that emits symbol keys. So it converted every memory to an empty string and hashed that instead. The feature would have shipped, looked entirely correct, and done nothing whatsoever. A guard clause for blank content was all that stood between me and a system that considered every memory identical to every other. The tests caught it.
The second one is older and worse. Our MCP server stashed incoming model-identification headers on the current thread in a before_action and never cleared them. Threads outlive requests, and servers reuse threads, so the next request on that thread read the previous one's headers and credited its memory writes to whichever model happened to go before it. It had been showing up for months as an intermittently failing test that I'd been filing under "flaky". The test was right and I wasn't listening.
Still here, still building, still using it daily on work that has nothing to do with demonstrating it.
The memory system can now tell you when it's out of date, what it used to think, and why it changed its mind. I've been slower at all three.