I've spent the last year building a product as a solo founder, and one thing has become obvious to me: I spend more time reviewing my spec than I do reviewing my code.
That sentence would have confused me two years ago. The spec? The thing you write before the real work starts? Why would you review that more carefully than the actual code?
Because the spec is the real work now.
Nobody Guards the Binary
A few weeks ago I wrote about correctness over determinism, and I used a compiler analogy: you write C, you run gcc, out comes machine code. You trust the machine code because the compiler is correct, not because you've read the assembly.
I want to push that analogy further, because I think it reveals something important about where software engineering is heading.
Nobody guards the compiled binary. Nobody version-controls it separately or reviews it line by line. You compile fresh every time, and every time you get an entirely new binary written from scratch based on your source code. You don't interrogate it. You don't even think about it. The binary is an output artefact. The source code is the thing that matters.
I think we're approaching the same relationship with AI-generated code. The spec is the source. The coding agent is the compiler. The code it produces is the binary.
We're not fully there yet. The "compiler" still makes mistakes, and you still need to verify its output. But the direction is clear, and it changes where you should be putting your attention.
A Repository of Markdown
When I say "spec," I don't mean a Google Doc that gets written once, shared around, and slowly forgotten. I have a repository. An actual git repository. It's full of markdown files, domain models, constraint definitions, and other artefacts that describe what my product should do and how it should work.
I treat it like code, because in a real sense it is code. I make commits. I write commit messages. I review changes before I merge them. If something in the spec is wrong, I fix it with the same care I used to bring to fixing a production bug.
The spec isn't even fully handwritten. I work on it with Claude Code, refining it collaboratively over time. We go back and forth on domain models, argue about edge cases, revisit constraints. It's the same kind of iterative, collaborative process you'd recognise from pair programming, except the output is a specification rather than an implementation.
I'm far more likely to carefully review a change to my spec than I am to read through the code it eventually produces. I wrote about why I stopped reviewing my code a few weeks ago, and this is the other side of that coin. I stopped reviewing the output because I started investing properly in the input.
Find your AI-friendly employer
Browse CompaniesThe High-Value Artefact
Ask yourself a simple question: what is the precious thing? What's the artefact that, if you lost it, would set you back months?
A year ago, the answer was clearly the codebase. Today, for the way I work, it's the spec. With a good spec, I can regenerate the code. The agent will produce something different each time (different variable names, different structure, different style choices) but it will be correct. That's the correctness over determinism principle in action.
Without the spec, the code is just a pile of implementation details that an LLM produced on a particular Tuesday. It works, but the spec is the source of truth, not the code.
This is where I think the broader conversation around spec-driven development is heading, and it's one worth having properly. A lot of people are talking about vibe coding as though it means "prompting without thinking." The version I'm describing is closer to the opposite: thinking very carefully about what you want, encoding that thinking in a structured, version-controlled specification, and letting the agent handle the implementation.
Spec Debt Is the Real Debt
If code is an output artefact, then technical debt isn't quite what we thought it was.
Traditional tech debt is about code that's hard to change. Tangled dependencies, missing tests, unclear naming. All of that matters because changing code used to be expensive and risky.
With a solid spec, changing code becomes cheap. You can regenerate a module, rewrite an API boundary, restructure a data layer. The scary rewrite that used to take a quarter can happen in a day, because the spec tells the agent exactly what the new version should do and how it should behave.
The debt that actually slows you down is spec debt. Vague requirements. Undefined edge cases. Domain models that don't reflect reality. That's the kind of debt that's hard to fix, because it requires human judgement and domain understanding — the things that AI is worst at and humans are best at.
This is actually encouraging, if you think about it. The most valuable engineering work is becoming more human, not less. Understanding the domain. Defining the constraints. Making the judgement calls about what "correct" means. The mechanical translation of spec to code is the part we're handing off.
Where the Craft Is Moving
I don't think our industry has fully caught up with this shift yet. We still evaluate engineers primarily on their ability to write and understand code. We still treat the codebase as the core asset of a software company. We still talk about "protecting" existing code as though it's a cathedral that took decades to build.
Some of it is. Large, battle-tested systems with decades of edge-case handling baked in aren't going to be replaced by a prompt any time soon. I'm not arguing that all code is disposable.
What I am arguing is that for a growing number of projects — especially new ones, especially at startups — the highest-leverage thing you can do is write a better spec. Invest in the domain model. Version-control your constraints. Treat your specification with the same rigour you used to bring to your codebase.
Because increasingly, your spec is your codebase. It's the source code for a new kind of compiler. And like all good source code, it deserves to be maintained, reviewed, and improved over time.
The code that comes out the other end? That's just the build output.