zuvo:design-review — UI/UX Design Consistency Audit
Audit frontend views for design consistency, state completeness, accessibility, and interaction patterns. Two modes: code-based (grep + read, fast) and visual (chrome-devtools screenshots + axe-core WCAG audit, slower).
Scope: Frontend view health, design system adoption, state coverage, a11y compliance, responsive behavior.
Out of scope: Code quality (zuvo:code-audit), test quality (zuvo:test-audit), creating new designs (zuvo:design), qualitative multi-agent review (zuvo:ui-design-team).
Mandatory File Loading
Read these files before any work begins:
../../shared/includes/codesift-setup.md-- CodeSift discovery and tool selection../../shared/includes/env-compat.md-- Agent dispatch and environment adaptation
Print the checklist:
CORE FILES LOADED:
1. codesift-setup.md -- [READ | MISSING -> STOP]
2. env-compat.md -- [READ | MISSING -> STOP]
3. ../../shared/includes/run-logger.md -- [READ | MISSING -> STOP]
4. ../../shared/includes/retrospective.md -- [READ | MISSING -> STOP]
If any file is missing, STOP.
Environment Compatibility
Read ../../shared/includes/env-compat.md for agent dispatch patterns, path resolution, and progress tracking across all supported platforms.
MANDATORY TOOL CALLS — Design Review Validity Gate
INVALID if any tool below is skipped. "DEFERRED", "N/A" NOT valid reasons.
| Tool | Trigger | Skip allowed? |
|---|---|---|
get_file_tree |
Always | NO — find component dirs, theme files |
search_text |
Always | NO — className=, design tokens, CSS variables |
search_symbols |
Always | NO — component discovery |
search_patterns |
Always | NO — DAP anti-patterns |
scan_secrets |
Always | NO — env-var leaks in client code |
audit_scan |
Always | NO — compound check |
| React tools (analyze_renders, analyze_hooks, trace_component_tree) | React detected | NO when React |
Forbidden: same (skipped/N/A/codesift unavailable when deferred — REJECTED).
POSTAMBLE: report on disk → retro appended → ~/.zuvo/append-runlog exit 0. Every DX/DAP finding needs path/to/file.ext:LINE (verify-audit gate).
Mandatory-tools-acknowledgment: I will run get_file_tree + search_text + search_symbols + search_patterns + scan_secrets + audit_scan + React tools (when React) for this design review. Every DX/DAP finding will cite a `path/to/file.ext:LINE` resolving in the current tree.
Use the deterministic preload helper FIRST. Run ~/.zuvo/compute-preload design-review "$PWD". Math gate enforced.
CodeSift Integration
Read ../../shared/includes/codesift-setup.md for the full initialization sequence.
Design-review CodeSift usage:
get_file_tree(repo, path_prefix="src/components/ui")-- UI component inventory with symbol countsfind_references(repo, symbol_name="Button")-- shared component adoption ratesearch_text(repo, query="aria-|role=", regex=true, file_pattern="*.tsx")-- a11y attribute scansearch_text(repo, query="className=.*\\[", regex=true, file_pattern="*.tsx")-- Tailwind magic values
Step 0: Parse $ARGUMENTS
| Argument | Behavior |
|---|---|
| (empty) | Audit all frontend views in src/ (auto-discover) |
[path] |
Audit views in specific directory |
[file] |
Audit single component (deep mode) |
visual |
Enable visual audit via chrome-devtools (requires running dev server) |
--quick |
DX checklist only, skip cross-view analysis |
--fix-critical |
After audit, auto-fix critical gate failures (DX6/DX7/DX10/DX20) |
--dry-run |
With --fix-critical: show planned edits without applying |
--max-files [N] |
Cap audit to N files (default: 30) |
--url [url] |
Dev server URL for visual audit (default: http://localhost:3000) |
loop |
Full cycle: audit, fix critical, re-audit quick, print delta |
--from-ui-team |
Skip visual re-scan (already captured), focus on DX1-DX20 code scoring |
Default: all views, code-only, with cross-view analysis.
Step 0.5: Prerequisites Check
Required (all modes)
| Check | How | If missing |
|---|---|---|
| Frontend files exist | `find src -name ".tsx" -o -name ".jsx" -o -name "*.vue" | head -1` |
| Package.json exists | cat package.json |
WARN -- cannot detect design system |
Required (visual mode only)
| Check | How | If missing |
|---|---|---|
| chrome-devtools MCP | Check whether chrome-devtools tooling is available | Skip visual, run code-only audit |
| Dev server running | `curl -sI [url] | head -1` |
Optional
| Check | How | If missing |
|---|---|---|
| mcp-accessibility-scanner | Check whether accessibility-scanner tooling is available | DX15-DX17 use manual ARIA grep |
| Tailwind config | cat tailwind.config.* 2>/dev/null |
DX2-DX4 token checks adapt |
| Design system artifacts | cat .interface-design/system.json 2>/dev/null |
Structural-only audit (no craft validation) |
Phase 1: Discovery
Step 1: Detect Design System
Auto-detect from project signals:
| Signal | Design System |
|---|---|
@shadcn/ui or components/ui/ with shadcn pattern |
shadcn/ui |
@radix-ui/* in deps |
Radix UI |
@mui/material in deps |
Material UI |
@mantine/core in deps |
Mantine |
@chakra-ui/react in deps |
Chakra UI |
@headlessui/react in deps |
Headless UI |
None + components/ dir |
Custom components |
| None + no shared components | No design system -- flag as DX20 |
Also detect CSS framework (Tailwind, CSS Modules, CSS-in-JS, CSS Variables).
Next.js boundary detection: If Next.js App Router detected, scan for co-located loading.tsx/error.tsx files alongside page.tsx. Pages with boundaries score DX6/DX7=1 automatically. Track as BOUNDARY_MAP.
Report: DESIGN SYSTEM: [name] | CSS: [name] | SHARED: [path] ([N] components)
Step 2: Discover Frontend Views
Find page-level and feature-level components. Classify as PAGE (route-level), FEATURE (>100 lines with data/state), or SHARED (reusable).
If >30 views (or --max-files limit), audit top files by size, capped at limit.
Phase 2: Code Audit (DX1-DX20)
DX Checklist
| # | Check | Critical Gate |
|---|---|---|
| DX1 | Layout structure (flex/grid, no absolute hacks) | No |
| DX2 | Color values from design tokens | No |
| DX3 | Spacing values from scale | No |
| DX4 | Typography from type scale | No |
| DX5 | Component composition (slots, not prop drilling) | No |
| DX6 | Loading state present for async operations | YES |
| DX7 | Error state present with recovery action | YES |
| DX8 | Empty state present for collections | No |
| DX9 | Success/confirmation feedback for mutations | No |
| DX10 | Destructive actions require confirmation | YES |
| DX11 | Form validation with inline errors | No |
| DX12 | Keyboard navigation for interactive elements | No |
| DX13 | Responsive behavior (mobile breakpoints) | No |
| DX14 | Focus management (visible focus rings) | No |
| DX15 | ARIA roles on interactive elements | No |
| DX16 | Color contrast (text: 4.5:1, UI: 3:1) | No |
| DX17 | Screen reader announcements for dynamic content | No |
| DX18 | Consistent interaction patterns across views | No |
| DX19 | Animation/transition timing consistent | No |
| DX20 | Uses shared component library (not one-off implementations) | YES |
Score: 1 = YES, 0 = NO, N/A with justification. N/A excludes from denominator.
Thresholds: PASS >= 80%, CONDITIONAL >= 70% and < 80%, FAIL < 70%. Inequalities, not
70-79%: the score is a percentage of applicable gates and can be fractional, so a hyphenated
band leaves 79.5% ungraded.
Step 3: Batch Code Analysis
Run grep commands across the codebase for:
- ARIA attributes and roles
- Hardcoded color values (hex outside tokens)
- Magic spacing values (arbitrary px/rem)
- Loading/error/empty state patterns
- Confirmation dialog usage
- Focus ring styles
Store as PROJECT_CONTEXT for per-view scoring.
Step 4: Per-View Audit
For each view, read the full component and evaluate DX1-DX20.
Dispatch follows ../../shared/includes/execution-policy.md through env-compat. Reuse existing
authorization within that policy; session restrictions take precedence. Run each required gate
and report its actual independence or an unmet requirement.
If >8 views: Split into batches of 4 and dispatch background agents where possible. Each agent receives the PROJECT_CONTEXT and scores independently.
Output per view:
### [file path]
View type: [PAGE/FEATURE]
DX: DX1=[0/1/NA] ... DX20=[0/1/NA]
Applicable: [N]/20 | Passed: [N] | Score: [%]
Critical gate: DX6=[0/1/NA] DX7=[0/1/NA] DX10=[0/1/NA] DX20=[0/1/NA] -- [PASS/FAIL]
Evidence (critical gates = 1): [DX=evidence pairs]
Anti-patterns: [DAP IDs or "none"]
Tier: [A/B/C/D]
Top 3 issues: [description]
DAP Anti-Patterns
Check for these common UI anti-patterns during scoring:
| ID | Anti-Pattern | Detection |
|---|---|---|
| DAP1 | Prop drilling through 3+ levels | Count prop pass-through depth |
| DAP2 | Inline styles overriding design system | style={{ next to className |
| DAP3 | Inconsistent button hierarchy (multiple primary CTAs) | Count primary-styled buttons per view |
| DAP4 | Missing disabled state on form submit | Button without disabled prop during async |
| DAP5 | Toast/notification without timeout or dismiss | Notification without auto-dismiss logic |
| DAP6 | Modal without escape-to-close | Dialog without onEscapeKeyDown or equivalent |
| DAP7 | Infinite scroll without loading indicator | Scroll listener without skeleton |
| DAP8 | Hard-coded breakpoint values | px media queries instead of theme tokens |
| DAP9 | Z-index wars (arbitrary values) | z-index values not from a defined scale |
| DAP10 | Color used as sole differentiator | Status/state communicated only by color |
| DAP11 | Duplicate component (same purpose, different implementation) | Cross-view comparison |
| DAP12 | Missing reduced-motion support | Animations without prefers-reduced-motion |
Step 5: Cross-View Analysis
After per-view scoring, check cross-cutting concerns:
- Component consistency -- same purpose, different implementations?
- State coverage matrix -- view x state (loading/error/empty/success). Gaps?
- Off-scale values -- count from Step 3 greps
- Icon library inventory -- >1 library = flag
- Shared component adoption rate -- percentage using shared components
Step 5.5: Craft Validation (design system artifacts exist)
Read .interface-design/system.json (preferred) or .interface-design/system.md (fallback). Run 4 Craft Validation Tests:
- Swap Test: Replace tokens with neutrals. Does personality survive?
- Squint Test: Is hierarchy clear when blurred?
- Signature Test: Is the unique element present (5 touchpoints)?
- Token Test: Do actual values match declared tokens?
No system artifacts = skip.
Phase 3: Visual and Accessibility Audit (visual mode only)
Requires: dev server running, chrome-devtools MCP available.
3.1 Screenshots
Capture at 3 breakpoints (1440, 768, 375) via chrome-devtools.
3.2 WCAG Accessibility Scan
If mcp-accessibility-scanner available:
scan_pageper route for axe-core violationsscan_page_matrixfor variant testing (mobile, forced-colors, reduced-motion, zoom-200%)audit_keyboardfor tab order, focus visibility, keyboard traps
axe-core results override grep-based checks: DX15-DX17 scores come from axe-core when scanner ran.
3.3 Computed Styles
Color and font inventories, ARIA attribute verification.
3.4 Cross-View Visual Comparison
Consistency analysis across captured screenshots.
If chrome-devtools unavailable: skip entire Phase 3 with message.
Phase 4: Report
Step 7: Aggregate Results
Combine per-view DX scores + cross-view analysis + visual audit (if run) + craft validation (if run).
Report Sections
- Header -- project, date, design system, CSS framework, mode
- Executive Summary -- average score, critical gate status, tier distribution
- Critical Gate Summary -- DX6/DX7/DX10/DX20 per view
- State Coverage Matrix -- views x states (loading/error/empty/success)
- Per-View Scores -- DX1-DX20 per view with tier
- Cross-View Analysis -- consistency findings
- Anti-Pattern Summary -- DAP occurrences across views
- Craft Validation Results (if system artifacts exist)
- Action Plan -- prioritized: critical gates -> consistency -> state gaps -> design system gaps
- Accessibility Summary (if visual mode ran)
Save to: zuvo/audits/design-review-YYYY-MM-DD.md — at the project root (zuvo/ resolves via git rev-parse --show-toplevel; override $ZUVO_OUTPUT_DIR. See ../../shared/includes/report-output-location.md).
Step 9: Propose Next Actions
If Tier D OR no design system OR DX20 widespread FAIL:
- "Run
zuvo:design extract [path]" -- formalize implicit patterns - "Fix critical gate failures only"
- "Fix specific view"
- "Skip -- keep report"
Otherwise (Tier A-C with design system):
- "[Best action from audit]"
- "Fix critical gate failures only"
- "Fix specific view"
- "Skip -- keep report"
Phase 5: Auto-Fix Critical (if --fix-critical)
Scope guard (NON-NEGOTIABLE): Auto-fix touches ONLY the UI/states layer -- loading wrappers, error boundaries, confirmation dialogs, component imports. Never modify business logic, data fetching, or event handlers.
--dry-run: List planned edits without applying.
For each critical gate failure:
| Gate | Fix |
|---|---|
| DX6=0 | Next.js App Router? Create loading.tsx. Otherwise: wrap with loading state. |
| DX7=0 | Next.js App Router? Create error.tsx. Otherwise: wrap with error state. |
| DX10=0 | Replace destructive onClick with confirmation dialog. |
| DX20=0 | Replace one-off component with shared library equivalent. |
After applying: re-run DX scoring on fixed views to verify gates pass.
Phase 6: Loop Mode (loop argument)
- Audit: Full audit (Phase 1-4) -- baseline scores
- Fix: Apply critical fixes (Phase 5)
- Re-audit: Quick mode -- post-fix scores
- Delta summary:
DESIGN LOOP DELTA
Before: Avg [X]% | Critical gates: [N] FAIL
After: Avg [Y]% | Critical gates: [N] FAIL
Delta: +[Z]% | [N] gates fixed
Remaining: [top 3 unfixed issues]
Next step: [recommendation]
Contract: zuvo:design <-> zuvo:design-review
This skill reads design system artifacts produced by zuvo:design:
system.json(preferred) -- machine-readable, stable token matchingsystem.md(fallback) -- human-readable, craft validation context
No artifacts = purely structural audit (DX1-DX20 only). With artifacts = adds craft validation + intent-aware token matching.
Completion
After completing the audit, print:
DESIGN-REVIEW COMPLETE
-----
Views audited: [N]
Avg DX score: [N]%
-----
Validity Gate (REQUIRED — print BEFORE Run line, AFTER retro append + append-runlog)
VALIDITY GATE
required_tool_calls:
get_file_tree: [<N> | NOT_CALLED]
search_text: [<N> | NOT_CALLED]
search_symbols: [<N> | NOT_CALLED]
search_patterns: [<N> | NOT_CALLED]
scan_secrets: [<N> | NOT_CALLED]
audit_scan: [<N> | NOT_CALLED]
react_tools: [<result> | not_required | NOT_CALLED]
postamble:
retros_log_appended: [yes(bytes_added=N) | NOT_APPENDED]
retros_md_appended: [yes(entry_count=N) | NOT_APPENDED]
verify_audit_pass: [yes(<verified>/<total>) | NOT_RUN | REJECTED]
gate_status: [PASS | FAIL]
If gate_status = FAIL → VERDICT = INCOMPLETE. Append the Run line via the retro-gated wrapper (NOT direct >> runs.log):
printf '%b\n' "$RUN_LINE" | ~/.zuvo/append-runlog
Run: <ISO-8601-Z> design-review <project> - - <VERDICT> - <DURATION> <NOTES> <BRANCH> <SHA7> <INCLUDES> <TIER>
Retrospective (REQUIRED)
Follow the retrospective protocol from retrospective.md.
Gate check → structured questions → TSV emit → markdown append.
If gate check skips: print "RETRO: skipped (trivial session)" and proceed.
After printing this block, append the Run: line value (without the Run: prefix) to the log file path resolved per run-logger.md.
<DURATION>: use N-dimensions (number of DX dimensions scored, typically 20).
Next-Action Routing
| Finding | Action | Command |
|---|---|---|
| DX6/DX7 State incompleteness | Fix component states | zuvo:design [component] improve |
| DX15-DX17 Accessibility violations | Fix a11y | Direct WCAG compliance fix |
| DX13 Responsive missing | Fix responsive | zuvo:design [component] improve |
| 3+ DX failures in same component | Full multi-agent review | zuvo:ui-design-team [path] |
| DAP anti-patterns found | Refactor component | zuvo:refactor [component] |
| No design system detected | Bootstrap design system | zuvo:design extract [path] |