@ketecode/loom 0.0.0-stage → 0.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/LICENSE +21 -0
- package/README.md +516 -2
- package/agents/accessibility-reviewer/AGENT.md +70 -0
- package/agents/accessibility-reviewer/evals/triggers.json +15 -0
- package/agents/agent-evaluator/AGENT.md +74 -0
- package/agents/agent-evaluator/evals/triggers.json +15 -0
- package/agents/architect/AGENT.md +82 -0
- package/agents/architect/evals/triggers.json +17 -0
- package/agents/billing-reviewer/AGENT.md +68 -0
- package/agents/billing-reviewer/evals/triggers.json +16 -0
- package/agents/code-reviewer/AGENT.md +51 -0
- package/agents/code-reviewer/evals/triggers.json +14 -0
- package/agents/code-simplifier/AGENT.md +74 -0
- package/agents/code-simplifier/evals/triggers.json +15 -0
- package/agents/cpp-build-resolver/AGENT.md +73 -0
- package/agents/cpp-build-resolver/evals/triggers.json +16 -0
- package/agents/cpp-reviewer/AGENT.md +59 -0
- package/agents/cpp-reviewer/evals/triggers.json +16 -0
- package/agents/csharp-build-resolver/AGENT.md +84 -0
- package/agents/csharp-build-resolver/evals/triggers.json +17 -0
- package/agents/csharp-reviewer/AGENT.md +88 -0
- package/agents/csharp-reviewer/evals/triggers.json +17 -0
- package/agents/dart-build-resolver/AGENT.md +80 -0
- package/agents/dart-build-resolver/evals/triggers.json +17 -0
- package/agents/dart-reviewer/AGENT.md +66 -0
- package/agents/dart-reviewer/evals/triggers.json +17 -0
- package/agents/database-reviewer/AGENT.md +72 -0
- package/agents/database-reviewer/evals/triggers.json +16 -0
- package/agents/django-reviewer/AGENT.md +61 -0
- package/agents/django-reviewer/evals/triggers.json +15 -0
- package/agents/doc-updater/AGENT.md +92 -0
- package/agents/doc-updater/evals/triggers.json +14 -0
- package/agents/e2e-runner/AGENT.md +88 -0
- package/agents/e2e-runner/evals/triggers.json +16 -0
- package/agents/fastapi-reviewer/AGENT.md +63 -0
- package/agents/fastapi-reviewer/evals/triggers.json +15 -0
- package/agents/flutter-reviewer/AGENT.md +70 -0
- package/agents/flutter-reviewer/evals/triggers.json +15 -0
- package/agents/fsharp-build-resolver/AGENT.md +81 -0
- package/agents/fsharp-build-resolver/evals/triggers.json +15 -0
- package/agents/fsharp-reviewer/AGENT.md +77 -0
- package/agents/fsharp-reviewer/evals/triggers.json +15 -0
- package/agents/go-build-resolver/AGENT.md +85 -0
- package/agents/go-build-resolver/evals/triggers.json +16 -0
- package/agents/go-reviewer/AGENT.md +66 -0
- package/agents/go-reviewer/evals/triggers.json +16 -0
- package/agents/healthcare-reviewer/AGENT.md +65 -0
- package/agents/healthcare-reviewer/evals/triggers.json +16 -0
- package/agents/i18n-reviewer/AGENT.md +64 -0
- package/agents/i18n-reviewer/evals/triggers.json +16 -0
- package/agents/infra-reviewer/AGENT.md +93 -0
- package/agents/infra-reviewer/evals/triggers.json +15 -0
- package/agents/java-build-resolver/AGENT.md +82 -0
- package/agents/java-build-resolver/evals/triggers.json +16 -0
- package/agents/java-reviewer/AGENT.md +64 -0
- package/agents/java-reviewer/evals/triggers.json +16 -0
- package/agents/kotlin-build-resolver/AGENT.md +89 -0
- package/agents/kotlin-build-resolver/evals/triggers.json +16 -0
- package/agents/kotlin-reviewer/AGENT.md +75 -0
- package/agents/kotlin-reviewer/evals/triggers.json +16 -0
- package/agents/mle-reviewer/AGENT.md +68 -0
- package/agents/mle-reviewer/evals/triggers.json +16 -0
- package/agents/network-config-reviewer/AGENT.md +68 -0
- package/agents/network-config-reviewer/evals/triggers.json +17 -0
- package/agents/payments-reviewer/AGENT.md +64 -0
- package/agents/payments-reviewer/evals/triggers.json +16 -0
- package/agents/performance-optimizer/AGENT.md +86 -0
- package/agents/performance-optimizer/evals/triggers.json +16 -0
- package/agents/perl-build-resolver/AGENT.md +84 -0
- package/agents/perl-build-resolver/evals/triggers.json +15 -0
- package/agents/perl-reviewer/AGENT.md +77 -0
- package/agents/perl-reviewer/evals/triggers.json +15 -0
- package/agents/php-build-resolver/AGENT.md +88 -0
- package/agents/php-build-resolver/evals/triggers.json +16 -0
- package/agents/php-reviewer/AGENT.md +61 -0
- package/agents/php-reviewer/evals/triggers.json +15 -0
- package/agents/planner/AGENT.md +75 -0
- package/agents/planner/evals/triggers.json +17 -0
- package/agents/pr-test-analyzer/AGENT.md +82 -0
- package/agents/pr-test-analyzer/evals/triggers.json +16 -0
- package/agents/python-build-resolver/AGENT.md +87 -0
- package/agents/python-build-resolver/evals/triggers.json +16 -0
- package/agents/python-reviewer/AGENT.md +63 -0
- package/agents/python-reviewer/evals/triggers.json +15 -0
- package/agents/rag-reviewer/AGENT.md +71 -0
- package/agents/rag-reviewer/evals/triggers.json +16 -0
- package/agents/react-reviewer/AGENT.md +70 -0
- package/agents/react-reviewer/evals/triggers.json +16 -0
- package/agents/refactor-cleaner/AGENT.md +82 -0
- package/agents/refactor-cleaner/evals/triggers.json +16 -0
- package/agents/ruby-build-resolver/AGENT.md +93 -0
- package/agents/ruby-build-resolver/evals/triggers.json +16 -0
- package/agents/ruby-reviewer/AGENT.md +62 -0
- package/agents/ruby-reviewer/evals/triggers.json +16 -0
- package/agents/rust-build-resolver/AGENT.md +98 -0
- package/agents/rust-build-resolver/evals/triggers.json +16 -0
- package/agents/rust-reviewer/AGENT.md +78 -0
- package/agents/rust-reviewer/evals/triggers.json +15 -0
- package/agents/security-reviewer/AGENT.md +84 -0
- package/agents/security-reviewer/evals/triggers.json +16 -0
- package/agents/silent-failure-hunter/AGENT.md +66 -0
- package/agents/silent-failure-hunter/evals/triggers.json +16 -0
- package/agents/solidity-reviewer/AGENT.md +70 -0
- package/agents/solidity-reviewer/evals/triggers.json +16 -0
- package/agents/swift-build-resolver/AGENT.md +85 -0
- package/agents/swift-build-resolver/evals/triggers.json +15 -0
- package/agents/swift-reviewer/AGENT.md +75 -0
- package/agents/swift-reviewer/evals/triggers.json +15 -0
- package/agents/typescript-build-resolver/AGENT.md +76 -0
- package/agents/typescript-build-resolver/evals/triggers.json +15 -0
- package/agents/typescript-reviewer/AGENT.md +76 -0
- package/agents/typescript-reviewer/evals/triggers.json +15 -0
- package/agents/vue-reviewer/AGENT.md +75 -0
- package/agents/vue-reviewer/evals/triggers.json +15 -0
- package/bin/kete-loom.js +683 -0
- package/commands/aside.md +19 -0
- package/commands/build-fix.md +26 -0
- package/commands/campaign.md +19 -0
- package/commands/changelog.md +36 -0
- package/commands/checkpoint.md +26 -0
- package/commands/codemap.md +25 -0
- package/commands/commit.md +26 -0
- package/commands/deps-audit.md +32 -0
- package/commands/epic-decompose.md +21 -0
- package/commands/explain.md +37 -0
- package/commands/feature-dev.md +22 -0
- package/commands/hookify.md +23 -0
- package/commands/i18n-check.md +39 -0
- package/commands/issue-sync.md +22 -0
- package/commands/jira.md +19 -0
- package/commands/learn.md +23 -0
- package/commands/loom.md +21 -0
- package/commands/loop.md +20 -0
- package/commands/model-route.md +27 -0
- package/commands/onboard.md +35 -0
- package/commands/orchestrate.md +21 -0
- package/commands/plan-feature.md +36 -0
- package/commands/postmortem.md +42 -0
- package/commands/pr-describe.md +39 -0
- package/commands/pr.md +22 -0
- package/commands/prd.md +41 -0
- package/commands/project-init.md +21 -0
- package/commands/refactor-clean.md +24 -0
- package/commands/resume-session.md +22 -0
- package/commands/review.md +35 -0
- package/commands/save-session.md +37 -0
- package/commands/security-scan.md +32 -0
- package/commands/sessions.md +21 -0
- package/commands/skill-create.md +21 -0
- package/commands/tdd.md +36 -0
- package/commands/test-coverage.md +24 -0
- package/commands/threat-model.md +36 -0
- package/commands/update-docs.md +25 -0
- package/commands/verify.md +21 -0
- package/hooks/block-dangerous-commands/HOOK.md +30 -0
- package/hooks/block-dangerous-commands/cases.json +50 -0
- package/hooks/block-dangerous-commands/hook.js +75 -0
- package/hooks/block-no-verify/HOOK.md +25 -0
- package/hooks/block-no-verify/cases.json +30 -0
- package/hooks/block-no-verify/hook.js +43 -0
- package/hooks/format-on-edit/HOOK.md +24 -0
- package/hooks/format-on-edit/hook.js +89 -0
- package/hooks/guard-secrets/HOOK.md +19 -0
- package/hooks/guard-secrets/cases.json +110 -0
- package/hooks/guard-secrets/hook.js +44 -0
- package/hooks/load-session-context/HOOK.md +20 -0
- package/hooks/load-session-context/hook.js +56 -0
- package/hooks/protect-files/HOOK.md +24 -0
- package/hooks/protect-files/cases.json +27 -0
- package/hooks/protect-files/hook.js +39 -0
- package/hooks/run.js +132 -0
- package/mcp/atlassian.json +11 -0
- package/mcp/chrome-devtools.json +18 -0
- package/mcp/cloudflare.json +11 -0
- package/mcp/context7.json +11 -0
- package/mcp/fetch.json +17 -0
- package/mcp/figma.json +11 -0
- package/mcp/git.json +17 -0
- package/mcp/github.json +11 -0
- package/mcp/linear.json +11 -0
- package/mcp/memory.json +18 -0
- package/mcp/notion.json +11 -0
- package/mcp/playwright.json +18 -0
- package/mcp/sentry.json +11 -0
- package/mcp/stripe.json +11 -0
- package/mcp/supabase.json +11 -0
- package/mcp/time.json +17 -0
- package/package.json +59 -4
- package/profiles.json +165 -0
- package/rules/common.md +21 -0
- package/rules/cpp.md +29 -0
- package/rules/csharp.md +25 -0
- package/rules/dart.md +29 -0
- package/rules/fsharp.md +28 -0
- package/rules/git.md +26 -0
- package/rules/go.md +29 -0
- package/rules/java.md +29 -0
- package/rules/kotlin.md +27 -0
- package/rules/perl.md +26 -0
- package/rules/php.md +28 -0
- package/rules/python.md +30 -0
- package/rules/ruby.md +27 -0
- package/rules/rust.md +26 -0
- package/rules/security.md +29 -0
- package/rules/swift.md +28 -0
- package/rules/testing.md +25 -0
- package/rules/typescript.md +29 -0
- package/schemas/skill-frontmatter.schema.json +52 -0
- package/scripts/lib/audit.js +96 -0
- package/scripts/lib/frontmatter.js +65 -0
- package/scripts/lib/hooks-install.js +292 -0
- package/scripts/lib/i18n.js +51 -0
- package/scripts/lib/inventory.js +85 -0
- package/scripts/lib/lint.js +158 -0
- package/scripts/lib/mcp-install.js +284 -0
- package/scripts/lib/profiles.js +128 -0
- package/scripts/lib/render.js +86 -0
- package/scripts/lib/rules-install.js +118 -0
- package/scripts/lib/skills.js +86 -0
- package/scripts/lib/targets.js +113 -0
- package/skills/accounting-api-integration/SKILL.md +81 -0
- package/skills/accounting-api-integration/evals/triggers.json +17 -0
- package/skills/accounting-api-integration/references/quickbooks.md +48 -0
- package/skills/accounting-api-integration/references/xero.md +45 -0
- package/skills/agent-harness-design/SKILL.md +125 -0
- package/skills/agent-harness-design/evals/triggers.json +21 -0
- package/skills/ai-media-generation/SKILL.md +89 -0
- package/skills/ai-media-generation/evals/triggers.json +16 -0
- package/skills/ai-media-generation/references/job-pipeline.md +76 -0
- package/skills/angular-patterns/SKILL.md +122 -0
- package/skills/angular-patterns/evals/triggers.json +16 -0
- package/skills/api-design/SKILL.md +96 -0
- package/skills/api-design/evals/triggers.json +18 -0
- package/skills/api-design/references/conventions.md +133 -0
- package/skills/architecture-decision-records/SKILL.md +98 -0
- package/skills/architecture-decision-records/evals/triggers.json +17 -0
- package/skills/article-writing/SKILL.md +108 -0
- package/skills/article-writing/evals/triggers.json +16 -0
- package/skills/aspnet-core-patterns/SKILL.md +149 -0
- package/skills/aspnet-core-patterns/evals/triggers.json +16 -0
- package/skills/auth-patterns/SKILL.md +104 -0
- package/skills/auth-patterns/evals/triggers.json +17 -0
- package/skills/auth-patterns/references/oauth-oidc.md +64 -0
- package/skills/autonomous-loops/SKILL.md +99 -0
- package/skills/autonomous-loops/evals/triggers.json +14 -0
- package/skills/aws-patterns/SKILL.md +91 -0
- package/skills/aws-patterns/evals/triggers.json +16 -0
- package/skills/azure-patterns/SKILL.md +86 -0
- package/skills/azure-patterns/evals/triggers.json +16 -0
- package/skills/benchmark-methodology/SKILL.md +88 -0
- package/skills/benchmark-methodology/evals/triggers.json +16 -0
- package/skills/benchmark-methodology/references/language-harnesses.md +130 -0
- package/skills/bgp-diagnostics/SKILL.md +84 -0
- package/skills/bgp-diagnostics/evals/triggers.json +18 -0
- package/skills/bgp-diagnostics/references/bgp-reference.md +81 -0
- package/skills/bioinformatics-workflows/SKILL.md +108 -0
- package/skills/bioinformatics-workflows/evals/triggers.json +16 -0
- package/skills/bioinformatics-workflows/references/commands.md +71 -0
- package/skills/bioinformatics-workflows/references/formats.md +24 -0
- package/skills/bioinformatics-workflows/references/workflow-managers.md +107 -0
- package/skills/brand-voice/SKILL.md +112 -0
- package/skills/brand-voice/evals/triggers.json +16 -0
- package/skills/browser-qa/SKILL.md +99 -0
- package/skills/browser-qa/evals/triggers.json +16 -0
- package/skills/bun-runtime/SKILL.md +93 -0
- package/skills/bun-runtime/evals/triggers.json +16 -0
- package/skills/cisco-ios-config/SKILL.md +101 -0
- package/skills/cisco-ios-config/evals/triggers.json +18 -0
- package/skills/cisco-ios-config/references/verification.md +63 -0
- package/skills/clickhouse-patterns/SKILL.md +101 -0
- package/skills/clickhouse-patterns/evals/triggers.json +18 -0
- package/skills/clickhouse-patterns/references/engines-and-views.md +138 -0
- package/skills/clinical-decision-support/SKILL.md +90 -0
- package/skills/clinical-decision-support/evals/triggers.json +16 -0
- package/skills/clinical-decision-support/references/cds-hooks.md +76 -0
- package/skills/clinical-decision-support/references/regulatory-boundaries.md +37 -0
- package/skills/code-tour/SKILL.md +97 -0
- package/skills/code-tour/evals/triggers.json +14 -0
- package/skills/codebase-onboarding/SKILL.md +112 -0
- package/skills/codebase-onboarding/evals/triggers.json +14 -0
- package/skills/cold-outreach-sequences/SKILL.md +90 -0
- package/skills/cold-outreach-sequences/evals/triggers.json +16 -0
- package/skills/content-repurposing/SKILL.md +82 -0
- package/skills/content-repurposing/evals/triggers.json +16 -0
- package/skills/context-budget/SKILL.md +84 -0
- package/skills/context-budget/evals/triggers.json +14 -0
- package/skills/conventional-commits/SKILL.md +144 -0
- package/skills/conventional-commits/evals/triggers.json +16 -0
- package/skills/cpp-patterns/SKILL.md +129 -0
- package/skills/cpp-patterns/evals/triggers.json +16 -0
- package/skills/cpp-patterns/references/cmake-and-tooling.md +88 -0
- package/skills/cpp-patterns/references/undefined-behaviour.md +75 -0
- package/skills/cpp-testing/SKILL.md +131 -0
- package/skills/cpp-testing/evals/triggers.json +16 -0
- package/skills/csharp-patterns/SKILL.md +110 -0
- package/skills/csharp-patterns/evals/triggers.json +17 -0
- package/skills/csharp-patterns/references/analyzers.md +59 -0
- package/skills/csharp-testing/SKILL.md +85 -0
- package/skills/csharp-testing/evals/triggers.json +17 -0
- package/skills/csharp-testing/references/integration-tests.md +77 -0
- package/skills/css-architecture/SKILL.md +143 -0
- package/skills/css-architecture/evals/triggers.json +16 -0
- package/skills/customs-trade-compliance/SKILL.md +95 -0
- package/skills/customs-trade-compliance/evals/triggers.json +16 -0
- package/skills/customs-trade-compliance/references/incoterms-2020.md +42 -0
- package/skills/dart-patterns/SKILL.md +157 -0
- package/skills/dart-patterns/evals/triggers.json +18 -0
- package/skills/dart-testing/SKILL.md +164 -0
- package/skills/dart-testing/evals/triggers.json +18 -0
- package/skills/data-analysis-notebooks/SKILL.md +113 -0
- package/skills/data-analysis-notebooks/evals/triggers.json +16 -0
- package/skills/data-analysis-notebooks/references/dataframe-pitfalls.md +49 -0
- package/skills/data-analysis-notebooks/references/statistics-pitfalls.md +24 -0
- package/skills/data-pipelines/SKILL.md +90 -0
- package/skills/data-pipelines/evals/triggers.json +16 -0
- package/skills/data-pipelines/references/orchestrators.md +64 -0
- package/skills/database-migrations/SKILL.md +102 -0
- package/skills/database-migrations/evals/triggers.json +16 -0
- package/skills/database-migrations/references/recipes.md +98 -0
- package/skills/database-migrations/references/tools.md +21 -0
- package/skills/dbt-patterns/SKILL.md +96 -0
- package/skills/dbt-patterns/evals/triggers.json +16 -0
- package/skills/dbt-patterns/references/yaml-examples.md +114 -0
- package/skills/deep-research/SKILL.md +107 -0
- package/skills/deep-research/evals/triggers.json +14 -0
- package/skills/dependency-audit/SKILL.md +103 -0
- package/skills/dependency-audit/evals/triggers.json +16 -0
- package/skills/dependency-audit/references/tools.md +124 -0
- package/skills/deployment-strategies/SKILL.md +108 -0
- package/skills/deployment-strategies/evals/triggers.json +16 -0
- package/skills/django-patterns/SKILL.md +123 -0
- package/skills/django-patterns/evals/triggers.json +16 -0
- package/skills/docker-patterns/SKILL.md +132 -0
- package/skills/docker-patterns/evals/triggers.json +16 -0
- package/skills/docker-patterns/references/dockerfiles.md +105 -0
- package/skills/e2e-testing-playwright/SKILL.md +94 -0
- package/skills/e2e-testing-playwright/evals/triggers.json +16 -0
- package/skills/e2e-testing-playwright/references/config-and-ci.md +129 -0
- package/skills/ef-core-patterns/SKILL.md +117 -0
- package/skills/ef-core-patterns/evals/triggers.json +16 -0
- package/skills/email-deliverability/SKILL.md +99 -0
- package/skills/email-deliverability/evals/triggers.json +17 -0
- package/skills/email-deliverability/references/dns-records.md +85 -0
- package/skills/error-handling-patterns/SKILL.md +112 -0
- package/skills/error-handling-patterns/evals/triggers.json +18 -0
- package/skills/error-handling-patterns/references/language-idioms.md +49 -0
- package/skills/estimation-and-scoping/SKILL.md +97 -0
- package/skills/estimation-and-scoping/evals/triggers.json +14 -0
- package/skills/evm-dapp-integration/SKILL.md +73 -0
- package/skills/evm-dapp-integration/evals/triggers.json +16 -0
- package/skills/fastapi-patterns/SKILL.md +127 -0
- package/skills/fastapi-patterns/evals/triggers.json +16 -0
- package/skills/ffmpeg-media-processing/SKILL.md +94 -0
- package/skills/ffmpeg-media-processing/evals/triggers.json +16 -0
- package/skills/ffmpeg-media-processing/references/recipes.md +112 -0
- package/skills/fhir-integration/SKILL.md +81 -0
- package/skills/fhir-integration/evals/triggers.json +16 -0
- package/skills/fhir-integration/references/search-and-bundles.md +73 -0
- package/skills/fhir-integration/references/smart-on-fhir.md +50 -0
- package/skills/flask-patterns/SKILL.md +132 -0
- package/skills/flask-patterns/evals/triggers.json +16 -0
- package/skills/flutter-patterns/SKILL.md +99 -0
- package/skills/flutter-patterns/evals/triggers.json +16 -0
- package/skills/flutterwave-integration/SKILL.md +75 -0
- package/skills/flutterwave-integration/evals/triggers.json +16 -0
- package/skills/flutterwave-integration/references/api.md +73 -0
- package/skills/flutterwave-integration/references/webhooks.md +49 -0
- package/skills/fsharp-patterns/SKILL.md +133 -0
- package/skills/fsharp-patterns/evals/triggers.json +16 -0
- package/skills/fsharp-testing/SKILL.md +136 -0
- package/skills/fsharp-testing/evals/triggers.json +16 -0
- package/skills/gcp-patterns/SKILL.md +86 -0
- package/skills/gcp-patterns/evals/triggers.json +16 -0
- package/skills/git-workflow/SKILL.md +114 -0
- package/skills/git-workflow/evals/triggers.json +16 -0
- package/skills/github-actions-ci/SKILL.md +117 -0
- package/skills/github-actions-ci/evals/triggers.json +16 -0
- package/skills/github-api-automation/SKILL.md +101 -0
- package/skills/github-api-automation/evals/triggers.json +17 -0
- package/skills/go-patterns/SKILL.md +118 -0
- package/skills/go-patterns/evals/triggers.json +17 -0
- package/skills/go-patterns/references/concurrency.md +162 -0
- package/skills/go-testing/SKILL.md +154 -0
- package/skills/go-testing/evals/triggers.json +17 -0
- package/skills/hexagonal-architecture/SKILL.md +89 -0
- package/skills/hexagonal-architecture/evals/triggers.json +17 -0
- package/skills/hipaa-compliance/SKILL.md +91 -0
- package/skills/hipaa-compliance/evals/triggers.json +18 -0
- package/skills/hipaa-compliance/references/safeguards.md +68 -0
- package/skills/hl7v2-integration/SKILL.md +69 -0
- package/skills/hl7v2-integration/evals/triggers.json +16 -0
- package/skills/hl7v2-integration/references/messages-and-ack.md +78 -0
- package/skills/homelab-network-setup/SKILL.md +125 -0
- package/skills/homelab-network-setup/evals/triggers.json +18 -0
- package/skills/homelab-network-setup/references/firewall-and-dns.md +45 -0
- package/skills/homelab-network-setup/references/wireguard.md +72 -0
- package/skills/hubtel-integration/SKILL.md +77 -0
- package/skills/hubtel-integration/evals/triggers.json +16 -0
- package/skills/hubtel-integration/references/api.md +92 -0
- package/skills/i18n-localization/SKILL.md +114 -0
- package/skills/i18n-localization/evals/triggers.json +16 -0
- package/skills/i18n-localization/references/libraries.md +52 -0
- package/skills/incident-postmortem/SKILL.md +118 -0
- package/skills/incident-postmortem/evals/triggers.json +14 -0
- package/skills/inventory-demand-planning/SKILL.md +89 -0
- package/skills/inventory-demand-planning/evals/triggers.json +16 -0
- package/skills/inventory-demand-planning/references/formulas.md +62 -0
- package/skills/investor-materials/SKILL.md +127 -0
- package/skills/investor-materials/evals/triggers.json +16 -0
- package/skills/investor-materials/references/templates.md +74 -0
- package/skills/invoicing-and-tax/SKILL.md +84 -0
- package/skills/invoicing-and-tax/evals/triggers.json +17 -0
- package/skills/invoicing-and-tax/references/e-invoicing.md +24 -0
- package/skills/invoicing-and-tax/references/invoice-fields.md +38 -0
- package/skills/invoicing-and-tax/references/rounding.md +26 -0
- package/skills/java-patterns/SKILL.md +141 -0
- package/skills/java-patterns/evals/triggers.json +17 -0
- package/skills/java-testing/SKILL.md +142 -0
- package/skills/java-testing/evals/triggers.json +16 -0
- package/skills/jetpack-compose-patterns/SKILL.md +88 -0
- package/skills/jetpack-compose-patterns/evals/triggers.json +16 -0
- package/skills/jira-integration/SKILL.md +92 -0
- package/skills/jira-integration/evals/triggers.json +17 -0
- package/skills/jpa-hibernate/SKILL.md +92 -0
- package/skills/jpa-hibernate/evals/triggers.json +18 -0
- package/skills/jpa-hibernate/references/mapping.md +99 -0
- package/skills/kotlin-multiplatform/SKILL.md +97 -0
- package/skills/kotlin-multiplatform/evals/triggers.json +16 -0
- package/skills/kotlin-patterns/SKILL.md +128 -0
- package/skills/kotlin-patterns/evals/triggers.json +16 -0
- package/skills/kotlin-testing/SKILL.md +117 -0
- package/skills/kotlin-testing/evals/triggers.json +16 -0
- package/skills/ktor-patterns/SKILL.md +135 -0
- package/skills/ktor-patterns/evals/triggers.json +18 -0
- package/skills/kubernetes-patterns/SKILL.md +106 -0
- package/skills/kubernetes-patterns/evals/triggers.json +16 -0
- package/skills/kubernetes-patterns/references/manifests.md +115 -0
- package/skills/laravel-patterns/SKILL.md +136 -0
- package/skills/laravel-patterns/evals/triggers.json +16 -0
- package/skills/linear-integration/SKILL.md +98 -0
- package/skills/linear-integration/evals/triggers.json +17 -0
- package/skills/literature-review/SKILL.md +109 -0
- package/skills/literature-review/evals/triggers.json +16 -0
- package/skills/literature-review/references/appraisal.md +41 -0
- package/skills/literature-review/references/search-sources.md +39 -0
- package/skills/llm-app-patterns/SKILL.md +97 -0
- package/skills/llm-app-patterns/evals/triggers.json +17 -0
- package/skills/llm-evals/SKILL.md +98 -0
- package/skills/llm-evals/evals/triggers.json +16 -0
- package/skills/llm-evals/references/graders.md +66 -0
- package/skills/logistics-exception-management/SKILL.md +90 -0
- package/skills/logistics-exception-management/evals/triggers.json +16 -0
- package/skills/manim-animations/SKILL.md +106 -0
- package/skills/manim-animations/evals/triggers.json +16 -0
- package/skills/market-research/SKILL.md +117 -0
- package/skills/market-research/evals/triggers.json +16 -0
- package/skills/marketing-campaign/SKILL.md +111 -0
- package/skills/marketing-campaign/evals/triggers.json +16 -0
- package/skills/mcp-server-patterns/SKILL.md +127 -0
- package/skills/mcp-server-patterns/evals/triggers.json +18 -0
- package/skills/mcp-server-patterns/references/protocol-notes.md +68 -0
- package/skills/metrics-dashboards/SKILL.md +113 -0
- package/skills/metrics-dashboards/evals/triggers.json +16 -0
- package/skills/ml-experiment-workflow/SKILL.md +125 -0
- package/skills/ml-experiment-workflow/evals/triggers.json +16 -0
- package/skills/mongodb-patterns/SKILL.md +115 -0
- package/skills/mongodb-patterns/evals/triggers.json +18 -0
- package/skills/mongodb-patterns/references/indexes-and-aggregation.md +94 -0
- package/skills/mpesa-daraja-integration/SKILL.md +70 -0
- package/skills/mpesa-daraja-integration/evals/triggers.json +16 -0
- package/skills/mpesa-daraja-integration/references/api.md +103 -0
- package/skills/mpesa-daraja-integration/references/callbacks.md +74 -0
- package/skills/mtn-momo-integration/SKILL.md +66 -0
- package/skills/mtn-momo-integration/evals/triggers.json +16 -0
- package/skills/mtn-momo-integration/references/api.md +153 -0
- package/skills/mtn-momo-integration/references/callbacks.md +92 -0
- package/skills/mtn-momo-integration/references/sandbox-and-go-live.md +51 -0
- package/skills/mtn-momo-integration/scripts/sandbox-setup.js +79 -0
- package/skills/mysql-patterns/SKILL.md +96 -0
- package/skills/mysql-patterns/evals/triggers.json +16 -0
- package/skills/mysql-patterns/references/explain.md +34 -0
- package/skills/mysql-patterns/references/online-ddl.md +41 -0
- package/skills/nestjs-patterns/SKILL.md +114 -0
- package/skills/nestjs-patterns/evals/triggers.json +16 -0
- package/skills/nestjs-patterns/references/testing.md +68 -0
- package/skills/network-automation/SKILL.md +107 -0
- package/skills/network-automation/evals/triggers.json +18 -0
- package/skills/network-automation/references/tool-snippets.md +153 -0
- package/skills/network-troubleshooting/SKILL.md +152 -0
- package/skills/network-troubleshooting/evals/triggers.json +18 -0
- package/skills/network-troubleshooting/references/commands.md +33 -0
- package/skills/nextjs-patterns/SKILL.md +150 -0
- package/skills/nextjs-patterns/evals/triggers.json +18 -0
- package/skills/nextjs-patterns/references/caching.md +87 -0
- package/skills/node-backend-patterns/SKILL.md +103 -0
- package/skills/node-backend-patterns/evals/triggers.json +16 -0
- package/skills/node-backend-patterns/references/templates.md +122 -0
- package/skills/nuxt-patterns/SKILL.md +103 -0
- package/skills/nuxt-patterns/evals/triggers.json +16 -0
- package/skills/parallel-agent-orchestration/SKILL.md +106 -0
- package/skills/parallel-agent-orchestration/evals/triggers.json +14 -0
- package/skills/paystack-integration/SKILL.md +59 -0
- package/skills/paystack-integration/evals/triggers.json +14 -0
- package/skills/paystack-integration/references/api.md +73 -0
- package/skills/paystack-integration/references/mobile-money.md +50 -0
- package/skills/paystack-integration/references/webhooks.md +80 -0
- package/skills/pci-dss-scope/SKILL.md +103 -0
- package/skills/pci-dss-scope/evals/triggers.json +18 -0
- package/skills/pci-dss-scope/references/saq-and-data.md +36 -0
- package/skills/perl-patterns/SKILL.md +135 -0
- package/skills/perl-patterns/evals/triggers.json +18 -0
- package/skills/perl-testing/SKILL.md +126 -0
- package/skills/perl-testing/evals/triggers.json +17 -0
- package/skills/php-patterns/SKILL.md +116 -0
- package/skills/php-patterns/evals/triggers.json +16 -0
- package/skills/php-testing/SKILL.md +123 -0
- package/skills/php-testing/evals/triggers.json +16 -0
- package/skills/postgres-patterns/SKILL.md +103 -0
- package/skills/postgres-patterns/evals/triggers.json +17 -0
- package/skills/postgres-patterns/references/explain.md +59 -0
- package/skills/postgres-patterns/references/locks.md +53 -0
- package/skills/prd-writing/SKILL.md +124 -0
- package/skills/prd-writing/evals/triggers.json +15 -0
- package/skills/prisma-patterns/SKILL.md +83 -0
- package/skills/prisma-patterns/evals/triggers.json +18 -0
- package/skills/prisma-patterns/references/prisma-8.md +46 -0
- package/skills/prisma-patterns/references/workflow.md +50 -0
- package/skills/privacy-compliance/SKILL.md +121 -0
- package/skills/privacy-compliance/evals/triggers.json +18 -0
- package/skills/privacy-compliance/references/jurisdictions.md +51 -0
- package/skills/production-scheduling/SKILL.md +98 -0
- package/skills/production-scheduling/evals/triggers.json +16 -0
- package/skills/prompt-engineering/SKILL.md +92 -0
- package/skills/prompt-engineering/evals/triggers.json +16 -0
- package/skills/python-patterns/SKILL.md +107 -0
- package/skills/python-patterns/evals/triggers.json +16 -0
- package/skills/python-patterns/references/tooling.md +101 -0
- package/skills/python-testing/SKILL.md +126 -0
- package/skills/python-testing/evals/triggers.json +16 -0
- package/skills/python-testing/references/mocking.md +71 -0
- package/skills/pytorch-patterns/SKILL.md +139 -0
- package/skills/pytorch-patterns/evals/triggers.json +16 -0
- package/skills/pytorch-patterns/references/debugging.md +39 -0
- package/skills/quarkus-patterns/SKILL.md +93 -0
- package/skills/quarkus-patterns/evals/triggers.json +18 -0
- package/skills/rag-pipeline-patterns/SKILL.md +117 -0
- package/skills/rag-pipeline-patterns/evals/triggers.json +18 -0
- package/skills/rag-pipeline-patterns/references/evaluation.md +37 -0
- package/skills/rag-pipeline-patterns/references/retrieval-recipes.md +78 -0
- package/skills/rails-patterns/SKILL.md +132 -0
- package/skills/rails-patterns/evals/triggers.json +16 -0
- package/skills/react-native-patterns/SKILL.md +101 -0
- package/skills/react-native-patterns/evals/triggers.json +16 -0
- package/skills/react-patterns/SKILL.md +140 -0
- package/skills/react-patterns/evals/triggers.json +18 -0
- package/skills/react-performance/SKILL.md +107 -0
- package/skills/react-performance/evals/triggers.json +18 -0
- package/skills/redis-patterns/SKILL.md +109 -0
- package/skills/redis-patterns/evals/triggers.json +18 -0
- package/skills/redis-patterns/references/operations.md +61 -0
- package/skills/refactoring-safely/SKILL.md +107 -0
- package/skills/refactoring-safely/evals/triggers.json +17 -0
- package/skills/release-management/SKILL.md +141 -0
- package/skills/release-management/evals/triggers.json +16 -0
- package/skills/remotion-video/SKILL.md +91 -0
- package/skills/remotion-video/evals/triggers.json +16 -0
- package/skills/remotion-video/references/lambda.md +66 -0
- package/skills/returns-reverse-logistics/SKILL.md +97 -0
- package/skills/returns-reverse-logistics/evals/triggers.json +16 -0
- package/skills/ruby-patterns/SKILL.md +127 -0
- package/skills/ruby-patterns/evals/triggers.json +18 -0
- package/skills/ruby-testing/SKILL.md +113 -0
- package/skills/ruby-testing/evals/triggers.json +18 -0
- package/skills/runbook-writing/SKILL.md +101 -0
- package/skills/runbook-writing/evals/triggers.json +14 -0
- package/skills/rust-patterns/SKILL.md +118 -0
- package/skills/rust-patterns/evals/triggers.json +16 -0
- package/skills/rust-patterns/references/cargo-and-clippy.md +105 -0
- package/skills/rust-patterns/references/errors-and-traits.md +97 -0
- package/skills/rust-testing/SKILL.md +148 -0
- package/skills/rust-testing/evals/triggers.json +16 -0
- package/skills/rust-testing/references/fakes-proptest-async.md +113 -0
- package/skills/search-first/SKILL.md +73 -0
- package/skills/search-first/evals/triggers.json +14 -0
- package/skills/security-review/SKILL.md +58 -0
- package/skills/security-review/evals/triggers.json +14 -0
- package/skills/security-review/references/checklist.md +54 -0
- package/skills/security-review/scripts/scan-secrets.js +79 -0
- package/skills/seo-audit/SKILL.md +111 -0
- package/skills/seo-audit/evals/triggers.json +16 -0
- package/skills/seo-audit/references/checks.md +65 -0
- package/skills/session-handoff/SKILL.md +101 -0
- package/skills/session-handoff/evals/triggers.json +14 -0
- package/skills/skill-authoring/SKILL.md +87 -0
- package/skills/skill-authoring/evals/triggers.json +14 -0
- package/skills/skill-authoring/references/frontmatter.md +40 -0
- package/skills/slack-app-integration/SKILL.md +108 -0
- package/skills/slack-app-integration/evals/triggers.json +17 -0
- package/skills/smart-contract-security/SKILL.md +110 -0
- package/skills/smart-contract-security/evals/triggers.json +16 -0
- package/skills/smart-contract-security/references/vulnerability-checklist.md +79 -0
- package/skills/social-media-publishing/SKILL.md +84 -0
- package/skills/social-media-publishing/evals/triggers.json +17 -0
- package/skills/social-media-publishing/references/platform-apis.md +116 -0
- package/skills/solidity-patterns/SKILL.md +95 -0
- package/skills/solidity-patterns/evals/triggers.json +16 -0
- package/skills/spring-boot-patterns/SKILL.md +128 -0
- package/skills/spring-boot-patterns/evals/triggers.json +18 -0
- package/skills/spring-boot-patterns/references/testing.md +72 -0
- package/skills/stripe-integration/SKILL.md +69 -0
- package/skills/stripe-integration/evals/triggers.json +16 -0
- package/skills/stripe-integration/references/api.md +71 -0
- package/skills/stripe-integration/references/billing.md +58 -0
- package/skills/stripe-integration/references/webhooks.md +76 -0
- package/skills/subscription-billing-ops/SKILL.md +118 -0
- package/skills/subscription-billing-ops/evals/triggers.json +17 -0
- package/skills/subscription-billing-ops/references/proration.md +47 -0
- package/skills/subscription-billing-ops/references/revenue-metrics.md +38 -0
- package/skills/svelte-patterns/SKILL.md +122 -0
- package/skills/svelte-patterns/evals/triggers.json +16 -0
- package/skills/swift-patterns/SKILL.md +113 -0
- package/skills/swift-patterns/evals/triggers.json +16 -0
- package/skills/swift-patterns/references/concurrency-migration.md +40 -0
- package/skills/swift-testing/SKILL.md +121 -0
- package/skills/swift-testing/evals/triggers.json +16 -0
- package/skills/swift-testing/references/swift-testing-cheatsheet.md +81 -0
- package/skills/swiftui-patterns/SKILL.md +102 -0
- package/skills/swiftui-patterns/evals/triggers.json +16 -0
- package/skills/tdd-workflow/SKILL.md +67 -0
- package/skills/tdd-workflow/evals/triggers.json +14 -0
- package/skills/technical-writing/SKILL.md +95 -0
- package/skills/technical-writing/evals/triggers.json +14 -0
- package/skills/terraform-patterns/SKILL.md +122 -0
- package/skills/terraform-patterns/evals/triggers.json +16 -0
- package/skills/terraform-patterns/references/backends.md +67 -0
- package/skills/test-coverage-improvement/SKILL.md +107 -0
- package/skills/test-coverage-improvement/evals/triggers.json +16 -0
- package/skills/threat-modeling/SKILL.md +113 -0
- package/skills/threat-modeling/evals/triggers.json +16 -0
- package/skills/typescript-patterns/SKILL.md +122 -0
- package/skills/typescript-patterns/evals/triggers.json +16 -0
- package/skills/typescript-testing/SKILL.md +101 -0
- package/skills/typescript-testing/evals/triggers.json +16 -0
- package/skills/verification-loop/SKILL.md +70 -0
- package/skills/verification-loop/evals/triggers.json +14 -0
- package/skills/verification-loop/scripts/detect-checks.js +102 -0
- package/skills/vite-patterns/SKILL.md +117 -0
- package/skills/vite-patterns/evals/triggers.json +16 -0
- package/skills/vue-patterns/SKILL.md +104 -0
- package/skills/vue-patterns/evals/triggers.json +16 -0
- package/skills/web-accessibility/SKILL.md +119 -0
- package/skills/web-accessibility/evals/triggers.json +16 -0
- package/skills/web-performance/SKILL.md +107 -0
- package/skills/web-performance/evals/triggers.json +16 -0
- package/skills/web-scraping/SKILL.md +80 -0
- package/skills/web-scraping/evals/triggers.json +16 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# DNS record shapes
|
|
2
|
+
|
|
3
|
+
Replace `example.com`, selectors and provider includes with the user's values. Always read existing records first.
|
|
4
|
+
|
|
5
|
+
## SPF (RFC 7208)
|
|
6
|
+
|
|
7
|
+
One TXT record at each name that appears as an envelope sender (Return-Path).
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
example.com. TXT "v=spf1 include:_spf.google.com include:amazonses.com ~all"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
- Only one `v=spf1` record per name. Two records is a `permerror`.
|
|
14
|
+
- At most 10 DNS-querying mechanisms (`include`, `a`, `mx`, `ptr`, `exists`, `redirect`), counted recursively. Over 10 is a `permerror`, which counts as a fail.
|
|
15
|
+
- To get under 10: move senders to subdomains (each subdomain has its own SPF), remove services no longer used, or replace an `include` with `ip4:`/`ip6:` ranges only if the provider publishes stable ones.
|
|
16
|
+
- `~all` (softfail) is normal once DMARC is in place; `-all` is fine when the list is complete. Never `+all`.
|
|
17
|
+
- A domain that never sends mail: `v=spf1 -all`.
|
|
18
|
+
|
|
19
|
+
## DKIM
|
|
20
|
+
|
|
21
|
+
The provider gives the selector and key, usually as a CNAME so it can rotate keys.
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
s1._domainkey.example.com. CNAME s1.domainkey.u123.wl.provider.net.
|
|
25
|
+
s1._domainkey.example.com. TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkq..."
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
- Use 2048-bit RSA where offered. Long TXT values may need splitting into several quoted strings; most DNS hosts do this for you.
|
|
29
|
+
- Check: `dig +short TXT s1._domainkey.example.com`. In a received message, `DKIM-Signature: d=` must be your domain for alignment.
|
|
30
|
+
|
|
31
|
+
## DMARC (RFC 9989, which obsoletes RFC 7489)
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
_dmarc.example.com. TXT "v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com; adkim=r; aspf=r"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
| Tag | Meaning |
|
|
38
|
+
|---|---|
|
|
39
|
+
| `p` | `none` (monitor), `quarantine`, `reject` |
|
|
40
|
+
| `sp` | policy for subdomains, defaults to `p` |
|
|
41
|
+
| `rua` | where aggregate XML reports go; use a mailbox or a DMARC report service |
|
|
42
|
+
| `pct` | RFC 7489 only: share of failing mail the policy applies to, default 100. RFC 9989 removed it (along with `rf` and `ri`) and added `t=y`, a test flag asking receivers to apply one policy level lower. Older receivers may still read `pct`; do not depend on it for rollout |
|
|
43
|
+
| `adkim` / `aspf` | `r` relaxed (organisational domain match, the default) or `s` strict |
|
|
44
|
+
|
|
45
|
+
Reports sent to a different domain need an authorisation record at that domain (`example.com._report._dmarc.reports.net TXT "v=DMARC1"`); report services set this up.
|
|
46
|
+
|
|
47
|
+
Rollout: `p=none` for a few weeks (2 to 4 is a rule of thumb), then `p=quarantine`, then `p=reject`. Rolling out per subdomain with `sp=` is a safer stage than `pct`.
|
|
48
|
+
|
|
49
|
+
## BIMI
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
default._bimi.example.com. TXT "v=BIMI1; l=https://example.com/bimi/logo.svg; a=https://example.com/bimi/vmc.pem"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
- Requires DMARC at `quarantine` or `reject` on the organisational domain; Gmail also requires `pct=100` if `pct` is present.
|
|
56
|
+
- `l=` is an HTTPS URL to an SVG Tiny PS file. `a=` is the PEM certificate (Gmail accepts a VMC or a CMC; other providers set their own rules).
|
|
57
|
+
- Display is at the mailbox provider's discretion even when everything validates.
|
|
58
|
+
|
|
59
|
+
## One-click unsubscribe headers (RFC 8058)
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
List-Unsubscribe: <https://example.com/unsub?t=opaque-token>, <mailto:unsub@example.com?subject=unsub>
|
|
63
|
+
List-Unsubscribe-Post: List-Unsubscribe=One-Click
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
- The HTTPS endpoint must accept a POST with body `List-Unsubscribe=One-Click` and unsubscribe without further confirmation or login.
|
|
67
|
+
- Both headers must be covered by the DKIM signature.
|
|
68
|
+
- The token identifies the recipient and list; it must not be guessable or expose the address.
|
|
69
|
+
|
|
70
|
+
## Useful checks
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
dig +short TXT example.com
|
|
74
|
+
dig +short TXT _dmarc.example.com
|
|
75
|
+
dig +short TXT default._bimi.example.com
|
|
76
|
+
dig +short -x <sending-ip> # reverse DNS (PTR)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Sources
|
|
80
|
+
|
|
81
|
+
- Gmail sender guidelines: https://support.google.com/a/answer/81126 and FAQ (48-hour unsubscribe): https://support.google.com/a/answer/14229414
|
|
82
|
+
- Outlook.com high-volume senders (`550 5.7.515`): https://support.microsoft.com/en-us/outlook/fix-ndr-error-550-5-7-515-in-outlook-com
|
|
83
|
+
- Gmail BIMI: https://knowledge.workspace.google.com/admin/security/set-up-bimi
|
|
84
|
+
- SPF: https://www.rfc-editor.org/rfc/rfc7208 . DMARC: https://www.rfc-editor.org/rfc/rfc9989 . One-click unsubscribe: https://www.rfc-editor.org/rfc/rfc8058
|
|
85
|
+
- CAN-SPAM: https://www.ftc.gov/business-guidance/resources/can-spam-act-compliance-guide-business
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: error-handling-patterns
|
|
3
|
+
description: Language-agnostic rules for designing how code fails, covering when to crash versus recover, typed and wrapped errors with context, retry with exponential backoff and jitter only for idempotent work, timeouts on every remote call, and separating what the user sees from what gets logged. Use when writing or restructuring try/catch, Result or error-return code, adding retries or timeouts to a network client, or deciding what an API should return on failure.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Any Agent Skills host. No tools required beyond the project's own test runner.
|
|
6
|
+
metadata:
|
|
7
|
+
kete-loom/version: "0.1.0"
|
|
8
|
+
kete-loom/category: coding
|
|
9
|
+
kete-loom/risk: writes-files
|
|
10
|
+
kete-loom/owner: "Kete-org"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Error handling patterns
|
|
14
|
+
|
|
15
|
+
Every error is either handled (something useful happens) or propagated (with context). Nothing in between.
|
|
16
|
+
|
|
17
|
+
## 0. Before you change anything
|
|
18
|
+
|
|
19
|
+
1. Find the project's existing error conventions: a base error class, an error-code enum, a `Result` type, a logging helper, an HTTP error middleware. Search for them before inventing new ones.
|
|
20
|
+
2. Find where errors finally land: top-level handler, request middleware, job runner, CLI `main`. That is where logging and user messages belong.
|
|
21
|
+
3. If the project has none of this and the change needs it, **stop and ask the user** whether to introduce a convention or keep it local.
|
|
22
|
+
|
|
23
|
+
## 1. Classify the failure first
|
|
24
|
+
|
|
25
|
+
| Kind | Examples | Default action |
|
|
26
|
+
|---|---|---|
|
|
27
|
+
| Programmer bug | null where impossible, broken invariant, bad index | Fail fast. Crash or throw; do not catch. |
|
|
28
|
+
| Invalid input | bad request body, unknown CLI flag, malformed file | Reject at the boundary with a precise message. Do not retry. |
|
|
29
|
+
| Expected domain outcome | not found, insufficient funds, already exists | Return it as a value or a typed error the caller must handle. |
|
|
30
|
+
| Transient infrastructure | timeout, connection reset, 429, 503, deadlock | Retry with backoff if the operation is idempotent; otherwise surface. |
|
|
31
|
+
| Fatal environment | missing config, disk full, bad credentials at startup | Fail at startup with a clear message, not on first request. |
|
|
32
|
+
|
|
33
|
+
Decision rule: if you cannot name what the caller should do differently for an error, it is not a separate type. Do not create one error class per function.
|
|
34
|
+
|
|
35
|
+
## 2. Raise and wrap with context
|
|
36
|
+
|
|
37
|
+
- Throw or return the most specific type the project already has.
|
|
38
|
+
- When propagating, add what *this* layer knows (the ID, the file path, the operation) and keep the original as the cause. Idioms per language are in `references/language-idioms.md`.
|
|
39
|
+
- Wrap once per layer that adds information. Do not re-wrap the same error at every stack frame.
|
|
40
|
+
- Never build an error message from secrets, tokens, full request bodies or personal data.
|
|
41
|
+
- Never use exceptions for normal control flow (loop exits, "not found" in a hot path) where the language offers a value.
|
|
42
|
+
|
|
43
|
+
## 3. Catch only what you can handle
|
|
44
|
+
|
|
45
|
+
A catch block is justified only if it does one of these:
|
|
46
|
+
|
|
47
|
+
1. Recovers: retries, falls back to a value that is **correct** for the caller, or takes a compensating action.
|
|
48
|
+
2. Translates: converts a low-level error into the layer's own type, keeping the cause.
|
|
49
|
+
3. Reports at the edge: logs once and converts to a user response or exit code.
|
|
50
|
+
4. Cleans up and rethrows (prefer `finally`, `defer`, `using`, `with`, RAII instead).
|
|
51
|
+
|
|
52
|
+
Never:
|
|
53
|
+
- Leave a catch block empty, or with only a comment.
|
|
54
|
+
- Catch the broadest type (`Exception`, `Throwable`, bare `except:`, `catch (e)`) except at the top-level edge.
|
|
55
|
+
- Log and rethrow at every layer; you get the same error five times in the logs.
|
|
56
|
+
- Return a default (`null`, `[]`, `0`, `false`) that the caller cannot tell apart from a real result.
|
|
57
|
+
- Ignore a returned error value or an unawaited promise or future.
|
|
58
|
+
|
|
59
|
+
## 4. Retries
|
|
60
|
+
|
|
61
|
+
Retry only when **all** are true:
|
|
62
|
+
|
|
63
|
+
- The failure is transient (timeouts, connection errors, 408, 429, 502, 503, 504, database serialisation or deadlock errors).
|
|
64
|
+
- The operation is idempotent, or you send an idempotency key the server honours. A non-idempotent POST that timed out may already have succeeded.
|
|
65
|
+
- There is a cap on attempts (typically 3 to 5) and on total time.
|
|
66
|
+
|
|
67
|
+
How:
|
|
68
|
+
1. Exponential backoff with jitter: `sleep = random(0, min(cap, base * 2^attempt))`. Without jitter, clients retry in lockstep.
|
|
69
|
+
2. Honour a `Retry-After` header when the server sends one.
|
|
70
|
+
3. Retry at one layer only. Retries in the HTTP client, the SDK and the job queue multiply.
|
|
71
|
+
4. Log each retry at debug or warn with the attempt number; log the final failure at error.
|
|
72
|
+
5. For writes that must not run twice (payments, emails, stock changes), generate the idempotency key once per logical operation and reuse it on every attempt.
|
|
73
|
+
|
|
74
|
+
Prefer the retry helper the project or SDK already ships over a hand-written loop.
|
|
75
|
+
|
|
76
|
+
## 5. Timeouts and cancellation
|
|
77
|
+
|
|
78
|
+
- Every network call, queue read, lock wait and subprocess gets an explicit timeout. Library defaults are often infinite.
|
|
79
|
+
- Pass the caller's deadline or cancellation token down (`context.Context`, `AbortSignal`, `CancellationToken`) instead of starting fresh timers at each layer.
|
|
80
|
+
- The inner timeout must be shorter than the outer one, or retries never get a chance.
|
|
81
|
+
- On timeout, treat the outcome of a write as unknown, not failed. Reconcile or use an idempotency key.
|
|
82
|
+
|
|
83
|
+
## 6. What the user sees vs what is logged
|
|
84
|
+
|
|
85
|
+
| Audience | Gets |
|
|
86
|
+
|---|---|
|
|
87
|
+
| End user / API client | A stable error code, a short human message, a correlation or request ID. No stack traces, SQL, paths or internal hostnames. |
|
|
88
|
+
| Logs | The full error chain, stack trace, operation, relevant IDs, correlation ID. No secrets or personal data. |
|
|
89
|
+
|
|
90
|
+
- Log each error exactly once, at the place that handles it (usually the edge).
|
|
91
|
+
- Use the level that matches action needed: error means someone should look; expected domain outcomes are info or not logged.
|
|
92
|
+
- Map error types to status codes or exit codes in one place, not scattered through handlers.
|
|
93
|
+
|
|
94
|
+
## 7. Verify
|
|
95
|
+
|
|
96
|
+
1. Write or update a test for each new error path: the error type or code returned, the message the user sees, and that cleanup ran.
|
|
97
|
+
2. For retries, test with a fake that fails N times then succeeds, and one that always fails; assert the attempt count and that non-idempotent calls are not retried.
|
|
98
|
+
3. For timeouts, test with a fake that never responds.
|
|
99
|
+
4. Run the full test suite. Do not report done while it is red.
|
|
100
|
+
|
|
101
|
+
## Report format
|
|
102
|
+
|
|
103
|
+
When you finish, report:
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
Error handling changes
|
|
107
|
+
- <file:line> <what changed> (<kind from step 1>)
|
|
108
|
+
Retries: <where, policy, idempotency guarantee> | none
|
|
109
|
+
Timeouts: <where, value> | none
|
|
110
|
+
Tests: <command run> -> <pass/fail>
|
|
111
|
+
Open questions: <anything you stopped to ask, or none>
|
|
112
|
+
```
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"should_trigger": [
|
|
3
|
+
"Add retries with exponential backoff to our HTTP client for the shipping API",
|
|
4
|
+
"How should this service decide between crashing and recovering when the config file is missing?",
|
|
5
|
+
"Restructure the error handling in the order service so we stop leaking stack traces to API clients",
|
|
6
|
+
"Wrap these database errors with context so the logs tell us which customer failed",
|
|
7
|
+
"Our outbound calls hang forever sometimes, add timeouts and cancellation properly",
|
|
8
|
+
"Design the error types for this new payments module"
|
|
9
|
+
],
|
|
10
|
+
"should_not_trigger": [
|
|
11
|
+
"Scan this module for empty catch blocks and swallowed errors and report them",
|
|
12
|
+
"Fix the TypeScript compile error in src/api/client.ts",
|
|
13
|
+
"Refactor this class into smaller functions without changing behaviour",
|
|
14
|
+
"Review my diff for bugs before I open the pull request",
|
|
15
|
+
"Integrate Paystack webhooks into our checkout flow",
|
|
16
|
+
"The checkout endpoint is slow, profile it and find the bottleneck"
|
|
17
|
+
]
|
|
18
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Error idioms by language
|
|
2
|
+
|
|
3
|
+
Read the section for the language you are editing. Follow the project's existing conventions when they differ.
|
|
4
|
+
|
|
5
|
+
## TypeScript / JavaScript
|
|
6
|
+
|
|
7
|
+
- Wrap with a cause: `throw new Error("loading invoice " + id, { cause: err })`.
|
|
8
|
+
- Subclass `Error` for types callers branch on; set `this.name`.
|
|
9
|
+
- In `catch (err)`, treat `err` as `unknown` (it is, under `strict` / `useUnknownInCatchVariables`): narrow with `instanceof` before reading fields. Anything can be thrown, not only `Error`.
|
|
10
|
+
- Every promise is awaited, returned, or explicitly handled. Lint with `@typescript-eslint/no-floating-promises`.
|
|
11
|
+
- Timeouts: `fetch(url, { signal: AbortSignal.timeout(5000) })`; pass an `AbortSignal` down for cancellation.
|
|
12
|
+
- ESLint `no-empty` flags empty catch blocks.
|
|
13
|
+
|
|
14
|
+
## Python
|
|
15
|
+
|
|
16
|
+
- Wrap with `raise LoadError(f"loading invoice {id}") from err`. Use `from None` only to hide an irrelevant cause deliberately.
|
|
17
|
+
- Catch specific exceptions. Bare `except:` also catches `KeyboardInterrupt` and `SystemExit`.
|
|
18
|
+
- Use `with` for cleanup. Use `logger.exception(...)` inside `except` to keep the traceback.
|
|
19
|
+
- Timeouts: `requests` has none by default; always pass `timeout=`. `httpx` defaults to 5 seconds.
|
|
20
|
+
- Ruff rules `BLE001` (blind except) and `S110` (try-except-pass) find swallowed errors.
|
|
21
|
+
|
|
22
|
+
## Go
|
|
23
|
+
|
|
24
|
+
- Wrap with `fmt.Errorf("loading invoice %s: %w", id, err)`; inspect with `errors.Is` and `errors.As`.
|
|
25
|
+
- Sentinel errors (`var ErrNotFound = errors.New("not found")`) for conditions callers check.
|
|
26
|
+
- Never `_ =` an error without a comment saying why it is safe.
|
|
27
|
+
- Pass `ctx context.Context` first; use `context.WithTimeout` and always `defer cancel()`.
|
|
28
|
+
- `errcheck` (also in `golangci-lint`) finds unchecked errors.
|
|
29
|
+
|
|
30
|
+
## Rust
|
|
31
|
+
|
|
32
|
+
- `Result<T, E>` for recoverable errors; `panic!` only for bugs.
|
|
33
|
+
- Libraries: a typed error enum (often with `thiserror`). Applications: `anyhow` with `.context("loading invoice")`.
|
|
34
|
+
- `?` propagates; `.unwrap()` and `.expect()` only where failure is a bug, with an `expect` message saying why.
|
|
35
|
+
- `#[must_use]` on functions whose result must not be ignored.
|
|
36
|
+
|
|
37
|
+
## Java / Kotlin
|
|
38
|
+
|
|
39
|
+
- Wrap with the cause constructor: `new LoadException("loading invoice " + id, e)`.
|
|
40
|
+
- Use try-with-resources (Java) or `use {}` (Kotlin) for cleanup.
|
|
41
|
+
- Do not catch `Throwable` or `Error`. In Kotlin coroutines, rethrow `CancellationException`.
|
|
42
|
+
- Set connect and read timeouts on every HTTP client explicitly.
|
|
43
|
+
|
|
44
|
+
## C#
|
|
45
|
+
|
|
46
|
+
- Rethrow with `throw;` not `throw ex;` (which resets the stack trace).
|
|
47
|
+
- Wrap with `new LoadException("...", ex)` using the inner-exception constructor.
|
|
48
|
+
- Use `using` / `await using` for cleanup; pass `CancellationToken` through async calls.
|
|
49
|
+
- Filter with `catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.ServiceUnavailable)`.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: estimation-and-scoping
|
|
3
|
+
description: Software effort estimation and scope negotiation that breaks a project into small tasks, gives each a best, likely and worst case instead of a single number, surfaces unknowns and time-boxed spikes to resolve them, adds integration, review and release overhead, and offers concrete scope cuts that fit a deadline, finishing with a range and a stated confidence level. Use when someone asks how long a feature or project will take, needs a quote or a sizing for planning, has a fixed date and must decide what to cut, or wants to know why an earlier estimate was wrong.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Any Agent Skills host. Reads the codebase to size the work; no other tools needed.
|
|
6
|
+
metadata:
|
|
7
|
+
kete-loom/version: "0.1.0"
|
|
8
|
+
kete-loom/category: docs
|
|
9
|
+
kete-loom/risk: read-only
|
|
10
|
+
kete-loom/owner: "Kete-org"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Estimation and scoping
|
|
14
|
+
|
|
15
|
+
An estimate is a range with a confidence level and the assumptions it depends on. It is not a promise. Give the reader what they need to make a decision: how big, how sure, and what would change it.
|
|
16
|
+
|
|
17
|
+
## 0. Pin down the question
|
|
18
|
+
|
|
19
|
+
1. What exactly is being estimated, and what does "done" mean (merged, released to all users, documented, migrated)? If unclear, **ask the user** before estimating.
|
|
20
|
+
2. Who is doing the work, how much of their time is available, and in what unit the answer is wanted (engineer-days, calendar weeks, story points). Calendar time is effort divided by real availability, not by headcount alone.
|
|
21
|
+
3. Is the date or the scope fixed? If the date is fixed, the job is scoping (section 4), not estimating.
|
|
22
|
+
4. If a PRD or plan exists, read it. If the requirements are vague, estimate only the parts that are defined and list the rest as unknowns.
|
|
23
|
+
|
|
24
|
+
## 1. Break it down
|
|
25
|
+
|
|
26
|
+
- Read the code the work touches: search for the modules, endpoints, tables and tests involved. Note anything unexpectedly tangled.
|
|
27
|
+
- Split into tasks of roughly half a day to three days each. Anything bigger is not understood yet; split again or mark it as an unknown.
|
|
28
|
+
- Include the work people forget: tests, migrations and backfills, config and feature flags, docs, code review rounds, QA, deploy and rollout, monitoring, and handling feedback after release.
|
|
29
|
+
- Note dependencies on other teams, approvals, vendors or environments. Waiting time goes in the calendar estimate even though it is not effort.
|
|
30
|
+
|
|
31
|
+
## 2. Estimate each task as a range
|
|
32
|
+
|
|
33
|
+
For each task give best case (B), likely case (L) and worst case (W) in the same unit.
|
|
34
|
+
|
|
35
|
+
- B: everything goes right. W: the realistic bad case, not the apocalypse.
|
|
36
|
+
- A wide B-to-W spread is information; do not narrow it to look confident.
|
|
37
|
+
- Roll-up: the common three-point (PERT) expected value per task is E = (B + 4L + W) / 6. Sum the E values for the planning number; do not sum likely cases, which understates the total because overruns are larger than underruns. Summed B and summed W give the outer range ends, but say that summed W overstates the bad tail, since not every task goes wrong at once.
|
|
38
|
+
- Use history if it exists: how long similar past work took, from tickets or git history. Prefer that over gut feel and say which you used.
|
|
39
|
+
|
|
40
|
+
## 3. Unknowns and spikes
|
|
41
|
+
|
|
42
|
+
- List every unknown: unfamiliar API, unclear requirement, performance not yet measured, legacy code nobody owns, a dependency's readiness.
|
|
43
|
+
- For each, either propose a **spike**: a time-boxed investigation (for example "2 days to prototype the vendor webhook and confirm rate limits") with the question it must answer, or carry it as a risk that widens the range.
|
|
44
|
+
- When unknowns dominate, recommend estimating in two stages: commit only to the spikes now, re-estimate after them.
|
|
45
|
+
|
|
46
|
+
## 4. Scope to fit
|
|
47
|
+
|
|
48
|
+
When the range does not fit the date or budget, offer options instead of squeezing the numbers:
|
|
49
|
+
|
|
50
|
+
- Cut or defer Should and Could requirements; name each and its saving.
|
|
51
|
+
- Ship a thinner first version: one platform, one customer segment, manual steps behind the scenes, no admin UI, a lower limit.
|
|
52
|
+
- Buy or reuse instead of build.
|
|
53
|
+
- Add people only when the work splits cleanly and there is time to onboard them; say this rarely shortens a late project.
|
|
54
|
+
- Make each option concrete: what is cut, what the user loses, the new range.
|
|
55
|
+
|
|
56
|
+
Never quietly lower an estimate because the requester wants a smaller number. If pushed, restate the range and offer scope cuts.
|
|
57
|
+
|
|
58
|
+
## 5. Communicate confidence
|
|
59
|
+
|
|
60
|
+
- State the range and a confidence level in plain words: "4 to 7 weeks; about 70% confident we finish within 7".
|
|
61
|
+
- Say what the estimate assumes (staffing, no major requirement changes, the spike result) and what would move it.
|
|
62
|
+
- Name the checkpoint where you will re-estimate (after the spike, at the halfway mark).
|
|
63
|
+
- Use the unit asked for. If asked for story points, give points but still list the unknowns.
|
|
64
|
+
|
|
65
|
+
## Output format
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
## Estimate: <work item>
|
|
69
|
+
Done means: <definition>
|
|
70
|
+
Assumes: <people, availability, fixed scope, other assumptions>
|
|
71
|
+
|
|
72
|
+
| # | Task | Best | Likely | Worst | Notes |
|
|
73
|
+
|---|------|------|--------|-------|-------|
|
|
74
|
+
| 1 | ... | 1d | 2d | 4d | touches billing/invoice.ts |
|
|
75
|
+
|
|
76
|
+
Effort: <sum best> to <sum worst> (expected <sum of PERT E>) engineer-days
|
|
77
|
+
Calendar: <range> at <availability>, including waits on <dependencies>
|
|
78
|
+
Confidence: <level and what it means>
|
|
79
|
+
Unknowns and spikes: <list with time boxes>
|
|
80
|
+
Scope options if it must be smaller: <option, saving, user cost>
|
|
81
|
+
Re-estimate at: <checkpoint>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Reviewing why an estimate was wrong
|
|
85
|
+
|
|
86
|
+
Compare the original breakdown to what happened: tasks that were missing entirely, tasks that grew, waiting time, scope added mid-way, availability lower than assumed. Report the biggest causes and one change to the next estimate for each. Do not assign blame.
|
|
87
|
+
|
|
88
|
+
## Never
|
|
89
|
+
|
|
90
|
+
- Never give a single number without a range and its assumptions.
|
|
91
|
+
- Never estimate work you have not broken down; say you need to break it down first.
|
|
92
|
+
- Never present a guess about someone else's team as fact; mark it and suggest asking them.
|
|
93
|
+
|
|
94
|
+
## Neighbours
|
|
95
|
+
|
|
96
|
+
- Writing the requirements being sized: `prd-writing`.
|
|
97
|
+
- An ordered implementation plan with files and tests: the `planner` agent or `/plan-feature`.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"should_trigger": [
|
|
3
|
+
"How long will it take to add SSO login to our app? Give me a range, not one number",
|
|
4
|
+
"We have to launch the mobile checkout by March 1. Look at the scope and tell me what to cut to make that date",
|
|
5
|
+
"Size this epic for quarterly planning, call out the unknowns and suggest spikes",
|
|
6
|
+
"Our last project was estimated at 3 weeks and took 9. Help me figure out why and estimate the next one better"
|
|
7
|
+
],
|
|
8
|
+
"should_not_trigger": [
|
|
9
|
+
"Write the product requirements doc for SSO login with acceptance criteria",
|
|
10
|
+
"List the files I need to change to add SSO and the order to change them in",
|
|
11
|
+
"Estimate how much this AWS setup will cost per month",
|
|
12
|
+
"Benchmark the checkout endpoint and tell me its p99 latency"
|
|
13
|
+
]
|
|
14
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: evm-dapp-integration
|
|
3
|
+
description: Connects web frontends and backends to Ethereum and EVM chains with viem (optionally wagmi) or ethers v6, covering EIP-1193 and EIP-6963 wallet discovery and connection, checking and switching chain IDs, typed contract reads, simulating before writes, token amounts kept as bigint with parseUnits and formatUnits against each token's decimals, the transaction lifecycle from signature to receipt status and confirmations, replaced or dropped transactions, event logs, and RPC rate limits and block-range caps. Use when adding a connect-wallet button, calling a deployed contract from a dapp or Node service, displaying or sending ERC-20 amounts, or debugging stuck transactions and RPC errors.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Any Agent Skills host. Needs Node.js 18+ and the project's package manager; examples use viem 2.x and ethers 6.x. Live calls need an RPC endpoint and network access.
|
|
6
|
+
metadata:
|
|
7
|
+
kete-loom/version: "0.1.0"
|
|
8
|
+
kete-loom/category: integrations
|
|
9
|
+
kete-loom/risk: network
|
|
10
|
+
kete-loom/owner: "Kete-org"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# EVM dapp integration
|
|
14
|
+
|
|
15
|
+
Make the app talk to the chain without losing precision, sending to the wrong network, or telling the user "done" before the chain agrees. Private keys belong to the user's wallet, not your code. This is engineering guidance, not financial advice.
|
|
16
|
+
|
|
17
|
+
## Ground rules
|
|
18
|
+
|
|
19
|
+
1. **Amounts are `bigint` in base units, end to end.** Convert at the edges only: `parseUnits(input, decimals)` from user text, `formatUnits(value, decimals)` for display (both in viem and ethers v6). Never use `Number`, `parseFloat` or JavaScript floats for token amounts; never assume 18 decimals (USDC and USDT are 6 on most chains). Read `decimals()` from the token or a reviewed token list.
|
|
20
|
+
2. **Check the chain ID before every write.** Compare the wallet's chain to the one your contract addresses belong to; prompt a switch (`switchChain` in viem/wagmi, `wallet_switchEthereumChain` via EIP-1193) rather than sending on the wrong network. Keep contract addresses in a map keyed by chain ID.
|
|
21
|
+
3. **Simulate, then write.** viem: `publicClient.simulateContract(...)` then `walletClient.writeContract(request)`. ethers v6: `contract.fn.staticCall(...)` or `estimateGas` before sending. Show the decoded revert reason if the simulation fails.
|
|
22
|
+
4. **A hash is not a success.** `writeContract`/`sendTransaction` returns only a hash. Wait for the receipt (`waitForTransactionReceipt({ hash, confirmations })` in viem, `await tx.wait(confirmations)` in ethers) and check it: viem returns the receipt with `status` `'success'` or `'reverted'` (it does not throw on revert); ethers v6 `wait()` throws a `CALL_EXCEPTION` error when the receipt status is `0`, so catch it.
|
|
23
|
+
5. **No private keys in frontends.** Browser code signs through the user's wallet only. Backend signers load keys from a secret manager or KMS, never from the repo or a `NEXT_PUBLIC_`/`VITE_` variable.
|
|
24
|
+
6. **Treat chain data as untrusted input.** Token names, symbols and metadata URIs can be anything; escape them before rendering.
|
|
25
|
+
|
|
26
|
+
## Library choice
|
|
27
|
+
|
|
28
|
+
| Situation | Use |
|
|
29
|
+
|---|---|
|
|
30
|
+
| React app with wallets | wagmi on top of viem, with a connector kit if the project already has one |
|
|
31
|
+
| Non-React frontend or Node service | viem `createPublicClient` / `createWalletClient` with `http()` or `webSocket()` transport |
|
|
32
|
+
| Existing ethers codebase | stay on ethers v6 (`BrowserProvider`, `JsonRpcProvider`, `Contract`); don't mix libraries in one module |
|
|
33
|
+
|
|
34
|
+
Generate types from ABIs (`as const` ABI with viem, or TypeChain/wagmi CLI) so function names and argument types are checked at compile time.
|
|
35
|
+
|
|
36
|
+
## Steps
|
|
37
|
+
|
|
38
|
+
1. **Config**: chains the app supports, RPC URLs per chain from environment variables, contract addresses per chain ID, ABIs as `const` exports. Use a paid or self-hosted RPC for production; public endpoints rate-limit hard.
|
|
39
|
+
2. **Wallet connection**: discover injected wallets with EIP-6963 (wagmi and most kits do this), fall back to `window.ethereum` (EIP-1193). Request accounts only on a user click. Listen for `accountsChanged` and `chainChanged` and reset app state on both.
|
|
40
|
+
3. **Reads**: `readContract` or `multicall` (viem) / `contract.fn()` (ethers). Batch reads with multicall instead of N calls. Pin a `blockNumber` when several reads must be consistent.
|
|
41
|
+
4. **Writes**:
|
|
42
|
+
- Validate inputs and convert amounts with the token's decimals.
|
|
43
|
+
- For ERC-20 spends, read `allowance` first; request an exact `approve` amount by default, not unlimited, unless the user opts in. Prefer EIP-2612 `permit` when the token supports it.
|
|
44
|
+
- Simulate, send, show the hash with an explorer link, then wait for the receipt.
|
|
45
|
+
5. **Lifecycle states in the UI**: `awaiting signature` → `pending` (hash known) → `confirmed` (receipt `success` with N confirmations) or `reverted` / `rejected by user` / `replaced`. Handle user rejection (EIP-1193 error code `4001`) as a normal cancel, not an error.
|
|
46
|
+
6. **Confirmations**: 1 is fine for UI feedback on L2s; for anything that releases off-chain value (crediting a deposit, shipping goods) wait for more blocks or the chain's finalized block (`getBlock({ blockTag: 'finalized' })`), and make the crediting idempotent per `(chainId, txHash, logIndex)`.
|
|
47
|
+
7. **Replaced transactions**: users speed up or cancel in their wallet, which changes the hash. viem's `waitForTransactionReceipt` reports this through `onReplaced` with reason `replaced`, `repriced` or `cancelled`; ethers `tx.wait()` throws a `TRANSACTION_REPLACED` error. Follow the new hash or show the cancel.
|
|
48
|
+
8. **Events**: `watchContractEvent` / `getLogs` (viem) or `contract.on` / `queryFilter` (ethers). Backfill history in block-range chunks (providers cap `eth_getLogs` ranges and result counts; check yours), and handle reorgs by re-reading recent blocks.
|
|
49
|
+
9. **RPC limits**: add retries with backoff for HTTP 429 and timeouts, a fallback transport (`fallback([http(a), http(b)])` in viem), and caching for reads that don't change per block.
|
|
50
|
+
|
|
51
|
+
## Backend services
|
|
52
|
+
|
|
53
|
+
- Use a dedicated hot wallet with only the funds it needs; track nonces yourself if sending concurrently, or serialise sends.
|
|
54
|
+
- Set `maxFeePerGas`/`maxPriorityFeePerGas` from `estimateFeesPerGas` (viem) or `getFeeData` (ethers), with a cap.
|
|
55
|
+
- Index by `(chainId, txHash, logIndex)` and never credit the same log twice.
|
|
56
|
+
|
|
57
|
+
## Stop and ask the user
|
|
58
|
+
|
|
59
|
+
- Before sending any transaction on a mainnet, or from a key that holds real funds.
|
|
60
|
+
- Which chains and which RPC provider to support in production.
|
|
61
|
+
- Whether to request unlimited token approvals.
|
|
62
|
+
- How many confirmations count as final for crediting value.
|
|
63
|
+
|
|
64
|
+
## Never
|
|
65
|
+
|
|
66
|
+
- Never hard-code a private key or mnemonic, even for a "test" wallet in committed code.
|
|
67
|
+
- Never compute amounts with floats or display a balance without its token's decimals.
|
|
68
|
+
- Never mark an action complete from the hash alone.
|
|
69
|
+
- Never trust a contract address or chain ID that comes from URL parameters or user input without checking it against your allow-list.
|
|
70
|
+
|
|
71
|
+
## Before you finish
|
|
72
|
+
|
|
73
|
+
Test against a local node (`anvil`, optionally `--fork-url` for real contract state) or a testnet: connect, wrong-network prompt, a read, an approve plus a write, a user rejection, a reverting call (simulation shows the reason), and a replaced transaction. Report the library versions, chains and addresses used, and anything not tested.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"should_trigger": [
|
|
3
|
+
"Connect MetaMask to our React app with viem and show the user's USDC balance",
|
|
4
|
+
"Show the token balance with the right decimals in our wagmi frontend and send an approve transaction",
|
|
5
|
+
"Our ethers v6 code says the transaction succeeded but the receipt status is 0, how should we handle the transaction lifecycle?",
|
|
6
|
+
"Prompt the user to switch to Base when their wallet is on the wrong chain ID before minting",
|
|
7
|
+
"getLogs keeps failing with a block range too large error from our RPC provider when backfilling Transfer events"
|
|
8
|
+
],
|
|
9
|
+
"should_not_trigger": [
|
|
10
|
+
"Write an ERC-20 token contract with a capped supply and an owner-only mint using Foundry",
|
|
11
|
+
"Audit our lending protocol contracts for oracle manipulation and reentrancy before launch",
|
|
12
|
+
"Review the Solidity diff in this PR for missing access control and storage collisions",
|
|
13
|
+
"Add Paystack checkout to our Next.js shop for Nigerian customers",
|
|
14
|
+
"Build a REST endpoint in Express that returns a user's order history"
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: fastapi-patterns
|
|
3
|
+
description: FastAPI service construction with APIRouter modules, Pydantic models as the request and response contract, Depends-based injection for settings, database sessions and the current user, choosing async def versus def per endpoint, consistent error bodies, BackgroundTasks, lifespan startup, and tests through TestClient or httpx with dependency_overrides. Use when creating or extending a FastAPI app, wiring a database session or auth into routes, deciding whether an endpoint should be async, or writing tests for FastAPI endpoints.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Any Agent Skills host. Needs Python and the project's FastAPI app. Assumes Pydantic v2; check the project's version first.
|
|
6
|
+
metadata:
|
|
7
|
+
kete-loom/version: "0.1.0"
|
|
8
|
+
kete-loom/category: coding
|
|
9
|
+
kete-loom/risk: runs-commands
|
|
10
|
+
kete-loom/requires: "python"
|
|
11
|
+
kete-loom/owner: "Kete-org"
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# FastAPI patterns
|
|
15
|
+
|
|
16
|
+
Build endpoints whose inputs and outputs are typed contracts, whose resources are opened and closed by dependencies, and which never block the event loop.
|
|
17
|
+
|
|
18
|
+
## 0. Before you change anything
|
|
19
|
+
|
|
20
|
+
1. Find the app object (`app = FastAPI(...)`) and how routers are included. Check the FastAPI and Pydantic versions in `pyproject.toml` or the lock file. Pydantic v1 and v2 APIs differ (`orm_mode` vs `from_attributes`, `.dict()` vs `.model_dump()`); match what is installed.
|
|
21
|
+
2. Find the database layer (SQLAlchemy sync or async, SQLModel, an async driver) and the existing session dependency. Reuse it.
|
|
22
|
+
3. Run the tests once (`pytest`). If they already fail, **stop and tell the user**.
|
|
23
|
+
|
|
24
|
+
## 1. Layout
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
app/
|
|
28
|
+
main.py # create FastAPI(), include routers, lifespan, exception handlers
|
|
29
|
+
config.py # Settings(BaseSettings) read from env
|
|
30
|
+
deps.py # get_db, get_current_user, get_settings
|
|
31
|
+
routers/orders.py
|
|
32
|
+
schemas/orders.py # Pydantic models (API contract)
|
|
33
|
+
models/orders.py # ORM models (storage)
|
|
34
|
+
services/orders.py # business logic, no FastAPI imports
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
- One `APIRouter(prefix="/orders", tags=["orders"])` per resource, included with `app.include_router(...)`.
|
|
38
|
+
- Keep ORM models and Pydantic schemas separate. Service functions take plain values and a session, so they can be tested without HTTP.
|
|
39
|
+
|
|
40
|
+
## 2. Pydantic at the boundary
|
|
41
|
+
|
|
42
|
+
- Separate input and output schemas: `OrderCreate` (what the client may send), `OrderUpdate` (all optional), `OrderRead` (what you return). Never accept the ORM model or a `dict` as a request body.
|
|
43
|
+
- Forbid unknown fields on inputs where silent drops would hide client bugs: `model_config = ConfigDict(extra="forbid")`.
|
|
44
|
+
- Constrain fields: `Field(gt=0)`, `Field(max_length=200)` or `Annotated[str, StringConstraints(max_length=200)]`, `EmailStr` (needs the `email-validator` package), enums for closed sets.
|
|
45
|
+
- Set `response_model=OrderRead` (or a return annotation) on every route that returns data, so fields like `password_hash` or `internal_notes` can't leak. For ORM objects, `OrderRead` needs `model_config = ConfigDict(from_attributes=True)`.
|
|
46
|
+
- Never let the client set server-owned fields (`id`, `owner_id`, `role`, `price`); set them from the authenticated user or your database.
|
|
47
|
+
|
|
48
|
+
## 3. Dependency injection
|
|
49
|
+
|
|
50
|
+
Prefer the `Annotated` style and reuse aliases:
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from typing import Annotated
|
|
54
|
+
from fastapi import Depends
|
|
55
|
+
|
|
56
|
+
def get_db():
|
|
57
|
+
db = SessionLocal()
|
|
58
|
+
try:
|
|
59
|
+
yield db
|
|
60
|
+
finally:
|
|
61
|
+
db.close()
|
|
62
|
+
|
|
63
|
+
DB = Annotated[Session, Depends(get_db)]
|
|
64
|
+
CurrentUser = Annotated[User, Depends(get_current_user)]
|
|
65
|
+
|
|
66
|
+
@router.get("/{order_id}", response_model=OrderRead)
|
|
67
|
+
def read_order(order_id: int, db: DB, user: CurrentUser):
|
|
68
|
+
order = db.get(Order, order_id)
|
|
69
|
+
if order is None or order.owner_id != user.id:
|
|
70
|
+
raise HTTPException(status_code=404, detail="Order not found")
|
|
71
|
+
return order
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
- Resources (sessions, clients, files) are opened in a `yield` dependency and closed in `finally`. Never create a session at module import or store one on a global.
|
|
75
|
+
- Decide commit policy once: either the dependency commits on success and rolls back on exception, or services commit explicitly. Follow the existing pattern.
|
|
76
|
+
- Settings: `@lru_cache` on `get_settings()` returning a `BaseSettings` (from `pydantic-settings` in v2), injected with `Depends`.
|
|
77
|
+
- Shared clients (`httpx.AsyncClient`, connection pools) are created in the `lifespan` context manager and closed when it exits; `@app.on_event` is deprecated.
|
|
78
|
+
|
|
79
|
+
## 4. async def or def
|
|
80
|
+
|
|
81
|
+
| Endpoint body does | Declare it |
|
|
82
|
+
|---|---|
|
|
83
|
+
| Only `await`s async libraries (async SQLAlchemy, `httpx.AsyncClient`, `asyncpg`) | `async def` |
|
|
84
|
+
| Calls blocking code (sync SQLAlchemy, `requests`, `time.sleep`, file I/O, CPU work) | `def` (FastAPI runs it in a threadpool) |
|
|
85
|
+
| Mostly async but one blocking call | `async def` plus `await run_in_threadpool(fn, ...)` (from `starlette.concurrency`) or `asyncio.to_thread` |
|
|
86
|
+
|
|
87
|
+
- **Never** call blocking I/O inside `async def`. It stalls every request on that worker.
|
|
88
|
+
- The same rule applies to dependencies: a sync `get_db` is fine; an `async def` dependency must not block.
|
|
89
|
+
- Heavy CPU work belongs in a worker queue, not a request.
|
|
90
|
+
|
|
91
|
+
## 5. Auth
|
|
92
|
+
|
|
93
|
+
- Implement auth as a dependency (`get_current_user`) built on `OAuth2PasswordBearer`, `HTTPBearer` or `APIKeyHeader`. Raise `HTTPException(401, headers={"WWW-Authenticate": "Bearer"})` on a bad token.
|
|
94
|
+
- Verify JWT signature, `exp`, and the expected algorithm (pass `algorithms=["HS256"]` or the one you use; never accept `none`). Check audience/issuer if you issue tokens for several services.
|
|
95
|
+
- Protect whole routers with `APIRouter(dependencies=[Depends(get_current_user)])` and add per-route role checks (`require_role("admin")`) on top. Every new route on an unprotected router needs its own dependency.
|
|
96
|
+
- Authorization is per object: filter by `owner_id`/tenant, and return 404 rather than 403 when revealing existence would leak data.
|
|
97
|
+
|
|
98
|
+
## 6. Error responses
|
|
99
|
+
|
|
100
|
+
- Raise `HTTPException(status_code, detail)` for expected client errors: 404 for not found, 409 for conflicts. FastAPI already returns 422 for request validation failures; don't reuse 422 for business-rule errors unless the API's error contract says so.
|
|
101
|
+
- Map domain exceptions once with `@app.exception_handler(OrderNotFound)` instead of try/except in every route.
|
|
102
|
+
- Keep one error body shape across the API. If you customise validation errors, override `RequestValidationError`'s handler and keep field locations.
|
|
103
|
+
- Never return stack traces or raw database errors to clients; log them server-side with a request id.
|
|
104
|
+
|
|
105
|
+
## 7. Background work
|
|
106
|
+
|
|
107
|
+
- `BackgroundTasks.add_task(fn, *args)` runs after the response is sent, in the same process. Use it only for short, loss-tolerant work (sending a notification email).
|
|
108
|
+
- Don't pass the request's database session to a background task; it may be closed. Open a new session inside the task.
|
|
109
|
+
- Anything that must survive a restart, retry, or take more than a few seconds goes to a real queue (Celery, RQ, Arq, Dramatiq).
|
|
110
|
+
|
|
111
|
+
## 8. Testing
|
|
112
|
+
|
|
113
|
+
- Sync tests: `from fastapi.testclient import TestClient`; `with TestClient(app) as client:` so lifespan runs.
|
|
114
|
+
- Async tests: `httpx.AsyncClient(transport=httpx.ASGITransport(app=app), base_url="http://test")` with `pytest-asyncio` or `anyio`. This client does **not** run lifespan; if the app needs it, wrap the app in `LifespanManager` from `asgi-lifespan` and pass `manager.app` to the transport.
|
|
115
|
+
- Swap dependencies, not internals: `app.dependency_overrides[get_db] = override_get_db`, `app.dependency_overrides[get_current_user] = lambda: fake_user`. Clear them in fixture teardown.
|
|
116
|
+
- Use a separate test database or a transaction rolled back per test. Never point tests at a shared database.
|
|
117
|
+
- For every route test the happy path, a validation failure (422), an unauthenticated call (401), another user's object (404/403), and that the response omits private fields.
|
|
118
|
+
|
|
119
|
+
## Rules
|
|
120
|
+
|
|
121
|
+
- Never return ORM objects without a `response_model`.
|
|
122
|
+
- Never block the event loop in `async def` routes or dependencies.
|
|
123
|
+
- Never disable auth dependencies to make a test pass; override them in the test.
|
|
124
|
+
|
|
125
|
+
## Report back
|
|
126
|
+
|
|
127
|
+
End with: routes added or changed (method and path), schemas added, dependencies touched, which endpoints are `async def` and why, the test command and result, and anything left untested.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"should_trigger": [
|
|
3
|
+
"Add a FastAPI router for invoices with create and list endpoints and Pydantic schemas",
|
|
4
|
+
"How should I wire a SQLAlchemy session into my FastAPI routes with Depends?",
|
|
5
|
+
"Should this FastAPI endpoint be async def or def? It calls requests and the ORM",
|
|
6
|
+
"Write tests for my FastAPI app using TestClient and override the auth dependency",
|
|
7
|
+
"Set up JWT bearer auth as a dependency for our FastAPI service"
|
|
8
|
+
],
|
|
9
|
+
"should_not_trigger": [
|
|
10
|
+
"Review this FastAPI pull request for blocking calls in async routes and leaked sessions",
|
|
11
|
+
"Add a Django model and migration for invoices",
|
|
12
|
+
"Restructure our Flask app into blueprints with an app factory",
|
|
13
|
+
"Explain asyncio.gather versus TaskGroup in a plain Python script",
|
|
14
|
+
"Design the REST resource naming and versioning for our public API"
|
|
15
|
+
]
|
|
16
|
+
}
|