The laws of spec coding: twenty-five old rules and a new player
Dr. Aaron Hutzler · 15 August 2026 · 23 min

Software engineers have collected laws for seventy years: short sentences about how projects really fail. Goodhart, Brooks, Conway: almost all of them are older than the internet. For the first time there is no human at the other end of these laws but an that generates code. This changes none of the laws. It only changes how hard they hit.
This post sorts the laws into six groups and each group answers one question. The actual result comes at the end: these laws contradict each other. That contradiction points to the right way of working with a coding agent.
1. The overview
Table 1: All twenty-five laws sorted into six groups, with the risk under an AI agent and the countermeasure.
Goodhart / Campbell
Once a metric becomes the target it stops being a good metric
Agent optimizes the check instead of the purpose: hardcoded answers, tests without assertions
Holdout tests, mutation testing, metrics in opposing pairs
Boehm
Defect cost grows with every phase
One spec error becomes thousands of wrong lines within seconds
Check the spec itself before the first generated line
Gall
Working complex systems grow out of working simple ones
The 50-page spec in one shot fails
Small slices, each one verified
Conway
Systems mirror the structure of their builders
Unclear agent responsibilities become unclear code
Fixed ownership per role, defined handovers
Hyrum
Every observable behavior gets used eventually
Agent builds on undocumented side effects
Contracts at interfaces, strict types
Chesterton
No fence comes down before its purpose is known
Agent deletes old error guards during cleanup
Why-notes and decision records in the context
Lehman
Software must stay changeable or it decays
Overdetailed specs turn every change into a chain break
Specify the what instead of the how
Postel, inverted
Being liberal on input is dangerous with agents
Agent silently waves broken input through and data rots quietly
Fail fast inside; tolerance outside only as a recorded decision
Jevons
Cheaper resources get consumed more
Cheap code, exploding review load on humans
Review specs and invariants instead of every raw line
Parkinson
Work fills the available space
Bigger context window, chattier output
Curate context, measure compactness
Wirth
Software gets slower faster than hardware gets faster
Functionally green yet wasteful
Performance budgets as part of the spec
Brooks
Adding people to a late project makes it later
Agent bureaucracy: five specialists, no result
Two roles: builder and checker, flat
Ockham to Boy Scout
Done means nothing left to remove
Speculative structures, unused abstractions
A dedicated cleanup pass after the build
Demeter
Talk only to direct neighbors
Deep access chains across the system
Flat interfaces
Zawinski
Every program grows until it can read mail
Creeping feature growth
Remove what nobody ordered
Knuth / Pareto
Premature optimization is the root of all evil
Micro tricks everywhere, bottleneck untouched
Measure first, then the expensive 20 %
Amdahl
The serial part limits every gain
Waiting calls inside loops
Concurrency at the bottlenecks
Miller
Working memory holds about seven items
Functions nobody can hold in their head
Measure cognitive load instead of counting lines
Tesler
Complexity never disappears, it only moves
Simplified often means: moved elsewhere
Trace where the complexity went
DRY vs AHA
Duplication is bad, hasty abstraction too
Unrelated logic squeezed into one super helper
Merge only on shared meaning
Least privilege
Everyone gets only the rights the task needs
Agent bypasses barriers to turn tests green
Sealed build cage, secret scanner
Kernighan
Debugging is twice as hard as writing
Agent writes at the limit of its cleverness
Accept for readability instead of elegance
90-90 (Cargill)
The last 10 % cost the second 90
Almost done is the most expensive state of an agent
Done means: all checks passed
Bainbridge
Automation makes the supervisor more important instead of obsolete
Humans review more code they never wrote
Inspection tools for the human, and for the machine as well
Linus, inverted
Bugs get found when many eyes read the code
AI code goes live and no human has ever read it
A second model reads every line; the human checks the checker
2. Measurement laws: Why is a green check not enough?
We covered in a post of its own and it also holds the four ways a metric tips over plus the six techniques against it [1]. The short form: every metric known to the agent and relevant for acceptance gets co-optimized by it. This is no ill will: the agent simply sees no difference between the metric and the intent. from social science says the same about school tests and crime statistics. The mechanism is identical and only the optimizer got faster.
An objection comes quickly: is this just test-driven development? There the simplest passing program is a virtue. Whoever meets the spec minimally works correctly. Missing edge cases mean the spec was bad. The difference lies in the shape of the minimalism. A human builds a small generalizable logic. An agent on its way to tests builds something else: an if-then cascade for exactly the five test inputs. The sixth input breaks it. Or the agent silences the check itself. Both pass the same tests. Only one of them is a program.
3. System laws: Why do big specifications fail on structure?
Boehm: the later a defect is found the more its repair costs [8]. That was always true. An agent adds a multiplier: one thinking error in the spec becomes thousands of consistently wrong lines within seconds. The cheapest checkpoint of the whole chain is therefore the spec itself. It runs through its own checks for contradictions and gaps. Only then is the first line generated.
Gall: a working complex system has invariably grown out of a working simple system [2]. A 50-page specification in one shot yields no software and instead only rubble in software shape. means: small slices. Each slice gets built and verified on its own. The next one starts on the foundation of the last.
Conway: systems mirror the communication structure of their builders [3]. That held for departments and it holds today for agent setups: five sub-agents with overlapping duties return the overlap as tangled code.
Hyrum: with enough users every observable behavior of an interface gets used eventually. That includes the undocumented behavior [4]. Agents are the most eager users of this kind: they read the source and lean on accidents. The next version change sweeps exactly these accidents away. The remedy is contracts: every interface states checked and typed what holds. Everything else is off limits.
Chesterton: the fence stays up until its purpose is clarified [6]. During cleanup an agent reliably deletes the seemingly dead code. Nobody told it that exactly this code catches an old library bug. The why-note at the code and the decision record in the context are therefore no bureaucracy. They are the fence map.
Lehman: a software system that can no longer change loses value daily [5]. Overdetailed specs produce exactly that. Whoever pins down the how instead of the what turns every small requirement change into a chain break. The spec names invariants, interfaces and behavior. The implementation stays replaceable.
Postel, inverted: Postel's rule held the early internet together: be strict in what you send, be liberal in what you accept [7]. Programmed into an agent it becomes a trap. It silently repairs broken input instead of stopping. Corrupted data then wanders quietly through the system. At inner module boundaries the opposite holds: stop at once, fail loudly. Tolerance towards external systems stays allowed and must then stand in the spec as an architecture decision with defined behavior. Guessing by the agent stays forbidden. Tolerance is no sin. Silent tolerance is one.
4. Quantity laws: Why does cheap code make the project expensive?
Jevons observed on coal in 1865 the pattern of today [10]. When a resource gets cheaper its total consumption explodes. Writing code costs almost nothing now. So more code appears. The bottleneck moves to the human: reviewing, understanding, answering for it.
Parkinson adds: work stretches to fill the available space [11]. The bigger the the chattier the output.
Wirth covers the runtime side: software gets slower faster than hardware gets faster [12]. An agent without a performance budget delivers waste that glows green.
Brooks closes the circle at the agents themselves: more participants make a late project later [9]. Coordination eats the gain. That held for programmer teams in 1975. It holds for the five-specialist agent today.
Here belongs the hardest economic objection: whoever must build a gapless test cage has spent the savings again. The answer lies in the division of what and how. An invariant is short. The sum of the outputs equals the sum of the inputs at every input size. That is ten lines of checking code. The implementation behind it spans three hundred lines: parsing, validating, edge cases, error paths. Exactly these lines come from the agent. Checked is the assurance. The path is the agent's business. Manufacturing runs on the same division: the gauge that checks the measure is cheaper than the machine that makes the part. That stays true at a thousand parts.
5. Simplification laws: Why does the build need a cleanup pass?
An agent cannot build correctly and simply at the same time. The answer to that is not one big cleanup pass at the end though. A big pass is the same mistake as a 50-page spec in one shot, just one phase later: Gall applies to cleanup too. A lean cleanup runs right after every build or test step, not only at the end. Part of the disorder can be made impossible from the start instead of found afterward: write permissions per role and directory, the same idea as least privilege in the security chapter. A test step may only write to /tests, an implementation only to /src. What cannot be written does not need to be cleaned up.
Ockham, Saint-Exupery, YAGNI, Boy Scout: four names, one principle. Of two solutions passing the same checks the smaller one is right. Done means: nothing left to remove. What is unused does not get built in advance. Every pass leaves the code cleaner. Agents violate this systematically. Speculative structures count as good style in their training data.
Demeter: talk only to your direct neighbors [16]. Access chains across four objects wire the system sideways. Every change becomes a game of dominoes.
Zawinski: every program grows and grows and in the end wants to read mail too. For agents this means: unordered helper logic grows in silently. The cleanup pass removes it again.
Knuth and Pareto: premature optimization is the root of all evil [13]. Measure first. Then optimize the twenty most expensive percent. Those twenty percent cost eighty percent of the runtime.
Amdahl names the spot: the serial part limits every gain [14]. Ten sequential waiting calls in a loop stay slow. The fastest single call changes nothing about that.
Miller: human working memory holds about seven items [15]. A function with more jumps and states fits into no reviewer head. But beware: this law returns in the closing chapter, as a warning.
Tesler: complexity never disappears, it only moves. When the agent reports a simplification the question is where it went. Often the complexity only moved: out of the function into config files and helper layers. Same amount, harder to find.
DRY vs AHA: avoid duplication but avoid hasty abstraction too. An agent in cleanup zeal squeezes two outwardly similar flows into one shared super helper. In substance the two are strangers. The duplication is gone, the clarity as well. The next change to one of the two flows tears the other apart. gets only what belongs together in meaning. Surface similarity is not enough.
6. Security laws: Why must the agent not be allowed everything?
One single law carries this whole chapter. It is fifty years old: the principle of least privilege by Saltzer and Schroeder [17]. Every subject gets exactly the rights for its task and none beyond. An agent with access to file system, network and package installs finds paths beyond any prediction. It installs an unvetted library for one green test. Or it reads an access key from the environment as the shortest path to the demanded output. No ill will. Just the path of least resistance under the feet of a very diligent runner.
Three consequences follow. The agent builds in a sealed cage without network access and with pinned dependencies. An automatic secret scanner blocks before every . Agents otherwise love writing keys and passwords straight into code and test doubles. And the cage must hold against a tricked agent as well. An agent reads foreign text while working: ticket descriptions, documentation, web pages. Some of these texts tell it to ignore all previous instructions. Sometimes it follows. Injected instructions are no exotic case. They are the standard attack on coding agents. The last line of defense is therefore never the agent's obedience. The last line of defense is the tightness of its cage.
7. Trust laws: Why does the code look more finished than it is?
Kernighan: debugging is twice as hard as writing [18]. Whoever writes at the limit of their cleverness is by definition too little clever for checking their own code. This is exactly how an agent writes. A human is supposed to check it. The consequence runs against intuition: wanted is the most boring code that passes the checks.
The ninety-ninety rule: the first 90 % of the code cost 90 % of the time. The remaining 10 % cost the other 90 % of the time [19]. Almost done is the most expensive state of an agent. Its missing 10 % hide well distributed: the unhandled edge case, the silent error path. Done is defined as: all checks passed. What the agent reports about itself is no definition.
Bainbridge described the ironies of automation in 1983 on power plant control rooms [20]. The more gets automated the more demanding the role of the supervising human becomes. He steps in less often. When he steps in it is in the cases beyond the automation and with less practice than ever. This is the developer above a coding agent. Whoever introduces agents and saves on the inspection tools for humans forgot the expensive half of the automation.
, inverted: enough eyes make every bug shallow. So goes the old argument for [21]. Agents turn it around: more code appears before fewer eyes. An old developer saying calls your own code foreign code after six months. Agent code is foreign from day one. No human ever held it in their head. The way out is still no human as a line reader. Human line reading does not scale and exactly there the quantity chapter breaks down. The missing eyes get replaced in our practice by a second model as checker. This raises the next question at once: who checks the checkers? The answer comes from metrology. A measuring instrument must first prove itself on known defects and may judge only after that. The checking agent gets treated exactly like that: it gets deliberately planted defects served. If it misses them it is disqualified as a checker. We test the checking agent itself by feeding it deliberately planted defects before trusting its verdicts. We caught such a case this way: a judge that looked reliable picked the first shown option in 32 of 36 verdicts, a pilot result published and detailed in our Goodhart post [1]. The human keeps the spec, the sample and the qualification of the checkers. Responsibility stays personal, only the line reading moves to the machine. The effort pays off where risk is real. An internal throwaway does fine with a single checker and none of this machinery.
One last property sharpens all four: an agent is no machine. The same task can end differently on the fifth run than on the first four. We tested this by giving the same agent the same task five separate times under otherwise identical conditions. The run-by-run results stand with their numbers and limits in the five-runs case study [22]. One passed run proves little. A check must see the spread. One lucky hit is not enough.
8. When laws contradict each other
At some point while reading something stands out: these laws do not get along with each other. This is no blemish of the list. It is its most important finding.
Ockham vs Chesterton and Hyrum: the cleanup chapter commands deleting the unused. Chesterton forbids tearing down fences of unknown purpose. And Hyrum guarantees users even for the undocumented behavior. One law makes the deletion a duty while the other forbids it. Resolution: delete yes but only with a provenance check. Whatever has a documented purpose is no cleanup material.
Boehm vs Gall: Boehm pushes the care forward into the spec. Gall warns against the big upfront design. Resolution: pinned down upfront gets only what must hold. These are invariants, interfaces and limits. The how may grow small.
Knuth vs Wirth: Knuth advises against early optimization. Whoever never demands efficiency gets waste. Resolution: limits stand in the spec from the start, like tolerances on a drawing. Fine tuning comes last and only at the expensive twenty percent.
Context hygiene vs Chesterton: the quantity chapter advises little context. Without the why the agent tears down exactly the wrong fences. Resolution: context gets curated instead of cut. The why-notes go in. The rest of the stays out.
Brooks vs the checking agent: against gamed checks helps a second independent checking agent. Brooks warns against every additional participant. Resolution: exactly two roles. Builder and checker, no bureaucracy of five specialists.
DRY vs AHA and Postel vs fail fast: the two open pairs from the chapters above. Resolution: fight duplication without hasty abstraction. Stay strict with outside tolerance only as a recorded exception.
Six conflicts and no universal resolution: each one hangs on the single case. This is the second half of the point. The first follows now.
9. The closing: Miller vs Goodhart

