History still matters. I just don't want it to be the default context for agents editing the present system.
A coding agent will read whatever you...
For further actions, you may consider blocking this person and/or reporting abuse
The line doing the most work here is "facts that carry their own freshness" — but I'd push on where that guarantee actually holds. Repo-as-truth fixes human-time drift (the doc rots between commits while the code moves). It doesn't fix within-a-run drift: on a multi-step change the agent reads the current schema/module graph at step 1, its own edits at steps 2–4 move them, and by step 5 it's acting on a structural snapshot as stale as any Markdown — except now the stale fact came from the repo, so it wears the trusted clothes. Dedup removes the second place a fact can rot; it doesn't make the agent re-read the place after it changed it. So the discipline isn't only "fewer spots a fact can rot," it's "re-derive structure after each edit that could have moved it."
Second push: "a boundary in the build is architecture" only holds for the boundary classes your toolchain can express — import graph (eslint), public surface (exports), data shape (schema). A lot of what actually ends up in CLAUDE.md are semantic invariants no linter has a rule shape for: "never write the ledger outside a settlement event," "this counter is monotonic," "this id is only minted in one place." There's no wall to move those into. So the advice/architecture table needs a middle row: what you can't prevent structurally, you make detectable structurally — a runtime assertion, a property test, an audit query that fails loudly. Otherwise "move it into the build" silently drops every rule the type system can't encode back into hope.
And the map is itself a fact that rots. A "Sources of truth" block pointing at packages/database/schema becomes a confident lie the day someone moves the schema — it survives change only if CI fails when any path in it doesn't resolve. An unchecked map hasn't escaped drift; it's just relocated it one level up, from stale description to stale address.
Thanks for the sharp questions. On the guarantees, my answer leans on experience and intuition more than anything I can prove — but let me respond.
On the first point: keeping the repo as an SSOT doesn't happen on its own. I'm consciously maintaining it throughout daily development — running QA and tests right after a feature lands, and treating refactoring for agent-legibility (naming, directory structure) as carrying the same weight as the feature work, done in parallel. I've tried to make that happen structurally. But your reframing is exactly right: it's not just "reduce the places a fact can rot," it's "re-derive the structure after every edit that could have moved it." Within-a-run drift can only be killed there.
The second point is just as sharp. The "middle row" — what you can't prevent structurally, you make detectable structurally — is exactly right, and in real operation it's non-negotiable. For declarative DB changes I'll reach for Atlas or Drizzle, but separately I stand up an intermediate representation that surfaces the live-vs-local schema diff, so the hazard shows up structurally. The type system matters, but it alone doesn't build a paradise for the agent.
Third: the map rots too. That's exactly why a "Sources of truth" block only earns its keep once CI fails the moment a path stops resolving. An unchecked map hasn't escaped drift — it's just moved it up a level. To keep it from degrading from a stale description into a stale address, I pair the map with a mechanism that inspects and maintains it.
What I wrote was the opening mindset; how I build those decision mechanisms to make the whole repo function as an SSOT is what I want to write about next. Grateful for the precise comments — they pushed my thinking further.
The three mechanisms — QA after a landing, the live-vs-local schema-diff IR, CI failing when a path stops resolving — are all the same good move: turn a thing that could silently rot into a thing that fails loud. The residual I'd point at is that each detector has a trigger, and the trigger fires on your repo moving. That covers within-repo drift cleanly. The edge it can't see is a fact whose referent lives outside the repo — a live schema, an external contract, anything the commit didn't touch — which can drift while the repo sits perfectly still and nothing trips. That's the boundary on "the repo is the context": the repo can carry freshness for facts it fully contains, but for facts about external state it can only carry an address, not a guarantee. The version where those facts carry their own freshness is lazy rather than eager — the binding points at the external referent's own version or hash, so the staleness surfaces at read time when something actually uses the fact, instead of depending on a maintenance pass firing at the right moment. Eager detection covers the part you commit; the read-time re-check is what covers the part your CI never sees move. Looking forward to the next post.
Exactly — that external-referent boundary is the part I was missing.
The repo can keep facts fresh when it fully contains them. But for anything outside it, the repo mostly carries an address, not a guarantee. CI can tell me the pointer still resolves; it can’t prove the thing behind it still means what the repo thinks it means.
So the split seems to be: pull into the repo what can be made eager-checkable, and use read-time binding for the genuinely external remainder.
That’s the line I want to make concrete next. Thanks — this sharpened it a lot!
The piece I'd nail down to make it concrete: bind to the referent's meaning, not its address. CI's "the pointer still resolves" is a liveness check; what you want at read time is an equivalence check — did the thing behind the pointer still mean what the code assumed. Cheap version: hash the part of the external contract you actually depend on (the schema shape, the response fields you read, the function signature) at the moment you write against it, store that hash next to the binding, re-hash on read. Pointer resolves but hash moved = semantic drift that path-resolution CI never sees.
The whole difficulty then collapses into one choice per dependency: what's the minimal projection of the external thing your code relies on. Hash too much and every cosmetic upstream change trips a false alarm; too little and a real breaking change slides under the hash. So "make it concrete" reduces to, per external referent, naming the smallest surface you'd want to be told changed — and that naming is the one piece the repo can't do for you.
That makes sense. Hashing the dependent slice of the external contract feels practical enough to experiment with.
In my current projects, I’ve been keeping external dependencies fairly limited, or at least avoiding APIs and tools whose contracts are unclear, so I haven’t hit this failure mode too hard yet.
But your framing gives me a good way to test it: for each external referent, what is the minimal semantic surface I actually depend on, and can I detect when that surface changes?
I’m going to experiment with that.
This is the exact thing I converged on, and your "a boundary in CLAUDE.md is advice, a boundary in the build is architecture" line is the cleanest statement of it I have read.
Two things from running this on consensus code, where a wrong edit forks the chain rather than breaks a build:
The "agents are loyal to drift" point is even sharper than it reads. I had two parallel explore agents confidently report a persistence layer used string keys when it used byte-string keys, and cite line numbers for it. The only thing that caught it was making the agent re-read the actual source before trusting the claim. Re-grounding against the present repo each phase is not just efficiency, it is the difference between a real fix and a confident wrong one.
The other half I would add: the same structural-over-advice idea applies to the agent's own process, not just the repo. Telling it "do not skip verification" is advice. Forcing each phase to fail a test before the fix exists, and gating the commit on the suite turning green, is architecture. The repo holds the present truth, and the test suite holds the proof the change is correct. Both sit closer to the system than any instruction about it.
Same caveat as yours on the models getting better underneath all this, hard to separate. But the direction has held for me too.
The point about applying the same idea to the agent’s own process really clicks for me.
With tools like Claude Code, some parts of the workflow can already be declared and controlled structurally, while others still can’t. But as Claude Code and Codex make local logs easier to capture, it feels increasingly possible to improve these processes from actual data rather than intuition.
I’d like to dig into that more too: how to observe exactly where drift or false confidence enters the workflow, and then turn those observations into constraints like re-grounding, required failing tests, or commit gates.
The "improve the process from data, not intuition" framing is the part I want to push on, because I have been living it this week and the data is messier than it sounds.
The honest problem: the moments where false confidence enters are exactly the moments that look clean in the logs. A subagent reporting a confident wrong answer leaves the same trace as a correct one. So the local logs tell you what happened, not where judgment quietly went wrong, and the drift you most want to catch is invisible to a log scan. What has actually worked for me is making the constraints non-optional rather than data-triggered: a required failing test that has to fail for the right reason before any implementation, re-grounding against the file every phase even when the window should be current, and a commit gate the operator holds. These do not wait to observe drift; they remove the chance for it. The gate fires whether or not the logs would have flagged anything.
Where I think your data idea pays off is one level up: not detecting drift live, but measuring after the fact which gates actually caught something. If a re-ground step never once changed an edit across fifty phases, it is theater and I can drop it. If the failing-test gate catches a wrong fix one time in ten, it earns its cost. That is the loop I would want from the logs, auditing the constraints, not trying to spot drift in real time.
I agree. The first priority is to make failure harder through mandatory gates and explicit decision mechanisms. Logs should not be the main defense against drift.
Where I think AI-readable logs still matter is afterward: they let us audit which gates actually changed outcomes, which ones became theater, and where uncertainty still slipped into action.
So: control mechanisms first, readable evidence second. Not live drift detection, but evidence-based improvement of the constraints.
"Control mechanisms first, readable evidence second" is the right ordering, and the second half is where the real discipline lives, because auditing which gates became theater is harder than it sounds. A gate that never fires reads two ways: either it is redundant, or it is covering a failure that has not happened yet. The logs cannot tell those apart on their own. What I have started doing is dating each gate and only retiring one after it has had real chances to fire and did not, across genuinely varied runs, not a quiet week. Otherwise you delete the smoke detector because the house has not burned down. So the evidence-based improvement you describe needs a second axis beyond "did this gate change an outcome": how many real opportunities did it have to. That is the number that separates theater from insurance.
I think there's a lot of truth in this.
One of the things I've noticed with AI projects is how quickly teams jump to building memory systems, vector databases, and retrieval pipelines before they've exhausted the context already in the repo.
The code, tests, commit history, issue discussions, ADRs, and docs often contain far more institutional knowledge than we give them credit for.
That said, I've also found that the repository usually tells me what the system does, but not always why it ended up that way.
Those answers often live outside the codebase entirely.
That's one of the reasons I've become interested in Memory as Infrastructure. The repository is absolutely part of an organization's memory, but it's usually only one layer of it. The challenge isn't storing more context—it's preserving the context that would otherwise disappear.
I agree with the point about teams reaching for memory systems or RAG before they have exhausted the context already present in the repo.
My experience is similar: the first priority is to make the repo structurally legible. When the current source of truth is clear in the code, tests, schemas, boundaries, and naming, Claude Code can already perform surprisingly well. But many teams try to improve the surrounding memory/retrieval layer before shaping the repo itself.
That said, I’m also in favor of the right kind of memory system. Claude Code’s current memory mechanism is still a bit awkward for me, and I’d like something more explicit and structural around the codebase. Maybe not a full SSOT, but a clearer layer of memory that lives near Git and the repo, with enough structure for agents to read and maintain it safely.
I increasingly feel that Git-adjacent tooling itself needs to evolve for AI agents.
“History is meant for humans. The current source of truth belongs to those who work in agencies.” This statement is truly brilliant. It’s full of profound wisdom. I’ve also noticed that agents often get misled by outdated information when they read a lot of documents. This phenomenon is quite common.
Thanks. I’m still practicing this day to day, testing what actually works and refining the approach as I go. I want to keep improving the repo and workflow so agents can rely less on stale context and more on the current source of truth.