@kensaurus/skills 0.0.0-stage → 2.0.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 +1761 -0
- package/LICENSE +21 -0
- package/NOTICE +13 -0
- package/README.md +820 -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 +93 -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 +296 -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 +154 -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 +379 -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 +304 -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-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 +242 -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 +104 -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 +387 -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 +296 -0
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-error-handling
|
|
3
|
+
description: >
|
|
4
|
+
Implement error-handling patterns: boundaries, toasts, one API error shape.
|
|
5
|
+
Use when "error boundary", "error toast", or "standardize API errors".
|
|
6
|
+
Plan-only audit → plan-error-handling. Sentry triage → debug-sentry-monitor.
|
|
7
|
+
license: MIT
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Error Handling Skill
|
|
11
|
+
|
|
12
|
+
**Degree of freedom: MIXED.** Which layer and message `[HIGH freedom]`;
|
|
13
|
+
existing-type/boundary probes `[LOW freedom — run exactly]`.
|
|
14
|
+
|
|
15
|
+
## How to reason
|
|
16
|
+
|
|
17
|
+
1. **Observe** — existing error types, boundaries, `ActionResult` / `ApiError`
|
|
18
|
+
2. **Interpret** — missing layer vs inconsistent shape vs swallowed catch
|
|
19
|
+
3. **Classify** — reuse-existing / extend-codes / add-boundary / toast-only
|
|
20
|
+
4. **Severity** — unhandled 500 on a mutation outranks a missing toast
|
|
21
|
+
|
|
22
|
+
## Worked example
|
|
23
|
+
|
|
24
|
+
> **Observe:** `createUser` throws Prisma `P2002`; UI shows a blank catch; `ActionResult` already lives in `types/errors.ts`.
|
|
25
|
+
> **Interpret:** known conflict is unmapped; no field/toast path.
|
|
26
|
+
> **Classify:** reuse `ActionResult` + `CONFLICT`; toast the message; do not add a second error type.
|
|
27
|
+
> **Verify:** duplicate email returns `{ success: false, error: { code: 'CONFLICT' } }`; form alert shown.
|
|
28
|
+
|
|
29
|
+
## Self-critique before reporting
|
|
30
|
+
|
|
31
|
+
- **Reuse shape** — searched `ActionResult` / `ApiError` / `error.tsx` before adding a type
|
|
32
|
+
- **User-safe** — `INTERNAL_ERROR` is generic; PII is not in the client message
|
|
33
|
+
- **Layered** — boundary + action result + toast, not toast-only
|
|
34
|
+
- **Right owner** — plan-only observability audit → `plan-error-handling`; live Sentry triage → `debug-sentry-monitor`
|
|
35
|
+
|
|
36
|
+
Layered error handling for full-stack apps: one action-result shape, boundaries, and toasts.
|
|
37
|
+
|
|
38
|
+
## When to Use
|
|
39
|
+
|
|
40
|
+
- Adding error handling to new features
|
|
41
|
+
- Improving error user experience
|
|
42
|
+
- Standardizing error responses
|
|
43
|
+
- Debugging error propagation
|
|
44
|
+
- Adding error monitoring
|
|
45
|
+
|
|
46
|
+
## Check existing first [LOW freedom — run exactly]
|
|
47
|
+
|
|
48
|
+
**Before adding ANY error handling, verify:**
|
|
49
|
+
|
|
50
|
+
1. **Check for existing error types:**
|
|
51
|
+
```bash
|
|
52
|
+
rg "type.*Error|interface.*Error" --type ts
|
|
53
|
+
rg "ActionResult|ApiError" --type ts
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
2. **Check for existing error boundaries:**
|
|
57
|
+
```bash
|
|
58
|
+
ls -la app/error.tsx app/global-error.tsx
|
|
59
|
+
rg "ErrorBoundary" --type tsx
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
3. **Check for existing error utilities:**
|
|
63
|
+
```bash
|
|
64
|
+
rg "formatError|handleError|reportError" --type ts
|
|
65
|
+
ls -la src/lib/errors* src/lib/error* 2>/dev/null # @/lib/errors
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
4. **Check established error response patterns:**
|
|
69
|
+
```bash
|
|
70
|
+
rg "success: false|error:" src/features/*/server/ --type ts | head -10
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Why:** Inconsistent error handling confuses users and complicates debugging. Always follow established patterns.
|
|
74
|
+
|
|
75
|
+
## Error Handling Layers [HIGH freedom]
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
┌─────────────────────────────────────────┐
|
|
79
|
+
│ UI Layer │
|
|
80
|
+
│ - Error boundaries │
|
|
81
|
+
│ - Form validation errors │
|
|
82
|
+
│ - Toast notifications │
|
|
83
|
+
├─────────────────────────────────────────┤
|
|
84
|
+
│ Application Layer │
|
|
85
|
+
│ - Server Action errors │
|
|
86
|
+
│ - API route errors │
|
|
87
|
+
│ - Business logic errors │
|
|
88
|
+
├─────────────────────────────────────────┤
|
|
89
|
+
│ Data Layer │
|
|
90
|
+
│ - Database errors │
|
|
91
|
+
│ - Validation errors (Zod) │
|
|
92
|
+
│ - External API errors │
|
|
93
|
+
└─────────────────────────────────────────┘
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Standard Error Types [HIGH freedom]
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
// types/errors.ts
|
|
100
|
+
|
|
101
|
+
// Base error shape
|
|
102
|
+
interface AppError {
|
|
103
|
+
code: string // Machine-readable: VALIDATION_ERROR
|
|
104
|
+
message: string // User-friendly message
|
|
105
|
+
details?: unknown // Additional context
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Action result pattern
|
|
109
|
+
type ActionResult<T> =
|
|
110
|
+
| { success: true; data: T }
|
|
111
|
+
| { success: false; error: AppError }
|
|
112
|
+
|
|
113
|
+
// Common error codes
|
|
114
|
+
const ErrorCode = {
|
|
115
|
+
VALIDATION_ERROR: 'VALIDATION_ERROR',
|
|
116
|
+
NOT_FOUND: 'NOT_FOUND',
|
|
117
|
+
UNAUTHORIZED: 'UNAUTHORIZED',
|
|
118
|
+
FORBIDDEN: 'FORBIDDEN',
|
|
119
|
+
CONFLICT: 'CONFLICT',
|
|
120
|
+
RATE_LIMITED: 'RATE_LIMITED',
|
|
121
|
+
INTERNAL_ERROR: 'INTERNAL_ERROR',
|
|
122
|
+
} as const
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Server Action Error Handling [HIGH freedom]
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
// features/users/server/actions.ts
|
|
129
|
+
'use server'
|
|
130
|
+
|
|
131
|
+
import { z } from 'zod'
|
|
132
|
+
import { revalidatePath } from 'next/cache'
|
|
133
|
+
|
|
134
|
+
const CreateUserSchema = z.object({
|
|
135
|
+
email: z.string().email('Invalid email address'),
|
|
136
|
+
name: z.string().min(1, 'Name is required'),
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
export async function createUser(
|
|
140
|
+
prevState: ActionResult<User>,
|
|
141
|
+
formData: FormData
|
|
142
|
+
): Promise<ActionResult<User>> {
|
|
143
|
+
try {
|
|
144
|
+
// 1. Validate input
|
|
145
|
+
const validated = CreateUserSchema.safeParse({
|
|
146
|
+
email: formData.get('email'),
|
|
147
|
+
name: formData.get('name'),
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
if (!validated.success) {
|
|
151
|
+
return {
|
|
152
|
+
success: false,
|
|
153
|
+
error: {
|
|
154
|
+
code: 'VALIDATION_ERROR',
|
|
155
|
+
message: 'Invalid input',
|
|
156
|
+
details: validated.error.flatten().fieldErrors,
|
|
157
|
+
},
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// 2. Check authorization
|
|
162
|
+
const session = await auth()
|
|
163
|
+
if (!session) {
|
|
164
|
+
return {
|
|
165
|
+
success: false,
|
|
166
|
+
error: {
|
|
167
|
+
code: 'UNAUTHORIZED',
|
|
168
|
+
message: 'Please sign in to continue',
|
|
169
|
+
},
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// 3. Execute business logic
|
|
174
|
+
const user = await db.user.create({
|
|
175
|
+
data: validated.data,
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
revalidatePath('/users')
|
|
179
|
+
|
|
180
|
+
return { success: true, data: user }
|
|
181
|
+
|
|
182
|
+
} catch (error) {
|
|
183
|
+
// 4. Handle known errors
|
|
184
|
+
if (error instanceof Prisma.PrismaClientKnownRequestError) {
|
|
185
|
+
if (error.code === 'P2002') {
|
|
186
|
+
return {
|
|
187
|
+
success: false,
|
|
188
|
+
error: {
|
|
189
|
+
code: 'CONFLICT',
|
|
190
|
+
message: 'A user with this email already exists',
|
|
191
|
+
},
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// 5. Log unknown errors, return generic message
|
|
197
|
+
console.error('createUser error:', error)
|
|
198
|
+
|
|
199
|
+
return {
|
|
200
|
+
success: false,
|
|
201
|
+
error: {
|
|
202
|
+
code: 'INTERNAL_ERROR',
|
|
203
|
+
message: 'Something went wrong. Please try again.',
|
|
204
|
+
},
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Form Error Display (React 19+) [HIGH freedom]
|
|
211
|
+
|
|
212
|
+
```tsx
|
|
213
|
+
// components/UserForm.tsx
|
|
214
|
+
'use client'
|
|
215
|
+
|
|
216
|
+
import { useActionState } from 'react'
|
|
217
|
+
import { useFormStatus } from 'react-dom'
|
|
218
|
+
import { createUser } from '@/features/users/server/actions'
|
|
219
|
+
|
|
220
|
+
// Separate submit button to use useFormStatus
|
|
221
|
+
function SubmitButton() {
|
|
222
|
+
const { pending } = useFormStatus()
|
|
223
|
+
return (
|
|
224
|
+
<button type="submit" disabled={pending}>
|
|
225
|
+
{pending ? 'Creating...' : 'Create User'}
|
|
226
|
+
</button>
|
|
227
|
+
)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export function UserForm() {
|
|
231
|
+
const [state, action, isPending] = useActionState(createUser, null)
|
|
232
|
+
|
|
233
|
+
// Get field errors from validation
|
|
234
|
+
const fieldErrors = state?.success === false
|
|
235
|
+
? state.error.details as Record<string, string[]>
|
|
236
|
+
: {}
|
|
237
|
+
|
|
238
|
+
return (
|
|
239
|
+
<form action={action}>
|
|
240
|
+
{/* Global error */}
|
|
241
|
+
{state?.success === false && state.error.code !== 'VALIDATION_ERROR' && (
|
|
242
|
+
<div role="alert" className="bg-red-50 text-red-700 p-3 rounded-lg mb-4">
|
|
243
|
+
{state.error.message}
|
|
244
|
+
</div>
|
|
245
|
+
)}
|
|
246
|
+
|
|
247
|
+
{/* Field with error */}
|
|
248
|
+
<div>
|
|
249
|
+
<label htmlFor="email">Email</label>
|
|
250
|
+
<input
|
|
251
|
+
id="email"
|
|
252
|
+
name="email"
|
|
253
|
+
type="email"
|
|
254
|
+
aria-invalid={!!fieldErrors.email}
|
|
255
|
+
aria-describedby={fieldErrors.email ? 'email-error' : undefined}
|
|
256
|
+
className={fieldErrors.email ? 'border-red-500' : ''}
|
|
257
|
+
/>
|
|
258
|
+
{fieldErrors.email && (
|
|
259
|
+
<p id="email-error" className="text-red-600 text-sm mt-1">
|
|
260
|
+
{fieldErrors.email[0]}
|
|
261
|
+
</p>
|
|
262
|
+
)}
|
|
263
|
+
</div>
|
|
264
|
+
|
|
265
|
+
<SubmitButton />
|
|
266
|
+
</form>
|
|
267
|
+
)
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**React 19 Form Patterns:**
|
|
272
|
+
- `useActionState` - Form state with Server Actions
|
|
273
|
+
- `useFormStatus` - Pending state in child components
|
|
274
|
+
- `useOptimistic` - Optimistic UI updates
|
|
275
|
+
|
|
276
|
+
## React Error Boundaries [HIGH freedom]
|
|
277
|
+
|
|
278
|
+
```tsx
|
|
279
|
+
// app/error.tsx (Next.js page error boundary)
|
|
280
|
+
'use client'
|
|
281
|
+
|
|
282
|
+
import { useEffect } from 'react'
|
|
283
|
+
|
|
284
|
+
export default function Error({
|
|
285
|
+
error,
|
|
286
|
+
reset,
|
|
287
|
+
}: {
|
|
288
|
+
error: Error & { digest?: string }
|
|
289
|
+
reset: () => void
|
|
290
|
+
}) {
|
|
291
|
+
useEffect(() => {
|
|
292
|
+
// Log to error reporting service
|
|
293
|
+
console.error('Page error:', error)
|
|
294
|
+
}, [error])
|
|
295
|
+
|
|
296
|
+
return (
|
|
297
|
+
<div className="flex flex-col items-center justify-center min-h-[400px]">
|
|
298
|
+
<h2 className="text-xl font-semibold mb-4">Something went wrong</h2>
|
|
299
|
+
<p className="text-muted-foreground mb-6">
|
|
300
|
+
We're sorry, but something unexpected happened.
|
|
301
|
+
</p>
|
|
302
|
+
<button
|
|
303
|
+
onClick={reset}
|
|
304
|
+
className="px-4 py-2 bg-primary text-primary-foreground rounded-lg"
|
|
305
|
+
>
|
|
306
|
+
Try again
|
|
307
|
+
</button>
|
|
308
|
+
</div>
|
|
309
|
+
)
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// app/global-error.tsx (root error boundary)
|
|
313
|
+
'use client'
|
|
314
|
+
|
|
315
|
+
export default function GlobalError({
|
|
316
|
+
error,
|
|
317
|
+
reset,
|
|
318
|
+
}: {
|
|
319
|
+
error: Error & { digest?: string }
|
|
320
|
+
reset: () => void
|
|
321
|
+
}) {
|
|
322
|
+
return (
|
|
323
|
+
<html>
|
|
324
|
+
<body>
|
|
325
|
+
<h2>Something went wrong!</h2>
|
|
326
|
+
<button onClick={reset}>Try again</button>
|
|
327
|
+
</body>
|
|
328
|
+
</html>
|
|
329
|
+
)
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
## API Route Error Handling [HIGH freedom]
|
|
334
|
+
|
|
335
|
+
```typescript
|
|
336
|
+
// app/api/products/route.ts
|
|
337
|
+
import { NextRequest, NextResponse } from 'next/server'
|
|
338
|
+
import { z } from 'zod'
|
|
339
|
+
|
|
340
|
+
export async function POST(request: NextRequest) {
|
|
341
|
+
try {
|
|
342
|
+
const body = await request.json()
|
|
343
|
+
|
|
344
|
+
const validated = ProductSchema.safeParse(body)
|
|
345
|
+
if (!validated.success) {
|
|
346
|
+
return NextResponse.json(
|
|
347
|
+
{
|
|
348
|
+
error: {
|
|
349
|
+
code: 'VALIDATION_ERROR',
|
|
350
|
+
message: 'Invalid request body',
|
|
351
|
+
details: validated.error.flatten().fieldErrors,
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
{ status: 400 }
|
|
355
|
+
)
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const product = await db.product.create({ data: validated.data })
|
|
359
|
+
|
|
360
|
+
return NextResponse.json({ data: product }, { status: 201 })
|
|
361
|
+
|
|
362
|
+
} catch (error) {
|
|
363
|
+
if (error instanceof SyntaxError) {
|
|
364
|
+
return NextResponse.json(
|
|
365
|
+
{ error: { code: 'INVALID_JSON', message: 'Invalid JSON body' } },
|
|
366
|
+
{ status: 400 }
|
|
367
|
+
)
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
console.error('POST /api/products error:', error)
|
|
371
|
+
|
|
372
|
+
return NextResponse.json(
|
|
373
|
+
{ error: { code: 'INTERNAL_ERROR', message: 'Internal server error' } },
|
|
374
|
+
{ status: 500 }
|
|
375
|
+
)
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
## TanStack Query Error Handling [HIGH freedom]
|
|
381
|
+
|
|
382
|
+
```tsx
|
|
383
|
+
// hooks/useProducts.ts
|
|
384
|
+
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
|
385
|
+
import { toast } from 'sonner'
|
|
386
|
+
|
|
387
|
+
export function useProducts() {
|
|
388
|
+
return useQuery({
|
|
389
|
+
queryKey: ['products'],
|
|
390
|
+
queryFn: async () => {
|
|
391
|
+
const res = await fetch('/api/products')
|
|
392
|
+
if (!res.ok) {
|
|
393
|
+
const error = await res.json()
|
|
394
|
+
throw new Error(error.error?.message || 'Failed to fetch products')
|
|
395
|
+
}
|
|
396
|
+
return res.json()
|
|
397
|
+
},
|
|
398
|
+
retry: (failureCount, error) => {
|
|
399
|
+
// Don't retry on 4xx errors
|
|
400
|
+
if (error.message.includes('401') || error.message.includes('403')) {
|
|
401
|
+
return false
|
|
402
|
+
}
|
|
403
|
+
return failureCount < 3
|
|
404
|
+
},
|
|
405
|
+
})
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
export function useCreateProduct() {
|
|
409
|
+
const queryClient = useQueryClient()
|
|
410
|
+
|
|
411
|
+
return useMutation({
|
|
412
|
+
mutationFn: async (data: ProductInput) => {
|
|
413
|
+
const res = await fetch('/api/products', {
|
|
414
|
+
method: 'POST',
|
|
415
|
+
body: JSON.stringify(data),
|
|
416
|
+
})
|
|
417
|
+
if (!res.ok) {
|
|
418
|
+
const error = await res.json()
|
|
419
|
+
throw new Error(error.error?.message || 'Failed to create product')
|
|
420
|
+
}
|
|
421
|
+
return res.json()
|
|
422
|
+
},
|
|
423
|
+
onSuccess: () => {
|
|
424
|
+
queryClient.invalidateQueries({ queryKey: ['products'] })
|
|
425
|
+
toast.success('Product created')
|
|
426
|
+
},
|
|
427
|
+
onError: (error) => {
|
|
428
|
+
toast.error(error.message)
|
|
429
|
+
},
|
|
430
|
+
})
|
|
431
|
+
}
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
## Error State UI Components [HIGH freedom]
|
|
435
|
+
|
|
436
|
+
```tsx
|
|
437
|
+
// components/ErrorState.tsx
|
|
438
|
+
import { AlertCircle, RefreshCw } from 'lucide-react'
|
|
439
|
+
|
|
440
|
+
interface ErrorStateProps {
|
|
441
|
+
title?: string
|
|
442
|
+
message: string
|
|
443
|
+
onRetry?: () => void
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
export function ErrorState({
|
|
447
|
+
title = 'Error',
|
|
448
|
+
message,
|
|
449
|
+
onRetry
|
|
450
|
+
}: ErrorStateProps) {
|
|
451
|
+
return (
|
|
452
|
+
<div className="flex flex-col items-center justify-center py-12 text-center">
|
|
453
|
+
<AlertCircle className="h-12 w-12 text-red-500 mb-4" />
|
|
454
|
+
<h3 className="font-semibold text-lg mb-2">{title}</h3>
|
|
455
|
+
<p className="text-muted-foreground mb-6 max-w-sm">{message}</p>
|
|
456
|
+
{onRetry && (
|
|
457
|
+
<button
|
|
458
|
+
onClick={onRetry}
|
|
459
|
+
className="inline-flex items-center gap-2 px-4 py-2 border rounded-lg hover:bg-muted"
|
|
460
|
+
>
|
|
461
|
+
<RefreshCw className="h-4 w-4" />
|
|
462
|
+
Try again
|
|
463
|
+
</button>
|
|
464
|
+
)}
|
|
465
|
+
</div>
|
|
466
|
+
)
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// Usage with TanStack Query
|
|
470
|
+
function ProductList() {
|
|
471
|
+
const { data, error, isLoading, refetch } = useProducts()
|
|
472
|
+
|
|
473
|
+
if (error) {
|
|
474
|
+
return (
|
|
475
|
+
<ErrorState
|
|
476
|
+
title="Failed to load products"
|
|
477
|
+
message={error.message}
|
|
478
|
+
onRetry={() => refetch()}
|
|
479
|
+
/>
|
|
480
|
+
)
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// ...
|
|
484
|
+
}
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
## Further reading
|
|
488
|
+
|
|
489
|
+
- [Error Logging & Monitoring and more](references/details.md)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
## Error Logging & Monitoring
|
|
2
|
+
|
|
3
|
+
```typescript
|
|
4
|
+
// lib/error-reporting.ts
|
|
5
|
+
|
|
6
|
+
export function reportError(error: Error, context?: Record<string, unknown>) {
|
|
7
|
+
// Development: log to console
|
|
8
|
+
if (process.env.NODE_ENV === 'development') {
|
|
9
|
+
console.error('Error:', error, context)
|
|
10
|
+
return
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Production: send to monitoring service
|
|
14
|
+
// Sentry example:
|
|
15
|
+
// Sentry.captureException(error, { extra: context })
|
|
16
|
+
|
|
17
|
+
// Or custom logging:
|
|
18
|
+
fetch('/api/log-error', {
|
|
19
|
+
method: 'POST',
|
|
20
|
+
body: JSON.stringify({
|
|
21
|
+
message: error.message,
|
|
22
|
+
stack: error.stack,
|
|
23
|
+
context,
|
|
24
|
+
timestamp: new Date().toISOString(),
|
|
25
|
+
}),
|
|
26
|
+
}).catch(() => {}) // Don't throw on logging failure
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Error Handling Checklist
|
|
31
|
+
|
|
32
|
+
### Server Side
|
|
33
|
+
- [ ] All Server Actions return `ActionResult<T>`
|
|
34
|
+
- [ ] Zod validation with user-friendly messages
|
|
35
|
+
- [ ] Known errors caught and mapped
|
|
36
|
+
- [ ] Unknown errors logged, generic message returned
|
|
37
|
+
- [ ] No sensitive info in error messages
|
|
38
|
+
|
|
39
|
+
### Client Side
|
|
40
|
+
- [ ] Error boundaries at page level
|
|
41
|
+
- [ ] Global error boundary for catastrophic failures
|
|
42
|
+
- [ ] Form field errors displayed inline
|
|
43
|
+
- [ ] Global errors shown in alert/toast
|
|
44
|
+
- [ ] Loading states during async operations
|
|
45
|
+
- [ ] Retry buttons where appropriate
|
|
46
|
+
|
|
47
|
+
### API
|
|
48
|
+
- [ ] Consistent error response shape
|
|
49
|
+
- [ ] Appropriate HTTP status codes
|
|
50
|
+
- [ ] Validation errors include field details
|
|
51
|
+
- [ ] Rate limiting with 429 response
|
|
52
|
+
- [ ] No stack traces in production
|
|
53
|
+
|
|
54
|
+
### Monitoring
|
|
55
|
+
- [ ] Error logging configured
|
|
56
|
+
- [ ] Alerts for critical errors
|
|
57
|
+
- [ ] Error rates tracked
|
|
58
|
+
- [ ] User-facing errors monitored
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-observability
|
|
3
|
+
description: >
|
|
4
|
+
Implement correlated errors, traces, and structured logs with PII redaction.
|
|
5
|
+
Use when "add logging", "instrument this", or wiring Sentry/Langfuse.
|
|
6
|
+
Plan-only audit → plan-error-handling. Sentry triage → debug-sentry-monitor.
|
|
7
|
+
license: MIT
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Observability Instrumentation
|
|
11
|
+
|
|
12
|
+
**Degree of freedom: MIXED.** What to wrap and alert on `[HIGH freedom]`;
|
|
13
|
+
correlation ids, PII redaction, and the DoD `[LOW freedom — run exactly]`.
|
|
14
|
+
|
|
15
|
+
## How to reason
|
|
16
|
+
|
|
17
|
+
1. **Observe** — which ids, logs, spans, and PII already exist
|
|
18
|
+
2. **Interpret** — can you pivot error ↔ trace ↔ log ↔ user from any one?
|
|
19
|
+
3. **Classify** — add-correlation / convert-console / redact / wrap-span / alert
|
|
20
|
+
4. **Severity** — uncorrelated prod 500 outranks a missing debug field
|
|
21
|
+
|
|
22
|
+
## Worked example
|
|
23
|
+
|
|
24
|
+
> **Observe:** checkout 500 in Sentry has no request_id; pino logs the cart id; no LLM (Langfuse unused).
|
|
25
|
+
> **Interpret:** cannot pivot error → logs; webhook still `console.log`s.
|
|
26
|
+
> **Classify:** ALS request_id on logs + `Sentry.setTag`; convert console to pino; redact `Authorization`.
|
|
27
|
+
> **Verify:** one id on the Sentry event and the log line; `beforeSend` strips the header.
|
|
28
|
+
|
|
29
|
+
## Self-critique before reporting
|
|
30
|
+
|
|
31
|
+
- **Correlated** — same request/trace id on the log, Sentry, and Langfuse
|
|
32
|
+
- **Redacted** — deny-list at the logger + `beforeSend`, not per-call hope
|
|
33
|
+
- **Leveled** — no `console.log` in prod; handled paths are not `error`
|
|
34
|
+
- **Right owner** — plan-only audit → `plan-error-handling`; investigate a Sentry issue → `debug-sentry-monitor`
|
|
35
|
+
|
|
36
|
+
> The build-time counterpart to your monitoring stack. The Sentry plugin installs the SDK; `debug-sentry-monitor` triages after the fact; `audit-langfuse-llm` audits LLM traces. This skill is about instrumenting **correctly while you build** so those tools have signal to work with — and so a 3am incident is debuggable.
|
|
37
|
+
|
|
38
|
+
## When this fires
|
|
39
|
+
Adding logging / tracing / metrics to new code, reviewing instrumentation, or fixing "we can't tell what happened in prod." Not for installing an SDK (use the Sentry/Langfuse plugins) or post-hoc triage (use the monitor/audit skills).
|
|
40
|
+
|
|
41
|
+
## The one rule that matters most: correlation [LOW freedom — run exactly]
|
|
42
|
+
A prod incident is only debuggable if you can pivot **error ↔ trace ↔ log ↔ user** from any one of them. Make every layer share an id.
|
|
43
|
+
|
|
44
|
+
- Generate/propagate a **request id** (or OTel `trace_id`) at the entry point (HTTP middleware, edge function, job start). Put it in async context (`AsyncLocalStorage` / context var), not a parameter threaded everywhere.
|
|
45
|
+
- **Stamp it on everything:** every log line, Sentry `setTag("request_id", id)` / `setContext`, and the Langfuse trace (`trace.id` or metadata). On an LLM error, attach the Langfuse trace URL to the Sentry event so you jump straight from the error to the prompt/response.
|
|
46
|
+
- Set user/session/tenant scope (`Sentry.setUser`, Langfuse `userId`/`sessionId`) — scrubbed (see redaction).
|
|
47
|
+
|
|
48
|
+
## Structured logging discipline [HIGH freedom]
|
|
49
|
+
- **Structured, not string-soup.** Emit JSON with stable fields (`level`, `msg`, `request_id`, `event`, domain ids). One event per line. Use the platform logger (pino / structlog / slog), not bare `console.log`.
|
|
50
|
+
- **Levels mean things:** `error` = needs a human; `warn` = degraded but handled; `info` = state transitions / business events; `debug` = dev-only, off in prod. Don't log `error` for handled flow.
|
|
51
|
+
- **No `console.log` shipped to prod** — it's unsearchable, unleveled, and a PII leak risk. Remove or convert to a leveled structured log.
|
|
52
|
+
- **Log decisions, not noise:** log the branch taken + key inputs/outputs at boundaries, not every line. A log you'd never grep is cost, not signal.
|
|
53
|
+
|
|
54
|
+
## PII / secret redaction (non-negotiable) [LOW freedom — run exactly]
|
|
55
|
+
- Never log tokens, passwords, API keys, full PANs, auth headers, or raw request bodies. Redact at the logger/transport layer (deny-list keys + pattern scrub) so it can't be bypassed per-call.
|
|
56
|
+
- Configure Sentry `beforeSend` / data-scrubbing and Langfuse masking to strip PII from events/traces. Assume anything you put in a span/breadcrumb may be retained.
|
|
57
|
+
- For LLM traces: decide explicitly whether prompts/completions may contain PII; mask or hash before sending if the jurisdiction requires it.
|
|
58
|
+
|
|
59
|
+
## Tracing / spans (what to wrap) [HIGH freedom]
|
|
60
|
+
- Wrap **boundaries and slow/fallible work**: inbound request, outbound HTTP/DB/queue calls, LLM calls, background jobs. Not every function.
|
|
61
|
+
- Name spans by operation (`http.server`, `db.query`, `llm.generate`), add attributes (route, status, row count, model) — follow **OTel semantic conventions**, including the **GenAI conventions** for LLM spans (model, tokens in/out, cost, latency, temperature).
|
|
62
|
+
- **Sampling:** you don't need 100%. Head-sample normal traffic (e.g. 10–20%), but **always keep errors and slow outliers**. Document the rate; it's a cost/visibility dial.
|
|
63
|
+
|
|
64
|
+
## LLM-specific (Langfuse) [HIGH freedom]
|
|
65
|
+
- Capture per generation: prompt, response, model, input/output tokens, cost, latency, and the eval/score if you run one. Group multi-step agents under one trace with nested spans.
|
|
66
|
+
- Link the Langfuse `trace_id` into the surrounding request id and into Sentry on failure — so an LLM error in Sentry is one click from the full trace.
|
|
67
|
+
- Tag traces with `userId` / `sessionId` / release so `audit-langfuse-llm` can slice quality by cohort.
|
|
68
|
+
|
|
69
|
+
## Alerts & SLOs (signal, not noise) [HIGH freedom]
|
|
70
|
+
- Alert on **symptoms users feel** (error-rate spike, p95 latency, checkout/login failure, LLM eval-score drop), not every error. A pager that cries wolf gets muted.
|
|
71
|
+
- Define a few SLOs (availability, latency, key-flow success) and alert on burn rate, not raw counts.
|
|
72
|
+
- Every alert names an owner and a first action. Route via `sentry-create-alert` / your channel.
|
|
73
|
+
|
|
74
|
+
## Definition of done [LOW freedom — do not skip]
|
|
75
|
+
- [ ] A shared request/trace id is on every log line, the Sentry scope, and the Langfuse trace.
|
|
76
|
+
- [ ] From a prod error you can reach the trace, the logs, and the user in ≤2 clicks.
|
|
77
|
+
- [ ] Logs are structured + correctly leveled; no `console.log` shipped to prod.
|
|
78
|
+
- [ ] PII/secret redaction is enforced at the logger + Sentry `beforeSend` + Langfuse masking.
|
|
79
|
+
- [ ] Spans cover boundaries with OTel-conventional names/attributes; errors are never sampled out.
|
|
80
|
+
- [ ] LLM generations record model/tokens/cost/latency and link back to the request id.
|
|
81
|
+
- [ ] Alerts fire on user-felt symptoms with an owner, not on every error.
|
|
82
|
+
|
|
83
|
+
## Composes with
|
|
84
|
+
- Sentry plugin (`sentry-sdk-setup`, `sentry-setup-ai-monitoring`, `sentry-create-alert`, `sentry-otel-exporter-setup`) — SDK + alert wiring.
|
|
85
|
+
- Langfuse plugin (`langfuse`) + `audit-langfuse-llm` — LLM trace capture + quality audit.
|
|
86
|
+
- `debug-sentry-monitor` / `debug-error` — post-hoc triage of what this instrumentation surfaces.
|
|
87
|
+
- `data-pipeline` — per-run pipeline metrics use these same correlation + logging rules.
|
|
88
|
+
- `workflow-spec-tdd` — make "observable" part of the spec's "done when", not an afterthought.
|