• The Work Was Always About Understanding

    A robed scribe pauses with a quill over blank parchment in a gray stone room with a blue arched window.

    A clean diff is not a good change.

    It can look like one. Idiomatic and formatted, the tests green. Good code by every local measure. And still nobody meant it.

    A diff is only the code: does it read well, does it run, do the tests pass. A change is the decision behind it — someone understood the system, saw why it should move, and moved it on purpose.

    That understanding used to come almost by accident. Writing code by hand had a side effect: you went looking for the place where the behavior lived, and on the way you rubbed against the system — the old test guarding a bug everyone had forgotten, the interface that only makes sense as a truce between two teams.

    Our client code had a helper called parseIdsAsStrings, with a standing joke attached: the spec says those ids are numbers, we just refuse to read the spec. It pulled ids out of the raw response text before JSON.parse could touch them; there was, of course, a cleanup ticket. Then a refactor dragged me through that corner, and tracing its call sites turned up what the name was quietly remembering: the backend hands out 64-bit ids, JavaScript silently rounds anything past 2^53, and one night — the commit is timestamped 4 a.m. — neighboring ids had started collapsing into the same number. The function was ugly because the incident it survived was ugly. The cleanup ticket died that afternoon, and I came out knowing more about the system than the refactor required.

    None of that guaranteed understanding. People have always shipped code they never understood: paste jobs, framework incantations, the noble tradition of flipping a boolean until production stopped screaming. But the friction was there, and understanding tended to grow in it. You arrived at the diff carrying reasons you had picked up on the way.

    Now the artifact can arrive without the path.

    An agent hands you a finished patch. It is polished and tested, with a tidy explanation attached. The code is there. The walk that used to deposit the reasons is not. The person holding the merge request can say what the patch does, but not why it took this shape and not another, or what it will cost to keep alive. Useful, and dangerous for the same reason: it looks complete.

    The code itself is the least of it. Often it is fine; sometimes it is better than what you would have written yourself; and when it is bad, that is a familiar problem with familiar tools — linters, tests, review. The real problem is plausible code with no intent behind it. Not wrong. Unmeant. A change nobody decided on, and nobody can answer for.

    That is worse than a bug, and not by a little: a bug leaves the intent standing — you find it, you fix it, the repair has something to be true to. Missing intent leaves nothing to repair. That helper is exactly what an unmeant patch deletes first: it looks wrong, the spec itself agrees, and no test will miss it, because no fixture ever ships an id past 2^53 — and the bill arrives months later, mid-incident, when the failure it was absorbing comes back and nobody remembers there ever was one.

    So the center of gravity in review shifts. It used to be a defect hunt: find the bug, name the smell before the fix needs a migration plan. Bugs did not resign when autocomplete got promoted — but they are the part we already have tools for. The hard part is finding out whether anyone understands the change. Anyone at all: the model that wrote it can summarize it fluently without understanding a line. Reviewing a generated merge request, you are not so much reading code as reconstructing a train of thought that may never have run.

    I have merged patches like that. I could say what they did. Nobody asked why they took the shape they took, and I remember being glad nobody asked.

    So the contract worth asking for is not “here is my diff.” It is “ask me anything about it.” What breaks if we revert this? Why this shape and not the obvious one? What did you try first, and why did you throw it away? What will it cost to keep alive? The answers are the part of a change Git cannot show.

    The agent will cheerfully generate those answers too, of course — a plausible problem, plausible constraints, plausibly rejected alternatives, all in the same even, confident voice. Which is why the contract cannot be paperwork stapled to the merge request. It is closer to an oath: the test is not that the answers exist, but whether a person holds up under the follow-up question that was not in the template — because the person is the one who will still be in the room when the change fails. The transcript does not attend the incident.

    The pride was never in the typing. That was labor, and the machine wins that race before lunch. The pride is in understanding the system well enough to know whether this change belongs in it.

    That was always the work. Peter Naur wrote it down in 1985: a program is a theory held by the people who built it, and the text without the theory is dead. AI did not create the problem. It made the theory-less text cheap, and stripped out the friction that used to smuggle the theory in for free. Now you have to go get it on purpose.

    Sometimes that means shipping the patch with your name on it, ready to answer for it.

    Sometimes it means saying no to a perfectly clean diff.