@ketecode/loom 0.0.0-stage → 0.2.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 +616 -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/behavior.json +60 -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/inbox-triager/AGENT.md +98 -0
- package/agents/inbox-triager/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/spec-reviewer/AGENT.md +95 -0
- package/agents/spec-reviewer/evals/behavior.json +57 -0
- package/agents/spec-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/task-implementer/AGENT.md +89 -0
- package/agents/task-implementer/evals/behavior.json +47 -0
- package/agents/task-implementer/evals/triggers.json +16 -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 +723 -0
- package/commands/aside.md +19 -0
- package/commands/brainstorm.md +25 -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/debug.md +27 -0
- package/commands/deps-audit.md +32 -0
- package/commands/dual-review.md +34 -0
- package/commands/epic-decompose.md +21 -0
- package/commands/explain.md +37 -0
- package/commands/feature-dev.md +23 -0
- package/commands/finish-branch.md +26 -0
- package/commands/fix-bug.md +38 -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/production-readiness.md +45 -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/usage-report.md +43 -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-foreground-servers/HOOK.md +34 -0
- package/hooks/block-foreground-servers/cases.json +31 -0
- package/hooks/block-foreground-servers/hook.js +41 -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/capture-lessons/HOOK.md +24 -0
- package/hooks/capture-lessons/hook.js +48 -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/notify-on-stop/HOOK.md +25 -0
- package/hooks/notify-on-stop/hook.js +27 -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/protect-lint-config/HOOK.md +29 -0
- package/hooks/protect-lint-config/cases.json +18 -0
- package/hooks/protect-lint-config/fixtures/.eslintrc.json +1 -0
- package/hooks/protect-lint-config/fixtures/.golangci.yml +1 -0
- package/hooks/protect-lint-config/fixtures/.prettierrc +1 -0
- package/hooks/protect-lint-config/fixtures/.rubocop.yml +1 -0
- package/hooks/protect-lint-config/fixtures/biome.json +1 -0
- package/hooks/protect-lint-config/fixtures/eslint.config.mjs +1 -0
- package/hooks/protect-lint-config/fixtures/ruff.toml +1 -0
- package/hooks/protect-lint-config/hook.js +25 -0
- package/hooks/read-before-edit/HOOK.md +26 -0
- package/hooks/read-before-edit/cases.json +15 -0
- package/hooks/read-before-edit/hook.js +50 -0
- package/hooks/run.js +148 -0
- package/hooks/verify-before-stop/HOOK.md +32 -0
- package/hooks/verify-before-stop/hook.js +70 -0
- package/mcp/atlassian.json +11 -0
- package/mcp/chrome-devtools.json +18 -0
- package/mcp/clickhouse.json +11 -0
- package/mcp/cloudflare.json +11 -0
- package/mcp/context7.json +11 -0
- package/mcp/exa.json +11 -0
- package/mcp/fetch.json +17 -0
- package/mcp/figma.json +11 -0
- package/mcp/firecrawl.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/mcp/vercel.json +11 -0
- package/package.json +61 -4
- package/profiles.json +214 -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/rules/use-skills.md +23 -0
- package/schemas/skill-frontmatter.schema.json +52 -0
- package/scripts/lib/audit.js +96 -0
- package/scripts/lib/behavior.js +52 -0
- package/scripts/lib/frontmatter.js +65 -0
- package/scripts/lib/hooks-install.js +294 -0
- package/scripts/lib/i18n.js +51 -0
- package/scripts/lib/inventory.js +85 -0
- package/scripts/lib/lint.js +180 -0
- package/scripts/lib/mcp-install.js +288 -0
- package/scripts/lib/profiles.js +128 -0
- package/scripts/lib/render.js +92 -0
- package/scripts/lib/rules-install.js +118 -0
- package/scripts/lib/skills.js +87 -0
- package/scripts/lib/targets.js +123 -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-failure-debugging/SKILL.md +92 -0
- package/skills/agent-failure-debugging/evals/triggers.json +16 -0
- package/skills/agent-harness-design/SKILL.md +125 -0
- package/skills/agent-harness-design/evals/triggers.json +21 -0
- package/skills/agent-outbound-messaging/SKILL.md +92 -0
- package/skills/agent-outbound-messaging/evals/triggers.json +16 -0
- package/skills/agent-security/SKILL.md +117 -0
- package/skills/agent-security/evals/triggers.json +16 -0
- package/skills/agent-security/references/host-configs.md +37 -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-client-integration/SKILL.md +86 -0
- package/skills/api-client-integration/evals/triggers.json +16 -0
- package/skills/api-client-integration/references/resilience.md +57 -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/blender-automation/SKILL.md +100 -0
- package/skills/blender-automation/evals/triggers.json +16 -0
- package/skills/blender-automation/references/batch-and-render.md +77 -0
- package/skills/blender-automation/references/bpy-inspection.md +91 -0
- package/skills/blender-automation/references/rig-and-retarget-checks.md +23 -0
- package/skills/brand-strategy/SKILL.md +83 -0
- package/skills/brand-strategy/evals/triggers.json +16 -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/change-impact-analysis/SKILL.md +89 -0
- package/skills/change-impact-analysis/evals/triggers.json +16 -0
- package/skills/change-impact-analysis/references/graph-commands.md +28 -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/contract-drafting/SKILL.md +96 -0
- package/skills/contract-drafting/evals/triggers.json +16 -0
- package/skills/contract-drafting/references/term-sheets.md +68 -0
- package/skills/contract-first-development/SKILL.md +86 -0
- package/skills/contract-first-development/evals/triggers.json +16 -0
- package/skills/contract-first-development/references/tooling.md +46 -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/decision-council/SKILL.md +98 -0
- package/skills/decision-council/evals/triggers.json +16 -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/design-brainstorming/SKILL.md +132 -0
- package/skills/design-brainstorming/evals/behavior.json +55 -0
- package/skills/design-brainstorming/evals/triggers.json +16 -0
- package/skills/design-brainstorming/references/visual-mockups.md +34 -0
- package/skills/desktop-app-testing/SKILL.md +104 -0
- package/skills/desktop-app-testing/evals/triggers.json +16 -0
- package/skills/desktop-app-testing/references/drivers.md +81 -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/document-processing/SKILL.md +100 -0
- package/skills/document-processing/evals/triggers.json +17 -0
- package/skills/document-processing/references/extraction-and-ocr.md +71 -0
- package/skills/document-processing/references/forms-and-conversion.md +69 -0
- package/skills/document-processing/references/redaction.md +61 -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/energy-procurement/SKILL.md +106 -0
- package/skills/energy-procurement/evals/triggers.json +16 -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/finishing-a-branch/SKILL.md +127 -0
- package/skills/finishing-a-branch/evals/behavior.json +49 -0
- package/skills/finishing-a-branch/evals/triggers.json +16 -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/freight-carrier-management/SKILL.md +107 -0
- package/skills/freight-carrier-management/evals/triggers.json +16 -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/git-worktrees/SKILL.md +130 -0
- package/skills/git-worktrees/evals/behavior.json +56 -0
- package/skills/git-worktrees/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/google-workspace-integration/SKILL.md +65 -0
- package/skills/google-workspace-integration/evals/triggers.json +17 -0
- package/skills/google-workspace-integration/references/api.md +121 -0
- package/skills/harmonyos-arkts/SKILL.md +117 -0
- package/skills/harmonyos-arkts/evals/triggers.json +16 -0
- package/skills/harmonyos-arkts/references/build-errors.md +42 -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/implementation-plans/SKILL.md +117 -0
- package/skills/implementation-plans/evals/behavior.json +54 -0
- package/skills/implementation-plans/evals/triggers.json +16 -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/ios-platform-features/SKILL.md +99 -0
- package/skills/ios-platform-features/evals/triggers.json +16 -0
- package/skills/ios-platform-features/references/foundation-models.md +90 -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/jvm-sql-mappers/SKILL.md +98 -0
- package/skills/jvm-sql-mappers/evals/triggers.json +16 -0
- package/skills/jvm-sql-mappers/references/examples.md +129 -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/mobile-accessibility/SKILL.md +94 -0
- package/skills/mobile-accessibility/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-design/SKILL.md +98 -0
- package/skills/network-design/evals/triggers.json +16 -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/observability/SKILL.md +125 -0
- package/skills/observability/evals/triggers.json +17 -0
- package/skills/observability/references/otel-setup.md +87 -0
- package/skills/observability/references/slo-alerts.md +70 -0
- package/skills/open-source-release/SKILL.md +107 -0
- package/skills/open-source-release/evals/triggers.json +15 -0
- package/skills/open-source-release/references/history-scrub.md +65 -0
- package/skills/parallel-agent-orchestration/SKILL.md +106 -0
- package/skills/parallel-agent-orchestration/evals/triggers.json +14 -0
- package/skills/patent-research/SKILL.md +94 -0
- package/skills/patent-research/evals/triggers.json +16 -0
- package/skills/patent-research/references/databases-and-queries.md +52 -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/prospect-research/SKILL.md +87 -0
- package/skills/prospect-research/evals/triggers.json +16 -0
- package/skills/python-app-distribution/SKILL.md +107 -0
- package/skills/python-app-distribution/evals/triggers.json +16 -0
- package/skills/python-app-distribution/references/pypi-trusted-publishing.md +55 -0
- package/skills/python-app-distribution/references/windows-macos-signing.md +70 -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/quality-nonconformance/SKILL.md +107 -0
- package/skills/quality-nonconformance/evals/triggers.json +16 -0
- package/skills/quality-nonconformance/references/8d-and-capa.md +46 -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/react-testing/SKILL.md +121 -0
- package/skills/react-testing/evals/triggers.json +18 -0
- package/skills/react-testing/references/msw.md +64 -0
- package/skills/react-testing/references/queries.md +41 -0
- package/skills/react-testing/references/setup.md +74 -0
- package/skills/recommender-systems/SKILL.md +119 -0
- package/skills/recommender-systems/evals/triggers.json +16 -0
- package/skills/recommender-systems/references/evaluation.md +39 -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/behavior.json +57 -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/reproducible-dev-environments/SKILL.md +132 -0
- package/skills/reproducible-dev-environments/evals/triggers.json +16 -0
- package/skills/responding-to-code-review/SKILL.md +124 -0
- package/skills/responding-to-code-review/evals/behavior.json +54 -0
- package/skills/responding-to-code-review/evals/triggers.json +16 -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/behavior.json +56 -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/behavior.json +55 -0
- package/skills/session-handoff/evals/triggers.json +14 -0
- package/skills/skill-authoring/SKILL.md +98 -0
- package/skills/skill-authoring/evals/triggers.json +15 -0
- package/skills/skill-authoring/references/frontmatter.md +40 -0
- package/skills/skill-authoring/references/pressure-testing.md +87 -0
- package/skills/slack-app-integration/SKILL.md +108 -0
- package/skills/slack-app-integration/evals/triggers.json +17 -0
- package/skills/slide-decks/SKILL.md +107 -0
- package/skills/slide-decks/evals/triggers.json +18 -0
- package/skills/slide-decks/references/html-decks.md +86 -0
- package/skills/slide-decks/references/layouts.md +45 -0
- package/skills/slide-decks/references/pptx.md +87 -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/subagent-driven-development/SKILL.md +109 -0
- package/skills/subagent-driven-development/evals/behavior.json +53 -0
- package/skills/subagent-driven-development/evals/triggers.json +15 -0
- package/skills/subagent-driven-development/references/implementer-brief.md +60 -0
- package/skills/subagent-driven-development/references/reviewer-briefs.md +52 -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/systematic-debugging/SKILL.md +92 -0
- package/skills/systematic-debugging/evals/behavior.json +59 -0
- package/skills/systematic-debugging/evals/triggers.json +16 -0
- package/skills/systematic-debugging/references/condition-waiting.md +52 -0
- package/skills/systematic-debugging/references/root-cause-tracing.md +49 -0
- package/skills/systematic-debugging/references/test-pollution.md +46 -0
- package/skills/tdd-workflow/SKILL.md +69 -0
- package/skills/tdd-workflow/evals/behavior.json +55 -0
- package/skills/tdd-workflow/evals/triggers.json +15 -0
- package/skills/tdd-workflow/references/testing-anti-patterns.md +87 -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/transactional-email/SKILL.md +68 -0
- package/skills/transactional-email/evals/triggers.json +17 -0
- package/skills/transactional-email/references/providers.md +63 -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/ui-demo-recording/SKILL.md +93 -0
- package/skills/ui-demo-recording/evals/triggers.json +16 -0
- package/skills/ui-demo-recording/references/cursor-and-captions.md +48 -0
- package/skills/ui-demo-recording/references/playwright-recording.md +63 -0
- package/skills/ui-demo-recording/references/post-processing.md +57 -0
- package/skills/ui-design-polish/SKILL.md +113 -0
- package/skills/ui-design-polish/evals/triggers.json +18 -0
- package/skills/ui-design-polish/references/detail-checklist.md +45 -0
- package/skills/ui-design-polish/references/tokens.md +68 -0
- package/skills/ui-flow-audit/SKILL.md +112 -0
- package/skills/ui-flow-audit/evals/triggers.json +17 -0
- package/skills/ui-motion/SKILL.md +103 -0
- package/skills/ui-motion/evals/triggers.json +18 -0
- package/skills/ui-motion/references/patterns.md +138 -0
- package/skills/ui-motion/references/tokens.md +52 -0
- package/skills/unicode-text-processing/SKILL.md +103 -0
- package/skills/unicode-text-processing/evals/triggers.json +17 -0
- package/skills/unicode-text-processing/references/apis.md +89 -0
- package/skills/unicode-text-processing/references/script-notes.md +50 -0
- package/skills/verification-loop/SKILL.md +70 -0
- package/skills/verification-loop/evals/behavior.json +52 -0
- package/skills/verification-loop/evals/triggers.json +14 -0
- package/skills/verification-loop/scripts/detect-checks.js +102 -0
- package/skills/video-editing/SKILL.md +111 -0
- package/skills/video-editing/evals/triggers.json +16 -0
- package/skills/video-editing/references/edl-and-logging.md +44 -0
- package/skills/video-editing/references/ffmpeg-edit-recipes.md +92 -0
- package/skills/video-editing/references/resolve-scripting.md +53 -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,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"should_trigger": [
|
|
3
|
+
"Our Hibernate entities trigger hundreds of selects when loading the order list, fix the N+1",
|
|
4
|
+
"Getting LazyInitializationException: could not initialize proxy - no Session when mapping to DTO",
|
|
5
|
+
"Add @Version optimistic locking to the JPA Account entity and return 409 on conflicts",
|
|
6
|
+
"How should I map a one-to-many between Order and OrderLine in JPA with cascade and orphan removal?",
|
|
7
|
+
"Replace spring.jpa.hibernate.ddl-auto=update with Flyway migrations for our entities",
|
|
8
|
+
"MultipleBagFetchException when I join fetch two lists in a JPQL query"
|
|
9
|
+
],
|
|
10
|
+
"should_not_trigger": [
|
|
11
|
+
"Add a new REST endpoint to our Spring Boot order service with request validation and proper 404 responses",
|
|
12
|
+
"Tune this slow PostgreSQL query plan and suggest indexes",
|
|
13
|
+
"Set up Prisma schema and migrations for our Node backend",
|
|
14
|
+
"Configure EF Core migrations and fix the tracking issue in our ASP.NET Core app",
|
|
15
|
+
"Plan a zero-downtime schema migration strategy for our Rails app",
|
|
16
|
+
"Write an Exposed DSL query in our Ktor service to list users"
|
|
17
|
+
]
|
|
18
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# JPA mapping examples
|
|
2
|
+
|
|
3
|
+
Jakarta Persistence 3.x / Hibernate 6. Adjust imports to `javax.persistence` on Hibernate 5.
|
|
4
|
+
|
|
5
|
+
## Parent with owned children
|
|
6
|
+
|
|
7
|
+
```java
|
|
8
|
+
@Entity
|
|
9
|
+
@Table(name = "orders")
|
|
10
|
+
public class Order {
|
|
11
|
+
@Id
|
|
12
|
+
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "orders_seq")
|
|
13
|
+
@SequenceGenerator(name = "orders_seq", sequenceName = "orders_seq", allocationSize = 50)
|
|
14
|
+
private Long id;
|
|
15
|
+
|
|
16
|
+
@Version
|
|
17
|
+
private long version;
|
|
18
|
+
|
|
19
|
+
@Enumerated(EnumType.STRING)
|
|
20
|
+
@Column(nullable = false, length = 20)
|
|
21
|
+
private OrderStatus status;
|
|
22
|
+
|
|
23
|
+
@Column(nullable = false, precision = 19, scale = 2)
|
|
24
|
+
private BigDecimal total;
|
|
25
|
+
|
|
26
|
+
@ManyToOne(fetch = FetchType.LAZY, optional = false)
|
|
27
|
+
@JoinColumn(name = "customer_id", nullable = false)
|
|
28
|
+
private Customer customer;
|
|
29
|
+
|
|
30
|
+
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
|
|
31
|
+
private Set<OrderLine> lines = new HashSet<>();
|
|
32
|
+
|
|
33
|
+
protected Order() {}
|
|
34
|
+
|
|
35
|
+
public void addLine(OrderLine line) { lines.add(line); line.setOrder(this); }
|
|
36
|
+
public void removeLine(OrderLine line) { lines.remove(line); line.setOrder(null); }
|
|
37
|
+
|
|
38
|
+
@Override public boolean equals(Object o) {
|
|
39
|
+
if (this == o) return true;
|
|
40
|
+
if (!(o instanceof Order other)) return false;
|
|
41
|
+
return id != null && id.equals(other.id);
|
|
42
|
+
}
|
|
43
|
+
@Override public int hashCode() { return getClass().hashCode(); }
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`allocationSize` must match the sequence's `INCREMENT BY` in the migration, or ids collide or Hibernate fails validation.
|
|
48
|
+
|
|
49
|
+
## Matching Flyway migration
|
|
50
|
+
|
|
51
|
+
```sql
|
|
52
|
+
-- V3__create_orders.sql
|
|
53
|
+
create sequence orders_seq start with 1 increment by 50;
|
|
54
|
+
|
|
55
|
+
create table orders (
|
|
56
|
+
id bigint primary key,
|
|
57
|
+
version bigint not null default 0,
|
|
58
|
+
status varchar(20) not null,
|
|
59
|
+
total numeric(19, 2) not null,
|
|
60
|
+
customer_id bigint not null references customers (id)
|
|
61
|
+
);
|
|
62
|
+
create index idx_orders_customer_id on orders (customer_id);
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Spring Data: entity graph and projection
|
|
66
|
+
|
|
67
|
+
```java
|
|
68
|
+
public interface OrderRepository extends JpaRepository<Order, Long> {
|
|
69
|
+
|
|
70
|
+
@EntityGraph(attributePaths = {"customer", "lines"})
|
|
71
|
+
Optional<Order> findWithLinesById(Long id);
|
|
72
|
+
|
|
73
|
+
@Query("select new com.acme.orders.OrderRow(o.id, c.name, o.total) " +
|
|
74
|
+
"from Order o join o.customer c where o.status = :status")
|
|
75
|
+
Page<OrderRow> findRows(@Param("status") OrderStatus status, Pageable pageable);
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Paging a collection fetch without in-memory paging
|
|
80
|
+
|
|
81
|
+
```java
|
|
82
|
+
List<Long> ids = em.createQuery(
|
|
83
|
+
"select o.id from Order o where o.status = :status order by o.id", Long.class)
|
|
84
|
+
.setParameter("status", status)
|
|
85
|
+
.setFirstResult(page * size)
|
|
86
|
+
.setMaxResults(size)
|
|
87
|
+
.getResultList();
|
|
88
|
+
|
|
89
|
+
List<Order> orders = em.createQuery(
|
|
90
|
+
"select distinct o from Order o join fetch o.lines where o.id in :ids order by o.id", Order.class)
|
|
91
|
+
.setParameter("ids", ids)
|
|
92
|
+
.getResultList();
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Kotlin notes
|
|
96
|
+
|
|
97
|
+
- Apply the `kotlin("plugin.jpa")` (no-arg) and `kotlin("plugin.allopen")` plugins, with `allOpen { annotation("jakarta.persistence.Entity") }` so lazy proxies work.
|
|
98
|
+
- Use a regular `class` with `var` properties, not a `data class`.
|
|
99
|
+
- Collections: `val lines: MutableSet<OrderLine> = mutableSetOf()`.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: jvm-sql-mappers
|
|
3
|
+
description: Writes and reviews SQL-first data access on the JVM without an ORM session, using MyBatis XML or annotation mappers with dynamic SQL and resultMaps, jOOQ's generated typesafe DSL, or Kotlin Exposed DSL and DAO tables, plus explicit transaction boundaries, HikariCP pool sizing, JDBC batch inserts and loading child rows without one query per parent. Use when a Java or Kotlin service uses MyBatis, jOOQ or Exposed rather than JPA, a mapper or query builder produces the wrong or slow SQL, ${} string substitution needs auditing for injection, bulk inserts are slow, or the connection pool times out under load.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Any Agent Skills host. Needs the project's JDK build tool (Gradle or Maven) and its test runner; integration tests need the target database, ideally through Testcontainers.
|
|
6
|
+
metadata:
|
|
7
|
+
kete-loom/version: "0.1.0"
|
|
8
|
+
kete-loom/category: coding
|
|
9
|
+
kete-loom/risk: runs-commands
|
|
10
|
+
kete-loom/owner: "Kete-org"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# JVM SQL mappers: MyBatis, jOOQ, Exposed
|
|
14
|
+
|
|
15
|
+
You write the SQL (or a typed DSL of it) and the library maps rows to objects. No lazy loading and no dirty checking: what you query is what runs. For JPA or Hibernate entities use the JPA skill instead.
|
|
16
|
+
|
|
17
|
+
## 0. Before you start
|
|
18
|
+
|
|
19
|
+
1. Identify the library and version from the build file (`org.mybatis`, `mybatis-spring-boot-starter`, `org.jooq`, `org.jetbrains.exposed`) and the database and driver.
|
|
20
|
+
2. Exposed 1.0 moved packages to `org.jetbrains.exposed.v1.*` (core, jdbc, r2dbc, dao). Check which the project imports and follow the docs for that major version.
|
|
21
|
+
3. Find how transactions are managed: Spring `@Transactional`, jOOQ `transaction { }`, Exposed `transaction { }`, or manual `SqlSession`.
|
|
22
|
+
4. Run the existing tests once. Turn on SQL logging (MyBatis `logImpl`, jOOQ `executeLogging`, Exposed `addLogger(StdOutSqlLogger)`) while you work so you see the real statements.
|
|
23
|
+
|
|
24
|
+
Read `references/examples.md` for complete mapper, DSL and batching snippets.
|
|
25
|
+
|
|
26
|
+
## 1. Rules for every library
|
|
27
|
+
|
|
28
|
+
1. **Bind every value.** Values go in as bind parameters: MyBatis `#{param}`, jOOQ `DSL.val`/typed conditions, Exposed column comparisons. Never build SQL by string concatenation.
|
|
29
|
+
2. **Identifiers that must be dynamic** (sort column, table suffix) come from an allow-list in code, never from the request. This is the only acceptable use of MyBatis `${}` or jOOQ `DSL.field(name(...))` from input.
|
|
30
|
+
3. **Select only the columns you use.** No `select *` in mappers; it breaks when columns are added and wastes I/O.
|
|
31
|
+
4. **One transaction per unit of work**, started at the service layer, short, and never open across a remote call or user think time.
|
|
32
|
+
5. **Paginate** with keyset (`WHERE id > :last ORDER BY id LIMIT :n`) for large or deep lists; `OFFSET` only for small pages.
|
|
33
|
+
6. **Schema changes** go through migrations (Flyway or Liquibase), never `SchemaUtils.create` or `ddl` at app start in production.
|
|
34
|
+
|
|
35
|
+
## 2. MyBatis
|
|
36
|
+
|
|
37
|
+
- Put SQL in mapper XML (namespace = mapper interface) or annotations for one-liners. Map with explicit `<resultMap>`; turn on `mapUnderscoreToCamelCase` only if the project already relies on it.
|
|
38
|
+
- Dynamic SQL: `<where>` (drops leading AND/OR), `<if test>`, `<choose>/<when>/<otherwise>`, `<set>` for partial updates, `<foreach>` for `IN` lists. An empty list in `<foreach>` produces `IN ()`: guard it with `<if test="ids != null and !ids.isEmpty()">` or return early in code.
|
|
39
|
+
- Audit every `${}`: each one must be an allow-listed identifier. Replace any other with `#{}`.
|
|
40
|
+
- Avoid N+1: a nested `<collection select="...">` runs one query per parent. Prefer a join with a nested `<collection>` resultMap (with `<id>` columns so rows collapse correctly), or load children in a second query with `IN (...)` and group in code.
|
|
41
|
+
- Batching: open the session with `ExecutorType.BATCH` (or a separate batch `SqlSessionTemplate` in Spring), call the insert in a loop, `flushStatements()` every 500 to 1000 rows, commit once. A multi-row `<foreach>` `INSERT ... VALUES` works for moderate sizes but hits parameter limits on large ones.
|
|
42
|
+
- Generated keys: `useGeneratedKeys="true" keyProperty="id"`.
|
|
43
|
+
|
|
44
|
+
## 3. jOOQ
|
|
45
|
+
|
|
46
|
+
- Generate code from the real schema (the jOOQ codegen plugin against a migrated database, or from Flyway scripts via the DDL database) and commit the config, not hand-written table classes.
|
|
47
|
+
- Use one `DSLContext` configured with the pool's `DataSource` and the correct `SQLDialect`.
|
|
48
|
+
- Fetch into records or projections: `fetchInto(Dto.class)`, `fetch(Records.mapping(Dto::new))`.
|
|
49
|
+
- Nested children without N+1: `multiset(select(...).from(CHILD).where(CHILD.PARENT_ID.eq(PARENT.ID)))` mapped with `convertFrom`, or a join plus `fetchGroups`.
|
|
50
|
+
- Transactions: `dsl.transaction(cfg -> { DSL.using(cfg)... })`, or Spring's transaction manager if jOOQ is wired with Spring Boot's starter. Do not mix both styles in one call path.
|
|
51
|
+
- Batching: `dsl.batchInsert(records)` or `dsl.batch(query).bind(...).bind(...).execute()`; for very large loads, the Loader API (`loadInto`).
|
|
52
|
+
- Plain SQL templates (`DSL.field("...")`) are an escape hatch; pass values as `{0}` bind arguments, never concatenated.
|
|
53
|
+
|
|
54
|
+
## 4. Kotlin Exposed
|
|
55
|
+
|
|
56
|
+
- DSL: `object Users : LongIdTable("users") { val email = varchar("email", 255).uniqueIndex() }`; query with `Users.selectAll().where { Users.email eq e }`.
|
|
57
|
+
- DAO: `class User(id: EntityID<Long>) : LongEntity(id) { companion object : LongEntityClass<User>(Users) }`. DAO references are lazy: load children eagerly with `.with(User::orders)` or `load(...)` to avoid N+1.
|
|
58
|
+
- Every query runs inside `transaction(db) { }`. With coroutines on JDBC, use `suspendTransaction { }` on Exposed 1.x (`newSuspendedTransaction` on 0.x, deprecated in 1.0). It takes no `CoroutineContext`, so call it inside `withContext(Dispatchers.IO) { }`; blocking JDBC must not run on `Dispatchers.Default` or the main thread. For non-blocking drivers use the `exposed-r2dbc` module.
|
|
59
|
+
- Batching: `Users.batchInsert(rows) { row -> this[Users.email] = row.email }`.
|
|
60
|
+
- For any of the three libraries, JDBC batches only become multi-row inserts if the driver rewrites them: add `rewriteBatchedStatements=true` to a MySQL Connector/J URL, `reWriteBatchedInserts=true` to a PostgreSQL (pgjdbc) URL.
|
|
61
|
+
- Spring: use the Exposed Spring starter's transaction manager so `@Transactional` and `transaction {}` share a connection.
|
|
62
|
+
|
|
63
|
+
## 5. HikariCP
|
|
64
|
+
|
|
65
|
+
- Start small: `maximumPoolSize` about 10 per instance (the default) and raise it only with evidence. Total connections across all instances must stay under the database's limit minus admin headroom.
|
|
66
|
+
- Set `maxLifetime` (default 30 min) a little shorter than any database, proxy or firewall connection cutoff. `keepaliveTime` (default 2 min in current releases, minimum 30 s) must be shorter than any idle cutoff; lower it only if a firewall drops idle connections sooner.
|
|
67
|
+
- `connectionTimeout` (default 30 s) is how long a caller waits for a connection. Timeouts under load usually mean long transactions or leaked connections, not a small pool: set `leakDetectionThreshold` (off by default, minimum 2000 ms; for example 60000 ms) in staging to find the leak.
|
|
68
|
+
- Defaults above are from the current HikariCP README; earlier releases had `keepaliveTime` off (0) by default, so check the version in use.
|
|
69
|
+
|
|
70
|
+
## 6. Verify
|
|
71
|
+
|
|
72
|
+
1. Integration tests run against the same database engine (Testcontainers), not H2 standing in for PostgreSQL or MySQL.
|
|
73
|
+
2. For each changed query, log the generated SQL and run `EXPLAIN` on it with realistic data; confirm it uses the intended index.
|
|
74
|
+
3. For N+1 fixes, assert the statement count in a test (a counting `DataSource` proxy or the library's listener), not just the result.
|
|
75
|
+
4. For batching, time a load of 10,000 rows before and after.
|
|
76
|
+
5. Run the full test suite.
|
|
77
|
+
|
|
78
|
+
## Stop and ask the user
|
|
79
|
+
|
|
80
|
+
- A dynamic identifier cannot be allow-listed because callers pass arbitrary column names.
|
|
81
|
+
- A fix needs a schema change or a new index on a large production table.
|
|
82
|
+
- Switching libraries (for example MyBatis to jOOQ) or major versions.
|
|
83
|
+
|
|
84
|
+
## Never
|
|
85
|
+
|
|
86
|
+
- Never use `${}` or string concatenation with request data.
|
|
87
|
+
- Never hold a transaction or connection open across an HTTP call or message wait.
|
|
88
|
+
- Never raise the pool size to hide a connection leak.
|
|
89
|
+
|
|
90
|
+
## Report back
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
Library / DB: <MyBatis|jOOQ|Exposed version>, <database>
|
|
94
|
+
Changed queries: <mapper or method> | <problem> | <fix> | <statements before/after>
|
|
95
|
+
Injection audit: <each ${} or plain-SQL use and its status>
|
|
96
|
+
Pool: <settings changed and why>
|
|
97
|
+
Tests: <command> -> <result>; EXPLAIN checked for: <queries>
|
|
98
|
+
```
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"should_trigger": [
|
|
3
|
+
"Our MyBatis mapper uses ${orderBy} from the request, make it injection-safe",
|
|
4
|
+
"The MyBatis nested collection select runs one query per order, fix the N+1",
|
|
5
|
+
"Load orders with their line items in one jOOQ query using multiset",
|
|
6
|
+
"Bulk inserting 50k rows with Kotlin Exposed takes minutes, speed it up with batchInsert",
|
|
7
|
+
"HikariCP 'Connection is not available, request timed out after 30000ms' under load in our jOOQ service"
|
|
8
|
+
],
|
|
9
|
+
"should_not_trigger": [
|
|
10
|
+
"Fix LazyInitializationException on a Hibernate @OneToMany association",
|
|
11
|
+
"Our Postgres query is slow, read this EXPLAIN ANALYZE output",
|
|
12
|
+
"Add a Flyway migration for a new column in our Spring Data JPA entity",
|
|
13
|
+
"Write a Ktor route that returns JSON with kotlinx.serialization",
|
|
14
|
+
"Fix N+1 queries in our EF Core DbContext with Include"
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Examples: MyBatis, jOOQ, Exposed
|
|
2
|
+
|
|
3
|
+
Each snippet shows one pattern from SKILL.md. Adapt names to the project; check the API against the docs for the library version in use.
|
|
4
|
+
|
|
5
|
+
## MyBatis: dynamic search with a safe sort column
|
|
6
|
+
|
|
7
|
+
```xml
|
|
8
|
+
<mapper namespace="com.example.order.OrderMapper">
|
|
9
|
+
<resultMap id="orderWithLines" type="com.example.order.Order">
|
|
10
|
+
<id property="id" column="o_id"/>
|
|
11
|
+
<result property="status" column="o_status"/>
|
|
12
|
+
<collection property="lines" ofType="com.example.order.OrderLine">
|
|
13
|
+
<id property="id" column="l_id"/>
|
|
14
|
+
<result property="sku" column="l_sku"/>
|
|
15
|
+
<result property="quantity" column="l_qty"/>
|
|
16
|
+
</collection>
|
|
17
|
+
</resultMap>
|
|
18
|
+
|
|
19
|
+
<select id="search" resultMap="orderWithLines">
|
|
20
|
+
SELECT o.id o_id, o.status o_status, l.id l_id, l.sku l_sku, l.quantity l_qty
|
|
21
|
+
FROM orders o LEFT JOIN order_lines l ON l.order_id = o.id
|
|
22
|
+
<where>
|
|
23
|
+
<if test="status != null">AND o.status = #{status}</if>
|
|
24
|
+
<if test="customerIds != null and !customerIds.isEmpty()">
|
|
25
|
+
AND o.customer_id IN
|
|
26
|
+
<foreach item="cid" collection="customerIds" open="(" separator="," close=")">#{cid}</foreach>
|
|
27
|
+
</if>
|
|
28
|
+
</where>
|
|
29
|
+
ORDER BY ${sortColumn}, o.id
|
|
30
|
+
</select>
|
|
31
|
+
</mapper>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```java
|
|
35
|
+
// The only ${} input: chosen from a fixed map, never from the raw request.
|
|
36
|
+
private static final Map<String, String> SORTS = Map.of("created", "o.created_at", "total", "o.total");
|
|
37
|
+
String sortColumn = SORTS.getOrDefault(request.sort(), "o.created_at");
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Joins with collections multiply rows; paginate parents first (select the page of order ids, then join lines for those ids).
|
|
41
|
+
|
|
42
|
+
## MyBatis: batch insert
|
|
43
|
+
|
|
44
|
+
```java
|
|
45
|
+
try (SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH)) {
|
|
46
|
+
OrderLineMapper mapper = session.getMapper(OrderLineMapper.class);
|
|
47
|
+
int n = 0;
|
|
48
|
+
for (OrderLine line : lines) {
|
|
49
|
+
mapper.insert(line);
|
|
50
|
+
if (++n % 500 == 0) session.flushStatements();
|
|
51
|
+
}
|
|
52
|
+
session.commit();
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
In Spring, define a second `SqlSessionTemplate` with `ExecutorType.BATCH` and use it inside the service's `@Transactional` method.
|
|
57
|
+
|
|
58
|
+
## jOOQ: parent with children in one query
|
|
59
|
+
|
|
60
|
+
```java
|
|
61
|
+
List<OrderDto> orders = dsl
|
|
62
|
+
.select(
|
|
63
|
+
ORDERS.ID, ORDERS.STATUS,
|
|
64
|
+
multiset(
|
|
65
|
+
select(ORDER_LINES.SKU, ORDER_LINES.QUANTITY)
|
|
66
|
+
.from(ORDER_LINES)
|
|
67
|
+
.where(ORDER_LINES.ORDER_ID.eq(ORDERS.ID))
|
|
68
|
+
).convertFrom(r -> r.map(Records.mapping(LineDto::new))))
|
|
69
|
+
.from(ORDERS)
|
|
70
|
+
.where(ORDERS.CUSTOMER_ID.eq(customerId))
|
|
71
|
+
.orderBy(ORDERS.ID)
|
|
72
|
+
.limit(50)
|
|
73
|
+
.fetch(Records.mapping(OrderDto::new));
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## jOOQ: transaction and batch
|
|
77
|
+
|
|
78
|
+
```java
|
|
79
|
+
dsl.transaction(cfg -> {
|
|
80
|
+
DSLContext tx = DSL.using(cfg);
|
|
81
|
+
tx.batchInsert(lineRecords).execute();
|
|
82
|
+
tx.update(ORDERS).set(ORDERS.STATUS, "READY").where(ORDERS.ID.eq(orderId)).execute();
|
|
83
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Exposed: DSL query, eager DAO load, batch insert (1.x packages)
|
|
87
|
+
|
|
88
|
+
```kotlin
|
|
89
|
+
import org.jetbrains.exposed.v1.core.and
|
|
90
|
+
import org.jetbrains.exposed.v1.core.dao.id.LongIdTable
|
|
91
|
+
import org.jetbrains.exposed.v1.core.eq
|
|
92
|
+
import org.jetbrains.exposed.v1.jdbc.transactions.transaction
|
|
93
|
+
import org.jetbrains.exposed.v1.jdbc.batchInsert
|
|
94
|
+
import org.jetbrains.exposed.v1.jdbc.selectAll
|
|
95
|
+
|
|
96
|
+
object Orders : LongIdTable("orders") {
|
|
97
|
+
val customerId = long("customer_id").index()
|
|
98
|
+
val status = varchar("status", 20)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
fun openOrders(customer: Long) = transaction {
|
|
102
|
+
Orders.selectAll()
|
|
103
|
+
.where { (Orders.customerId eq customer) and (Orders.status eq "OPEN") }
|
|
104
|
+
.map { it[Orders.id].value to it[Orders.status] }
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
fun saveLines(lines: List<LineInput>) = transaction {
|
|
108
|
+
OrderLines.batchInsert(lines) { line ->
|
|
109
|
+
this[OrderLines.orderId] = line.orderId
|
|
110
|
+
this[OrderLines.sku] = line.sku
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
DAO eager loading: `Order.find { Orders.customerId eq id }.with(Order::lines)`.
|
|
116
|
+
|
|
117
|
+
Import paths above follow the Exposed 1.0 migration guide (core table types under `v1.core`, JDBC operations under `v1.jdbc`); confirm each import in the docs for the exact version, and use the 0.x `org.jetbrains.exposed.sql.*` packages if the project has not migrated.
|
|
118
|
+
|
|
119
|
+
## HikariCP (Spring Boot properties)
|
|
120
|
+
|
|
121
|
+
```properties
|
|
122
|
+
spring.datasource.hikari.maximum-pool-size=10
|
|
123
|
+
spring.datasource.hikari.connection-timeout=30000
|
|
124
|
+
spring.datasource.hikari.max-lifetime=1500000
|
|
125
|
+
spring.datasource.hikari.keepalive-time=300000
|
|
126
|
+
spring.datasource.hikari.leak-detection-threshold=60000
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
`max-lifetime` here assumes an infrastructure idle cutoff above 25 minutes; set it below whatever your database or proxy enforces. Leak detection is for staging and diagnosis; it logs a stack trace for connections held longer than the threshold.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kotlin-multiplatform
|
|
3
|
+
description: Sets up and evolves Kotlin Multiplatform (KMP) and Compose Multiplatform projects, covering the shared module and source-set layout (commonMain, androidMain, iosMain), expect/actual versus interfaces with injected platform implementations, choosing multiplatform-ready libraries, exporting a framework to Xcode, exposing suspend functions and Flows to Swift, and Gradle build setup for Android and iOS targets. Use when starting or restructuring a KMP shared module, deciding what code to share between Android and iOS, adding a platform-specific API behind expect/actual, wiring the shared framework into an Xcode project, or sharing UI with Compose Multiplatform.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Any Agent Skills host. Needs a JDK and the Gradle wrapper; building iOS targets needs macOS with Xcode.
|
|
6
|
+
metadata:
|
|
7
|
+
kete-loom/version: "0.1.0"
|
|
8
|
+
kete-loom/category: coding
|
|
9
|
+
kete-loom/risk: runs-commands
|
|
10
|
+
kete-loom/requires: "java"
|
|
11
|
+
kete-loom/owner: "Kete-org"
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Kotlin Multiplatform
|
|
15
|
+
|
|
16
|
+
Share the code that is the same on every platform, keep platform code behind a small seam, and keep the iOS side pleasant to call from Swift. Single-platform Kotlin idioms belong to `kotlin-patterns`; Android-only Compose UI belongs to `jetpack-compose-patterns`; native iOS UI belongs to `swiftui-patterns`.
|
|
17
|
+
|
|
18
|
+
## 0. Before you change anything
|
|
19
|
+
|
|
20
|
+
1. Read `settings.gradle.kts`, the shared module's `build.gradle.kts` and `gradle/libs.versions.toml`: Kotlin version, targets declared in `kotlin { }`, Android plugin in use, and whether Compose Multiplatform (`org.jetbrains.compose`) is applied.
|
|
21
|
+
2. Find how iOS consumes the shared code: a framework built by an Xcode run-script phase (`embedAndSignAppleFrameworkForXcode`), CocoaPods (`kotlin("native.cocoapods")`), or Swift Package Manager via an XCFramework.
|
|
22
|
+
3. Run `./gradlew build` (or `:shared:allTests`) once and record the result. On a machine without Xcode, iOS tasks will be skipped or fail; say so in your report.
|
|
23
|
+
|
|
24
|
+
## 1. What to share
|
|
25
|
+
|
|
26
|
+
Decision rule:
|
|
27
|
+
|
|
28
|
+
1. **Share**: domain models, business rules, validation, networking (Ktor client), persistence (SQLDelight, Room KMP), serialization (`kotlinx.serialization`), repositories and ViewModel-level presentation logic.
|
|
29
|
+
2. **Share UI with Compose Multiplatform** only when the team accepts a non-native-looking iOS UI or has designed for it. Compose Multiplatform for iOS has been stable since 1.8.0.
|
|
30
|
+
3. **Keep native**: platform UI the user expects (iOS system navigation, widgets, extensions), and anything that needs deep platform APIs.
|
|
31
|
+
|
|
32
|
+
**Stop and ask the user** before moving existing native UI into Compose Multiplatform or moving a large existing module into shared code.
|
|
33
|
+
|
|
34
|
+
## 2. Module and source-set structure
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
shared/
|
|
38
|
+
src/commonMain/kotlin/ # pure Kotlin, multiplatform libraries only
|
|
39
|
+
src/commonTest/kotlin/ # kotlin.test tests that run on every target
|
|
40
|
+
src/androidMain/kotlin/ # Android actuals, Android SDK allowed
|
|
41
|
+
src/iosMain/kotlin/ # shared by iosArm64 + iosSimulatorArm64 (+ iosX64)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
- Rely on the default hierarchy template: declaring `iosArm64()` and `iosSimulatorArm64()` gives you an `iosMain` source set automatically. Don't hand-wire `dependsOn` unless the project already does.
|
|
45
|
+
- `commonMain` must never import `android.*`, `java.*` or `platform.*`. If it needs one, that's a seam (section 3).
|
|
46
|
+
- For larger apps, split by feature (`:shared:feature-auth`, `:shared:core-network`) and export only an umbrella module to iOS, because each exported framework carries its own copy of the Kotlin runtime.
|
|
47
|
+
- Android: new KMP library modules use the Android-KMP library plugin (`com.android.kotlin.multiplatform.library`). Configure the Android target inside `kotlin { }` with `android { namespace = ...; compileSdk = ...; minSdk = ... }` on AGP 8.12+, or `androidLibrary { }` on older AGP (`androidLibrary` is deprecated in newer AGP). Applying `com.android.library` to a KMP module relies on AGP APIs that need an opt-in from AGP 9.0 and are planned for removal in AGP 10; migrate only when the user agrees.
|
|
48
|
+
|
|
49
|
+
## 3. expect/actual vs interfaces
|
|
50
|
+
|
|
51
|
+
Prefer, in this order:
|
|
52
|
+
|
|
53
|
+
1. **A multiplatform library** that already wraps the API (Ktor, `kotlinx-datetime`, `multiplatform-settings`, Okio).
|
|
54
|
+
2. **An interface in `commonMain`** implemented per platform and injected (Koin or constructor injection). Best for anything stateful or that needs mocking in tests; iOS implementations can even be written in Swift and passed in.
|
|
55
|
+
3. **`expect fun` / `expect val`** for small, stateless platform facts (`expect fun platformName(): String`, a UUID or clock).
|
|
56
|
+
4. **`expect class`** last. expect/actual classes are still Beta and need the compiler opt-in the build reports when you use them.
|
|
57
|
+
|
|
58
|
+
Every `expect` needs an `actual` in each target's source set (or an intermediate set like `iosMain`). Keep actuals thin: translate and delegate, no business logic.
|
|
59
|
+
|
|
60
|
+
## 4. Platform dependencies
|
|
61
|
+
|
|
62
|
+
- Put each dependency in the narrowest source set: `commonMain.dependencies { }` for multiplatform libraries, `androidMain.dependencies { }` / `iosMain.dependencies { }` for platform engines (for example `ktor-client-okhttp` vs `ktor-client-darwin`).
|
|
63
|
+
- Before adding a library to `commonMain`, check its published targets include every target you declare (look for iOS artifacts on Maven Central or klibs.io).
|
|
64
|
+
- Use the version catalog; don't hard-code versions in build scripts.
|
|
65
|
+
- Calling Apple frameworks from Kotlin goes through the `platform.*` cinterop bindings in `iosMain`; CocoaPods or custom cinterop are only for third-party native libraries.
|
|
66
|
+
|
|
67
|
+
## 5. iOS interop
|
|
68
|
+
|
|
69
|
+
- Configure the framework once:
|
|
70
|
+
|
|
71
|
+
```kotlin
|
|
72
|
+
listOf(iosArm64(), iosSimulatorArm64()).forEach {
|
|
73
|
+
it.binaries.framework { baseName = "Shared"; isStatic = true }
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
- Kotlin `suspend` functions appear in Swift as async functions or completion handlers, and Flows arrive as plain objects that are awkward to collect. For a Swift-friendly API, use SKIE or KMP-NativeCoroutines if the project allows a plugin; otherwise expose a small callback wrapper (`fun watch(onEach: (T) -> Unit): Closeable`).
|
|
77
|
+
- Sealed classes and enums lose exhaustiveness in Swift without such tooling. Keep the Swift-facing API small and explicit: one facade per feature.
|
|
78
|
+
- Kotlin exceptions crossing into Swift crash unless declared with `@Throws`. Annotate every public suspend or throwing function exported to iOS, or return a result type.
|
|
79
|
+
- Keep all shared code that touches UI-observable state on the main dispatcher when called from Swift.
|
|
80
|
+
- After a shared-code change, rebuild the iOS app from Xcode (or `xcodebuild`) to prove the framework links.
|
|
81
|
+
|
|
82
|
+
## 6. Build setup and checks
|
|
83
|
+
|
|
84
|
+
- Use the same Kotlin version for the Kotlin, Compose compiler and serialization plugins; mismatches are the most common build failure.
|
|
85
|
+
- Common tests go in `commonTest` with `kotlin.test`; run `./gradlew :shared:allTests` (or the project's task) so they run on JVM/Android and iOS simulator.
|
|
86
|
+
- Commit `gradle/libs.versions.toml`, the Gradle wrapper and the Xcode project changes together.
|
|
87
|
+
|
|
88
|
+
## Never
|
|
89
|
+
|
|
90
|
+
- Never import a platform package from `commonMain`.
|
|
91
|
+
- Never put business logic in an `actual`.
|
|
92
|
+
- Never export every Gradle module to iOS as its own framework.
|
|
93
|
+
- Never let an undeclared exception cross the Kotlin/Swift boundary.
|
|
94
|
+
|
|
95
|
+
## Report back
|
|
96
|
+
|
|
97
|
+
End with: modules and source sets changed, each new expect/actual or injected interface, Gradle tasks run (and whether iOS targets actually built on this machine), and anything the iOS team must change in Xcode.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"should_trigger": [
|
|
3
|
+
"Set up a KMP shared module so our Android and iOS apps share the networking layer",
|
|
4
|
+
"How do I use expect/actual to read the device UUID on iOS and Android?",
|
|
5
|
+
"Swift can't collect the Flow exported from our Kotlin Multiplatform framework",
|
|
6
|
+
"Should we share the UI with Compose Multiplatform or keep SwiftUI on iOS?",
|
|
7
|
+
"commonMain keeps failing because it imports java.time, how should I restructure this?"
|
|
8
|
+
],
|
|
9
|
+
"should_not_trigger": [
|
|
10
|
+
"Write a Kotlin data class with a sealed result type for this Android repository",
|
|
11
|
+
"Add a Jetpack Compose bottom sheet to the Android settings screen",
|
|
12
|
+
"Build a SwiftUI onboarding flow with a NavigationStack",
|
|
13
|
+
"Fix the Gradle error: Could not resolve com.squareup.okhttp3 in the Android app",
|
|
14
|
+
"Share business logic between iOS and Android using a Flutter plugin"
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kotlin-patterns
|
|
3
|
+
description: Idiomatic Kotlin for JVM and Android code, covering null safety without !!, data and sealed classes with exhaustive when, restrained extension functions, structured concurrency with coroutine scopes and dispatchers, cold Flow versus StateFlow and SharedFlow, Result and exception handling, and Gradle Kotlin DSL build scripts with version catalogs. Use when writing or restructuring Kotlin code, modelling state with sealed hierarchies, choosing a coroutine scope or dispatcher, exposing data as a Flow, or editing build.gradle.kts files.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Any Agent Skills host. Needs the project's Gradle wrapper (or Maven) and a JDK to build and test.
|
|
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
|
+
# Kotlin patterns
|
|
14
|
+
|
|
15
|
+
Write Kotlin that the compiler can check: nullability in the types, states in sealed hierarchies, concurrency tied to a scope. Follow the project's existing style first; these rules settle what it does not.
|
|
16
|
+
|
|
17
|
+
## 0. Before you write
|
|
18
|
+
|
|
19
|
+
1. Find the Kotlin version, JVM target and build tool: search `gradle/libs.versions.toml`, `build.gradle.kts` and `settings.gradle.kts`. Do not use language or library features newer than that version.
|
|
20
|
+
2. Check whether the code is Android (an `com.android.*` plugin is applied) or plain JVM. Android code must never block the main thread.
|
|
21
|
+
3. Find the existing conventions: error type (exceptions, `Result`, a sealed `Outcome`), DI framework, coroutine scopes in use, and the lint/format tool (ktlint, detekt, Spotless). Match them.
|
|
22
|
+
|
|
23
|
+
## 1. Null safety
|
|
24
|
+
|
|
25
|
+
- Model absence in the type (`String?`) only when absence is a real state. Otherwise make it non-null and validate at the boundary.
|
|
26
|
+
- Never use `!!` in new code. Replace it with, in order of preference:
|
|
27
|
+
1. a non-null type, so the question never arises;
|
|
28
|
+
2. `?: return`, `?: continue` or `?: throw IllegalStateException("why")` with a message;
|
|
29
|
+
3. `requireNotNull(x) { "message" }` for arguments, `checkNotNull(x) { "message" }` for state.
|
|
30
|
+
- Use `?.let { }` for a short side effect, not as a general `if`. Two nested `?.let` blocks mean an early return reads better.
|
|
31
|
+
- `lateinit var` only for values a framework sets before first use (DI fields, test setup). Never for values that can legitimately be missing.
|
|
32
|
+
- Java interop: values from unannotated Java APIs are platform types (`String!`). Give them an explicit Kotlin type at the call site (`val name: String? = javaObj.name`) so a null fails where it enters, not three calls later. For strict JSR-305 annotations, the compiler flag is `-Xjsr305=strict`.
|
|
33
|
+
|
|
34
|
+
## 2. Data, value and sealed types
|
|
35
|
+
|
|
36
|
+
- `data class` for value holders with structural equality. Keep properties `val`; use `copy()` to change them. Do not put mutable collections in them.
|
|
37
|
+
- `@JvmInline value class` to give a primitive a meaning (`UserId(val raw: String)`) without allocation.
|
|
38
|
+
- `sealed interface` (or `sealed class` when subtypes share state) for closed sets of states or results:
|
|
39
|
+
|
|
40
|
+
```kotlin
|
|
41
|
+
sealed interface LoadState<out T> {
|
|
42
|
+
data object Loading : LoadState<Nothing>
|
|
43
|
+
data class Loaded<T>(val value: T) : LoadState<T>
|
|
44
|
+
data class Failed(val cause: Throwable) : LoadState<Nothing>
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
fun render(state: LoadState<User>) = when (state) {
|
|
48
|
+
LoadState.Loading -> showSpinner()
|
|
49
|
+
is LoadState.Loaded -> show(state.value)
|
|
50
|
+
is LoadState.Failed -> showError(state.cause)
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
- `data object` needs Kotlin 1.9 or later; on older versions use a plain `object`.
|
|
55
|
+
- Use `when` as an expression over a sealed type with no `else` branch, so adding a subtype is a compile error at every call site.
|
|
56
|
+
- `enum class` when the cases carry no per-instance data.
|
|
57
|
+
|
|
58
|
+
## 3. Functions and extensions
|
|
59
|
+
|
|
60
|
+
- Prefer expression bodies for one-expression functions, named and default arguments over overloads, and `val` over `var`.
|
|
61
|
+
- Write an extension function only when it reads as a natural operation on that type and is used in more than one place. Keep it `private` or `internal` unless it is part of a public API. Never add extensions on `Any`, `String` or other broad types for one call site.
|
|
62
|
+
- Scope functions: `apply` to configure an object, `also` for a side effect, `let` for a nullable or a transform, `run`/`with` sparingly. Do not nest them.
|
|
63
|
+
- Collections: return read-only `List`/`Map` types; keep `MutableList` private. Use `Sequence` only for long pipelines over large inputs.
|
|
64
|
+
|
|
65
|
+
## 4. Coroutines and structured concurrency
|
|
66
|
+
|
|
67
|
+
Rules that prevent leaks and freezes:
|
|
68
|
+
|
|
69
|
+
1. Every coroutine has an owner scope with a lifecycle: `viewModelScope`, `lifecycleScope`, a scope injected into a class that cancels it on shutdown, or `coroutineScope { }` inside a suspend function.
|
|
70
|
+
2. Never use `GlobalScope` in production code. Never create `CoroutineScope(Job())` in a class without a matching `cancel()`.
|
|
71
|
+
3. Suspend functions are main-safe: the function that blocks switches dispatcher itself with `withContext(Dispatchers.IO)` (blocking I/O) or `withContext(Dispatchers.Default)` (CPU work). Callers never have to know.
|
|
72
|
+
4. Inject dispatchers (constructor parameter with a default) so tests can replace them.
|
|
73
|
+
5. Never call `runBlocking` on the main thread or inside a coroutine. It is for `main()` and bridging blocking APIs at the edge.
|
|
74
|
+
6. Never swallow `CancellationException`. If you catch `Exception` or `Throwable` in suspend code, rethrow cancellation:
|
|
75
|
+
|
|
76
|
+
```kotlin
|
|
77
|
+
try { repo.sync() }
|
|
78
|
+
catch (e: CancellationException) { throw e }
|
|
79
|
+
catch (e: IOException) { log.warn("sync failed", e) }
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
7. Use `coroutineScope` when one child failing should cancel siblings, and `supervisorScope` when children are independent. Parallel work: `coroutineScope { val a = async { f() }; val b = async { g() }; a.await() to b.await() }`.
|
|
83
|
+
8. Long loops must be cancellable: call `ensureActive()` or a suspending function each iteration.
|
|
84
|
+
|
|
85
|
+
## 5. Flow
|
|
86
|
+
|
|
87
|
+
- A `Flow` is cold: it runs once per collector. Expose `Flow` from repositories, `StateFlow` for UI state, `SharedFlow` for events.
|
|
88
|
+
- Keep mutable flows private: `private val _state = MutableStateFlow(UiState())` and `val state: StateFlow<UiState> = _state.asStateFlow()`. Update with `_state.update { it.copy(...) }`, never read-modify-write.
|
|
89
|
+
- Convert cold to hot with `stateIn(scope, SharingStarted.WhileSubscribed(5_000), initial)` so the upstream stops when nobody listens.
|
|
90
|
+
- Move upstream work off the main thread with `flowOn(Dispatchers.IO)`. Never call `emit` from inside `withContext` or `launch` within `flow { }`: it throws `IllegalStateException` (Flow invariant is violated). Use `flowOn`, or `channelFlow` when you need concurrent emitters. A `withContext` that returns a value you then emit outside it is fine.
|
|
91
|
+
- Collect on Android with `repeatOnLifecycle(Lifecycle.State.STARTED)` (or `collectAsStateWithLifecycle()` in Compose) so collection stops in the background.
|
|
92
|
+
- `collect` suspends until the flow ends. Two `collect` calls in a row in one coroutine means the second never runs for an infinite flow: launch each in its own coroutine.
|
|
93
|
+
- Pick the operator on purpose: `map`, `filter`, `combine`, `flatMapLatest` (cancel previous), `debounce`, `distinctUntilChanged`. Handle errors with `catch { }` upstream of `collect`.
|
|
94
|
+
|
|
95
|
+
## 6. Error handling
|
|
96
|
+
|
|
97
|
+
- Exceptions for programming errors and truly unexpected failures; `require`/`check`/`error()` for preconditions.
|
|
98
|
+
- For expected domain failures, return a sealed result type the caller must handle. Use the project's existing type if there is one.
|
|
99
|
+
- `runCatching` also catches `CancellationException`; do not use it around suspend calls unless you rethrow cancellation.
|
|
100
|
+
- Never catch and ignore. Log with context or convert to a domain error.
|
|
101
|
+
|
|
102
|
+
## 7. Gradle Kotlin DSL
|
|
103
|
+
|
|
104
|
+
- Keep versions in `gradle/libs.versions.toml` and reference them as `libs.foo`, `alias(libs.plugins.foo)`. Do not hard-code versions in module scripts.
|
|
105
|
+
- Set the JDK with `kotlin { jvmToolchain(17) }` (use the project's version) rather than `sourceCompatibility` alone.
|
|
106
|
+
- Compiler options go in `kotlin { compilerOptions { ... } }`, for example `freeCompilerArgs.add("-Xjsr305=strict")` or `allWarningsAsErrors.set(true)`.
|
|
107
|
+
- Shared build logic goes in convention plugins (`build-logic/` or `buildSrc/`), not copy-pasted blocks.
|
|
108
|
+
- Prefer KSP (`com.google.devtools.ksp`, `ksp(...)`) over kapt for processors that support it.
|
|
109
|
+
- Keep the Kotlin Gradle plugin, KSP, Compose compiler and Android Gradle Plugin versions compatible; check the official compatibility tables before bumping one.
|
|
110
|
+
- Run builds through the wrapper: `./gradlew build`.
|
|
111
|
+
|
|
112
|
+
## 8. Check your work
|
|
113
|
+
|
|
114
|
+
1. Build and test: `./gradlew build` (or the module task, e.g. `./gradlew :app:testDebugUnitTest`).
|
|
115
|
+
2. Run the project's linter if configured (`./gradlew ktlintCheck`, `./gradlew detekt`, `./gradlew spotlessCheck`).
|
|
116
|
+
3. Search your diff for `!!`, `GlobalScope`, `runBlocking` and `catch (e: Exception)` and justify or remove each.
|
|
117
|
+
|
|
118
|
+
## Stop and ask the user
|
|
119
|
+
|
|
120
|
+
- Before changing a public API signature other modules or apps call.
|
|
121
|
+
- Before bumping the Kotlin, AGP or Gradle version to use a feature.
|
|
122
|
+
- When the project mixes error styles and you would have to pick one for a new module.
|
|
123
|
+
|
|
124
|
+
## Report back
|
|
125
|
+
|
|
126
|
+
List the files changed, the build and lint commands you ran with their result, and any `!!`, `runBlocking` or broad catch you kept, with the reason.
|
|
127
|
+
|
|
128
|
+
For tests, use the `kotlin-testing` skill. For a review of existing changes, the `kotlin-reviewer` agent. For compile or Gradle failures, the `kotlin-build-resolver` agent.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"should_trigger": [
|
|
3
|
+
"Model the checkout screen state in Kotlin as a sealed interface with loading, success and error cases",
|
|
4
|
+
"This Kotlin repository class has !! everywhere, rewrite it with proper null safety",
|
|
5
|
+
"Which dispatcher should my suspend function use for the database call, and who should own the coroutine scope?",
|
|
6
|
+
"Expose the user list from my Android ViewModel as a StateFlow instead of LiveData",
|
|
7
|
+
"Move our hard-coded dependency versions in build.gradle.kts into a libs.versions.toml catalog"
|
|
8
|
+
],
|
|
9
|
+
"should_not_trigger": [
|
|
10
|
+
"Add a test that checks my Kotlin repository retries twice before failing",
|
|
11
|
+
"Go through the Kotlin PR my teammate opened and flag any risky coroutine code",
|
|
12
|
+
"The Android build broke with a Duplicate class error after adding a library",
|
|
13
|
+
"Build the settings screen in Jetpack Compose with a lazy list",
|
|
14
|
+
"Share the networking layer between Android and iOS with Kotlin Multiplatform"
|
|
15
|
+
]
|
|
16
|
+
}
|