diff --git a/.claude/CUSTOM-AGENTS-GUIDE.md b/.claude/CUSTOM-AGENTS-GUIDE.md index 3492fb5..825c890 100644 --- a/.claude/CUSTOM-AGENTS-GUIDE.md +++ b/.claude/CUSTOM-AGENTS-GUIDE.md @@ -139,7 +139,7 @@ User: "Use the accessibility-auditor agent to check this page" ## Agent + Skill Integration -Agents work alongside the 19 custom skills in `.claude/skills/`: +Agents work alongside the 20 custom skills in `.claude/skills/`: | Agent | Complementary Skill | |-------|-------------------| diff --git a/.claude/skills/README.md b/.claude/skills/README.md index 23c20a8..3d6ee8d 100644 --- a/.claude/skills/README.md +++ b/.claude/skills/README.md @@ -1,7 +1,7 @@ # Skills Catalog -**Last Updated:** 2026-03-18 -**Total Skills:** 17 +**Last Updated:** 2026-05-23 +**Total Skills:** 20 **Location:** `.claude/skills/` Skills are documentation-based workflows that trigger automatically when relevant keywords appear in conversation. They provide systematic guidance, not tool integrations. @@ -44,69 +44,86 @@ These skills power the `/build-from-figma` and `/build-from-canva` autonomous pi - **Triggers:** "visual QA", "compare to Figma", "screenshot diff", "verify app" - **Works with:** visual-qa-agent, Chrome DevTools MCP, Figma MCP -### Canva Pipeline Skills +#### 7. parallel-orchestration (Phases 4-9) +- **Purpose:** Concurrent phase runner that dispatches independent pipeline phases in parallel, respecting the dependency graph and resource constraints defined in `pipeline.config.json`. +- **Triggers:** Invoked by pipeline commands after Phase 3 (TDD gate) +- **Works with:** all build/QA phases; falls back to sequential execution when disabled -These skills power the `/build-from-canva` autonomous pipeline. They handle Canva-specific phases (1, 2) before converging with the shared pipeline (phases 3-9). +### Canva & Screenshot Pipeline Skills -#### 7. canva-intake (Phase 1 -- Canva) +These skills power the `/build-from-canva` and `/build-from-screenshot` autonomous pipelines. They handle source-specific phases (1, 2) before converging with the shared pipeline (phases 3-9). + +#### 8. canva-intake (Phase 1 -- Canva) - **Purpose:** Structured discovery for Canva designs. Exports screenshots via Canva AI Connector MCP, uses Claude vision to analyze page structure and components, asks 3-5 targeted questions, and produces a `build-spec.json` with `source: "canva"`. - **Triggers:** Phase 1 of `/build-from-canva`, or any Canva design URL conversation - **Output:** `.claude/plans/build-spec.json` -#### 8. canva-token-inference (Phase 2 -- Canva) -- **Purpose:** AI-powered token extraction from Canva screenshots with confidence scoring. Uses Claude vision to infer colors, typography, spacing, and effects. Presents tokens with confidence levels for user confirmation before locking. -- **Triggers:** Phase 2 of `/build-from-canva`, "extract Canva tokens", "Canva design tokens" +#### 9. canva-token-inference (Phase 2 -- Canva/Screenshot) +- **Purpose:** AI-powered token extraction from Canva or screenshot sources with confidence scoring. Uses Claude vision to infer colors, typography, spacing, and effects. Presents tokens with confidence levels for user confirmation before locking. +- **Triggers:** Phase 2 of `/build-from-canva` and `/build-from-screenshot`, "extract Canva tokens", "Canva design tokens" - **Output:** `src/styles/design-tokens.lock.json`, `tailwind.config.ts`, `src/styles/tokens.css` +#### 10. screenshot-intake (Phase 1 -- Screenshot) +- **Purpose:** Structured discovery from a URL or provided screenshot files. Captures pages via Chrome DevTools or Playwright MCP, analyzes structure with Claude vision, and produces a `build-spec.json` with `outputTarget`. +- **Triggers:** Phase 1 of `/build-from-screenshot`, "build from screenshot", "clone this site" +- **Output:** `.claude/plans/build-spec.json` + ### React Development Skills These skills provide patterns and best practices. They trigger on relevant keywords during any React development work. -#### 9. react-component-development +#### 11. react-component-development - **Purpose:** Component patterns, TypeScript conventions, custom hooks, composition, and Tailwind CSS best practices - **Triggers:** "create component", "component pattern", "custom hook", "React best practices" - **Works with:** frontend-developer agent, ui-designer agent -#### 10. react-testing-workflows +#### 12. react-testing-workflows - **Purpose:** Testing strategy with Vitest, React Testing Library, Playwright, and Storybook - **Triggers:** "write tests", "test coverage", "Vitest", "Playwright", "Storybook" - **Works with:** test-writer-fixer agent, test-results-analyzer agent -#### 11. react-performance-optimization +#### 13. react-performance-optimization - **Purpose:** Performance profiling, bundle analysis, code splitting, and Web Vitals - **Triggers:** "performance", "bundle size", "Web Vitals", "lazy loading", "profiling" - **Works with:** performance-benchmarker agent, analytics-reporter agent -#### 12. react-accessibility +#### 14. react-accessibility - **Purpose:** WCAG 2.1 AA patterns for React, ARIA usage, keyboard navigation, focus management - **Triggers:** "accessibility", "WCAG", "ARIA", "a11y", "keyboard navigation" - **Works with:** accessibility-auditor agent, ux-researcher agent -#### 13. state-management +#### 15. state-management - **Purpose:** State architecture decisions — Zustand for global UI state, TanStack Query for server state, URL state patterns, and anti-patterns to avoid - **Triggers:** "state management", "zustand", "tanstack query", "react query", "global state", "data fetching", "caching" - **Works with:** frontend-developer agent -#### 14. form-handling +#### 16. form-handling - **Purpose:** Form patterns with React Hook Form + Zod — typed forms, reusable field components, dynamic field arrays, multi-step wizards, server actions, and accessible error handling - **Triggers:** "form", "form handling", "react hook form", "zod", "validation", "multi-step form", "wizard" - **Works with:** frontend-developer agent, accessibility-auditor agent -#### 15. auth-flows +#### 17. auth-flows - **Purpose:** Authentication patterns — Auth.js v5 (NextAuth), Clerk, Supabase Auth. Covers session management, protected routes, OAuth, and role-based access control (RBAC) - **Triggers:** "auth", "authentication", "login", "sign in", "session", "protected route", "OAuth", "clerk", "supabase auth" - **Works with:** backend-architect agent, frontend-developer agent -#### 16. animation-motion +#### 18. animation-motion - **Purpose:** Animation patterns — Framer Motion (motion/react), CSS transitions, page transitions, scroll-driven animations, staggered lists, and reduced-motion accessibility - **Triggers:** "animation", "framer motion", "transition", "micro-interaction", "page transition", "scroll animation", "motion" - **Works with:** frontend-developer agent, whimsy-injector agent -#### 17. seo-metadata +#### 19. seo-metadata - **Purpose:** SEO patterns — Next.js Metadata API, Open Graph tags, dynamic OG images, structured data (JSON-LD), sitemaps, robots.txt, and Vite SPA SEO with react-helmet-async - **Triggers:** "SEO", "metadata", "open graph", "og image", "sitemap", "structured data", "json-ld", "meta tags" - **Works with:** frontend-developer agent, content-creator agent +### Export Skills + +#### 20. export-design-system +- **Purpose:** Exports generated components + `design-tokens.lock.json` as a publishable pnpm workspace. Generates a framework-agnostic tokens package and a framework-specific component library (React/Vue/Svelte via Vite library mode, React Native via tsc), with Tailwind preset, ThemeProvider, and Changesets versioning. +- **Triggers:** `/export-design-system`, "export design system", "publishable component library" +- **Output:** `packages/` pnpm workspace (tokens + component library) + --- ## Pipeline Flow diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d07173f..9c1abe8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -142,6 +142,9 @@ jobs: [ $count -eq 0 ] && echo "Note: no skill .md files found in .claude/skills/" exit $errors + - name: Check doc counts match agents/skills on disk + run: bash scripts/check-doc-counts.sh + - name: Validate templates run: | errors=0 diff --git a/.husky/pre-commit b/.husky/pre-commit index 4cc7734..e052c35 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -2,3 +2,8 @@ if [ -f "scripts/verify-tokens.sh" ] && [ -d "app/src" ]; then bash scripts/verify-tokens.sh fi + +# Pre-commit hook: flag drift between documented agent/skill counts and disk +if [ -f "scripts/check-doc-counts.sh" ]; then + bash scripts/check-doc-counts.sh +fi diff --git a/CLAUDE.md b/CLAUDE.md index 98827b1..7050a29 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -17,8 +17,8 @@ The framework is designed for: ``` project-root/ ├── .claude/ # Claude Code configuration -│ ├── agents/ # 51 specialized agents -│ ├── skills/ # 19 React-specific skills +│ ├── agents/ # 53 specialized agents +│ ├── skills/ # 20 React-specific skills │ ├── commands/ # Custom slash commands │ ├── hooks/ # Hook scripts (automated hooks configured in settings.json) │ └── pipeline.config.json # Pipeline thresholds, iteration limits, app types @@ -546,6 +546,7 @@ gh issue create # Create issue ./scripts/regression-test.sh # Visual regression testing ./scripts/export-design-system.sh # Export components + tokens as pnpm workspace ./scripts/validate-pipeline-config.sh # Validate pipeline.config.json against schema +./scripts/check-doc-counts.sh # Flag drift between documented agent/skill counts and disk ./scripts/verify-all.sh # Run all quality checks with summary ./scripts/verify-all.sh --ci # CI mode: JSON output, exit 1 on any failure ``` @@ -564,7 +565,7 @@ node scripts/metrics-dashboard.js summary # Quick metrics summary --- -**Last Updated:** 2026-05-21 +**Last Updated:** 2026-05-23 **Architecture:** 53 agents, 20 skills, 4 plugins + gh CLI, Figma + Canva + Playwright MCP, 33 scripts, 8 hooks -> **Keeping counts in sync:** When adding or removing agents, skills, scripts, or hooks, update all count references across the project. Search for the old count number in `*.md` files to find all references: `CLAUDE.md`, `README.md`, `CONTRIBUTING.md`, `docs/onboarding/`, `docs/react-development/`, and `.claude/AGENT-NAMING-GUIDE.md`. +> **Keeping counts in sync:** When adding or removing agents, skills, scripts, or hooks, update all count references across the project. Search for the old count number in `*.md` files to find all references: `CLAUDE.md`, `README.md`, `CONTRIBUTING.md`, `docs/onboarding/`, `docs/react-development/`, and `.claude/AGENT-NAMING-GUIDE.md`. The agent and skill counts are enforced automatically by `scripts/check-doc-counts.sh` (run in CI and on pre-commit), which recounts `.claude/agents/` and `.claude/skills/` and fails on any documented count that disagrees. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 695b51e..8a8d3a2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -137,7 +137,7 @@ Because the bump is derived from commit history, **conventional commit messages ## Claude Code Agents -Aurelius includes 53 specialized Claude Code agents and 19 skills that automate significant portions of the development workflow — from design-to-code conversion to testing, accessibility, and deployment. +Aurelius includes 53 specialized Claude Code agents and 20 skills that automate significant portions of the development workflow — from design-to-code conversion to testing, accessibility, and deployment. If you have Claude Code installed, these agents and skills are available to you automatically when working in this repository. They can assist with component development, test writing, visual QA, and much more. diff --git a/README.md b/README.md index 4590bce..e3741eb 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ A Claude Code-integrated multi-framework app development framework with TypeScri ## What This Framework Provides -- **48 Custom Agents** -- Specialized AI agents for engineering, design, testing, marketing, operations, and more -- **17 Development Skills** -- Automated workflows for Figma/Canva conversion, TDD, E2E testing, visual QA, state management, forms, auth, animation, SEO, and more +- **53 Custom Agents** -- Specialized AI agents for engineering, design, testing, marketing, operations, and more +- **20 Development Skills** -- Automated workflows for Figma/Canva conversion, TDD, E2E testing, visual QA, state management, forms, auth, animation, SEO, and more - **10-Phase Design-to-React Pipeline** -- Convert Figma or Canva designs into fully working, tested React apps with a single command - **App-Type Awareness** -- Tailored build and test strategies for web apps, Chrome extensions, and PWAs - **Testing Stack** -- Vitest, React Testing Library, Playwright (cross-browser), Storybook, and pixel-diff visual QA @@ -85,8 +85,8 @@ project-root/ │ ├── canva-to-react/ # Canva pipeline guide │ └── react-development/ # Development standards ├── .claude/ # Claude Code configuration -│ ├── agents/ # 48 custom agents -│ ├── skills/ # 17 development skills +│ ├── agents/ # 53 custom agents +│ ├── skills/ # 20 development skills │ ├── commands/ # Slash commands (/build-from-figma, /lint, /test) │ ├── pipeline.config.json # Pipeline thresholds and app-type definitions │ ├── CUSTOM-AGENTS-GUIDE.md # Agent catalog @@ -136,15 +136,15 @@ All thresholds and behavior are configurable in `.claude/pipeline.config.json`: - Lighthouse minimums (performance: 80, accessibility: 90) - App-type-specific E2E strategies -## 48 Custom Agents +## 53 Custom Agents Agents are auto-selected by Claude Code based on your task: | Category | Count | Key Agents | |----------|-------|------------| -| Engineering | 10 | frontend-developer, backend-architect, rapid-prototyper, test-writer-fixer, error-boundary-architect, migration-specialist, i18n-engineer | +| Engineering | 12 | frontend-developer, backend-architect, rapid-prototyper, test-writer-fixer, error-boundary-architect, migration-specialist, i18n-engineer, animation-optimizer, bundle-analyzer | | Design | 5 | ui-designer, ux-researcher, brand-guardian | -| Design-to-Code | 3 | figma-react-converter, canva-react-converter, asset-cataloger | +| Design-to-Code | 6 | figma-react-converter, canva-react-converter, vue-converter, svelte-converter, react-native-converter, asset-cataloger | | Testing & QA | 7 | visual-qa-agent, accessibility-auditor, api-tester, performance-benchmarker | | Product | 3 | sprint-prioritizer, feedback-synthesizer, trend-researcher | | Marketing | 7 | content-creator, growth-hacker, app-store-optimizer | @@ -154,9 +154,9 @@ Agents are auto-selected by Claude Code based on your task: Full catalog: `.claude/CUSTOM-AGENTS-GUIDE.md` -## 17 Development Skills +## 20 Development Skills -### Pipeline Skills (Phases 1-6) +### Pipeline Skills | # | Skill | Purpose | |---|-------|---------| @@ -166,27 +166,35 @@ Full catalog: `.claude/CUSTOM-AGENTS-GUIDE.md` | 4 | figma-to-react-workflow | Generate components that pass the tests | | 5 | visual-qa-verification | Pixel-diff comparison loop with region analysis | | 6 | e2e-test-generator | Generate Playwright E2E tests (app-type-aware) | +| 7 | parallel-orchestration | Concurrent phase execution with dependency graph | -### Canva Pipeline Skills +### Canva & Screenshot Pipeline Skills | # | Skill | Purpose | |---|-------|---------| -| 7 | canva-intake | Canva design discovery + build-spec.json generation | -| 8 | canva-token-inference | AI-powered token extraction from Canva screenshots | +| 8 | canva-intake | Canva design discovery + build-spec.json generation | +| 9 | canva-token-inference | AI-powered token extraction from Canva/screenshot sources | +| 10 | screenshot-intake | URL/screenshot capture + vision-based discovery | ### React Development Skills | # | Skill | Purpose | |---|-------|---------| -| 9 | react-component-development | Component patterns, hooks, composition | -| 10 | react-testing-workflows | Vitest, RTL, Playwright, Storybook | -| 11 | react-performance-optimization | Profiling, bundle analysis, Web Vitals | -| 12 | react-accessibility | WCAG 2.1 AA patterns for React | -| 13 | state-management | Zustand, TanStack Query, URL state architecture | -| 14 | form-handling | React Hook Form + Zod: typed forms, wizards | -| 15 | auth-flows | Auth.js, Clerk, Supabase Auth, RBAC | -| 16 | animation-motion | Framer Motion, CSS transitions, reduced-motion a11y | -| 17 | seo-metadata | Next.js Metadata API, JSON-LD, OG images, sitemaps | +| 11 | react-component-development | Component patterns, hooks, composition | +| 12 | react-testing-workflows | Vitest, RTL, Playwright, Storybook | +| 13 | react-performance-optimization | Profiling, bundle analysis, Web Vitals | +| 14 | react-accessibility | WCAG 2.1 AA patterns for React | +| 15 | state-management | Zustand, TanStack Query, URL state architecture | +| 16 | form-handling | React Hook Form + Zod: typed forms, wizards | +| 17 | auth-flows | Auth.js, Clerk, Supabase Auth, RBAC | +| 18 | animation-motion | Framer Motion, CSS transitions, reduced-motion a11y | +| 19 | seo-metadata | Next.js Metadata API, JSON-LD, OG images, sitemaps | + +### Export Skills + +| # | Skill | Purpose | +|---|-------|---------| +| 20 | export-design-system | Export components + tokens as a publishable pnpm workspace | Full catalog: `.claude/skills/README.md` @@ -262,7 +270,7 @@ Details: `.claude/PLUGINS-REFERENCE.md` |----------|----------|-------------| | **Developer onboarding** | `docs/onboarding/README.md` | Start here -- quickstart, architecture, configuration, troubleshooting | | Quickstart guide | `docs/onboarding/quickstart.md` | Clone to running project in 10 minutes | -| Architecture overview | `docs/onboarding/architecture.md` | All 53 agents, 19 skills, 3 pipelines, and how they connect | +| Architecture overview | `docs/onboarding/architecture.md` | All 53 agents, 20 skills, 3 pipelines, and how they connect | | Pipeline configuration | `docs/onboarding/pipeline-configuration.md` | Every setting in pipeline.config.json explained | | Troubleshooting FAQ | `docs/onboarding/troubleshooting.md` | Common issues and solutions | | Project instructions | `CLAUDE.md` | Full project config for Claude Code | @@ -270,7 +278,7 @@ Details: `.claude/PLUGINS-REFERENCE.md` | React standards | `docs/react-development/README.md` | TypeScript, Tailwind, testing conventions | | Canva pipeline guide | `docs/canva-to-react/README.md` | Canva pipeline overview and troubleshooting | | Agent catalog | `.claude/CUSTOM-AGENTS-GUIDE.md` | All 53 agents with use cases | -| Skills catalog | `.claude/skills/README.md` | All 19 skills with triggers | +| Skills catalog | `.claude/skills/README.md` | All 20 skills with triggers | | Plugin reference | `.claude/PLUGINS-REFERENCE.md` | Plugin configuration and commands | | Scripts reference | `scripts/README.md` | All scripts with usage examples | | Templates reference | `templates/README.md` | Starter configs and how to use them | diff --git a/docs/onboarding/README.md b/docs/onboarding/README.md index 7eb40b7..8b688e3 100644 --- a/docs/onboarding/README.md +++ b/docs/onboarding/README.md @@ -11,7 +11,7 @@ This guide will get you productive with the framework quickly, whether you are b | Document | What You Will Learn | |----------|-------------------| | [Quickstart Guide](quickstart.md) | Clone, install, create your first project, and run your first pipeline in under 10 minutes | -| [Architecture Overview](architecture.md) | How the 53 agents, 19 skills, 3 pipelines, and 8 hooks fit together | +| [Architecture Overview](architecture.md) | How the 53 agents, 20 skills, 3 pipelines, and 8 hooks fit together | | [Pipeline Configuration](pipeline-configuration.md) | Every setting in `pipeline.config.json` explained, with examples | | [Troubleshooting FAQ](troubleshooting.md) | Common issues, error messages, and how to resolve them | | [Framework Guides](../guides/README.md) | Deep dives into design tokens, visual QA, caching, hooks, error recovery, agent creation, and framework-specific workflows | @@ -53,7 +53,7 @@ Optional (for specific workflows): - [Main README](../../README.md) -- Project overview - [Contributing Guide](../../CONTRIBUTING.md) -- Branch naming, PR process, commit conventions - [Agent Catalog](../../.claude/CUSTOM-AGENTS-GUIDE.md) -- All 53 agents with use cases -- [Skills Catalog](../../.claude/skills/README.md) -- All 19 skills with triggers +- [Skills Catalog](../../.claude/skills/README.md) -- All 20 skills with triggers - [Plugin Reference](../../.claude/PLUGINS-REFERENCE.md) -- Installed plugins and commands - [Pipeline Config](../../.claude/pipeline.config.json) -- Thresholds and app-type definitions - [React Development Standards](../react-development/README.md) -- TypeScript, Tailwind, testing conventions diff --git a/docs/onboarding/architecture.md b/docs/onboarding/architecture.md index af3677c..8a2f52d 100644 --- a/docs/onboarding/architecture.md +++ b/docs/onboarding/architecture.md @@ -15,7 +15,7 @@ This document explains how Aurelius is structured and how its components work to ┌────────────────────┼─────────────────────┐ │ │ │ ┌───────▼──────┐ ┌────────▼────────┐ ┌────────▼────────┐ - │ 53 Agents │ │ 19 Skills │ │ 4 Plugins │ + │ 53 Agents │ │ 20 Skills │ │ 4 Plugins │ │ (specialized │ │ (workflow │ │ (extensions: │ │ task workers) │ │ automation) │ │ memory, git, │ └───────┬──────┘ └────────┬────────┘ │ superpowers) │ @@ -141,7 +141,7 @@ Agents are specialized Claude Code sub-processes that handle complex, multi-step --- -## Skills (19 Total) +## Skills (20 Total) Skills are automated workflows triggered by slash commands or keyword detection. Unlike agents (which are general-purpose workers), skills encode specific multi-step processes. @@ -159,6 +159,7 @@ Skills are automated workflows triggered by slash commands or keyword detection. | `e2e-test-generator` | Phase 6 | Generates Playwright E2E tests (web app, Chrome extension, PWA) | | `visual-qa-verification` | Phase 5 | Automated pixel-diff using pixelmatch, up to 5 iterations | | `parallel-orchestration` | Phases 4-9 | Concurrent phase execution with dependency graph | +| `export-design-system` | Post-build | Exports components + tokens as a publishable pnpm workspace (`/export-design-system`) | ### React Development Skills diff --git a/docs/onboarding/quickstart.md b/docs/onboarding/quickstart.md index 2784798..7c1a8e1 100644 --- a/docs/onboarding/quickstart.md +++ b/docs/onboarding/quickstart.md @@ -187,7 +187,7 @@ The pipeline auto-detects the framework from `package.json` if `outputTarget` is Aurelius/ ├── .claude/ │ ├── agents/ # 53 specialized agents -│ ├── skills/ # 19 development skills +│ ├── skills/ # 20 development skills │ ├── commands/ # Slash commands (/build-from-figma, /lint, /test) │ ├── hooks/ # Hook scripts (8 automated hooks) │ ├── pipeline.config.json # All pipeline thresholds and behavior diff --git a/docs/react-development/README.md b/docs/react-development/README.md index 2beba64..b60e9e6 100644 --- a/docs/react-development/README.md +++ b/docs/react-development/README.md @@ -175,8 +175,8 @@ project-root/ ├── templates/ # Starter configs (shared, Next.js, Vite, Chrome ext) ├── docs/ # Documentation └── .claude/ # Claude Code configuration - ├── agents/ # 48 custom agents - ├── skills/ # 17 development skills + ├── agents/ # 53 custom agents + ├── skills/ # 20 development skills └── pipeline.config.json ``` @@ -203,7 +203,7 @@ pnpm build - `docs/figma-to-react/README.md` -- Figma-to-React conversion pipeline - `docs/canva-to-react/README.md` -- Canva-to-React conversion pipeline -- `.claude/skills/README.md` -- Skills catalog (19 skills) +- `.claude/skills/README.md` -- Skills catalog (20 skills) - `.claude/CUSTOM-AGENTS-GUIDE.md` -- Agent catalog (53 agents) - `.claude/PLUGINS-REFERENCE.md` -- Plugin reference - `scripts/README.md` -- Scripts reference diff --git a/scripts/__tests__/check-doc-counts.test.js b/scripts/__tests__/check-doc-counts.test.js new file mode 100644 index 0000000..08b6b42 --- /dev/null +++ b/scripts/__tests__/check-doc-counts.test.js @@ -0,0 +1,88 @@ +import { describe, it, expect } from "vitest"; +import { execFileSync } from "child_process"; +import { join, dirname } from "path"; +import { fileURLToPath } from "url"; +import { readdirSync, existsSync, statSync } from "fs"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const SCRIPT = join(__dirname, "..", "check-doc-counts.sh"); +const PROJECT_ROOT = join(__dirname, "..", ".."); + +/** + * Tests for check-doc-counts.sh + * + * The script derives PROJECT_ROOT from its own location and cd's into it, so + * it always runs against the actual repo. Expected counts are recomputed here + * from the filesystem rather than hardcoded, so the test stays correct when + * agents or skills are added or removed. + */ + +function run(args = []) { + try { + const stdout = execFileSync("bash", [SCRIPT, ...args], { + encoding: "utf-8", + timeout: 60000, + cwd: PROJECT_ROOT, + }); + return { stdout, exitCode: 0 }; + } catch (err) { + return { stdout: err.stdout || "", stderr: err.stderr || "", exitCode: err.status }; + } +} + +function countAgents() { + const dir = join(PROJECT_ROOT, ".claude", "agents"); + return readdirSync(dir).filter((f) => f.endsWith(".md") && f.toLowerCase() !== "readme.md") + .length; +} + +function countSkills() { + const dir = join(PROJECT_ROOT, ".claude", "skills"); + return readdirSync(dir).filter((name) => { + const full = join(dir, name); + return statSync(full).isDirectory() && existsSync(join(full, "SKILL.md")); + }).length; +} + +describe("check-doc-counts.sh — help flag", () => { + it("shows usage and exits 0", () => { + const result = run(["--help"]); + expect(result.exitCode).toBe(0); + expect(result.stdout).toContain("Usage:"); + expect(result.stdout).toContain("--json"); + }); +}); + +describe("check-doc-counts.sh — unknown flag", () => { + it("exits 2 on unknown argument", () => { + const result = run(["--bogus"]); + expect(result.exitCode).toBe(2); + }); +}); + +describe("check-doc-counts.sh — human-readable run", () => { + it("prints the header and the on-disk counts", () => { + const result = run([]); + expect(result.stdout).toContain("Documentation Count Check"); + expect(result.stdout).toContain(`${countAgents()} agents, ${countSkills()} skills`); + }); + + it("reports docs in sync (exit 0) — guards against count drift", () => { + const result = run([]); + expect(result.exitCode).toBe(0); + expect(result.stdout).toContain("match the entries on disk"); + }); +}); + +describe("check-doc-counts.sh — JSON output", () => { + it("returns valid JSON reflecting the disk counts", () => { + const result = run(["--json"]); + const parsed = JSON.parse(result.stdout.trim()); + expect(parsed.agents).toBe(countAgents()); + expect(parsed.skills).toBe(countSkills()); + expect(parsed).toHaveProperty("drift"); + expect(Array.isArray(parsed.violations)).toBe(true); + // violations array length is consistent with the drift count + expect(parsed.violations.length).toBe(parsed.drift); + }); +}); diff --git a/scripts/__tests__/verify-test-coverage.test.js b/scripts/__tests__/verify-test-coverage.test.js index 9e3ce56..049ee4b 100644 --- a/scripts/__tests__/verify-test-coverage.test.js +++ b/scripts/__tests__/verify-test-coverage.test.js @@ -3,7 +3,7 @@ import { execFileSync } from "child_process"; import { join, dirname } from "path"; import { fileURLToPath } from "url"; import { tmpdir } from "os"; -import { mkdirSync, writeFileSync, rmSync, existsSync, readdirSync } from "fs"; +import { mkdirSync, writeFileSync, rmSync, existsSync } from "fs"; const __dirname = dirname(fileURLToPath(import.meta.url)); const SCRIPT = join(__dirname, "..", "verify-test-coverage.sh"); diff --git a/scripts/check-doc-counts.sh b/scripts/check-doc-counts.sh new file mode 100644 index 0000000..7245965 --- /dev/null +++ b/scripts/check-doc-counts.sh @@ -0,0 +1,163 @@ +#!/usr/bin/env bash +# check-doc-counts.sh — Flag documentation drift in agent/skill counts. +# +# Counts the real entries on disk: +# agents → *.md files in .claude/agents/ (excluding README) +# skills → subdirectories of .claude/skills/ that contain a SKILL.md +# +# Then scans the live Markdown docs for any "N agents" / "N skills" claim and +# fails if a claim disagrees with the on-disk count. Historical records +# (CHANGELOG.md, docs/plans/) are intentionally excluded — they describe a +# past release and must not be rewritten. +# +# Usage: +# ./scripts/check-doc-counts.sh # human-readable report, exit 1 on drift +# ./scripts/check-doc-counts.sh --json # machine-readable output +# +# Exit codes: 0 = in sync, 1 = drift detected, 2 = usage/IO error. +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/lib/colors.sh" +source "$SCRIPT_DIR/lib/common.sh" + +ROOT="$(common_project_root)" +cd "$ROOT" + +JSON=0 +for arg in "$@"; do + case "$arg" in + --json) JSON=1 ;; + -h|--help) + # Print the leading comment block (skip shebang, stop at first code line). + awk 'NR==1{next} /^#/{sub(/^# ?/,""); print; next} {exit}' "${BASH_SOURCE[0]}" + exit 0 + ;; + *) say_err "Unknown argument: $arg"; exit 2 ;; + esac +done + +# --- Count entries on disk ------------------------------------------------ + +AGENT_DIR=".claude/agents" +SKILL_DIR=".claude/skills" + +agent_count=0 +if [[ -d "$AGENT_DIR" ]]; then + while IFS= read -r f; do + [[ "$(basename "$f")" =~ ^[Rr][Ee][Aa][Dd][Mm][Ee]\.md$ ]] && continue + agent_count=$((agent_count + 1)) + done < <(find "$AGENT_DIR" -maxdepth 1 -type f -name '*.md') +fi + +skill_count=0 +if [[ -d "$SKILL_DIR" ]]; then + while IFS= read -r d; do + [[ -f "$d/SKILL.md" ]] && skill_count=$((skill_count + 1)) + done < <(find "$SKILL_DIR" -mindepth 1 -maxdepth 1 -type d) +fi + +# --- Scan docs for count claims ------------------------------------------- +# +# A "claim" is a number adjacent to the PLURAL word "agents" or "skills". +# Count statements are always plural, so requiring the plural form avoids +# matching incidental phrases like "Phase 1 skill" or "Phase 4 agent". Three +# forms are recognized: +# A: " [adj]{0,3} agents" e.g. "53 custom agents", "20 skills" +# B: "Agents ( Total)" e.g. "Skills (20 Total)" +# C: "Total Agents:** " e.g. "**Total Skills:** 20" +# +# Each match is reduced to (noun, number) and compared against the disk count. + +DRIFT=0 +declare -a DRIFT_LINES=() + +# Count the docs in scope (every *.md except historical records) for the report. +DOC_COUNT=$(find . -type f -name '*.md' \ + -not -path './.git/*' \ + -not -path '*/node_modules/*' \ + -not -path './docs/plans/*' \ + -not -name 'CHANGELOG.md' \ + | wc -l | tr -d ' ') + +# Combined matcher for the three claim forms. Run once recursively (a single +# grep process) for speed — important because this also runs on pre-commit. +COMBINED='[0-9]+( +[a-z][a-z./+-]*){0,3} +(agents|skills)' +COMBINED+='|(agents|skills) *\(?[0-9]+ +total' +COMBINED+='|total +(agents|skills)[^0-9]{0,8}[0-9]+' + +# grep -rIno output is "path:lineno:matched-text". Process each match with +# pure bash (no per-match subprocess): the matched substring contains exactly +# one number in every form, so stripping non-digits yields the claimed count. +while IFS= read -r match; do + [[ -z "$match" ]] && continue + file="${match%%:*}"; rest="${match#*:}" + lineno="${rest%%:*}"; text="${rest#*:}" + lc="${text,,}" + num="${text//[!0-9]/}" + [[ -z "$num" ]] && continue + if [[ "$lc" == *agent* ]]; then + noun="agents"; expected="$agent_count" + elif [[ "$lc" == *skill* ]]; then + noun="skills"; expected="$skill_count" + else + continue + fi + if [[ "$num" != "$expected" ]]; then + squished="${text//$'\t'/ }" + while [[ "$squished" == *" "* ]]; do squished="${squished// / }"; done + DRIFT_LINES+=("${file#./}:${lineno}: claims ${num} ${noun}, expected ${expected} -> \"${squished}\"") + fi +done < <(grep -riInoE "$COMBINED" \ + --include='*.md' \ + --exclude='CHANGELOG.md' \ + --exclude-dir='.git' \ + --exclude-dir='node_modules' \ + --exclude-dir='plans' \ + . 2>/dev/null || true) + +# A single claim can match more than one form; de-duplicate before counting. +if ((${#DRIFT_LINES[@]})); then + mapfile -t DRIFT_LINES < <(printf '%s\n' "${DRIFT_LINES[@]}" | sort -u) +fi +DRIFT=${#DRIFT_LINES[@]} + +# --- Report --------------------------------------------------------------- + +if [[ "$JSON" -eq 1 ]]; then + printf '{\n' + printf ' "agents": %d,\n' "$agent_count" + printf ' "skills": %d,\n' "$skill_count" + printf ' "drift": %d,\n' "$DRIFT" + printf ' "violations": [' + if ((${#DRIFT_LINES[@]})); then + printf '\n' + for i in "${!DRIFT_LINES[@]}"; do + esc="${DRIFT_LINES[$i]//\\/\\\\}"; esc="${esc//\"/\\\"}" + printf ' "%s"' "$esc" + [[ "$i" -lt $((${#DRIFT_LINES[@]} - 1)) ]] && printf ',' + printf '\n' + done + printf ' ' + fi + printf ']\n}\n' +else + say_banner "Documentation Count Check" + echo "" + say_step "On disk: ${agent_count} agents, ${skill_count} skills" + say_step "Scanned ${DOC_COUNT} Markdown files (CHANGELOG.md and docs/plans/ excluded)" + echo "" + if [[ "$DRIFT" -eq 0 ]]; then + say_pass "All agent/skill counts in docs match the entries on disk" + else + say_fail "${DRIFT} documentation count(s) drifted from disk:" + for line in "${DRIFT_LINES[@]}"; do + echo " ${RED}${line}${NC}" + done + echo "" + echo " Fix the counts above, or re-run after adding/removing agents or skills." + echo " (See the \"Keeping counts in sync\" note in CLAUDE.md.)" + fi +fi + +[[ "$DRIFT" -eq 0 ]] || exit 1 diff --git a/scripts/generate-stories.js b/scripts/generate-stories.js index 45c9e97..50b2fbd 100644 --- a/scripts/generate-stories.js +++ b/scripts/generate-stories.js @@ -684,7 +684,6 @@ function main() { for (const filePath of componentFiles) { const relPath = relative(cwd, filePath); - const fileName = basename(filePath); const fileDir = dirname(filePath); const componentBasename = basename(filePath, ".tsx");