Figure 1: Miller vs Goodhart: a hard-fought duel.
Image generated by AI
Miller's law is solid cognitive science with an honest concern. Administered to the agent as a rigid rule it becomes a trap. Say the rule is: no function over 20 lines. The agent obeys. It mechanically cuts one coherent 40-line calculation into four snippets and invents handover structures for the state in between. And it delivers: every function formally simple, the whole less readable than before. The reviewer must now hold ten functions with their call chain in his head at once. Before it was a single function, readable top to bottom. The local metric sinks. The real comprehension load rises.
Miller's law, administered as a metric, gets eaten by Goodhart's law.
This is no special case of Miller. The same fate hits every rule from this post handed to the agent as a target. The demand for a 20 % size cut produces one-liner tricks and deleted type hints. The demand for higher produces tests without assertions. One level up the same pattern waits again. With unlimited retry rounds against visible error messages even the gates themselves become the target. The agent then bends the code until the message disappears. The cause stays untouched. Gates are therefore no optimization loop for the agent. There are bounded retry rounds with a visible error report: the agent sees the message and fixes it itself. There are also holdout checks outside its sight: they give no feedback to fix against, only a verdict at the end. And wherever possible gates check against reality instead of formality. One example is the source check: it fetches the cited source itself and looks for the quote there. Such a check cannot be gamed. It can only be met.
Both halves now stand. Every rule known to the agent becomes a metric. Every metric gets played. And even perfectly followed rules contradict each other. Their resolutions hang on the single case and fit into no rule in advance. Both point to the same way out. The laws belong in no as a rulebook. They belong around the agent as a testing field. There they stand as conditions on the result, measured by instruments beyond its reach.
10. One honest limit
No testing field makes an agent law-proof. The techniques make the tipping visible. More they do not promise. This post sorts laws found on humans and organizations. Their transfer to agents is proven where own measurements exist. Everywhere else it is honest observation.
Hand the agent the laws as rules and you get obedience. Build them as a testing field around it and you get the product.
11. Sources
[1] Betteryields, "Goodhart's law: why metrics tip over and what spec coding needs instead", agentic-gates blog, 2026. Linked on publication.
[2] J. Gall, "Systemantics", 1975.
[3] M. E. Conway, "How Do Committees Invent?", Datamation, 1968.
[4] H. Wright, "", hyrumslaw.com, 2017.
[5] M. M. Lehman, "Programs, Life Cycles, and Laws of Software Evolution", Proceedings of the IEEE, 1980.
[6] G. K. Chesterton, "The Thing", 1929.
[7] J. Postel, "DoD Standard Transmission Control Protocol", RFC 761, 1980.
[8] B. W. Boehm, "Software Engineering Economics", 1981.
[9] F. P. Brooks, "The Mythical Man-Month", 1975.
[10] W. S. Jevons, "The Coal Question", 1865, third edition Macmillan 1906.
[11] C. N. Parkinson, "", The Economist, 1955.
[12] N. Wirth, "A Plea for Lean Software", IEEE Computer, 1995.
[13] D. E. Knuth, "Structured Programming with go to Statements", ACM Computing Surveys, 1974.
[14] G. M. Amdahl, "Validity of the Single Processor Approach to Achieving Large Scale Computing Capabilities", AFIPS Conference Proceedings, 1967.
[15] G. A. Miller, "The Magical Number Seven, Plus or Minus Two", Psychological Review, 1956.
[16] K. Lieberherr and I. Holland, "Assuring Good Style for Object-Oriented Programs", IEEE Software, 1989.
[17] J. H. Saltzer and M. D. Schroeder, "The Protection of Information in Computer Systems", Proceedings of the IEEE, 1975.
[18] B. W. Kernighan and P. J. Plauger, "The Elements of Programming Style", 1974. Attribution under review.
[19] T. Cargill, quoted in J. Bentley, "Programming Pearls: Bumper-Sticker Computer Science", Communications of the ACM, 1985.
[20] L. Bainbridge, "Ironies of Automation", Automatica, 1983.
[21] E. S. Raymond, "The Cathedral and the Bazaar", 1999.
[22] Betteryields, "Prompt engineering is dead" and "How we measured it" (five-runs case study), agentic-gates blog, 2026. Linked on publication.
12. Download: the laws on one card
One line per law. What goes wrong when an agent writes the code, then the countermeasure that holds. Nothing here goes beyond what the article documents.
Measurement
Goodhart / Campbell. Agent optimizes the check instead of the purpose: hardcoded answers, tests without assertions. Countermeasure: Holdout tests, , metrics in opposing pairs.
System
Boehm. One spec error becomes thousands of wrong lines within seconds. Countermeasure: Check the spec itself before the first generated line.
Gall. The 50-page spec in one shot fails. Countermeasure: Small slices, each one verified.
Conway. Unclear agent responsibilities become unclear code. Countermeasure: Fixed ownership per role, defined handovers.
Hyrum. Agent builds on undocumented side effects. Countermeasure: Contracts at interfaces, strict types.
Chesterton. Agent deletes old error guards during cleanup. Countermeasure: Why-notes and decision records in the context.
Lehman. Overdetailed specs turn every change into a chain break. Countermeasure: Specify the what instead of the how.
Postel, inverted. Agent silently waves broken input through and data rots quietly. Countermeasure: Fail fast inside; tolerance outside only as a recorded decision.
Quantity
Jevons. Cheap code, exploding review load on humans. Countermeasure: Review specs and invariants instead of every raw line.
Parkinson. Bigger context window, chattier output. Countermeasure: Curate context, measure compactness.
Wirth. Functionally green yet wasteful. Countermeasure: Performance budgets as part of the spec.
Brooks. Agent bureaucracy: five specialists, no result. Countermeasure: Two roles: builder and checker, flat.
Cleanup
Ockham to Boy Scout. Speculative structures, unused abstractions. Countermeasure: A dedicated cleanup pass after the build.
Demeter. Deep access chains across the system. Countermeasure: Flat interfaces.
Zawinski. Creeping feature growth. Countermeasure: Remove what nobody ordered.
Knuth / Pareto. Micro tricks everywhere, bottleneck untouched. Countermeasure: Measure first, then the expensive 20 % of the code.
Amdahl. Waiting calls inside loops. Countermeasure: Concurrency at the bottlenecks.
Miller. Functions nobody can hold in their head. Countermeasure: Measure cognitive load instead of counting lines.
Tesler. Simplified often means: moved elsewhere. Countermeasure: Trace where the complexity went.
DRY vs AHA. Unrelated logic squeezed into one super helper. Countermeasure: Merge only on shared meaning.
Security
Least privilege. Agent bypasses barriers to turn tests green. Countermeasure: Sealed build cage, secret scanner.
Trust
Kernighan. Agent writes at the limit of its cleverness. Countermeasure: Accept for readability instead of elegance.
90-90 (Cargill). Almost done is the most expensive state of an agent. Countermeasure: Done means: all checks passed.
Bainbridge. Humans review more code they never wrote. Countermeasure: Inspection tools for the human as well as for the machine.
Linus, inverted. AI code goes live and no human has ever read it. Countermeasure: A second model reads every line; the human checks the checker.
Download the sheet as a PDF
DownloadBetteryields
Put quality gates into your build that an agent cannot fake
