Add workflow infrastructure — ESLint, Prettier, Husky, Vitest, 7 new skills

Phase 1: Session log archived (1096→91 lines), D031 token access convention
Phase 2: ESLint v9 + Prettier + jsx-a11y, initial config and lint fixes
Phase 3: 7 new skills (polish, harden, normalize, clarify, typeset, quieter, adapt)
         + Vercel reference docs, updated audit/review-component refs
Phase 4: Husky + lint-staged pre-commit hooks, preflight updated to 8 checks
Phase 5: Vitest + Testing Library + /write-tests skill

- Badge.tsx colour maps unified to CSS variables (D031)
- 5 empty interface→type alias fixes (Switch, Radio, Divider, IconButton, Link)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-27 16:41:57 +11:00
parent c5bfeaee2f
commit aa7cdeecf0
33 changed files with 7685 additions and 1088 deletions

View File

@@ -0,0 +1,146 @@
---
name: normalize
description: Cross-component consistency scan — checks token access patterns, transitions, focus styles, spacing methods, and displayName across all components in a tier or the entire system.
user-invocable: true
argument-hint: "[tier (atoms/molecules/organisms) or 'all']"
---
Scan all components in a tier (or the entire system) for consistency violations and fix them. Unlike audit/critique which evaluate individual components, **normalize ensures the system behaves as one cohesive whole**. This skill finds AND fixes issues.
**Target tier:** $ARGUMENTS
## Preparation
1. Read `docs/design-system.md` for FA design conventions
2. Read `docs/memory/decisions-log.md` for design rationale (especially D031 on token access)
3. Read `docs/conventions/component-conventions.md` for structural rules
4. List all component files in the target tier(s):
- Atoms: `src/components/atoms/*/`
- Molecules: `src/components/molecules/*/`
- Organisms: `src/components/organisms/*/`
- If target is "all", scan every tier
**FA context**: Consistency is trust. When components behave differently for no reason — different transition speeds, different focus styles, different spacing methods — users sense it even if they cannot articulate it. For families in distress, inconsistency creates subconscious unease. Normalize ruthlessly.
## Consistency Dimensions
For each dimension, scan ALL components in the target scope, compare patterns, identify outliers, and fix them to match the established convention.
### 1. Token Access Patterns (D031)
**Convention**: Two access methods, by token tier:
- **Semantic tokens** (colour, spacing, typography, shape): `theme.palette.*`, `theme.spacing()`, `theme.typography.*`, `theme.shape.*` inside theme callbacks. `var(--fa-color-*)`, `var(--fa-spacing-*)` in static contexts.
- **Component tokens** (badge sizes, card shadows, input dimensions): `var(--fa-badge-*)`, `var(--fa-card-*)` CSS variables only — these are NOT in the MUI theme.
**Scan for violations**:
- [ ] Hardcoded hex/rgb colour values (should use theme or CSS var)
- [ ] Hardcoded px spacing values (should use `theme.spacing()` or `var(--fa-spacing-*)`)
- [ ] Hardcoded font sizes or weights (should use `theme.typography.*`)
- [ ] Semantic tokens accessed via CSS var when inside a theme callback (prefer theme accessor)
- [ ] Component tokens accessed via theme (they are CSS vars only)
- [ ] Primitive tokens used directly instead of semantic tokens
### 2. Transition Timing
**Convention**: 150ms ease-in-out for all state transitions.
**Scan for violations**:
- [ ] Transitions using durations other than 150ms (or `theme.transitions.duration.short`)
- [ ] Transitions using easing other than ease-in-out
- [ ] Transitions using bounce, elastic, or spring easing (remove — feels dated)
- [ ] Missing transitions on interactive state changes (hover, focus, active)
- [ ] Transitions on layout properties (`width`, `height`, `top`, `left`) instead of `transform`/`opacity`
### 3. Focus-Visible Style
**Convention**: `:focus-visible` with 2px outline, offset 2px, high contrast (3:1 minimum against adjacent colours).
**Scan for violations**:
- [ ] `outline: none` without `:focus-visible` replacement
- [ ] Focus styles on `:focus` instead of `:focus-visible` (shows ring on click)
- [ ] Inconsistent outline width, colour, or offset across components
- [ ] Missing focus styles entirely on interactive elements
- [ ] Focus ring colour that does not meet 3:1 contrast
### 4. Spacing Method
**Convention**: `theme.spacing()` in styled components and `sx` props. `var(--fa-spacing-*)` in static contexts.
**Scan for violations**:
- [ ] Raw pixel values for padding/margin/gap (e.g., `padding: '16px'`)
- [ ] Mixed methods in the same component (some `theme.spacing()`, some raw values)
- [ ] Inconsistent spacing scale usage across similar components (e.g., one card uses `spacing(2)` for padding, another uses `spacing(3)`)
### 5. Component Structure
**Convention**: Per `docs/conventions/component-conventions.md`.
**Scan for violations**:
- [ ] Missing `displayName` on the component
- [ ] Missing barrel export (`index.ts` with `export { default }` and `export *`)
- [ ] Missing JSDoc on props interface (every prop needs a `/** description */`)
- [ ] Missing JSDoc on the component itself
- [ ] Props defined as `type` instead of `interface` (interfaces produce better autodocs)
- [ ] Missing `sx` prop forwarding (every component must accept consumer overrides)
- [ ] Interactive elements not using `React.forwardRef`
### 6. Story Coverage
**Convention**: Per story coverage checklist in `docs/conventions/component-conventions.md`.
**Scan for violations**:
- [ ] Missing `tags: ['autodocs']` in story meta
- [ ] Missing Default story
- [ ] Missing AllVariants story (if component has variants)
- [ ] Missing Disabled story (if component can be disabled)
- [ ] Missing Loading story (if component has loading state)
- [ ] Incorrect `title` prefix (should match tier: `Atoms/`, `Molecules/`, `Organisms/`)
### 7. Naming Consistency
**Scan for violations**:
- [ ] Component folder not in PascalCase
- [ ] File names not matching component name
- [ ] Inconsistent prop naming across similar components (e.g., `isDisabled` vs `disabled`, `colour` vs `color`)
- [ ] CSS custom properties not prefixed with `--fa-`
## Normalize Process
1. **Scan**: Read every component file in the target tier(s)
2. **Tabulate**: Build a comparison table for each dimension showing what each component does
3. **Identify outliers**: Find components that deviate from the convention
4. **Fix**: Update outlier components to match the convention
5. **Verify**: Ensure TypeScript compiles and Storybook renders after fixes
## Normalization Report
Present findings in this format:
### Scan Summary
| Dimension | Components scanned | Violations found | Fixed |
|-----------|-------------------|-----------------|-------|
| Token access | ? | ? | ? |
| Transitions | ? | ? | ? |
| Focus styles | ? | ? | ? |
| Spacing | ? | ? | ? |
| Structure | ? | ? | ? |
| Stories | ? | ? | ? |
| Naming | ? | ? | ? |
### Violations Fixed
For each fix, note:
- **Component**: Which component was changed
- **Dimension**: Which consistency rule was violated
- **Before**: What it was doing
- **After**: What it does now
### System-Level Observations
Note any patterns that suggest a convention should be updated (e.g., if most components deviate from the convention, perhaps the convention is wrong).
**NEVER**:
- Change a component's behaviour or API — normalize only changes implementation details
- Fix one component and leave similar components unfixed — normalize the whole tier
- Change conventions without flagging it — if you think a convention should change, note it as an observation, do not unilaterally change the rule