I was sitting in a lounge outside Robb Winkle’s office, talking about building with AI and the things we’re each stuck on. Robb’s a founder and CTO with twenty-plus years of building enterprise systems and running technology teams, and he’s clearly ahead of me on this. As I described what I was working on, he started handing me principles back, and they fit a little too well. I think he was testing his own position on me while he was at it, which I liked.
Eventually I asked where all of this was coming from, because it was a big body of thinking and not something you improvise in a lounge chair. He said: the Phoenix Architecture.
I couldn’t find it. I caught up with him that night at an OhioX dinner in Columbus and told him so, and he AirDropped me the site across a bar table. I’ve been chewing on it ever since. This is exactly the kind of thing I’m all over.
I’m a Lego kid who builds bigger systems now, and I’ve got three of them running with AI engineering teams doing the work while I steer, counting this website. So I read this stuff with a running scoreboard of “yes, that’s what happens” and “no, not in my experience.” Phoenix scored higher than anything else I’ve read this year, and I want the people who follow my work to know it exists.
What Chad Fowler is arguing
The Phoenix Architecture is a series, twenty-seven essays now, going back to last December, and it’s the best sustained attempt I’ve seen to answer a question the whole industry is fumbling: if AI writes most of the code, what actually holds a system together?
His answer is that code stops being the asset, and never really was one. When generating an implementation costs almost nothing, the implementation becomes something closer to a cache, a compiled artifact you regenerate rather than maintain. What survives the fire is whatever lets you throw code away without fear: what you meant, the boundaries between the parts, and above all the evaluations, because those encode what the system must do no matter how any particular version does it.
Four of his ideas have stuck to me and won’t come off. Conceptual mass, “the number of things a human, or an AI, must understand to make a safe change,” is the cleanest description I’ve read of why some codebases are a joy and others are a swamp, and you can manage it like a budget. The conversation is the commit: the decisions happen in the dialogue and the diff is just where they land, and most of our tooling still assumes the opposite. The implementation remembers and the organization forgets. Mature systems are full of arbitrary retries and weirdly specific timeouts that look wrong until the day you remove them, and when you hand a model a messy function to tidy up, “sometimes it removes the memory along with the mess.” I’ve watched that happen. It’s the most expensive sentence in the series. And UI is a conservation layer: “Protocols don’t churn. Implementations do.” Regenerate freely underneath but not up into the interface, because you’re spending your users’ habits to buy your own flexibility. As a product guy, that’s the one I’d tattoo on somebody.
The summary line comes from “Relocating Rigor”: “The pattern is: probabilistic inside, deterministic at the edges.” It feels like when Agile first came out, the early part, before the certifications, when it was a handful of people writing down what they’d noticed actually worked. I wrote about enterprise teams adopting Agile back when that was still an argument. Right now this is one person publishing carefully into a space that badly needs a shared vocabulary, and the alternative is every team rediscovering all of it alone, and paying for it.
Turns out I’m late to my own party. Back in July, Martin Fowler wrote up a Thoughtworks retreat where a room of people who do this for a living spent their time arguing about exactly this, and he came away with two competing bets. One is that the models eventually get such a galaxy brain that they’ll handle whatever spaghetti we hand them, and internal design quality stops mattering. The other is Laura Tacho’s line, which I wish I’d written: “the Venn Diagram of Developer Experience and Agent Experience is a circle.” The agent reads your codebase using the same handholds you do, so good modularity and clear naming help it for the same reasons they help you.
I’ve been writing about agent experience from the buying side, so let me put my chips down. I think the circle is real right now and I don’t think it stays a circle. The rigor doesn’t go away. What changes is who’s expected to sit down and author it, and I don’t think that stays a person for much longer.
Which is a difference of emphasis, not a fight. I don’t think I’m disagreeing with Martin. He’s reporting the room, and everybody in that room has run into the same wall I have. And Chad is further out ahead than I am on the part we all eventually have to buy into, which is that you burn the implementation. Fine. I believe him. I’m the guy in the back of the room asking how we actually do that at scale, and what the rest of us are supposed to do between now and whenever the tooling shows up to do it for us.
Where I’d push it
Here’s my one disagreement, and it’s a disagreement about who does the work, not about whether the work is right.
He’s already ahead of me on half of this. In “The Specification Is Not a Document” he argues the spec isn’t a file you sit down and read at all. “There is no SPEC.md. No 900-page requirements document. No canonical YAML file.” It’s a body of knowledge you interrogate, and documentation is just one view of it. Good. That’s righter than where I started.
But the interrogation runs the wrong way. In his version, I ask it questions. In mine, it asks me.
You should be able to describe what you need, in a conversation. The model runs the interview. It notices what you left unspecified and asks, the way a good engineer does in a design review: if inventory is unreachable during checkout, do we fail, queue and retry, or take the order as a backorder? Then it compiles your answers into the schemas and the contracts and the tests, back where you never have to look at them.
I want the rigor. I don’t want to be the one authoring it. Chad reasons from an engineering lens and I reason from a product one, and the product question is always the same: who is being asked to hold the complexity, and can we move it off them?
Chad has an answer to this, and it’s a good one. He says specifying intent precisely enough that a machine can generate correct implementations “is not easier than writing code. It’s a different skill, and in some ways a more demanding one.” In “When Does a Specification Become a Program?” he takes up the sharper version, from Gabriella Gonzalez, whose essay is titled “A sufficiently detailed spec is code”. Her point is that if a spec detailed enough for an agent requires the same intellectual work as programming, you haven’t escaped anything, you’ve just changed notation.
That’s the real objection and I don’t think it’s been settled. My answer is that it assumes the human carries the precision burden. In an interview you don’t have to generate the right answer, you only have to recognize it, and recognizing is enormously cheaper than generating. The model has read a million specs and knows which questions have bitten people before.
There’s a harder objection sitting in the same paragraph, from Mario Zechner in his talk Building Pi in a World of Slop, and Chad quotes it too: whatever you leave unspecified gets filled in by the model, and those decisions are no longer yours. I am currently doing exactly that, on purpose, and trying to come out better than the usual outcome. What the interview buys me isn’t that every gap gets closed. It’s that I become aware of which gaps exist, so I can weigh the economics of them and decide where to spend my attention and where to trust the model. Some of those calls I make deliberately. Some of them I’m making because I don’t yet know enough to make them any other way. It’s foggy, and I don’t have the clear path.
When I wrote the first version of this I called that a bet. It’s less of a bet now, because I went and built it. Two of my projects have a file the agent has to use to ask me things, and the rules on it got specific in a hurry. Ask in batches, not as a running stream of interruptions, and never as a decision already made that shows up finished in a pull request. Every question arrives with a recommendation attached, so I’m reacting instead of composing. Anything I leave blank, it builds to the recommendation and tells me it did. And every open item has to say how you’d know it was finished: a command to run, something you could go look at.
That last rule came out of a bruise. One of the projects kept an item on my list for a day after it was already done, because the proof was sitting in a CI log nobody had gone and read, and the next morning a fresh session dutifully reported finished work back to me as still pending. If I can’t go check an item myself, all I can do is take its word for it, and that’s how you end up managing a list instead of a system.
The rule I actually use for what comes to me: a standard affordance ships without asking. Delete needs a confirm. That’s not my call, just build it. What the confirm should say, and when it should stay quiet, is mine. The agent kept collapsing the second kind into the first, which is how I ended up with decisions I’d never made reported back to me as settled.
I said something to my wife about this, who’s also in product. It’s taught me how lazy we really are in product, and how much our engineering teammates quietly fill in for us. The difference in the human world is that we’re talking constantly, so they build a good sense of how to fill the voids and a great instinct for when to push back on us. That’s the part the models aren’t doing at all today.
We called it the TCER
There’s one essay in the series I had a physical reaction to, and it’s the one on provenance. His argument is that the thing worth keeping isn’t the diff, it’s the chain: which requirement, which decision, which check, which code. Then he puts a section heading on it that made me sit all the way back in my chair. “Why Traceability Failed and Why It Might Not Now.” Traceability. I read that and thought: oh, I used to do this.
We had the TCER, which stood for Test Conditions and Expected Results. Giant Excel files. Every test condition traced back to one or more requirements, so when somebody ran it and the expected result came back, you signed off that the requirement worked. In our usage, verification meant walking every requirement and proving a test existed to cover it, and validation meant running the test. That’s the V-model, it was the core of Accenture’s SDLC, and CMM was pushing the whole industry the same way. Clients loved it, because what they were really buying was the transparency. It was expensive and slow, and for systems that mattered it was worth every dollar.
I thought it was the answer to ensuring systems were shipped meeting expectations.
So why doesn’t anybody do this anymore? Two reasons, and neither one is that it was a bad idea. The first is that no amount of coverage tells you what happens in the wild, which I learned the hard way on a telecom launch in 2003 and wrote about here, and which is Chad’s argument that production is a compiler input arriving from the other direction. The second is the one that matters for everything above.
A human had to hold the thread. Traceability was gorgeous on the day you finished it and started rotting the next morning, the way all documentation does. We got sophisticated about it. ClearCase and ClearQuest could tell you a requirement had changed and flag which tests now needed review. But the overhead of maintaining all that linking was massive, and I think the industry just quietly put it down. We reference Jira tickets now and call it even, except one ticket routinely carries a dozen requirements inside it and there’s no mechanical way to know that the intent and the essence of all of them got covered.
The tooling moved too. I got into XP and came around to the idea that the person who can see and review a function is the person who knows what tests it needs, which put QA inside engineering, where I still think it belongs. Worth noticing, in hindsight, that we then spent twenty years deliberately closing the gap between the person writing the code and the person writing the checks.
Chad gets there in one sentence, and it’s the sentence I wish I’d had twenty years ago: traceability failed “because humans were asked to maintain links that the system itself did not depend on.” That’s it. That’s the whole autopsy. It didn’t fail because it was wrong, it failed because a person had to hold the thread by hand and the links rotted faster than anyone could re-tie them. And that constraint is the one that just got lifted. The machine doesn’t get bored maintaining links. It doesn’t leave the project. It can re-derive the whole chain on every change, for free, forever, and it never needs to be talked into it.
The thing my own projects keep telling me
Now the part that complicates my own wish, which I’d rather tell you myself than have you find later.
In two of my projects, the agents write the code and the agents write the checks. Both run adversarial reviews, where you break something on purpose and see whether anything notices. What keeps turning up is that a lot of the checks agree with the code because they were derived from the same understanding that produced the code. Delete a shared list and four test files quietly start checking less, all of them still green. One test derives its expectation from the same definition it’s supposed to be policing, so loosening the definition loosens the test in the same motion, and nothing objects.
None of this is exotic. Practitioners have complained about tautological tests forever, and mutation testing exists precisely because human test suites are worse than their green checkmarks suggest. I’m not claiming a discovery. Both of those projects are unfinished, one isn’t even at MVP, and neither has been through the code reviews a shipping product gets.
Chad has this covered, and more thoroughly than I first gave him credit for. It isn’t a trick he pulls twice, it’s a principle running through the series. Evaluations should “encode what the system must do, independent of how any particular implementation does it.” Behavior must be “verifiable independently of implementation.” And in “The Generative Stack” the instruction is to “maintain independent evaluation approaches” because blind spots don’t overlap across them.
So what’s left for me to add is narrower, and I think it’s the part that bites. Independence of the artifact isn’t independence of the source. A test that never mentions the code is still downstream of the code if the same model derived both. Chad’s independence is measured against the implementation. Mine has to be measured against the thing that wrote it.
That distinction has history behind it. Independence used to be designed. That’s what a separate test organization was for. Glenford Myers wrote in 1979, in The Art of Software Testing, that you shouldn’t test your own code; DO-178C mandates independence outright; and I spent years running orgs built on that premise. Then we folded QA into engineering, for good reasons, and what was left was the cheap accidental version: a person writing the expectation down in a different sitting, from memory of what they wanted. Never free, and never as good as the green checkmarks implied. But it was something. Take the human out of that loop, which is exactly where all of this is heading, and even that residue goes. I’m not worried that AI writes bad tests. I’m worried that it writes tests that pass, that passing means less than it used to, and that a better model makes it worse rather than better, because a better model is a more persuasive author of its own alibi.
So it has to be put back deliberately, and I’d rank the ways to do it by how much independence they actually buy.
The strongest by a distance is evidence from outside the system entirely. Real user monitoring, digital analytics on actual behavior, observability on what production is really doing. None of that is derived from your spec or your generator, which is exactly why it counts, and it’s the one I’d tell any team to wire up first. The catch is that it only ever tells you late, which is the trade you’re making.
Next is getting the check from a different mind than the one that wrote the code. A different model family, or a persona review by an agent briefed to argue against the implementation rather than to confirm it. That last one is how I run reviews on my own projects. Every significant change gets read by seven to nine reviewers, each an AI agent with a different job. One checks every factual claim. One plays security. One plays the skeptical customer who has to use the thing. The rule I had to learn the hard way is that they have to run separately, each starting cold, without seeing each other’s work, because a single model playing all nine parts in one conversation gives you nine opinions with one blind spot. And the quiet part, since it’s the same argument turned on me: running them cold buys separation of context, not separation of weights. Nine cold instances of one model still share a prior, and independently built versions of the same thing have been known to fail in the same places since Knight and Leveson showed it in 1986.
Then the rest of it. A list of the rules written down once and changed only by a deliberate act on its own track, so a change to the code can’t quietly change the standard it’s measured against. Property-based tests, which I only started reading about recently and which look to me like the cleanest small version of this idea, because an invariant that comes out of the problem rather than out of the implementation stays independent no matter who wrote it.
Probabilistic inside, deterministic at the edges, and the edge only counts if it came from somewhere your generator can’t reach.
Go read it
I don’t have all of this yet. I’m going to keep studying it, and I’m going to build the next thing with these ideas deliberately in hand rather than discovered halfway through, with that one amendment about where the checks come from. I’ll report back on what burned and what came out of the fire.
If you’re building with AI right now and you feel the ground moving, start with the series. Start with “The Conversation Is the Commit” and “The Implementation Remembers.” Ten minutes, and you’ll recognize your own week in both of them.
And if Chad Fowler is reading this: what I actually want is to point at a system an agent built for me and know that every requirement in it has something standing behind it, still proving it’s true. That’s the thing I never stopped wanting. I can’t figure out how to get it in Claude Code yet, and part of why I keep reading you is that I’m hoping you’ll just hand the industry the answer.
Thanks, Robb.