ENFORCEMENT
The design system is enforced in CI — rules are not documentation, they are gates.
CI Gates (PR A)
Four new steps run in build-and-gate before the build:
| Gate | Script | What it checks |
|---|---|---|
| Token build | pnpm tokens:build | Style Dictionary builds without error |
| Token drift | pnpm tokens:check | design-system/dist/ matches source JSON |
| Boundary lint | pnpm lint:token-boundary | No primitive refs in component CSS |
| No-magic-values | pnpm lint:no-magic-values | No raw hex/px/ms/z-index in module CSS |
| Contrast | pnpm lint:contrast | All WCAG AA pairs pass |
Token Boundary Lint
File: scripts/lint-token-boundary.mjs
Rejects any .module.css file that uses a CSS primitive var when a semantic alias exists.
Forbidden (primitives with semantic aliases):
var(--ds-green-NNN)— usevar(--ds-color-signal)(or other signal alias)var(--ds-text-NNN)(digit suffix) — usevar(--ds-color-text-*)var(--ds-space-NNN)(digit suffix) — usevar(--ds-space-pad)or--ds-space-rhythmvar(--ds-text-size-*)— usevar(--ds-font-size-*)
Allowed (no semantic layer exists):
var(--ds-duration-*),var(--ds-ease-*),var(--ds-layer-*),var(--ds-radius-*),var(--ds-border-*),var(--ds-chrome-*)
No-Magic-Values Lint
File: scripts/lint-no-magic-values.mjs
Rejects raw values that should be token references:
- Hex colors (
#rrggbb) — usevar(--ds-color-*) - Raw
pxvalues outside the allowlist — use spacing tokens - Raw
ms/sdurations — usevar(--ds-duration-*) - Raw
z-indexintegers — usevar(--ds-layer-*)
Exceptions are documented in scripts/lint-no-magic-values.allowlist.json.
Naming Convention
Primitives MUST NOT use the --ds-color- prefix. That prefix is reserved for semantic tokens. The boundary lint allowlist var(--ds-color-*) works correctly only if this convention holds.
Adding a New Component
- Create
design-system/components/NewComponent/with 4 files (.tsx,.module.css,.test.tsx,index.ts) - Export from
design-system/index.ts - Use only semantic tokens in
.module.css— boundary lint will fail otherwise - Add
## NewComponentheading inapp/design-system/components/page.mdx— thecheck:component-docsgate will fail if missing - Write Playwright visual baseline in
tests/e2e/design-system-components.spec.ts