Keep a useful system coherent without treating every exception as a defect. Inspect actual consumers and documentation; rendered behavior outranks a naming preference.
Work
- Locate token, primitive, feature-component, layout, and documentation sources. Inventory only the areas relevant to the request.
- Distinguish accidental drift from intentional differences in task, density, platform, or brand. A raw value or arbitrary utility is a review candidate, not a severity rating.
- Find duplicated behavior, inaccessible variants, missing theme pairs, unstable shared layouts, and undocumented ownership.
- Prioritize by user consequence and spread: a broken keyboard path outranks two inconsistent colors.
- For each change, decide reuse, extension, or new component; identify consumers and compatibility impact. Retire APIs only with a migration route.
- Update DESIGN.md or existing guidance when an authorized change creates a durable convention. Do not create a duplicate registry just to satisfy a template.
Deliver
For audit: finding → evidence → impact → suggested fix → verification, with confirmed facts separated from hypotheses. For implementation: make scoped fixes, update consumers/docs, and recheck affected siblings.
## System review
Sources: token, component, layout, docs locations Maturity: ...
Drift issues
| Issue | Evidence | Impact | Fix | Verification |
|---|---|---|---|---|
Priority fixes
- ...
Guardrails
- ...
Example: two dialog wrappers may legitimately differ in destructive confirmation behavior. Consolidate their shared focus and surface treatment without erasing the distinction.
Verify representative consumers across supported themes, sizes, and states. Do not claim visual improvement from source checks alone. Use `$tokens` for a missing token foundation and `$component` for one component's contract.
## Worked example
```markdown
## System review
**Sources:** Tokens in `src/styles/globals.css`; components in `src/components/ui/`; no DESIGN.md yet.
**Maturity:** Evolving: tokens plus 40 components with no registry.
### Drift issues
| Issue | Evidence | Impact | Fix | Verification |
|---|---|---|---|---|
| Inline hex in feature code | `#3b82f6` twice in `features/reports` | Breaks theming; wrong in the dark theme | Replace with the existing action color role | Render every shipped theme; search for remaining raw hex in consumer code |
| LegacyCard duplicates Card | Two callers; LegacyCard adds only a header slot | Divergent padding and focus behavior | Add the header slot to Card; deprecate LegacyCard with a prop mapping | Update both callers; compare renders before and after |
| Page-specific gutters | `dashboard/settings` sets its own padding | Content edge shifts between routes | Use the shell's existing gutter token | Compare routes at a fixed width |
### Priority fixes
1. Replace stray hex values
2. Deprecate LegacyCard
3. Align settings page gutters
### Guardrails
- Register new components in the inventory before merge; every new token needs a value in each shipped theme.
Gotchas
- A difference is not drift until you know why it exists; a denser table or a stricter destructive dialog may be deliberate.
- Raw-value searches overstate drift: literals at the token source, in fixtures, or in generated code are not defects.
- Merging similar components breaks callers that relied on their differences; list each caller's props before consolidating.
- A fix to a shared token or primitive changes every consumer; render a sample of consumers in each theme before and after.
- A deprecation without an old-to-new prop mapping leaves two components forever.
Boundaries
- Do not use on a brand-new project with no UI yet; use
$tokensinstead. - Do not use when the question is one component's behavior; use
$componentinstead.