ADR 0005 — Token group lifecycle
Status
Accepted, 2026-05-17.
Context
Adding a new token group (e.g. size-control in foundations, or
color.bone in semantic) requires synchronized changes across multiple
files: JSON definition, TypeScript types, resolver, emit pipeline,
fixtures, and validation. Without a documented process, new additions
risk partial implementation and broken builds.
Decision
Adding a new foundation group requires:
- Add to
packages/core/tokens/foundations.json— the JSON entries under the new group key - Extend
FOUNDATION_GROUPSarray inpackages/core/src/types.ts - Extend
FoundationsTokensinterface inpackages/core/src/types.ts - Update
resolve.tsif cross-tier references will use the new group - Update
__tests__/fixtures.tsso existing core tests still pass under the stricter interface - Verify
pnpm build && pnpm testpasses - Commit as
feat(core): add <group-name> foundation tokens
Adding a new semantic group:
- Add to
packages/core/tokens/semantic.jsonin BOTH light and dark schemes - Extend
SEMANTIC_GROUPSarray if it's a new group key - Extend
SemanticTierinterface if needed - No changes needed in
resolve.tsfor aliases of existing foundation paths - Verify
pnpm buildemits the new CSS custom property - Commit as
feat(core): add <group-name> semantic tokens
Adding component-specific (tier-3) tokens:
- Add to
packages/core/tokens/component-specific.jsononly - No types.ts changes needed — ComponentTier is
Record<string, Record<string, string>>(generic) - No resolver changes needed — resolves to semantic via
{path}syntax automatically - Verify pipeline emits
--{component}-{key}CSS variable - Commit with the component implementation
Promotion criteria
A foundation seed should be promoted to semantic when:
- Two or more components need it (e.g.
color.bonefor Card and Avatar) - Or it represents a system-wide role (e.g.
size-controlfor all interactive elements)
A semantic token should be added when:
- The role is shared across multiple components
- It can be expressed without component-specific context
A tier-3 token should be used when:
- Only ONE component needs the value
- Or component requires precise per-variant control (e.g.
button-background-accent-active)
Consequences
Positive:
- Clear checklist prevents partial implementations
- Architectural intent stays consistent
- CC and other AI agents can follow the process autonomously
Negative:
- Manual coordination across 4-5 files for foundation additions
- Pipeline does not auto-generate types from JSON (deliberate trade-off for IDE autocomplete)
Alternatives considered
- Auto-generated types from JSON — rejected; loses IDE autocomplete for specific group names
- Single generic
Record<string, any>for all tiers — rejected; loses type safety - Schema-driven generation — deferred; over-engineered for current velocity