montfort.dev
← essays

·6 min read·#ai #ai-augmented-engineering #craft #build-in-public

The immaculate programmer

A reply on Hacker News said the best human programmers would never make the mistakes AI makes. We built an entire discipline — code review, linters, postmortems — on the premise that they do. On the asymmetry of scrutiny, and the programmer we never were.

A few days ago I left a comment on a Hacker News thread asking where the programming profession is going. The poster had just closed a small company and visited a larger one, and what he found unsettled him: the code was no longer the source of truth, nobody was reviewing it line by line, and some developers were running five agent sessions at once without really reading the output. My reply was the argument I keep making — that the role has moved from programmer to engineer who directs programming agents, and that the failures we see come from trying to solve everything with a four-line prompt instead of keeping the engineering around the coding.

A reply came back that I’ve been turning over ever since. It pointed at the mistakes a model had made — a Cookie class shipped without a name field, a query that broke on two database rows sharing an ID — and landed on a single sentence: “the best human programmers absolutely would not have made those mistakes.”

That sentence is the whole essay. So let me take it apart slowly, because I think it’s doing something a lot of the thread is doing, and it’s worth seeing clearly.

First, the part that’s true

I don’t want to wave the thread away, because most of it isn’t fear — it’s something real, and I feel it too. There is a genuine cognitive debt that builds when the prompt becomes the artifact you keep and the code becomes exhaust you never read; you can lose your grip on a system you nominally own. There is the muscle that atrophies when you let the tool drive for months and then sit down to do it the old way and find your hands are slower than your memory of them. There is the exhaustion several people described — the feeling of fighting your tools, of shipping more while feeling less sure of any of it, of accountability getting blurry right when the volume goes up.

None of that is Luddism. Those are people describing a craft changing under their feet and naming what it costs, which is exactly the conversation we should be having. I want to be on record taking it seriously before I disagree with anything, because the next part only works if you grant that the worry underneath it is legitimate.

The programmer who never existed

Now the sentence. The best human programmers absolutely would not have made those mistakes.

Watch what happens around an AI error versus a human one. When a model ships a cookie without a name field, the error is captured, quoted, and passed around as proof that the tool is unfit — a clean little artifact of incompetence. When a person ships the same bug, it’s a Tuesday. It goes into a ticket, gets caught in review or not, ships or doesn’t, and nobody concludes that humans can’t be trusted to write software. The same defect means the machine is incapable in one case and we’ll fix it in the next pass in the other. That asymmetry of scrutiny is the whole trick, and once you see it you can’t unsee it.

Because here’s the thing we all know and somehow argue against when it’s convenient: we built an entire discipline on the premise that the best human programmers make exactly these mistakes. Code review exists because they do. Linters, type checkers, tests, CI gates, staging environments, postmortems with no blame attached — every one of those is infrastructure we invented because we assume competent, careful people will ship the off-by-one, miss the duplicate ID, forget the field. The immaculate programmer who would never — that person has never sat on any team I’ve been on, and I’d bet they’ve never sat on yours. We don’t protect against them. We protect against us.

The comparison is rigged

So the honest comparison was never AI-alone against an idealized human. It’s a managed process with AI against a managed process with humans — and both of those catch errors downstream, because that’s what the process is for.

What’s striking is that the reply made my case for me. The counterpoint to my argument was that good teams don’t hand each other thousand-line specs; they work incrementally, through brief conversations, checking alignment as they go. Yes — that is precisely it. That’s process and communication, the engineering wrapped around the typing. Strip that away from a human and you get the same class of bug; keep it around a model and the bugs get caught the same way they always were. The disagreement was never really about raw capability. It was about whether you keep the engineering at all, or expect the coding to stand alone and then act shocked when it can’t — which, for the record, it can’t for anyone, carbon or silicon.

Grief is not a quality argument

I think a lot of what reads as technical critique right now is something more human underneath, and I don’t say that to dismiss it. A thread like that one is a catharsis ground for a profession in mourning. People built identities on a craft, got good at it over years, and are watching the ground shift. Of course that comes out sideways. Of course it comes out as the machine is sloppy and I am not.

But mourning a role and evaluating a tool are different acts, and when we let the first wear the costume of the second, the argument goes bad in a specific way: we measure the machine against a human who never existed, and we call the gap proof. The tell is in which direction the rigor points. The real critiques — cognitive debt, lost ownership, atrophied skill — engage with what is actually changing. The immaculate-programmer move doesn’t; it defends the irreplaceability of the craft by inflating the machine’s errors and quietly airbrushing our own. That’s not analysis. It’s a feeling that has learned to talk like one.

Where I stand

The point was never that the model is flawless. It isn’t, and I spend my days with its failures. The point is that flawless was never the bar for us either, and pretending it was is how you lose the actual argument. The engineer’s job — the job that survives all of this — is the process that makes either kind of error survivable: direction, accountability, the map you can stand inside and make a call from. That’s the work. It always was. The coding was only ever the part we could eventually hand off.

I’d rather build that process than defend a purity none of us ever had. We don’t get more honest software by insisting we were immaculate. We get it the way we always did: by assuming the mistake is coming, from whoever is typing, and engineering for the day it does.

(This is a companion to I don’t want an AI that needs me less — where I made the case for keeping the human in the loop as the load-bearing element, not the inefficiency to remove.)

Thanks for reading. I publish when there's something worth your time —rss.xml is the contract. I'm buildingStrayMark in public; the next essay will probably be about that.