Skip to specification

Code Is Not Cheap

The layer under the floor: the artifact the agents actually read and write. Regenerating from a spec without investing in design compounds entropy, so bad code has never been more expensive. Four fundamentals answer four failure modes — a shared design concept before the plan, a ubiquitous language both parties speak, feedback rate as the speed limit, and deep modules that let you design the interface and delegate the implementation.

A context layer tells every agent on the floor what the system is — the services, the owners, the standards. It does not tell them the system is safe to touch. Underneath the index sits the thing the agents actually read and actually write, and if that thing resists change, everything above it is stranded.

Matt Pocock spent eighteen months teaching engineers to build with agents and arrived at a claim that sounds reactionary and is not: software fundamentals matter more now than they ever have. Not as nostalgia. As the constraint that decides how much of the machine you get to use.

The compiler you keep re-running

The idea he is arguing against has a name — specs to code. Write a specification of how the application should behave, let a model turn it into code, and when something is wrong, go back and fix the spec rather than the code. Recompile. You are not supposed to look at the output.

He tried it, and looked anyway.

Four passes of the compiler

Nobody reads the code in between — the spec is the only thing edited

CodePASS 01Worse codePASS 02Worse againPASS 03UnusablePASS 04INVEST IN THE DESIGN EACH PASS — CLAIMED, NOT MEASURED
  1. 01Write the spec, compile itCode
  2. 02Change the spec, compile againWorse code
  3. 03Change the spec, compile againWorse again
  4. 04Keep goingUnusable

No scaleThe vertical axis is deliberately unnumbered. The source reports the ordering — code, worse, worse again, unusable — and publishes no measurement of it, so the drawing carries the ordering and stops there.

FIG. 1 — four passes with nobody reading the code in between. The ordering is the source's; the scale is deliberately absent, because the source published none.
From the talk

"I kept running the compiler, kept running the compiler, and I would just end up with garbage."

The Pragmatic Programmer has a name for this too: software entropy. Change a codebase while thinking only about the change — never about the design of the whole — and the codebase gets worse every time. Specs-to-code industrialises exactly that. Every pass is a change made by something that has no stake in the design, and there is no pass on which anyone invests in the design instead.

Which makes it, in his reading, vibe coding with a document attached.

What "bad code" actually means

The argument only works if bad is defined, and he borrows the definition from John Ousterhout's A Philosophy of Software Design: complexity is whatever about a system's structure makes it hard to understand and modify. That is the whole test. A bad codebase is one you cannot change without breaking it. A good one is one you can.

Then the turn that matters here:

This is the sdlc pillar's own claim from underneath. Beyond code generation argues that writing code was only ever a fifth of shipping software. This adds the harder half: even that fifth only pays out on a codebase that can absorb it.

Four failure modes, four old books

The useful part of the talk is that each failure mode is diagnosed as a missing fundamental rather than a missing model capability — and each one has a fix that predates the model by decades.

01It built the wrong thing

What it looks like

You had a clear picture in your head. What came back is recognisably a different application.

The fundamental it is missing

A shared design concept. Brooks: when two parties design together, the real design is an unwritten thing floating between them — and you do not have one with the model.

02It will not stop talking

What it looks like

Enormous replies, restated plans, four names for the same object across three files.

The fundamental it is missing

A ubiquitous language. Domain-driven design's oldest move: one agreed vocabulary spanning the conversation, the code, and the domain expert.

03It does not work

What it looks like

The right feature, built fast, failing. Types, tests, and a browser were all available and none of them were used in time.

The fundamental it is missing

Feedback discipline. The Pragmatic Programmer calls it outrunning your headlights — the rate of feedback is the speed limit, and the model drives well past it.

04You cannot keep up

What it looks like

More code shipping than you have ever shipped, and no confidence you understand any of it.

The fundamental it is missing

Deep modules. Ousterhout again: substantial functionality behind a simple interface, so most of what exists is not something you have to hold.

The design concept, and the interview that builds one

Brooks's term is worth keeping exactly as he means it. The design concept is not an artifact. It is not the PRD, and it is not the markdown file. It is the shared theory of the thing being built, held between the people building it — and you and the model do not have one at the moment you start typing.

Pocock's remedy is a prompt short enough to quote in full: interview me relentlessly about every aspect of this plan until we reach a shared understanding, walking down each branch of the design tree and resolving dependencies between decisions one at a time. What comes back is not a plan. It is forty questions, sometimes a hundred, before the model is satisfied that the two of you mean the same thing.

His preference for this over a planning mode is a preference about eagerness. A planning mode wants to produce an asset. The interview refuses to produce anything until the theory is shared — and the transcript of it is what becomes the requirements document afterwards.

The vocabulary, written down

The ubiquitous language fix is unglamorous and mechanical: scan the codebase for the terms it already uses, write them into a markdown file of tables, and then hold both parties to it — in the planning conversation, in the code, and in the words used with whoever owns the domain.

What he reports getting back is not just cleaner prose. Reading the model's thinking traces, the reasoning itself got shorter, and the implementation landed closer to what was planned. A shared vocabulary is compression: naming a thing once costs less than describing it every time it comes up.

That is the unified context layer at the scale of a single repository — and it is the same move as pointing an agent at an existing service instead of describing one.

The speed limit

Static types, a suite that runs, a browser the model can actually look at: the feedback loops are mostly available and mostly already installed. The failure is not that they are missing. It is that the model writes an enormous amount of code and only then thinks to check it.

Test-driven development is offered here for a reason that has nothing to do with coverage. TDD is a governor. Write the test, make it pass, refactor — the cycle is small on purpose, and its purpose in an agentic loop is to stop the model outrunning what can be verified. Rate of feedback, speed limit.

