$npx -y skills add strongeron/storybook-workbench --skill sb-auditPeriodic Storybook audit — naming-drift survey, archived/decision-board review, lifecycle tagging, usage refresh. Use for 'audit my Storybook', 'find drift', 'show pending decisions', or a periodic catalog health check.
| 1 | # sb-audit — drift survey + decision board |
| 2 | |
| 3 | The periodic gate. Surveys the catalog, seeds the ledger, names consolidation candidates. |
| 4 | |
| 5 | ## Run it |
| 6 | |
| 7 | ```bash |
| 8 | SKILL=${CLAUDE_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}} |
| 9 | CORE=${CLAUDE_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}} |
| 10 | "$SKILL/scripts/audit-drift.sh" # naming drift across stories |
| 11 | "$SKILL/scripts/audit-archived.sh" # L1/L2/L3 preservation surveillance (HEAVY warning) |
| 12 | "$CORE/scripts/find-stories-by-tag.sh" decision:pending # stale decisions needing a nudge |
| 13 | "$CORE/scripts/extract-component-usage.sh" # REFRESH real prop-usage → component-usage.json (auto, no hand-edits) |
| 14 | "$SKILL/scripts/audit-controls.sh" . # Controls-panel coverage: component stories missing argTypes + manager showPanel |
| 15 | "$CORE/scripts/refresh-usage.sh" --docs . # ONE-COMMAND refresh: components + tokens + routes + health JSON + re-stamp per-component usage MDX |
| 16 | |
| 17 | # App flow + component lists: re-run the repo-local app-graph extractor if present, then VALIDATE it |
| 18 | [ -f .storybook/scripts/extract-app-graph.mjs ] && node .storybook/scripts/extract-app-graph.mjs # refresh app-graph.json + component-pages.json |
| 19 | [ -f .storybook/app-graph.json ] && node -e 'const g=require("./.storybook/app-graph.json"); const by={}; for(const e of g.edges) by[e.attribution]=(by[e.attribution]||0)+1; console.log("flow edges by attribution:", by, "| unresolved:", g.unresolvedEdges.length); for (const u of g.unresolvedEdges) console.log(" UNRESOLVED", u.provenance, "→", u.to, "—", u.reason)' |
| 20 | ``` |
| 21 | |
| 22 | **Sequence — don't run all six cold.** Start with `audit-drift.sh` (cheap, names consolidation |
| 23 | candidates). The **HEAVY `audit-archived.sh`** L1/L2/L3 scan only earns its cost once the catalog is |
| 24 | sizable — **skip it under ~20 chosen stories** (nothing to prune yet). Run `audit-controls.sh` + |
| 25 | `extract-component-usage.sh` when you're checking coverage; `refresh-usage.sh --docs` is the |
| 26 | all-in-one rendered refresh — run it last, not alongside the individual extractors it supersedes. |
| 27 | |
| 28 | **One-command usage refresh.** `refresh-usage.sh` runs all four extractors (inventory/token map, |
| 29 | component prop-usage, routes, design-system health — every **rendered** file; see `CONTEXT.md` |
| 30 | §STORAGE MAP) and — with `--docs` — re-stamps every `<Name>.usage.mdx`. The autodocs |
| 31 | import the JSON, so a Storybook rebuild after this reflects current reality with no hand-editing. Trigger |
| 32 | it three ways: per-script (here, or call one extractor directly), every audit (this step), or in CI before |
| 33 | `storybook build`. The `usage` prop on `StateGrid`/`StateMatrix` reads the same JSON to badge each |
| 34 | variant cell with its real call-site count (declared-but-unused → struck through). |
| 35 | |
| 36 | **Auto-refresh usage (no human authoring).** Re-running `extract-component-usage.sh` here keeps |
| 37 | `component-usage.json` current as the app changes; the `usage-profile.mdx` autodocs read that JSON at |
| 38 | build time, so the "real usage in this app" tables update themselves on the next Storybook build. Wire |
| 39 | the same one-liner into CI for repos that want it always fresh. If usage shifted (a variant that was |
| 40 | `declaredButUnused` is now shipped, or vice-versa), flag the affected stories' `usage:unused` tags as a |
| 41 | drift finding. |
| 42 | |
| 43 | ## Decide (ask yourself) |
| 44 | |
| 45 | - **Drift** — 17 names for "empty state" → consolidation candidate; 1 cluster → noise, ignore. |
| 46 | - **Archive** — `audit-archived.sh` flags >20 chosen stories → prune to the durable ledger seeded from |
| 47 | `templates/design-decisions.md` (`$SKILL/scripts/prune-to-ledger.sh`); otherwise leave it. |
| 48 | - **Pending decisions** — stale `decision:pending` → remind stakeholders. |
| 49 | - **Controls coverage** — `audit-controls.sh` flags component stories that pass `args` but wire neither |
| 50 | `argTypes` nor a controls-disable (so they expose no usable Controls panel), and warns if |
| 51 | `.storybook/manager.ts` doesn't `showPanel`. Fix by wiring `argTypes` (unions → select, |