- Home
- The Thinking Wire
- A Clean Diff Does Not Mean the Contract Is Complete. It May Mean It Is Thin.
A Clean Diff Does Not Mean the Contract Is Complete. It May Mean It Is Thin.
Spec-driven development rests on an assumption we rarely test: that the spec is complete. We check whether the generated artifact matches the spec. We almost never check whether the spec could have described the artifact in the first place.
Nathan Curtis built the test. In August 2026 he published What Component Specs Leave Behind, which walks a component out of a design system into a spec, back into a component, and out into a second spec. Then it diffs the two specs. Whatever survives that loop is what the contract actually carries. Whatever falls out was never in the contract, no matter how confident the document looked.
His own summary, reproduced with the typo as published: “Turns out, around trip [sic] is a brutal test of a contract. Anything a transform and schema can’t capture gets dropped beaming out, and anything a spec captures too loosely risks loss and differences beaming back.”
That sentence is about design tokens and Figma properties. It applies to every spec-governed generated artifact you own.
The Loop, Exactly as Published
Six steps, in order:
generatea baseline spec from an existing component.rendera test component from that spec.generatea test spec from the test component.diffthe baseline spec against the test spec.reportacross an entire library.deletethe test component.
Step six is the part that makes this operable rather than academic. The test component is disposable, so the loop can run over a whole library without polluting it. The artifact under test is destroyed; the diff is the output.
What the Diff Caught
Curtis reports classes of failure, not counts, and the classes are the interesting part.
A hex code emitted where a color token was bound. The rendered component looked right and was wrong in the only way that matters for a design system: it had lost its link to the token.
A maxWidth applied to only the last of many options. The spec described a constraint; the render applied it once.
A backgroundColor change and a layer-presence change omitted when properties interact. selected:true combined with state:hover produces behavior that neither property describes alone. The spec had no vocabulary for the combination, so the combination vanished.
A decorative icon represented as customizable by variant when it should not have been. The contract granted an affordance the design did not intend.
Padding varying by size, depending on whether the label came through a slot or was built in. Two paths through the same component, one of them undocumented.
A Figma BOOLEAN prop and a SLOT prop errantly consolidated into a single nullable slot property. Two distinct concepts collapsed into one because the schema had one place to put them.
And the one that should worry you most: a clipsContent bug that, in Curtis’s words, “silently never worked because it was coded as clipContent.” A missing letter. No error, no warning, no failing test. Human review had not caught it. The round trip did, because the round trip does not read the code, it compares what two independent passes claim the component is.
The Trap in a Clean Result
Here is where the exercise stops being a design-systems story.
A contract that round-trips perfectly may be excellent. It may also be nearly empty. The loop measures fidelity of the transform, not richness of the contract. A spec that captures a handful of properties will round-trip that handful cleanly and say nothing about everything it never mentioned. The diff is silent about everything outside its own vocabulary.
So a clean diff is evidence of nothing until you know how much the contract was carrying. Read the result as a ratio you have to estimate yourself: fidelity over coverage. High fidelity on thin coverage is the most dangerous shape, because it produces a green report and a false sense of governance.
This is the same failure mode as a test suite that passes every test it has while covering a fraction of the code. Nobody would accept that number without the second half. Spec completeness is routinely accepted without it.
Limits That Are Not Bugs
Curtis draws a line worth copying. Some losses in the round trip are defects. Others are permanent structural limits of the platform, and the honest move is to name them rather than chase them.
Two he identifies: custom property order is not exposed by the API for BOOLEAN, INSTANCE_SWAP, TEXT and SLOT props. Locked aspect-ratio bindings cannot carry both width and height bound at the same time. Neither is fixable from inside the spec. Both would show up in a diff forever.
He also names a deliberate non-goal: the motion data model, which he declines to support because “few in our field know it well.” That is a scoping decision recorded as a scoping decision, and it belongs in the spec’s documentation so a future diff does not read it as regression.
A round-trip report without that classification degrades into noise. Every recurring difference needs a label: bug to fix, platform limit to accept, or scope deliberately excluded. Curtis records these against his own internal decision records (he cites ADR-066 and ADR-069, his team’s numbering, not any public standard). The mechanism matters more than the numbering. Differences that nobody has adjudicated will be re-litigated every run until people stop reading the report.
Where Else This Applies
Anything you generate from a machine-readable contract can be round-tripped, and I have not seen one of those contracts tested for what it silently drops.
An OpenAPI schema that generates a client. Generate the client, then generate a schema from the client, and diff. Optionality, discriminated unions and header semantics are where I would look first.
An infrastructure module rendered from a variables file. Render, re-extract, diff. Defaults that only exist in the provider are the ones I would expect not to come back.
A prompt or tool definition that governs an agent. This one is closest to home. If your agent’s contract is a JSON schema plus a description, the round trip asks whether a second reader, given only the schema, would produce the same tool. If it would not, the difference is exactly the behavior your evals cannot explain.
We have argued before that design systems are governance infrastructure, that agents can act as drift detectors against a system assumed correct, and that an agent writing the system is not the same as an agent reviewing it. This inverts all three. Those tested conformance to the contract. The round trip tests the contract.
Do This Now
Take the single most-used component, endpoint, or tool definition you own. Not the whole library. One.
Generate a spec from it with whatever tooling you have. Hand that spec, and only that spec, to a fresh agent session with no access to the original. Have it produce the artifact. Generate a spec from the result. Diff the two.
Then read the diff twice. The first read finds the bugs. The second read asks the harder question: of everything that matters about this artifact, how much did either spec mention at all? Write that number down as an estimate, next to the diff. A clean diff on a thin contract is the outcome you are trying to detect, and it is the one that looks like success.
This analysis synthesizes What Component Specs Leave Behind (Nathan Curtis, August 2026).
Victorino Group helps engineering teams test whether their specs actually carry the contract their generated systems depend on. Let’s talk.
All articles on The Thinking Wire are written with the assistance of Anthropic's Opus LLM. Each piece goes through multi-agent research to verify facts and surface contradictions, followed by human review and approval before publication. If you find any inaccurate information or wish to contact our editorial team, please reach out at editorial@victorinollc.com . About The Thinking Wire →
If this resonates, let's talk
We help companies implement AI without losing control.
Schedule a Conversation