AI in practice / Design systems

Rules a generator will actually obey.

Free generation against our design system produced output that looked right and was not — which is expensive, because catching a right-looking wrong token needs someone who already knows the system.

ContributionAuthor of the generation contract
PeriodMar – Aug 2026 · ongoing
StatusShipped in the consumer bundle; small-text fixes remain.
4 rulesMoved onto the shipped surface the generator actually reads
52 / 52Shared paths brought to byte-identity with a named commit
14 valuesHardcoded values still needing correction

Right-looking and wrong

One measured build picked the correct typography class and then wrote an inline 28px override on the same element. It used a table row-selection token for navigation active state. It invented a 13px font size that does not exist in the system. It never used the third surface layer at all.

Worse, the sync step was interpreting prompt text that described the design system rather than fetching bytes from the canonical repository. No output had provable identity to the real thing.

Rules live on the shipped surface

I decided the rules live in the shipped consumer bundle, not in the private working spec — and I reversed the copy direction to enforce it. Before this, the spec repository was upstream and the bundle held a mirror marked do-not-hand-edit, which meant the next regeneration would overwrite the contract I had just hand-applied.

Generation reads whatever surface it is mounted against. So the rules have to live on the shipped surface, or they are decoration.

One direction only

The tool pulls from the repository and never pushes upstream. If a fetch fails it says so, instead of falling back to interpreting the prompt.

The contract

A contract section in the bundle README carrying the rules that were being broken most: page titles use a named heading class with no inline override; surfaces use all three layers, with the third on the table container; navigation active state uses a four-token recipe rather than a borrowed table token; and a screenshot never overrides a written rule.

Five standing design system rules, including that prototype files stay private and are never auto-promoted into a public component surface, and that a system-check warning is never resolved by inventing an API to satisfy it.

A twelfth section in the component spec format covering Storybook deliverables — required story list, composition of the canonical story components rather than forked markup, a content-hygiene rule, and full-denominator test reporting. That section exists because good decisions were living in one chat’s history instead of in the contract, and the same defect shipped twice.

Same prompt. Same screenshot.

The A/B is the evidence. Between the old bundle and the contract version, with no constraints from me:

Page titleRight class plus inline override → correct class, no override
NavigationMisused table token plus a 1px outline → full four-token recipe with a 3px accent
SurfacesFlat → two at layer one, two at layer two, one correctly at layer three
Hex literalsZero in both runs
The residual

Small text still leaks: fourteen bare pixel values in one tier, three at 13px, one at 12px. The heading tier obeys the class rule and the label and body tier does not yet — which tells me exactly which line the contract is missing.

Provable identity

After the sync step was found to be interpreting prompt text rather than fetching bytes, an audit against the real repository brought fifty-two of fifty-two shared paths to byte-identity with a named commit. Before that, no generated output could be traced to a known state of the system.

Rules that survive the session

The four contract rules now survive between sessions instead of being re-explained each time, because they live on the surface the generator reads rather than in a conversation.