Summary
The orphaned-tokens rule fires on every MD3 semantic color token (surface-*, on-*, inverse-*, *-container, *-fixed, etc.) because they aren't referenced by any entry in components:. Result: every one of the three shipped examples (examples/atmospheric-glass, examples/paws-and-paths, examples/totality-festival) fails linting with 33–43 orphan warnings each, zero errors.
Reproduce
git clone https://github.com/google-labs-code/design.md && cd design.md
bun install && bun run build # or: cd packages/cli && npm install && npm run build
for ex in atmospheric-glass paws-and-paths totality-festival; do
echo "=== $ex ==="
node packages/cli/dist/index.js lint examples/$ex/DESIGN.md | jq '.summary'
done
Expected output:
=== atmospheric-glass ===
{ "errors": 0, "warnings": 43, "infos": 1 }
=== paws-and-paths ===
{ "errors": 0, "warnings": 33, "infos": 1 }
=== totality-festival ===
{ "errors": 0, "warnings": 38, "infos": 1 }
All warnings are of the form 'surface-container-low' is defined but never referenced by any component.
Why this is a false positive
MD3-style token systems are semantic layers, not component property primitives. Tokens like surface-container-low, on-secondary-container, or inverse-primary are meant to be consumed by the theme / runtime / CSS custom properties — not declared explicitly in each component entry. The spec itself acknowledges this non-component-driven usage:
A common convention is to name the palettes in this order: primary, secondary, tertiary, and neutral. (spec.md § Colors)
The rule assumes every color token must have a components: consumer, which inverts the semantic-layer pattern the examples themselves model.
Proposed fix
Skip the rule when the token name matches the MD3 semantic namespace:
^(surface|on-|inverse-|primary-|secondary-|tertiary-|neutral-|error-|background|scrim|shadow)
Or, more conservatively, downgrade orphaned-tokens to severity: info for tokens matching that pattern. Authors who genuinely want strict orphan detection can re-raise severity via a custom rule.
Happy to open a PR if this direction is acceptable — have a working patch against linter/rules/orphaned-tokens.ts ready to submit once the CLA is signed.
Context
Caught while integrating @google/design.md as a library in an external bridge (oknemix/os, tools/design-md-bridge). All 299 of our regression tests pass, but the orphaned-tokens signal was too noisy to surface real issues until we mapped the pattern. Sharing upstream because every user of MD3-shaped tokens hits the same wall.
Summary
The
orphaned-tokensrule fires on every MD3 semantic color token (surface-*,on-*,inverse-*,*-container,*-fixed, etc.) because they aren't referenced by any entry incomponents:. Result: every one of the three shipped examples (examples/atmospheric-glass,examples/paws-and-paths,examples/totality-festival) fails linting with 33–43 orphan warnings each, zero errors.Reproduce
Expected output:
All warnings are of the form
'surface-container-low' is defined but never referenced by any component.Why this is a false positive
MD3-style token systems are semantic layers, not component property primitives. Tokens like
surface-container-low,on-secondary-container, orinverse-primaryare meant to be consumed by the theme / runtime / CSS custom properties — not declared explicitly in each component entry. The spec itself acknowledges this non-component-driven usage:The rule assumes every color token must have a
components:consumer, which inverts the semantic-layer pattern the examples themselves model.Proposed fix
Skip the rule when the token name matches the MD3 semantic namespace:
Or, more conservatively, downgrade
orphaned-tokenstoseverity: infofor tokens matching that pattern. Authors who genuinely want strict orphan detection can re-raise severity via a custom rule.Happy to open a PR if this direction is acceptable — have a working patch against
linter/rules/orphaned-tokens.tsready to submit once the CLA is signed.Context
Caught while integrating
@google/design.mdas a library in an external bridge (oknemix/os,tools/design-md-bridge). All 299 of our regression tests pass, but the orphaned-tokens signal was too noisy to surface real issues until we mapped the pattern. Sharing upstream because every user of MD3-shaped tokens hits the same wall.