Except that testing is genuinely hard, and hard for a structural reason: how large a unit, what to fake, which behaviours are even worth asserting — and every one of those answers depends on the others. Which is where the four failure modes stop being four.

Testability is a property of the walls

One codebase, two boundary sets

Twelve units of functionality — identical in both. Only the walls move.

SurfaceTwelve interfaces. Each one is a thing a caller can depend on and an agent has to find.

Pick oneChoose any unit to see where it sits — and what it costs you when it sits there.

Units drawn
12
On the surface
12
Testable boundaries
12 — one per unit

Drawn, not measured. The source gives the distinction and its consequence for an agent reading a codebase; it publishes no counts, so the tally above counts this drawing’s own boundaries and nothing else.

FIG. 2 — the same twelve units of functionality, laid out two ways. Choose a layout, then pick a unit to see where it sits and what that costs.

A shallow module is a small amount of functionality behind an interface about as complicated as the functionality. Build a codebase out of them and you get a field of tiny exported things — which is, notably, the codebase an unsupervised agent tends to produce.

It is also the codebase an agent cannot read. Exploration has to reach the right file, and then the eleven files it depends on, and the dependency graph is as wide as the module count. What that failure looks like from the outside is a model that does not understand your code — and the instinct is to blame the model, or the window.

Rearrange the same functionality behind three interfaces and the exploration problem mostly stops existing. So does the testing problem, because now there is an obvious place to test: the wall.

A testable codebase is not a codebase with more tests. It is a codebase with fewer, better-placed boundaries — and it is the one that rewards TDD, because there is somewhere for the test to stand.

Design the interface, delegate the implementation

One module, wall showing

Design the interface · delegate the implementation

Outside the wall — strategic, yours

  • The name and the purpose

    What this module is for, in the words the rest of the system already uses. If it cannot be named in the shared vocabulary, the boundary is in the wrong place.

  • The signature

    What goes in, what comes back, what it promises. This is the part every caller depends on, and the part that is expensive to change later.

  • The failure behaviour

    What it does when it cannot do its job. A caller cannot handle a failure it was never told about.

  • The tests at the boundary

    Written against the interface, not the internals. They are what makes the wall real rather than aspirational — and what lets the inside be rewritten without anyone's permission.

Inside the wall — tactical, delegated

  • The internal structure

    How many functions, how they are arranged, what is private. None of it is visible from outside, so none of it is a decision anyone else inherits.

  • The implementation

    The line-by-line work. This is the tactical layer, and it is the layer the model is genuinely good at.

  • Its own refactors

    Rearranging the inside is free when the outside is fixed and the boundary tests hold. That is the whole return on drawing the wall.

Why it is grey, not blackYou can open the box whenever you want to. The point is that on most days you do not have to — which is what keeps the amount you must hold in your head from scaling with the amount of code being produced.

Carve-outNot every module earns this. Where being wrong is expensive rather than annoying — money moving, access being granted — the inside is reviewed too, and the wall buys you a clean place to test rather than a reason to stop reading.

FIG. 3 — the grey box. What you design and review, and what you hand over — plus the case where you do not hand it over.

The last failure mode is the one nobody plans for: the loops work, the throughput arrives, and you become the bottleneck, because you are still trying to read all of it.

Deep modules are what make that survivable. Design the interface carefully — it is the part everything else depends on, and the part a model will quietly get wrong. Then treat the inside as a grey box: verified from outside the wall, opened when you want to rather than because you have to.

The carve-out is his and it is worth keeping: this does not apply everywhere. Where being wrong costs money rather than time, the inside gets read too.

And there is a standing obligation attached. If the modules are the unit of delegation, then the module map has to be something you know — part of the shared vocabulary, named in the requirements document, and revisited whenever the boundaries move. Kent Beck's version: invest in the design of the system every day. Specs-to-code is the practice of divesting from it.

Where this evidence stops

This is one practitioner's account of eighteen months of teaching, and it is offered as one. There is no trial, no cohort, no measured comparison between a specs-to-code team and a deep-module team — the failure modes are observed, and the fixes are argued from books rather than demonstrated against a control.

Two consequences worth holding.

The regeneration curve in FIG. 1 is a reported ordering, not a measurement, which is why it is drawn without a scale. And the popularity of the interview prompt is mentioned in the talk as a recalled figure — the speaker hedges it in the saying — so it stays out of the argument here. A skill being widely copied would not have been evidence that it works.

What survives all of that is the mechanism, and the mechanism is checkable against your own repository this afternoon: whether your codebase is one you can change, and whether the agent working in it can find anything.

The reveal

Step back and look at what this pillar assembled: specs and guardrails shaping behavior — instructions. Agents wielding CI, deploy, and rollback — tool interfaces with an execution environment. A pipeline of gates, retries, and human approval — orchestration. Specialist roles on the floor — sub-agents. Codified practices — skills. Receipts before ship — verification. A context layer feeding every decision — context assembly over shared memory. And a feedback agent turning failures into infrastructure — evolution.

This last link supplies the floor the rest of it stands on, and it turns out to be made of the same primitives. A deep module is a tool interface: substantial capability behind a small, described surface, which is the exact property that makes a tool usable by a model. A ubiquitous language file is instructions that were derived rather than declared. The grilling interview is a skill. TDD is verification with a governor bolted on. The codebase is not the thing the harness acts upon. The codebase is a harness layer — the one you have been editing all along without calling it that.

The agentic SDLC isn't a new discipline. It's a harness at organizational scale — the same primitives you'd build around one model, built around a team. Same machine, bigger floor.

And every remedy across this pillar is a harness change. Not one of them was a better model.