If naming every value is what keeps generated UI on-system, must you name all of them? I gave the model one component built perfectly and measured what it learned from it. Nothing — and it made every remaining error deterministic.
A real design system has hundreds of components, so I tested the obvious shortcut: show the AI one component built perfectly and let it learn the pattern. It doesn’t work.
Worse, the example’s own spacing became a rule the AI applied everywhere — including the places where that spacing was wrong. Without the example it guessed differently each time, and inconsistent output looks like a bug someone fixes. With the example it was wrong the same way every single time, which looks like a decision and survives review.
Field test 01 found that completeness is what holds generated UI on-system — naming every value took first-build accuracy from 93.2% to 100%, while rephrasing the same information changed nothing.
Which raises the question any team with a real system asks next. A design system has hundreds of components. Do I have to specify every value in every one of them — or can I document one properly and let the model generalise?
It is a reasonable hope. It is how we teach people.
Same rig, same 74-property rubric, same isolation: each run performed by a separate agent that sees only the tokens and one condition, in a directory containing nothing else.
Two conditions, differing by exactly one file:
| Condition | Documentation | Plus |
|---|---|---|
| A | Prose. Every selector named, zero of 74 values given — spacing described only as “tighter than a button’s”, “one step up from the field scale”. | — |
| E | The identical prose. | One complete, correct implementation of the button |
The button is excluded from scoring. Condition E is handed its implementation, so counting it would let that component score itself. Both are compared over the remaining 58 properties across input, badge, card and tabs.
One nuance worth stating, because it makes the test harder rather than easier: a real design system reuses its tokens, so the button’s implementation contains values the other components also use — 36px is both the button and the field height. The values are visible. What is not stated is which other properties they belong to. That mapping is exactly what a model would have to generalise.
The example taught nothing. E lands at the bottom of A’s own range, so with three runs the 1.7-point gap is not a meaningful decline — the honest statement is that one perfectly documented component produced no improvement whatsoever on the components around it.
I recorded a prediction before running it: the card-padding failure from test 01 would survive, because nothing in a button implementation says what a card’s padding is. That held.
What I did not predict is the interesting part.
Without the example, the model was inconsistent. It sometimes got the card gap right and sometimes did not. With the example it never got it right, and all three runs came back with exactly the same score — the same mistakes, every time.
| Failure | Specified | Generated | A · no example | E · with example |
|---|---|---|---|---|
| .card padding ×4 | 20px | 16px | 3/3 | 3/3 |
| .tablist gap | 4px | 8px | 2/3 | 3/3 |
| .card gap | 12px | 8px | 1/3 | 3/3 |
One of the generators explained the mechanism in its own report, unprompted — it was not asked to justify anything:
“Standard spacing step” is pinned to 8px by the reference button’s gap: 8px, so label-to-field spacing, card child gap, and tab gap all use 8px.
Generator E2, in its own wordsThe button’s gap: 8px was read as the standard spacing step, and applied to two properties it does not govern: the card gap, which is 12px, and the tablist gap, which is 4px. The example did not fill the gap in the documentation. It filled it with its own value, confidently.
An example teaches form, not values. Where a value is missing, it supplies its own as though it were the rule.
Guessing wrong occasionally and being wrong every time score almost identically. They are not the same problem at all.
Wrong-sometimes shows up as inconsistency. Two cards with different gaps, on the same screen, in the same sprint. Somebody notices, because it looks like a mistake.
Wrong-every-time looks like a decision. Every card gets 8px. It is uniform, self-consistent, and wrong in exactly the same way everywhere — which is indistinguishable from a choice somebody made, and survives review for exactly that reason.
So the practical advice is narrower than “write good examples”. Examples are worth having, but they are not a substitute for naming the value, and an example placed next to an under-specified rule will quietly propagate its own numbers into everything nearby.
Three runs per condition, one model, 58 graded properties, one worked example of one component. A larger example set, or an example closer to the component being generated, could behave differently — this shows what one example did, not what examples in general do.
The rig, both conditions, all runs, the auditor and the prediction recorded before the runs are public.