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
package/src/generators/capabilities/llm/providers/ollama/stacks/go/internal/llm/llm.go.template
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
package llm
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"bytes"
|
|
5
|
+
"context"
|
|
6
|
+
"encoding/json"
|
|
7
|
+
"fmt"
|
|
8
|
+
"io"
|
|
9
|
+
"net/http"
|
|
10
|
+
"os"
|
|
11
|
+
"time"
|
|
12
|
+
|
|
13
|
+
"<%= moduleName %>/internal/core/service"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
// Ensure Client implements the service.TextGenerator interface.
|
|
17
|
+
var _ service.TextGenerator = (*Client)(nil)
|
|
18
|
+
|
|
19
|
+
// Client calls a self-hosted, OpenAI-compatible endpoint (Ollama,
|
|
20
|
+
// vLLM, llama.cpp, LM Studio) over HTTP. Minimal net/http adapter, no SDK
|
|
21
|
+
// dependency. Reads LLM_BASE_URL (the server you run) / LLM_MODEL / LLM_API_KEY
|
|
22
|
+
// from env; local servers usually ignore the key.
|
|
23
|
+
type Client struct {
|
|
24
|
+
apiKey string
|
|
25
|
+
baseURL string
|
|
26
|
+
model string
|
|
27
|
+
http *http.Client
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
func NewClient() *Client {
|
|
31
|
+
base := os.Getenv("LLM_BASE_URL")
|
|
32
|
+
if base == "" {
|
|
33
|
+
base = "http://localhost:11434/v1"
|
|
34
|
+
}
|
|
35
|
+
model := os.Getenv("LLM_MODEL")
|
|
36
|
+
if model == "" {
|
|
37
|
+
model = "llama3.1"
|
|
38
|
+
}
|
|
39
|
+
apiKey := os.Getenv("LLM_API_KEY")
|
|
40
|
+
if apiKey == "" {
|
|
41
|
+
apiKey = "not-needed"
|
|
42
|
+
}
|
|
43
|
+
return &Client{
|
|
44
|
+
apiKey: apiKey,
|
|
45
|
+
baseURL: base,
|
|
46
|
+
model: model,
|
|
47
|
+
http: &http.Client{Timeout: 120 * time.Second},
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
func (a *Client) GenerateText(ctx context.Context, prompt string, maxTokens int) (string, error) {
|
|
52
|
+
reqBody, err := json.Marshal(map[string]any{
|
|
53
|
+
"model": a.model,
|
|
54
|
+
"max_tokens": maxTokens,
|
|
55
|
+
"messages": []map[string]string{{"role": "user", "content": prompt}},
|
|
56
|
+
})
|
|
57
|
+
if err != nil {
|
|
58
|
+
return "", fmt.Errorf("llm: marshal request: %w", err)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
var lastErr error
|
|
62
|
+
for attempt := 0; attempt < 3; attempt++ {
|
|
63
|
+
req, err := http.NewRequestWithContext(ctx, http.MethodPost, a.baseURL+"/chat/completions", bytes.NewReader(reqBody))
|
|
64
|
+
if err != nil {
|
|
65
|
+
return "", fmt.Errorf("llm: build request: %w", err)
|
|
66
|
+
}
|
|
67
|
+
req.Header.Set("content-type", "application/json")
|
|
68
|
+
req.Header.Set("authorization", "Bearer "+a.apiKey)
|
|
69
|
+
|
|
70
|
+
resp, err := a.http.Do(req)
|
|
71
|
+
if err != nil {
|
|
72
|
+
lastErr = fmt.Errorf("llm: connection error (is the local model server up at %s?): %w", a.baseURL, err)
|
|
73
|
+
continue // transient — retry
|
|
74
|
+
}
|
|
75
|
+
body, _ := io.ReadAll(resp.Body)
|
|
76
|
+
resp.Body.Close()
|
|
77
|
+
|
|
78
|
+
if resp.StatusCode >= 500 || resp.StatusCode == http.StatusTooManyRequests {
|
|
79
|
+
lastErr = fmt.Errorf("llm: transient endpoint error (status %d): %s", resp.StatusCode, body)
|
|
80
|
+
continue
|
|
81
|
+
}
|
|
82
|
+
if resp.StatusCode >= 400 {
|
|
83
|
+
return "", fmt.Errorf("llm: endpoint request error (status %d): %s", resp.StatusCode, body)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
var parsed struct {
|
|
87
|
+
Choices []struct {
|
|
88
|
+
Message struct {
|
|
89
|
+
Content string `json:"content"`
|
|
90
|
+
} `json:"message"`
|
|
91
|
+
} `json:"choices"`
|
|
92
|
+
}
|
|
93
|
+
if err := json.Unmarshal(body, &parsed); err != nil {
|
|
94
|
+
return "", fmt.Errorf("llm: decode response: %w", err)
|
|
95
|
+
}
|
|
96
|
+
if len(parsed.Choices) == 0 || parsed.Choices[0].Message.Content == "" {
|
|
97
|
+
return "", fmt.Errorf("llm: empty response from local endpoint")
|
|
98
|
+
}
|
|
99
|
+
return parsed.Choices[0].Message.Content, nil
|
|
100
|
+
}
|
|
101
|
+
return "", fmt.Errorf("llm: exhausted retries: %w", lastErr)
|
|
102
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from <%= packageName %>.core.domain.exceptions import TransientInferenceError, PermanentInferenceError, CircuitBreakerOpenError
|
|
2
|
+
from tenacity import retry, wait_exponential_jitter, stop_after_attempt, retry_if_exception_type
|
|
3
|
+
from circuitbreaker import circuit
|
|
4
|
+
from <%= packageName %>.adapters.config import settings
|
|
5
|
+
import openai
|
|
6
|
+
import logging
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
def fallback_circuit_breaker(e):
|
|
11
|
+
logger.error(f"Circuit breaker tripped or open! {e}")
|
|
12
|
+
raise CircuitBreakerOpenError(f"Local LLM endpoint is unavailable. Is the model server running at LLM_BASE_URL?")
|
|
13
|
+
|
|
14
|
+
class LLMClient:
|
|
15
|
+
"""OpenAI-compatible adapter for a self-hosted endpoint (Ollama, vLLM,
|
|
16
|
+
llama.cpp, LM Studio). Talks to settings.llm_base_url; the API key is usually
|
|
17
|
+
irrelevant for local servers, so it defaults to a placeholder."""
|
|
18
|
+
|
|
19
|
+
def __init__(self):
|
|
20
|
+
self.client = openai.AsyncOpenAI(
|
|
21
|
+
api_key=settings.llm_api_key or "not-needed",
|
|
22
|
+
base_url=settings.llm_base_url,
|
|
23
|
+
)
|
|
24
|
+
self.model = settings.llm_model
|
|
25
|
+
|
|
26
|
+
@circuit(failure_threshold=5, recovery_timeout=30, fallback_function=fallback_circuit_breaker, expected_exception=TransientInferenceError)
|
|
27
|
+
@retry(
|
|
28
|
+
wait=wait_exponential_jitter(initial=1, max=30),
|
|
29
|
+
stop=stop_after_attempt(5),
|
|
30
|
+
retry=retry_if_exception_type(TransientInferenceError)
|
|
31
|
+
)
|
|
32
|
+
async def generate_text(self, prompt: str, max_tokens: int = 100) -> str:
|
|
33
|
+
try:
|
|
34
|
+
response = await self.client.chat.completions.create(
|
|
35
|
+
model=self.model,
|
|
36
|
+
messages=[{"role": "user", "content": prompt}],
|
|
37
|
+
max_tokens=max_tokens
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
content = response.choices[0].message.content
|
|
41
|
+
if not content:
|
|
42
|
+
raise PermanentInferenceError("Received empty response from local LLM endpoint")
|
|
43
|
+
|
|
44
|
+
return content
|
|
45
|
+
|
|
46
|
+
except openai.APIConnectionError as e:
|
|
47
|
+
raise TransientInferenceError(f"Connection error (is the local model server up?): {e}")
|
|
48
|
+
except openai.RateLimitError as e:
|
|
49
|
+
raise TransientInferenceError(f"Rate limited: {e}")
|
|
50
|
+
except openai.APIStatusError as e:
|
|
51
|
+
if e.status_code >= 500:
|
|
52
|
+
raise TransientInferenceError(f"Local endpoint server error: {e}")
|
|
53
|
+
raise PermanentInferenceError(f"Local endpoint request error: {e}")
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "env",
|
|
3
|
+
"summary": "OpenAI (or any OpenAI-compatible endpoint) over HTTPS. API key in env; no infrastructure.",
|
|
4
|
+
"env": [
|
|
5
|
+
{ "name": "LLM_API_KEY", "required": true, "default": "" },
|
|
6
|
+
{ "name": "LLM_BASE_URL", "required": false, "default": "" },
|
|
7
|
+
{ "name": "LLM_MODEL", "required": false, "default": "gpt-4o" }
|
|
8
|
+
],
|
|
9
|
+
"stacks": {
|
|
10
|
+
"python": { "dependencies": ["openai>=1.14.0"] },
|
|
11
|
+
"go": { "dependencies": [] }
|
|
12
|
+
}
|
|
13
|
+
}
|
package/src/generators/capabilities/llm/providers/openai/stacks/go/internal/llm/llm.go.template
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
package llm
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"bytes"
|
|
5
|
+
"context"
|
|
6
|
+
"encoding/json"
|
|
7
|
+
"fmt"
|
|
8
|
+
"io"
|
|
9
|
+
"net/http"
|
|
10
|
+
"os"
|
|
11
|
+
"time"
|
|
12
|
+
|
|
13
|
+
"<%= moduleName %>/internal/core/service"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
// Ensure Client implements the service.TextGenerator interface.
|
|
17
|
+
var _ service.TextGenerator = (*Client)(nil)
|
|
18
|
+
|
|
19
|
+
// Client calls the OpenAI Chat Completions API (or any
|
|
20
|
+
// OpenAI-compatible endpoint via LLM_BASE_URL) over HTTPS. Minimal net/http
|
|
21
|
+
// adapter (no SDK dependency) — extend or swap for the official SDK behind this
|
|
22
|
+
// same port. Reads LLM_API_KEY / LLM_BASE_URL / LLM_MODEL from env.
|
|
23
|
+
type Client struct {
|
|
24
|
+
apiKey string
|
|
25
|
+
baseURL string
|
|
26
|
+
model string
|
|
27
|
+
http *http.Client
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
func NewClient() *Client {
|
|
31
|
+
base := os.Getenv("LLM_BASE_URL")
|
|
32
|
+
if base == "" {
|
|
33
|
+
base = "https://api.openai.com/v1"
|
|
34
|
+
}
|
|
35
|
+
model := os.Getenv("LLM_MODEL")
|
|
36
|
+
if model == "" {
|
|
37
|
+
model = "gpt-4o"
|
|
38
|
+
}
|
|
39
|
+
return &Client{
|
|
40
|
+
apiKey: os.Getenv("LLM_API_KEY"),
|
|
41
|
+
baseURL: base,
|
|
42
|
+
model: model,
|
|
43
|
+
http: &http.Client{Timeout: 60 * time.Second},
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
func (a *Client) GenerateText(ctx context.Context, prompt string, maxTokens int) (string, error) {
|
|
48
|
+
reqBody, err := json.Marshal(map[string]any{
|
|
49
|
+
"model": a.model,
|
|
50
|
+
"max_tokens": maxTokens,
|
|
51
|
+
"messages": []map[string]string{{"role": "user", "content": prompt}},
|
|
52
|
+
})
|
|
53
|
+
if err != nil {
|
|
54
|
+
return "", fmt.Errorf("llm: marshal request: %w", err)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
var lastErr error
|
|
58
|
+
for attempt := 0; attempt < 3; attempt++ {
|
|
59
|
+
req, err := http.NewRequestWithContext(ctx, http.MethodPost, a.baseURL+"/chat/completions", bytes.NewReader(reqBody))
|
|
60
|
+
if err != nil {
|
|
61
|
+
return "", fmt.Errorf("llm: build request: %w", err)
|
|
62
|
+
}
|
|
63
|
+
req.Header.Set("content-type", "application/json")
|
|
64
|
+
req.Header.Set("authorization", "Bearer "+a.apiKey)
|
|
65
|
+
|
|
66
|
+
resp, err := a.http.Do(req)
|
|
67
|
+
if err != nil {
|
|
68
|
+
lastErr = fmt.Errorf("llm: connection error: %w", err)
|
|
69
|
+
continue // transient — retry
|
|
70
|
+
}
|
|
71
|
+
body, _ := io.ReadAll(resp.Body)
|
|
72
|
+
resp.Body.Close()
|
|
73
|
+
|
|
74
|
+
if resp.StatusCode >= 500 || resp.StatusCode == http.StatusTooManyRequests {
|
|
75
|
+
lastErr = fmt.Errorf("llm: transient provider error (status %d): %s", resp.StatusCode, body)
|
|
76
|
+
continue
|
|
77
|
+
}
|
|
78
|
+
if resp.StatusCode >= 400 {
|
|
79
|
+
return "", fmt.Errorf("llm: provider request error (status %d): %s", resp.StatusCode, body)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
var parsed struct {
|
|
83
|
+
Choices []struct {
|
|
84
|
+
Message struct {
|
|
85
|
+
Content string `json:"content"`
|
|
86
|
+
} `json:"message"`
|
|
87
|
+
} `json:"choices"`
|
|
88
|
+
}
|
|
89
|
+
if err := json.Unmarshal(body, &parsed); err != nil {
|
|
90
|
+
return "", fmt.Errorf("llm: decode response: %w", err)
|
|
91
|
+
}
|
|
92
|
+
if len(parsed.Choices) == 0 || parsed.Choices[0].Message.Content == "" {
|
|
93
|
+
return "", fmt.Errorf("llm: empty response from provider")
|
|
94
|
+
}
|
|
95
|
+
return parsed.Choices[0].Message.Content, nil
|
|
96
|
+
}
|
|
97
|
+
return "", fmt.Errorf("llm: exhausted retries: %w", lastErr)
|
|
98
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from <%= packageName %>.core.domain.exceptions import TransientInferenceError, PermanentInferenceError, CircuitBreakerOpenError
|
|
2
|
+
from tenacity import retry, wait_exponential_jitter, stop_after_attempt, retry_if_exception_type
|
|
3
|
+
from circuitbreaker import circuit
|
|
4
|
+
from <%= packageName %>.adapters.config import settings
|
|
5
|
+
import openai
|
|
6
|
+
import logging
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
def fallback_circuit_breaker(e):
|
|
11
|
+
logger.error(f"Circuit breaker tripped or open! {e}")
|
|
12
|
+
raise CircuitBreakerOpenError(f"External LLM API is unavailable. Please try again later.")
|
|
13
|
+
|
|
14
|
+
class LLMClient:
|
|
15
|
+
def __init__(self):
|
|
16
|
+
# Defer building the provider client until the first generate_text call so
|
|
17
|
+
# the service boots and serves its non-LLM routes even when no API key is
|
|
18
|
+
# configured — the OpenAI client raises at construction on a missing key,
|
|
19
|
+
# which would otherwise 500 every route that depends on this service.
|
|
20
|
+
self._client: openai.AsyncOpenAI | None = None
|
|
21
|
+
self.model = settings.llm_model
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def client(self) -> openai.AsyncOpenAI:
|
|
25
|
+
if self._client is None:
|
|
26
|
+
self._client = openai.AsyncOpenAI(
|
|
27
|
+
api_key=settings.llm_api_key,
|
|
28
|
+
base_url=settings.llm_base_url,
|
|
29
|
+
)
|
|
30
|
+
return self._client
|
|
31
|
+
|
|
32
|
+
@circuit(failure_threshold=5, recovery_timeout=30, fallback_function=fallback_circuit_breaker, expected_exception=TransientInferenceError)
|
|
33
|
+
@retry(
|
|
34
|
+
wait=wait_exponential_jitter(initial=1, max=30),
|
|
35
|
+
stop=stop_after_attempt(5),
|
|
36
|
+
retry=retry_if_exception_type(TransientInferenceError)
|
|
37
|
+
)
|
|
38
|
+
async def generate_text(self, prompt: str, max_tokens: int = 100) -> str:
|
|
39
|
+
try:
|
|
40
|
+
response = await self.client.chat.completions.create(
|
|
41
|
+
model=self.model,
|
|
42
|
+
messages=[{"role": "user", "content": prompt}],
|
|
43
|
+
max_tokens=max_tokens
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
# Boundary validation: ensure we got a valid response
|
|
47
|
+
content = response.choices[0].message.content
|
|
48
|
+
if not content:
|
|
49
|
+
raise PermanentInferenceError("Received empty response from LLM provider")
|
|
50
|
+
|
|
51
|
+
return content
|
|
52
|
+
|
|
53
|
+
except openai.APIConnectionError as e:
|
|
54
|
+
raise TransientInferenceError(f"Connection error: {e}")
|
|
55
|
+
except openai.RateLimitError as e:
|
|
56
|
+
raise TransientInferenceError(f"Rate limited: {e}")
|
|
57
|
+
except openai.APIStatusError as e:
|
|
58
|
+
if e.status_code >= 500:
|
|
59
|
+
raise TransientInferenceError(f"Provider server error: {e}")
|
|
60
|
+
raise PermanentInferenceError(f"Provider request error: {e}")
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
package service
|
|
2
|
+
|
|
3
|
+
import "context"
|
|
4
|
+
|
|
5
|
+
// TextGenerator is the interface the core depends on for large-language-model
|
|
6
|
+
// text generation. It is declared here, in the consuming service package, so
|
|
7
|
+
// the dependency arrow points inward: concrete adapters live in internal/llm
|
|
8
|
+
// and are swappable at scaffold time (anthropic | openai | local | none)
|
|
9
|
+
// without touching this interface or its callers.
|
|
10
|
+
type TextGenerator interface {
|
|
11
|
+
GenerateText(ctx context.Context, prompt string, maxTokens int) (string, error)
|
|
12
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
package llm
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"testing"
|
|
6
|
+
|
|
7
|
+
"<%= moduleName %>/internal/core/service"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
// Compile-time conformance: the adapter satisfies the service.TextGenerator
|
|
11
|
+
// interface. If the interface and adapter drift, this test file fails to build —
|
|
12
|
+
// the contract is enforced at compile time, the strongest place to put it.
|
|
13
|
+
var _ service.TextGenerator = (*Client)(nil)
|
|
14
|
+
|
|
15
|
+
func TestClientConformsToInterface(t *testing.T) {
|
|
16
|
+
var _ service.TextGenerator = (*Client)(nil)
|
|
17
|
+
}
|
|
18
|
+
<% if (provider === 'none') { %>
|
|
19
|
+
// Bet: the bare adapter has no implementation yet. While the stub returns an
|
|
20
|
+
// error this test Skips, so a freshly scaffolded service stays green. The moment
|
|
21
|
+
// you implement GenerateText it runs for real and asserts the contract — your
|
|
22
|
+
// cue that the bet is delivered and this Skip can come out. The interface is the
|
|
23
|
+
// spec, the adapter is the bet.
|
|
24
|
+
func TestClientGeneratesText(t *testing.T) {
|
|
25
|
+
out, err := NewClient().GenerateText(context.Background(), "ping", 8)
|
|
26
|
+
if err != nil {
|
|
27
|
+
t.Skipf("bet: LLM adapter not implemented yet: %v", err)
|
|
28
|
+
}
|
|
29
|
+
if out == "" {
|
|
30
|
+
t.Fatal("expected non-empty text from the LLM client")
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
<% } %>
|
package/src/generators/capabilities/llm/stacks/python/src/__packageName__/core/llm.py.template
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from typing import Protocol, runtime_checkable
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@runtime_checkable
|
|
5
|
+
class TextGenerator(Protocol):
|
|
6
|
+
"""Port: large-language-model text generation.
|
|
7
|
+
|
|
8
|
+
This interface is the stable contract the domain depends on. Concrete
|
|
9
|
+
adapters live in src/<%= packageName %>/adapters/llm.py and are swappable at scaffold time
|
|
10
|
+
(anthropic | openai | local | none) without touching this port or its
|
|
11
|
+
callers — that is the whole point of the ports/adapters boundary.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
async def generate_text(self, prompt: str, max_tokens: int = 100) -> str:
|
|
15
|
+
...
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""Contract test for the LLM capability port.
|
|
2
|
+
|
|
3
|
+
Generated by the `llm` capability. Asserts the chosen adapter satisfies the
|
|
4
|
+
TextGenerator port so a provider swap can never silently break the boundary.
|
|
5
|
+
"""
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
8
|
+
from <%= packageName %>.core.llm import TextGenerator
|
|
9
|
+
from <%= packageName %>.adapters.llm import LLMClient
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_adapter_conforms_to_text_generator_port():
|
|
13
|
+
"""Structural conformance: the adapter implements the port's method surface.
|
|
14
|
+
|
|
15
|
+
Uses issubclass against the runtime_checkable Protocol so it never has to
|
|
16
|
+
construct the adapter (no network, no API key, no provider SDK call).
|
|
17
|
+
"""
|
|
18
|
+
assert issubclass(LLMClient, TextGenerator)
|
|
19
|
+
<% if (provider === 'none') { %>
|
|
20
|
+
|
|
21
|
+
@pytest.mark.asyncio
|
|
22
|
+
@pytest.mark.xfail(
|
|
23
|
+
strict=True,
|
|
24
|
+
reason="bet: implement the LLM adapter, then remove this marker",
|
|
25
|
+
)
|
|
26
|
+
async def test_unimplemented_adapter_generates_text():
|
|
27
|
+
"""RED bet — the bare adapter has no implementation yet.
|
|
28
|
+
|
|
29
|
+
Marked xfail(strict) so a freshly scaffolded service stays green while the
|
|
30
|
+
bet is open. The moment you implement LLMClient.generate_text this test
|
|
31
|
+
XPASSes and the suite goes red: your cue to remove this marker and own the
|
|
32
|
+
behavioural contract. This is GroundWork's design-locked-in-tests loop —
|
|
33
|
+
the port is the spec, the adapter is the bet.
|
|
34
|
+
"""
|
|
35
|
+
result = await LLMClient().generate_text("ping", max_tokens=8)
|
|
36
|
+
assert isinstance(result, str) and result
|
|
37
|
+
<% } %>
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# <%= name %>
|
|
2
|
+
|
|
3
|
+
A command-line tool scaffolded by GroundWork. It is built on the **composable spine**
|
|
4
|
+
every GroundWork CLI shares — structured `--json` output, exit-code discipline, colour
|
|
5
|
+
that degrades to plain text, and a non-TTY fallback so it never blocks in CI or pipes —
|
|
6
|
+
and it is themed from your design system's **brand tokens**, so it looks like a sibling of
|
|
7
|
+
this project's `./dev` control plane.
|
|
8
|
+
|
|
9
|
+
## Develop
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install
|
|
13
|
+
npm run build # bundle to dist/cli.js
|
|
14
|
+
npm run typecheck # tsc --noEmit
|
|
15
|
+
npm test # node:test — compiles src/ to dist-test/ and runs *.test.ts
|
|
16
|
+
node dist/cli.js --help
|
|
17
|
+
node dist/cli.js hello you
|
|
18
|
+
node dist/cli.js hello you --json
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Structure
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
src/
|
|
25
|
+
├── cli.ts # entry: arg parsing, dispatch, --json, exit codes
|
|
26
|
+
├── registry.ts # the command registry (single source of truth)
|
|
27
|
+
├── registry.test.ts # keeps the registry honest as commands accrete
|
|
28
|
+
├── brand.json # brand tokens projected from the design system
|
|
29
|
+
├── theme/ # the shared render layer (colour resolution, output hierarchy)
|
|
30
|
+
│ ├── tokens.ts
|
|
31
|
+
│ ├── color.ts
|
|
32
|
+
│ └── render.ts
|
|
33
|
+
<% if (core) { %>├── core/
|
|
34
|
+
│ ├── client.ts # the core-access seam — the ONLY place this CLI talks to the workspace gateway
|
|
35
|
+
│ └── client.test.ts # seam proven without a network (fetch injected)
|
|
36
|
+
<% } %>└── commands/
|
|
37
|
+
└── hello.ts # a sample command — replace with your own
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`src/brand.json` is projected from `.groundwork/config/brand-tokens.json` at scaffold time.
|
|
41
|
+
Re-run the design system to evolve the brand; update `brand.json` to match.
|
|
42
|
+
|
|
43
|
+
<% if (core) { %>## Workspace core mode
|
|
44
|
+
|
|
45
|
+
This CLI fronts the workspace's services. All gateway traffic flows through the
|
|
46
|
+
**core-access seam** (`src/core/client.ts`) — commands consume its typed functions and
|
|
47
|
+
never carry transport detail themselves.
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
node dist/cli.js status # the wiring proof: probes the core's /health
|
|
51
|
+
node dist/cli.js status --json # {"baseUrl": ..., "reachable": ..., "status": ...}
|
|
52
|
+
API_BASE_URL=http://staging:4000 node dist/cli.js status
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
- **Base URL** — defaults to `http://localhost:4000` (the workspace gateway); override
|
|
56
|
+
with the `API_BASE_URL` environment variable.
|
|
57
|
+
- **Auth** — unauthenticated by default. Wire your identity provider in
|
|
58
|
+
`coreAuthHeaders` (a service token becomes a `Bearer` header); `/health` stays public.
|
|
59
|
+
- **Exit codes** — `status` exits 0 when the core is reachable, 1 when it is not, so
|
|
60
|
+
scripts and the system-test harness gate on it without parsing output.
|
|
61
|
+
- **Growing the contract** — add one thin function per promoted-contract operation to
|
|
62
|
+
`src/core/client.ts`; when the contract outgrows hand-rolled functions, switch to a
|
|
63
|
+
generated client and keep this module as the seam.
|
|
64
|
+
|
|
65
|
+
<% } else { %>## Standalone
|
|
66
|
+
|
|
67
|
+
This CLI was scaffolded **standalone** — it fronts no workspace services and carries no
|
|
68
|
+
core client. If it later grows into a frontend for the workspace's services, re-run the
|
|
69
|
+
generator with `--core=true` (or copy the `src/core/` seam from a core-wired sibling)
|
|
70
|
+
to add the core-access seam and the `status` wiring-proof command.
|
|
71
|
+
|
|
72
|
+
<% } %>## Add a command
|
|
73
|
+
|
|
74
|
+
1. Create `src/commands/<name>.ts` exporting `async function <name>(ctx): Promise<number>`.
|
|
75
|
+
2. Register it in `src/registry.ts`.
|
|
76
|
+
3. It gets `--json`, exit-code handling, and themed output for free.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Bundles the CLI into a single executable at dist/cli.js.
|
|
2
|
+
import { build } from 'esbuild';
|
|
3
|
+
|
|
4
|
+
await build({
|
|
5
|
+
entryPoints: ['src/cli.ts'],
|
|
6
|
+
bundle: true,
|
|
7
|
+
platform: 'node',
|
|
8
|
+
target: 'node18',
|
|
9
|
+
format: 'cjs',
|
|
10
|
+
outfile: 'dist/cli.js',
|
|
11
|
+
banner: { js: '#!/usr/bin/env node' },
|
|
12
|
+
loader: { '.json': 'json' },
|
|
13
|
+
legalComments: 'none',
|
|
14
|
+
logLevel: 'info',
|
|
15
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "<%= binName %>",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "commonjs",
|
|
6
|
+
"bin": {
|
|
7
|
+
"<%= binName %>": "dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "node build.mjs",
|
|
11
|
+
"typecheck": "tsc --noEmit",
|
|
12
|
+
"test": "tsc -p tsconfig.test.json && node --test \"dist-test/**/*.test.js\"",
|
|
13
|
+
"dev": "node build.mjs && node dist/cli.js",
|
|
14
|
+
"start": "node dist/cli.js"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/node": "^22.0.0",
|
|
18
|
+
"esbuild": "^0.25.0",
|
|
19
|
+
"typescript": "^5.6.0"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* <%= name %> — command-line entry point.
|
|
3
|
+
*
|
|
4
|
+
* Built on the composable spine every GroundWork CLI shares: structured `--json`
|
|
5
|
+
* output, exit-code discipline (0/1/2, 130 on interrupt), colour that degrades, and a
|
|
6
|
+
* non-TTY fallback so the tool never blocks in CI or pipes. The render layer in
|
|
7
|
+
* src/theme/ is themed from your design system's brand tokens (src/brand.json), so this
|
|
8
|
+
* CLI and the project's ./dev control plane look like kin.
|
|
9
|
+
*/
|
|
10
|
+
import brand from './brand.json';
|
|
11
|
+
import { COMMANDS, findCommand, CommandGroup } from './registry';
|
|
12
|
+
import { makeRenderer, Renderer } from './theme/render';
|
|
13
|
+
|
|
14
|
+
function showHelp(r: Renderer): void {
|
|
15
|
+
r.logo('<%= name %>');
|
|
16
|
+
const groups: CommandGroup[] = ['CORE', 'META'];
|
|
17
|
+
for (const g of groups) {
|
|
18
|
+
const cmds = COMMANDS.filter((c) => c.group === g);
|
|
19
|
+
if (cmds.length === 0) continue;
|
|
20
|
+
r.category(g);
|
|
21
|
+
for (const c of cmds) r.cmd(c.name, c.summary);
|
|
22
|
+
}
|
|
23
|
+
process.stderr.write('\n');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function main(): Promise<number> {
|
|
27
|
+
const argv = process.argv.slice(2);
|
|
28
|
+
let json = false;
|
|
29
|
+
let help = false;
|
|
30
|
+
const rest: string[] = [];
|
|
31
|
+
for (const a of argv) {
|
|
32
|
+
if (a === '--json') json = true;
|
|
33
|
+
else if (a === '-h' || a === '--help') help = true;
|
|
34
|
+
else if (a === '--version' || a === '-V') {
|
|
35
|
+
process.stdout.write('<%= binName %> 0.1.0\n');
|
|
36
|
+
return 0;
|
|
37
|
+
} else rest.push(a);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const r = makeRenderer(brand);
|
|
41
|
+
const command = rest[0];
|
|
42
|
+
const args = rest.slice(1);
|
|
43
|
+
|
|
44
|
+
if (!command || command === 'help' || help) {
|
|
45
|
+
showHelp(r);
|
|
46
|
+
return 0;
|
|
47
|
+
}
|
|
48
|
+
const def = findCommand(command);
|
|
49
|
+
if (!def) {
|
|
50
|
+
r.error(`Unknown command: ${command}`);
|
|
51
|
+
showHelp(r);
|
|
52
|
+
return 2;
|
|
53
|
+
}
|
|
54
|
+
return def.handler({ r, json, args });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
process.on('SIGINT', () => {
|
|
58
|
+
process.stderr.write('\n\x1b[?25h');
|
|
59
|
+
process.exit(130);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
main()
|
|
63
|
+
.then((code) => process.exit(code))
|
|
64
|
+
.catch((err) => {
|
|
65
|
+
makeRenderer(brand).error(err?.message ?? String(err));
|
|
66
|
+
process.exit(1);
|
|
67
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Ctx } from '../registry';
|
|
2
|
+
|
|
3
|
+
/** A sample command. It demonstrates the spine: themed human output by default, clean
|
|
4
|
+
* JSON on stdout under --json. Replace it with your own commands. */
|
|
5
|
+
export async function hello(ctx: Ctx): Promise<number> {
|
|
6
|
+
const who = ctx.args[0] ?? 'world';
|
|
7
|
+
|
|
8
|
+
if (ctx.json) {
|
|
9
|
+
process.stdout.write(JSON.stringify({ greeting: `Hello, ${who}!` }) + '\n');
|
|
10
|
+
return 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
ctx.r.logo();
|
|
14
|
+
ctx.r.success(`Hello, ${who}!`);
|
|
15
|
+
ctx.r.info('Edit src/commands/ and register new commands in src/registry.ts.');
|
|
16
|
+
return 0;
|
|
17
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Ctx } from '../registry';
|
|
2
|
+
import { coreBaseUrl, fetchCoreHealth } from '../core/client';
|
|
3
|
+
|
|
4
|
+
/** Probe the workspace core this CLI fronts — the surface's wiring proof.
|
|
5
|
+
* Exit-code discipline carries the verdict: 0 reachable, 1 unreachable, so
|
|
6
|
+
* scripts and the system-test harness gate on it without parsing output. */
|
|
7
|
+
export async function status(ctx: Ctx): Promise<number> {
|
|
8
|
+
const baseUrl = coreBaseUrl();
|
|
9
|
+
const health = await fetchCoreHealth(baseUrl);
|
|
10
|
+
|
|
11
|
+
if (ctx.json) {
|
|
12
|
+
process.stdout.write(JSON.stringify({ baseUrl, ...health }) + '\n');
|
|
13
|
+
return health.reachable ? 0 : 1;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (health.reachable) {
|
|
17
|
+
ctx.r.success(`Workspace core reachable at ${baseUrl} — status ${health.status}`);
|
|
18
|
+
return 0;
|
|
19
|
+
}
|
|
20
|
+
ctx.r.error(`Workspace core unreachable at ${baseUrl} (${health.status})`);
|
|
21
|
+
ctx.r.info('Set API_BASE_URL to point at your workspace gateway.');
|
|
22
|
+
return 1;
|
|
23
|
+
}
|