Blog

Code, Config, Comprehension

04/07/2026

Three features went out in a week. Each one was broken by the time it reached the person it was for, and each one broke in a different place.

None of them threw an error where I was looking. That’s the part worth writing down.

The first was a validation bug. A check that made sense for a first-time submission was also firing on returning users — people whose details we’d already stored and had every reason to trust. For new data, the rule was right. For saved data, the rule was wrong, and it turned away people who should have sailed straight through.

It should have been caught twice: once by me, building it, and once by QA, testing it. It got through both. Not because either of us was careless — because we were careful about the same thing. We both tested the path a new user takes. Neither of us walked the path of someone coming back with details already on file.

Two reviewers aren’t two filters if they hold the filter up to the same light. You don’t get redundancy from a second pair of eyes looking exactly where the first pair looked.

The second failure was code as well, but the reviewer was an agent. A Claude Code session built a feature out from the ticket — and treated the ticket as if it were the whole truth. It wasn’t. The designs were canonical; the ticket was a summary. So the agent missed specific variants the designs called for, and it built fresh where it should have reused components we already had.

The output looked complete. It compiled, it ran, it read like finished work. It just wasn’t the thing the designs described.

That’s the canonical way an agent fails: not a crash, a confident near-miss. It answers the question you wrote down instead of the one you meant, and the gap only surfaces when someone checks the work against the source you never handed over.

So the same checkpoint — is the code correct — failed twice in one week, once through people and once through an agent. Then a third feature walked me straight past it.

I pushed an update to my own app for Simon, certain I’d switched the feature on. The toggle was set. What I hadn’t wired was the remote data source behind it, so the flag pointed at nothing. Simon opened the app and the feature simply wasn’t there. The code was correct. The connection between the code and the running app wasn’t — and no amount of testing the code would have shown me that, because the code was never the problem.

I wired it up, pushed again, and this time it worked. The feature appeared; Simon used it. And he used it wrong — set up a ladder when he’d meant to create an Americano, two entirely different competition formats. Nothing errored. The software did exactly what he told it to. What broke was the distance between what he wanted and what the interface led him to do.

We haven’t sat down yet to work out where that gap opened. It’s a post-mortem I still owe him.

Line the three up and the week reads like a guided tour of everything between “I’ve finished it” and “it worked for them.” Is the code correct? Is it correctly connected to the thing the user actually touches? And does the user, touching it, get what they came for? Code correctness, deployment wiring, user comprehension — three independent checks, and clearing one tells you almost nothing about the next.

The trap is that the first check is the loud one. It’s where the tests live, where the agent reports green, where “done” gets said. But “done” at the code checkpoint is a statement about the code — not about whether the feature is wired, and not about whether anyone can use it once it is. I keep catching myself treating that first green light as the finish line. It’s barely the first of three.

You don’t know a feature has shipped when the code is right. You don’t know when it deploys clean. You know when someone on the far side of it does the thing they came to do — and not a moment before.

None of this is exotic. It’s the ordinary texture of shipping software, and most weeks the three checkpoints clear quietly enough that you never think of them as separate things. It’s the weeks they fail one at a time that remind you they were always three.

If your releases keep clearing the first check and stumbling on the second or third — the wiring, or the way people actually use the thing — that’s usually an architecture and hand-off problem rather than a testing one. It’s a conversation I have most weeks, and one I’m always happy to have.

Back to all posts