cfsa-antigravity 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.mjs +324 -0
- package/package.json +34 -0
- package/template/.agent/instructions/commands.md +48 -0
- package/template/.agent/instructions/patterns.md +61 -0
- package/template/.agent/instructions/structure.md +29 -0
- package/template/.agent/instructions/tech-stack.md +43 -0
- package/template/.agent/instructions/workflow.md +41 -0
- package/template/.agent/kit-sync.md +15 -0
- package/template/.agent/rules/boundary-not-placeholder.md +146 -0
- package/template/.agent/rules/completion-checklist.md +48 -0
- package/template/.agent/rules/decision-classification.md +103 -0
- package/template/.agent/rules/extensibility.md +47 -0
- package/template/.agent/rules/question-vs-command.md +81 -0
- package/template/.agent/rules/security-first.md +43 -0
- package/template/.agent/rules/specificity-standards.md +54 -0
- package/template/.agent/rules/tdd-contract-first.md +57 -0
- package/template/.agent/rules/vertical-slices.md +42 -0
- package/template/.agent/skill-library/MANIFEST.md +480 -0
- package/template/.agent/skill-library/README.md +38 -0
- package/template/.agent/skill-library/meta/brand-guidelines/SKILL.md +73 -0
- package/template/.agent/skill-library/meta/claude-code/README.md +9 -0
- package/template/.agent/skill-library/meta/claude-code/agent-development/SKILL.md +415 -0
- package/template/.agent/skill-library/meta/claude-code/hook-development/SKILL.md +712 -0
- package/template/.agent/skill-library/meta/claude-code/plugin-structure/SKILL.md +476 -0
- package/template/.agent/skill-library/meta/git-advanced/SKILL.md +972 -0
- package/template/.agent/skill-library/meta/mcp-builder/SKILL.md +236 -0
- package/template/.agent/skill-library/meta/product-marketing-context/SKILL.md +241 -0
- package/template/.agent/skill-library/meta/regex-patterns/SKILL.md +751 -0
- package/template/.agent/skill-library/meta/tmux-processes/SKILL.md +210 -0
- package/template/.agent/skill-library/meta/using-tmux-for-interactive-commands/SKILL.md +178 -0
- package/template/.agent/skill-library/stack/3d/threejs-pro/SKILL.md +300 -0
- package/template/.agent/skill-library/stack/ai/ai-sdk/SKILL.md +77 -0
- package/template/.agent/skill-library/stack/ai/langchain/SKILL.md +530 -0
- package/template/.agent/skill-library/stack/ai/ollama/SKILL.md +321 -0
- package/template/.agent/skill-library/stack/ai/openai-sdk/SKILL.md +549 -0
- package/template/.agent/skill-library/stack/analytics/google-analytics/SKILL.md +153 -0
- package/template/.agent/skill-library/stack/api/graphql/SKILL.md +1061 -0
- package/template/.agent/skill-library/stack/api/trpc/SKILL.md +576 -0
- package/template/.agent/skill-library/stack/auth/authjs/SKILL.md +569 -0
- package/template/.agent/skill-library/stack/auth/clerk/SKILL.md +590 -0
- package/template/.agent/skill-library/stack/auth/firebase-auth/SKILL.md +734 -0
- package/template/.agent/skill-library/stack/cms/payload-cms/SKILL.md +573 -0
- package/template/.agent/skill-library/stack/cms/shopify/SKILL.md +1193 -0
- package/template/.agent/skill-library/stack/cms/wordpress/SKILL.md +1104 -0
- package/template/.agent/skill-library/stack/css/sass-scss/SKILL.md +1121 -0
- package/template/.agent/skill-library/stack/css/tailwind-css-patterns/SKILL.md +863 -0
- package/template/.agent/skill-library/stack/css/tailwind-design-system/SKILL.md +490 -0
- package/template/.agent/skill-library/stack/css/vanilla-css/SKILL.md +1078 -0
- package/template/.agent/skill-library/stack/databases/clickhouse/SKILL.md +311 -0
- package/template/.agent/skill-library/stack/databases/influxdb/SKILL.md +280 -0
- package/template/.agent/skill-library/stack/databases/lancedb/SKILL.md +415 -0
- package/template/.agent/skill-library/stack/databases/mongodb/SKILL.md +1169 -0
- package/template/.agent/skill-library/stack/databases/neo4j/SKILL.md +839 -0
- package/template/.agent/skill-library/stack/databases/pgvector/SKILL.md +241 -0
- package/template/.agent/skill-library/stack/databases/pinecone/SKILL.md +212 -0
- package/template/.agent/skill-library/stack/databases/postgresql/SKILL.md +658 -0
- package/template/.agent/skill-library/stack/databases/qdrant/SKILL.md +312 -0
- package/template/.agent/skill-library/stack/databases/redis/SKILL.md +1079 -0
- package/template/.agent/skill-library/stack/databases/spacetimedb/SKILL.md +532 -0
- package/template/.agent/skill-library/stack/databases/sqlite/SKILL.md +1132 -0
- package/template/.agent/skill-library/stack/databases/supabase/SKILL.md +640 -0
- package/template/.agent/skill-library/stack/databases/surrealdb-expert/SKILL.md +945 -0
- package/template/.agent/skill-library/stack/databases/timescaledb/SKILL.md +745 -0
- package/template/.agent/skill-library/stack/databases/weaviate/SKILL.md +218 -0
- package/template/.agent/skill-library/stack/devops/github-actions/SKILL.md +554 -0
- package/template/.agent/skill-library/stack/devops/kubernetes/SKILL.md +950 -0
- package/template/.agent/skill-library/stack/devops/nginx/SKILL.md +841 -0
- package/template/.agent/skill-library/stack/devops/terraform/SKILL.md +860 -0
- package/template/.agent/skill-library/stack/email/resend/SKILL.md +391 -0
- package/template/.agent/skill-library/stack/engines/godot/SKILL.md +488 -0
- package/template/.agent/skill-library/stack/extensions/chrome-extension/SKILL.md +375 -0
- package/template/.agent/skill-library/stack/extensions/vscode-extension/SKILL.md +453 -0
- package/template/.agent/skill-library/stack/frameworks/astro-framework/SKILL.md +162 -0
- package/template/.agent/skill-library/stack/frameworks/electron/SKILL.md +1286 -0
- package/template/.agent/skill-library/stack/frameworks/fastapi/SKILL.md +650 -0
- package/template/.agent/skill-library/stack/frameworks/hono/SKILL.md +90 -0
- package/template/.agent/skill-library/stack/frameworks/nestjs/SKILL.md +878 -0
- package/template/.agent/skill-library/stack/frameworks/nextjs/SKILL.md +635 -0
- package/template/.agent/skill-library/stack/frameworks/nuxt/SKILL.md +564 -0
- package/template/.agent/skill-library/stack/frameworks/sveltekit/SKILL.md +614 -0
- package/template/.agent/skill-library/stack/frameworks/tauri/SKILL.md +920 -0
- package/template/.agent/skill-library/stack/gamedev/godot/SKILL.md +1032 -0
- package/template/.agent/skill-library/stack/gamedev/unity/SKILL.md +1175 -0
- package/template/.agent/skill-library/stack/hosting/aws/SKILL.md +467 -0
- package/template/.agent/skill-library/stack/hosting/cloudflare/SKILL.md +201 -0
- package/template/.agent/skill-library/stack/hosting/docker-expert/SKILL.md +409 -0
- package/template/.agent/skill-library/stack/hosting/vercel/SKILL.md +484 -0
- package/template/.agent/skill-library/stack/languages/bash-scripting/SKILL.md +773 -0
- package/template/.agent/skill-library/stack/languages/c-cpp/SKILL.md +712 -0
- package/template/.agent/skill-library/stack/languages/gdscript/SKILL.md +789 -0
- package/template/.agent/skill-library/stack/languages/go/SKILL.md +664 -0
- package/template/.agent/skill-library/stack/languages/java/SKILL.md +778 -0
- package/template/.agent/skill-library/stack/languages/kotlin/SKILL.md +665 -0
- package/template/.agent/skill-library/stack/languages/python/SKILL.md +678 -0
- package/template/.agent/skill-library/stack/languages/rust/SKILL.md +673 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/SKILL.md +141 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/advanced-generics.md +90 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/branded-types.md +57 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/builder-pattern.md +71 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/common-pitfalls.md +135 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/conditional-types.md +27 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/decorators.md +98 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/discriminated-unions.md +62 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/mapped-types.md +53 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/performance-best-practices.md +104 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/template-literal-types.md +49 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/testing-types.md +112 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-guards.md +70 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-inference.md +101 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/utility-types.md +98 -0
- package/template/.agent/skill-library/stack/languages/vanilla-javascript/SKILL.md +803 -0
- package/template/.agent/skill-library/stack/messaging/kafka/SKILL.md +235 -0
- package/template/.agent/skill-library/stack/mobile/expo-react-native/SKILL.md +665 -0
- package/template/.agent/skill-library/stack/mobile/flutter/SKILL.md +316 -0
- package/template/.agent/skill-library/stack/mobile/react-native/SKILL.md +337 -0
- package/template/.agent/skill-library/stack/monitoring/posthog/SKILL.md +396 -0
- package/template/.agent/skill-library/stack/monitoring/sentry/SKILL.md +509 -0
- package/template/.agent/skill-library/stack/observability/datadog/SKILL.md +179 -0
- package/template/.agent/skill-library/stack/observability/distributed-tracing/SKILL.md +140 -0
- package/template/.agent/skill-library/stack/observability/logging-best-practices/SKILL.md +168 -0
- package/template/.agent/skill-library/stack/observability/opentelemetry/SKILL.md +164 -0
- package/template/.agent/skill-library/stack/observability/prometheus-grafana/SKILL.md +246 -0
- package/template/.agent/skill-library/stack/observability/python-observability/SKILL.md +158 -0
- package/template/.agent/skill-library/stack/orm/drizzle-orm/SKILL.md +613 -0
- package/template/.agent/skill-library/stack/orm/prisma/SKILL.md +744 -0
- package/template/.agent/skill-library/stack/payments/lemonsqueezy/SKILL.md +393 -0
- package/template/.agent/skill-library/stack/payments/stripe-integration/SKILL.md +457 -0
- package/template/.agent/skill-library/stack/queue/bullmq/SKILL.md +385 -0
- package/template/.agent/skill-library/stack/queue/inngest/SKILL.md +438 -0
- package/template/.agent/skill-library/stack/realtime/socketio/SKILL.md +595 -0
- package/template/.agent/skill-library/stack/search/elasticsearch/SKILL.md +248 -0
- package/template/.agent/skill-library/stack/search/meilisearch/SKILL.md +385 -0
- package/template/.agent/skill-library/stack/security/crypto-patterns/SKILL.md +437 -0
- package/template/.agent/skill-library/stack/security/csp-cors-headers/SKILL.md +588 -0
- package/template/.agent/skill-library/stack/security/dependency-auditing/SKILL.md +560 -0
- package/template/.agent/skill-library/stack/security/input-sanitization/SKILL.md +430 -0
- package/template/.agent/skill-library/stack/security/owasp-web-security/SKILL.md +421 -0
- package/template/.agent/skill-library/stack/state/tanstack-query/SKILL.md +637 -0
- package/template/.agent/skill-library/stack/state/zustand/SKILL.md +483 -0
- package/template/.agent/skill-library/stack/storage/aws-s3/SKILL.md +415 -0
- package/template/.agent/skill-library/stack/testing/playwright/SKILL.md +641 -0
- package/template/.agent/skill-library/stack/testing/storybook/SKILL.md +923 -0
- package/template/.agent/skill-library/stack/testing/testing-library/SKILL.md +872 -0
- package/template/.agent/skill-library/stack/testing/vitest/SKILL.md +714 -0
- package/template/.agent/skill-library/stack/ui/react-best-practices/SKILL.md +877 -0
- package/template/.agent/skill-library/stack/ui/react-composition-patterns/SKILL.md +1107 -0
- package/template/.agent/skill-library/stack/ui/react-flow/SKILL.md +425 -0
- package/template/.agent/skill-library/stack/ui/shadcn-ui/SKILL.md +703 -0
- package/template/.agent/skill-library/surface/api/api-caching/SKILL.md +458 -0
- package/template/.agent/skill-library/surface/api/api-documentation-openapi/SKILL.md +697 -0
- package/template/.agent/skill-library/surface/api/api-error-handling/SKILL.md +478 -0
- package/template/.agent/skill-library/surface/api/api-security-checklist/SKILL.md +147 -0
- package/template/.agent/skill-library/surface/api/api-versioning/SKILL.md +420 -0
- package/template/.agent/skill-library/surface/api/email-best-practices/SKILL.md +59 -0
- package/template/.agent/skill-library/surface/api/rate-limiting-abuse-protection/SKILL.md +147 -0
- package/template/.agent/skill-library/surface/api/rest-api-design/SKILL.md +478 -0
- package/template/.agent/skill-library/surface/api/webhook-design/SKILL.md +752 -0
- package/template/.agent/skill-library/surface/cli/cli-configuration-management/SKILL.md +445 -0
- package/template/.agent/skill-library/surface/cli/cli-error-diagnostics/SKILL.md +515 -0
- package/template/.agent/skill-library/surface/cli/cli-shell-integration/SKILL.md +479 -0
- package/template/.agent/skill-library/surface/cli/cli-ux-design/SKILL.md +477 -0
- package/template/.agent/skill-library/surface/desktop/desktop-app-distribution/SKILL.md +416 -0
- package/template/.agent/skill-library/surface/desktop/desktop-security-sandboxing/SKILL.md +407 -0
- package/template/.agent/skill-library/surface/desktop/desktop-ux-conventions/SKILL.md +361 -0
- package/template/.agent/skill-library/surface/desktop/native-os-integration/SKILL.md +563 -0
- package/template/.agent/skill-library/surface/extension/browser-extension-patterns/SKILL.md +482 -0
- package/template/.agent/skill-library/surface/extension/plugin-architecture-design/SKILL.md +632 -0
- package/template/.agent/skill-library/surface/extension/vscode-extension-development/SKILL.md +728 -0
- package/template/.agent/skill-library/surface/mobile/app-store-submission/SKILL.md +304 -0
- package/template/.agent/skill-library/surface/mobile/mobile-offline-sync/SKILL.md +443 -0
- package/template/.agent/skill-library/surface/mobile/mobile-responsive-patterns/SKILL.md +432 -0
- package/template/.agent/skill-library/surface/mobile/push-notifications/SKILL.md +495 -0
- package/template/.agent/skill-library/surface/web/accessibility-compliance/SKILL.md +827 -0
- package/template/.agent/skill-library/surface/web/ai-seo/SKILL.md +398 -0
- package/template/.agent/skill-library/surface/web/ai-seo/references/content-patterns.md +285 -0
- package/template/.agent/skill-library/surface/web/ai-seo/references/platform-ranking-factors.md +152 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/SKILL.md +309 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/event-library.md +260 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/ga4-implementation.md +300 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/gtm-implementation.md +390 -0
- package/template/.agent/skill-library/surface/web/authentication-ui-flows/SKILL.md +530 -0
- package/template/.agent/skill-library/surface/web/dark-mode-theming/SKILL.md +516 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/SKILL.md +105 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/charts.csv +26 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/colors.csv +97 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/landing.csv +31 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/styles.csv +59 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/typography.csv +58 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/ux-guidelines.csv +100 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/core.py +258 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/design_system.py +1067 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/search.py +106 -0
- package/template/.agent/skill-library/surface/web/form-handling-validation/SKILL.md +675 -0
- package/template/.agent/skill-library/surface/web/frontend-design/SKILL.md +1393 -0
- package/template/.agent/skill-library/surface/web/frontend-design/templates/cppn-hero.tsx +299 -0
- package/template/.agent/skill-library/surface/web/frontend-design/templates/wave-hero.tsx +875 -0
- package/template/.agent/skill-library/surface/web/frontend-verification/SKILL.md +111 -0
- package/template/.agent/skill-library/surface/web/frontend-verification/scripts/ux_audit.py +739 -0
- package/template/.agent/skill-library/surface/web/i18n-localization/SKILL.md +154 -0
- package/template/.agent/skill-library/surface/web/offline-first-pwa/SKILL.md +657 -0
- package/template/.agent/skill-library/surface/web/page-cro/SKILL.md +182 -0
- package/template/.agent/skill-library/surface/web/page-cro/references/experiments.md +248 -0
- package/template/.agent/skill-library/surface/web/programmatic-seo/SKILL.md +238 -0
- package/template/.agent/skill-library/surface/web/programmatic-seo/references/playbooks.md +308 -0
- package/template/.agent/skill-library/surface/web/schema-markup/SKILL.md +179 -0
- package/template/.agent/skill-library/surface/web/schema-markup/references/schema-examples.md +398 -0
- package/template/.agent/skill-library/surface/web/seo-audit/SKILL.md +394 -0
- package/template/.agent/skill-library/surface/web/seo-audit/references/ai-writing-detection.md +200 -0
- package/template/.agent/skill-library/surface/web/web-performance-optimization/SKILL.md +646 -0
- package/template/.agent/skill-library/surface/web/web-scraping/SKILL.md +58 -0
- package/template/.agent/skills/accessibility/SKILL.md +522 -0
- package/template/.agent/skills/accessibility/references/WCAG.md +162 -0
- package/template/.agent/skills/adversarial-review/SKILL.md +90 -0
- package/template/.agent/skills/antigravity-workflows/SKILL.md +81 -0
- package/template/.agent/skills/antigravity-workflows/resources/implementation-playbook.md +36 -0
- package/template/.agent/skills/api-design-principles/SKILL.md +37 -0
- package/template/.agent/skills/api-design-principles/assets/api-design-checklist.md +155 -0
- package/template/.agent/skills/api-design-principles/assets/rest-api-template.py +182 -0
- package/template/.agent/skills/api-design-principles/references/graphql-schema-design.md +583 -0
- package/template/.agent/skills/api-design-principles/references/rest-best-practices.md +408 -0
- package/template/.agent/skills/api-design-principles/resources/implementation-playbook.md +513 -0
- package/template/.agent/skills/api-versioning/SKILL.md +420 -0
- package/template/.agent/skills/architecture-mapping/SKILL.md +219 -0
- package/template/.agent/skills/bootstrap-agents/SKILL.md +259 -0
- package/template/.agent/skills/brainstorming/SKILL.md +236 -0
- package/template/.agent/skills/brand-guidelines/SKILL.md +44 -0
- package/template/.agent/skills/clean-code/SKILL.md +94 -0
- package/template/.agent/skills/code-review-pro/SKILL.md +152 -0
- package/template/.agent/skills/concise-planning/SKILL.md +68 -0
- package/template/.agent/skills/cross-layer-consistency/SKILL.md +117 -0
- package/template/.agent/skills/database-schema-design/SKILL.md +429 -0
- package/template/.agent/skills/deployment-procedures/SKILL.md +241 -0
- package/template/.agent/skills/design-anti-cliche/SKILL.md +159 -0
- package/template/.agent/skills/design-direction/SKILL.md +45 -0
- package/template/.agent/skills/error-handling-patterns/SKILL.md +721 -0
- package/template/.agent/skills/find-skills/SKILL.md +145 -0
- package/template/.agent/skills/git-advanced/SKILL.md +972 -0
- package/template/.agent/skills/git-workflow/SKILL.md +420 -0
- package/template/.agent/skills/idea-extraction/SKILL.md +271 -0
- package/template/.agent/skills/logging-best-practices/SKILL.md +851 -0
- package/template/.agent/skills/migration-management/SKILL.md +384 -0
- package/template/.agent/skills/minimalist-surgical-development/SKILL.md +69 -0
- package/template/.agent/skills/parallel-agents/SKILL.md +165 -0
- package/template/.agent/skills/parallel-debugging/SKILL.md +135 -0
- package/template/.agent/skills/parallel-feature-development/SKILL.md +166 -0
- package/template/.agent/skills/performance-budgeting/SKILL.md +144 -0
- package/template/.agent/skills/pipeline-rubrics/SKILL.md +51 -0
- package/template/.agent/skills/pipeline-rubrics/references/architecture-rubric.md +19 -0
- package/template/.agent/skills/pipeline-rubrics/references/be-rubric.md +21 -0
- package/template/.agent/skills/pipeline-rubrics/references/fe-rubric.md +20 -0
- package/template/.agent/skills/pipeline-rubrics/references/ia-rubric.md +19 -0
- package/template/.agent/skills/pipeline-rubrics/references/scoring.md +28 -0
- package/template/.agent/skills/pipeline-rubrics/references/vision-rubric.md +11 -0
- package/template/.agent/skills/prd-templates/SKILL.md +88 -0
- package/template/.agent/skills/prd-templates/references/architecture-design-template.md +88 -0
- package/template/.agent/skills/prd-templates/references/be-spec-template.md +101 -0
- package/template/.agent/skills/prd-templates/references/data-placement-template.md +74 -0
- package/template/.agent/skills/prd-templates/references/decomposition-templates.md +211 -0
- package/template/.agent/skills/prd-templates/references/design-system-decisions.md +198 -0
- package/template/.agent/skills/prd-templates/references/engineering-standards-template.md +124 -0
- package/template/.agent/skills/prd-templates/references/fe-classification-procedures.md +47 -0
- package/template/.agent/skills/prd-templates/references/fe-spec-template.md +84 -0
- package/template/.agent/skills/prd-templates/references/infrastructure-report-template.md +71 -0
- package/template/.agent/skills/prd-templates/references/operational-templates.md +116 -0
- package/template/.agent/skills/prd-templates/references/placeholder-guard-template.md +21 -0
- package/template/.agent/skills/prd-templates/references/surface-model.md +61 -0
- package/template/.agent/skills/prd-templates/references/vision-template.md +66 -0
- package/template/.agent/skills/prompt-engineer/README.md +659 -0
- package/template/.agent/skills/prompt-engineer/SKILL.md +249 -0
- package/template/.agent/skills/regex-patterns/SKILL.md +751 -0
- package/template/.agent/skills/resolve-ambiguity/SKILL.md +278 -0
- package/template/.agent/skills/rest-api-design/SKILL.md +478 -0
- package/template/.agent/skills/security-scanning-security-hardening/SKILL.md +231 -0
- package/template/.agent/skills/session-continuity/SKILL.md +730 -0
- package/template/.agent/skills/session-continuity/protocols/01-session-resumption.md +38 -0
- package/template/.agent/skills/session-continuity/protocols/02-progress-generation.md +85 -0
- package/template/.agent/skills/session-continuity/protocols/03-progress-update.md +70 -0
- package/template/.agent/skills/session-continuity/protocols/04-pattern-extraction.md +60 -0
- package/template/.agent/skills/session-continuity/protocols/05-session-close.md +37 -0
- package/template/.agent/skills/session-continuity/protocols/06-decision-analysis.md +84 -0
- package/template/.agent/skills/session-continuity/protocols/07-spec-pipeline-generation.md +48 -0
- package/template/.agent/skills/session-continuity/protocols/08-spec-pipeline-update.md +43 -0
- package/template/.agent/skills/session-continuity/protocols/09-parallel-claim.md +122 -0
- package/template/.agent/skills/session-continuity/protocols/10-placeholder-verification-gate.md +104 -0
- package/template/.agent/skills/session-continuity/protocols/ambiguity-gates.md +48 -0
- package/template/.agent/skills/skill-creator/LICENSE.txt +202 -0
- package/template/.agent/skills/skill-creator/README.md +270 -0
- package/template/.agent/skills/skill-creator/SKILL.md +590 -0
- package/template/.agent/skills/skill-creator/references/output-patterns.md +82 -0
- package/template/.agent/skills/skill-creator/references/workflows.md +28 -0
- package/template/.agent/skills/skill-creator/scripts/init_skill.py +303 -0
- package/template/.agent/skills/skill-creator/scripts/package_skill.py +110 -0
- package/template/.agent/skills/skill-creator/scripts/quick_validate.py +95 -0
- package/template/.agent/skills/spec-writing/SKILL.md +110 -0
- package/template/.agent/skills/systematic-debugging/CREATION-LOG.md +119 -0
- package/template/.agent/skills/systematic-debugging/SKILL.md +297 -0
- package/template/.agent/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/template/.agent/skills/systematic-debugging/condition-based-waiting.md +115 -0
- package/template/.agent/skills/systematic-debugging/defense-in-depth.md +122 -0
- package/template/.agent/skills/systematic-debugging/find-polluter.sh +63 -0
- package/template/.agent/skills/systematic-debugging/root-cause-tracing.md +169 -0
- package/template/.agent/skills/systematic-debugging/test-academic.md +14 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-1.md +58 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-2.md +68 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-3.md +69 -0
- package/template/.agent/skills/tdd-workflow/SKILL.md +409 -0
- package/template/.agent/skills/tech-stack-catalog/SKILL.md +49 -0
- package/template/.agent/skills/tech-stack-catalog/references/constraint-questions.md +21 -0
- package/template/.agent/skills/tech-stack-catalog/references/dev-tooling-decisions.md +37 -0
- package/template/.agent/skills/tech-stack-catalog/references/surface-decision-tables.md +69 -0
- package/template/.agent/skills/technical-writer/SKILL.md +242 -0
- package/template/.agent/skills/testing-strategist/SKILL.md +932 -0
- package/template/.agent/skills/verification-before-completion/SKILL.md +145 -0
- package/template/.agent/skills/workflow-automation/SKILL.md +73 -0
- package/template/.agent/workflows/audit-ambiguity-execute.md +165 -0
- package/template/.agent/workflows/audit-ambiguity-rubrics.md +83 -0
- package/template/.agent/workflows/audit-ambiguity.md +64 -0
- package/template/.agent/workflows/bootstrap-agents-fill.md +201 -0
- package/template/.agent/workflows/bootstrap-agents-provision.md +197 -0
- package/template/.agent/workflows/bootstrap-agents.md +66 -0
- package/template/.agent/workflows/create-prd-architecture.md +119 -0
- package/template/.agent/workflows/create-prd-compile.md +138 -0
- package/template/.agent/workflows/create-prd-design-system.md +135 -0
- package/template/.agent/workflows/create-prd-security.md +113 -0
- package/template/.agent/workflows/create-prd-stack.md +91 -0
- package/template/.agent/workflows/create-prd.md +168 -0
- package/template/.agent/workflows/decompose-architecture-structure.md +82 -0
- package/template/.agent/workflows/decompose-architecture-validate.md +119 -0
- package/template/.agent/workflows/decompose-architecture.md +111 -0
- package/template/.agent/workflows/evolve-contract.md +98 -0
- package/template/.agent/workflows/evolve-feature-cascade.md +140 -0
- package/template/.agent/workflows/evolve-feature-classify.md +116 -0
- package/template/.agent/workflows/evolve-feature.md +56 -0
- package/template/.agent/workflows/ideate-discover.md +144 -0
- package/template/.agent/workflows/ideate-extract.md +129 -0
- package/template/.agent/workflows/ideate-validate.md +117 -0
- package/template/.agent/workflows/ideate.md +113 -0
- package/template/.agent/workflows/implement-slice-setup.md +113 -0
- package/template/.agent/workflows/implement-slice-tdd.md +198 -0
- package/template/.agent/workflows/implement-slice.md +50 -0
- package/template/.agent/workflows/plan-phase.md +202 -0
- package/template/.agent/workflows/propagate-decision-apply.md +135 -0
- package/template/.agent/workflows/propagate-decision-scan.md +147 -0
- package/template/.agent/workflows/propagate-decision.md +56 -0
- package/template/.agent/workflows/remediate-pipeline-assess.md +138 -0
- package/template/.agent/workflows/remediate-pipeline-execute.md +135 -0
- package/template/.agent/workflows/remediate-pipeline.md +55 -0
- package/template/.agent/workflows/resolve-ambiguity.md +82 -0
- package/template/.agent/workflows/sync-kit.md +209 -0
- package/template/.agent/workflows/update-architecture-map.md +74 -0
- package/template/.agent/workflows/validate-phase.md +219 -0
- package/template/.agent/workflows/verify-infrastructure.md +207 -0
- package/template/.agent/workflows/write-architecture-spec-deepen.md +139 -0
- package/template/.agent/workflows/write-architecture-spec-design.md +202 -0
- package/template/.agent/workflows/write-architecture-spec.md +63 -0
- package/template/.agent/workflows/write-be-spec-classify.md +165 -0
- package/template/.agent/workflows/write-be-spec-write.md +98 -0
- package/template/.agent/workflows/write-be-spec.md +76 -0
- package/template/.agent/workflows/write-fe-spec-classify.md +170 -0
- package/template/.agent/workflows/write-fe-spec-write.md +94 -0
- package/template/.agent/workflows/write-fe-spec.md +71 -0
- package/template/AGENTS.md +176 -0
- package/template/GEMINI.md +177 -0
- package/template/docs/README.md +187 -0
- package/template/docs/audits/.gitkeep +0 -0
- package/template/docs/audits/README.md +10 -0
- package/template/docs/plans/.gitkeep +0 -0
- package/template/docs/plans/README.md +21 -0
- package/template/docs/plans/be/.gitkeep +0 -0
- package/template/docs/plans/be/README.md +11 -0
- package/template/docs/plans/fe/.gitkeep +0 -0
- package/template/docs/plans/fe/README.md +11 -0
- package/template/docs/plans/ia/.gitkeep +0 -0
- package/template/docs/plans/ia/README.md +17 -0
- package/template/docs/plans/ia/deep-dives/.gitkeep +0 -0
- package/template/docs/plans/ia/deep-dives/README.md +5 -0
- package/template/docs/plans/phases/.gitkeep +0 -0
- package/template/docs/plans/phases/README.md +11 -0
|
@@ -0,0 +1,664 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: go
|
|
3
|
+
description: Go development patterns for building reliable, scalable services. Covers error handling idioms, goroutines/channels, interfaces, context.Context, testing, go modules, HTTP handlers, middleware, and generics.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Go Development Patterns
|
|
8
|
+
|
|
9
|
+
Expert guidance for writing idiomatic, production-grade Go code. Covers error handling, concurrency with goroutines and channels, interface design, context propagation, table-driven tests, and the conventions that make Go codebases maintainable at scale.
|
|
10
|
+
|
|
11
|
+
## When to Use This Skill
|
|
12
|
+
|
|
13
|
+
- Building HTTP services, APIs, and microservices
|
|
14
|
+
- Writing CLI tools and system utilities
|
|
15
|
+
- Implementing concurrent data pipelines
|
|
16
|
+
- Creating libraries with clean, idiomatic APIs
|
|
17
|
+
- Building networked applications (gRPC, WebSocket, TCP)
|
|
18
|
+
- Developing cloud-native applications (Kubernetes operators, cloud functions)
|
|
19
|
+
|
|
20
|
+
## Core Concepts
|
|
21
|
+
|
|
22
|
+
### 1. Error Handling Idioms
|
|
23
|
+
|
|
24
|
+
Go uses explicit error returns instead of exceptions.
|
|
25
|
+
|
|
26
|
+
```go
|
|
27
|
+
// Basic error handling -- always check errors
|
|
28
|
+
func readFile(path string) ([]byte, error) {
|
|
29
|
+
data, err := os.ReadFile(path)
|
|
30
|
+
if err != nil {
|
|
31
|
+
return nil, fmt.Errorf("reading %s: %w", path, err)
|
|
32
|
+
}
|
|
33
|
+
return data, nil
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Wrapping errors with context (use %w for wrapping)
|
|
37
|
+
func loadConfig(path string) (*Config, error) {
|
|
38
|
+
data, err := readFile(path)
|
|
39
|
+
if err != nil {
|
|
40
|
+
return nil, fmt.Errorf("loadConfig: %w", err)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
var cfg Config
|
|
44
|
+
if err := json.Unmarshal(data, &cfg); err != nil {
|
|
45
|
+
return nil, fmt.Errorf("loadConfig: parsing JSON: %w", err)
|
|
46
|
+
}
|
|
47
|
+
return &cfg, nil
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Custom error types
|
|
51
|
+
type NotFoundError struct {
|
|
52
|
+
Resource string
|
|
53
|
+
ID string
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
func (e *NotFoundError) Error() string {
|
|
57
|
+
return fmt.Sprintf("%s %q not found", e.Resource, e.ID)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Checking error types with errors.Is and errors.As
|
|
61
|
+
func handleError(err error) {
|
|
62
|
+
var notFound *NotFoundError
|
|
63
|
+
if errors.As(err, ¬Found) {
|
|
64
|
+
// Handle not found specifically
|
|
65
|
+
log.Printf("Not found: %s %s", notFound.Resource, notFound.ID)
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
if errors.Is(err, os.ErrPermission) {
|
|
69
|
+
log.Printf("Permission denied")
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
// Generic error handling
|
|
73
|
+
log.Printf("Unexpected error: %v", err)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Sentinel errors for known conditions
|
|
77
|
+
var (
|
|
78
|
+
ErrNotFound = errors.New("not found")
|
|
79
|
+
ErrUnauthorized = errors.New("unauthorized")
|
|
80
|
+
ErrConflict = errors.New("conflict")
|
|
81
|
+
)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Rules:**
|
|
85
|
+
|
|
86
|
+
| Rule | Explanation |
|
|
87
|
+
|------|-------------|
|
|
88
|
+
| Always check `err != nil` | Never ignore returned errors |
|
|
89
|
+
| Wrap with `fmt.Errorf("context: %w", err)` | Add context while preserving the error chain |
|
|
90
|
+
| Use `errors.Is` for sentinel errors | Works through wrapped error chains |
|
|
91
|
+
| Use `errors.As` for typed errors | Extracts the specific error type |
|
|
92
|
+
| Return errors, do not panic | Panics are for programmer bugs, not runtime conditions |
|
|
93
|
+
|
|
94
|
+
### 2. Goroutines and Channels
|
|
95
|
+
|
|
96
|
+
```go
|
|
97
|
+
// Basic goroutine
|
|
98
|
+
func processItems(items []string) {
|
|
99
|
+
var wg sync.WaitGroup
|
|
100
|
+
for _, item := range items {
|
|
101
|
+
wg.Add(1)
|
|
102
|
+
go func(item string) {
|
|
103
|
+
defer wg.Done()
|
|
104
|
+
process(item)
|
|
105
|
+
}(item)
|
|
106
|
+
}
|
|
107
|
+
wg.Wait()
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Channels for communication
|
|
111
|
+
func pipeline(input <-chan int) <-chan int {
|
|
112
|
+
output := make(chan int)
|
|
113
|
+
go func() {
|
|
114
|
+
defer close(output)
|
|
115
|
+
for v := range input {
|
|
116
|
+
output <- v * 2
|
|
117
|
+
}
|
|
118
|
+
}()
|
|
119
|
+
return output
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Fan-out, fan-in pattern
|
|
123
|
+
func fanOut(input <-chan int, workers int) []<-chan int {
|
|
124
|
+
channels := make([]<-chan int, workers)
|
|
125
|
+
for i := 0; i < workers; i++ {
|
|
126
|
+
channels[i] = pipeline(input)
|
|
127
|
+
}
|
|
128
|
+
return channels
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
func fanIn(channels ...<-chan int) <-chan int {
|
|
132
|
+
var wg sync.WaitGroup
|
|
133
|
+
merged := make(chan int)
|
|
134
|
+
|
|
135
|
+
for _, ch := range channels {
|
|
136
|
+
wg.Add(1)
|
|
137
|
+
go func(c <-chan int) {
|
|
138
|
+
defer wg.Done()
|
|
139
|
+
for v := range c {
|
|
140
|
+
merged <- v
|
|
141
|
+
}
|
|
142
|
+
}(ch)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
go func() {
|
|
146
|
+
wg.Wait()
|
|
147
|
+
close(merged)
|
|
148
|
+
}()
|
|
149
|
+
|
|
150
|
+
return merged
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Select for multiplexing channels
|
|
154
|
+
func withTimeout(ch <-chan string, timeout time.Duration) (string, error) {
|
|
155
|
+
select {
|
|
156
|
+
case msg := <-ch:
|
|
157
|
+
return msg, nil
|
|
158
|
+
case <-time.After(timeout):
|
|
159
|
+
return "", fmt.Errorf("timed out after %v", timeout)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Buffered channels for rate limiting
|
|
164
|
+
func rateLimiter(requests <-chan Request, rps int) <-chan Request {
|
|
165
|
+
throttled := make(chan Request, rps)
|
|
166
|
+
ticker := time.NewTicker(time.Second / time.Duration(rps))
|
|
167
|
+
|
|
168
|
+
go func() {
|
|
169
|
+
defer close(throttled)
|
|
170
|
+
for req := range requests {
|
|
171
|
+
<-ticker.C
|
|
172
|
+
throttled <- req
|
|
173
|
+
}
|
|
174
|
+
ticker.Stop()
|
|
175
|
+
}()
|
|
176
|
+
|
|
177
|
+
return throttled
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Concurrency rules:**
|
|
182
|
+
|
|
183
|
+
| Rule | Explanation |
|
|
184
|
+
|------|-------------|
|
|
185
|
+
| Do not communicate by sharing memory | Share memory by communicating (channels) |
|
|
186
|
+
| Always close channels from the sender | Never close from the receiver |
|
|
187
|
+
| Use `sync.WaitGroup` for goroutine coordination | Prevents goroutine leaks |
|
|
188
|
+
| Use `context.Context` for cancellation | Propagates cancellation through call chains |
|
|
189
|
+
| Never start a goroutine without knowing how it stops | Every goroutine needs an exit strategy |
|
|
190
|
+
|
|
191
|
+
### 3. Interfaces
|
|
192
|
+
|
|
193
|
+
```go
|
|
194
|
+
// Small interfaces -- the Go way
|
|
195
|
+
type Reader interface {
|
|
196
|
+
Read(p []byte) (n int, err error)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
type Writer interface {
|
|
200
|
+
Write(p []byte) (n int, err error)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Compose interfaces
|
|
204
|
+
type ReadWriter interface {
|
|
205
|
+
Reader
|
|
206
|
+
Writer
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Accept interfaces, return structs
|
|
210
|
+
type UserStore interface {
|
|
211
|
+
GetUser(ctx context.Context, id string) (*User, error)
|
|
212
|
+
CreateUser(ctx context.Context, user *User) error
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
type postgresUserStore struct {
|
|
216
|
+
db *sql.DB
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
func NewUserStore(db *sql.DB) UserStore {
|
|
220
|
+
return &postgresUserStore{db: db}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
func (s *postgresUserStore) GetUser(ctx context.Context, id string) (*User, error) {
|
|
224
|
+
var user User
|
|
225
|
+
err := s.db.QueryRowContext(ctx,
|
|
226
|
+
"SELECT id, name, email FROM users WHERE id = $1", id,
|
|
227
|
+
).Scan(&user.ID, &user.Name, &user.Email)
|
|
228
|
+
if err == sql.ErrNoRows {
|
|
229
|
+
return nil, &NotFoundError{Resource: "user", ID: id}
|
|
230
|
+
}
|
|
231
|
+
if err != nil {
|
|
232
|
+
return nil, fmt.Errorf("getting user %s: %w", id, err)
|
|
233
|
+
}
|
|
234
|
+
return &user, nil
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Interface satisfaction is implicit -- no "implements" keyword
|
|
238
|
+
// This is checked at compile time when you use the interface
|
|
239
|
+
var _ UserStore = (*postgresUserStore)(nil) // Compile-time check
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
**Interface guidelines:**
|
|
243
|
+
|
|
244
|
+
| Guideline | Explanation |
|
|
245
|
+
|-----------|-------------|
|
|
246
|
+
| Keep interfaces small (1-3 methods) | Large interfaces are hard to implement and mock |
|
|
247
|
+
| Define interfaces where they are used | Not where the implementation lives |
|
|
248
|
+
| Accept interfaces, return concrete types | Maximizes flexibility for callers |
|
|
249
|
+
| Use `var _ Interface = (*Type)(nil)` | Compile-time interface satisfaction check |
|
|
250
|
+
|
|
251
|
+
### 4. context.Context
|
|
252
|
+
|
|
253
|
+
```go
|
|
254
|
+
// Always pass context as the first parameter
|
|
255
|
+
func GetUser(ctx context.Context, id string) (*User, error) {
|
|
256
|
+
// Check for cancellation
|
|
257
|
+
select {
|
|
258
|
+
case <-ctx.Done():
|
|
259
|
+
return nil, ctx.Err()
|
|
260
|
+
default:
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return store.GetUser(ctx, id)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Adding values to context (use sparingly)
|
|
267
|
+
type contextKey string
|
|
268
|
+
|
|
269
|
+
const requestIDKey contextKey = "requestID"
|
|
270
|
+
|
|
271
|
+
func WithRequestID(ctx context.Context, id string) context.Context {
|
|
272
|
+
return context.WithValue(ctx, requestIDKey, id)
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
func RequestIDFrom(ctx context.Context) string {
|
|
276
|
+
if id, ok := ctx.Value(requestIDKey).(string); ok {
|
|
277
|
+
return id
|
|
278
|
+
}
|
|
279
|
+
return ""
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Timeouts and deadlines
|
|
283
|
+
func fetchWithTimeout(ctx context.Context, url string) ([]byte, error) {
|
|
284
|
+
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
|
285
|
+
defer cancel() // Always defer cancel
|
|
286
|
+
|
|
287
|
+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
|
288
|
+
if err != nil {
|
|
289
|
+
return nil, err
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
resp, err := http.DefaultClient.Do(req)
|
|
293
|
+
if err != nil {
|
|
294
|
+
return nil, err
|
|
295
|
+
}
|
|
296
|
+
defer resp.Body.Close()
|
|
297
|
+
|
|
298
|
+
return io.ReadAll(resp.Body)
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
**Context rules:**
|
|
303
|
+
|
|
304
|
+
| Rule | Explanation |
|
|
305
|
+
|------|-------------|
|
|
306
|
+
| First parameter, named `ctx` | Convention: `func Foo(ctx context.Context, ...)` |
|
|
307
|
+
| Never store in a struct | Pass explicitly through function calls |
|
|
308
|
+
| `defer cancel()` always | Prevents context leak |
|
|
309
|
+
| Use `context.WithValue` sparingly | For request-scoped data only (request ID, auth token) |
|
|
310
|
+
| Never pass `nil` context | Use `context.Background()` or `context.TODO()` |
|
|
311
|
+
|
|
312
|
+
### 5. Testing
|
|
313
|
+
|
|
314
|
+
```go
|
|
315
|
+
// Basic test
|
|
316
|
+
func TestAdd(t *testing.T) {
|
|
317
|
+
got := Add(2, 3)
|
|
318
|
+
want := 5
|
|
319
|
+
if got != want {
|
|
320
|
+
t.Errorf("Add(2, 3) = %d, want %d", got, want)
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Table-driven tests -- the Go standard
|
|
325
|
+
func TestParseAge(t *testing.T) {
|
|
326
|
+
tests := []struct {
|
|
327
|
+
name string
|
|
328
|
+
input string
|
|
329
|
+
want int
|
|
330
|
+
wantErr bool
|
|
331
|
+
}{
|
|
332
|
+
{name: "valid age", input: "25", want: 25, wantErr: false},
|
|
333
|
+
{name: "zero", input: "0", want: 0, wantErr: false},
|
|
334
|
+
{name: "negative", input: "-1", want: 0, wantErr: true},
|
|
335
|
+
{name: "too large", input: "200", want: 0, wantErr: true},
|
|
336
|
+
{name: "non-numeric", input: "abc", want: 0, wantErr: true},
|
|
337
|
+
{name: "empty", input: "", want: 0, wantErr: true},
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
for _, tt := range tests {
|
|
341
|
+
t.Run(tt.name, func(t *testing.T) {
|
|
342
|
+
got, err := ParseAge(tt.input)
|
|
343
|
+
if (err != nil) != tt.wantErr {
|
|
344
|
+
t.Errorf("ParseAge(%q) error = %v, wantErr %v", tt.input, err, tt.wantErr)
|
|
345
|
+
return
|
|
346
|
+
}
|
|
347
|
+
if got != tt.want {
|
|
348
|
+
t.Errorf("ParseAge(%q) = %d, want %d", tt.input, got, tt.want)
|
|
349
|
+
}
|
|
350
|
+
})
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Subtests for shared setup
|
|
355
|
+
func TestUserStore(t *testing.T) {
|
|
356
|
+
db := setupTestDB(t)
|
|
357
|
+
store := NewUserStore(db)
|
|
358
|
+
|
|
359
|
+
t.Run("create", func(t *testing.T) {
|
|
360
|
+
user := &User{Name: "Alice", Email: "alice@example.com"}
|
|
361
|
+
err := store.CreateUser(context.Background(), user)
|
|
362
|
+
if err != nil {
|
|
363
|
+
t.Fatalf("CreateUser: %v", err)
|
|
364
|
+
}
|
|
365
|
+
})
|
|
366
|
+
|
|
367
|
+
t.Run("get", func(t *testing.T) {
|
|
368
|
+
user, err := store.GetUser(context.Background(), "1")
|
|
369
|
+
if err != nil {
|
|
370
|
+
t.Fatalf("GetUser: %v", err)
|
|
371
|
+
}
|
|
372
|
+
if user.Name != "Alice" {
|
|
373
|
+
t.Errorf("Name = %q, want %q", user.Name, "Alice")
|
|
374
|
+
}
|
|
375
|
+
})
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Test helpers
|
|
379
|
+
func setupTestDB(t *testing.T) *sql.DB {
|
|
380
|
+
t.Helper()
|
|
381
|
+
db, err := sql.Open("sqlite3", ":memory:")
|
|
382
|
+
if err != nil {
|
|
383
|
+
t.Fatalf("opening test db: %v", err)
|
|
384
|
+
}
|
|
385
|
+
t.Cleanup(func() { db.Close() })
|
|
386
|
+
return db
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// Benchmarks
|
|
390
|
+
func BenchmarkProcess(b *testing.B) {
|
|
391
|
+
data := generateTestData()
|
|
392
|
+
b.ResetTimer()
|
|
393
|
+
for i := 0; i < b.N; i++ {
|
|
394
|
+
Process(data)
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### 6. HTTP Handlers and Middleware
|
|
400
|
+
|
|
401
|
+
```go
|
|
402
|
+
// Handler function
|
|
403
|
+
func handleGetUser(store UserStore) http.HandlerFunc {
|
|
404
|
+
return func(w http.ResponseWriter, r *http.Request) {
|
|
405
|
+
id := r.PathValue("id") // Go 1.22+ routing
|
|
406
|
+
|
|
407
|
+
user, err := store.GetUser(r.Context(), id)
|
|
408
|
+
if err != nil {
|
|
409
|
+
var notFound *NotFoundError
|
|
410
|
+
if errors.As(err, ¬Found) {
|
|
411
|
+
http.Error(w, notFound.Error(), http.StatusNotFound)
|
|
412
|
+
return
|
|
413
|
+
}
|
|
414
|
+
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
|
415
|
+
return
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
w.Header().Set("Content-Type", "application/json")
|
|
419
|
+
json.NewEncoder(w).Encode(user)
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// Middleware pattern
|
|
424
|
+
type Middleware func(http.Handler) http.Handler
|
|
425
|
+
|
|
426
|
+
func LoggingMiddleware(logger *slog.Logger) Middleware {
|
|
427
|
+
return func(next http.Handler) http.Handler {
|
|
428
|
+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
429
|
+
start := time.Now()
|
|
430
|
+
wrapped := &responseWriter{ResponseWriter: w, statusCode: http.StatusOK}
|
|
431
|
+
|
|
432
|
+
next.ServeHTTP(wrapped, r)
|
|
433
|
+
|
|
434
|
+
logger.Info("request",
|
|
435
|
+
"method", r.Method,
|
|
436
|
+
"path", r.URL.Path,
|
|
437
|
+
"status", wrapped.statusCode,
|
|
438
|
+
"duration", time.Since(start),
|
|
439
|
+
)
|
|
440
|
+
})
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
type responseWriter struct {
|
|
445
|
+
http.ResponseWriter
|
|
446
|
+
statusCode int
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
func (w *responseWriter) WriteHeader(code int) {
|
|
450
|
+
w.statusCode = code
|
|
451
|
+
w.ResponseWriter.WriteHeader(code)
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// Chaining middleware
|
|
455
|
+
func Chain(handler http.Handler, middlewares ...Middleware) http.Handler {
|
|
456
|
+
for i := len(middlewares) - 1; i >= 0; i-- {
|
|
457
|
+
handler = middlewares[i](handler)
|
|
458
|
+
}
|
|
459
|
+
return handler
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// Router setup (Go 1.22+)
|
|
463
|
+
func NewRouter(store UserStore, logger *slog.Logger) http.Handler {
|
|
464
|
+
mux := http.NewServeMux()
|
|
465
|
+
|
|
466
|
+
mux.HandleFunc("GET /api/users/{id}", handleGetUser(store))
|
|
467
|
+
mux.HandleFunc("POST /api/users", handleCreateUser(store))
|
|
468
|
+
|
|
469
|
+
return Chain(mux,
|
|
470
|
+
LoggingMiddleware(logger),
|
|
471
|
+
RecoveryMiddleware(),
|
|
472
|
+
CORSMiddleware(),
|
|
473
|
+
)
|
|
474
|
+
}
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
### 7. Generics (Go 1.18+)
|
|
478
|
+
|
|
479
|
+
```go
|
|
480
|
+
// Generic function
|
|
481
|
+
func Map[T, U any](slice []T, fn func(T) U) []U {
|
|
482
|
+
result := make([]U, len(slice))
|
|
483
|
+
for i, v := range slice {
|
|
484
|
+
result[i] = fn(v)
|
|
485
|
+
}
|
|
486
|
+
return result
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// Generic function with constraints
|
|
490
|
+
func Max[T constraints.Ordered](a, b T) T {
|
|
491
|
+
if a > b {
|
|
492
|
+
return a
|
|
493
|
+
}
|
|
494
|
+
return b
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// Custom constraint
|
|
498
|
+
type Number interface {
|
|
499
|
+
~int | ~int32 | ~int64 | ~float32 | ~float64
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
func Sum[T Number](values []T) T {
|
|
503
|
+
var total T
|
|
504
|
+
for _, v := range values {
|
|
505
|
+
total += v
|
|
506
|
+
}
|
|
507
|
+
return total
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// Generic data structure
|
|
511
|
+
type Set[T comparable] struct {
|
|
512
|
+
items map[T]struct{}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
func NewSet[T comparable]() *Set[T] {
|
|
516
|
+
return &Set[T]{items: make(map[T]struct{})}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
func (s *Set[T]) Add(item T) {
|
|
520
|
+
s.items[item] = struct{}{}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
func (s *Set[T]) Contains(item T) bool {
|
|
524
|
+
_, ok := s.items[item]
|
|
525
|
+
return ok
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
func (s *Set[T]) Len() int {
|
|
529
|
+
return len(s.items)
|
|
530
|
+
}
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
### 8. Struct Embedding and Composition
|
|
534
|
+
|
|
535
|
+
```go
|
|
536
|
+
// Embedding for composition (not inheritance)
|
|
537
|
+
type BaseModel struct {
|
|
538
|
+
ID string `json:"id"`
|
|
539
|
+
CreatedAt time.Time `json:"created_at"`
|
|
540
|
+
UpdatedAt time.Time `json:"updated_at"`
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
type User struct {
|
|
544
|
+
BaseModel // Embedded -- User "has" BaseModel fields
|
|
545
|
+
Name string `json:"name"`
|
|
546
|
+
Email string `json:"email"`
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// User now has ID, CreatedAt, UpdatedAt promoted to top level
|
|
550
|
+
user := User{
|
|
551
|
+
BaseModel: BaseModel{ID: "123"},
|
|
552
|
+
Name: "Alice",
|
|
553
|
+
Email: "alice@example.com",
|
|
554
|
+
}
|
|
555
|
+
fmt.Println(user.ID) // "123" -- promoted field
|
|
556
|
+
|
|
557
|
+
// Embedding interfaces
|
|
558
|
+
type ReadCloser struct {
|
|
559
|
+
io.Reader
|
|
560
|
+
io.Closer
|
|
561
|
+
}
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
### 9. defer, panic, recover
|
|
565
|
+
|
|
566
|
+
```go
|
|
567
|
+
// defer for cleanup -- executes in LIFO order
|
|
568
|
+
func processFile(path string) error {
|
|
569
|
+
f, err := os.Open(path)
|
|
570
|
+
if err != nil {
|
|
571
|
+
return err
|
|
572
|
+
}
|
|
573
|
+
defer f.Close() // Always runs when function returns
|
|
574
|
+
|
|
575
|
+
// Process file...
|
|
576
|
+
return nil
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
// Defer with named returns for error handling
|
|
580
|
+
func doWork() (err error) {
|
|
581
|
+
tx, err := db.Begin()
|
|
582
|
+
if err != nil {
|
|
583
|
+
return err
|
|
584
|
+
}
|
|
585
|
+
defer func() {
|
|
586
|
+
if err != nil {
|
|
587
|
+
tx.Rollback()
|
|
588
|
+
} else {
|
|
589
|
+
err = tx.Commit()
|
|
590
|
+
}
|
|
591
|
+
}()
|
|
592
|
+
|
|
593
|
+
// Do work within transaction...
|
|
594
|
+
return nil
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// panic and recover -- use only for truly unrecoverable situations
|
|
598
|
+
func safeDiv(a, b float64) (result float64, err error) {
|
|
599
|
+
defer func() {
|
|
600
|
+
if r := recover(); r != nil {
|
|
601
|
+
err = fmt.Errorf("panic in division: %v", r)
|
|
602
|
+
}
|
|
603
|
+
}()
|
|
604
|
+
|
|
605
|
+
if b == 0 {
|
|
606
|
+
panic("division by zero") // In practice, return an error instead
|
|
607
|
+
}
|
|
608
|
+
return a / b, nil
|
|
609
|
+
}
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
## Anti-Patterns
|
|
613
|
+
|
|
614
|
+
| Anti-Pattern | Why It Is Bad | Do This Instead |
|
|
615
|
+
|-------------|--------------|----------------|
|
|
616
|
+
| `_ = someFunc()` (ignoring errors) | Hides failures silently | Handle the error or log it |
|
|
617
|
+
| Goroutine without exit strategy | Goroutine leak | Use context cancellation or done channel |
|
|
618
|
+
| `interface{}` / `any` everywhere | Loses type safety | Use generics or specific types |
|
|
619
|
+
| Package-level `init()` abuse | Hidden side effects, hard to test | Explicit initialization in `main()` |
|
|
620
|
+
| Large interfaces (10+ methods) | Hard to mock, violates ISP | Break into small, focused interfaces |
|
|
621
|
+
| Naked returns in long functions | Confusing, error-prone | Only use naked returns in short functions |
|
|
622
|
+
| `sync.Mutex` for channel-shaped problems | Over-complication | Use channels for communication |
|
|
623
|
+
|
|
624
|
+
## Project Structure
|
|
625
|
+
|
|
626
|
+
```
|
|
627
|
+
my-service/
|
|
628
|
+
cmd/
|
|
629
|
+
server/
|
|
630
|
+
main.go # Entry point
|
|
631
|
+
internal/
|
|
632
|
+
handler/ # HTTP handlers
|
|
633
|
+
service/ # Business logic
|
|
634
|
+
store/ # Database access
|
|
635
|
+
model/ # Domain types
|
|
636
|
+
pkg/ # Public library code (if any)
|
|
637
|
+
go.mod
|
|
638
|
+
go.sum
|
|
639
|
+
Makefile
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
## Common Commands
|
|
643
|
+
|
|
644
|
+
```bash
|
|
645
|
+
go build ./... # Build all packages
|
|
646
|
+
go test ./... # Test all packages
|
|
647
|
+
go test -race ./... # Test with race detector
|
|
648
|
+
go test -cover ./... # Test with coverage
|
|
649
|
+
go vet ./... # Static analysis
|
|
650
|
+
golangci-lint run # Comprehensive linting
|
|
651
|
+
go mod tidy # Clean up go.mod and go.sum
|
|
652
|
+
go mod vendor # Vendor dependencies
|
|
653
|
+
go generate ./... # Run code generators
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
## Resources
|
|
657
|
+
|
|
658
|
+
- **Effective Go**: https://go.dev/doc/effective_go
|
|
659
|
+
- **Go Blog**: https://go.dev/blog/
|
|
660
|
+
- **Go by Example**: https://gobyexample.com/
|
|
661
|
+
- **Standard Library**: https://pkg.go.dev/std
|
|
662
|
+
- **Go Proverbs**: https://go-proverbs.github.io/
|
|
663
|
+
- **uber-go/guide**: https://github.com/uber-go/guide/blob/master/style.md
|
|
664
|
+
- **golangci-lint**: https://golangci-lint.run/
|