Chapter 24 — Greenfield vs Legacy: the Harnessability Inversion
3168 words
"The harness is most needed where it is hardest to build." — Böckeler [D]
True of half of it. This chapter is about which half.
- Why the inversion is an accounting identity rather than a misfortune
- Why the greenfield/legacy framing — including this chapter's title — is the wrong axis, and what the right one is
- The greenfield trap: the window for cheap banking closes before the need is felt
- Which components of harnessability retrofit cheaply into legacy, which do not, and why that substantially softens the inversion
- The ordering constraint: why the graph must precede structural work in legacy
- The monoculture that harness templates produce, and why it causes Chapter 23's problem
the inversion holds for structure and is much weaker for sensors. The two harnessability components Chapter 13 identified as mattering most — a held-out acceptance set and blocking sensors in the edit cycle — are also the two cheapest to retrofit, because neither requires touching existing code. So the honest position is more optimistic than the quoted sentence, and more specific about where the pessimism applies.
24.1 The inversion is an identity
Chapter 8 §8.4 defined harnessability as variety reduction already banked: a strongly typed codebase has spent past effort making most programs unexpressible; one with enforced layering has already forbidden most call graphs. The regulator has less to regulate because someone already narrowed the system.
Given that definition, Böckeler's observation stops being a cruel irony and becomes arithmetic.
That matters practically, because it rules out a whole class of hope. There is no clever technique that makes an unconstrained codebase cheap to harness, for the same reason there is no clever technique that makes a large number small. Everything below is about working at the margins of an identity, not defeating it.
24.2 The framing is wrong
Now a correction to this chapter's own title, because testing the framing against Chapter 13's scoring instrument exposes a problem.
Chapter 13 §13.5 scored harnessability on six questions: types enforced, a held-out acceptance set, mechanically enforced boundaries, blocking sensors in the edit cycle, reliable reference enumeration, and drill evidence. Not one of them mentions age.
And two counter-examples settle it. A twenty-year-old Java service with strict types, enforced layering, and a comprehensive test suite scores high — and it is thoroughly legacy. A six-month-old startup codebase in untyped Python with no boundaries and no tests scores near zero — and it is thoroughly greenfield.
So the honest statement of the inversion is not about age:
Harnessability is banked variety reduction, and greenfield is merely the cheapest moment to bank it. The axis is banked versus unbanked. Age correlates because time without discipline accumulates variety, not because old code is inherently unharnessable.
This changes the advice. A team with a well-structured fifteen-year-old monolith should stop apologising for its age and read its H-score. A team six months into an untyped greenfield project should stop congratulating itself on being modern.
24.3 The greenfield trap
If greenfield is the cheapest moment to bank variety reduction, why do so few teams do it?
Not carelessness. The timing is genuinely adverse.
At day one there is almost nothing to govern. A five-hundred-line codebase has small variety, so a harness feels like pure overhead — and it is pure overhead, at that moment, measured honestly. Deferring is the locally rational choice, which by now is a familiar shape.
But the two curves move differently.
That is the greenfield trap, and it explains why the greenfield advantage is usually squandered rather than seized. Nobody declines it. It expires while being deferred for locally sound reasons.
24.4 What retrofits, and what does not
Chapter 8 left this chapter an open question and a pessimistic prior: "none of them is as good as having banked it, and it is not clear anything could be."
Working through Chapter 13's six components produces a more useful answer than that, and it materially softens the inversion — not by contradicting it, but by locating where it applies.
| Component | Retrofit cost in legacy | Why | |
|---|---|---|---|
| H1 | Types enforced | High | Whole-codebase; every module and every boundary |
| H3 | Enforced boundaries | High for a full layering scheme; low for one rule | A single "this may not import that" is cheap; a coherent architecture is not |
| H5 | Reliable reference enumeration | Moderate | Tree-sitter parses anything, but dynamic dispatch resolves badly (Ch 9 §9.1) |
| H2 | Held-out acceptance set | LOW | Written for the change you are making now. Requires no existing code to be touched. |
| H4 | Blocking sensors in the edit cycle | LOW | A hook wrapping a tool you already have. Runs on the diff, not the repository. |
| H6 | Drill evidence | LOW | Costs agent time and almost no human time (Ch 8 §8.9) |
Look at what fell out.
The three expensive components — types, boundaries, references — are all structural. They are Chapter 10's territory, they describe properties of the existing code, and retrofitting them means changing that code.
The three cheap components — acceptance set, blocking sensors, drills — are all harness. They are Chapters 7 and 8's territory, they attach to the change rather than to the codebase, and none of them requires touching a line that already exists.
And Chapter 13 §13.5 already flagged H2 and H4 as the two that matter most — H2 because it is the only defence against Chapter 8's consistency-not-correctness problem, H4 because it is the highest-authority control in Chapter 7's quadrant.
The two highest-value harnessability components are also the two cheapest to retrofit. The inversion is real for structure and much weaker for sensors.
So Böckeler's sentence is true of the structural half of harnessability and overstated about the sensor half. That is a meaningful refinement rather than a quibble, because it locates the first move for a legacy team precisely: not a typing project, not a refactor, but an acceptance set for the change in front of you and a blocking check on the edit cycle — which is exactly Chapter 15's L1→L2 transition, and which Chapter 15 argued you can do without perfecting L1.
Two further legacy strategies, both consequences of earlier chapters.
Bank at the boundary, not the interior. You cannot type a legacy codebase, but you can type the edges of the module you are about to work in. This is strangler-fig logic applied to harnessability: raise the H-score of the region you touch, leave the rest alone, and let coverage grow with activity rather than with a programme.
Score per module, not per repository. Chapter 13 established that an autonomy level applies to a class of work rather than to an organisation. The same holds here. A legacy repository has no single H-score; it has a distribution, and the parts you change most are the parts worth banking in.
24.5 The ordering constraint
One sequencing claim, and it is not optional.
Chapter 10 §10.6 established that whether duplication is debt depends on whether you built the graph: what makes extraction expensive is the fan-in enumeration problem, and lexical search supplies recall without a guarantee. An agent — or an engineer — that finds three of six call sites, extracts, and breaks production has learned something true about its instruments.
In a legacy codebase this is not a marginal effect. Dynamic dispatch, string-keyed handlers, reflection, and re-exports are exactly what accumulates over fifteen years, and they are exactly what defeats lexical search. So:
In legacy, the graph precedes structural work. Without reliable reference enumeration, refactoring is genuinely dangerous, teams correctly refuse to do it, and the codebase's structure cannot improve. The graph is not an optimisation here; it is the precondition that makes structural improvement affordable at all.
This inverts the intuitive order. The instinct is to clean up the code first and instrument it afterwards. The correct order is to build the map first, because the map is what makes the cleaning survivable — and Chapter 9 §9.7 was careful that this comes with a real freshness cost and a genuine failure rate.
24.6 What to lock in on day one
For the greenfield case, and with a caveat that matters.
The rule is to commit to what is cheap to have and expensive to add, and to defer what encodes domain knowledge you do not yet possess.
Lock in immediately:
- Types, enforced. The single steepest cost curve in Figure 24.3. Free on day one, and the most expensive thing on this list to add in year three.
- Trace capture. Chapter 15 §15.6 identified this as the prerequisite no maturity model lists, and showed that L3 is unreachable without it regardless of how many controls exist. It costs nothing on day one and cannot be recovered retroactively — traces not captured are gone.
- One blocking check in the edit cycle. Not for its immediate value, which on a small codebase is near zero, but because it establishes where checks live. Adding the second is then trivial.
- A topology commitment. Chapter 8 §8.3's Ashby constraint: harness templates only work if the organisation has bounded the space of service shapes. This is an architectural decision, it is cheapest at day one, and Chapter 15 priced it as an executive decision rather than a technical one.
Defer deliberately:
- Bounded contexts and layering. These encode domain understanding. On day one you do not have it, and a boundary drawn in the wrong place is worse than none — it will be violated, the violations will be normalised, and Chapter 21's Autonomy Creep has an architectural sibling.
That asymmetry is worth stating plainly, because "set up everything on day one" is bad advice: structure that encodes what you know is cheap to add early; structure that encodes what you have not learned yet is expensive to get wrong. Types and traces are the first kind. Domain boundaries are the second.
24.7 The monoculture
Chapter 8 §8.10 left one debt: harness templates may lead teams to choose architectures partly on the basis of which harnesses exist, and this chapter was to argue that is both a virtuous cycle and a monoculture.
It is both, and the two are the same mechanism.
The virtuous cycle is real. A well-harnessed topology gets chosen, which increases its usage, which justifies further investment in its harness, which raises its harnessability, which — via Chapter 13's ceiling matrix — permits higher autonomy on work in that shape. Ashby is satisfied more cheaply each cycle. These are genuine compounding returns and an organisation that achieves them is materially better off.
The monoculture is also real, and it has three costs.
The unharnessed topology becomes unchoosable even where it is technically correct. The decision stops being "what shape does this problem want?" and becomes "what shape can we govern?" — which is a reasonable trade until it silently becomes the only question.
Correlated failure. Every service shares the same weaknesses, the same blind spots, and the same unexamined assumptions in the same template. This is Taleb's standing objection to efficiency-through-uniformity: diversity is what absorbs shocks, and a system optimised into a single shape has traded resilience for throughput without recording the trade.
And it causes Chapter 23's problem. This one is not obvious and it is the most damaging. A team whose problem does not fit the supported topology does not stop working. They build it anyway, unofficially, outside the template — which is precisely the prototype that will acquire a user, a maintainer, a secret, or a schedule with nobody watching. Monoculture manufactures uncrossed prototypes, and the organisation that thought it had standardised has instead pushed variety into the places it cannot see.
The resolution is the barbell shape Chapter 13 §13.8 arrived at from a different direction: standardise the majority hard, and explicitly fund a supported exception path — a way to build something that does not fit, with an owner and a review, rather than driving it underground. An exception path that exists is variety you can see. An exception path that does not exist is variety that has gone somewhere else.
24.8 Choosing where to start
Pulling it together into a sequence.
If your H-score is low and the code is new, you are in Figure 24.2's top-left quadrant, which nobody warns about. Do §24.6 now — types, traces, one blocking check, a topology commitment — and understand from Figure 24.3 that the window is closing while it still feels unnecessary.
If your H-score is low and the code is old, do not begin with a typing project or a refactor. Begin with H2 and H4, which cost nothing structural: a human-written acceptance set for the change in front of you, and a blocking check on the edit cycle. Then build the graph, because §24.5 says structural work is unsafe without it. Then improve structure, in the modules you actually touch.
If your H-score is already high, whatever the age of the code, you are in the best position in Figure 24.2 and the constraint is organisational rather than technical. Chapter 16 applies: name a harness owner, fund the public good centrally, and staff the enabling capability that moves other teams.
And one honest closing note, because Chapter 8's pessimism deserves to survive the refinement.
Everything in §24.4 makes the sensor half of harnessability affordable in legacy. None of it makes the structural half affordable. A tangled, untyped, unlayered codebase with excellent sensors is genuinely better off than one without them — Chapter 7's evidence says most organisations do not even have that — but it remains a codebase where local inference is unsound, where Chapter 10's leaky abstractions are invisible from the inside, and where the autonomy ceiling stays low no matter how many checks you add.
The inversion is softened at its edges. It is not dissolved, and Chapter 8's open question stands: nothing yet discovered is as good as having banked it.
The inversion is an accounting identity and cannot be dissolved, but it applies to structure rather than to sensors — and since the two highest-value harnessability components are also the two cheapest to retrofit, a legacy team's first move is an acceptance set and a blocking check, not a refactor.
- Does the H-score predict outcomes? Chapter 13's instrument is used throughout this chapter as though it measures something real. Whether a repository's H-score predicts agent success rates, defect escape, or the duplication signature is unmeasured, and it is the test that would validate or discard the whole framework.
- Where is the greenfield window, in months? Figure 24.3 asserts the curves cross and does not say when. A study of retrofit costs against codebase size at time of adoption would give the number, and it is the number a founding team actually needs.
- Can the graph be built well enough on legacy? §24.5 makes the graph a precondition for structural work in exactly the codebases where dynamic dispatch is worst. Chapter 9 §9.7 conceded the code-specific positive evidence is two unreplicated papers, both on public Python repositories.
- Does the exception path work? §24.7's remedy for monoculture is a funded, supported way to build something that does not fit. Every organisation I am aware of that has tried this has watched the exception path either atrophy or become the default, and I know of no account of one that stayed in balance.
- Böckeler, Birgitta. Harness engineering for coding agent users [D] ✅ — "the harness is most needed where it is hardest to build"; harnessability and ambient affordances; harness templates and the possibility that teams choose architectures by which harnesses exist. The refinement in §24.4 — that the inversion holds for structure and not for sensors — is this book's
- Ashby ✅ canonical — via Chapter 8's constraint; the definition of harnessability as banked variety reduction that makes §24.1 an identity
- Galster, Mohsenimofidi, Lulla, Abubakar, Treude, Baltes. arXiv 2602.14690, AIware '26 [A] ✅ — Hooks at 0.9–3.2%, i.e. most organisations lack even the cheap half of §24.4
- Chen et al. LocAgent. arXiv 2503.09089 [B] ✅ and When to use Graphs in RAG, arXiv 2506.05690 [B] ✅ — the capability and the honest failure rate behind §24.5's ordering claim
- Parnas (1972) ✅ canonical; Evans, Domain-Driven Design ✅ canonical — the structural half, and the reason §24.6 defers bounded contexts
- Ford, Parsons, Kua ✅ canonical — fitness functions as the mechanism for H3
- Taleb — diversity as shock absorption, against efficiency-through-uniformity (§24.7); the barbell shape of its resolution
- The remainder is derived from Chapters 8, 9, 10, 13, 15, 16, and 23, cited inline
Full entries and verification status: references/sources.md.