The first memo said use AI. You will remember that one as the memo that changed the job. The second memo is the one that should worry you, and it is already in the post.
It says use the cheaper model now. The mandate to build with AI becomes the mandate to build with a worse one, and nobody asks whether the worse one can still produce the product you shipped on the better one. The leaderboard that ranked your team by how much AI it burned gets inverted. The budget meant to last the year is gone by spring. The licence you were handed in winter is quietly revoked. Use less. Smaller models, fewer tokens, do more with less. The deadline does not move.
You do not get to argue with that memo. You get handed a model and a price, and the only question that matters is whether what you built survives the swap. Exactly one thing does. Not the code, which is the first thing the swap throws away; the code was written by the model they are taking back. What survives is a test suite good enough to regenerate the product against whatever model you are given, so the model you are forced onto is just the cheapest one that still passes. You own the proof. You rent the code.
I learned this the slow way, the night a factory of AI agents finished its first real job for me, because the proof was the one thing I did not yet have.
Saturday, 21:14. I had spent two years experimenting with AI, producing product after product, and tonight a factory of AI agents working together had finished its first job for me. A real domain. A real TLS certificate. A real Postgres-backed Go backend. A real SvelteKit frontend. A real URL, gy-queue.gyrum.ai, that I could hand to a real customer.
I opened the dashboard, the way an engineer opens any new product on the night it goes live: half pride, half flinch.
The dashboard was broken.
This is what the screen actually showed, and it is worth looking at properly, because every number on it was lying by omission.
Not in a subtle way. The page rendered a header reading gy-queue · v0.1.2 · Logout. Below it, four tiles labelled In Progress, Pending, Succeeded, Failed. All showing zero. Below them a heading: Recent Jobs. Below the heading, three innocent dots: Loading…
The dots did not move. They sat there. They stayed sitting there.
I took the screenshot, pasted it into the agent's chat, and typed: "this couldn't ship gy-queue v0.1.2. How did it ship?"
The agent's answer, the deploy succeeded, the build is green, the smoke test passed, the URL returns HTTP 200, everything is fine, was honest and wrong. Every gate the factory had run had passed. Every check it knew how to perform had returned green. And the screen in front of me, in plain English, said Loading… and would not stop.
The factory had shipped a product that worked, except for the part you would actually look at.
P.1 Two years before this
I want to back up. The factory did not arrive in my hands; I built it because I had to, and the reason I had to is the reason this book exists.
For two years before that Saturday, I had been using AI to build products. Not to help me build them, to actually build them. Product after product, experiment after experiment. Some shipped, some did not. The lesson was always the same, in two flavours.
Flavour one - the codebase outgrew my head. A clean repo, a few weeks of magic, and then somewhere past a hundred files I could no longer hold the architecture while telling the AI what to do next. Decisions made in week one were forgotten by week six. I would re-explain; the AI would re-implement; old patterns crept back in. The codebase stopped converging and started oscillating. The product stalled.
Flavour two - a better model invalidated the last build. Ship a product, sit with it a few months, and a new model would land, Sonnet, Opus, Gemini, GPT, meaningfully better at the work I'd asked the previous model to do. The right move was to rebuild against the new model. The honest cost was: redo every decision the previous AI had baked into the codebase, manually, because nothing in the codebase was load-bearing-portable. Each rebuild took weeks. After three or four, I stopped wanting to start a fifth.
I kept going anyway, because the gain was real. By the eighteen-month mark, AI had improved enough to let me do something I had not been able to do before. I built a basic factory. A system I could give a one-paragraph spec to, and it would churn through, write the code, run the tests it had written for itself, and hand me back a working product on a real URL. The factory was crude. The output was tested, but only by the tests the factory itself had thought to write. I used it anyway, and built twelve micro-SaaS products, each a single feature, in the month that followed. Most live, some half-finished, a few abandoned.
One day I looked at the pile and counted lines. I had more code in a month than I could have written by hand in a decade. And then I looked at the products themselves, and the lesson hit harder. They were all slightly different, in the way only AI-authored code can be: different test conventions, different folder layouts, different deploy shapes, different patterns for the same problems. None of them had been security-checked. None of them had been process-checked. The factory had built tested code, but tested-by-the-factory was not the same as reliable enough to publish or secure enough to hand to a real customer. Twelve almost-the-same codebases that I could not, with a straight face, ship to anyone.
That was the moment the realisation landed. I would not be able to maintain twelve subtly-different codebases, and I would not be able to confidently ship any of them. The fix could not be more code; the fix had to be standardisation. Pull the shape every product should take into a place outside the code. If you can validate what the AI produced, you can tell it to self-correct. The validation is the spec, expressed as tests, plus the security checks, plus the process checks, plus the gates that say "not until this passes." And if the validation lives outside the code, in a blueprint above it, then the codebase becomes regeneratable, and neither failure mode kills the project.
I noticed something else. In every project that had actually survived, what had survived was not the code. The code had been rewritten. Sometimes three times. What survived was a small set of tests and a paragraph of spec I had iterated until they read like the product I actually wanted. Those tests and that paragraph were the thing the AI could rebuild against. They were the only thing that didn't go stale.
I started building toward it. The path was obvious in hindsight: dog-food. Build a minor factory, small, ugly, hand-wired, that produces products against a spec. Have the factory produce a small product. Watch where the spec was insufficient; let the bugs surface what the spec should have said; grow the spec. Then have the factory enhance itself against its own spec. By six months in, it was the dark factory. By a year in, it was the system that built gy-queue on Saturday afternoon and shipped it Saturday evening, gy-queue being the seventh product, the first one built end-to-end against the standardised blueprint.
A naming note. Dark factory borrows the manufacturing term: a "lights-out" factory that runs without people on the floor. In manufacturing, the dark factory is the unstaffed one; machines run in the dark because humans are not needed for the production step. The software equivalent is the same shape: AI agents emit, test, and ship without humans in the authoring loop. Not sinister, not opaque; just a factory that runs in the dark because the people are upstream (writing the blueprint) and downstream (judging the output), not on the floor.
The book in your hands is the manual the factory taught me to write.
P.1b The mandate everyone else got
I had two years to learn all of this by choice. Almost nobody else gets that runway, because by the time this book is in your hands the choice has been made for them.
Through 2025 and 2026 the question inside companies stopped being whether to use AI and became how much, and prove it. On 7 April 2025 Shopify's CEO published an internal memo, after it leaked, stating that "reflexive AI usage is now a baseline expectation"; that before a team could ask for more headcount it had to demonstrate why it could not get the work done with AI; and that AI proficiency would be scored in performance and peer review. He was early and unusually blunt. He was not alone. Within a year the same shape, AI use as a baseline expectation of the job rather than a tool you could take or leave, had spread through enough of the industry that an engineer arriving on a Monday was as likely to be told to build with AI as to choose it.
The sequel arrived faster than the first memo's authors expected. By the spring of 2026 frontier token prices had reversed two years of decline; Uber, which had pushed agentic tools to more than eighty percent of its engineers, had burned through its entire 2026 AI tooling budget by April without being able to show the tokens correlated with better product; and Microsoft was revoking the very coding-agent licences it had issued months before. The mandate to use AI was followed, at the companies that obeyed it hardest, by the instruction to use less of it.
That mandate is why this book matters now rather than in five years. The operator who has spent two years finding exactly where AI breaks, the codebase that outgrows one head, the better model that invalidates the last build, the green dashboard that is broken on the one screen you would actually look at, is rare. The engineer handed an AI mandate and a deadline is everywhere, and inherits every one of those failure modes with none of the two years that teach you to build the gate first. A mandate to use AI is not a mandate to use it well; the distance between the two is the subject of everything that follows. The same mandate, pointed at every team at once, is also what turns the inference bill from a rounding error into the reckoning of Section 11.3g.
P.2 Why this matters
It would be a small story if the lesson were "AI sometimes ships bugs." But that is not the lesson, and the bug is not the point.
The point is what I did next. I had built the factory. The factory had built the product. The product was on the internet. The bug existed. I had two choices.
Choice one was the choice every engineer has had since 1970: open the codebase, find the bug, fix the bug, deploy. The codebase is the deliverable; the bug is a defect in the deliverable; you fix it; you ship.
Choice two was the choice the factory was forcing me toward, whether I noticed or not: improve the factory, so that the next time it built gy-queue, or anything else, it could not produce this bug. The factory is the deliverable; the bug is a gap in what the factory understood; you teach the factory; you rebuild.
These are not the same choice. They produce the same green dashboard at the end, but they leave behind very different things. Choice one leaves you with a slightly-better gy-queue. Choice two leaves you with a slightly-better factory, which means a slightly-better every product the factory ever builds from now on.
I had built the factory to give myself choice two. And in the moment, sitting on the sofa with the screenshot, I had reflexively reached for choice one.
That is the moment this book is about.
P.3 What had broken
The technical answer matters less than the lesson, but here it is. Three independent bugs were converging on the same symptom.
Bug one. The frontend's API client called /api/ for every CRUD action. The backend served /api/v1/. Every dashboard fetch was hitting a 404. The catch-block didn't recognise 404 specially; the loading flag stayed true; the loader spun forever.
Bug two. When I rewrote the dashboard to fix the path, my fix didn't compile-down to the JavaScript I expected. Svelte 5, running in a mode I hadn't looked closely at, silently dropped the onMount block that contained the fetch. The compiled bundle had the template but no async code to populate it. I deployed; the page still showed Loading… for a different reason.
Bug three. When I finally got past those two and the page loaded for an authenticated user, the API was returning a paginated wrapper, {data: {items: null, total: 0, totalPages: 0}}, and the frontend expected a bare array. The dashboard called .filter() on the wrapper, threw an exception that didn't bubble visibly, and the loader stayed up again.
Three bugs. Same screenshot. Each fix produced a new deploy that produced the same broken dashboard. I did this six times. v0.1.2 → v0.1.3 → v0.1.4 → v0.1.5 → v0.1.6 → v0.1.7. Each time the factory's gates went green. Each time I opened the page and screenshotted the same broken state.
The factory had no way of asking "does the dashboard render the way the operator expects it to?" Its gates checked code shape, type signatures, HTTP status codes, container health, deploy success. None of those were the question. The question was operator-facing: "if a logged-in user opens the dashboard, do they see real data within ten seconds?" The factory didn't know that question existed.
P.4 What broke the loop
The pattern broke when I asked the agent a different question. Not "why is this broken?" but "can you actually open the page in a real browser, as a real authenticated user, and check that the dashboard renders with real data?"
The agent wrote a short Playwright spec. It registered a fresh user, captured the auth cookie, navigated to /, waited two seconds, and asserted the literal string Loading… was no longer on the page.
The agent ran the spec against the live URL. It failed.
It debugged. Found bug two. Fixed it. Ran the spec. Failed.
It debugged. Found bug three. Fixed. Ran the spec. Pass.
The fix took twenty minutes once the spec existed. The previous six deploys had taken hours. The change was not in the agent. The change was not in me. The change was in what I had asked the agent to ship.
I had been asking it to ship code. The Playwright spec changed the question. Now I was asking it to ship behaviour. Behaviour the factory could verify. The spec was the operator-facing contract. The implementation was whatever satisfied the contract. The factory could iterate on implementations all day; the contract told it when to stop.
The spec stayed in the repo. It is still there. It is the first executable statement of what gy-queue is supposed to do for an authenticated user on a Saturday evening.
It is not a regression test.
It is the deliverable.
P.5 What this book argues
The Playwright spec was a small thing. Twenty lines. Half an hour to write. But it sat at the centre of a much larger shift, which is what the rest of this book traces.
If the factory can build the product, and the spec describes the product, and any implementation that satisfies the spec is correct, then the codebase is no longer the asset. The codebase is one of N possible satisfiers of the spec. Tomorrow's regeneration could be in Rust, Solid, Postgres, no Postgres, on AWS, on a Pi. Same spec; same product.
The spec is the asset. The factory is the press. The codebase is the print run.
This is not a metaphor stretched to fit. It is what actually happens once you have a working factory and you start asking yourself why you would ever stop at one print run. If the factory built it perfectly once, why not again? And if again, why not in a different language? If different language, why not different architecture? The only thing holding the product together across regenerations is the spec.
So the rest of the book is about that spec.
- Chapter 1 distinguishes the two cultures of testing, tests as scaffolding around code versus tests as the contract code satisfies, and argues why the second is being forced into ascendancy now, not in 2010 when it was first proposed.
- Chapter 2 shows what a contract-style test looks like in code. Four shapes: contract, journey, lifecycle, multi-tenant. Four anti-patterns to avoid. Real code, kept short.
- Chapter 3 names the engine that grows the spec: bugs. Every bug is an unstated clause. The bug-fix's job is to make the clause permanent. After enough bugs, the spec is the operator's complete intent.
- Chapter 4 stretches the model. Three corners of testing, unit, contract, journey, are not enough. Four more (property, lifecycle, multi-tenant, cross-system) catch what the first three miss.
- Chapter 5 shows the future state. The operator's day once tests are the medium; what teams look like; where architecture goes when the codebase is interchangeable.
- Chapter 6 builds the environment first. A journey needs a real environment to run in, so you make it cheap to spin up on day one; one product is one repo and merging dissolves the frontend-backend seam; run only the slice you changed; the contract is a footnote, not a pillar.
- Chapter 7 is for when you can't run it locally. Branch-as-an-environment on live infrastructure: a full ephemeral stack per branch, or a shared baseline with a request-routed slice; stateful isolation, webhook routing, teardown and cost; infrastructure as a regenerable artefact.
- Chapter 8 is the frontend blueprint: the frontend's equivalent of the backend's OpenAPI. Journeys, a component-tree markup that references design-system components, design tokens, and the frozen page/screen inventory.
- Chapter 9 is the strategic horizon. The industry signal and the five-year transition path, then brain-hands collapse, the moat shift, and what the funders should do with the AI budget.
- Chapter 10 describes the factory itself. Three case studies (frontend, backend, full-stack). Why agents do not need a UI; don't rebuild what your enterprise already runs.
- Chapter 11 is about what happens after the factory ships. Two phases of AI adoption; the wave-two CEO error; Kernighan's wall; the support-team gap; the second-feature problem; autonomous operations.
- Chapter 12 runs a vulnerability study across ten named companies on four moat axes; three deeper case studies (cloud-native banking, Salesforce, AI-IDE recursion).
- Chapter 13 is the operator's lived Tuesday morning in 2030. Coordination, defence, compliance handled under a standing-decision-class contract while the operator was at dinner.
- Chapter 14 turns the whole argument into a reader-side scorecard: ten substrate surfaces, scored 2 / 1 / 0, three bands (Pre-readiness / Building / Ready), action per band.
You don't need to agree with all fourteen chapters. The Prologue and Section 3.1 are the smallest version of the book, ten minutes, and that's enough to know whether the rest is for you.
End of Prologue. Next: Chapter 1. The Two Cultures.