After the intent gap
Three gaps that build up quietly once every feature is understood: comprehension, coherence, continuity. Why going back is wrong, and what to spend instead.
More than once before 2024 I took over a client’s system that had passed through several generations of developers, none of whom still worked there. The documentation was the code. When the client wanted a new feature, the request was often one sentence: make it work like screen X. Nobody could say what screen X did. Reading it meant tracing nested conditionals and exception handlers with no comment on why any branch existed, and git blame did not help: the commits that last touched those parts had nothing to do with what they were for. We could not even tell whether the data they produced was already wrong. So we wrote the feature on a partial understanding and waited for the testers to tell us.
The history was all there. The reasons were not. Not one line of that code had been written by a model.
The intent gap is a problem of a moment: how one request gets understood correctly. Suppose you solve it. Good specs, tight gates, every feature right. The next problem is a problem of time and scale: a system that is right piece by piece and slowly stops being understood, consistent, or described. Multiply the volume of code and divide the number of people who understand it, and the situation above stops being a story about a neglected legacy system and becomes the default. It has three faces.
Comprehension
Code that exists and that nobody understands. People have started calling it cognitive debt, and Thoughtworks’ radar has held complacency with AI-generated code in its Hold ring since 2024. Writing code used to be the process by which understanding formed: when you finished, you had a model of the system in your head. When a model writes most of the code, the amount of code grows and the amount of understanding in heads does not. Every pull request is reviewed to standard, and nobody holds the whole picture. The bill arrives at the worst time, in a production incident, when the question is not whether the code matches the spec but how this system actually works, and the person who could answer does not exist.
Coherence
Right locally, fraying globally. Each agent optimises inside its task; no agent holds the architecture. The result is three ways of handling errors in one codebase, duplicated logic, abstractions stacked on abstractions. Each pull request passes the gates, because the gates check correctness and not consistency. Architecture erodes along the lines the current rules do not encode: a fitness function catches the drift someone has already written a rule for, and the next article argues for writing more of them, but the drift nobody anticipated is only visible to a person holding the big picture, and that person is being eaten by the first gap.
Continuity
The intent artifacts themselves rot. The specs, the conventions file, the glossary, everything built to close the intent gap is a document, and documents drift from reality. Spec-code drift means the machinery that closes the intent gap is silently broken: the agent reads yesterday’s conventions and generates code for a world that no longer exists. On the human side, skill atrophy and a broken pipeline of juniors mean the organisation’s capacity to understand falls at the moment the need for it rises.
Together these are the problem of the shared mental model. The intent gap asks whether the machine understands you. This asks whether you still understand the system. It is a degree harder, because the intent gap has a short feedback loop, a wrong reading shows up in review or in acceptance, and these three accumulate in silence and show only when they are large.
Going back is not the answer, with two corrections
The tempting conclusion is that these are human costs to be traded for letting the model in deeper, and that the alternative, returning to the days when one developer knew every model, every flow and every quirk of the system, is not a real option. Reverting is indeed wrong. But two things in that framing lead to bad design decisions if left standing.
First, the developer who knew everything never existed for long. Systems outgrew a single head decades ago, and the industry’s answer was distributed understanding: modules, ownership by area, decision records, runbooks, on-call rotation. “It is all in A’s head” was always a bus-factor risk, not a golden age. So decision records, ownership maps and docs-as-code are not the old way to be avoided. They are the non-nostalgic tools for a problem that is old and has been made a degree worse.
Second, this is not a trade-off to accept. It is a trade-off to price, and to spend selectively. Compare the earlier abstractions. Developers stopped understanding assembly when compilers arrived, and stopped understanding hardware when the cloud did, and that was fine, because the layer underneath was sealed, deterministic, and under a contract you could trust. Nobody debugs the compiler’s output. Generated code is not that layer. It sits at the layer you operate, the layer you debug at two in the morning, the layer you answer for. As long as you have to debug and warrant it, you are not permitted to stop understanding it the way you stopped understanding the compiler.
The replacement for “accept the trade-off” is a formula: the understanding you may let go of in a zone is proportional to the maturity of verification in that zone. Dense tests, strict types, good observability, small blast radius: let go freely, shallow understanding is enough. The core domain, money, data, security: human understanding is an operating requirement there, not a luxury. The risk tiers you already use for review apply to the understanding budget too. Letting go everywhere is a mistake. Letting go by address is design.
And the target is not “understanding in people’s heads”. It is understanding recoverable on demand, by people, artifacts and models together. This is where the bet gets interesting, because the model is not only the cause of lost understanding; it is the cheapest tool for regenerating understanding there has ever been. Ask the codebase, any time. But the bet has a known limit. A model reading code answers what and how. It answers why, why this design, what was tried and failed, only if someone wrote that down. The minimum investment that makes the bet safe is to have the agent leave a decision record with every change, while the why still exists in its context.
That is what sets the understanding minimum, and it is not a philosophical quantity. Write down what you will have to answer when the system fails, and who will be asking. Make the list concrete enough to be checked: diagnose the overnight job that failed before anyone has opened a terminal; explain why two invoices for the same order carry different tax; move the billing cutoff without breaking the proration that hangs off it. Three obligations, three zones where comprehension has to be real, and everything outside them can stay at the level of knowing where to look. Nobody will ask you to explain pagination on an admin screen.
Most teams never get a handover date. They get resignations, a reorganisation and an on-call rotation, which ask the same questions on a worse schedule. So write the reason down while the decision is live. A reason written a week later is a reconstruction.
In Rindo that reason is a page with its full history, who changed what, when, through which channel, and nothing rewritten afterwards, and a page can be linked to the task that made the decision, so the why survives the people who knew it.