ADR-085 ActifActive contract

`audit-tokens.js` debt triage: exclusions, `audit-ignore` escape hatch, 7 promoted tokens

DateDate
2026-07-22
DécideursDecision makers
Guilherme Negreiros — Design System Lead

Context

The backlog carried a P2 ticket: ~5800 violations reported by node scripts/audit-tokens.js --ci (noted 2026-07-08, already down to ~2508 by this session — other work in between had organically reduced it), with the ticket explicitly flagging that "many are plausible" (e.g. direct component.jsonprimitive.* references) and asking for a triage with the Design System Lead.

A full categorized breakdown of the ~2508 violations showed four structural buckets accounting for ~96% of the total, none of which represented real drift in authored, enforceable source:

CategoryCountWhy not real debt
packages/tokens/{css,js,tailwind,tokens}/1758 (70%)Style Dictionary build output, gitignored, regenerated by npm run tokens — hex values there are the resolved primitives doing their job, not drift
decisions/*.md392 (16%)ADRs cite historical hex values while explaining a past decision (e.g. "teal.9 → #12A594") — an ADR is immutable once active (decisions/README.md), not enforceable current code
packages/components/agtc-*.js~19Verbatim gitignored copy of components/*.js — pure duplicate of violations already counted there
scripts/figma/*.js45 (2%)Figma Plugin API scripts read hex directly from tokens/*.json to apply Figma paints — the Plugin API has no CSS var() concept, literal hex is expected

site/audit-lib.js's CONTRAST_PAIRS fixture (30 violations) turned out to be a fifth, narrower case: literal hex used as WCAG contrast-check test data, already self-documented in a comment as intentional — but audit-tokens.js had no escape-hatch mechanism at all (unlike scripts/audit-language.js's lang-audit-ignore), so a reviewed exception had no way to stop being reported.

A sixth, unrelated finding surfaced while investigating the file most responsible for the remaining real debt (site/build.js, 182 of the post-exclusion 750 violations): 7 CSS custom properties — --agtc-semantic-fontWeight-bold, --agtc-semantic-fontWeight-display, --agtc-semantic-radius-pill, --agtc-semantic-color-border-strong, --agtc-semantic-color-accent, --agtc-semantic-color-secondary, --agtc-semantic-color-tertiary — were declared locally in site/build.js's own :root extension block, under the --agtc-semantic-* prefix (implying they're part of the real token system), but were never actually added to tokens/semantic.json. The code even carried its own comment acknowledging this: "Brand semantic tokens (nouveaux — absents de tokens/semantic.json)". --agtc-semantic-fontWeight-bold/-display alone were used 60+ times throughout the file — an established de facto convention, not a one-off typo. This is audit-tokens.js's separate "Phantom tokens" check (#2: used in code but not defined), distinct from the "hardcoded values" check (#3) that accounts for the bulk of the ~2508.

Decision

1. scripts/audit-tokens.js now excludes, by path:

gitignored build output (mirrors the exclusion scripts/audit-language.js already had).

neither of which is enforceable "current source" in the sense this audit checks.

2. scripts/audit-tokens.js gains an audit-ignore line-comment escape hatch, mirroring lang-audit-ignore: a line containing the string audit-ignore is skipped by the hardcoded- value check. Applied immediately to site/audit-lib.js's CONTRAST_PAIRS (15 lines), the one already-self-documented case that needed it.

3. The 7 phantom tokens are promoted to real entries in tokens/semantic.json (and one new primitive, primitive.fontWeight.extrabold: 800 — no primitive step existed at that weight):

the existing per-context typography.*.weight tokens.

precedent as component.badge.md.radius). This also fixes a real bug: the local shim had it at 999px, one digit short of the conventional "large enough to always fully round" value — harmless in practice (every real instance is far smaller than 999px, so the visual output is identical), but wrong on its face.

shim's value exactly.

accent/secondary/tertiary trio the code already treated as a set. accent and secondary already existed as real tokens (semantic.color.brand.accent/.secondary) with values identical to the fake local ones — site/build.js's usages were renamed to point at the real names instead of getting new aliases.

and brand-tertiary had no dark override at all under their real names — the fake shim's dark-tuned values (#ff8aa1, #6b7280, deliberately different from the light values for contrast) were carried over to the real token names rather than dropped, to avoid a silent dark-mode contrast regression.

needed there.

4. site/build.js's local :root shim block removed (7 fake-semantic lines + 5 lines of duplicated primitive accent/secondary steps that were also just gitignored-primitives.css duplicates with identical values) — the real tokens now flow through site/build.js's own tokensCSS() function, which independently flattens tokens/semantic.json (it does not consume Style Dictionary's compiled output directly).

Rejected alternatives

AlternativeReason for rejection
Triage all ~2508 violations line-by-line with audit-ignore comments, no path exclusions~2150 of them sit in gitignored generated output or immutable historical ADRs — annotating files that are either not committed or not meant to be edited again would be pointless busywork
Leave the 7 phantom tokens as an undocumented site-local conventionThe naming already claims to be part of the real token system (--agtc-semantic-* prefix) and is used 60+ times — leaving it un-promoted keeps the phantom-token check permanently red for no reason, and keeps a real (if minor) radius-pill bug alive
Rename brand-accent/brand-tertiary dark-mode usages to fall back to the light value rather than adding dark overridesWould have silently regressed dark-mode contrast — the fake shim's separate dark values were deliberate, not accidental

Consequences

a 90% reduction). The remainder is genuine per-line triage in site/build.js, .stories.js, and a few test files — no more systemic bucket.

color.border.strong, color.brand.tertiary; tokens/primitives.json gains fontWeight.extrabold.

custom property resolves to the exact same value as before in both themes — zero visual regression, confirmed by direct computed-style comparison, not just a screenshot glance.

← ADR-084 ADR-086 →