Jerry Orta
← Blog

What the Repository Remembers

An agent's accuracy is bounded less by how well it reasons than by what it is holding while it reasons. A monorepo of any real size cannot be held at once, so every session is an act of selection: some few thousand tokens of the repository arrive, the rest stays out, and the quality of the work is decided largely by that choice. Architecture is what makes the choice well. Arrange the repository so the relevant material is addressable and the irrelevant material is silent, and an agent produces on-pattern work at a fraction of the cost; leave it unarranged, and the same agent guesses fluently.

The agent-files note describes how the code's own instructions are arranged for that selection — one small always-loaded core, a routing table into a deep-dive library, thin pointers colocated with the code they govern. What that note leaves out is the more interesting half. Not everything worth telling an agent is a statement about how the code should be written.

Three registers

Context that helps an agent falls into three registers, and they are not interchangeable. There is what should be true — the standards, constraints, and conventions that make a change idiomatic here. There is what turned out to be true — the deployment that failed for a non-obvious reason, the framework behavior no document predicted, the correction a person gave once and should not have to give twice. And there is what is about to be true — the plan for work not yet done.

Documentation, memory, and plans. Most setups keep the first, improvise the second, and leave the third in a tracker. Keeping all three, in separate stores chosen for what each register actually is, is what makes complicated work repeatable.

Documentation is normative, and belongs with the code

The first register is law. It says how a component is authored, which patterns are forbidden, what a review must check — and it is true by decree rather than by observation, because it describes the standard rather than reporting an event. Law of that kind belongs in the working tree: tracked beside the code it governs, reviewed in the same pull request, and corrected when it goes wrong rather than discarded. It is also loaded by routing rather than by volume, which is the subject of the note above and is not worth repeating here.

Memory is observational, and is a different kind of claim

The second register is not law but evidence. A memory records something learned at a particular moment: that a shared function bundle forces a minimum memory allocation on every callable, that a package manager's incremental install fails where a clean reinstall succeeds, that a stated preference is to route verbose subagent work to a smaller model. None of it is a rule anyone decreed. All of it is expensive to rediscover.

The shape is deliberately small. One fact per file, with front matter carrying a slug, a one-line description, and a type — user, feedback, project, or reference. The body links to siblings with [[name]], so the corpus accumulates as a graph rather than as a log, and a link written before its target exists marks the next thing worth recording.

Recall is routed exactly as documentation is. A single MEMORY.md index loads at the start of every session and holds one line per memory — a title and a hook, never the content — beside a router table that maps a domain to its own index file, loaded only when that domain becomes the subject of the work. The always-present cost is a page of addresses. The contents are paid for by the task that needs them.

One negative rule does most of the work of keeping the register clean: do not record what the repository already records. Code structure, past fixes, git history, anything already in the standards — none of it is a memory, because all of it is retrievable. What earns a file is what could not be derived from the tree: the reason behind a decision, the exception that contradicts a documented default, the failure mode that consumed an afternoon.

The registers also fail differently, and are therefore governed differently. A memory is dated testimony, so it is surfaced with its age attached and a standing instruction to verify it against current code before acting on it; a memory that has gone wrong is deleted outright. Documentation is never deleted for being wrong — it is amended, because the standard still needs to say something. Treating an observation as law is how a stale gotcha becomes an enforced rule.

Memory belongs in a repository of its own

One line of user-scope configuration points every session on this machine at one directory:

"autoMemoryDirectory": "~/Dev/agent-memory/memory"

That directory is itself a git repository, and its position outside every working tree is what makes it valuable. Nine checkouts of the same monorepo live on this machine at once — one per long-running effort, each on its own branch, with its own dev server and its own session history — and a tenth, unrelated repository besides. Every one of them reads and writes the same memory. A gotcha discovered while deploying from one checkout is present in the next session started in another, with no merge, no copy, and no person remembering to carry it across. Memory is scoped to the practitioner and the work, not to the working tree, which is precisely the scope at which most of it is actually true.

Git is the store for two reasons, and neither of them is sentiment about version control. The first is size: the corpus is a few hundred small files, which is well within what a directory handles gracefully, and a database would be infrastructure bought against a scale that does not yet exist. The second, and the one that decides it, is latency. Every read and write in a session is a local file operation with no network in the path — an index consulted at startup, a memory opened when the router points at it, a new file written the moment something is learned. Synchronization is deferred entirely to the end of the session, where a commit, a rebase, and a push cost nothing that the work is waiting on. A database would move that cost into the critical path and charge a round trip for every recall. The correct time to revisit the choice is when the corpus outgrows a plain directory; until then, the filesystem is both the faster store and the cheaper one.

Persistence is a hook rather than a discipline, because a discipline is the part that fails. When a session ends, a Stop hook commits the directory and syncs it:

git add -A
git diff --cached --quiet && exit 0
git commit -q -m "chore(memory): auto-update $(date '+%Y-%m-%d %H:%M') [$(hostname -s)]"
git pull --rebase --autostash --no-edit origin main || git rebase --abort
git push origin main
exit 0

Three properties there matter more than the commands. Rebasing before the push folds in whatever concurrent sessions wrote, which is what lets many checkouts share one store without coordinating. The unconditional exit 0 guarantees the sync can never fail a session — an offline machine simply pushes on the next run, since the commit is already safe locally. And stamping the hostname keeps the record honest about which machine learned what, which matters as soon as a second one is involved.

Plans are intentional, and get the same treatment

The third register lives in a second sibling repository, shared by the same checkouts on the same terms. Ticket content — description, implementation plan, acceptance criteria — is one markdown file per ticket at /.md, while the tracker keeps status and a stub that points at the file.

The economy is stark enough to force the decision on its own: the tracker's integration returns roughly five and a half kilobytes per issue and ignores any request to narrow the fields, whereas the same status read as a compact list costs about two hundred bytes per issue, and the plan itself is an ordinary file read. The principle outlasts the economy, though. A plan is the artifact a planning pass produces before any code exists, and a plan held as a tracked file is diffable, reviewable in the same pull request as the work it describes, and readable by the agent that implements it. The workflow note covers the mechanics of that split in full.

Why the separation pays

The dividend is precision rather than volume. An agent asked to do complicated work correctly needs a few hundred lines of exactly the right material, and every irrelevant page loaded alongside them both costs money and dilutes attention. Three stores, each with a small always-loaded index and a large addressable body, is how the right few hundred lines arrive while the other hundred thousand stay out.

Misplacement is what the separation prevents, and it is costly in both directions. An observation written into documentation becomes law: stale, normative, and enforced against work it no longer describes. A convention written into memory becomes invisible: exempt from review, absent from a colleague's clone, and unavailable to the pull request where it should have been argued. Sorting by register is not tidiness. It is the difference between a correction that propagates and one that quietly rots.

The pattern travels

The same three-layer shape runs in ngx-experiments, the public workspace where much of my design-system work lives, and the two are not perfectly aligned — the standards differ in places, and the memory router covers different ground. That divergence is the useful part of the evidence. What transfers between two repositories with different contents is not any particular file but the arrangement: a small always-loaded index of addresses, a periphery that stays silent until a task calls for it, and observation kept firmly apart from law.

A repository far too large to read is still legible to an agent, provided it knows what to say and when to say it. Most of that legibility is not written for the machine at all. It is the ordinary discipline of putting each kind of claim in the store built for it — and then letting a hook remember to save it.