@kensaurus/skills 0.0.0-stage → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +53 -0
- package/.claude-plugin/plugin.json +40 -0
- package/.cursor-plugin/plugin.json +38 -0
- package/.mcp.json +28 -0
- package/CHANGELOG.md +1790 -0
- package/LICENSE +21 -0
- package/LICENSE-APACHE +62 -0
- package/NOTICE +13 -0
- package/README.md +821 -2
- package/SECURITY.md +55 -0
- package/agents/code-reviewer.md +60 -0
- package/agents/completion-judge.md +89 -0
- package/agents/db-migrator.md +125 -0
- package/agents/debugger.md +47 -0
- package/agents/deploy-checker.md +100 -0
- package/agents/perf-monitor.md +74 -0
- package/assets/favicon.png +0 -0
- package/assets/logo-light.png +0 -0
- package/assets/logo.png +0 -0
- package/assets/logo.svg +6 -0
- package/assets/og.png +0 -0
- package/bin/install.mjs +1127 -0
- package/bin/kenji.js +2 -0
- package/commands/adr.md +17 -0
- package/commands/aeo-plan.md +18 -0
- package/commands/arch-boundaries.md +17 -0
- package/commands/aso-plan.md +18 -0
- package/commands/auth-flows.md +19 -0
- package/commands/backup-plan.md +17 -0
- package/commands/burndown-full.md +25 -0
- package/commands/capacitor-plan.md +18 -0
- package/commands/codemod-safety.md +22 -0
- package/commands/commit.md +18 -0
- package/commands/complete-everything.md +40 -0
- package/commands/cost-plan.md +19 -0
- package/commands/deadcode-plan.md +26 -0
- package/commands/deadcode.md +32 -0
- package/commands/debug-issue.md +17 -0
- package/commands/deps-plan.md +18 -0
- package/commands/docs-plan.md +17 -0
- package/commands/doctrine.md +19 -0
- package/commands/error-plan.md +19 -0
- package/commands/feedback-to-closure.md +36 -0
- package/commands/fix-issue.md +76 -0
- package/commands/gate-logic.md +26 -0
- package/commands/green-repo.md +36 -0
- package/commands/grill-me.md +19 -0
- package/commands/gtm-plan.md +21 -0
- package/commands/gtm-weekly.md +17 -0
- package/commands/gtm.md +22 -0
- package/commands/handoff.md +15 -0
- package/commands/housekeep-backlog.md +18 -0
- package/commands/housekeep-files.md +22 -0
- package/commands/housekeep-gates.md +18 -0
- package/commands/instant-nav.md +11 -0
- package/commands/integrity-plan.md +19 -0
- package/commands/launch-kit.md +16 -0
- package/commands/mcp-guide.md +40 -0
- package/commands/mobile-plan.md +19 -0
- package/commands/native-rn-monorepo/README.md +78 -0
- package/commands/native-rn-monorepo/android-build.md +26 -0
- package/commands/native-rn-monorepo/android-install.md +32 -0
- package/commands/native-rn-monorepo/android-logcat.md +37 -0
- package/commands/native-rn-monorepo/ios-ci-logs.md +56 -0
- package/commands/native-rn-monorepo/ios-ci-status.md +52 -0
- package/commands/native-rn-monorepo/ios-ci-trigger.md +59 -0
- package/commands/native-rn-monorepo/rn-reset.md +50 -0
- package/commands/native-rn-monorepo/rn-ship-ios.md +67 -0
- package/commands/native-rn-monorepo/rn-verify.md +53 -0
- package/commands/perf-plan.md +18 -0
- package/commands/plan-mode.md +74 -0
- package/commands/pr.md +16 -0
- package/commands/pricing-plan.md +20 -0
- package/commands/privacy-plan.md +18 -0
- package/commands/readability.md +12 -0
- package/commands/readme.md +15 -0
- package/commands/refactor.md +15 -0
- package/commands/release-prep.md +17 -0
- package/commands/research.md +25 -0
- package/commands/responsive-audit.md +21 -0
- package/commands/review-code.md +18 -0
- package/commands/rls-plan.md +18 -0
- package/commands/secrets-plan.md +18 -0
- package/commands/security-plan.md +19 -0
- package/commands/ship-and-observe.md +36 -0
- package/commands/skill-conflicts.md +19 -0
- package/commands/slop-plan.md +18 -0
- package/commands/stub-plan.md +18 -0
- package/commands/test-mutation.md +16 -0
- package/commands/test-plan.md +17 -0
- package/commands/test.md +29 -0
- package/commands/thirdparty-web-interface-guidelines.md +185 -0
- package/commands/uiux-plan.md +18 -0
- package/commands/uiux.md +45 -0
- package/commands/update-deps.md +21 -0
- package/commands/validation-plan.md +19 -0
- package/commands-portable/fix-issue.md +72 -0
- package/commands-portable/plan-mode.md +92 -0
- package/commands-portable/research.md +91 -0
- package/docs/screenshots/README.md +5 -0
- package/docs/screenshots/audit-dark.png +0 -0
- package/docs/screenshots/build-dark.png +0 -0
- package/docs/screenshots/grill-dark.png +0 -0
- package/docs/screenshots/hero-dark.png +0 -0
- package/docs/screenshots/hero-light.png +0 -0
- package/docs/screenshots/ship-dark.png +0 -0
- package/docs/screenshots/src/showcase.html +320 -0
- package/hooks/completion-gate.mjs +258 -0
- package/hooks/cursor-hooks.json +13 -0
- package/hooks/hooks.json +15 -0
- package/install.sh +21 -0
- package/llms.txt +40 -0
- package/mcp/README.md +266 -0
- package/mcp/VERSIONS.md +41 -0
- package/mcp/mcp-full.json.template +124 -0
- package/mcp/mcp.json.template +29 -0
- package/mcp/pinned-versions.json +27 -0
- package/package.json +94 -4
- package/rules/approved-plan-execution.mdc +65 -0
- package/rules/full-stack-ship-discipline.mdc +37 -0
- package/rules/native-rn-monorepo/README.md +63 -0
- package/rules/native-rn-monorepo/_project.mdc +69 -0
- package/rules/native-rn-monorepo/native-android.mdc +72 -0
- package/rules/native-rn-monorepo/native-ios.mdc +61 -0
- package/rules/native-rn-monorepo/react-native-js.mdc +78 -0
- package/rules/native-rn-monorepo/web.mdc +60 -0
- package/rules/project-starter/components.mdc +54 -0
- package/rules/project-starter/data-fetching.mdc +77 -0
- package/rules/project-starter/git.mdc +41 -0
- package/rules/project-starter/supabase.mdc +37 -0
- package/rules/project-starter/tailwind.mdc +48 -0
- package/rules/project-starter/typescript.mdc +36 -0
- package/rules/project-starter/web-performance.mdc +42 -0
- package/rules/senior-engineer.mdc +30 -0
- package/rules/shell-first-search.mdc +19 -0
- package/rules/skill-workflows.mdc +35 -0
- package/rules/verification-before-completion.mdc +57 -0
- package/skills/audit-accessibility/SKILL.md +441 -0
- package/skills/audit-agent-speed/SKILL.md +181 -0
- package/skills/audit-agent-speed/scripts/stop-typecheck.mjs +151 -0
- package/skills/audit-analytics/SKILL.md +138 -0
- package/skills/audit-auth-flows/SKILL.md +267 -0
- package/skills/audit-backend-architecture/SKILL.md +266 -0
- package/skills/audit-backend-architecture/references/patterns.md +386 -0
- package/skills/audit-bundle-size/SKILL.md +295 -0
- package/skills/audit-cicd/SKILL.md +218 -0
- package/skills/audit-code-quality/SKILL.md +314 -0
- package/skills/audit-code-review/SKILL.md +289 -0
- package/skills/audit-codemod-safety/SKILL.md +159 -0
- package/skills/audit-db-schema/SKILL.md +465 -0
- package/skills/audit-db-schema/references/details.md +110 -0
- package/skills/audit-doctrine/SKILL.md +189 -0
- package/skills/audit-env-parity/SKILL.md +133 -0
- package/skills/audit-fe-api/SKILL.md +458 -0
- package/skills/audit-gate-logic/SKILL.md +219 -0
- package/skills/audit-i18n/SKILL.md +339 -0
- package/skills/audit-infra-cost/SKILL.md +142 -0
- package/skills/audit-langfuse-llm/SKILL.md +468 -0
- package/skills/audit-langfuse-llm/references/details.md +226 -0
- package/skills/audit-llm-security/SKILL.md +147 -0
- package/skills/audit-monetization-iap/SKILL.md +137 -0
- package/skills/audit-payment-system/SKILL.md +268 -0
- package/skills/audit-payment-system/references/checklist.md +283 -0
- package/skills/audit-performance/SKILL.md +383 -0
- package/skills/audit-performance/references/loading-priority-2026.md +81 -0
- package/skills/audit-realworld/SKILL.md +287 -0
- package/skills/audit-registry-listing/SKILL.md +122 -0
- package/skills/audit-resilience/SKILL.md +153 -0
- package/skills/audit-responsive/SKILL.md +221 -0
- package/skills/audit-responsive/references/checklist.md +166 -0
- package/skills/audit-security/SKILL.md +289 -0
- package/skills/audit-skill-conflicts/SKILL.md +178 -0
- package/skills/audit-ui-states/SKILL.md +146 -0
- package/skills/audit-uiux-design-system/SKILL.md +475 -0
- package/skills/audit-uiux-design-system/references/details.md +71 -0
- package/skills/audit-ux/SKILL.md +381 -0
- package/skills/audit-ux/references/details.md +245 -0
- package/skills/audit-ux-journeys/SKILL.md +215 -0
- package/skills/audit-ux-journeys/references/checklist.md +179 -0
- package/skills/backend-db-performance/SKILL.md +441 -0
- package/skills/backend-error-handling/SKILL.md +489 -0
- package/skills/backend-error-handling/references/details.md +58 -0
- package/skills/backend-observability/SKILL.md +88 -0
- package/skills/backend-patterns/SKILL.md +499 -0
- package/skills/backend-patterns/references/architecture-patterns.md +298 -0
- package/skills/backend-realtime/SKILL.md +403 -0
- package/skills/backend-realtime/references/patterns.md +74 -0
- package/skills/burndown-full/SKILL.md +174 -0
- package/skills/complete-everything/SKILL.md +295 -0
- package/skills/data-pipeline/SKILL.md +109 -0
- package/skills/data-visualization/SKILL.md +488 -0
- package/skills/debug-error/SKILL.md +322 -0
- package/skills/debug-fe-be-integration/SKILL.md +459 -0
- package/skills/debug-sentry-monitor/SKILL.md +497 -0
- package/skills/debug-sentry-monitor/references/details.md +165 -0
- package/skills/deploy-npm/SKILL.md +394 -0
- package/skills/deploy-npm/references/example-mushi-mushi.md +52 -0
- package/skills/deploy-verify/SKILL.md +489 -0
- package/skills/design-api/SKILL.md +379 -0
- package/skills/design-canvas/SKILL.md +155 -0
- package/skills/design-email/SKILL.md +370 -0
- package/skills/design-frontend/SKILL.md +143 -0
- package/skills/design-generative-art/SKILL.md +474 -0
- package/skills/design-mobile-first/SKILL.md +506 -0
- package/skills/design-motion/SKILL.md +333 -0
- package/skills/design-motion/references/delight-interactions.md +191 -0
- package/skills/design-prd/SKILL.md +443 -0
- package/skills/design-system/SKILL.md +457 -0
- package/skills/design-theme/SKILL.md +226 -0
- package/skills/design-theme/themes/tsumagoi-ranch.md +150 -0
- package/skills/docs-adr/SKILL.md +168 -0
- package/skills/docs-coauthor/SKILL.md +368 -0
- package/skills/docs-comparison-pages/SKILL.md +117 -0
- package/skills/docs-domain-modeling/SKILL.md +97 -0
- package/skills/docs-launch-kit/SKILL.md +139 -0
- package/skills/docs-writer/SKILL.md +469 -0
- package/skills/enhance-agent-guardrails/SKILL.md +164 -0
- package/skills/enhance-arch-boundaries/SKILL.md +154 -0
- package/skills/enhance-capacitor-ui/SKILL.md +463 -0
- package/skills/enhance-capacitor-ui/references/details.md +750 -0
- package/skills/enhance-email-deliverability/SKILL.md +143 -0
- package/skills/enhance-growth-loops/SKILL.md +122 -0
- package/skills/enhance-lifecycle-email/SKILL.md +130 -0
- package/skills/enhance-motion/SKILL.md +193 -0
- package/skills/enhance-onboarding/SKILL.md +148 -0
- package/skills/enhance-pwa/SKILL.md +303 -0
- package/skills/enhance-readability/SKILL.md +146 -0
- package/skills/enhance-readme/SKILL.md +496 -0
- package/skills/enhance-readme/package-lock.json +187 -0
- package/skills/enhance-readme/package.json +17 -0
- package/skills/enhance-readme/scripts/generate-readme-blocks.mjs +199 -0
- package/skills/enhance-readme/scripts/record-readme-tour.mjs +442 -0
- package/skills/enhance-skill-prompts/SKILL.md +167 -0
- package/skills/enhance-skill-prompts/references/exemplar-audit-auth-flows.md +311 -0
- package/skills/enhance-ux-laws/SKILL.md +409 -0
- package/skills/enhance-web-conversion/SKILL.md +155 -0
- package/skills/enhance-web-forms/SKILL.md +154 -0
- package/skills/enhance-web-instant-nav/SKILL.md +138 -0
- package/skills/enhance-web-instant-nav/references/bfcache-blockers.md +23 -0
- package/skills/enhance-web-instant-nav/references/early-hints.md +33 -0
- package/skills/enhance-web-instant-nav/references/speculation-rules.md +44 -0
- package/skills/enhance-web-landing/SKILL.md +459 -0
- package/skills/enhance-web-landing/references/details.md +773 -0
- package/skills/enhance-web-redesign/SKILL.md +228 -0
- package/skills/enhance-web-seo/SKILL.md +276 -0
- package/skills/enhance-web-ui/SKILL.md +473 -0
- package/skills/enhance-web-ui/references/details.md +674 -0
- package/skills/enhance-web-ux/HEURISTICS.md +248 -0
- package/skills/enhance-web-ux/PATTERNS.md +375 -0
- package/skills/enhance-web-ux/SKILL.md +464 -0
- package/skills/enhance-web-ux/examples.md +222 -0
- package/skills/enhance-web-ux/references/details.md +406 -0
- package/skills/enhance-web-web3d/SKILL.md +397 -0
- package/skills/enhance-web-web3d/references/css-canvas-effects.md +180 -0
- package/skills/handoff/SKILL.md +66 -0
- package/skills/housekeep-backlog/SKILL.md +149 -0
- package/skills/housekeep-dead-code/SKILL.md +387 -0
- package/skills/housekeep-dead-code/references/ratchet-ci.md +205 -0
- package/skills/housekeep-dead-code/references/supabase-hygiene.md +152 -0
- package/skills/housekeep-design/SKILL.md +207 -0
- package/skills/housekeep-files/SKILL.md +220 -0
- package/skills/housekeep-files/references/naming-and-catalog.md +86 -0
- package/skills/housekeep-files/scripts/housekeep-files.ps1 +360 -0
- package/skills/housekeep-files/scripts/housekeep-files.sh +238 -0
- package/skills/housekeep-gates/SKILL.md +174 -0
- package/skills/iterate-agent-harness/SKILL.md +137 -0
- package/skills/iterate-gtm-weekly/SKILL.md +103 -0
- package/skills/iterate-post-launch/SKILL.md +292 -0
- package/skills/meta-mcp-builder/SKILL.md +313 -0
- package/skills/meta-skill-creator/SKILL.md +304 -0
- package/skills/mobile-capacitor-platform/SKILL.md +103 -0
- package/skills/mobile-emulator-start/SKILL.md +296 -0
- package/skills/mobile-emulator-test/SKILL.md +491 -0
- package/skills/mobile-emulator-test/references/details.md +478 -0
- package/skills/mobile-rn-performance/SKILL.md +107 -0
- package/skills/mobile-rn-screen/SKILL.md +476 -0
- package/skills/mobile-rn-screen/references/details.md +785 -0
- package/skills/mushi-health/SKILL.md +206 -0
- package/skills/mushi-integration/SKILL.md +257 -0
- package/skills/plan-aeo-readiness/SKILL.md +166 -0
- package/skills/plan-antislop/SKILL.md +281 -0
- package/skills/plan-aso/SKILL.md +149 -0
- package/skills/plan-backup-dr/SKILL.md +131 -0
- package/skills/plan-capacitor-hardening/SKILL.md +217 -0
- package/skills/plan-data-integrity/SKILL.md +187 -0
- package/skills/plan-dead-code/SKILL.md +386 -0
- package/skills/plan-dead-code/references/knip-config.md +214 -0
- package/skills/plan-dead-code/references/output-templates.md +133 -0
- package/skills/plan-dead-code/references/preservation-contract.md +50 -0
- package/skills/plan-dead-code/references/residue-greps.md +84 -0
- package/skills/plan-dependency-provenance/SKILL.md +200 -0
- package/skills/plan-docs-sync/SKILL.md +143 -0
- package/skills/plan-docs-sync/references/drift-taxonomy.md +43 -0
- package/skills/plan-docs-sync/references/output-templates.md +33 -0
- package/skills/plan-docs-sync/references/preservation-contract.md +17 -0
- package/skills/plan-error-handling/SKILL.md +205 -0
- package/skills/plan-gtm/SKILL.md +276 -0
- package/skills/plan-gtm/references/benchmarks-2026.md +183 -0
- package/skills/plan-input-validation/SKILL.md +179 -0
- package/skills/plan-llm-cost-guardrails/SKILL.md +176 -0
- package/skills/plan-mobile-readiness/SKILL.md +171 -0
- package/skills/plan-perf-audit/SKILL.md +145 -0
- package/skills/plan-perf-audit/references/audit-scope.md +51 -0
- package/skills/plan-perf-audit/references/output-templates.md +33 -0
- package/skills/plan-perf-audit/references/preservation-contract.md +13 -0
- package/skills/plan-pricing/SKILL.md +173 -0
- package/skills/plan-privacy-compliance/SKILL.md +148 -0
- package/skills/plan-rls-audit/SKILL.md +231 -0
- package/skills/plan-secrets-audit/SKILL.md +181 -0
- package/skills/plan-security-audit/SKILL.md +168 -0
- package/skills/plan-security-audit/references/output-templates.md +36 -0
- package/skills/plan-security-audit/references/owasp-supabase-scope.md +55 -0
- package/skills/plan-security-audit/references/preservation-contract.md +18 -0
- package/skills/plan-stub-checker/SKILL.md +216 -0
- package/skills/plan-stub-checker/references/detection-methodology.md +75 -0
- package/skills/plan-stub-checker/references/detection-taxonomy.md +34 -0
- package/skills/plan-stub-checker/references/output-templates.md +63 -0
- package/skills/plan-stub-checker/references/preservation-contract.md +24 -0
- package/skills/plan-test-coverage/SKILL.md +170 -0
- package/skills/plan-test-coverage/references/methodology.md +54 -0
- package/skills/plan-test-coverage/references/output-templates.md +34 -0
- package/skills/plan-test-coverage/references/preservation-contract.md +15 -0
- package/skills/plan-uiux-unification/SKILL.md +230 -0
- package/skills/plan-uiux-unification/references/output-templates.md +67 -0
- package/skills/plan-uiux-unification/references/phase-workbook.md +85 -0
- package/skills/plan-uiux-unification/references/preservation-contract.md +24 -0
- package/skills/protocol-browser-anti-stall/SKILL.md +211 -0
- package/skills/protocol-browser-anti-stall/references/mcp-to-cli-map.md +113 -0
- package/skills/protocol-browser-anti-stall/references/playwright-session-coordination.md +170 -0
- package/skills/research/SKILL.md +422 -0
- package/skills/test-exploratory/SKILL.md +165 -0
- package/skills/test-exploratory/references/charter-template.md +29 -0
- package/skills/test-load/SKILL.md +126 -0
- package/skills/test-mutation/SKILL.md +160 -0
- package/skills/test-playwright/SKILL.md +354 -0
- package/skills/test-qa/SKILL.md +364 -0
- package/skills/test-qa/references/details.md +268 -0
- package/skills/test-red-team/SKILL.md +386 -0
- package/skills/test-red-team/references/owasp-attack-checklist.md +193 -0
- package/skills/test-unit/SKILL.md +259 -0
- package/skills/test-unit/references/details.md +267 -0
- package/skills/test-visual-regression/SKILL.md +132 -0
- package/skills/thirdparty-emil-design-eng/ATTRIBUTION.md +20 -0
- package/skills/thirdparty-emil-design-eng/SKILL.md +21 -0
- package/skills/thirdparty-emil-design-eng/references/emil-design-eng.md +676 -0
- package/skills/thirdparty-ui-ux-pro-max/ATTRIBUTION.md +22 -0
- package/skills/thirdparty-ui-ux-pro-max/SKILL.md +304 -0
- package/skills/thirdparty-ui-ux-pro-max/data/charts.csv +26 -0
- package/skills/thirdparty-ui-ux-pro-max/data/colors.csv +97 -0
- package/skills/thirdparty-ui-ux-pro-max/data/icons.csv +101 -0
- package/skills/thirdparty-ui-ux-pro-max/data/landing.csv +31 -0
- package/skills/thirdparty-ui-ux-pro-max/data/products.csv +97 -0
- package/skills/thirdparty-ui-ux-pro-max/data/react-performance.csv +45 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/astro.csv +54 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/skills/thirdparty-ui-ux-pro-max/data/styles.csv +68 -0
- package/skills/thirdparty-ui-ux-pro-max/data/typography.csv +58 -0
- package/skills/thirdparty-ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/skills/thirdparty-ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/skills/thirdparty-ui-ux-pro-max/data/web-interface.csv +31 -0
- package/skills/thirdparty-ui-ux-pro-max/scripts/core.py +253 -0
- package/skills/thirdparty-ui-ux-pro-max/scripts/design_system.py +1067 -0
- package/skills/thirdparty-ui-ux-pro-max/scripts/search.py +114 -0
- package/skills/thirdparty-web-interface-guidelines/ATTRIBUTION.md +23 -0
- package/skills/thirdparty-web-interface-guidelines/SKILL.md +190 -0
- package/skills/workflow-build-feature/SKILL.md +118 -0
- package/skills/workflow-coding-discipline/SKILL.md +140 -0
- package/skills/workflow-environment-ready/SKILL.md +128 -0
- package/skills/workflow-feature-flag/SKILL.md +262 -0
- package/skills/workflow-feedback-to-closure/SKILL.md +165 -0
- package/skills/workflow-fix-and-ship/SKILL.md +136 -0
- package/skills/workflow-git-commit/SKILL.md +200 -0
- package/skills/workflow-green-repo/SKILL.md +166 -0
- package/skills/workflow-grilling/SKILL.md +73 -0
- package/skills/workflow-gtm/SKILL.md +153 -0
- package/skills/workflow-housekeep/SKILL.md +453 -0
- package/skills/workflow-housekeep/references/templates.md +109 -0
- package/skills/workflow-launch-ready/SKILL.md +145 -0
- package/skills/workflow-merge-conflicts/SKILL.md +62 -0
- package/skills/workflow-onboard/SKILL.md +99 -0
- package/skills/workflow-parallel-agents/SKILL.md +164 -0
- package/skills/workflow-pr/SKILL.md +197 -0
- package/skills/workflow-quality-gate/SKILL.md +147 -0
- package/skills/workflow-refactor/SKILL.md +274 -0
- package/skills/workflow-release-prep/SKILL.md +207 -0
- package/skills/workflow-ship-and-observe/SKILL.md +164 -0
- package/skills/workflow-spec-tdd/SKILL.md +141 -0
- package/skills/workflow-spec-tdd/references/spec-template.md +126 -0
- package/skills/workflow-spec-tdd/references/tdd-patterns.md +167 -0
- package/skills-cursor/babysit/SKILL.md +17 -0
- package/skills-cursor/canvas/SKILL.md +142 -0
- package/skills-cursor/canvas/sdk/canvas-tokens.d.ts +235 -0
- package/skills-cursor/canvas/sdk/chart-primitives.d.ts +200 -0
- package/skills-cursor/canvas/sdk/dag-layout.d.ts +102 -0
- package/skills-cursor/canvas/sdk/diff-view.d.ts +130 -0
- package/skills-cursor/canvas/sdk/form-primitives.d.ts +194 -0
- package/skills-cursor/canvas/sdk/hooks.d.ts +117 -0
- package/skills-cursor/canvas/sdk/index.d.ts +47 -0
- package/skills-cursor/canvas/sdk/theme.d.ts +61 -0
- package/skills-cursor/canvas/sdk/todo-list.d.ts +49 -0
- package/skills-cursor/canvas/sdk/ui-primitives.d.ts +549 -0
- package/skills-cursor/canvas/sdk/ui-primitives.test.d.ts +2 -0
- package/skills-cursor/create-hook/SKILL.md +238 -0
- package/skills-cursor/create-rule/SKILL.md +185 -0
- package/skills-cursor/create-skill/SKILL.md +269 -0
- package/skills-cursor/create-skill/references/authoring-guide.md +182 -0
- package/skills-cursor/create-subagent/SKILL.md +228 -0
- package/skills-cursor/migrate-to-skills/SKILL.md +121 -0
- package/skills-cursor/shell/SKILL.md +22 -0
- package/skills-cursor/split-to-prs/SKILL.md +47 -0
- package/skills-cursor/statusline/SKILL.md +193 -0
- package/skills-cursor/update-cli-config/SKILL.md +85 -0
- package/skills-cursor/update-cursor-settings/SKILL.md +137 -0
- package/skills.sh.json +297 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: test-unit
|
|
3
|
+
description: >
|
|
4
|
+
Write unit and integration tests for a named module or change. Use when
|
|
5
|
+
"write unit tests" or "add tests for this function". Coverage plan →
|
|
6
|
+
plan-test-coverage. Mutation score → test-mutation. Browser check →
|
|
7
|
+
test-playwright.
|
|
8
|
+
license: MIT
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# test-unit — Write tests that would notice a break
|
|
12
|
+
|
|
13
|
+
**Degree of freedom: MIXED** — which cases to write `[HIGH freedom]`;
|
|
14
|
+
detect-then-match existing harness `[LOW freedom — run exactly]`. This skill
|
|
15
|
+
**writes tests**. Coverage theater / mutation score → `test-mutation`.
|
|
16
|
+
|
|
17
|
+
Write effective, maintainable unit tests from the project's actual
|
|
18
|
+
framework, production error data, and current best practices.
|
|
19
|
+
|
|
20
|
+
## This skill vs neighbors
|
|
21
|
+
|
|
22
|
+
| Skill | Owns |
|
|
23
|
+
|:------|:-----|
|
|
24
|
+
| **test-unit** (this) | **Write** the tests |
|
|
25
|
+
| `test-mutation` | Survivors / assertion theater — hand off the score |
|
|
26
|
+
| `plan-test-coverage` | What *should* be tested — plan only, no harness |
|
|
27
|
+
| `test-playwright` | Live this-diff PDCA, not unit files |
|
|
28
|
+
| `test-qa` | Story/CRUD QA in a headed browser |
|
|
29
|
+
|
|
30
|
+
## How to reason (each test you add)
|
|
31
|
+
|
|
32
|
+
1. **Observe** — target function, existing pattern, Sentry gap if any
|
|
33
|
+
2. **Interpret** — behavior under test vs implementation detail
|
|
34
|
+
3. **Classify** — write (public/edge/error) / skip (trivial/third-party/markup)
|
|
35
|
+
4. **Severity** — prod-error gap and money/auth paths first
|
|
36
|
+
|
|
37
|
+
## Worked example
|
|
38
|
+
|
|
39
|
+
> **Observe:** Sentry `TypeError` in `parsePrice`; `parsePrice.test.ts` only
|
|
40
|
+
> asserts the happy path; coverage 91%.
|
|
41
|
+
> **Interpret:** suite executes the file but never the empty/malformed branch.
|
|
42
|
+
> **Classify:** write the missing edge cases here — do not declare coverage done.
|
|
43
|
+
> **Handoff:** if the new tests still wouldn't catch a `>`/`>=` flip → `test-mutation`.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Step 0: Auto-Detect Test Environment [LOW freedom — match the harness]
|
|
48
|
+
|
|
49
|
+
### 0a. Detect Test Framework
|
|
50
|
+
|
|
51
|
+
Read the dependency manifest (`package.json`, `requirements.txt`,
|
|
52
|
+
`pyproject.toml`, `go.mod`, `Cargo.toml`, `build.gradle`, `Gemfile`):
|
|
53
|
+
|
|
54
|
+
| Framework | Detection Signal |
|
|
55
|
+
|-----------|-----------------|
|
|
56
|
+
| **Vitest** | `vitest` in devDependencies, `vitest.config.ts` |
|
|
57
|
+
| **Jest** | `jest` in devDependencies, `jest.config.*`, `"jest"` key |
|
|
58
|
+
| **Testing Library** | `@testing-library/react`, `@testing-library/vue`, etc. |
|
|
59
|
+
| **Playwright** | `@playwright/test`, `playwright.config.ts` |
|
|
60
|
+
| **Cypress** | `cypress`, `cypress.config.*` |
|
|
61
|
+
| **pytest** | `pytest` in requirements, `conftest.py` |
|
|
62
|
+
| **Go test** | `_test.go`, `go test` in Makefile |
|
|
63
|
+
| **RSpec** | `rspec` in Gemfile, `spec/` |
|
|
64
|
+
| **JUnit** | `junit` in build.gradle, `src/test/` |
|
|
65
|
+
|
|
66
|
+
### 0b. Discover Existing Test Patterns
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
Glob: **/*.test.{ts,tsx,js,jsx} → JS/TS test files
|
|
70
|
+
Glob: **/*.spec.{ts,tsx,js,jsx} → JS/TS spec files
|
|
71
|
+
Glob: **/test_*.py → Python
|
|
72
|
+
Glob: **/*_test.go → Go
|
|
73
|
+
Glob: **/spec/**/*_spec.rb → Ruby
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Read 2–3 existing tests: imports/utilities, `describe`/`it` vs `test`,
|
|
77
|
+
mock style (`vi.mock`, `jest.mock`, `unittest.mock`), setup/teardown,
|
|
78
|
+
assertion library (`expect`, `assert`, `chai`).
|
|
79
|
+
|
|
80
|
+
### 0c. Detect Test Configuration
|
|
81
|
+
|
|
82
|
+
Glob `vitest.config.*`, `jest.config.*`, `pytest.ini`, `conftest.py`,
|
|
83
|
+
`setup.cfg`, `.nycrc*`, `c8.config.*`. Extract coverage thresholds, test
|
|
84
|
+
dirs, global setup, module aliases.
|
|
85
|
+
|
|
86
|
+
### 0d. Check Coverage Status
|
|
87
|
+
|
|
88
|
+
If c8 / istanbul/nyc / coverage.py is configured, grep `package.json`
|
|
89
|
+
scripts for `coverage` / `c8` / `nyc` / `istanbul`.
|
|
90
|
+
|
|
91
|
+
### 0e. Record Discovery
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
TEST ENVIRONMENT:
|
|
95
|
+
- Framework: [Vitest/Jest/pytest/etc. + version]
|
|
96
|
+
- Assertion style: [expect/assert/chai]
|
|
97
|
+
- Component testing: [Testing Library/Enzyme/none]
|
|
98
|
+
- Mock pattern: [vi.mock/jest.mock/unittest.mock]
|
|
99
|
+
- Coverage tool: [c8/nyc/coverage.py/none]
|
|
100
|
+
- Coverage threshold: [X% or not configured]
|
|
101
|
+
- Test directory: [__tests__/tests/spec/co-located]
|
|
102
|
+
- Existing tests: [count]
|
|
103
|
+
- Config file: [path]
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Step 1: Research Testing Best Practices [HIGH freedom]
|
|
109
|
+
|
|
110
|
+
Context7 for the detected framework + each major testing dep (`vitest`,
|
|
111
|
+
`@testing-library/react`, `msw`):
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
context7:resolve-library-id
|
|
115
|
+
{ "libraryName": "<DETECTED_FRAMEWORK>", "query": "unit testing best practices" }
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Then `context7:query-docs` for mocking, setup, teardown.
|
|
119
|
+
|
|
120
|
+
Firecrawl — one current-year search, scrape the most authoritative result:
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
firecrawl:firecrawl_search
|
|
124
|
+
{
|
|
125
|
+
"query": "<FRAMEWORK> unit testing best practices [current year]",
|
|
126
|
+
"limit": 5, "sources": [{ "type": "web" }]
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Optional second query: `<framework> mocking API calls` or `React Testing
|
|
131
|
+
Library component testing patterns [current year]`.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Step 2: Analyze Coverage Gaps (Sentry Integration) [HIGH freedom]
|
|
136
|
+
|
|
137
|
+
```json
|
|
138
|
+
sentry:search_issues
|
|
139
|
+
{
|
|
140
|
+
"organizationSlug": "<ORG_SLUG>",
|
|
141
|
+
"query": "unresolved errors from the last 30 days",
|
|
142
|
+
"projectSlugOrId": "<PROJECT_SLUG>",
|
|
143
|
+
"regionUrl": "<REGION_URL>",
|
|
144
|
+
"limit": 25
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
For each issue: stack-trace file → `Glob: **/<filename>.test.*` → does a
|
|
149
|
+
test cover the failing path? No file, or happy-path-only → prioritize it.
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
COVERAGE GAP ANALYSIS:
|
|
153
|
+
- Production errors without tests: [count]
|
|
154
|
+
1. [file] — [error type] — [frequency] — NO TEST FILE
|
|
155
|
+
2. [file] — [error type] — [frequency] — test exists but missing edge case
|
|
156
|
+
- Highest-impact files to test: [ordered list]
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Step 3: Write Tests [HIGH freedom]
|
|
162
|
+
|
|
163
|
+
### Test Structure (AAA Pattern)
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
describe('ComponentOrModule', () => {
|
|
167
|
+
describe('methodOrBehavior', () => {
|
|
168
|
+
it('should [expected behavior] when [condition]', () => {
|
|
169
|
+
// Arrange
|
|
170
|
+
const input = createTestData();
|
|
171
|
+
// Act
|
|
172
|
+
const result = functionUnderTest(input);
|
|
173
|
+
// Assert
|
|
174
|
+
expect(result).toEqual(expectedOutput);
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Naming Conventions
|
|
181
|
+
|
|
182
|
+
Co-locate or mirror the source tree:
|
|
183
|
+
|
|
184
|
+
| Source File | Test File |
|
|
185
|
+
|-------------|-----------|
|
|
186
|
+
| `src/utils/formatDate.ts` | `src/utils/formatDate.test.ts` |
|
|
187
|
+
| `src/components/Button.tsx` | `src/components/Button.test.tsx` |
|
|
188
|
+
| `app/services/user.py` | `tests/services/test_user.py` |
|
|
189
|
+
|
|
190
|
+
Descriptions: `should [behavior] when [condition]`.
|
|
191
|
+
|
|
192
|
+
### What to Test
|
|
193
|
+
|
|
194
|
+
**DO test:** public API / exported functions; business/domain rules; edge
|
|
195
|
+
and boundary values; error/failure modes; user interactions; state
|
|
196
|
+
transitions; data transformations.
|
|
197
|
+
|
|
198
|
+
**DON'T test:** private methods / internal state; third-party internals;
|
|
199
|
+
trivial getters/setters; framework behavior; CSS classes or DOM structure
|
|
200
|
+
(behavior, not markup).
|
|
201
|
+
|
|
202
|
+
### Edge Cases to Cover
|
|
203
|
+
|
|
204
|
+
| Category | Test Values |
|
|
205
|
+
|----------|------------|
|
|
206
|
+
| Empty | `null`, `undefined`, `""`, `[]`, `{}` |
|
|
207
|
+
| Boundary | `0`, `-1`, `Number.MAX_SAFE_INTEGER`, `Number.MIN_SAFE_INTEGER` |
|
|
208
|
+
| Type confusion | String where number expected, array where object expected |
|
|
209
|
+
| Unicode | Emoji, CJK, RTL, zero-width spaces |
|
|
210
|
+
| Concurrency | Rapid successive calls, races |
|
|
211
|
+
| Network | Timeout, 404, 500, empty body, malformed JSON |
|
|
212
|
+
| Dates | Midnight, DST, leap years, timezone boundaries |
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Step 4: Match the repo's patterns [HIGH freedom]
|
|
217
|
+
|
|
218
|
+
Write mocks, component, hook, and route-handler tests in the shape the existing suite uses (Step 0b) and the framework docs describe (Step 1). Generic templates per category live in [references/details.md](references/details.md) for repos with no precedent.
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Step 5: Test Data Management [HIGH freedom]
|
|
223
|
+
|
|
224
|
+
### Use Factories
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
const createUser = (overrides: Partial<User> = {}): User => ({
|
|
228
|
+
id: crypto.randomUUID(),
|
|
229
|
+
name: 'Test User',
|
|
230
|
+
email: 'test@example.com',
|
|
231
|
+
role: 'user',
|
|
232
|
+
createdAt: new Date('2024-01-01'),
|
|
233
|
+
...overrides,
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
const admin = createUser({ role: 'admin' });
|
|
237
|
+
const inactive = createUser({ status: 'inactive', name: 'Inactive User' });
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Use Meaningful Data
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
// Bad — meaningless
|
|
244
|
+
const data = { a: 'b', c: 'd' };
|
|
245
|
+
// Good — realistic and descriptive
|
|
246
|
+
const user = { name: 'Jane Doe', email: 'jane@example.com', role: 'admin' };
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## Self-critique before reporting [LOW freedom — do not skip]
|
|
250
|
+
|
|
251
|
+
1. **Wrote tests** — this skill does not stop at a plan
|
|
252
|
+
2. **Behavior not markup** — no className / private internals
|
|
253
|
+
3. **Matched harness** — same runner, naming, mock style as existing files
|
|
254
|
+
4. **Isolated + deterministic** — factories, no shared mutable
|
|
255
|
+
5. **Mutation theater not claimed** — score → `test-mutation`
|
|
256
|
+
|
|
257
|
+
## Further reading
|
|
258
|
+
|
|
259
|
+
- [Avoid Shared Mutable State and more](references/details.md)
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
### Avoid Shared Mutable State
|
|
2
|
+
|
|
3
|
+
```typescript
|
|
4
|
+
// Bad — tests can interfere with each other
|
|
5
|
+
const users = [createUser()];
|
|
6
|
+
|
|
7
|
+
// Good — fresh data per test
|
|
8
|
+
let users: User[];
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
users = [createUser()];
|
|
11
|
+
});
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Step 6: Database-Aware Tests (Supabase Integration)
|
|
17
|
+
|
|
18
|
+
If the project uses Supabase, verify test data matches the actual schema:
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
supabase:execute_sql
|
|
22
|
+
{
|
|
23
|
+
"query": "SELECT column_name, data_type, is_nullable FROM information_schema.columns WHERE table_name = '<TABLE_BEING_TESTED>' ORDER BY ordinal_position"
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Use this to ensure:
|
|
28
|
+
- Test factories produce data matching actual column types
|
|
29
|
+
- Nullable fields are tested with both values and null
|
|
30
|
+
- Enum values in tests match actual database enums
|
|
31
|
+
- Foreign key relationships are correctly represented
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Output: Test Plan Report
|
|
36
|
+
|
|
37
|
+
After analyzing the codebase and production errors, produce:
|
|
38
|
+
|
|
39
|
+
```markdown
|
|
40
|
+
## Test Plan — [Project Name]
|
|
41
|
+
|
|
42
|
+
### Environment
|
|
43
|
+
- Framework: [detected]
|
|
44
|
+
- Coverage tool: [detected]
|
|
45
|
+
- Current coverage: [if available]
|
|
46
|
+
|
|
47
|
+
### Production Error Coverage Gaps
|
|
48
|
+
| Error | Source File | Test Exists | Priority |
|
|
49
|
+
|-------|-----------|-------------|----------|
|
|
50
|
+
| [TypeError: Cannot read...] | [src/utils/parse.ts] | No | HIGH |
|
|
51
|
+
| [NetworkError: timeout] | [src/api/client.ts] | Yes (missing edge case) | MEDIUM |
|
|
52
|
+
|
|
53
|
+
### Recommended Tests (Priority Order)
|
|
54
|
+
|
|
55
|
+
#### 1. [file path] — [why this file needs tests]
|
|
56
|
+
- Test: [description of test case]
|
|
57
|
+
- Test: [description of test case]
|
|
58
|
+
|
|
59
|
+
#### 2. [file path] — [why]
|
|
60
|
+
- Test: [description]
|
|
61
|
+
|
|
62
|
+
### Research Findings Applied
|
|
63
|
+
- [Pattern from research]: applied to [which tests]
|
|
64
|
+
- [Best practice]: [how it informed the test strategy]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Quick Reference
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Run all tests
|
|
73
|
+
npm test # or: pnpm test, yarn test
|
|
74
|
+
python -m pytest # Python
|
|
75
|
+
go test ./... # Go
|
|
76
|
+
|
|
77
|
+
# Run specific file
|
|
78
|
+
npx vitest src/utils/formatDate.test.ts
|
|
79
|
+
npx jest --testPathPattern formatDate
|
|
80
|
+
python -m pytest tests/test_format.py
|
|
81
|
+
|
|
82
|
+
# Run with coverage
|
|
83
|
+
npx vitest --coverage
|
|
84
|
+
npx jest --coverage
|
|
85
|
+
python -m pytest --cov=src
|
|
86
|
+
|
|
87
|
+
# Watch mode
|
|
88
|
+
npx vitest --watch
|
|
89
|
+
npx jest --watch
|
|
90
|
+
|
|
91
|
+
# Run matching pattern
|
|
92
|
+
npx vitest -t "should format"
|
|
93
|
+
npx jest -t "should format"
|
|
94
|
+
python -m pytest -k "test_format"
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Checklist
|
|
100
|
+
|
|
101
|
+
- [ ] Test environment auto-detected (framework, config, patterns)
|
|
102
|
+
- [ ] Research completed (Context7 docs, Firecrawl best practices)
|
|
103
|
+
- [ ] Production errors checked (Sentry coverage gaps identified)
|
|
104
|
+
- [ ] Tests follow AAA pattern (Arrange, Act, Assert)
|
|
105
|
+
- [ ] Descriptive test names (`should [behavior] when [condition]`)
|
|
106
|
+
- [ ] Edge cases covered (null, empty, boundary, error)
|
|
107
|
+
- [ ] Mocks reset between tests (`beforeEach` cleanup)
|
|
108
|
+
- [ ] No test interdependency (each test runs in isolation)
|
|
109
|
+
- [ ] Tests are fast (mock external dependencies)
|
|
110
|
+
- [ ] Tests are deterministic (no random, no time-dependent without fakes)
|
|
111
|
+
- [ ] Test data uses factories (no hardcoded shared state)
|
|
112
|
+
- [ ] Coverage gaps from Sentry addressed
|
|
113
|
+
|
|
114
|
+
## Testing patterns by category
|
|
115
|
+
|
|
116
|
+
Generic templates for repos with no precedent. Prefer the shape the existing suite already uses.
|
|
117
|
+
|
|
118
|
+
### Pure Functions
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
describe('formatCurrency', () => {
|
|
122
|
+
it('should format positive amounts', () => {
|
|
123
|
+
expect(formatCurrency(1234.5)).toBe('$1,234.50');
|
|
124
|
+
});
|
|
125
|
+
it('should handle zero', () => {
|
|
126
|
+
expect(formatCurrency(0)).toBe('$0.00');
|
|
127
|
+
});
|
|
128
|
+
it('should handle negative amounts', () => {
|
|
129
|
+
expect(formatCurrency(-100)).toBe('-$100.00');
|
|
130
|
+
});
|
|
131
|
+
it('should handle very large numbers', () => {
|
|
132
|
+
expect(formatCurrency(999999999.99)).toBe('$999,999,999.99');
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Async Functions
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
describe('fetchUser', () => {
|
|
141
|
+
it('should return user data for valid id', async () => {
|
|
142
|
+
const user = await fetchUser('123');
|
|
143
|
+
expect(user).toEqual({ id: '123', name: 'John Doe' });
|
|
144
|
+
});
|
|
145
|
+
it('should throw for non-existent user', async () => {
|
|
146
|
+
await expect(fetchUser('invalid')).rejects.toThrow('User not found');
|
|
147
|
+
});
|
|
148
|
+
it('should handle network timeout', async () => {
|
|
149
|
+
vi.useFakeTimers();
|
|
150
|
+
const promise = fetchUser('123');
|
|
151
|
+
vi.advanceTimersByTime(30000);
|
|
152
|
+
await expect(promise).rejects.toThrow('timeout');
|
|
153
|
+
vi.useRealTimers();
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Mocking
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
// Vitest
|
|
162
|
+
import { vi } from 'vitest';
|
|
163
|
+
vi.mock('./emailService', () => ({
|
|
164
|
+
sendEmail: vi.fn().mockResolvedValue({ success: true }),
|
|
165
|
+
}));
|
|
166
|
+
|
|
167
|
+
// Jest
|
|
168
|
+
jest.mock('./emailService');
|
|
169
|
+
|
|
170
|
+
// MSW (API mocking — preferred for HTTP)
|
|
171
|
+
import { http, HttpResponse } from 'msw';
|
|
172
|
+
import { setupServer } from 'msw/node';
|
|
173
|
+
|
|
174
|
+
const server = setupServer(
|
|
175
|
+
http.get('/api/users/:id', ({ params }) => {
|
|
176
|
+
return HttpResponse.json({ id: params.id, name: 'Test User' });
|
|
177
|
+
})
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
beforeAll(() => server.listen());
|
|
181
|
+
afterEach(() => server.resetHandlers());
|
|
182
|
+
afterAll(() => server.close());
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### React Components (Testing Library)
|
|
186
|
+
|
|
187
|
+
```tsx
|
|
188
|
+
import { render, screen, waitFor } from '@testing-library/react';
|
|
189
|
+
import userEvent from '@testing-library/user-event';
|
|
190
|
+
|
|
191
|
+
describe('LoginForm', () => {
|
|
192
|
+
it('should submit with valid credentials', async () => {
|
|
193
|
+
const onSubmit = vi.fn();
|
|
194
|
+
const user = userEvent.setup();
|
|
195
|
+
render(<LoginForm onSubmit={onSubmit} />);
|
|
196
|
+
await user.type(screen.getByLabelText(/email/i), 'test@example.com');
|
|
197
|
+
await user.type(screen.getByLabelText(/password/i), 'password123');
|
|
198
|
+
await user.click(screen.getByRole('button', { name: /sign in/i }));
|
|
199
|
+
await waitFor(() => {
|
|
200
|
+
expect(onSubmit).toHaveBeenCalledWith({
|
|
201
|
+
email: 'test@example.com', password: 'password123',
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('should show validation error for invalid email', async () => {
|
|
207
|
+
const user = userEvent.setup();
|
|
208
|
+
render(<LoginForm onSubmit={vi.fn()} />);
|
|
209
|
+
await user.type(screen.getByLabelText(/email/i), 'invalid');
|
|
210
|
+
await user.click(screen.getByRole('button', { name: /sign in/i }));
|
|
211
|
+
expect(screen.getByText(/valid email/i)).toBeInTheDocument();
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('should disable submit button while loading', () => {
|
|
215
|
+
render(<LoginForm onSubmit={vi.fn()} isLoading />);
|
|
216
|
+
expect(screen.getByRole('button', { name: /sign in/i })).toBeDisabled();
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Custom Hooks
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
import { renderHook, act } from '@testing-library/react';
|
|
225
|
+
|
|
226
|
+
describe('useCounter', () => {
|
|
227
|
+
it('should start with initial value', () => {
|
|
228
|
+
const { result } = renderHook(() => useCounter(10));
|
|
229
|
+
expect(result.current.count).toBe(10);
|
|
230
|
+
});
|
|
231
|
+
it('should increment', () => {
|
|
232
|
+
const { result } = renderHook(() => useCounter(0));
|
|
233
|
+
act(() => result.current.increment());
|
|
234
|
+
expect(result.current.count).toBe(1);
|
|
235
|
+
});
|
|
236
|
+
it('should not go below zero', () => {
|
|
237
|
+
const { result } = renderHook(() => useCounter(0));
|
|
238
|
+
act(() => result.current.decrement());
|
|
239
|
+
expect(result.current.count).toBe(0);
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### API Route Handlers (Next.js / Node)
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
describe('POST /api/users', () => {
|
|
248
|
+
it('should create user with valid data', async () => {
|
|
249
|
+
const req = new Request('http://localhost/api/users', {
|
|
250
|
+
method: 'POST',
|
|
251
|
+
body: JSON.stringify({ name: 'Test', email: 'test@example.com' }),
|
|
252
|
+
});
|
|
253
|
+
const response = await POST(req);
|
|
254
|
+
const data = await response.json();
|
|
255
|
+
expect(response.status).toBe(201);
|
|
256
|
+
expect(data).toMatchObject({ name: 'Test', email: 'test@example.com' });
|
|
257
|
+
});
|
|
258
|
+
it('should return 422 for invalid email', async () => {
|
|
259
|
+
const req = new Request('http://localhost/api/users', {
|
|
260
|
+
method: 'POST',
|
|
261
|
+
body: JSON.stringify({ name: 'Test', email: 'invalid' }),
|
|
262
|
+
});
|
|
263
|
+
const response = await POST(req);
|
|
264
|
+
expect(response.status).toBe(422);
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
```
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: test-visual-regression
|
|
3
|
+
description: >
|
|
4
|
+
Set up Playwright screenshot baselines and CI diffing so UI changes fail
|
|
5
|
+
pixel by pixel instead of by eye. Use when "add visual regression tests" or
|
|
6
|
+
"catch UI regressions". Functional clicks → test-playwright.
|
|
7
|
+
license: MIT
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# test-visual-regression — Screenshot baselines that stay green
|
|
11
|
+
|
|
12
|
+
**Degree of freedom: MIXED** — what to baseline `[HIGH freedom]`;
|
|
13
|
+
determinism loop and 3× clean runs `[LOW freedom — run exactly]`.
|
|
14
|
+
playwright-cli / project runner — never Playwright MCP.
|
|
15
|
+
|
|
16
|
+
Establish a screenshot baseline for important UI states and wire diffing so
|
|
17
|
+
unintended visual change fails CI.
|
|
18
|
+
|
|
19
|
+
**Functional tests prove the button works; visual tests prove it didn't move,
|
|
20
|
+
shrink, lose styling, or overlap the next element.**
|
|
21
|
+
|
|
22
|
+
Use **playwright-cli** (`npx --yes @playwright/cli@latest`) and the project's
|
|
23
|
+
Playwright test runner — never Playwright MCP. Read
|
|
24
|
+
`protocol-browser-anti-stall` before any headed session.
|
|
25
|
+
|
|
26
|
+
## This skill vs neighbors
|
|
27
|
+
|
|
28
|
+
| Skill | Owns |
|
|
29
|
+
|---|---|
|
|
30
|
+
| **test-visual-regression** (this) | Pixel baselines + CI diff artifacts |
|
|
31
|
+
| `test-playwright` | Drive the app like a user; fix functional pain |
|
|
32
|
+
| `audit-responsive` | Find linearized layout; this *locks* the fix |
|
|
33
|
+
| `audit-ui-states` | Design empty/error states; this *locks* them |
|
|
34
|
+
| `audit-uiux-design-system` | Token/component compliance (not screenshot CI) |
|
|
35
|
+
| `test-qa` | Exploratory CRUD QA |
|
|
36
|
+
|
|
37
|
+
## How to reason
|
|
38
|
+
|
|
39
|
+
1. **Observe** — which surface, viewport, and state; what is volatile
|
|
40
|
+
2. **Interpret** — will this pixel-lock a bug, or fail every run on a timestamp?
|
|
41
|
+
3. **Classify** — baseline / exclude / mask
|
|
42
|
+
4. **Severity** — unmasked volatile content = harness will be abandoned
|
|
43
|
+
|
|
44
|
+
## Worked example
|
|
45
|
+
|
|
46
|
+
> **Observe:** dashboard spec screenshots the whole page; a relative
|
|
47
|
+
> "Updated 3s ago" label sits in the header.
|
|
48
|
+
> **Interpret:** every CI run diffs that label.
|
|
49
|
+
> **Classify:** must mask (or freeze time) — not a product regression.
|
|
50
|
+
> **Fix:** `mask` the timestamp; prove ≥3 consecutive local runs with zero diff.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Phase 0 — Detect the setup [HIGH freedom]
|
|
55
|
+
|
|
56
|
+
- Test runner: Playwright test / Vitest / Storybook + Chromatic/Loki
|
|
57
|
+
- Existing snapshot config
|
|
58
|
+
- Route list or story catalog
|
|
59
|
+
- CI provider (usually GitHub Actions)
|
|
60
|
+
|
|
61
|
+
Prefer the repo's existing Playwright. Do not add a second visual vendor if
|
|
62
|
+
Playwright screenshots already work.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Phase 1 — Choose what to baseline (not everything) [HIGH freedom]
|
|
67
|
+
|
|
68
|
+
- **Key screens** at 375 / 768 / 1440 (`audit-responsive` breakpoints)
|
|
69
|
+
- **State matrix** from `audit-ui-states`: empty, error, loaded
|
|
70
|
+
- **DS primitives:** button/input/card variants
|
|
71
|
+
- **Both color schemes** if dark mode exists
|
|
72
|
+
|
|
73
|
+
Exclude volatile content (timestamps, live feeds, mid-animation). Mask or
|
|
74
|
+
freeze it — otherwise every run is a false positive.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Phase 2 — Determinism (or the suite gets abandoned) [LOW freedom — 3× clean]
|
|
79
|
+
|
|
80
|
+
- Seeded fixtures, never live/random content
|
|
81
|
+
- Freeze time; `prefers-reduced-motion`; disable transitions
|
|
82
|
+
- Wait for fonts + images + network idle
|
|
83
|
+
- Mask dates/avatars via the tool's mask API
|
|
84
|
+
- Pin viewport, device-scale-factor, browser version
|
|
85
|
+
- Same environment locally and in CI (container) so host fonts don't diff
|
|
86
|
+
|
|
87
|
+
Prove stability: **≥3 consecutive local runs with zero diff** before calling
|
|
88
|
+
the harness done.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Phase 3 — Wire the loop [HIGH freedom]
|
|
93
|
+
|
|
94
|
+
- Commit baselines after a human reviews them (a broken screen locks the bug)
|
|
95
|
+
- CI required check; upload expected / actual / diff artifacts
|
|
96
|
+
- Intentional UI changes update snapshots in the same PR (`--update-snapshots`)
|
|
97
|
+
- Small anti-aliasing threshold only — never wide enough to hide real shifts
|
|
98
|
+
|
|
99
|
+
Save ad-hoc captures under `.playwright-mcp/`, not the repo root.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Definition of Done
|
|
104
|
+
|
|
105
|
+
- [ ] Tooling + snapshot config in place
|
|
106
|
+
- [ ] Baseline scoped to key screens × breakpoints + critical states + DS primitives
|
|
107
|
+
- [ ] Volatile regions masked; 3× local runs clean
|
|
108
|
+
- [ ] Baselines human-reviewed
|
|
109
|
+
- [ ] CI check + triptych artifacts
|
|
110
|
+
- [ ] Update path documented
|
|
111
|
+
|
|
112
|
+
## Self-critique before reporting [LOW freedom — do not skip]
|
|
113
|
+
|
|
114
|
+
1. **3× clean locally** — fewer is not "done"
|
|
115
|
+
2. **Human reviewed baselines** — a broken screen must not be locked
|
|
116
|
+
3. **Threshold tight** — anti-alias only; never hide real shifts
|
|
117
|
+
4. **Right owner** — functional clicks stay on `test-playwright`
|
|
118
|
+
5. **Artifacts** under `.playwright-mcp/` for ad-hoc; baselines in the harness dir
|
|
119
|
+
|
|
120
|
+
## Output format
|
|
121
|
+
|
|
122
|
+
1. **Baseline plan** — captured / excluded / why
|
|
123
|
+
2. **Determinism checklist** — flakiness source → neutralization
|
|
124
|
+
3. **CI wiring** — check, artifacts, update path
|
|
125
|
+
4. Implement the harness; present artifact location
|
|
126
|
+
|
|
127
|
+
## Related
|
|
128
|
+
|
|
129
|
+
- `audit-responsive` / `audit-ui-states` — what to lock
|
|
130
|
+
- `test-playwright` / `test-qa` — functional, not pixel
|
|
131
|
+
- `protocol-browser-anti-stall` — headed sessions
|
|
132
|
+
- `audit-cicd` — CI minutes / artifact retention
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Attribution — thirdparty-emil-design-eng
|
|
2
|
+
|
|
3
|
+
| Field | Value |
|
|
4
|
+
|-------|-------|
|
|
5
|
+
| **Upstream** | [emilkowalski/skills](https://github.com/emilkowalski/skills) |
|
|
6
|
+
| **Upstream path** | `skills/emil-design-eng/SKILL.md` |
|
|
7
|
+
| **Author** | Emil Kowalski |
|
|
8
|
+
| **License** | [MIT](https://github.com/emilkowalski/skills/blob/main/LICENSE) — Copyright (c) 2026 Emil Kowalski |
|
|
9
|
+
| **Local name** | `thirdparty-emil-design-eng` |
|
|
10
|
+
| **Curated in** | [kenji](https://github.com/kensaurus/skills) |
|
|
11
|
+
|
|
12
|
+
## Update policy
|
|
13
|
+
|
|
14
|
+
1. Pull the latest `SKILL.md` from upstream.
|
|
15
|
+
2. Replace `references/emil-design-eng.md` with the upstream body beginning
|
|
16
|
+
at `## Initial Response`; keep the thin local `SKILL.md` loader.
|
|
17
|
+
3. Adjust only the final local attribution link to `../ATTRIBUTION.md`.
|
|
18
|
+
4. Run the repository validation and install smoke test.
|
|
19
|
+
|
|
20
|
+
Do **not** add Kenji-specific "Check Existing First" sections to upstream content — keep this skill faithful to the source.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: thirdparty-emil-design-eng
|
|
3
|
+
description: >
|
|
4
|
+
Third-party skill — Emil Kowalski's design-engineering notes (animation
|
|
5
|
+
craft, Sonner-style components). Use when the user names emil-design-eng or
|
|
6
|
+
asks for that philosophy. Motion pass → enhance-motion.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Design Engineering
|
|
10
|
+
|
|
11
|
+
> **Third-party skill** (upstream-maintained). See [ATTRIBUTION.md](ATTRIBUTION.md).
|
|
12
|
+
> Upstream: [emilkowalski/skills](https://github.com/emilkowalski/skills) · Local name: `thirdparty-emil-design-eng`
|
|
13
|
+
|
|
14
|
+
Before responding, read
|
|
15
|
+
[`references/emil-design-eng.md`](references/emil-design-eng.md) **in full**
|
|
16
|
+
and follow it as the authoritative playbook. It contains the required initial
|
|
17
|
+
response, review format, animation guidance, accessibility rules, and checklist.
|
|
18
|
+
|
|
19
|
+
The upstream body is kept in that single canonical reference file so future
|
|
20
|
+
syncs remain diff-able without loading 600+ lines into the routing surface.
|
|
21
|
+
Only local attribution links are adjusted for the reference location.
|