groundwork-method 0.0.1 → 0.11.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/CHANGELOG.md +823 -0
- package/LICENSE +21 -0
- package/README.md +44 -29
- package/bin/groundwork.js +1723 -0
- package/dist/src/generators/add-capability/generator.d.ts +8 -0
- package/dist/src/generators/add-capability/generator.js +60 -0
- package/dist/src/generators/add-capability/generator.js.map +1 -0
- package/dist/src/generators/cli-app/generator.d.ts +9 -0
- package/dist/src/generators/cli-app/generator.js +140 -0
- package/dist/src/generators/cli-app/generator.js.map +1 -0
- package/dist/src/generators/docs-site/generator.d.ts +5 -0
- package/dist/src/generators/docs-site/generator.js +441 -0
- package/dist/src/generators/docs-site/generator.js.map +1 -0
- package/dist/src/generators/electron-app/generator.d.ts +6 -0
- package/dist/src/generators/electron-app/generator.js +261 -0
- package/dist/src/generators/electron-app/generator.js.map +1 -0
- package/dist/src/generators/flutter-app/generator.d.ts +6 -0
- package/dist/src/generators/flutter-app/generator.js +314 -0
- package/dist/src/generators/flutter-app/generator.js.map +1 -0
- package/dist/src/generators/go-microservice/generator.d.ts +8 -0
- package/dist/src/generators/go-microservice/generator.js +232 -0
- package/dist/src/generators/go-microservice/generator.js.map +1 -0
- package/dist/src/generators/nextjs-app/generator.d.ts +8 -0
- package/dist/src/generators/nextjs-app/generator.js +294 -0
- package/dist/src/generators/nextjs-app/generator.js.map +1 -0
- package/dist/src/generators/python-microservice/generator.d.ts +13 -0
- package/dist/src/generators/python-microservice/generator.js +265 -0
- package/dist/src/generators/python-microservice/generator.js.map +1 -0
- package/dist/src/generators/shared/brand-tokens.d.ts +89 -0
- package/dist/src/generators/shared/brand-tokens.js +308 -0
- package/dist/src/generators/shared/brand-tokens.js.map +1 -0
- package/dist/src/generators/shared/capabilities.d.ts +101 -0
- package/dist/src/generators/shared/capabilities.js +279 -0
- package/dist/src/generators/shared/capabilities.js.map +1 -0
- package/dist/src/generators/shared/provenance.d.ts +2 -0
- package/dist/src/generators/shared/provenance.js +85 -0
- package/dist/src/generators/shared/provenance.js.map +1 -0
- package/dist/src/generators/shared/scaffold-helpers.d.ts +72 -0
- package/dist/src/generators/shared/scaffold-helpers.js +309 -0
- package/dist/src/generators/shared/scaffold-helpers.js.map +1 -0
- package/dist/src/generators/system-test-runner/generator.d.ts +23 -0
- package/dist/src/generators/system-test-runner/generator.js +173 -0
- package/dist/src/generators/system-test-runner/generator.js.map +1 -0
- package/dist/src/generators/workspace-dev-cli/generator.d.ts +7 -0
- package/dist/src/generators/workspace-dev-cli/generator.js +138 -0
- package/dist/src/generators/workspace-dev-cli/generator.js.map +1 -0
- package/generators.json +57 -0
- package/lib/repo-map/grammars/tree-sitter-c.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-cpp.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-csharp.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-dart.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-go.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-java.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-javascript.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-kotlin.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-lua.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-php.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-python.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-ruby.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-rust.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-scala.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-swift.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-tsx.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-typescript.wasm +0 -0
- package/lib/repo-map/index.js +386 -0
- package/lib/repo-map/languages.js +514 -0
- package/lib/repo-map/pagerank.js +59 -0
- package/migrations/README.md +60 -0
- package/migrations/_template/cli-migration.js +27 -0
- package/migrations/gw-bet-prose-redesign.js +105 -0
- package/migrations/gw-drop-test-manifest.js +37 -0
- package/migrations/gw-register-serena-mcp.js +42 -0
- package/migrations/gw-relocate-hidden-skills.js +40 -0
- package/migrations/gw-seed-config-toml.js +24 -0
- package/migrations/index.json +40 -0
- package/package.json +70 -6
- package/src/AGENTS.md +36 -0
- package/src/config/config.toml +30 -0
- package/src/config/groundwork-state.json +5 -0
- package/src/docs/llms.txt +72 -0
- package/src/docs/principles/ai-native/agent-native-systems.md +90 -0
- package/src/docs/principles/ai-native/agentic-systems.md +78 -0
- package/src/docs/principles/ai-native/ai-engineering.md +100 -0
- package/src/docs/principles/ai-native/ai-native-product.md +76 -0
- package/src/docs/principles/delivery/cost-engineering.md +89 -0
- package/src/docs/principles/delivery/day-2-operational-baseline.md +57 -0
- package/src/docs/principles/delivery/devex.md +88 -0
- package/src/docs/principles/delivery/platform.md +101 -0
- package/src/docs/principles/delivery/progressive-delivery.md +92 -0
- package/src/docs/principles/design/ai-native-design.md +73 -0
- package/src/docs/principles/design/design-foundations.md +80 -0
- package/src/docs/principles/design/design-systems-and-tokens.md +72 -0
- package/src/docs/principles/design/interaction-and-motion.md +69 -0
- package/src/docs/principles/design/layout-and-space.md +72 -0
- package/src/docs/principles/design/usability-and-ux.md +79 -0
- package/src/docs/principles/design/visual-design.md +84 -0
- package/src/docs/principles/foundations/code-craft.md +86 -0
- package/src/docs/principles/foundations/continuous-discovery.md +75 -0
- package/src/docs/principles/foundations/documentation.md +102 -0
- package/src/docs/principles/foundations/prioritization-and-appetite.md +78 -0
- package/src/docs/principles/foundations/product-engineering.md +90 -0
- package/src/docs/principles/foundations/product-risks.md +89 -0
- package/src/docs/principles/foundations/requirements-and-specs.md +80 -0
- package/src/docs/principles/foundations/success-metrics.md +66 -0
- package/src/docs/principles/foundations/testing.md +108 -0
- package/src/docs/principles/index.md +24 -0
- package/src/docs/principles/quality/accessibility.md +88 -0
- package/src/docs/principles/quality/observability.md +84 -0
- package/src/docs/principles/quality/performance.md +84 -0
- package/src/docs/principles/quality/privacy.md +92 -0
- package/src/docs/principles/quality/reliability.md +89 -0
- package/src/docs/principles/quality/security.md +78 -0
- package/src/docs/principles/stack/postgres.md +100 -0
- package/src/docs/principles/system-design/api-design.md +86 -0
- package/src/docs/principles/system-design/architecture-decisions.md +81 -0
- package/src/docs/principles/system-design/code-structure.md +104 -0
- package/src/docs/principles/system-design/data-engineering.md +87 -0
- package/src/docs/principles/system-design/durable-execution.md +89 -0
- package/src/docs/principles/system-design/evolutionary-architecture.md +81 -0
- package/src/docs/principles/system-design/identity-and-access.md +76 -0
- package/src/docs/principles/system-design/integration-patterns.md +84 -0
- package/src/docs/principles/system-design/real-time.md +83 -0
- package/src/docs/principles/system-design/surface-architecture.md +74 -0
- package/src/docs/ways-of-working/documentation.md +69 -0
- package/src/docs/ways-of-working/how-we-work.md +76 -0
- package/src/docs/ways-of-working/units-of-work.md +40 -0
- package/src/engineer-skills/groundwork-electron-engineer/SKILL.md +123 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/documentation.md +126 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/ipc-contracts.md +138 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/observability.md +37 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/packaging-and-updates.md +82 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/performance-and-reliability.md +80 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/process-model.md +94 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/security.md +107 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/testing-and-smoke.md +129 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/theming-and-tokens.md +74 -0
- package/src/engineer-skills/groundwork-electron-engineer/sync-anchor.md +22 -0
- package/src/engineer-skills/groundwork-flutter-engineer/SKILL.md +114 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/accessibility.md +92 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/architecture.md +189 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/data-and-contracts.md +136 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/documentation.md +122 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/navigation.md +122 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/observability.md +37 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/performance-and-reliability.md +100 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/platform-channels.md +93 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/releases-and-distribution.md +84 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/security.md +96 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/state-management.md +166 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/testing.md +160 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/theming-and-design-tokens.md +109 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/widgets-and-composition.md +123 -0
- package/src/engineer-skills/groundwork-flutter-engineer/sync-anchor.md +24 -0
- package/src/engineer-skills/groundwork-go-engineer/SKILL.md +174 -0
- package/src/engineer-skills/groundwork-go-engineer/references/api-design.md +82 -0
- package/src/engineer-skills/groundwork-go-engineer/references/architecture.md +42 -0
- package/src/engineer-skills/groundwork-go-engineer/references/capability-ports.md +50 -0
- package/src/engineer-skills/groundwork-go-engineer/references/code-craft-security.md +34 -0
- package/src/engineer-skills/groundwork-go-engineer/references/concurrency.md +108 -0
- package/src/engineer-skills/groundwork-go-engineer/references/documentation.md +130 -0
- package/src/engineer-skills/groundwork-go-engineer/references/go-services.md +77 -0
- package/src/engineer-skills/groundwork-go-engineer/references/http-handlers.md +172 -0
- package/src/engineer-skills/groundwork-go-engineer/references/implementation-patterns.md +156 -0
- package/src/engineer-skills/groundwork-go-engineer/references/integration-realtime-data.md +57 -0
- package/src/engineer-skills/groundwork-go-engineer/references/observability.md +49 -0
- package/src/engineer-skills/groundwork-go-engineer/references/postgres.md +41 -0
- package/src/engineer-skills/groundwork-go-engineer/references/reliability-performance.md +105 -0
- package/src/engineer-skills/groundwork-go-engineer/references/testing.md +201 -0
- package/src/engineer-skills/groundwork-go-engineer/sync-anchor.md +20 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/SKILL.md +112 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/accessibility.md +111 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/architecture.md +323 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/data-fetching.md +458 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/documentation.md +324 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/error-boundaries.md +383 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/mutations-and-forms.md +396 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/observability.md +48 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/performance-and-deployment.md +947 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/routing-and-navigation.md +405 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/security.md +131 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/server-components.md +394 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/tailwind-and-styling.md +134 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/testing.md +491 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/type-system.md +368 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/ux-principles.md +230 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/visual-language.md +69 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/sync-anchor.md +16 -0
- package/src/engineer-skills/groundwork-python-engineer/SKILL.md +199 -0
- package/src/engineer-skills/groundwork-python-engineer/references/api-standards.md +88 -0
- package/src/engineer-skills/groundwork-python-engineer/references/architecture.md +57 -0
- package/src/engineer-skills/groundwork-python-engineer/references/async-patterns.md +103 -0
- package/src/engineer-skills/groundwork-python-engineer/references/capability-ports.md +44 -0
- package/src/engineer-skills/groundwork-python-engineer/references/database.md +88 -0
- package/src/engineer-skills/groundwork-python-engineer/references/documentation-mcp.md +167 -0
- package/src/engineer-skills/groundwork-python-engineer/references/implementation-patterns.md +166 -0
- package/src/engineer-skills/groundwork-python-engineer/references/ml-pipelines.md +119 -0
- package/src/engineer-skills/groundwork-python-engineer/references/ml-systems-ai-engineering.md +74 -0
- package/src/engineer-skills/groundwork-python-engineer/references/observability.md +57 -0
- package/src/engineer-skills/groundwork-python-engineer/references/resilience.md +126 -0
- package/src/engineer-skills/groundwork-python-engineer/references/security.md +148 -0
- package/src/engineer-skills/groundwork-python-engineer/references/testing.md +216 -0
- package/src/engineer-skills/groundwork-python-engineer/sync-anchor.md +20 -0
- package/src/generators/add-capability/generator.ts +70 -0
- package/src/generators/add-capability/schema.json +30 -0
- package/src/generators/capabilities/llm/capability.json +28 -0
- package/src/generators/capabilities/llm/providers/anthropic/footprint.json +13 -0
- package/src/generators/capabilities/llm/providers/anthropic/stacks/go/internal/llm/llm.go.template +102 -0
- package/src/generators/capabilities/llm/providers/anthropic/stacks/python/src/__packageName__/adapters/llm.py.template +61 -0
- package/src/generators/capabilities/llm/providers/local/footprint.json +13 -0
- package/src/generators/capabilities/llm/providers/local/stacks/go/internal/llm/llm.go.template +102 -0
- package/src/generators/capabilities/llm/providers/local/stacks/python/src/__packageName__/adapters/llm.py.template +53 -0
- package/src/generators/capabilities/llm/providers/localai/footprint.json +29 -0
- package/src/generators/capabilities/llm/providers/localai/stacks/go/internal/llm/llm.go.template +102 -0
- package/src/generators/capabilities/llm/providers/localai/stacks/python/src/__packageName__/adapters/llm.py.template +53 -0
- package/src/generators/capabilities/llm/providers/none/footprint.json +9 -0
- package/src/generators/capabilities/llm/providers/none/stacks/go/internal/llm/llm.go.template +35 -0
- package/src/generators/capabilities/llm/providers/none/stacks/python/src/__packageName__/adapters/llm.py.template +25 -0
- package/src/generators/capabilities/llm/providers/ollama/footprint.json +20 -0
- package/src/generators/capabilities/llm/providers/ollama/stacks/go/internal/llm/llm.go.template +102 -0
- package/src/generators/capabilities/llm/providers/ollama/stacks/python/src/__packageName__/adapters/llm.py.template +53 -0
- package/src/generators/capabilities/llm/providers/openai/footprint.json +13 -0
- package/src/generators/capabilities/llm/providers/openai/stacks/go/internal/llm/llm.go.template +98 -0
- package/src/generators/capabilities/llm/providers/openai/stacks/python/src/__packageName__/adapters/llm.py.template +60 -0
- package/src/generators/capabilities/llm/stacks/go/internal/core/service/llm.go.template +12 -0
- package/src/generators/capabilities/llm/stacks/go/internal/llm/llm_test.go.template +33 -0
- package/src/generators/capabilities/llm/stacks/python/src/__packageName__/core/llm.py.template +15 -0
- package/src/generators/capabilities/llm/stacks/python/tests/contracts/test_llm.py.template +37 -0
- package/src/generators/cli-app/files/README.md.template +76 -0
- package/src/generators/cli-app/files/build.mjs.template +15 -0
- package/src/generators/cli-app/files/package.json.template +21 -0
- package/src/generators/cli-app/files/src/cli.ts.template +67 -0
- package/src/generators/cli-app/files/src/commands/hello.ts.template +17 -0
- package/src/generators/cli-app/files/src/commands/status.ts.template +23 -0
- package/src/generators/cli-app/files/src/core/client.test.ts.template +80 -0
- package/src/generators/cli-app/files/src/core/client.ts.template +64 -0
- package/src/generators/cli-app/files/src/registry.test.ts.template +35 -0
- package/src/generators/cli-app/files/src/registry.ts.template +31 -0
- package/src/generators/cli-app/files/tsconfig.json.template +16 -0
- package/src/generators/cli-app/files/tsconfig.test.json.template +11 -0
- package/src/generators/cli-app/generator.ts +138 -0
- package/src/generators/cli-app/schema.json +24 -0
- package/src/generators/docs-site/files/.gitignore.ejs +40 -0
- package/src/generators/docs-site/files/app/docs/__slug__/page.tsx +101 -0
- package/src/generators/docs-site/files/app/docs/layout.tsx +14 -0
- package/src/generators/docs-site/files/app/docs.css +43 -0
- package/src/generators/docs-site/files/app/layout.tsx +24 -0
- package/src/generators/docs-site/files/app/page.tsx +135 -0
- package/src/generators/docs-site/files/app/source.ts +8 -0
- package/src/generators/docs-site/files/components/mermaid.tsx +67 -0
- package/src/generators/docs-site/files/next.config.mjs +10 -0
- package/src/generators/docs-site/files/package.json +32 -0
- package/src/generators/docs-site/files/pnpm-workspace.yaml +7 -0
- package/src/generators/docs-site/files/postcss.config.mjs +6 -0
- package/src/generators/docs-site/files/source.config.ts +77 -0
- package/src/generators/docs-site/files/tailwind.config.js +10 -0
- package/src/generators/docs-site/files/tsconfig.json +27 -0
- package/src/generators/docs-site/generator.ts +476 -0
- package/src/generators/docs-site/schema.json +17 -0
- package/src/generators/electron-app/docs/principles/stack/electron/index.md +49 -0
- package/src/generators/electron-app/docs/principles/stack/electron/ipc-contracts.md +71 -0
- package/src/generators/electron-app/docs/principles/stack/electron/packaging-and-updates.md +59 -0
- package/src/generators/electron-app/docs/principles/stack/electron/process-model.md +53 -0
- package/src/generators/electron-app/docs/principles/stack/electron/security.md +70 -0
- package/src/generators/electron-app/docs/principles/stack/typescript/frontend.md +65 -0
- package/src/generators/electron-app/files/.gitignore.template +20 -0
- package/src/generators/electron-app/files/README.md.template +125 -0
- package/src/generators/electron-app/files/electron.vite.config.ts +31 -0
- package/src/generators/electron-app/files/eslint.config.mjs +92 -0
- package/src/generators/electron-app/files/forge.config.ts.template +44 -0
- package/src/generators/electron-app/files/package.json.template +54 -0
- package/src/generators/electron-app/files/playwright.config.ts +18 -0
- package/src/generators/electron-app/files/project.json.template +65 -0
- package/src/generators/electron-app/files/src/main/core-client.test.ts +81 -0
- package/src/generators/electron-app/files/src/main/core-client.ts +55 -0
- package/src/generators/electron-app/files/src/main/index.ts +157 -0
- package/src/generators/electron-app/files/src/main/ipc.ts +52 -0
- package/src/generators/electron-app/files/src/main/policy.test.ts +71 -0
- package/src/generators/electron-app/files/src/main/policy.ts +73 -0
- package/src/generators/electron-app/files/src/preload/index.ts +23 -0
- package/src/generators/electron-app/files/src/renderer/index.html.template +20 -0
- package/src/generators/electron-app/files/src/renderer/src/App.test.tsx +61 -0
- package/src/generators/electron-app/files/src/renderer/src/App.tsx.template +43 -0
- package/src/generators/electron-app/files/src/renderer/src/assets/main.css +40 -0
- package/src/generators/electron-app/files/src/renderer/src/env.d.ts +14 -0
- package/src/generators/electron-app/files/src/renderer/src/main.tsx +25 -0
- package/src/generators/electron-app/files/src/shared/ipc.ts +54 -0
- package/src/generators/electron-app/files/tests/smoke/app.spec.ts.template +133 -0
- package/src/generators/electron-app/files/tool/electron_exec.sh.template +83 -0
- package/src/generators/electron-app/files/tsconfig.json +7 -0
- package/src/generators/electron-app/files/tsconfig.node.json +27 -0
- package/src/generators/electron-app/files/tsconfig.web.json +22 -0
- package/src/generators/electron-app/files/vitest.config.ts +32 -0
- package/src/generators/electron-app/files/vitest.setup.ts +1 -0
- package/src/generators/electron-app/generator.ts +288 -0
- package/src/generators/electron-app/schema.json +23 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/architecture.md +78 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/index.md +38 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/platform-channels.md +51 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/releases-and-distribution.md +59 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/state-management.md +85 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/testing.md +86 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/widgets-and-composition.md +69 -0
- package/src/generators/flutter-app/files/.gitignore.template +30 -0
- package/src/generators/flutter-app/files/README.md.template +100 -0
- package/src/generators/flutter-app/files/analysis_options.yaml.template +18 -0
- package/src/generators/flutter-app/files/integration_test/app_test.dart.template +64 -0
- package/src/generators/flutter-app/files/lib/app.dart.template +24 -0
- package/src/generators/flutter-app/files/lib/config/app_config.dart +15 -0
- package/src/generators/flutter-app/files/lib/data/repositories/status_repository.dart +36 -0
- package/src/generators/flutter-app/files/lib/data/services/api_client.dart +71 -0
- package/src/generators/flutter-app/files/lib/domain/models/health_status.dart +23 -0
- package/src/generators/flutter-app/files/lib/main.dart +11 -0
- package/src/generators/flutter-app/files/lib/router.dart +23 -0
- package/src/generators/flutter-app/files/lib/ui/core/theme/app_theme.dart +110 -0
- package/src/generators/flutter-app/files/lib/ui/home/home_view.dart +89 -0
- package/src/generators/flutter-app/files/lib/ui/home/home_view_model.dart.template +38 -0
- package/src/generators/flutter-app/files/project.json.template +51 -0
- package/src/generators/flutter-app/files/pubspec.yaml.template +47 -0
- package/src/generators/flutter-app/files/test/api_client_test.dart.template +63 -0
- package/src/generators/flutter-app/files/test/fakes/fake_status_repository.dart.template +19 -0
- package/src/generators/flutter-app/files/test/home_view_test.dart.template +58 -0
- package/src/generators/flutter-app/files/tool/flutter_exec.sh.template +60 -0
- package/src/generators/flutter-app/generator.ts +362 -0
- package/src/generators/flutter-app/schema.json +23 -0
- package/src/generators/go-microservice/docs/principles/stack/go/concurrency.md +123 -0
- package/src/generators/go-microservice/docs/principles/stack/go/index.md +70 -0
- package/src/generators/go-microservice/docs/principles/stack/go/testing.md +168 -0
- package/src/generators/go-microservice/files/.air.toml.template +38 -0
- package/src/generators/go-microservice/files/.env.template +4 -0
- package/src/generators/go-microservice/files/.golangci.yml.template +82 -0
- package/src/generators/go-microservice/files/Dockerfile.dev.template +12 -0
- package/src/generators/go-microservice/files/asyncapi-pubsub.yaml.template +33 -0
- package/src/generators/go-microservice/files/asyncapi-ws.yaml.template +34 -0
- package/src/generators/go-microservice/files/cmd/api/main.go.template +149 -0
- package/src/generators/go-microservice/files/cmd/api/main_test.go.template +99 -0
- package/src/generators/go-microservice/files/cmd/worker/cleanup/main.go.template +39 -0
- package/src/generators/go-microservice/files/db/schema.sql.template +24 -0
- package/src/generators/go-microservice/files/go.mod.template +39 -0
- package/src/generators/go-microservice/files/internal/config/config.go.template +52 -0
- package/src/generators/go-microservice/files/internal/config/otel.go.template +93 -0
- package/src/generators/go-microservice/files/internal/core/domain/errors.go.template +16 -0
- package/src/generators/go-microservice/files/internal/core/domain/model.go.template +28 -0
- package/src/generators/go-microservice/files/internal/core/domain/user.go.template +13 -0
- package/src/generators/go-microservice/files/internal/core/pagination.go.template +16 -0
- package/src/generators/go-microservice/files/internal/core/service/app_service.go.template +79 -0
- package/src/generators/go-microservice/files/internal/core/service/event_hub.go.template +9 -0
- package/src/generators/go-microservice/files/internal/core/service/message_queue.go.template +10 -0
- package/src/generators/go-microservice/files/internal/core/service/outbox_repository.go.template +31 -0
- package/src/generators/go-microservice/files/internal/core/service/repository.go.template +23 -0
- package/src/generators/go-microservice/files/internal/core/service/user_repository.go.template +15 -0
- package/src/generators/go-microservice/files/internal/core/service/user_service.go.template +43 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/app_handler.go.template +108 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/auth_middleware_test.go.template +52 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/clerk_webhook.go.template +202 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/clerk_webhook_test.go.template +82 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/health_handler.go.template +80 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/idempotency/middleware.go.template +87 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/idempotency/middleware_test.go.template +76 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/idempotency/repository.go.template +37 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_auth.go.template +40 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_loadshed.go.template +38 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_logging.go.template +40 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_ratelimit.go.template +48 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_test.go.template +81 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/router.go.template +105 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/types.go.template +70 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/websocket_handler.go.template +39 -0
- package/src/generators/go-microservice/files/internal/httpclient/http_client.go.template +87 -0
- package/src/generators/go-microservice/files/internal/kafka/kafka.go.template +34 -0
- package/src/generators/go-microservice/files/internal/postgres/postgres.go.template +195 -0
- package/src/generators/go-microservice/files/internal/postgres/postgres_test.go.template +156 -0
- package/src/generators/go-microservice/files/internal/postgres/user_repository.go.template +56 -0
- package/src/generators/go-microservice/files/internal/pubsub/gcp_pubsub.go.template +35 -0
- package/src/generators/go-microservice/files/internal/websocket/client.go.template +151 -0
- package/src/generators/go-microservice/files/internal/websocket/hub.go.template +261 -0
- package/src/generators/go-microservice/files/scripts/apply-schema.sh.template +21 -0
- package/src/generators/go-microservice/files/tools/tools.go.template +10 -0
- package/src/generators/go-microservice/generator.ts +240 -0
- package/src/generators/go-microservice/schema.json +63 -0
- package/src/generators/nextjs-app/docs/principles/stack/typescript/frontend.md +65 -0
- package/src/generators/nextjs-app/files/.dockerignore.template +7 -0
- package/src/generators/nextjs-app/files/.env.example.template +24 -0
- package/src/generators/nextjs-app/files/.gitignore.template +5 -0
- package/src/generators/nextjs-app/files/Dockerfile +53 -0
- package/src/generators/nextjs-app/files/app/(auth)/sign-in/__sign-in__/page.tsx.template +9 -0
- package/src/generators/nextjs-app/files/app/(auth)/sign-up/__sign-up__/page.tsx.template +9 -0
- package/src/generators/nextjs-app/files/app/api/config/route.ts.template +39 -0
- package/src/generators/nextjs-app/files/app/api/healthz/route.test.ts +15 -0
- package/src/generators/nextjs-app/files/app/api/healthz/route.ts +5 -0
- package/src/generators/nextjs-app/files/app/api/proxy/__path__/route.test.ts.template +55 -0
- package/src/generators/nextjs-app/files/app/api/proxy/__path__/route.ts.template +126 -0
- package/src/generators/nextjs-app/files/app/error.tsx +39 -0
- package/src/generators/nextjs-app/files/app/global-error.tsx +68 -0
- package/src/generators/nextjs-app/files/app/globals.css +105 -0
- package/src/generators/nextjs-app/files/app/layout.tsx +59 -0
- package/src/generators/nextjs-app/files/app/loading.tsx +13 -0
- package/src/generators/nextjs-app/files/app/not-found.tsx +30 -0
- package/src/generators/nextjs-app/files/app/page.tsx +20 -0
- package/src/generators/nextjs-app/files/components/providers/default.tsx +19 -0
- package/src/generators/nextjs-app/files/components/providers/production.tsx +32 -0
- package/src/generators/nextjs-app/files/components/providers/telemetry.tsx +76 -0
- package/src/generators/nextjs-app/files/components/render-smoke.test.tsx +29 -0
- package/src/generators/nextjs-app/files/components/theme-provider.tsx +11 -0
- package/src/generators/nextjs-app/files/components.json +21 -0
- package/src/generators/nextjs-app/files/eslint.config.mjs +120 -0
- package/src/generators/nextjs-app/files/hooks/use-toast.ts +7 -0
- package/src/generators/nextjs-app/files/instrumentation.ts +90 -0
- package/src/generators/nextjs-app/files/lib/api/fetcher.ts.template +130 -0
- package/src/generators/nextjs-app/files/lib/config.ts +21 -0
- package/src/generators/nextjs-app/files/lib/logger.ts +29 -0
- package/src/generators/nextjs-app/files/lib/schemas/index.ts +19 -0
- package/src/generators/nextjs-app/files/lib/utils.ts +6 -0
- package/src/generators/nextjs-app/files/next.config.mjs +9 -0
- package/src/generators/nextjs-app/files/package.json +70 -0
- package/src/generators/nextjs-app/files/postcss.config.mjs +8 -0
- package/src/generators/nextjs-app/files/proxy.test.ts.template +30 -0
- package/src/generators/nextjs-app/files/proxy.ts +31 -0
- package/src/generators/nextjs-app/files/public/.gitkeep +1 -0
- package/src/generators/nextjs-app/files/tsconfig.json +42 -0
- package/src/generators/nextjs-app/files/vitest.config.mts +15 -0
- package/src/generators/nextjs-app/files/vitest.setup.ts +7 -0
- package/src/generators/nextjs-app/generator.ts +307 -0
- package/src/generators/nextjs-app/schema.json +44 -0
- package/src/generators/python-microservice/docs/principles/stack/python/async.md +168 -0
- package/src/generators/python-microservice/docs/principles/stack/python/documentation.md +240 -0
- package/src/generators/python-microservice/docs/principles/stack/python/mcp.md +147 -0
- package/src/generators/python-microservice/docs/principles/stack/python/resilience.md +193 -0
- package/src/generators/python-microservice/docs/principles/stack/python/testing.md +322 -0
- package/src/generators/python-microservice/files/.env.example.template +30 -0
- package/src/generators/python-microservice/files/Dockerfile.template +36 -0
- package/src/generators/python-microservice/files/db/schema.sql.template +19 -0
- package/src/generators/python-microservice/files/pyproject.toml.template +76 -0
- package/src/generators/python-microservice/files/scripts/apply-schema.sh.template +25 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/comfyui.py.template +87 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/config.py.template +48 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/database.py.template +21 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/message_queue.py.template +29 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/repository.py.template +130 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/telemetry.py.template +68 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/websocket_hub.py.template +36 -0
- package/src/generators/python-microservice/files/src/__packageName__/core/domain/entities.py.template +22 -0
- package/src/generators/python-microservice/files/src/__packageName__/core/domain/exceptions.py.template +43 -0
- package/src/generators/python-microservice/files/src/__packageName__/core/ports.py.template +42 -0
- package/src/generators/python-microservice/files/src/__packageName__/core/service/example_service.py.template +68 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/dependencies.py.template +50 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/middleware.py.template +131 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/router.py.template +37 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/websocket_handler.py.template +20 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/worker/cleanup.py.template +35 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/worker/worker.py.template +28 -0
- package/src/generators/python-microservice/files/src/__packageName__/main.py.template +108 -0
- package/src/generators/python-microservice/files/tests/test_main.py.template +74 -0
- package/src/generators/python-microservice/files/tests/test_middleware.py.template +109 -0
- package/src/generators/python-microservice/files/tests/test_worker.py.template +16 -0
- package/src/generators/python-microservice/generator.ts +286 -0
- package/src/generators/python-microservice/schema.json +86 -0
- package/src/generators/shared/brand-tokens.ts +301 -0
- package/src/generators/shared/capabilities.ts +349 -0
- package/src/generators/shared/provenance.ts +61 -0
- package/src/generators/shared/scaffold-helpers.ts +309 -0
- package/src/generators/system-test-runner/NATIVE-CHECK-CONTRACT.md +20 -0
- package/src/generators/system-test-runner/files/tests/bets/.gitkeep +0 -0
- package/src/generators/system-test-runner/files/tests/bets/_archive/.gitkeep +0 -0
- package/src/generators/system-test-runner/files/tests/conftest.py.template +503 -0
- package/src/generators/system-test-runner/files/tests/pyproject.toml.template +20 -0
- package/src/generators/system-test-runner/files/tests/system/pages/__init__.py.template +9 -0
- package/src/generators/system-test-runner/files/tests/system/pages/base_page.py.template +36 -0
- package/src/generators/system-test-runner/files/tests/system/test_a11y_smoke.py.template +132 -0
- package/src/generators/system-test-runner/files/tests/system/test_contract_conformance.py.template +140 -0
- package/src/generators/system-test-runner/files/tests/system/test_layout_geometry.py.template +109 -0
- package/src/generators/system-test-runner/files/tests/system/test_render_smoke.py.template +257 -0
- package/src/generators/system-test-runner/files/tests/system/test_system.py.template +158 -0
- package/src/generators/system-test-runner/files/tests/system/test_token_conformance.py.template +206 -0
- package/src/generators/system-test-runner/files/tests/system/test_visual_regression.py.template +104 -0
- package/src/generators/system-test-runner/generator.ts +196 -0
- package/src/generators/system-test-runner/schema.json +24 -0
- package/src/generators/workspace-dev-cli/cli-src/build.mjs +42 -0
- package/src/generators/workspace-dev-cli/cli-src/dist/dev-bundle.js +2168 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/bet.ts +442 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/completion.ts +87 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/doctor.ts +139 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/lifecycle.ts +548 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/quality.ts +127 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/surface.ts +214 -0
- package/src/generators/workspace-dev-cli/cli-src/src/index.ts +127 -0
- package/src/generators/workspace-dev-cli/cli-src/src/registry.ts +194 -0
- package/src/generators/workspace-dev-cli/cli-src/src/theme/color.ts +130 -0
- package/src/generators/workspace-dev-cli/cli-src/src/theme/render.ts +158 -0
- package/src/generators/workspace-dev-cli/cli-src/src/theme/tokens.ts +122 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/context.ts +43 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/extensions.ts +99 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/paths.ts +46 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/proc.ts +106 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/prompt.ts +108 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/runners.ts +70 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/services.ts +221 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/version.ts +21 -0
- package/src/generators/workspace-dev-cli/cli-src/tsconfig.json +16 -0
- package/src/generators/workspace-dev-cli/files/.agents/skills/workspace-cli/SKILL.md.template +74 -0
- package/src/generators/workspace-dev-cli/files/dev.template +16 -0
- package/src/generators/workspace-dev-cli/files/docker-compose.yml.template +20 -0
- package/src/generators/workspace-dev-cli/files/scripts/cli/templates/milestone-test.pytmpl.template +46 -0
- package/src/generators/workspace-dev-cli/files/scripts/cli/templates/slice-test.pytmpl.template +38 -0
- package/src/generators/workspace-dev-cli/generator.ts +136 -0
- package/src/generators/workspace-dev-cli/schema.json +22 -0
- package/src/hidden-skills/code-intelligence.md +135 -0
- package/src/hidden-skills/groundwork-architect/SKILL.md +114 -0
- package/src/hidden-skills/groundwork-architect/references/agentic-systems.md +44 -0
- package/src/hidden-skills/groundwork-architect/references/ai-native-architecture.md +37 -0
- package/src/hidden-skills/groundwork-architect/references/api-and-contracts.md +45 -0
- package/src/hidden-skills/groundwork-architect/references/core-and-boundaries.md +45 -0
- package/src/hidden-skills/groundwork-architect/references/data-architecture.md +33 -0
- package/src/hidden-skills/groundwork-architect/references/decision-records.md +34 -0
- package/src/hidden-skills/groundwork-architect/references/durable-execution.md +45 -0
- package/src/hidden-skills/groundwork-architect/references/evolutionary-architecture.md +37 -0
- package/src/hidden-skills/groundwork-architect/references/identity-and-access.md +41 -0
- package/src/hidden-skills/groundwork-architect/references/integration-patterns.md +39 -0
- package/src/hidden-skills/groundwork-architect/references/observability.md +36 -0
- package/src/hidden-skills/groundwork-architect/references/performance-and-scale.md +41 -0
- package/src/hidden-skills/groundwork-architect/references/platform-and-delivery.md +47 -0
- package/src/hidden-skills/groundwork-architect/references/realtime-and-async.md +28 -0
- package/src/hidden-skills/groundwork-architect/references/reliability.md +31 -0
- package/src/hidden-skills/groundwork-architect/references/security-and-trust.md +47 -0
- package/src/hidden-skills/groundwork-architect/references/surface-architecture.md +40 -0
- package/src/hidden-skills/groundwork-architect/sync-anchor.md +34 -0
- package/src/hidden-skills/groundwork-architecture/architecture-template.md +50 -0
- package/src/hidden-skills/groundwork-architecture/instructions.md +139 -0
- package/src/hidden-skills/groundwork-architecture/phases/01-context-ingestion.md +18 -0
- package/src/hidden-skills/groundwork-architecture/phases/02-technical-constraints.md +27 -0
- package/src/hidden-skills/groundwork-architecture/phases/03-service-design.md +19 -0
- package/src/hidden-skills/groundwork-architecture/phases/04-data-flow-communication.md +23 -0
- package/src/hidden-skills/groundwork-architecture/phases/05-component-boundaries-contracts.md +17 -0
- package/src/hidden-skills/groundwork-architecture/phases/06-draft-review-present.md +38 -0
- package/src/hidden-skills/groundwork-architecture/phases/07-commit.md +33 -0
- package/src/hidden-skills/groundwork-architecture/templates/architecture-cache.md +43 -0
- package/src/hidden-skills/groundwork-architecture-extract/instructions.md +163 -0
- package/src/hidden-skills/groundwork-architecture-extract/templates/architecture-extract-cache.md +21 -0
- package/src/hidden-skills/groundwork-bet/briefs/acceptance-auditor.md +68 -0
- package/src/hidden-skills/groundwork-bet/briefs/blind-reviewer.md +56 -0
- package/src/hidden-skills/groundwork-bet/briefs/coverage-auditor.md +95 -0
- package/src/hidden-skills/groundwork-bet/briefs/edge-case-tracer.md +64 -0
- package/src/hidden-skills/groundwork-bet/briefs/experience-auditor.md +83 -0
- package/src/hidden-skills/groundwork-bet/briefs/slice-worker.md +257 -0
- package/src/hidden-skills/groundwork-bet/instructions.md +88 -0
- package/src/hidden-skills/groundwork-bet/templates/bet-progress-test.md +115 -0
- package/src/hidden-skills/groundwork-bet/templates/change-proposal.md +38 -0
- package/src/hidden-skills/groundwork-bet/templates/decomposition/meta.json +4 -0
- package/src/hidden-skills/groundwork-bet/templates/decomposition/milestone-index.md +31 -0
- package/src/hidden-skills/groundwork-bet/templates/decomposition/slice.md +31 -0
- package/src/hidden-skills/groundwork-bet/templates/pitch.md +45 -0
- package/src/hidden-skills/groundwork-bet/templates/technical-design/01-ui-design.md +51 -0
- package/src/hidden-skills/groundwork-bet/templates/technical-design/02-data-flows.md +36 -0
- package/src/hidden-skills/groundwork-bet/templates/technical-design/03-api-design.md +90 -0
- package/src/hidden-skills/groundwork-bet/templates/technical-design/04-data-design.md +29 -0
- package/src/hidden-skills/groundwork-bet/workflows/01-discovery.md +200 -0
- package/src/hidden-skills/groundwork-bet/workflows/02-design.md +178 -0
- package/src/hidden-skills/groundwork-bet/workflows/03-decomposition.md +242 -0
- package/src/hidden-skills/groundwork-bet/workflows/04-delivery.md +226 -0
- package/src/hidden-skills/groundwork-bet/workflows/05-validation.md +210 -0
- package/src/hidden-skills/groundwork-design-system/instructions.md +125 -0
- package/src/hidden-skills/groundwork-design-system/templates/brand-tokens.md +182 -0
- package/src/hidden-skills/groundwork-design-system/templates/design-system-cache.md +64 -0
- package/src/hidden-skills/groundwork-design-system/tracks/_foundation.md +136 -0
- package/src/hidden-skills/groundwork-design-system/tracks/agentic-protocol.md +269 -0
- package/src/hidden-skills/groundwork-design-system/tracks/cli.md +355 -0
- package/src/hidden-skills/groundwork-design-system/tracks/graphical-ui.md +330 -0
- package/src/hidden-skills/groundwork-design-system-extract/instructions.md +124 -0
- package/src/hidden-skills/groundwork-design-system-extract/templates/design-system-extract-cache.md +19 -0
- package/src/hidden-skills/groundwork-designer/SKILL.md +108 -0
- package/src/hidden-skills/groundwork-designer/references/accessibility.md +33 -0
- package/src/hidden-skills/groundwork-designer/references/ai-native-design.md +37 -0
- package/src/hidden-skills/groundwork-designer/references/design-review.md +29 -0
- package/src/hidden-skills/groundwork-designer/references/design-systems-and-tokens.md +33 -0
- package/src/hidden-skills/groundwork-designer/references/interaction-and-motion.md +37 -0
- package/src/hidden-skills/groundwork-designer/references/layout-and-space.md +33 -0
- package/src/hidden-skills/groundwork-designer/references/usability-and-ux.md +33 -0
- package/src/hidden-skills/groundwork-designer/references/visual-craft.md +49 -0
- package/src/hidden-skills/groundwork-designer/sync-anchor.md +20 -0
- package/src/hidden-skills/groundwork-doc-sync/instructions.md +100 -0
- package/src/hidden-skills/groundwork-elicit/instructions.md +66 -0
- package/src/hidden-skills/groundwork-elicit/methods.md +65 -0
- package/src/hidden-skills/groundwork-infra-adopt/instructions.md +168 -0
- package/src/hidden-skills/groundwork-infra-adopt/templates/infra-adopt-cache.md +21 -0
- package/src/hidden-skills/groundwork-mvp/instructions.md +223 -0
- package/src/hidden-skills/groundwork-mvp/templates/mvp-cache.md +9 -0
- package/src/hidden-skills/groundwork-patch/instructions.md +40 -0
- package/src/hidden-skills/groundwork-persona/instructions.md +65 -0
- package/src/hidden-skills/groundwork-product/SKILL.md +102 -0
- package/src/hidden-skills/groundwork-product/references/ai-native-product.md +45 -0
- package/src/hidden-skills/groundwork-product/references/discovery-and-opportunity.md +38 -0
- package/src/hidden-skills/groundwork-product/references/product-risks.md +52 -0
- package/src/hidden-skills/groundwork-product/references/requirements-and-specs.md +39 -0
- package/src/hidden-skills/groundwork-product/references/scope-and-sequencing.md +35 -0
- package/src/hidden-skills/groundwork-product/references/shaping-and-appetite.md +48 -0
- package/src/hidden-skills/groundwork-product/references/success-metrics-and-signals.md +37 -0
- package/src/hidden-skills/groundwork-product/sync-anchor.md +19 -0
- package/src/hidden-skills/groundwork-product-brief/instructions.md +231 -0
- package/src/hidden-skills/groundwork-product-brief-extract/instructions.md +139 -0
- package/src/hidden-skills/groundwork-product-brief-extract/templates/product-brief-extract-cache.md +17 -0
- package/src/hidden-skills/groundwork-review/checklists/architecture.md +93 -0
- package/src/hidden-skills/groundwork-review/checklists/bet-pitch.md +94 -0
- package/src/hidden-skills/groundwork-review/checklists/decomposition.md +135 -0
- package/src/hidden-skills/groundwork-review/checklists/design-system.md +85 -0
- package/src/hidden-skills/groundwork-review/checklists/domain-entity.md +66 -0
- package/src/hidden-skills/groundwork-review/checklists/implementation-readiness.md +47 -0
- package/src/hidden-skills/groundwork-review/checklists/infrastructure.md +68 -0
- package/src/hidden-skills/groundwork-review/checklists/maturity.md +71 -0
- package/src/hidden-skills/groundwork-review/checklists/product-brief.md +69 -0
- package/src/hidden-skills/groundwork-review/checklists/technical-design.md +112 -0
- package/src/hidden-skills/groundwork-review/instructions.md +181 -0
- package/src/hidden-skills/groundwork-scaffold/instructions.md +254 -0
- package/src/hidden-skills/groundwork-scaffold/phases/01-ingestion-service-mapping.md +87 -0
- package/src/hidden-skills/groundwork-scaffold/phases/02-scaffolding-execution.md +15 -0
- package/src/hidden-skills/groundwork-scaffold/phases/03-service-documentation-api-stubs.md +100 -0
- package/src/hidden-skills/groundwork-scaffold/phases/04-infrastructure-verification.md +17 -0
- package/src/hidden-skills/groundwork-scaffold/phases/05-draft-review.md +19 -0
- package/src/hidden-skills/groundwork-scaffold/phases/06-commit.md +19 -0
- package/src/hidden-skills/groundwork-scaffold/templates/scaffold-cache.md +23 -0
- package/src/hidden-skills/groundwork-scan/instructions.md +164 -0
- package/src/hidden-skills/groundwork-scan/references/digest-schema.md +66 -0
- package/src/hidden-skills/groundwork-scan/references/exclusions.md +44 -0
- package/src/hidden-skills/groundwork-scan/templates/architecture-findings.md +42 -0
- package/src/hidden-skills/groundwork-scan/templates/design-findings.md +23 -0
- package/src/hidden-skills/groundwork-scan/templates/overview.md +26 -0
- package/src/hidden-skills/groundwork-scan/templates/product-findings.md +23 -0
- package/src/hidden-skills/groundwork-scan/templates/scan-state.json +19 -0
- package/src/hidden-skills/groundwork-stack-forge/instructions.md +150 -0
- package/src/hidden-skills/groundwork-stack-forge/references/authoring-engineer-skills.md +107 -0
- package/src/hidden-skills/groundwork-surface-activation/instructions.md +138 -0
- package/src/hidden-skills/groundwork-update/briefs/reconcile-worker.md +196 -0
- package/src/hidden-skills/groundwork-update/instructions.md +200 -0
- package/src/hidden-skills/groundwork-writer/SKILL.md +278 -0
- package/src/hidden-skills/maturity-model.md +125 -0
- package/src/hidden-skills/operating-contract.md +400 -0
- package/src/hidden-skills/repo-map-schema.md +90 -0
- package/src/hidden-skills/templates/adr.md +57 -0
- package/src/hidden-skills/templates/capability-ports.md +71 -0
- package/src/hidden-skills/templates/discovery-notes.md +33 -0
- package/src/hidden-skills/templates/domain-entity.md +80 -0
- package/src/hidden-skills/templates/gap-ledger.md +21 -0
- package/src/hidden-skills/templates/handoff.md +37 -0
- package/src/hidden-skills/templates/maturity.md +39 -0
- package/src/hidden-skills/templates/surfaces.md +207 -0
- package/src/skills/groundwork-check/SKILL.md +56 -0
- package/src/skills/groundwork-check/instructions.md +70 -0
- package/src/skills/groundwork-orchestrator/SKILL.md +176 -0
- package/src/skills/groundwork-orchestrator/workflow-index.md +50 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Testing
|
|
3
|
+
description: Go honeycomb testing with Testcontainers, table-driven tests, service perimeter tests, and httptest.
|
|
4
|
+
status: active
|
|
5
|
+
last_reviewed: 2026-05-26
|
|
6
|
+
---
|
|
7
|
+
# Testing
|
|
8
|
+
|
|
9
|
+
## TL;DR
|
|
10
|
+
|
|
11
|
+
Service perimeter tests are our default: real Postgres via Testcontainers, real HTTP via `httptest`, no mocks inside the service boundary. Unit tests exist for isolated, complex logic only. The default shape is the **test honeycomb** — a fat middle of sociable service tests, a thin solitary-unit layer, a few end-to-end checks — not the pyramid, which assumes a database in a test is expensive. This is the Go idiom of the framework testing canon (`docs/principles/foundations/testing.md`); the canon is the parent principle and wins on any disagreement.
|
|
12
|
+
|
|
13
|
+
## Why this matters
|
|
14
|
+
|
|
15
|
+
Tests that mock the database tell you the code compiles and the mock behaves as you programmed it — not that the real system works. Testcontainers has eliminated the main excuse for mocking Postgres. A service perimeter test catches the handler, service, repository, and schema working together; a unit test catches none of those integration points. The cost of a slow test suite is paid once per CI run; the cost of a mock that diverges from production is paid in incidents.
|
|
16
|
+
|
|
17
|
+
## The testing tiers
|
|
18
|
+
|
|
19
|
+
### Tier 1 — Service perimeter tests (default)
|
|
20
|
+
|
|
21
|
+
Most tests live here. They start a real Postgres container, run migrations, exercise the handler through `httptest.NewRecorder`, and assert on HTTP responses and database state.
|
|
22
|
+
|
|
23
|
+
```go
|
|
24
|
+
func TestCreateMeeting(t *testing.T) {
|
|
25
|
+
ctx := context.Background()
|
|
26
|
+
|
|
27
|
+
pg, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
|
|
28
|
+
ContainerRequest: testcontainers.ContainerRequest{
|
|
29
|
+
Image: "postgres:16",
|
|
30
|
+
ExposedPorts: []string{"5432/tcp"},
|
|
31
|
+
Env: map[string]string{
|
|
32
|
+
"POSTGRES_PASSWORD": "test",
|
|
33
|
+
"POSTGRES_DB": "service_test",
|
|
34
|
+
},
|
|
35
|
+
WaitingFor: wait.ForListeningPort("5432/tcp"),
|
|
36
|
+
},
|
|
37
|
+
Started: true,
|
|
38
|
+
})
|
|
39
|
+
require.NoError(t, err)
|
|
40
|
+
t.Cleanup(func() { pg.Terminate(ctx) })
|
|
41
|
+
|
|
42
|
+
connStr, _ := pg.ConnectionString(ctx, "sslmode=disable")
|
|
43
|
+
db, err := sql.Open("pgx", connStr)
|
|
44
|
+
require.NoError(t, err)
|
|
45
|
+
|
|
46
|
+
// run migrations
|
|
47
|
+
require.NoError(t, migrate.Up(ctx, db))
|
|
48
|
+
|
|
49
|
+
handler := buildHandler(db) // your composition root helper
|
|
50
|
+
rec := httptest.NewRecorder()
|
|
51
|
+
req := httptest.NewRequest(http.MethodPost, "/meetings", body(t, createReq))
|
|
52
|
+
handler.ServeHTTP(rec, req)
|
|
53
|
+
|
|
54
|
+
require.Equal(t, http.StatusCreated, rec.Code)
|
|
55
|
+
// assert database state
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Use `t.Cleanup` for container teardown. Use `require` for fatal assertions; `assert` for non-fatal checks on the same response.
|
|
60
|
+
|
|
61
|
+
### Tier 2 — Unit tests (complex isolated logic only)
|
|
62
|
+
|
|
63
|
+
Write a unit test when:
|
|
64
|
+
|
|
65
|
+
- The function has complex conditional logic or multiple branches that would be expensive to exercise through HTTP
|
|
66
|
+
- The function is pure (no I/O, no database) and has clear inputs/outputs
|
|
67
|
+
- Validating edge cases would require brittle HTTP request construction
|
|
68
|
+
|
|
69
|
+
Do not write a unit test because it is faster or easier to write. A unit test that passes while the integrated system is broken is a false signal.
|
|
70
|
+
|
|
71
|
+
```go
|
|
72
|
+
func TestScoringLogic(t *testing.T) {
|
|
73
|
+
cases := []struct {
|
|
74
|
+
name string
|
|
75
|
+
input ScoringInput
|
|
76
|
+
want float64
|
|
77
|
+
}{
|
|
78
|
+
{"zero input", ScoringInput{}, 0},
|
|
79
|
+
{"full confidence", ScoringInput{Confidence: 1.0, Length: 100}, 1.0},
|
|
80
|
+
{"penalises short segments", ScoringInput{Confidence: 1.0, Length: 5}, 0.5},
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
for _, tc := range cases {
|
|
84
|
+
t.Run(tc.name, func(t *testing.T) {
|
|
85
|
+
got := Score(tc.input)
|
|
86
|
+
assert.InDelta(t, tc.want, got, 0.001)
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Table-driven tests are the Go idiom for parameterised cases. Use a `cases` slice with descriptive `name` fields so failure output identifies which case broke.
|
|
93
|
+
|
|
94
|
+
### Tier 3 — System tests (rare, explicit)
|
|
95
|
+
|
|
96
|
+
Full end-to-end tests across multiple live services. These run in a dedicated CI stage against a deployed environment, not on every PR. They are expensive to write and maintain — add one only when no Tier 1 test can reach the integration point being verified.
|
|
97
|
+
|
|
98
|
+
## Test structure
|
|
99
|
+
|
|
100
|
+
### Package layout
|
|
101
|
+
|
|
102
|
+
Test files live in `_test.go` files alongside the code they test. Internal tests use the same package name (`package meetings`); black-box tests use the `_test` suffix (`package meetings_test`). Prefer black-box tests for handlers and services to prevent coupling tests to unexported implementation details.
|
|
103
|
+
|
|
104
|
+
### Shared test helpers
|
|
105
|
+
|
|
106
|
+
Shared helpers (container setup, database fixtures, request builders) live in `internal/testutil/` and are only compiled for tests (`package testutil`). They are not shipped with the binary.
|
|
107
|
+
|
|
108
|
+
### Test isolation
|
|
109
|
+
|
|
110
|
+
Each test creates its own database state. Use a fresh schema per test run, or truncate tables in `t.Cleanup`. Do not share mutable state across tests — parallel tests will race.
|
|
111
|
+
|
|
112
|
+
### Parallel tests
|
|
113
|
+
|
|
114
|
+
Mark independent tests with `t.Parallel()`. Tests that share a container must synchronise table state or use separate databases/schemas. Testcontainers supports `ReuseRequest` for container reuse across a test suite; use it for long-lived containers that are read-only.
|
|
115
|
+
|
|
116
|
+
## What to mock
|
|
117
|
+
|
|
118
|
+
Mock only what you cannot make real or what is genuinely too expensive:
|
|
119
|
+
|
|
120
|
+
| Dependency | Approach |
|
|
121
|
+
|---|---|
|
|
122
|
+
| Postgres | Real container via Testcontainers |
|
|
123
|
+
| External HTTP APIs | `httptest.NewServer` returning canned responses |
|
|
124
|
+
| LLM / embedding providers | Interface mock with fixed outputs |
|
|
125
|
+
| Pub/Sub | `testcontainers/modules/pubsub` or interface mock |
|
|
126
|
+
| Time | Pass `time.Time` / `func() time.Time` as dependency; no global `time.Now` |
|
|
127
|
+
|
|
128
|
+
Do not mock the database. Do not mock internal service or repository interfaces. Mocking your own internals tests the mock, not the code.
|
|
129
|
+
|
|
130
|
+
## Running tests
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# all unit and service tests
|
|
134
|
+
go test ./...
|
|
135
|
+
|
|
136
|
+
# with race detector (required before merging concurrency changes)
|
|
137
|
+
go test -race ./...
|
|
138
|
+
|
|
139
|
+
# specific package
|
|
140
|
+
go test ./internal/meetings/...
|
|
141
|
+
|
|
142
|
+
# verbose output for a single test
|
|
143
|
+
go test -v -run TestCreateMeeting ./internal/meetings/...
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Trace assertions — observability is a test surface
|
|
147
|
+
|
|
148
|
+
A critical-path request must emit an unbroken trace; a missing span is a test failure, not an instrumentation TODO. The mechanism is the OTel SDK's **in-memory span exporter** — register one in the test process, exercise the handler, and assert on the finished spans (the entry span exists, the work span is its descendant, the attributes a dashboard query depends on are present). Use `go.opentelemetry.io/otel/sdk/trace/tracetest` (`NewInMemoryExporter`), no external tooling. Assert what the contract promises and let the rest float — pinning the whole span tree couples the test to implementation.
|
|
149
|
+
|
|
150
|
+
## Mutation testing — the assertion-quality read-out
|
|
151
|
+
|
|
152
|
+
A fat service-perimeter test drives many branches through one HTTP call and can *execute* them all while only asserting on the response body. Mutation testing is the instrument that proves the suite checks what it runs: inject a fault, confirm a test fails; a surviving mutant is a covered-but-unchecked line. It is a **signal, never a gate**. Go's tooling is immature (`gremlins` is pre-1.0 and slow; `go-mutesting` is unmaintained), so here it stays a hand-run spot check on a dense package under active change, not a CI expectation.
|
|
153
|
+
|
|
154
|
+
## Generate the inputs you can't enumerate
|
|
155
|
+
|
|
156
|
+
Example-based tests check the cases you thought of; the bugs live in the cases you didn't. For dense, boundary-poor logic with a real invariant — a round-trip, a parser that must never panic, a calculation with an algebraic law — state the property and let the framework generate and shrink counterexamples (`pgregory.net/rapid`, or stdlib `testing/quick`). At the byte boundary, native `go test -fuzz` is first-class for parsers and decoders, and a failing input is saved under `testdata/fuzz/` as a permanent regression seed. Reach for these where invariants are real, not everywhere.
|
|
157
|
+
|
|
158
|
+
## Naming
|
|
159
|
+
|
|
160
|
+
Name a test by behaviour, not implementation: `[Function] should [expected outcome] when [condition]`. `TestCreateItem_Success` conveys nothing the dashboard does not already show; a failing name should let an on-call engineer form a hypothesis without opening the file.
|
|
161
|
+
|
|
162
|
+
## Anti-patterns
|
|
163
|
+
|
|
164
|
+
- **Mocking the database.** The whole point is to test the repository against a real schema.
|
|
165
|
+
- **`testing.Short()` skipping service tests.** Service tests are fast; don't gate-keep them.
|
|
166
|
+
- **Test helpers that test nothing.** A helper that builds a fully valid object in one line is fine; a helper that makes assertions on your behalf hides failures.
|
|
167
|
+
- **Magic `time.Sleep` in tests.** Use `eventually` loops with tight timeouts, or make the behaviour deterministic.
|
|
168
|
+
- **One giant test.** Each test case should be independently runnable and independently failing.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
root = "."
|
|
2
|
+
testdata_dir = "testdata"
|
|
3
|
+
tmp_dir = "tmp"
|
|
4
|
+
|
|
5
|
+
[build]
|
|
6
|
+
args_bin = []
|
|
7
|
+
bin = "./tmp/main"
|
|
8
|
+
cmd = "go build -o ./tmp/main ./cmd/api"
|
|
9
|
+
delay = 1000
|
|
10
|
+
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
|
|
11
|
+
exclude_file = []
|
|
12
|
+
exclude_regex = ["_test.go"]
|
|
13
|
+
exclude_unchanged = false
|
|
14
|
+
follow_symlink = false
|
|
15
|
+
full_bin = ""
|
|
16
|
+
include_dir = []
|
|
17
|
+
include_ext = ["go", "tpl", "tmpl", "html"]
|
|
18
|
+
include_file = []
|
|
19
|
+
kill_delay = "0s"
|
|
20
|
+
log = "build-errors.log"
|
|
21
|
+
send_interrupt = false
|
|
22
|
+
stop_on_error = true
|
|
23
|
+
|
|
24
|
+
[color]
|
|
25
|
+
app = ""
|
|
26
|
+
build = "yellow"
|
|
27
|
+
main = "magenta"
|
|
28
|
+
runner = "green"
|
|
29
|
+
watcher = "cyan"
|
|
30
|
+
|
|
31
|
+
[log]
|
|
32
|
+
time = false
|
|
33
|
+
|
|
34
|
+
[misc]
|
|
35
|
+
clean_on_exit = false
|
|
36
|
+
|
|
37
|
+
[screen]
|
|
38
|
+
clear_on_rebuild = false
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
version: "2"
|
|
2
|
+
|
|
3
|
+
run:
|
|
4
|
+
concurrency: 4
|
|
5
|
+
|
|
6
|
+
linters:
|
|
7
|
+
default: none
|
|
8
|
+
enable:
|
|
9
|
+
- bodyclose
|
|
10
|
+
- depguard
|
|
11
|
+
- errcheck
|
|
12
|
+
- gosec
|
|
13
|
+
- govet
|
|
14
|
+
- ineffassign
|
|
15
|
+
- nilerr
|
|
16
|
+
- prealloc
|
|
17
|
+
- staticcheck
|
|
18
|
+
- unparam
|
|
19
|
+
- unused
|
|
20
|
+
settings:
|
|
21
|
+
govet:
|
|
22
|
+
enable:
|
|
23
|
+
- shadow
|
|
24
|
+
# depguard enforces the inward dependency rule mechanically: the core
|
|
25
|
+
# (internal/core/... — domain entities and the application services that
|
|
26
|
+
# declare the interfaces they consume) must never import an edge adapter or
|
|
27
|
+
# an infrastructure driver. Adapters (internal/postgres, internal/kafka, …)
|
|
28
|
+
# and the composition root (cmd/...) may import anything; the arrow only ever
|
|
29
|
+
# points inward (edge -> core). This makes the architecture a CI gate, not a
|
|
30
|
+
# convention. A deliberate internal/core -> internal/postgres import fails the
|
|
31
|
+
# `golangci-lint run`.
|
|
32
|
+
depguard:
|
|
33
|
+
rules:
|
|
34
|
+
core:
|
|
35
|
+
files:
|
|
36
|
+
- "**/internal/core/**"
|
|
37
|
+
deny:
|
|
38
|
+
- pkg: "<%= name %>/internal/postgres"
|
|
39
|
+
desc: "the core declares interfaces; it must not import the postgres adapter (edge -> core only)"
|
|
40
|
+
- pkg: "<%= name %>/internal/kafka"
|
|
41
|
+
desc: "the core must not import the kafka adapter (edge -> core only)"
|
|
42
|
+
- pkg: "<%= name %>/internal/pubsub"
|
|
43
|
+
desc: "the core must not import the pubsub adapter (edge -> core only)"
|
|
44
|
+
- pkg: "<%= name %>/internal/httpclient"
|
|
45
|
+
desc: "the core must not import the outbound HTTP adapter (edge -> core only)"
|
|
46
|
+
- pkg: "<%= name %>/internal/websocket"
|
|
47
|
+
desc: "the core must not import the websocket adapter (edge -> core only)"
|
|
48
|
+
- pkg: "<%= name %>/internal/llm"
|
|
49
|
+
desc: "the core must not import the llm adapter (edge -> core only)"
|
|
50
|
+
- pkg: "<%= name %>/internal/entrypoints"
|
|
51
|
+
desc: "the core must not import the inbound HTTP edge (edge -> core only)"
|
|
52
|
+
- pkg: "database/sql"
|
|
53
|
+
desc: "the core is persistence-agnostic; SQL belongs in internal/postgres"
|
|
54
|
+
- pkg: "net/http"
|
|
55
|
+
desc: "the core is transport-agnostic; HTTP belongs at the edges"
|
|
56
|
+
- pkg: "github.com/go-chi/chi/v5"
|
|
57
|
+
desc: "routing is an edge concern; keep web frameworks out of the core"
|
|
58
|
+
- pkg: "github.com/danielgtaylor/huma/v2"
|
|
59
|
+
desc: "the API framework is an edge concern; keep it out of the core"
|
|
60
|
+
- pkg: "github.com/gorilla/websocket"
|
|
61
|
+
desc: "the websocket driver belongs in internal/websocket, not the core"
|
|
62
|
+
- pkg: "github.com/lib/pq"
|
|
63
|
+
desc: "the postgres driver belongs in internal/postgres, not the core"
|
|
64
|
+
- pkg: "github.com/confluentinc/confluent-kafka-go/v2/kafka"
|
|
65
|
+
desc: "the kafka driver belongs in internal/kafka, not the core"
|
|
66
|
+
- pkg: "cloud.google.com/go/pubsub"
|
|
67
|
+
desc: "the pubsub driver belongs in internal/pubsub, not the core"
|
|
68
|
+
domain:
|
|
69
|
+
files:
|
|
70
|
+
- "**/internal/core/domain/**"
|
|
71
|
+
deny:
|
|
72
|
+
- pkg: "<%= name %>/internal"
|
|
73
|
+
desc: "the domain depends on nothing inside the module; pure types and rules only"
|
|
74
|
+
exclusions:
|
|
75
|
+
generated: lax
|
|
76
|
+
rules:
|
|
77
|
+
- path: _test\.go
|
|
78
|
+
linters:
|
|
79
|
+
- bodyclose
|
|
80
|
+
- errcheck
|
|
81
|
+
- gosec
|
|
82
|
+
- unparam
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
asyncapi: 3.0.0
|
|
2
|
+
info:
|
|
3
|
+
title: <%= name %> PubSub API
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
description: Asynchronous event schema for <%= name %> backend message brokers.
|
|
6
|
+
servers:
|
|
7
|
+
production:
|
|
8
|
+
host: broker.example.com
|
|
9
|
+
protocol: <%= messaging === 'kafka' ? 'kafka' : 'googlepubsub' %>
|
|
10
|
+
channels:
|
|
11
|
+
<%= name %>-events:
|
|
12
|
+
address: <%= name %>.events
|
|
13
|
+
messages:
|
|
14
|
+
publish:
|
|
15
|
+
$ref: '#/components/messages/cloudEvent'
|
|
16
|
+
components:
|
|
17
|
+
messages:
|
|
18
|
+
cloudEvent:
|
|
19
|
+
payload:
|
|
20
|
+
type: object
|
|
21
|
+
properties:
|
|
22
|
+
specversion:
|
|
23
|
+
type: string
|
|
24
|
+
id:
|
|
25
|
+
type: string
|
|
26
|
+
type:
|
|
27
|
+
type: string
|
|
28
|
+
source:
|
|
29
|
+
type: string
|
|
30
|
+
time:
|
|
31
|
+
type: string
|
|
32
|
+
data:
|
|
33
|
+
type: object
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
asyncapi: 3.0.0
|
|
2
|
+
info:
|
|
3
|
+
title: <%= name %> WebSocket API
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
description: WebSocket API for real-time <%= name %> events.
|
|
6
|
+
servers:
|
|
7
|
+
dev:
|
|
8
|
+
host: localhost:4000
|
|
9
|
+
protocol: ws
|
|
10
|
+
pathname: /api/v1/ws
|
|
11
|
+
channels:
|
|
12
|
+
events:
|
|
13
|
+
address: /api/v1/ws
|
|
14
|
+
messages:
|
|
15
|
+
subscribe:
|
|
16
|
+
$ref: '#/components/messages/cloudEvent'
|
|
17
|
+
components:
|
|
18
|
+
messages:
|
|
19
|
+
cloudEvent:
|
|
20
|
+
payload:
|
|
21
|
+
type: object
|
|
22
|
+
properties:
|
|
23
|
+
specversion:
|
|
24
|
+
type: string
|
|
25
|
+
id:
|
|
26
|
+
type: string
|
|
27
|
+
type:
|
|
28
|
+
type: string
|
|
29
|
+
source:
|
|
30
|
+
type: string
|
|
31
|
+
time:
|
|
32
|
+
type: string
|
|
33
|
+
data:
|
|
34
|
+
type: object
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"fmt"
|
|
6
|
+
"net/http"
|
|
7
|
+
"os"
|
|
8
|
+
"os/signal"
|
|
9
|
+
"syscall"
|
|
10
|
+
"time"
|
|
11
|
+
|
|
12
|
+
"github.com/rs/zerolog"
|
|
13
|
+
"github.com/rs/zerolog/log"
|
|
14
|
+
_ "github.com/joho/godotenv/autoload"
|
|
15
|
+
_ "github.com/lib/pq"
|
|
16
|
+
|
|
17
|
+
"<%= name %>/internal/config"
|
|
18
|
+
"<%= name %>/internal/core/service"
|
|
19
|
+
"<%= name %>/internal/entrypoints/api"
|
|
20
|
+
"<%= name %>/internal/postgres"
|
|
21
|
+
<% if (websockets) { %>
|
|
22
|
+
"<%= name %>/internal/websocket"
|
|
23
|
+
<% } %>
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
func main() {
|
|
27
|
+
setupLogger()
|
|
28
|
+
|
|
29
|
+
cfg := config.Load()
|
|
30
|
+
|
|
31
|
+
// Initialize OpenTelemetry
|
|
32
|
+
otelShutdown, err := config.InitProvider(context.Background(), "<%= name %>", cfg.Telemetry.CollectorURL)
|
|
33
|
+
if err != nil {
|
|
34
|
+
log.Fatal().Err(err).Msg("Failed to initialize OpenTelemetry")
|
|
35
|
+
}
|
|
36
|
+
defer otelShutdown(context.Background())
|
|
37
|
+
|
|
38
|
+
db, err := postgres.NewDB(cfg.Database.URI)
|
|
39
|
+
if err != nil {
|
|
40
|
+
log.Fatal().Err(err).Msg("Failed to connect to database")
|
|
41
|
+
}
|
|
42
|
+
defer db.Close()
|
|
43
|
+
|
|
44
|
+
<% if (websockets) { %>
|
|
45
|
+
// Initialize WebSocket Hub
|
|
46
|
+
wsHub := websocket.NewHub(cfg)
|
|
47
|
+
go wsHub.Run()
|
|
48
|
+
|
|
49
|
+
// Composition root: wire adapters into services
|
|
50
|
+
router, err := buildApp(cfg, db, wsHub)
|
|
51
|
+
<% } else { %>
|
|
52
|
+
// Composition root: wire adapters into services
|
|
53
|
+
router, err := buildApp(cfg, db)
|
|
54
|
+
<% } %>
|
|
55
|
+
if err != nil {
|
|
56
|
+
log.Fatal().Err(err).Msg("Failed to build application")
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
srv := &http.Server{
|
|
60
|
+
Addr: fmt.Sprintf(":%d", cfg.Server.Port),
|
|
61
|
+
Handler: router,
|
|
62
|
+
ReadTimeout: 15 * time.Second,
|
|
63
|
+
WriteTimeout: 0,
|
|
64
|
+
IdleTimeout: 60 * time.Second,
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
go func() {
|
|
68
|
+
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
69
|
+
log.Fatal().Err(err).Msg("Server failed to start")
|
|
70
|
+
}
|
|
71
|
+
}()
|
|
72
|
+
|
|
73
|
+
log.Info().Int("port", cfg.Server.Port).Msg("Service ready")
|
|
74
|
+
|
|
75
|
+
<% if (websockets) { %>
|
|
76
|
+
gracefulShutdown(srv, wsHub)
|
|
77
|
+
<% } else { %>
|
|
78
|
+
gracefulShutdown(srv)
|
|
79
|
+
<% } %>
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// buildApp wires all repositories, external clients, and services together,
|
|
83
|
+
// returning the fully configured HTTP handler. This enforces explicit dependency injection.
|
|
84
|
+
<% if (websockets) { %>
|
|
85
|
+
func buildApp(cfg *config.Config, db *postgres.DB, wsHub *websocket.Hub) (http.Handler, error) {
|
|
86
|
+
<% } else { %>
|
|
87
|
+
func buildApp(cfg *config.Config, db *postgres.DB) (http.Handler, error) {
|
|
88
|
+
<% } %>
|
|
89
|
+
// --- Adapters ---
|
|
90
|
+
|
|
91
|
+
txManager := postgres.NewTransactionManager(db)
|
|
92
|
+
entityRepo := postgres.NewRepository(db)
|
|
93
|
+
<% if (messaging !== 'none') { %>
|
|
94
|
+
outboxRepo := postgres.NewOutboxRepository(db)
|
|
95
|
+
<% } %>
|
|
96
|
+
|
|
97
|
+
// --- Services (Use Cases) ---
|
|
98
|
+
|
|
99
|
+
<% if (websockets) { %>
|
|
100
|
+
appSvc := service.NewAppService(txManager, entityRepo, wsHub<% if (messaging !== 'none') { %>, outboxRepo<% } %>)
|
|
101
|
+
<% } else { %>
|
|
102
|
+
appSvc := service.NewAppService(txManager, entityRepo, nil<% if (messaging !== 'none') { %>, outboxRepo<% } %>)
|
|
103
|
+
<% } %>
|
|
104
|
+
|
|
105
|
+
<% if (auth === 'clerk') { %>
|
|
106
|
+
userRepo := postgres.NewUserRepository(db)
|
|
107
|
+
userSvc := service.NewUserService(userRepo)
|
|
108
|
+
<% } %>
|
|
109
|
+
|
|
110
|
+
// --- Router ---
|
|
111
|
+
<% if (websockets) { %>
|
|
112
|
+
router := api.RegisterRoutes(cfg, db.DB, appSvc<% if (auth === 'clerk') { %>, userSvc<% } %>, wsHub)
|
|
113
|
+
<% } else { %>
|
|
114
|
+
router := api.RegisterRoutes(cfg, db.DB, appSvc<% if (auth === 'clerk') { %>, userSvc<% } %>)
|
|
115
|
+
<% } %>
|
|
116
|
+
|
|
117
|
+
return router, nil
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
func setupLogger() {
|
|
121
|
+
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
|
|
122
|
+
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
<% if (websockets) { %>
|
|
126
|
+
func gracefulShutdown(srv *http.Server, wsHub *websocket.Hub) {
|
|
127
|
+
<% } else { %>
|
|
128
|
+
func gracefulShutdown(srv *http.Server) {
|
|
129
|
+
<% } %>
|
|
130
|
+
quit := make(chan os.Signal, 1)
|
|
131
|
+
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
|
132
|
+
<-quit
|
|
133
|
+
|
|
134
|
+
log.Info().Msg("Shutting down server...")
|
|
135
|
+
|
|
136
|
+
<% if (websockets) { %>
|
|
137
|
+
log.Info().Msg("Stopping WebSocket Hub...")
|
|
138
|
+
wsHub.Stop()
|
|
139
|
+
<% } %>
|
|
140
|
+
|
|
141
|
+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
142
|
+
defer cancel()
|
|
143
|
+
|
|
144
|
+
if err := srv.Shutdown(ctx); err != nil {
|
|
145
|
+
log.Fatal().Err(err).Msg("Server forced to shutdown")
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
log.Info().Msg("Server exited properly")
|
|
149
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"net/http"
|
|
6
|
+
"net/http/httptest"
|
|
7
|
+
"os"
|
|
8
|
+
"testing"
|
|
9
|
+
"time"
|
|
10
|
+
"path/filepath"
|
|
11
|
+
|
|
12
|
+
"github.com/stretchr/testify/require"
|
|
13
|
+
"github.com/testcontainers/testcontainers-go"
|
|
14
|
+
"github.com/testcontainers/testcontainers-go/modules/postgres"
|
|
15
|
+
"github.com/testcontainers/testcontainers-go/wait"
|
|
16
|
+
|
|
17
|
+
"<%= name %>/internal/config"
|
|
18
|
+
pg "<%= name %>/internal/postgres"
|
|
19
|
+
<% if (websockets) { %>
|
|
20
|
+
"<%= name %>/internal/websocket"
|
|
21
|
+
<% } %>
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
func TestAPIIntegration(t *testing.T) {
|
|
25
|
+
if testing.Short() {
|
|
26
|
+
t.Skip("skipping integration test")
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
|
30
|
+
defer cancel()
|
|
31
|
+
|
|
32
|
+
// 1. Start Postgres Container
|
|
33
|
+
pgContainer, err := postgres.RunContainer(ctx,
|
|
34
|
+
testcontainers.WithImage("postgres:16-alpine"),
|
|
35
|
+
postgres.WithDatabase("<%= name %>_test"),
|
|
36
|
+
postgres.WithUsername("testuser"),
|
|
37
|
+
postgres.WithPassword("testpass"),
|
|
38
|
+
testcontainers.WithWaitStrategy(
|
|
39
|
+
wait.ForLog("database system is ready to accept connections").
|
|
40
|
+
WithOccurrence(2).WithStartupTimeout(5*time.Second)),
|
|
41
|
+
)
|
|
42
|
+
require.NoError(t, err)
|
|
43
|
+
defer func() {
|
|
44
|
+
if err := pgContainer.Terminate(context.Background()); err != nil {
|
|
45
|
+
t.Fatalf("failed to terminate container: %s", err)
|
|
46
|
+
}
|
|
47
|
+
}()
|
|
48
|
+
|
|
49
|
+
connStr, err := pgContainer.ConnectionString(ctx, "sslmode=disable")
|
|
50
|
+
require.NoError(t, err)
|
|
51
|
+
|
|
52
|
+
// 2. Set Env variables for Config
|
|
53
|
+
os.Setenv("DATABASE_URL", connStr)
|
|
54
|
+
os.Setenv("PORT", "8080")
|
|
55
|
+
// Dummy OTEL endpoint to prevent failure on startup
|
|
56
|
+
os.Setenv("OTEL_EXPORTER_OTLP_ENDPOINT", "localhost:4317")
|
|
57
|
+
|
|
58
|
+
cfg := config.Load()
|
|
59
|
+
|
|
60
|
+
// 3. Apply Schema
|
|
61
|
+
// In a real integration test, we use the schema diff tool or just execute the SQL
|
|
62
|
+
// Assuming db/schema.sql is available at the project root relative to cmd/api
|
|
63
|
+
schemaPath := filepath.Join("..", "..", "db", "schema.sql")
|
|
64
|
+
schemaBytes, err := os.ReadFile(schemaPath)
|
|
65
|
+
require.NoError(t, err, "failed to read schema.sql from %s", schemaPath)
|
|
66
|
+
|
|
67
|
+
db, err := pg.NewDB(cfg.Database.URI)
|
|
68
|
+
require.NoError(t, err)
|
|
69
|
+
defer db.Close()
|
|
70
|
+
|
|
71
|
+
_, err = db.DB.ExecContext(ctx, string(schemaBytes))
|
|
72
|
+
require.NoError(t, err, "failed to apply schema")
|
|
73
|
+
|
|
74
|
+
<% if (websockets) { %>
|
|
75
|
+
// 4. Initialize WebSocket Hub
|
|
76
|
+
wsHub := websocket.NewHub(cfg)
|
|
77
|
+
go wsHub.Run()
|
|
78
|
+
defer wsHub.Stop()
|
|
79
|
+
|
|
80
|
+
// 5. Build the App
|
|
81
|
+
router, err := buildApp(cfg, db, wsHub)
|
|
82
|
+
<% } else { %>
|
|
83
|
+
// 5. Build the App
|
|
84
|
+
router, err := buildApp(cfg, db)
|
|
85
|
+
<% } %>
|
|
86
|
+
require.NoError(t, err)
|
|
87
|
+
|
|
88
|
+
// 6. Test the /health endpoint
|
|
89
|
+
req := httptest.NewRequest(http.MethodGet, "/health", nil)
|
|
90
|
+
req = req.WithContext(ctx)
|
|
91
|
+
|
|
92
|
+
rr := httptest.NewRecorder()
|
|
93
|
+
router.ServeHTTP(rr, req)
|
|
94
|
+
|
|
95
|
+
require.Equal(t, http.StatusOK, rr.Code)
|
|
96
|
+
|
|
97
|
+
// The health check response should have status ok since db and hub are healthy
|
|
98
|
+
require.Contains(t, rr.Body.String(), `"status":"ok"`)
|
|
99
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"database/sql"
|
|
6
|
+
"os"
|
|
7
|
+
|
|
8
|
+
_ "github.com/lib/pq"
|
|
9
|
+
"github.com/rs/zerolog/log"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
func main() {
|
|
13
|
+
dbURL := os.Getenv("DATABASE_URL")
|
|
14
|
+
if dbURL == "" {
|
|
15
|
+
log.Fatal().Msg("DATABASE_URL environment variable is required")
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
db, err := sql.Open("postgres", dbURL)
|
|
19
|
+
if err != nil {
|
|
20
|
+
log.Fatal().Err(err).Msg("Failed to connect to database")
|
|
21
|
+
}
|
|
22
|
+
defer db.Close()
|
|
23
|
+
|
|
24
|
+
if err := db.Ping(); err != nil {
|
|
25
|
+
log.Fatal().Err(err).Msg("Failed to ping database")
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
log.Info().Msg("Starting idempotency key cleanup worker...")
|
|
29
|
+
|
|
30
|
+
// Delete keys older than 24 hours
|
|
31
|
+
query := `DELETE FROM idempotency_keys WHERE created_at < NOW() - INTERVAL '24 hours'`
|
|
32
|
+
res, err := db.ExecContext(context.Background(), query)
|
|
33
|
+
if err != nil {
|
|
34
|
+
log.Fatal().Err(err).Msg("Failed to execute cleanup query")
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
rowsAffected, _ := res.RowsAffected()
|
|
38
|
+
log.Info().Int64("deleted_keys", rowsAffected).Msg("Cleanup complete")
|
|
39
|
+
}
|