<!-- https://getkonjo.com/design/process/governance · source: docs/design/governance.md -->

# Governance

How a token is added, how a chapter changes, and who decides.

> Part of the [Konjo design language](konjo-design-language.md).

A design system without governance becomes a style guide within two quarters: someone needs a
colour, adds it locally, and the palette quietly forks. This chapter is short on purpose —
every rule here exists because its absence has already cost something.

## The source of truth is code

**`packages/design-tokens/tokens.ts` is the only place a design value is defined.** Not this
documentation, not the skill, not Studio's CSS, not a component.

Three references are **generated** from it and are never hand-edited:

| File | Generated from |
|---|---|
| [Token tables](../../.claude/skills/design/references/tokens.md) | `packages/design-tokens/tokens.ts` |
| [Component inventory](../../.claude/skills/design/references/components.md) | `src/components/ui/index.ts` |
| `apps/studio/src/app/tokens.generated.css` | `packages/design-tokens/tokens.ts` |

`npm run design:sync` regenerates all three. `npm run design:check` fails if any is stale, and
runs in CI.

This exists because the alternative was tried. The documentation has published, at various
points: a type scale with two sizes the code did not ship, a contrast token that failed the
law it was created to enforce, a belt ring in a width the ramp does not contain, an
instruction to hand-compose eight components that already existed, and a whole second design
brief — marked *"strict — do not deviate"* — still carrying four superseded colours. Every one
survived multiple careful readings. Generation is not tidiness; it is the only thing that has
worked.

## Adding a token

1. **Prove the existing tokens can't do it.** Most requests are a missing *rule*, not a
   missing value. "There's no colour for a warning row" usually means the feedback pair
   already covers it.
2. **Add it to both palettes.** `ThemeColors = typeof lightColors` makes a one-sided addition
   a compile error — that guard is doing its job when it fires.
3. **State the contrast, computed.** Every colour token arrives with its ratio against the
   surfaces it is legal on, from `scripts/design/contrast.mjs`. Never eyeballed, never
   remembered from a similar value.
4. **Say where it is illegal.** `text.tertiary` is card-only; `surface.tag` needs a border to
   be a control. A token without a boundary becomes a token used everywhere.
5. **`npm run design:sync`**, and commit the regenerated files alongside.
6. **Write the rule in the chapter that owns it.** A value with no prose is a value the next
   agent will misuse.

## Deprecating a token

**Deprecate in place; never delete in the same change.** Mark it `@deprecated` in the token
source with the replacement named, leave it exported, and land the migration separately. A
deleted token is a broken build for anyone mid-branch, and it turns a design decision into a
merge conflict.

A token stops being exported only once `design-check` reports zero uses.

## Changing a rule

- **A rule changes when it is wrong, not when it is inconvenient.** "This screen would look
  better without the budget" is a screen problem.
- **Rules that came from founder calibration are not changed by an agent.** The sixteen
  calibration rounds in [the calibration record](2026-08-22-design-calibration.md) are settled
  decisions — bold athletic, light-first, ceilings not quotas, white cards on a tinted page,
  no shadows, one red role. Reopening one is a conversation, not a commit. The record exists
  precisely so nobody re-litigates from scratch.
- **Everything else is fair game with evidence.** Evidence means a computed ratio, a measured
  count, a screenshot in both themes, or a blind test — not an opinion about taste.
- **A rule with no enforcement decays.** When you add one, say how it gets checked: a
  `design-check` rule, a `design-doc-check` assertion, or an item on the skill's checklist. If
  it cannot be checked at all, say that too, in the rule.

## Say how far a rule reaches

**A rule written in a shape-specific chapter must say whether it is shape-local or system-wide.**
This is the cheapest correction in the whole record and it fixes a failure that has recurred
in every round of the completeness test.

Two examples of the damage, both found by agents who read carefully and still got it wrong:

- *"Never render an unbounded list, and never infinite-scroll"* and the two paging shapes live
  in `studio/tables.md`, in a chapter that opens by defining what a table is and is not. They
  are **system-wide** — a board column and a feed obey them too — but an agent building a board
  had to decide that alone.
- *"A region with nothing to say prints one line"* lives in `studio/dashboard.md` and is
  **shape-local**: it is the fixed-grid answer, and it deliberately overrides the detail-screen
  rule in `states.md`. An agent applying it to a detail screen would be wrong.

Both read as universal truths in the voice they are written in. Neither says which it is.

So, when a chapter states a rule that is not obviously about its own shape:

- **System-wide** → say so, in the sentence: *"this holds for any scrolling collection, not just
  a table."*
- **Shape-local** → say what it overrides and why: *"on a fixed grid, unlike a detail screen…"*
- **A foundation chapter is system-wide by default**, and states its exceptions.
- **A pattern or dialect chapter is shape-local by default**, and states its reach.

A rule with no stated reach will be copied to the shape next door, correctly or not, and
whichever it is will not be your decision.

## Adding a chapter

Chapters live under `docs/design/`, one topic each, and are reachable from the index in the
[spine](konjo-design-language.md) and from the router in
[the design skill](../../.claude/skills/design/SKILL.md). A chapter nobody routes to is a
chapter nobody reads.

Every chapter opens with what it settles and closes with what never ships.

## Testing the documentation

Two tests, one gate. Full protocol: [design-completeness](testing/design-completeness.md).

**The gate is the design-completeness test.** A fresh agent gets the skill, the router **and
[product-facts.md](product-facts.md)**, and specifies a screen. Green is **zero design defects
and zero contradictions** — product blockers do not count against it, as long as each was either
answered from the catalog or named and stopped on. That condition is reachable, and it is the
honest definition of the design layer being done.

**The blind test still runs, and is no longer a gate.** Same setup minus the product facts, with
every question the agent wanted to ask counted as a defect. It cannot come back green, by
construction — some of what it needs was never design information. It is a smoke detector: you
run it to find holes, and it earns its keep by going off. Three rounds of it produced four error
borders invisible in dark mode, eight of nineteen belt ranks invisible on a dark card, a token
that failed the law it existed to enforce, and a reference target teaching heights no token
produces. A passing test would have found none of them.

Confusing the two is what made a working system look broken for three rounds. Keep them separate
and read each for what it measures.

## When the design system cannot answer

Some of what a screen needs is not a design decision. Whether a promotion can be undone, who
may record one, what a removal cascades to — those are product facts, and no amount of design
documentation will contain them.

**The system's job is to make that visible rather than fillable.** A blind test of the
promotion screen produced a specification roughly a third of which was invention wearing the
system's vocabulary, and the most dangerous single line in it was a consequence sentence
asserting what "remove from dojo" does — written confidently, from nothing.

**The answered ones now live in [product-facts.md](product-facts.md)** — promotions, incidents,
removals, waivers, push categories — as given inputs rather than open questions. When a rule
requires a fact that file does not hold, the answer is to name the missing fact and stop, not to
write something plausible; the file's own "Not yet decided" table is where it goes. That applies to the documentation too. A
chapter that does not know something says it does not know, rather than offering a default
nobody chose.

## Who decides

- **Founder** — anything in the calibration record: brand, voice, the budgets, what the
  product feels like.
- **Whoever is building** — everything else, under these rules, with evidence.
- **CI** — whether the documentation is telling the truth. That one is not a judgement call.
