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,307 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatFiles,
|
|
3
|
+
generateFiles,
|
|
4
|
+
Tree,
|
|
5
|
+
names,
|
|
6
|
+
} from '@nx/devkit';
|
|
7
|
+
import * as path from 'path';
|
|
8
|
+
import { recordGeneratorProvenance } from '../shared/provenance';
|
|
9
|
+
import {
|
|
10
|
+
promoteEngineerSkill,
|
|
11
|
+
deployStackDocs,
|
|
12
|
+
ensureOptionalInfra,
|
|
13
|
+
readProjectPrefix,
|
|
14
|
+
} from '../shared/scaffold-helpers';
|
|
15
|
+
import {
|
|
16
|
+
SHADCN_VARS,
|
|
17
|
+
ResolvedVisual,
|
|
18
|
+
resolveVisual,
|
|
19
|
+
} from '../shared/brand-tokens';
|
|
20
|
+
|
|
21
|
+
export interface NextjsAppGeneratorSchema {
|
|
22
|
+
name: string;
|
|
23
|
+
auth: 'none' | 'clerk';
|
|
24
|
+
apiProxy: boolean;
|
|
25
|
+
websockets: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Render app/brand.css from the resolved visual tokens. globals.css imports
|
|
29
|
+
* this file and owns the structure (token mappings + surface utilities); this
|
|
30
|
+
* file is pure values and is regenerated, never hand-edited. */
|
|
31
|
+
function renderBrandCss(v: ResolvedVisual): string {
|
|
32
|
+
const out: string[] = [];
|
|
33
|
+
out.push('/* GENERATED by the GroundWork nextjs-app generator from');
|
|
34
|
+
out.push(' * .groundwork/config/brand-tokens.json — do not hand-edit this file.');
|
|
35
|
+
out.push(' * Re-run the design system to evolve the brand, then regenerate.');
|
|
36
|
+
out.push(' * app/globals.css imports this file and maps these values into Tailwind');
|
|
37
|
+
out.push(' * token utilities and surface classes; components consume those, never');
|
|
38
|
+
out.push(` * these variables directly. Projection source: ${v.source}. */`);
|
|
39
|
+
out.push('');
|
|
40
|
+
out.push(':root {');
|
|
41
|
+
out.push(` --radius: ${v.radius};`);
|
|
42
|
+
for (const name of Object.keys(SHADCN_VARS)) {
|
|
43
|
+
out.push(` --${name}: ${v.shadcn[name].light};`);
|
|
44
|
+
}
|
|
45
|
+
out.push('');
|
|
46
|
+
out.push(' /* Atmosphere — blur radii, elevation stacks, hero gradient. */');
|
|
47
|
+
out.push(` --gw-blur-subtle: ${v.blur.subtle};`);
|
|
48
|
+
out.push(` --gw-blur-standard: ${v.blur.standard};`);
|
|
49
|
+
out.push(` --gw-blur-heavy: ${v.blur.heavy};`);
|
|
50
|
+
out.push(` --gw-shadow-low: ${v.shadow.low.light};`);
|
|
51
|
+
out.push(` --gw-shadow-mid: ${v.shadow.mid.light};`);
|
|
52
|
+
out.push(` --gw-shadow-high: ${v.shadow.high.light};`);
|
|
53
|
+
out.push(` --gw-gradient-hero: ${v.gradientHero.light};`);
|
|
54
|
+
out.push('');
|
|
55
|
+
out.push(' /* Surface treatments — tint + border per named treatment. */');
|
|
56
|
+
for (const name of ['glass', 'elevated', 'hero'] as const) {
|
|
57
|
+
out.push(` --gw-surface-${name}-tint: ${v.surfaces[name].tint.light};`);
|
|
58
|
+
out.push(` --gw-surface-${name}-border: ${v.surfaces[name].border.light};`);
|
|
59
|
+
}
|
|
60
|
+
out.push('');
|
|
61
|
+
out.push(' /* Typography roles — size, line-height, weight, tracking. */');
|
|
62
|
+
for (const [role, r] of Object.entries(v.typeRoles)) {
|
|
63
|
+
out.push(` --gw-text-${role}-size: ${r.size};`);
|
|
64
|
+
out.push(` --gw-text-${role}-line: ${r.line};`);
|
|
65
|
+
out.push(` --gw-text-${role}-weight: ${r.weight};`);
|
|
66
|
+
out.push(` --gw-text-${role}-tracking: ${r.tracking};`);
|
|
67
|
+
}
|
|
68
|
+
out.push('');
|
|
69
|
+
out.push(' /* Motion interaction profiles — duration, easing, transform. */');
|
|
70
|
+
for (const [ctx, m] of Object.entries(v.motion)) {
|
|
71
|
+
out.push(` --gw-motion-${ctx}-duration: ${m.duration};`);
|
|
72
|
+
out.push(` --gw-motion-${ctx}-ease: ${m.ease};`);
|
|
73
|
+
out.push(` --gw-motion-${ctx}-transform: ${m.transform};`);
|
|
74
|
+
}
|
|
75
|
+
out.push('}');
|
|
76
|
+
out.push('');
|
|
77
|
+
out.push('.dark {');
|
|
78
|
+
for (const name of Object.keys(SHADCN_VARS)) {
|
|
79
|
+
out.push(` --${name}: ${v.shadcn[name].dark};`);
|
|
80
|
+
}
|
|
81
|
+
out.push('');
|
|
82
|
+
out.push(' /* Atmosphere — dark-theme variants. */');
|
|
83
|
+
out.push(` --gw-shadow-low: ${v.shadow.low.dark};`);
|
|
84
|
+
out.push(` --gw-shadow-mid: ${v.shadow.mid.dark};`);
|
|
85
|
+
out.push(` --gw-shadow-high: ${v.shadow.high.dark};`);
|
|
86
|
+
out.push(` --gw-gradient-hero: ${v.gradientHero.dark};`);
|
|
87
|
+
for (const name of ['glass', 'elevated', 'hero'] as const) {
|
|
88
|
+
out.push(` --gw-surface-${name}-tint: ${v.surfaces[name].tint.dark};`);
|
|
89
|
+
out.push(` --gw-surface-${name}-border: ${v.surfaces[name].border.dark};`);
|
|
90
|
+
}
|
|
91
|
+
out.push('}');
|
|
92
|
+
out.push('');
|
|
93
|
+
return out.join('\n');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export default async function (tree: Tree, options: NextjsAppGeneratorSchema) {
|
|
97
|
+
const serviceNames = names(options.name);
|
|
98
|
+
const projectRoot = `services/${serviceNames.fileName}`;
|
|
99
|
+
|
|
100
|
+
// Calculate assignedPort from docker-compose.yml (base 4000, sequential)
|
|
101
|
+
let assignedPort = 4000;
|
|
102
|
+
let composeDoc: any = null;
|
|
103
|
+
if (tree.exists('docker-compose.yml')) {
|
|
104
|
+
try {
|
|
105
|
+
const yaml = require('yaml');
|
|
106
|
+
const composeContent = tree.read('docker-compose.yml', 'utf-8');
|
|
107
|
+
composeDoc = yaml.parseDocument(composeContent);
|
|
108
|
+
|
|
109
|
+
const usedPorts = new Set<number>();
|
|
110
|
+
|
|
111
|
+
// Collect ports from docker-compose.yml
|
|
112
|
+
const servicesMap = composeDoc.get('services');
|
|
113
|
+
if (servicesMap && servicesMap.items) {
|
|
114
|
+
for (const item of servicesMap.items) {
|
|
115
|
+
const service = item.value;
|
|
116
|
+
if (service && service.get) {
|
|
117
|
+
const ports = service.get('ports');
|
|
118
|
+
if (ports && ports.items) {
|
|
119
|
+
for (const pItem of ports.items) {
|
|
120
|
+
const portStr = String(pItem.value || pItem);
|
|
121
|
+
const match = portStr.match(/^(\d+):/);
|
|
122
|
+
if (match) {
|
|
123
|
+
usedPorts.add(parseInt(match[1], 10));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Also collect ports from .env files of natively-run services (not in docker-compose)
|
|
132
|
+
if (tree.exists('services')) {
|
|
133
|
+
for (const svcName of tree.children('services') ?? []) {
|
|
134
|
+
const envPath = `services/${svcName}/.env`;
|
|
135
|
+
if (tree.exists(envPath)) {
|
|
136
|
+
const envContent = tree.read(envPath, 'utf-8') ?? '';
|
|
137
|
+
for (const line of envContent.split('\n')) {
|
|
138
|
+
const m = line.match(/^(?:PORT|SERVER_PORT)=(\d+)/);
|
|
139
|
+
if (m) usedPorts.add(parseInt(m[1], 10));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
while (usedPorts.has(assignedPort)) {
|
|
146
|
+
assignedPort++;
|
|
147
|
+
}
|
|
148
|
+
} catch (e) {
|
|
149
|
+
console.warn('Failed to parse docker-compose.yml for port calculation:', e);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const templateOptions = {
|
|
154
|
+
...options,
|
|
155
|
+
...serviceNames,
|
|
156
|
+
assignedPort,
|
|
157
|
+
tmpl: '' // required by generateFiles
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
generateFiles(
|
|
161
|
+
tree,
|
|
162
|
+
path.join(__dirname, '..', '..', '..', '..', 'src', 'generators', 'nextjs-app', 'files'),
|
|
163
|
+
projectRoot,
|
|
164
|
+
templateOptions
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
deployStackDocs(tree, path.join(__dirname, '..', '..', '..', '..', 'src', 'generators', 'nextjs-app', 'docs'));
|
|
168
|
+
|
|
169
|
+
// Nx's generateFiles treats __var__ as template substitution, which
|
|
170
|
+
// conflicts with Next.js dynamic route segments like [...path] and
|
|
171
|
+
// [[...sign-in]]. We use placeholder dir names and rename post-generation.
|
|
172
|
+
const renames: [string, string][] = [
|
|
173
|
+
[`${projectRoot}/app/api/proxy/__path__`, `${projectRoot}/app/api/proxy/[...path]`],
|
|
174
|
+
[`${projectRoot}/app/(auth)/sign-in/__sign-in__`, `${projectRoot}/app/(auth)/sign-in/[[...sign-in]]`],
|
|
175
|
+
[`${projectRoot}/app/(auth)/sign-up/__sign-up__`, `${projectRoot}/app/(auth)/sign-up/[[...sign-up]]`],
|
|
176
|
+
];
|
|
177
|
+
|
|
178
|
+
for (const [oldDir, newDir] of renames) {
|
|
179
|
+
// Find all files under the old directory and move them
|
|
180
|
+
const children = tree.children(oldDir);
|
|
181
|
+
if (children && children.length > 0) {
|
|
182
|
+
for (const child of children) {
|
|
183
|
+
const content = tree.read(`${oldDir}/${child}`);
|
|
184
|
+
if (content) {
|
|
185
|
+
tree.write(`${newDir}/${child}`, content);
|
|
186
|
+
tree.delete(`${oldDir}/${child}`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Project brand-tokens.json's visual block into app/brand.css — the per-app
|
|
193
|
+
// palette + atmosphere layer (elevation, blur, gradients, surface treatments,
|
|
194
|
+
// type-role micro, motion profiles). Parity with electron-app/flutter-app:
|
|
195
|
+
// globals.css imports this file and owns the structure, this file owns the
|
|
196
|
+
// values, and no engineer skill carries a fixed aesthetic catalogue.
|
|
197
|
+
tree.write(
|
|
198
|
+
`${projectRoot}/app/brand.css`,
|
|
199
|
+
renderBrandCss(resolveVisual(tree)),
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
// Auto-inject into docker-compose.yml if it exists
|
|
203
|
+
if (composeDoc) {
|
|
204
|
+
try {
|
|
205
|
+
if (!composeDoc.get('services')) {
|
|
206
|
+
// createNode so the result is a YAMLMap with .has/.set (a plain {} is not).
|
|
207
|
+
composeDoc.set('services', composeDoc.createNode({}));
|
|
208
|
+
}
|
|
209
|
+
const servicesMap = composeDoc.get('services');
|
|
210
|
+
if (!servicesMap.has(serviceNames.fileName)) {
|
|
211
|
+
const envVars = [
|
|
212
|
+
`PORT=${assignedPort}`,
|
|
213
|
+
`OTEL_SERVICE_NAME=${serviceNames.fileName}`,
|
|
214
|
+
'OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318',
|
|
215
|
+
];
|
|
216
|
+
|
|
217
|
+
if (options.apiProxy) {
|
|
218
|
+
envVars.push('API_URL=http://core:4000');
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (options.auth === 'clerk') {
|
|
222
|
+
envVars.push('NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=${CLERK_PUBLISHABLE_KEY}');
|
|
223
|
+
envVars.push('CLERK_SECRET_KEY=${CLERK_SECRET_KEY}');
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const newService: Record<string, unknown> = {
|
|
227
|
+
build: {
|
|
228
|
+
context: `./${projectRoot}`,
|
|
229
|
+
dockerfile: 'Dockerfile'
|
|
230
|
+
},
|
|
231
|
+
container_name: serviceNames.fileName,
|
|
232
|
+
restart: 'unless-stopped',
|
|
233
|
+
ports: [
|
|
234
|
+
`${assignedPort}:${assignedPort}`
|
|
235
|
+
],
|
|
236
|
+
environment: envVars,
|
|
237
|
+
// The node:alpine runtime image has no curl, but ships busybox wget,
|
|
238
|
+
// which probes the health route without an extra binary.
|
|
239
|
+
healthcheck: {
|
|
240
|
+
test: [
|
|
241
|
+
'CMD',
|
|
242
|
+
'wget',
|
|
243
|
+
'-q',
|
|
244
|
+
'--spider',
|
|
245
|
+
`http://localhost:${assignedPort}/api/healthz`
|
|
246
|
+
],
|
|
247
|
+
interval: '10s',
|
|
248
|
+
timeout: '5s',
|
|
249
|
+
retries: 5,
|
|
250
|
+
start_period: '20s'
|
|
251
|
+
},
|
|
252
|
+
networks: [
|
|
253
|
+
'groundwork-net'
|
|
254
|
+
]
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
servicesMap.set(serviceNames.fileName, newService);
|
|
258
|
+
// A Next.js app exports OTLP telemetry but uses no database, so it
|
|
259
|
+
// provisions jaeger only (no longer in the base compose).
|
|
260
|
+
ensureOptionalInfra(composeDoc, servicesMap, {
|
|
261
|
+
usesRedis: false,
|
|
262
|
+
usesPubSub: false,
|
|
263
|
+
usesTelemetry: true,
|
|
264
|
+
projectPrefix: readProjectPrefix(tree),
|
|
265
|
+
});
|
|
266
|
+
tree.write('docker-compose.yml', composeDoc.toString());
|
|
267
|
+
}
|
|
268
|
+
} catch (e) {
|
|
269
|
+
console.warn('Failed to update docker-compose.yml:', e);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Conditionally remove auth files
|
|
274
|
+
if (options.auth !== 'clerk') {
|
|
275
|
+
tree.delete(`${projectRoot}/app/(auth)`);
|
|
276
|
+
tree.delete(`${projectRoot}/proxy.ts`);
|
|
277
|
+
tree.delete(`${projectRoot}/proxy.test.ts`);
|
|
278
|
+
tree.delete(`${projectRoot}/components/providers/production.tsx`);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Conditionally remove API proxy files
|
|
282
|
+
if (!options.apiProxy) {
|
|
283
|
+
tree.delete(`${projectRoot}/app/api/proxy`);
|
|
284
|
+
tree.delete(`${projectRoot}/lib/api`);
|
|
285
|
+
tree.delete(`${projectRoot}/lib/config.ts`);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Conditionally remove websocket files
|
|
289
|
+
if (!options.websockets) {
|
|
290
|
+
tree.delete(`${projectRoot}/app/api/config`);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
promoteEngineerSkill(tree, 'groundwork-nextjs-engineer');
|
|
294
|
+
|
|
295
|
+
await formatFiles(tree);
|
|
296
|
+
|
|
297
|
+
recordGeneratorProvenance(tree, 'nextjs-app', options as unknown as Record<string, unknown>);
|
|
298
|
+
|
|
299
|
+
return () => {
|
|
300
|
+
const { execSync } = require('child_process');
|
|
301
|
+
try {
|
|
302
|
+
execSync('pnpm install', { cwd: projectRoot, stdio: 'inherit' });
|
|
303
|
+
} catch (e) {
|
|
304
|
+
console.warn(`Failed to run pnpm install in ${projectRoot}. Run it manually.`);
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/schema",
|
|
3
|
+
"id": "nextjs-app",
|
|
4
|
+
"title": "Next.js App",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"name": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "The name of the Next.js application",
|
|
10
|
+
"$default": {
|
|
11
|
+
"$source": "argv",
|
|
12
|
+
"index": 0
|
|
13
|
+
},
|
|
14
|
+
"x-prompt": "What name would you like to use for the app?"
|
|
15
|
+
},
|
|
16
|
+
"auth": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"enum": ["none", "clerk"],
|
|
19
|
+
"default": "none",
|
|
20
|
+
"description": "Authentication provider to include",
|
|
21
|
+
"x-prompt": {
|
|
22
|
+
"message": "Which authentication provider should we include?",
|
|
23
|
+
"type": "list",
|
|
24
|
+
"items": [
|
|
25
|
+
{ "value": "none", "label": "None" },
|
|
26
|
+
{ "value": "clerk", "label": "Clerk (User Auth + Middleware)" }
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"apiProxy": {
|
|
31
|
+
"type": "boolean",
|
|
32
|
+
"description": "Include a server-side reverse proxy to a backend API service",
|
|
33
|
+
"default": false,
|
|
34
|
+
"x-prompt": "Do you want to include an API reverse proxy to a backend service?"
|
|
35
|
+
},
|
|
36
|
+
"websockets": {
|
|
37
|
+
"type": "boolean",
|
|
38
|
+
"description": "Include a WebSocket provider with runtime config discovery",
|
|
39
|
+
"default": false,
|
|
40
|
+
"x-prompt": "Do you want to enable WebSocket support?"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"required": ["name"]
|
|
44
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Async Patterns
|
|
3
|
+
description: Structured concurrency, FastAPI async, background tasks, and the application lifecycle for Python microservices.
|
|
4
|
+
status: active
|
|
5
|
+
last_reviewed: 2026-05-26
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Async Patterns
|
|
9
|
+
|
|
10
|
+
## TL;DR
|
|
11
|
+
|
|
12
|
+
A Python microservice built on FastAPI is async-first. Every route handler, service method, and provider call is `async def`. The event loop must never block. CPU-bound and blocking operations run off the event loop via `asyncio.to_thread`. Concurrent work uses `asyncio.TaskGroup` — never bare `create_task`.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Why Async
|
|
17
|
+
|
|
18
|
+
An async-first service design is suited to these characteristics:
|
|
19
|
+
|
|
20
|
+
1. **Streaming connections** — WebSocket connections remain open for the duration of a session. A synchronous server blocks the entire process on each open connection.
|
|
21
|
+
2. **Concurrent inference** — Multiple independent operations run in parallel. Async makes this composition natural and explicit.
|
|
22
|
+
3. **Pub/Sub consumption** — Background message processing runs alongside live HTTP traffic without requiring threads.
|
|
23
|
+
|
|
24
|
+
A synchronous model can handle all of this, but requires explicit thread management, shared state coordination, and careful GIL reasoning. Async eliminates that complexity at one cost: the event loop must never block.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## The One Rule: Never Block the Event Loop
|
|
29
|
+
|
|
30
|
+
Any synchronous call longer than a few milliseconds inside an `async def` function stalls every other coroutine in the process. The symptoms look like random, unrelated timeouts across the service.
|
|
31
|
+
|
|
32
|
+
Blocking calls — file I/O, model loading, `time.sleep`, synchronous SDK methods — must run in a thread:
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
import asyncio
|
|
36
|
+
|
|
37
|
+
result = await asyncio.to_thread(load_and_run_model, audio_path)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`asyncio.to_thread` runs the callable in the default thread pool executor and returns a coroutine. The event loop stays responsive while the blocking work executes.
|
|
41
|
+
|
|
42
|
+
If you are unsure whether a call blocks, check for it in OpenTelemetry traces. A span that is unexpectedly long without any child spans is a sign the event loop was blocked inside it.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Structured Concurrency with TaskGroup
|
|
47
|
+
|
|
48
|
+
When multiple coroutines should run concurrently, use `asyncio.TaskGroup`. It is the only primitive that guarantees all tasks complete — or are cancelled — before control returns to the caller.
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
async def process_meeting(meeting_id: str) -> MeetingResult:
|
|
52
|
+
async with asyncio.TaskGroup() as tg:
|
|
53
|
+
transcription_task = tg.create_task(transcribe(meeting_id))
|
|
54
|
+
speaker_task = tg.create_task(identify_speakers(meeting_id))
|
|
55
|
+
|
|
56
|
+
return MeetingResult(
|
|
57
|
+
transcript=transcription_task.result(),
|
|
58
|
+
speakers=speaker_task.result(),
|
|
59
|
+
)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
If either task raises, `TaskGroup` cancels the sibling and re-raises the exception — no orphaned tasks, no leaked resources, no silent failures.
|
|
63
|
+
|
|
64
|
+
**Never use bare `asyncio.create_task` for fire-and-forget work.** The event loop holds only a weak reference to tasks created this way. If the calling coroutine exits before the task completes, it is garbage collected mid-execution. This is a source of silent data loss that is extremely difficult to reproduce.
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
# Wrong — task may be silently dropped
|
|
68
|
+
asyncio.create_task(publish_event(event))
|
|
69
|
+
|
|
70
|
+
# Correct — task lifetime is bound to the TaskGroup scope
|
|
71
|
+
async with asyncio.TaskGroup() as tg:
|
|
72
|
+
tg.create_task(publish_event(event))
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Route Handlers
|
|
78
|
+
|
|
79
|
+
All route handlers are `async def`. FastAPI runs them directly in the event loop. Synchronous `def` handlers are threaded by FastAPI's default executor — this makes the async/sync boundary invisible and is a source of subtle performance issues.
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
from fastapi import APIRouter
|
|
83
|
+
|
|
84
|
+
router = APIRouter()
|
|
85
|
+
|
|
86
|
+
@router.post("/transcribe")
|
|
87
|
+
async def transcribe_endpoint(request: TranscribeRequest) -> TranscribeResponse:
|
|
88
|
+
result = await transcription_service.transcribe(request.audio_url)
|
|
89
|
+
return TranscribeResponse.from_domain(result)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Background Tasks
|
|
95
|
+
|
|
96
|
+
For work that should happen after a response is returned — publishing a Pub/Sub event, triggering downstream processing — use FastAPI's `BackgroundTasks`:
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
from fastapi import BackgroundTasks
|
|
100
|
+
|
|
101
|
+
@router.post("/transcribe")
|
|
102
|
+
async def transcribe_endpoint(
|
|
103
|
+
request: TranscribeRequest,
|
|
104
|
+
background_tasks: BackgroundTasks,
|
|
105
|
+
) -> TranscribeResponse:
|
|
106
|
+
result = await transcription_service.transcribe(request.audio_url)
|
|
107
|
+
background_tasks.add_task(publish_completed_event, result.id)
|
|
108
|
+
return TranscribeResponse.from_domain(result)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
FastAPI runs background tasks after the response is sent but before the connection closes. They are bound to the request lifecycle and will complete before the server exits during graceful shutdown.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Application Lifespan
|
|
116
|
+
|
|
117
|
+
Initialise shared resources — database connection pools, model clients, Pub/Sub subscriptions — in the FastAPI `lifespan` context manager. This ensures resources are available before the first request and are released cleanly on shutdown.
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from contextlib import asynccontextmanager
|
|
121
|
+
from fastapi import FastAPI
|
|
122
|
+
|
|
123
|
+
@asynccontextmanager
|
|
124
|
+
async def lifespan(app: FastAPI):
|
|
125
|
+
db_pool = await create_db_pool()
|
|
126
|
+
pubsub_client = await create_pubsub_client()
|
|
127
|
+
|
|
128
|
+
app.state.db = db_pool
|
|
129
|
+
app.state.pubsub = pubsub_client
|
|
130
|
+
|
|
131
|
+
yield
|
|
132
|
+
|
|
133
|
+
await db_pool.close()
|
|
134
|
+
await pubsub_client.close()
|
|
135
|
+
|
|
136
|
+
app = FastAPI(lifespan=lifespan)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Never initialise database pools or SDK clients at module level. Module-level initialisation runs at import time, before environment variables are loaded, and cannot be awaited.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Toolchain
|
|
144
|
+
|
|
145
|
+
`uv` manages all Python tooling — dependencies, virtual environments, and script execution:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
uv run pytest # Run tests
|
|
149
|
+
uv add httpx # Add a dependency
|
|
150
|
+
uv sync # Sync from lockfile
|
|
151
|
+
uv run python -m your_service # Run the service
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The lockfile (`uv.lock`) is committed. Every developer and CI run resolves identical dependency trees. There is no `pip`, `poetry`, or `pipenv` in this service.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Anti-Patterns
|
|
159
|
+
|
|
160
|
+
**Blocking the event loop.** Any synchronous call over ~1ms inside `async def` degrades the entire service. Use `asyncio.to_thread` for blocking operations.
|
|
161
|
+
|
|
162
|
+
**Bare `asyncio.create_task`.** Creates an untracked task that can be silently dropped. Use `TaskGroup`.
|
|
163
|
+
|
|
164
|
+
**Synchronous `def` route handlers.** FastAPI threads them silently. Write `async def` so the boundary is explicit.
|
|
165
|
+
|
|
166
|
+
**Module-level async initialisation.** Calling `asyncio.run()` at import time or using `asyncio.get_event_loop()` creates a new event loop that conflicts with FastAPI's loop. Initialise in `lifespan`.
|
|
167
|
+
|
|
168
|
+
**`asyncio.sleep` as a retry delay.** Sleeping inline blocks the coroutine's task slot. Use `tenacity` with async backoff (see [Resilience](resilience.md)).
|