# Retrieval was never the hard part. Staying in sync is.

Five 'codebase memory for AI' tools trended in a single week. Almost all of them solve retrieval — the easy half. Here's the hard half, and what it takes to stay correct as your code changes.

Five different "codebase memory for AI" tools trended on GitHub in a single week: code-context-engine, contextplus, sdl-mcp, marm-memory, and claude-mem. That's not noise. That's a category forming in real time — the market working out that AI coding tools are brilliant at reasoning and hopeless at remembering the specific codebase in front of them.

But look closely at what most of these tools actually do, and they're solving the same half of the problem. The easy half.

## Retrieval is the easy half

Almost every "give your agent memory of your codebase" tool is, underneath, retrieval: chunk the repo, embed it, vector-search the chunks at query time, stuff the top matches into the context window. You can build a passable version of this in an afternoon — there's a library for every step.

And it works, right up until your code changes.

The moment you rename a function, move a module, or change a signature, the index is quietly wrong. The embeddings still point at the old shape. The retrieved chunk still describes code that no longer exists. Nothing errors, nothing warns you — the tool just starts confidently answering questions about a codebase that has drifted out from under it. On a repo that ships every day, "indexed last Tuesday" is a liability, not a feature.

Retrieval was never the hard problem. Staying correct as the code moves is.

## The hard half: staying in sync

Think about what a useful memory has to guarantee. If you renamed `hashPassword` to `hashSecret` and deleted the old one, a note bound to `hashPassword` should die the instant `hashPassword` does. A summary that still references it isn't memory — it's a stale artifact wearing memory's clothes.

That guarantee is only possible if the memory is anchored to your code's actual *structure*, not to a bag of text chunks. A vector doesn't know `hashPassword` was renamed; it just knows some numbers used to sit near some other numbers. A symbol knows. A call graph knows. That's the difference between memory that decays gracefully and memory that lies.

## What structure buys you that vectors don't

SecondOS parses your repo into real structure — symbols and signatures, a resolved call graph (which function actually calls which, across modules), routes, and your database schema. From that it answers things retrieval can't:

- **`who_uses` / `impact_of`** — the real callers of a function and the blast radius of changing it, resolved across the codebase, not text-matched.
- **Drift detection** — code that writes a column your schema doesn't have, an env var read but never declared. The bug isn't in the file you're reading; it's in the gap between two files that were supposed to agree.
- **Notes bound to symbols** — a decision recorded against `hashPassword` is flagged stale the moment `hashPassword` is rewritten.

And when the structure genuinely can't be resolved — a dynamic dispatch, a receiver type that isn't knowable statically — SecondOS says `unknown` instead of guessing a plausible-but-wrong caller. A memory you can't trust is worse than no memory.

## Proof: docs that refresh on every push and cost nothing when nothing changed

Here's the same principle applied to documentation. SecondOS auto-writes a [living knowledge base](/docs/knowledge-base) — eleven documents (architecture, module reference, dependency map, API reference, data model, glossary, and more) generated *from* the code's structure and refreshed on every push.

The catch is that "refresh on every push" would be a token bill you pay forever. So each section is content-addressed by a hash of the slice of the map it describes. Push a commit that doesn't touch that slice, and the section doesn't regenerate — zero tokens. Most pushes leave most docs byte-identical.

And notice *which* docs these are. A generic summarizer can write an overview or a glossary. It cannot write a dependency map, an API reference, or a data model — those need a resolved call graph, parsed routes, and the actual schema. Structure again, not vectors.

## The honest numbers

We publish a reproducible [benchmark](/benchmark). For a single question on real repos, feeding an AI tool the structural *map* of the relevant files instead of their full source is **~5–9× fewer tokens per question** — same files, map versus body.

We also publish the graph-resolution rate per language, including the unflattering ones: Python around 60%, Ruby around 9%. We report the low number on purpose, because in this domain a wrong answer costs more than a missing one. "Honest but stuck" beats "confident but wrong" every time you're debugging production at 2am.

## And your source never leaves your machine

The thing that makes this safe to adopt: SecondOS syncs a structural *map* plus embeddings, never your code bodies. The signatures leave; the implementations stay local. You get memory your tools read over MCP without shipping your source anywhere.

## Retrieval was table stakes

The wave of codebase-memory tools trending this week is a good sign — the problem is real, and the market knows it now. But retrieval is where you start, not where the moat is. The hard, durable part is staying correct as the code changes underneath you. That's the part we built SecondOS around.

See [how the structure fits together](/product), [reproduce the benchmark](/benchmark), or read about the [living knowledge base](/docs/knowledge-base).
