A follow-up. I raced a spec-driven framework to build Snake, and it never wrote a line of code.

The exercise was a one-hour jam: build the game, use one of the famous spec-driven tools, do it properly. So the tool did what it’s built to do. It interviewed us. Each human taking a role, and answering the same questions we do in our current roles. Architecture was introduced. Do you want a component architecture or a single game loop. OOO or stateless. Then it started producing documents: a PRD, an architecture doc, an intent file, a spec, and a full set of unit tests. All of it before one line of game code existed.

While it churned, I opened Claude Code and typed four sentences. The essence of what the spec was circling, plus two features I thought would be fun. Then I hit enter. By the time the framework finished its planning documents, I had a snake crawling across a screen and eating things.

Yes, this is contrived. It’s a tiny piece of software and a rigged little race. But it mimics the real thing closely enough to be worth sitting with, because the part that decided the outcome is the part nobody’s building tools for.

I stayed in the chair. I wrote the four sentences, I watched the thing run, and I decided whether it was any good. I wanted a HUD with four readouts on it, so I said so. The color and placement came back wrong, and fixing that was a ten-second nudge. I asked for music like Pac-Man. It didn’t copy Pac-Man. It hallucinated something adjacent, its own off-brand arcade jingle, and honestly it was better.

I can’t even tell you whether the spec’s version was better, because there never was one to run. It was still a stack of documents when the hour ended. Mine was a game you could play. It needed work, the way every first version needs work, but “needs polish” and “doesn’t exist yet” are not the same starting line.

And the work mine needed was not more architecture up front. It needed a frame-rate counter and an input-latency readout. It needed outcome monitoring. Numbers about whether the game felt right, not assumptions about whether the design was right.

That gap is the whole argument.

We optimize the thing before it exists

We tune the architecture before the software runs. We interrogate the design before we’ve watched it move. And we do it because we’re proud of knowing how software scales. We know the patterns, we know they hold up, and reaching for them feels like competence.

Knuth told us in 1974 that premature optimization is the root of all evil. We quote it in code reviews and break it in planning meetings without noticing the contradiction. Pre-deciding an architecture is premature optimization wearing a nicer suit. You’re tuning something that doesn’t exist against a workload you haven’t measured.

Sometimes a layer needs a custom optimization scheme. Sometimes it needs none at all, because the whole thing runs at 200 FPS on a potato and no player will ever feel the difference. You cannot know which from a document. You learn it from the FPS counter.

I learned this the expensive way

Years ago at Google I was building an internal code-generation tool. Protobuf in, C++ out. I knew the domain cold, which is exactly what made me dangerous. I architected the whole thing in my head, wrote three thousand lines, and sent it for review, already planning the two-week path to ship.

My reviewer bounced it in about five minutes. This doesn’t even work. How am I supposed to know what you’re doing? Start over.

I stormed off to lunch. Weeks of work, rejected before I’d finished my sandwich. Somewhere on the walk back I stopped being angry long enough to admit they were right.

So I started over, and I started stupid. Read a file. Tokenize it. Build an AST. Emit one line of output. Smaller than that, actually. Hello world. We got the hello-world case working end to end, then added one feature, then another. It took far longer than my three-thousand-line cannonball had. But I had running software by the second day, and every layer that turned out wrong was small enough to tear out and redo in an afternoon.

That’s the whole skill. Not foresight. The cheapness of being wrong.

Your perfect architecture is a moat

The architecture I was so sure of, that first time, was wrong. They usually are. If you drew a design two years ago and it still looks exactly the way you drew it, you didn’t nail it. You defended it. It became your moat, the sunk cost you keep patching because you can’t stand to admit the shape was off. You put months into it, so now you struggle to keep it alive without ever letting it change.

Let it change. Be wrong early, while wrong is a small refactor instead of a rewrite. Failure that early isn’t a lack of vision. It’s the mechanism. It’s how the design finds the shape it was always going to need.

A quick word for the TDD crowd. Test-driven development is one of the good dogmas when it stays honest. Written well, tests pin down what the software must do and free you to change everything underneath. Written badly, they pour today’s implementation into concrete, and every honest refactor comes back red for the wrong reason. Protect the outcome, not the structure. Same lesson, different tool.

The guy in the chair

In the last article, I compared this whole setup to Rick Rubin, who produced some of the biggest records of the last forty years and can’t work a soundboard. He’s paid for exactly one thing: the confidence of his taste. He knows when the take is wrong and says do it again.

That’s the job now. The agent is the session musician who can play anything I hum. It built a working Snake and invented its own arcade music on the spot. The spec framework was the consultant who booked an hour to interview the band about the sonic architecture of the record before anyone plugged in. I don’t want either of them making the call. I want to hear the take and know.

The framework asked smart-sounding questions. Component boundaries, scoring rules, collision semantics, all reasonable. But every one was a question about the input, and the game was decided at the output, on the screen, in the feel of the snake turning a corner. No document it generated could tell me whether the game was fun. I had to watch it run.

Generation is nearly free now, and getting freer. When the machine will build whatever you describe, the scarce thing isn’t the description and it isn’t the code. It’s the person who looks at what came out and knows. The FPS counter can tell you the frame rate. It can’t tell you the game is boring. That part is still mine, and I don’t think it’s leaving, which turns out to be a strange kind of good news. The last thing to automate is the part I actually like.

Originally published on LinkedIn.