# Workflow: Audit Mode Review existing motion design and produce a per-designer report. Reconnaissance first, then a full audit, then a structured report. Never apply rules blindly. ## Required Reading Read as you reach each step (not all upfront): 1. `references/audit-checklist.md` — your systematic guide (STEP 2) 2. The weighted designer file(s) — `emil-kowalski.md`, `jakub-krehel.md`, `jhey-tompkins.md` (STEP 2) 3. `references/accessibility.md` — mandatory every audit (STEP 2) 4. `references/anti-checklist.md` — the quality gate: AI-slop motion categories + anti-patterns to flag (STEP 2) 5. `references/output-format.md` — the report template, HTML mode + terminal mode (STEP 3) 6. `references/demo-shell.html` — the demo-card template for HTML-mode per-finding demos (STEP 3) --- ## STEP 1: Context Reconnaissance (DO THIS FIRST) Before auditing any code, understand the project context. ### Gather Context Check these sources: 1. **CLAUDE.md** — Any explicit context about the project's purpose or design intent 2. **package.json** — What type of app? (Next.js marketing site vs Electron productivity app vs mobile PWA) 3. **Existing animations** — Grep for `motion`, `animate`, `transition`, `@keyframes`. What durations are used? What patterns exist? 4. **Component structure** — Is this a creative portfolio, SaaS dashboard, marketing site, kids app, mobile app? ### Motion Gap Analysis (CRITICAL - Don't Skip) After finding existing animations, actively search for **missing** animations. These are UI changes that happen without any transition: **Search for conditional renders without AnimatePresence:** ```bash # Find conditional renders: {condition && } grep -n "&&\s*(" --include="*.tsx" --include="*.jsx" -r . # Find ternary UI swaps: {condition ? : } grep -n "?\s*<" --include="*.tsx" --include="*.jsx" -r . ``` **For each conditional render found, check:** - Is it wrapped in ``? - Does the component inside have enter/exit animations? - If NO to both → this is a **motion gap** that needs fixing **Common motion gap patterns:** - `{isOpen && }` — Modal appears/disappears instantly - `{mode === "a" && }` — Controls swap without transition - `{isLoading ? : }` — Loading state snaps - `style={{ height: isExpanded ? 200 : 0 }}` — Height changes without CSS transition - Inline styles with dynamic values but no `transition` property **Where to look for motion gaps:** - Inspector/settings panels with mode switches - Conditional form fields - Tab content areas - Expandable/collapsible sections - Toast/notification systems - Loading states - Error states ### State Your Inference After gathering context, tell the user what you found and propose a weighting: ``` ## Reconnaissance Complete **Project type**: [What you inferred — e.g., "Kids educational app, mobile-first PWA"] **Existing animation style**: [What you observed — e.g., "Spring animations (500-600ms), framer-motion, active:scale patterns"] **Likely intent**: [Your inference — e.g., "Delight and engagement for young children"] **Motion gaps found**: [Number] conditional renders without AnimatePresence - [List the files/areas with gaps, e.g., "Settings panel mode switches", "Loading states"] **Proposed perspective weighting**: - **Primary**: [Designer] — [Why] - **Secondary**: [Designer] — [Why] - **Selective**: [Designer] — [When applicable] Does this approach sound right? Should I adjust the weighting before proceeding with the full audit? ``` Use the Context-to-Perspective Mapping table in SKILL.md to propose the weighting. ### Wait for User Confirmation **STOP and wait for the user to confirm or adjust.** Do not proceed to the full audit until they respond. If `AskUserQuestion` is available, present the decision as tappable options: - **Confirm weighting** — Proceed with the proposed primary/secondary/selective designers - **Adjust primary** — Swap which designer is primary (e.g., prioritize delight over restraint) - **Adjust secondary** — Change the secondary lens while keeping primary - **Rebuild weighting** — The project type inference was wrong; start over Otherwise ask in plain text: "Does this weighting sound right, or should I adjust?" If they adjust (e.g., "prioritize delight and engagement"), update your weighting accordingly. --- ## STEP 2: Full Audit (After User Confirms) Once the user confirms, perform the complete audit by reading the reference files in this order: ### 2a. Read the Audit Checklist First **Read `references/audit-checklist.md`** — Use this as your systematic guide. It provides the structured checklist of what to evaluate. ### 2b. Read Designer Files for Your Weighted Perspectives Based on your context weighting, read the relevant designer files: - **Read `references/emil-kowalski.md`** if Emil is primary/secondary — Restraint philosophy, frequency rules, decision frameworks - **Read `references/jakub-krehel.md`** if Jakub is primary/secondary — Production polish philosophy, what to check - **Read `references/jhey-tompkins.md`** if Jhey is primary/secondary — Playful experimentation philosophy, opportunities to surface ### 2c. Read Topical References as Needed - **Read `references/accessibility.md`** — MANDATORY. Always check for prefers-reduced-motion. No exceptions. - **Read `references/anti-checklist.md`** — Apply this as the audit's quality gate. AI-slop categories at the top (pulsing indicators, hover-scale-on-everything, stagger-spam, etc.) trigger findings; perspective-specific and general anti-patterns sit below. Each category includes a frequency heuristic so single intentional uses don't trip the gate. - **Read `references/performance.md`** — If you see complex animations, check for GPU optimization issues - **Read `references/motion-cookbook.md`** — Reference when making specific implementation recommendations (the recommended fix code, including the per-finding demo motion in HTML mode) --- ## STEP 3: Output Format (HTML by default) The audit produces a **self-contained HTML report** with auto-looping CSS demos beside Critical and Important findings. **Read `references/output-format.md`** for the full template (both HTML mode and terminal mode). ### Default behavior — write and open the HTML report 1. **Resolve the write location.** The file is written to `motion-audits/{project-name}-{ISO-date}.html` in the audited project's root. - **Audited project root**: run `git rev-parse --show-toplevel` from the agent's cwd. If it succeeds, use that path. If it fails (no `.git` ancestor), use cwd. - **`{project-name}`**: the `name` field from `package.json` at the project root if it exists; else the `name` field from `pyproject.toml`; else the basename of the project root. Strip any scoping prefix (`@scope/pkg` → `pkg`) and sanitize to lowercase kebab-case (`[a-z0-9-]`, replace others with `-`). - **`{ISO-date}`**: today's date as `YYYY-MM-DD`. - Example: `/motion-audits/my-app-2026-05-20.html`. - Do not modify `.gitignore`. The user sees `motion-audits/` in `git status` and decides whether to ignore it. 2. **Read `references/demo-shell.html`** and use it as the template for each demo card. Embed one card per Critical + Important finding (Opportunities do not get demo cards). Use the suffixed-naming contract — `@keyframes motion-{n}-...` and `.demo-card-{n}__motion-target`, `{n}` = the finding's 1-indexed position across the whole report — so multiple findings don't collide on CSS names. 3. **Generate per-finding motion code** by reading the audited code, the relevant lens reference, and `references/motion-cookbook.md` for the recipe. Use the shell's 0% / 66% / 100% cadence at `animation-duration: 3s` (~2s motion, ~1s hold, loop). The `@keyframes` 100% state must match the motion-target's default static rendering so the shell's `prefers-reduced-motion` guard shows the correct final visual. 4. **Write the file.** Create `motion-audits/` if it doesn't exist. Write the complete self-contained HTML document. 5. **Open in the default browser** via OS-detected Bash dispatch: ```bash path="" if [ -n "$WSL_DISTRO_NAME" ] || grep -qi microsoft /proc/version 2>/dev/null; then win_path=$(wslpath -w "$path") cmd.exe /c start "" "$win_path" 2>/dev/null else case "$(uname -s)" in Darwin) open "$path" ;; Linux) xdg-open "$path" ;; MINGW*|MSYS*|CYGWIN*) start "" "$path" ;; *) echo "Unknown platform — open this file manually: $path" ;; esac fi ``` If the open command returns non-zero or the platform is unrecognized, print `Open this file in your browser: {absolute path}` and continue. Never abort the audit because of a failed browser-open. 6. **Print the 3-line terminal summary:** ``` 🎬 Motion audit complete — 🔴 {N} Critical · 🟡 {N} Important · 🟢 {N} Opportunities 📄 Report: {absolute path} 💡 Want the full report inline instead? Re-run with --terminal or say "show inline". ``` ### Terminal mode (flag-triggered) When the user signals terminal mode (`--terminal` / `--inline` / `--no-html` flag, or "show the full report inline" / "skip the HTML" / "terminal only"), **skip the HTML write and the browser-open** and render the decorated-markdown report inline per `references/output-format.md` terminal mode. Do not print the 3-line summary in this case. Do not summarize the audit content in either mode — users want full per-lens perspectives. --- ## Agent Gotchas (Self-Check Before Writing the Report) Common failure modes during HTML report generation. Most break silently or only manifest when a second finding lands in the same report. - **Don't reuse keyframe or class names across findings.** Each demo uses `@keyframes motion-{n}-...` and `.demo-card-{n}__motion-target` where `{n}` is the 1-indexed position across the WHOLE report. Duplicate names mean the second finding shadows the first and the first demo breaks silently. - **Don't redefine the shell's CSS variables.** Per-finding code uses `var(--bg)`, `var(--fg)`, `var(--border)`, `var(--accent)`, `var(--loop-dim)`, `var(--sans)`, `var(--mono)`. Hard-coding colors or fonts breaks dark mode and typography consistency. - **Don't write per-finding overrides inside the `prefers-reduced-motion` block.** The shell's guard collapses all `[class*="__motion-target"]` animations. Make the `@keyframes` 100% state match the motion-target's default static rendering instead. - **Don't include demo cards for Opportunities.** Demos are reserved for Critical and Important. Surface Opportunities in text only. - **Don't animate the report itself.** No entrance, scroll, or mount animations on the report chrome — only the demo cards animate. Animating the report reproduces the AI-slop patterns the audit exists to catch. - **Don't write to cwd if `git rev-parse --show-toplevel` succeeds.** The report goes to `{project-root}/motion-audits/`. Only fall back to cwd when git returns nonzero. - **Don't abort the audit if browser-open fails.** A non-zero exit code is a "no default handler" condition, not an error. Print the path and continue. - **Don't modify `.gitignore`.** The skill never touches it. The user adds `motion-audits/` themselves if they want. - **Don't summarize per-lens findings.** Each section needs its own findings + working-well items + the `Through {Designer}'s lens:` summary. --- ## Success Criteria - [ ] Context gathered (CLAUDE.md, package.json, existing animations, structure) - [ ] Motion gap analysis run — conditional renders checked for missing animation - [ ] Weighting proposed and confirmed by the user - [ ] Audit checklist worked through systematically - [ ] Anti-checklist applied — AI-slop categories checked against the codebase - [ ] Accessibility checked — prefers-reduced-motion verified (mandatory) - [ ] HTML report written to `motion-audits/`, opened in browser, 3-line summary printed (or terminal-mode report rendered inline when flagged) - [ ] Report follows output-format.md with full per-lens sections; Critical + Important findings have looping demo cards