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.
Files changed (647) hide show
  1. package/CHANGELOG.md +823 -0
  2. package/LICENSE +21 -0
  3. package/README.md +44 -29
  4. package/bin/groundwork.js +1723 -0
  5. package/dist/src/generators/add-capability/generator.d.ts +8 -0
  6. package/dist/src/generators/add-capability/generator.js +60 -0
  7. package/dist/src/generators/add-capability/generator.js.map +1 -0
  8. package/dist/src/generators/cli-app/generator.d.ts +9 -0
  9. package/dist/src/generators/cli-app/generator.js +140 -0
  10. package/dist/src/generators/cli-app/generator.js.map +1 -0
  11. package/dist/src/generators/docs-site/generator.d.ts +5 -0
  12. package/dist/src/generators/docs-site/generator.js +441 -0
  13. package/dist/src/generators/docs-site/generator.js.map +1 -0
  14. package/dist/src/generators/electron-app/generator.d.ts +6 -0
  15. package/dist/src/generators/electron-app/generator.js +261 -0
  16. package/dist/src/generators/electron-app/generator.js.map +1 -0
  17. package/dist/src/generators/flutter-app/generator.d.ts +6 -0
  18. package/dist/src/generators/flutter-app/generator.js +314 -0
  19. package/dist/src/generators/flutter-app/generator.js.map +1 -0
  20. package/dist/src/generators/go-microservice/generator.d.ts +8 -0
  21. package/dist/src/generators/go-microservice/generator.js +232 -0
  22. package/dist/src/generators/go-microservice/generator.js.map +1 -0
  23. package/dist/src/generators/nextjs-app/generator.d.ts +8 -0
  24. package/dist/src/generators/nextjs-app/generator.js +294 -0
  25. package/dist/src/generators/nextjs-app/generator.js.map +1 -0
  26. package/dist/src/generators/python-microservice/generator.d.ts +13 -0
  27. package/dist/src/generators/python-microservice/generator.js +265 -0
  28. package/dist/src/generators/python-microservice/generator.js.map +1 -0
  29. package/dist/src/generators/shared/brand-tokens.d.ts +89 -0
  30. package/dist/src/generators/shared/brand-tokens.js +308 -0
  31. package/dist/src/generators/shared/brand-tokens.js.map +1 -0
  32. package/dist/src/generators/shared/capabilities.d.ts +101 -0
  33. package/dist/src/generators/shared/capabilities.js +279 -0
  34. package/dist/src/generators/shared/capabilities.js.map +1 -0
  35. package/dist/src/generators/shared/provenance.d.ts +2 -0
  36. package/dist/src/generators/shared/provenance.js +85 -0
  37. package/dist/src/generators/shared/provenance.js.map +1 -0
  38. package/dist/src/generators/shared/scaffold-helpers.d.ts +72 -0
  39. package/dist/src/generators/shared/scaffold-helpers.js +309 -0
  40. package/dist/src/generators/shared/scaffold-helpers.js.map +1 -0
  41. package/dist/src/generators/system-test-runner/generator.d.ts +23 -0
  42. package/dist/src/generators/system-test-runner/generator.js +173 -0
  43. package/dist/src/generators/system-test-runner/generator.js.map +1 -0
  44. package/dist/src/generators/workspace-dev-cli/generator.d.ts +7 -0
  45. package/dist/src/generators/workspace-dev-cli/generator.js +138 -0
  46. package/dist/src/generators/workspace-dev-cli/generator.js.map +1 -0
  47. package/generators.json +57 -0
  48. package/lib/repo-map/grammars/tree-sitter-c.wasm +0 -0
  49. package/lib/repo-map/grammars/tree-sitter-cpp.wasm +0 -0
  50. package/lib/repo-map/grammars/tree-sitter-csharp.wasm +0 -0
  51. package/lib/repo-map/grammars/tree-sitter-dart.wasm +0 -0
  52. package/lib/repo-map/grammars/tree-sitter-go.wasm +0 -0
  53. package/lib/repo-map/grammars/tree-sitter-java.wasm +0 -0
  54. package/lib/repo-map/grammars/tree-sitter-javascript.wasm +0 -0
  55. package/lib/repo-map/grammars/tree-sitter-kotlin.wasm +0 -0
  56. package/lib/repo-map/grammars/tree-sitter-lua.wasm +0 -0
  57. package/lib/repo-map/grammars/tree-sitter-php.wasm +0 -0
  58. package/lib/repo-map/grammars/tree-sitter-python.wasm +0 -0
  59. package/lib/repo-map/grammars/tree-sitter-ruby.wasm +0 -0
  60. package/lib/repo-map/grammars/tree-sitter-rust.wasm +0 -0
  61. package/lib/repo-map/grammars/tree-sitter-scala.wasm +0 -0
  62. package/lib/repo-map/grammars/tree-sitter-swift.wasm +0 -0
  63. package/lib/repo-map/grammars/tree-sitter-tsx.wasm +0 -0
  64. package/lib/repo-map/grammars/tree-sitter-typescript.wasm +0 -0
  65. package/lib/repo-map/index.js +386 -0
  66. package/lib/repo-map/languages.js +514 -0
  67. package/lib/repo-map/pagerank.js +59 -0
  68. package/migrations/README.md +60 -0
  69. package/migrations/_template/cli-migration.js +27 -0
  70. package/migrations/gw-bet-prose-redesign.js +105 -0
  71. package/migrations/gw-drop-test-manifest.js +37 -0
  72. package/migrations/gw-register-serena-mcp.js +42 -0
  73. package/migrations/gw-relocate-hidden-skills.js +40 -0
  74. package/migrations/gw-seed-config-toml.js +24 -0
  75. package/migrations/index.json +40 -0
  76. package/package.json +70 -6
  77. package/src/AGENTS.md +36 -0
  78. package/src/config/config.toml +30 -0
  79. package/src/config/groundwork-state.json +5 -0
  80. package/src/docs/llms.txt +72 -0
  81. package/src/docs/principles/ai-native/agent-native-systems.md +90 -0
  82. package/src/docs/principles/ai-native/agentic-systems.md +78 -0
  83. package/src/docs/principles/ai-native/ai-engineering.md +100 -0
  84. package/src/docs/principles/ai-native/ai-native-product.md +76 -0
  85. package/src/docs/principles/delivery/cost-engineering.md +89 -0
  86. package/src/docs/principles/delivery/day-2-operational-baseline.md +57 -0
  87. package/src/docs/principles/delivery/devex.md +88 -0
  88. package/src/docs/principles/delivery/platform.md +101 -0
  89. package/src/docs/principles/delivery/progressive-delivery.md +92 -0
  90. package/src/docs/principles/design/ai-native-design.md +73 -0
  91. package/src/docs/principles/design/design-foundations.md +80 -0
  92. package/src/docs/principles/design/design-systems-and-tokens.md +72 -0
  93. package/src/docs/principles/design/interaction-and-motion.md +69 -0
  94. package/src/docs/principles/design/layout-and-space.md +72 -0
  95. package/src/docs/principles/design/usability-and-ux.md +79 -0
  96. package/src/docs/principles/design/visual-design.md +84 -0
  97. package/src/docs/principles/foundations/code-craft.md +86 -0
  98. package/src/docs/principles/foundations/continuous-discovery.md +75 -0
  99. package/src/docs/principles/foundations/documentation.md +102 -0
  100. package/src/docs/principles/foundations/prioritization-and-appetite.md +78 -0
  101. package/src/docs/principles/foundations/product-engineering.md +90 -0
  102. package/src/docs/principles/foundations/product-risks.md +89 -0
  103. package/src/docs/principles/foundations/requirements-and-specs.md +80 -0
  104. package/src/docs/principles/foundations/success-metrics.md +66 -0
  105. package/src/docs/principles/foundations/testing.md +108 -0
  106. package/src/docs/principles/index.md +24 -0
  107. package/src/docs/principles/quality/accessibility.md +88 -0
  108. package/src/docs/principles/quality/observability.md +84 -0
  109. package/src/docs/principles/quality/performance.md +84 -0
  110. package/src/docs/principles/quality/privacy.md +92 -0
  111. package/src/docs/principles/quality/reliability.md +89 -0
  112. package/src/docs/principles/quality/security.md +78 -0
  113. package/src/docs/principles/stack/postgres.md +100 -0
  114. package/src/docs/principles/system-design/api-design.md +86 -0
  115. package/src/docs/principles/system-design/architecture-decisions.md +81 -0
  116. package/src/docs/principles/system-design/code-structure.md +104 -0
  117. package/src/docs/principles/system-design/data-engineering.md +87 -0
  118. package/src/docs/principles/system-design/durable-execution.md +89 -0
  119. package/src/docs/principles/system-design/evolutionary-architecture.md +81 -0
  120. package/src/docs/principles/system-design/identity-and-access.md +76 -0
  121. package/src/docs/principles/system-design/integration-patterns.md +84 -0
  122. package/src/docs/principles/system-design/real-time.md +83 -0
  123. package/src/docs/principles/system-design/surface-architecture.md +74 -0
  124. package/src/docs/ways-of-working/documentation.md +69 -0
  125. package/src/docs/ways-of-working/how-we-work.md +76 -0
  126. package/src/docs/ways-of-working/units-of-work.md +40 -0
  127. package/src/engineer-skills/groundwork-electron-engineer/SKILL.md +123 -0
  128. package/src/engineer-skills/groundwork-electron-engineer/references/documentation.md +126 -0
  129. package/src/engineer-skills/groundwork-electron-engineer/references/ipc-contracts.md +138 -0
  130. package/src/engineer-skills/groundwork-electron-engineer/references/observability.md +37 -0
  131. package/src/engineer-skills/groundwork-electron-engineer/references/packaging-and-updates.md +82 -0
  132. package/src/engineer-skills/groundwork-electron-engineer/references/performance-and-reliability.md +80 -0
  133. package/src/engineer-skills/groundwork-electron-engineer/references/process-model.md +94 -0
  134. package/src/engineer-skills/groundwork-electron-engineer/references/security.md +107 -0
  135. package/src/engineer-skills/groundwork-electron-engineer/references/testing-and-smoke.md +129 -0
  136. package/src/engineer-skills/groundwork-electron-engineer/references/theming-and-tokens.md +74 -0
  137. package/src/engineer-skills/groundwork-electron-engineer/sync-anchor.md +22 -0
  138. package/src/engineer-skills/groundwork-flutter-engineer/SKILL.md +114 -0
  139. package/src/engineer-skills/groundwork-flutter-engineer/references/accessibility.md +92 -0
  140. package/src/engineer-skills/groundwork-flutter-engineer/references/architecture.md +189 -0
  141. package/src/engineer-skills/groundwork-flutter-engineer/references/data-and-contracts.md +136 -0
  142. package/src/engineer-skills/groundwork-flutter-engineer/references/documentation.md +122 -0
  143. package/src/engineer-skills/groundwork-flutter-engineer/references/navigation.md +122 -0
  144. package/src/engineer-skills/groundwork-flutter-engineer/references/observability.md +37 -0
  145. package/src/engineer-skills/groundwork-flutter-engineer/references/performance-and-reliability.md +100 -0
  146. package/src/engineer-skills/groundwork-flutter-engineer/references/platform-channels.md +93 -0
  147. package/src/engineer-skills/groundwork-flutter-engineer/references/releases-and-distribution.md +84 -0
  148. package/src/engineer-skills/groundwork-flutter-engineer/references/security.md +96 -0
  149. package/src/engineer-skills/groundwork-flutter-engineer/references/state-management.md +166 -0
  150. package/src/engineer-skills/groundwork-flutter-engineer/references/testing.md +160 -0
  151. package/src/engineer-skills/groundwork-flutter-engineer/references/theming-and-design-tokens.md +109 -0
  152. package/src/engineer-skills/groundwork-flutter-engineer/references/widgets-and-composition.md +123 -0
  153. package/src/engineer-skills/groundwork-flutter-engineer/sync-anchor.md +24 -0
  154. package/src/engineer-skills/groundwork-go-engineer/SKILL.md +174 -0
  155. package/src/engineer-skills/groundwork-go-engineer/references/api-design.md +82 -0
  156. package/src/engineer-skills/groundwork-go-engineer/references/architecture.md +42 -0
  157. package/src/engineer-skills/groundwork-go-engineer/references/capability-ports.md +50 -0
  158. package/src/engineer-skills/groundwork-go-engineer/references/code-craft-security.md +34 -0
  159. package/src/engineer-skills/groundwork-go-engineer/references/concurrency.md +108 -0
  160. package/src/engineer-skills/groundwork-go-engineer/references/documentation.md +130 -0
  161. package/src/engineer-skills/groundwork-go-engineer/references/go-services.md +77 -0
  162. package/src/engineer-skills/groundwork-go-engineer/references/http-handlers.md +172 -0
  163. package/src/engineer-skills/groundwork-go-engineer/references/implementation-patterns.md +156 -0
  164. package/src/engineer-skills/groundwork-go-engineer/references/integration-realtime-data.md +57 -0
  165. package/src/engineer-skills/groundwork-go-engineer/references/observability.md +49 -0
  166. package/src/engineer-skills/groundwork-go-engineer/references/postgres.md +41 -0
  167. package/src/engineer-skills/groundwork-go-engineer/references/reliability-performance.md +105 -0
  168. package/src/engineer-skills/groundwork-go-engineer/references/testing.md +201 -0
  169. package/src/engineer-skills/groundwork-go-engineer/sync-anchor.md +20 -0
  170. package/src/engineer-skills/groundwork-nextjs-engineer/SKILL.md +112 -0
  171. package/src/engineer-skills/groundwork-nextjs-engineer/references/accessibility.md +111 -0
  172. package/src/engineer-skills/groundwork-nextjs-engineer/references/architecture.md +323 -0
  173. package/src/engineer-skills/groundwork-nextjs-engineer/references/data-fetching.md +458 -0
  174. package/src/engineer-skills/groundwork-nextjs-engineer/references/documentation.md +324 -0
  175. package/src/engineer-skills/groundwork-nextjs-engineer/references/error-boundaries.md +383 -0
  176. package/src/engineer-skills/groundwork-nextjs-engineer/references/mutations-and-forms.md +396 -0
  177. package/src/engineer-skills/groundwork-nextjs-engineer/references/observability.md +48 -0
  178. package/src/engineer-skills/groundwork-nextjs-engineer/references/performance-and-deployment.md +947 -0
  179. package/src/engineer-skills/groundwork-nextjs-engineer/references/routing-and-navigation.md +405 -0
  180. package/src/engineer-skills/groundwork-nextjs-engineer/references/security.md +131 -0
  181. package/src/engineer-skills/groundwork-nextjs-engineer/references/server-components.md +394 -0
  182. package/src/engineer-skills/groundwork-nextjs-engineer/references/tailwind-and-styling.md +134 -0
  183. package/src/engineer-skills/groundwork-nextjs-engineer/references/testing.md +491 -0
  184. package/src/engineer-skills/groundwork-nextjs-engineer/references/type-system.md +368 -0
  185. package/src/engineer-skills/groundwork-nextjs-engineer/references/ux-principles.md +230 -0
  186. package/src/engineer-skills/groundwork-nextjs-engineer/references/visual-language.md +69 -0
  187. package/src/engineer-skills/groundwork-nextjs-engineer/sync-anchor.md +16 -0
  188. package/src/engineer-skills/groundwork-python-engineer/SKILL.md +199 -0
  189. package/src/engineer-skills/groundwork-python-engineer/references/api-standards.md +88 -0
  190. package/src/engineer-skills/groundwork-python-engineer/references/architecture.md +57 -0
  191. package/src/engineer-skills/groundwork-python-engineer/references/async-patterns.md +103 -0
  192. package/src/engineer-skills/groundwork-python-engineer/references/capability-ports.md +44 -0
  193. package/src/engineer-skills/groundwork-python-engineer/references/database.md +88 -0
  194. package/src/engineer-skills/groundwork-python-engineer/references/documentation-mcp.md +167 -0
  195. package/src/engineer-skills/groundwork-python-engineer/references/implementation-patterns.md +166 -0
  196. package/src/engineer-skills/groundwork-python-engineer/references/ml-pipelines.md +119 -0
  197. package/src/engineer-skills/groundwork-python-engineer/references/ml-systems-ai-engineering.md +74 -0
  198. package/src/engineer-skills/groundwork-python-engineer/references/observability.md +57 -0
  199. package/src/engineer-skills/groundwork-python-engineer/references/resilience.md +126 -0
  200. package/src/engineer-skills/groundwork-python-engineer/references/security.md +148 -0
  201. package/src/engineer-skills/groundwork-python-engineer/references/testing.md +216 -0
  202. package/src/engineer-skills/groundwork-python-engineer/sync-anchor.md +20 -0
  203. package/src/generators/add-capability/generator.ts +70 -0
  204. package/src/generators/add-capability/schema.json +30 -0
  205. package/src/generators/capabilities/llm/capability.json +28 -0
  206. package/src/generators/capabilities/llm/providers/anthropic/footprint.json +13 -0
  207. package/src/generators/capabilities/llm/providers/anthropic/stacks/go/internal/llm/llm.go.template +102 -0
  208. package/src/generators/capabilities/llm/providers/anthropic/stacks/python/src/__packageName__/adapters/llm.py.template +61 -0
  209. package/src/generators/capabilities/llm/providers/local/footprint.json +13 -0
  210. package/src/generators/capabilities/llm/providers/local/stacks/go/internal/llm/llm.go.template +102 -0
  211. package/src/generators/capabilities/llm/providers/local/stacks/python/src/__packageName__/adapters/llm.py.template +53 -0
  212. package/src/generators/capabilities/llm/providers/localai/footprint.json +29 -0
  213. package/src/generators/capabilities/llm/providers/localai/stacks/go/internal/llm/llm.go.template +102 -0
  214. package/src/generators/capabilities/llm/providers/localai/stacks/python/src/__packageName__/adapters/llm.py.template +53 -0
  215. package/src/generators/capabilities/llm/providers/none/footprint.json +9 -0
  216. package/src/generators/capabilities/llm/providers/none/stacks/go/internal/llm/llm.go.template +35 -0
  217. package/src/generators/capabilities/llm/providers/none/stacks/python/src/__packageName__/adapters/llm.py.template +25 -0
  218. package/src/generators/capabilities/llm/providers/ollama/footprint.json +20 -0
  219. package/src/generators/capabilities/llm/providers/ollama/stacks/go/internal/llm/llm.go.template +102 -0
  220. package/src/generators/capabilities/llm/providers/ollama/stacks/python/src/__packageName__/adapters/llm.py.template +53 -0
  221. package/src/generators/capabilities/llm/providers/openai/footprint.json +13 -0
  222. package/src/generators/capabilities/llm/providers/openai/stacks/go/internal/llm/llm.go.template +98 -0
  223. package/src/generators/capabilities/llm/providers/openai/stacks/python/src/__packageName__/adapters/llm.py.template +60 -0
  224. package/src/generators/capabilities/llm/stacks/go/internal/core/service/llm.go.template +12 -0
  225. package/src/generators/capabilities/llm/stacks/go/internal/llm/llm_test.go.template +33 -0
  226. package/src/generators/capabilities/llm/stacks/python/src/__packageName__/core/llm.py.template +15 -0
  227. package/src/generators/capabilities/llm/stacks/python/tests/contracts/test_llm.py.template +37 -0
  228. package/src/generators/cli-app/files/README.md.template +76 -0
  229. package/src/generators/cli-app/files/build.mjs.template +15 -0
  230. package/src/generators/cli-app/files/package.json.template +21 -0
  231. package/src/generators/cli-app/files/src/cli.ts.template +67 -0
  232. package/src/generators/cli-app/files/src/commands/hello.ts.template +17 -0
  233. package/src/generators/cli-app/files/src/commands/status.ts.template +23 -0
  234. package/src/generators/cli-app/files/src/core/client.test.ts.template +80 -0
  235. package/src/generators/cli-app/files/src/core/client.ts.template +64 -0
  236. package/src/generators/cli-app/files/src/registry.test.ts.template +35 -0
  237. package/src/generators/cli-app/files/src/registry.ts.template +31 -0
  238. package/src/generators/cli-app/files/tsconfig.json.template +16 -0
  239. package/src/generators/cli-app/files/tsconfig.test.json.template +11 -0
  240. package/src/generators/cli-app/generator.ts +138 -0
  241. package/src/generators/cli-app/schema.json +24 -0
  242. package/src/generators/docs-site/files/.gitignore.ejs +40 -0
  243. package/src/generators/docs-site/files/app/docs/__slug__/page.tsx +101 -0
  244. package/src/generators/docs-site/files/app/docs/layout.tsx +14 -0
  245. package/src/generators/docs-site/files/app/docs.css +43 -0
  246. package/src/generators/docs-site/files/app/layout.tsx +24 -0
  247. package/src/generators/docs-site/files/app/page.tsx +135 -0
  248. package/src/generators/docs-site/files/app/source.ts +8 -0
  249. package/src/generators/docs-site/files/components/mermaid.tsx +67 -0
  250. package/src/generators/docs-site/files/next.config.mjs +10 -0
  251. package/src/generators/docs-site/files/package.json +32 -0
  252. package/src/generators/docs-site/files/pnpm-workspace.yaml +7 -0
  253. package/src/generators/docs-site/files/postcss.config.mjs +6 -0
  254. package/src/generators/docs-site/files/source.config.ts +77 -0
  255. package/src/generators/docs-site/files/tailwind.config.js +10 -0
  256. package/src/generators/docs-site/files/tsconfig.json +27 -0
  257. package/src/generators/docs-site/generator.ts +476 -0
  258. package/src/generators/docs-site/schema.json +17 -0
  259. package/src/generators/electron-app/docs/principles/stack/electron/index.md +49 -0
  260. package/src/generators/electron-app/docs/principles/stack/electron/ipc-contracts.md +71 -0
  261. package/src/generators/electron-app/docs/principles/stack/electron/packaging-and-updates.md +59 -0
  262. package/src/generators/electron-app/docs/principles/stack/electron/process-model.md +53 -0
  263. package/src/generators/electron-app/docs/principles/stack/electron/security.md +70 -0
  264. package/src/generators/electron-app/docs/principles/stack/typescript/frontend.md +65 -0
  265. package/src/generators/electron-app/files/.gitignore.template +20 -0
  266. package/src/generators/electron-app/files/README.md.template +125 -0
  267. package/src/generators/electron-app/files/electron.vite.config.ts +31 -0
  268. package/src/generators/electron-app/files/eslint.config.mjs +92 -0
  269. package/src/generators/electron-app/files/forge.config.ts.template +44 -0
  270. package/src/generators/electron-app/files/package.json.template +54 -0
  271. package/src/generators/electron-app/files/playwright.config.ts +18 -0
  272. package/src/generators/electron-app/files/project.json.template +65 -0
  273. package/src/generators/electron-app/files/src/main/core-client.test.ts +81 -0
  274. package/src/generators/electron-app/files/src/main/core-client.ts +55 -0
  275. package/src/generators/electron-app/files/src/main/index.ts +157 -0
  276. package/src/generators/electron-app/files/src/main/ipc.ts +52 -0
  277. package/src/generators/electron-app/files/src/main/policy.test.ts +71 -0
  278. package/src/generators/electron-app/files/src/main/policy.ts +73 -0
  279. package/src/generators/electron-app/files/src/preload/index.ts +23 -0
  280. package/src/generators/electron-app/files/src/renderer/index.html.template +20 -0
  281. package/src/generators/electron-app/files/src/renderer/src/App.test.tsx +61 -0
  282. package/src/generators/electron-app/files/src/renderer/src/App.tsx.template +43 -0
  283. package/src/generators/electron-app/files/src/renderer/src/assets/main.css +40 -0
  284. package/src/generators/electron-app/files/src/renderer/src/env.d.ts +14 -0
  285. package/src/generators/electron-app/files/src/renderer/src/main.tsx +25 -0
  286. package/src/generators/electron-app/files/src/shared/ipc.ts +54 -0
  287. package/src/generators/electron-app/files/tests/smoke/app.spec.ts.template +133 -0
  288. package/src/generators/electron-app/files/tool/electron_exec.sh.template +83 -0
  289. package/src/generators/electron-app/files/tsconfig.json +7 -0
  290. package/src/generators/electron-app/files/tsconfig.node.json +27 -0
  291. package/src/generators/electron-app/files/tsconfig.web.json +22 -0
  292. package/src/generators/electron-app/files/vitest.config.ts +32 -0
  293. package/src/generators/electron-app/files/vitest.setup.ts +1 -0
  294. package/src/generators/electron-app/generator.ts +288 -0
  295. package/src/generators/electron-app/schema.json +23 -0
  296. package/src/generators/flutter-app/docs/principles/stack/flutter/architecture.md +78 -0
  297. package/src/generators/flutter-app/docs/principles/stack/flutter/index.md +38 -0
  298. package/src/generators/flutter-app/docs/principles/stack/flutter/platform-channels.md +51 -0
  299. package/src/generators/flutter-app/docs/principles/stack/flutter/releases-and-distribution.md +59 -0
  300. package/src/generators/flutter-app/docs/principles/stack/flutter/state-management.md +85 -0
  301. package/src/generators/flutter-app/docs/principles/stack/flutter/testing.md +86 -0
  302. package/src/generators/flutter-app/docs/principles/stack/flutter/widgets-and-composition.md +69 -0
  303. package/src/generators/flutter-app/files/.gitignore.template +30 -0
  304. package/src/generators/flutter-app/files/README.md.template +100 -0
  305. package/src/generators/flutter-app/files/analysis_options.yaml.template +18 -0
  306. package/src/generators/flutter-app/files/integration_test/app_test.dart.template +64 -0
  307. package/src/generators/flutter-app/files/lib/app.dart.template +24 -0
  308. package/src/generators/flutter-app/files/lib/config/app_config.dart +15 -0
  309. package/src/generators/flutter-app/files/lib/data/repositories/status_repository.dart +36 -0
  310. package/src/generators/flutter-app/files/lib/data/services/api_client.dart +71 -0
  311. package/src/generators/flutter-app/files/lib/domain/models/health_status.dart +23 -0
  312. package/src/generators/flutter-app/files/lib/main.dart +11 -0
  313. package/src/generators/flutter-app/files/lib/router.dart +23 -0
  314. package/src/generators/flutter-app/files/lib/ui/core/theme/app_theme.dart +110 -0
  315. package/src/generators/flutter-app/files/lib/ui/home/home_view.dart +89 -0
  316. package/src/generators/flutter-app/files/lib/ui/home/home_view_model.dart.template +38 -0
  317. package/src/generators/flutter-app/files/project.json.template +51 -0
  318. package/src/generators/flutter-app/files/pubspec.yaml.template +47 -0
  319. package/src/generators/flutter-app/files/test/api_client_test.dart.template +63 -0
  320. package/src/generators/flutter-app/files/test/fakes/fake_status_repository.dart.template +19 -0
  321. package/src/generators/flutter-app/files/test/home_view_test.dart.template +58 -0
  322. package/src/generators/flutter-app/files/tool/flutter_exec.sh.template +60 -0
  323. package/src/generators/flutter-app/generator.ts +362 -0
  324. package/src/generators/flutter-app/schema.json +23 -0
  325. package/src/generators/go-microservice/docs/principles/stack/go/concurrency.md +123 -0
  326. package/src/generators/go-microservice/docs/principles/stack/go/index.md +70 -0
  327. package/src/generators/go-microservice/docs/principles/stack/go/testing.md +168 -0
  328. package/src/generators/go-microservice/files/.air.toml.template +38 -0
  329. package/src/generators/go-microservice/files/.env.template +4 -0
  330. package/src/generators/go-microservice/files/.golangci.yml.template +82 -0
  331. package/src/generators/go-microservice/files/Dockerfile.dev.template +12 -0
  332. package/src/generators/go-microservice/files/asyncapi-pubsub.yaml.template +33 -0
  333. package/src/generators/go-microservice/files/asyncapi-ws.yaml.template +34 -0
  334. package/src/generators/go-microservice/files/cmd/api/main.go.template +149 -0
  335. package/src/generators/go-microservice/files/cmd/api/main_test.go.template +99 -0
  336. package/src/generators/go-microservice/files/cmd/worker/cleanup/main.go.template +39 -0
  337. package/src/generators/go-microservice/files/db/schema.sql.template +24 -0
  338. package/src/generators/go-microservice/files/go.mod.template +39 -0
  339. package/src/generators/go-microservice/files/internal/config/config.go.template +52 -0
  340. package/src/generators/go-microservice/files/internal/config/otel.go.template +93 -0
  341. package/src/generators/go-microservice/files/internal/core/domain/errors.go.template +16 -0
  342. package/src/generators/go-microservice/files/internal/core/domain/model.go.template +28 -0
  343. package/src/generators/go-microservice/files/internal/core/domain/user.go.template +13 -0
  344. package/src/generators/go-microservice/files/internal/core/pagination.go.template +16 -0
  345. package/src/generators/go-microservice/files/internal/core/service/app_service.go.template +79 -0
  346. package/src/generators/go-microservice/files/internal/core/service/event_hub.go.template +9 -0
  347. package/src/generators/go-microservice/files/internal/core/service/message_queue.go.template +10 -0
  348. package/src/generators/go-microservice/files/internal/core/service/outbox_repository.go.template +31 -0
  349. package/src/generators/go-microservice/files/internal/core/service/repository.go.template +23 -0
  350. package/src/generators/go-microservice/files/internal/core/service/user_repository.go.template +15 -0
  351. package/src/generators/go-microservice/files/internal/core/service/user_service.go.template +43 -0
  352. package/src/generators/go-microservice/files/internal/entrypoints/api/app_handler.go.template +108 -0
  353. package/src/generators/go-microservice/files/internal/entrypoints/api/auth_middleware_test.go.template +52 -0
  354. package/src/generators/go-microservice/files/internal/entrypoints/api/clerk_webhook.go.template +202 -0
  355. package/src/generators/go-microservice/files/internal/entrypoints/api/clerk_webhook_test.go.template +82 -0
  356. package/src/generators/go-microservice/files/internal/entrypoints/api/health_handler.go.template +80 -0
  357. package/src/generators/go-microservice/files/internal/entrypoints/api/idempotency/middleware.go.template +87 -0
  358. package/src/generators/go-microservice/files/internal/entrypoints/api/idempotency/middleware_test.go.template +76 -0
  359. package/src/generators/go-microservice/files/internal/entrypoints/api/idempotency/repository.go.template +37 -0
  360. package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_auth.go.template +40 -0
  361. package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_loadshed.go.template +38 -0
  362. package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_logging.go.template +40 -0
  363. package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_ratelimit.go.template +48 -0
  364. package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_test.go.template +81 -0
  365. package/src/generators/go-microservice/files/internal/entrypoints/api/router.go.template +105 -0
  366. package/src/generators/go-microservice/files/internal/entrypoints/api/types.go.template +70 -0
  367. package/src/generators/go-microservice/files/internal/entrypoints/api/websocket_handler.go.template +39 -0
  368. package/src/generators/go-microservice/files/internal/httpclient/http_client.go.template +87 -0
  369. package/src/generators/go-microservice/files/internal/kafka/kafka.go.template +34 -0
  370. package/src/generators/go-microservice/files/internal/postgres/postgres.go.template +195 -0
  371. package/src/generators/go-microservice/files/internal/postgres/postgres_test.go.template +156 -0
  372. package/src/generators/go-microservice/files/internal/postgres/user_repository.go.template +56 -0
  373. package/src/generators/go-microservice/files/internal/pubsub/gcp_pubsub.go.template +35 -0
  374. package/src/generators/go-microservice/files/internal/websocket/client.go.template +151 -0
  375. package/src/generators/go-microservice/files/internal/websocket/hub.go.template +261 -0
  376. package/src/generators/go-microservice/files/scripts/apply-schema.sh.template +21 -0
  377. package/src/generators/go-microservice/files/tools/tools.go.template +10 -0
  378. package/src/generators/go-microservice/generator.ts +240 -0
  379. package/src/generators/go-microservice/schema.json +63 -0
  380. package/src/generators/nextjs-app/docs/principles/stack/typescript/frontend.md +65 -0
  381. package/src/generators/nextjs-app/files/.dockerignore.template +7 -0
  382. package/src/generators/nextjs-app/files/.env.example.template +24 -0
  383. package/src/generators/nextjs-app/files/.gitignore.template +5 -0
  384. package/src/generators/nextjs-app/files/Dockerfile +53 -0
  385. package/src/generators/nextjs-app/files/app/(auth)/sign-in/__sign-in__/page.tsx.template +9 -0
  386. package/src/generators/nextjs-app/files/app/(auth)/sign-up/__sign-up__/page.tsx.template +9 -0
  387. package/src/generators/nextjs-app/files/app/api/config/route.ts.template +39 -0
  388. package/src/generators/nextjs-app/files/app/api/healthz/route.test.ts +15 -0
  389. package/src/generators/nextjs-app/files/app/api/healthz/route.ts +5 -0
  390. package/src/generators/nextjs-app/files/app/api/proxy/__path__/route.test.ts.template +55 -0
  391. package/src/generators/nextjs-app/files/app/api/proxy/__path__/route.ts.template +126 -0
  392. package/src/generators/nextjs-app/files/app/error.tsx +39 -0
  393. package/src/generators/nextjs-app/files/app/global-error.tsx +68 -0
  394. package/src/generators/nextjs-app/files/app/globals.css +105 -0
  395. package/src/generators/nextjs-app/files/app/layout.tsx +59 -0
  396. package/src/generators/nextjs-app/files/app/loading.tsx +13 -0
  397. package/src/generators/nextjs-app/files/app/not-found.tsx +30 -0
  398. package/src/generators/nextjs-app/files/app/page.tsx +20 -0
  399. package/src/generators/nextjs-app/files/components/providers/default.tsx +19 -0
  400. package/src/generators/nextjs-app/files/components/providers/production.tsx +32 -0
  401. package/src/generators/nextjs-app/files/components/providers/telemetry.tsx +76 -0
  402. package/src/generators/nextjs-app/files/components/render-smoke.test.tsx +29 -0
  403. package/src/generators/nextjs-app/files/components/theme-provider.tsx +11 -0
  404. package/src/generators/nextjs-app/files/components.json +21 -0
  405. package/src/generators/nextjs-app/files/eslint.config.mjs +120 -0
  406. package/src/generators/nextjs-app/files/hooks/use-toast.ts +7 -0
  407. package/src/generators/nextjs-app/files/instrumentation.ts +90 -0
  408. package/src/generators/nextjs-app/files/lib/api/fetcher.ts.template +130 -0
  409. package/src/generators/nextjs-app/files/lib/config.ts +21 -0
  410. package/src/generators/nextjs-app/files/lib/logger.ts +29 -0
  411. package/src/generators/nextjs-app/files/lib/schemas/index.ts +19 -0
  412. package/src/generators/nextjs-app/files/lib/utils.ts +6 -0
  413. package/src/generators/nextjs-app/files/next.config.mjs +9 -0
  414. package/src/generators/nextjs-app/files/package.json +70 -0
  415. package/src/generators/nextjs-app/files/postcss.config.mjs +8 -0
  416. package/src/generators/nextjs-app/files/proxy.test.ts.template +30 -0
  417. package/src/generators/nextjs-app/files/proxy.ts +31 -0
  418. package/src/generators/nextjs-app/files/public/.gitkeep +1 -0
  419. package/src/generators/nextjs-app/files/tsconfig.json +42 -0
  420. package/src/generators/nextjs-app/files/vitest.config.mts +15 -0
  421. package/src/generators/nextjs-app/files/vitest.setup.ts +7 -0
  422. package/src/generators/nextjs-app/generator.ts +307 -0
  423. package/src/generators/nextjs-app/schema.json +44 -0
  424. package/src/generators/python-microservice/docs/principles/stack/python/async.md +168 -0
  425. package/src/generators/python-microservice/docs/principles/stack/python/documentation.md +240 -0
  426. package/src/generators/python-microservice/docs/principles/stack/python/mcp.md +147 -0
  427. package/src/generators/python-microservice/docs/principles/stack/python/resilience.md +193 -0
  428. package/src/generators/python-microservice/docs/principles/stack/python/testing.md +322 -0
  429. package/src/generators/python-microservice/files/.env.example.template +30 -0
  430. package/src/generators/python-microservice/files/Dockerfile.template +36 -0
  431. package/src/generators/python-microservice/files/db/schema.sql.template +19 -0
  432. package/src/generators/python-microservice/files/pyproject.toml.template +76 -0
  433. package/src/generators/python-microservice/files/scripts/apply-schema.sh.template +25 -0
  434. package/src/generators/python-microservice/files/src/__packageName__/adapters/comfyui.py.template +87 -0
  435. package/src/generators/python-microservice/files/src/__packageName__/adapters/config.py.template +48 -0
  436. package/src/generators/python-microservice/files/src/__packageName__/adapters/database.py.template +21 -0
  437. package/src/generators/python-microservice/files/src/__packageName__/adapters/message_queue.py.template +29 -0
  438. package/src/generators/python-microservice/files/src/__packageName__/adapters/repository.py.template +130 -0
  439. package/src/generators/python-microservice/files/src/__packageName__/adapters/telemetry.py.template +68 -0
  440. package/src/generators/python-microservice/files/src/__packageName__/adapters/websocket_hub.py.template +36 -0
  441. package/src/generators/python-microservice/files/src/__packageName__/core/domain/entities.py.template +22 -0
  442. package/src/generators/python-microservice/files/src/__packageName__/core/domain/exceptions.py.template +43 -0
  443. package/src/generators/python-microservice/files/src/__packageName__/core/ports.py.template +42 -0
  444. package/src/generators/python-microservice/files/src/__packageName__/core/service/example_service.py.template +68 -0
  445. package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/dependencies.py.template +50 -0
  446. package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/middleware.py.template +131 -0
  447. package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/router.py.template +37 -0
  448. package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/websocket_handler.py.template +20 -0
  449. package/src/generators/python-microservice/files/src/__packageName__/entrypoints/worker/cleanup.py.template +35 -0
  450. package/src/generators/python-microservice/files/src/__packageName__/entrypoints/worker/worker.py.template +28 -0
  451. package/src/generators/python-microservice/files/src/__packageName__/main.py.template +108 -0
  452. package/src/generators/python-microservice/files/tests/test_main.py.template +74 -0
  453. package/src/generators/python-microservice/files/tests/test_middleware.py.template +109 -0
  454. package/src/generators/python-microservice/files/tests/test_worker.py.template +16 -0
  455. package/src/generators/python-microservice/generator.ts +286 -0
  456. package/src/generators/python-microservice/schema.json +86 -0
  457. package/src/generators/shared/brand-tokens.ts +301 -0
  458. package/src/generators/shared/capabilities.ts +349 -0
  459. package/src/generators/shared/provenance.ts +61 -0
  460. package/src/generators/shared/scaffold-helpers.ts +309 -0
  461. package/src/generators/system-test-runner/NATIVE-CHECK-CONTRACT.md +20 -0
  462. package/src/generators/system-test-runner/files/tests/bets/.gitkeep +0 -0
  463. package/src/generators/system-test-runner/files/tests/bets/_archive/.gitkeep +0 -0
  464. package/src/generators/system-test-runner/files/tests/conftest.py.template +503 -0
  465. package/src/generators/system-test-runner/files/tests/pyproject.toml.template +20 -0
  466. package/src/generators/system-test-runner/files/tests/system/pages/__init__.py.template +9 -0
  467. package/src/generators/system-test-runner/files/tests/system/pages/base_page.py.template +36 -0
  468. package/src/generators/system-test-runner/files/tests/system/test_a11y_smoke.py.template +132 -0
  469. package/src/generators/system-test-runner/files/tests/system/test_contract_conformance.py.template +140 -0
  470. package/src/generators/system-test-runner/files/tests/system/test_layout_geometry.py.template +109 -0
  471. package/src/generators/system-test-runner/files/tests/system/test_render_smoke.py.template +257 -0
  472. package/src/generators/system-test-runner/files/tests/system/test_system.py.template +158 -0
  473. package/src/generators/system-test-runner/files/tests/system/test_token_conformance.py.template +206 -0
  474. package/src/generators/system-test-runner/files/tests/system/test_visual_regression.py.template +104 -0
  475. package/src/generators/system-test-runner/generator.ts +196 -0
  476. package/src/generators/system-test-runner/schema.json +24 -0
  477. package/src/generators/workspace-dev-cli/cli-src/build.mjs +42 -0
  478. package/src/generators/workspace-dev-cli/cli-src/dist/dev-bundle.js +2168 -0
  479. package/src/generators/workspace-dev-cli/cli-src/src/commands/bet.ts +442 -0
  480. package/src/generators/workspace-dev-cli/cli-src/src/commands/completion.ts +87 -0
  481. package/src/generators/workspace-dev-cli/cli-src/src/commands/doctor.ts +139 -0
  482. package/src/generators/workspace-dev-cli/cli-src/src/commands/lifecycle.ts +548 -0
  483. package/src/generators/workspace-dev-cli/cli-src/src/commands/quality.ts +127 -0
  484. package/src/generators/workspace-dev-cli/cli-src/src/commands/surface.ts +214 -0
  485. package/src/generators/workspace-dev-cli/cli-src/src/index.ts +127 -0
  486. package/src/generators/workspace-dev-cli/cli-src/src/registry.ts +194 -0
  487. package/src/generators/workspace-dev-cli/cli-src/src/theme/color.ts +130 -0
  488. package/src/generators/workspace-dev-cli/cli-src/src/theme/render.ts +158 -0
  489. package/src/generators/workspace-dev-cli/cli-src/src/theme/tokens.ts +122 -0
  490. package/src/generators/workspace-dev-cli/cli-src/src/util/context.ts +43 -0
  491. package/src/generators/workspace-dev-cli/cli-src/src/util/extensions.ts +99 -0
  492. package/src/generators/workspace-dev-cli/cli-src/src/util/paths.ts +46 -0
  493. package/src/generators/workspace-dev-cli/cli-src/src/util/proc.ts +106 -0
  494. package/src/generators/workspace-dev-cli/cli-src/src/util/prompt.ts +108 -0
  495. package/src/generators/workspace-dev-cli/cli-src/src/util/runners.ts +70 -0
  496. package/src/generators/workspace-dev-cli/cli-src/src/util/services.ts +221 -0
  497. package/src/generators/workspace-dev-cli/cli-src/src/util/version.ts +21 -0
  498. package/src/generators/workspace-dev-cli/cli-src/tsconfig.json +16 -0
  499. package/src/generators/workspace-dev-cli/files/.agents/skills/workspace-cli/SKILL.md.template +74 -0
  500. package/src/generators/workspace-dev-cli/files/dev.template +16 -0
  501. package/src/generators/workspace-dev-cli/files/docker-compose.yml.template +20 -0
  502. package/src/generators/workspace-dev-cli/files/scripts/cli/templates/milestone-test.pytmpl.template +46 -0
  503. package/src/generators/workspace-dev-cli/files/scripts/cli/templates/slice-test.pytmpl.template +38 -0
  504. package/src/generators/workspace-dev-cli/generator.ts +136 -0
  505. package/src/generators/workspace-dev-cli/schema.json +22 -0
  506. package/src/hidden-skills/code-intelligence.md +135 -0
  507. package/src/hidden-skills/groundwork-architect/SKILL.md +114 -0
  508. package/src/hidden-skills/groundwork-architect/references/agentic-systems.md +44 -0
  509. package/src/hidden-skills/groundwork-architect/references/ai-native-architecture.md +37 -0
  510. package/src/hidden-skills/groundwork-architect/references/api-and-contracts.md +45 -0
  511. package/src/hidden-skills/groundwork-architect/references/core-and-boundaries.md +45 -0
  512. package/src/hidden-skills/groundwork-architect/references/data-architecture.md +33 -0
  513. package/src/hidden-skills/groundwork-architect/references/decision-records.md +34 -0
  514. package/src/hidden-skills/groundwork-architect/references/durable-execution.md +45 -0
  515. package/src/hidden-skills/groundwork-architect/references/evolutionary-architecture.md +37 -0
  516. package/src/hidden-skills/groundwork-architect/references/identity-and-access.md +41 -0
  517. package/src/hidden-skills/groundwork-architect/references/integration-patterns.md +39 -0
  518. package/src/hidden-skills/groundwork-architect/references/observability.md +36 -0
  519. package/src/hidden-skills/groundwork-architect/references/performance-and-scale.md +41 -0
  520. package/src/hidden-skills/groundwork-architect/references/platform-and-delivery.md +47 -0
  521. package/src/hidden-skills/groundwork-architect/references/realtime-and-async.md +28 -0
  522. package/src/hidden-skills/groundwork-architect/references/reliability.md +31 -0
  523. package/src/hidden-skills/groundwork-architect/references/security-and-trust.md +47 -0
  524. package/src/hidden-skills/groundwork-architect/references/surface-architecture.md +40 -0
  525. package/src/hidden-skills/groundwork-architect/sync-anchor.md +34 -0
  526. package/src/hidden-skills/groundwork-architecture/architecture-template.md +50 -0
  527. package/src/hidden-skills/groundwork-architecture/instructions.md +139 -0
  528. package/src/hidden-skills/groundwork-architecture/phases/01-context-ingestion.md +18 -0
  529. package/src/hidden-skills/groundwork-architecture/phases/02-technical-constraints.md +27 -0
  530. package/src/hidden-skills/groundwork-architecture/phases/03-service-design.md +19 -0
  531. package/src/hidden-skills/groundwork-architecture/phases/04-data-flow-communication.md +23 -0
  532. package/src/hidden-skills/groundwork-architecture/phases/05-component-boundaries-contracts.md +17 -0
  533. package/src/hidden-skills/groundwork-architecture/phases/06-draft-review-present.md +38 -0
  534. package/src/hidden-skills/groundwork-architecture/phases/07-commit.md +33 -0
  535. package/src/hidden-skills/groundwork-architecture/templates/architecture-cache.md +43 -0
  536. package/src/hidden-skills/groundwork-architecture-extract/instructions.md +163 -0
  537. package/src/hidden-skills/groundwork-architecture-extract/templates/architecture-extract-cache.md +21 -0
  538. package/src/hidden-skills/groundwork-bet/briefs/acceptance-auditor.md +68 -0
  539. package/src/hidden-skills/groundwork-bet/briefs/blind-reviewer.md +56 -0
  540. package/src/hidden-skills/groundwork-bet/briefs/coverage-auditor.md +95 -0
  541. package/src/hidden-skills/groundwork-bet/briefs/edge-case-tracer.md +64 -0
  542. package/src/hidden-skills/groundwork-bet/briefs/experience-auditor.md +83 -0
  543. package/src/hidden-skills/groundwork-bet/briefs/slice-worker.md +257 -0
  544. package/src/hidden-skills/groundwork-bet/instructions.md +88 -0
  545. package/src/hidden-skills/groundwork-bet/templates/bet-progress-test.md +115 -0
  546. package/src/hidden-skills/groundwork-bet/templates/change-proposal.md +38 -0
  547. package/src/hidden-skills/groundwork-bet/templates/decomposition/meta.json +4 -0
  548. package/src/hidden-skills/groundwork-bet/templates/decomposition/milestone-index.md +31 -0
  549. package/src/hidden-skills/groundwork-bet/templates/decomposition/slice.md +31 -0
  550. package/src/hidden-skills/groundwork-bet/templates/pitch.md +45 -0
  551. package/src/hidden-skills/groundwork-bet/templates/technical-design/01-ui-design.md +51 -0
  552. package/src/hidden-skills/groundwork-bet/templates/technical-design/02-data-flows.md +36 -0
  553. package/src/hidden-skills/groundwork-bet/templates/technical-design/03-api-design.md +90 -0
  554. package/src/hidden-skills/groundwork-bet/templates/technical-design/04-data-design.md +29 -0
  555. package/src/hidden-skills/groundwork-bet/workflows/01-discovery.md +200 -0
  556. package/src/hidden-skills/groundwork-bet/workflows/02-design.md +178 -0
  557. package/src/hidden-skills/groundwork-bet/workflows/03-decomposition.md +242 -0
  558. package/src/hidden-skills/groundwork-bet/workflows/04-delivery.md +226 -0
  559. package/src/hidden-skills/groundwork-bet/workflows/05-validation.md +210 -0
  560. package/src/hidden-skills/groundwork-design-system/instructions.md +125 -0
  561. package/src/hidden-skills/groundwork-design-system/templates/brand-tokens.md +182 -0
  562. package/src/hidden-skills/groundwork-design-system/templates/design-system-cache.md +64 -0
  563. package/src/hidden-skills/groundwork-design-system/tracks/_foundation.md +136 -0
  564. package/src/hidden-skills/groundwork-design-system/tracks/agentic-protocol.md +269 -0
  565. package/src/hidden-skills/groundwork-design-system/tracks/cli.md +355 -0
  566. package/src/hidden-skills/groundwork-design-system/tracks/graphical-ui.md +330 -0
  567. package/src/hidden-skills/groundwork-design-system-extract/instructions.md +124 -0
  568. package/src/hidden-skills/groundwork-design-system-extract/templates/design-system-extract-cache.md +19 -0
  569. package/src/hidden-skills/groundwork-designer/SKILL.md +108 -0
  570. package/src/hidden-skills/groundwork-designer/references/accessibility.md +33 -0
  571. package/src/hidden-skills/groundwork-designer/references/ai-native-design.md +37 -0
  572. package/src/hidden-skills/groundwork-designer/references/design-review.md +29 -0
  573. package/src/hidden-skills/groundwork-designer/references/design-systems-and-tokens.md +33 -0
  574. package/src/hidden-skills/groundwork-designer/references/interaction-and-motion.md +37 -0
  575. package/src/hidden-skills/groundwork-designer/references/layout-and-space.md +33 -0
  576. package/src/hidden-skills/groundwork-designer/references/usability-and-ux.md +33 -0
  577. package/src/hidden-skills/groundwork-designer/references/visual-craft.md +49 -0
  578. package/src/hidden-skills/groundwork-designer/sync-anchor.md +20 -0
  579. package/src/hidden-skills/groundwork-doc-sync/instructions.md +100 -0
  580. package/src/hidden-skills/groundwork-elicit/instructions.md +66 -0
  581. package/src/hidden-skills/groundwork-elicit/methods.md +65 -0
  582. package/src/hidden-skills/groundwork-infra-adopt/instructions.md +168 -0
  583. package/src/hidden-skills/groundwork-infra-adopt/templates/infra-adopt-cache.md +21 -0
  584. package/src/hidden-skills/groundwork-mvp/instructions.md +223 -0
  585. package/src/hidden-skills/groundwork-mvp/templates/mvp-cache.md +9 -0
  586. package/src/hidden-skills/groundwork-patch/instructions.md +40 -0
  587. package/src/hidden-skills/groundwork-persona/instructions.md +65 -0
  588. package/src/hidden-skills/groundwork-product/SKILL.md +102 -0
  589. package/src/hidden-skills/groundwork-product/references/ai-native-product.md +45 -0
  590. package/src/hidden-skills/groundwork-product/references/discovery-and-opportunity.md +38 -0
  591. package/src/hidden-skills/groundwork-product/references/product-risks.md +52 -0
  592. package/src/hidden-skills/groundwork-product/references/requirements-and-specs.md +39 -0
  593. package/src/hidden-skills/groundwork-product/references/scope-and-sequencing.md +35 -0
  594. package/src/hidden-skills/groundwork-product/references/shaping-and-appetite.md +48 -0
  595. package/src/hidden-skills/groundwork-product/references/success-metrics-and-signals.md +37 -0
  596. package/src/hidden-skills/groundwork-product/sync-anchor.md +19 -0
  597. package/src/hidden-skills/groundwork-product-brief/instructions.md +231 -0
  598. package/src/hidden-skills/groundwork-product-brief-extract/instructions.md +139 -0
  599. package/src/hidden-skills/groundwork-product-brief-extract/templates/product-brief-extract-cache.md +17 -0
  600. package/src/hidden-skills/groundwork-review/checklists/architecture.md +93 -0
  601. package/src/hidden-skills/groundwork-review/checklists/bet-pitch.md +94 -0
  602. package/src/hidden-skills/groundwork-review/checklists/decomposition.md +135 -0
  603. package/src/hidden-skills/groundwork-review/checklists/design-system.md +85 -0
  604. package/src/hidden-skills/groundwork-review/checklists/domain-entity.md +66 -0
  605. package/src/hidden-skills/groundwork-review/checklists/implementation-readiness.md +47 -0
  606. package/src/hidden-skills/groundwork-review/checklists/infrastructure.md +68 -0
  607. package/src/hidden-skills/groundwork-review/checklists/maturity.md +71 -0
  608. package/src/hidden-skills/groundwork-review/checklists/product-brief.md +69 -0
  609. package/src/hidden-skills/groundwork-review/checklists/technical-design.md +112 -0
  610. package/src/hidden-skills/groundwork-review/instructions.md +181 -0
  611. package/src/hidden-skills/groundwork-scaffold/instructions.md +254 -0
  612. package/src/hidden-skills/groundwork-scaffold/phases/01-ingestion-service-mapping.md +87 -0
  613. package/src/hidden-skills/groundwork-scaffold/phases/02-scaffolding-execution.md +15 -0
  614. package/src/hidden-skills/groundwork-scaffold/phases/03-service-documentation-api-stubs.md +100 -0
  615. package/src/hidden-skills/groundwork-scaffold/phases/04-infrastructure-verification.md +17 -0
  616. package/src/hidden-skills/groundwork-scaffold/phases/05-draft-review.md +19 -0
  617. package/src/hidden-skills/groundwork-scaffold/phases/06-commit.md +19 -0
  618. package/src/hidden-skills/groundwork-scaffold/templates/scaffold-cache.md +23 -0
  619. package/src/hidden-skills/groundwork-scan/instructions.md +164 -0
  620. package/src/hidden-skills/groundwork-scan/references/digest-schema.md +66 -0
  621. package/src/hidden-skills/groundwork-scan/references/exclusions.md +44 -0
  622. package/src/hidden-skills/groundwork-scan/templates/architecture-findings.md +42 -0
  623. package/src/hidden-skills/groundwork-scan/templates/design-findings.md +23 -0
  624. package/src/hidden-skills/groundwork-scan/templates/overview.md +26 -0
  625. package/src/hidden-skills/groundwork-scan/templates/product-findings.md +23 -0
  626. package/src/hidden-skills/groundwork-scan/templates/scan-state.json +19 -0
  627. package/src/hidden-skills/groundwork-stack-forge/instructions.md +150 -0
  628. package/src/hidden-skills/groundwork-stack-forge/references/authoring-engineer-skills.md +107 -0
  629. package/src/hidden-skills/groundwork-surface-activation/instructions.md +138 -0
  630. package/src/hidden-skills/groundwork-update/briefs/reconcile-worker.md +196 -0
  631. package/src/hidden-skills/groundwork-update/instructions.md +200 -0
  632. package/src/hidden-skills/groundwork-writer/SKILL.md +278 -0
  633. package/src/hidden-skills/maturity-model.md +125 -0
  634. package/src/hidden-skills/operating-contract.md +400 -0
  635. package/src/hidden-skills/repo-map-schema.md +90 -0
  636. package/src/hidden-skills/templates/adr.md +57 -0
  637. package/src/hidden-skills/templates/capability-ports.md +71 -0
  638. package/src/hidden-skills/templates/discovery-notes.md +33 -0
  639. package/src/hidden-skills/templates/domain-entity.md +80 -0
  640. package/src/hidden-skills/templates/gap-ledger.md +21 -0
  641. package/src/hidden-skills/templates/handoff.md +37 -0
  642. package/src/hidden-skills/templates/maturity.md +39 -0
  643. package/src/hidden-skills/templates/surfaces.md +207 -0
  644. package/src/skills/groundwork-check/SKILL.md +56 -0
  645. package/src/skills/groundwork-check/instructions.md +70 -0
  646. package/src/skills/groundwork-orchestrator/SKILL.md +176 -0
  647. package/src/skills/groundwork-orchestrator/workflow-index.md +50 -0
@@ -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
+ const anthropicVersion = "2023-06-01"
20
+
21
+ // Client calls the Anthropic Messages API over HTTPS. It is a minimal
22
+ // net/http adapter (no SDK dependency) — a transparent starting point you can
23
+ // extend (streaming, tool use, prompt caching) or swap for the official SDK
24
+ // behind this same interface. Reads LLM_API_KEY / LLM_BASE_URL / LLM_MODEL from env.
25
+ type Client struct {
26
+ apiKey string
27
+ baseURL string
28
+ model string
29
+ http *http.Client
30
+ }
31
+
32
+ func NewClient() *Client {
33
+ base := os.Getenv("LLM_BASE_URL")
34
+ if base == "" {
35
+ base = "https://api.anthropic.com"
36
+ }
37
+ model := os.Getenv("LLM_MODEL")
38
+ if model == "" {
39
+ model = "claude-sonnet-4-6"
40
+ }
41
+ return &Client{
42
+ apiKey: os.Getenv("LLM_API_KEY"),
43
+ baseURL: base,
44
+ model: model,
45
+ http: &http.Client{Timeout: 60 * time.Second},
46
+ }
47
+ }
48
+
49
+ func (a *Client) GenerateText(ctx context.Context, prompt string, maxTokens int) (string, error) {
50
+ reqBody, err := json.Marshal(map[string]any{
51
+ "model": a.model,
52
+ "max_tokens": maxTokens,
53
+ "messages": []map[string]string{{"role": "user", "content": prompt}},
54
+ })
55
+ if err != nil {
56
+ return "", fmt.Errorf("llm: marshal request: %w", err)
57
+ }
58
+
59
+ var lastErr error
60
+ for attempt := 0; attempt < 3; attempt++ {
61
+ req, err := http.NewRequestWithContext(ctx, http.MethodPost, a.baseURL+"/v1/messages", bytes.NewReader(reqBody))
62
+ if err != nil {
63
+ return "", fmt.Errorf("llm: build request: %w", err)
64
+ }
65
+ req.Header.Set("content-type", "application/json")
66
+ req.Header.Set("x-api-key", a.apiKey)
67
+ req.Header.Set("anthropic-version", anthropicVersion)
68
+
69
+ resp, err := a.http.Do(req)
70
+ if err != nil {
71
+ lastErr = fmt.Errorf("llm: connection error: %w", err)
72
+ continue // transient — retry
73
+ }
74
+ body, _ := io.ReadAll(resp.Body)
75
+ resp.Body.Close()
76
+
77
+ if resp.StatusCode >= 500 || resp.StatusCode == http.StatusTooManyRequests {
78
+ lastErr = fmt.Errorf("llm: transient provider error (status %d): %s", resp.StatusCode, body)
79
+ continue
80
+ }
81
+ if resp.StatusCode >= 400 {
82
+ return "", fmt.Errorf("llm: provider request error (status %d): %s", resp.StatusCode, body)
83
+ }
84
+
85
+ var parsed struct {
86
+ Content []struct {
87
+ Type string `json:"type"`
88
+ Text string `json:"text"`
89
+ } `json:"content"`
90
+ }
91
+ if err := json.Unmarshal(body, &parsed); err != nil {
92
+ return "", fmt.Errorf("llm: decode response: %w", err)
93
+ }
94
+ for _, block := range parsed.Content {
95
+ if block.Type == "text" && block.Text != "" {
96
+ return block.Text, nil
97
+ }
98
+ }
99
+ return "", fmt.Errorf("llm: empty response from provider")
100
+ }
101
+ return "", fmt.Errorf("llm: exhausted retries: %w", lastErr)
102
+ }
@@ -0,0 +1,61 @@
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 anthropic
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 Anthropic client raises at construction on a missing key,
19
+ # which would otherwise 500 every route that depends on this service.
20
+ self._client: anthropic.AsyncAnthropic | None = None
21
+ self.model = settings.llm_model
22
+
23
+ @property
24
+ def client(self) -> anthropic.AsyncAnthropic:
25
+ if self._client is None:
26
+ # base_url is optional — leave LLM_BASE_URL blank to use Anthropic's default endpoint.
27
+ self._client = anthropic.AsyncAnthropic(
28
+ api_key=settings.llm_api_key,
29
+ base_url=settings.llm_base_url or None,
30
+ )
31
+ return self._client
32
+
33
+ @circuit(failure_threshold=5, recovery_timeout=30, fallback_function=fallback_circuit_breaker, expected_exception=TransientInferenceError)
34
+ @retry(
35
+ wait=wait_exponential_jitter(initial=1, max=30),
36
+ stop=stop_after_attempt(5),
37
+ retry=retry_if_exception_type(TransientInferenceError)
38
+ )
39
+ async def generate_text(self, prompt: str, max_tokens: int = 100) -> str:
40
+ try:
41
+ response = await self.client.messages.create(
42
+ model=self.model,
43
+ max_tokens=max_tokens,
44
+ messages=[{"role": "user", "content": prompt}]
45
+ )
46
+
47
+ # Boundary validation: ensure we got a valid text response
48
+ content = next((block.text for block in response.content if block.type == "text"), None)
49
+ if not content:
50
+ raise PermanentInferenceError("Received empty response from LLM provider")
51
+
52
+ return content
53
+
54
+ except anthropic.APIConnectionError as e:
55
+ raise TransientInferenceError(f"Connection error: {e}")
56
+ except anthropic.RateLimitError as e:
57
+ raise TransientInferenceError(f"Rate limited: {e}")
58
+ except anthropic.APIStatusError as e:
59
+ if e.status_code >= 500:
60
+ raise TransientInferenceError(f"Provider server error: {e}")
61
+ raise PermanentInferenceError(f"Provider request error: {e}")
@@ -0,0 +1,13 @@
1
+ {
2
+ "kind": "env",
3
+ "summary": "A self-hosted, OpenAI-compatible endpoint (Ollama, vLLM, llama.cpp, LM Studio). Points at a base URL you run; no cloud key, no infrastructure this scaffold provisions. If you containerise the model server, add it as a compose service; if it is a host process, register it as a runner.",
4
+ "env": [
5
+ { "name": "LLM_API_KEY", "required": false, "default": "not-needed" },
6
+ { "name": "LLM_BASE_URL", "required": true, "default": "http://localhost:11434/v1" },
7
+ { "name": "LLM_MODEL", "required": false, "default": "llama3.1" }
8
+ ],
9
+ "stacks": {
10
+ "python": { "dependencies": ["openai>=1.14.0"] },
11
+ "go": { "dependencies": [] }
12
+ }
13
+ }
@@ -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,29 @@
1
+ {
2
+ "kind": "compose-service",
3
+ "summary": "A model-inference server (LocalAI) running as a docker-compose service, exposing an OpenAI-compatible API on :8080. Selecting it injects the container into the workspace compose; the adapter talks to it by env-configured base URL (the compose service name on the network, or localhost from the host).",
4
+ "env": [
5
+ { "name": "LLM_API_KEY", "required": false, "default": "not-needed" },
6
+ { "name": "LLM_BASE_URL", "required": true, "default": "http://localhost:8080/v1" },
7
+ { "name": "LLM_MODEL", "required": false, "default": "gpt-4" }
8
+ ],
9
+ "composeService": {
10
+ "name": "localai",
11
+ "definition": {
12
+ "image": "localai/localai:latest-aio-cpu",
13
+ "ports": ["8080:8080"],
14
+ "networks": ["groundwork-net"],
15
+ "volumes": ["localai_models:/models"],
16
+ "healthcheck": {
17
+ "test": ["CMD", "curl", "-f", "http://localhost:8080/readyz"],
18
+ "interval": "30s",
19
+ "timeout": "10s",
20
+ "retries": 5
21
+ }
22
+ },
23
+ "volumes": ["localai_models"]
24
+ },
25
+ "stacks": {
26
+ "python": { "dependencies": ["openai>=1.14.0"] },
27
+ "go": { "dependencies": [] }
28
+ }
29
+ }
@@ -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,9 @@
1
+ {
2
+ "kind": "none",
3
+ "summary": "Bare interface. The TextGenerator interface plus a not-yet-implemented stub and a strict-xfail contract test — a bet. No provider SDK, no env, no infrastructure. Implement it (or run `add-capability` with a real provider) to cash the bet.",
4
+ "env": [],
5
+ "stacks": {
6
+ "python": { "dependencies": [] },
7
+ "go": { "dependencies": [] }
8
+ }
9
+ }
@@ -0,0 +1,35 @@
1
+ // Package llm — bare LLM adapter: the interface is defined, the adapter is NOT
2
+ // implemented. A bet.
3
+ //
4
+ // The service.TextGenerator interface (internal/core/service/llm.go) fixes the
5
+ // contract the core depends on; this adapter is the slot where you build the
6
+ // implementation. The contract test (llm_test.go) Skips while this stub returns
7
+ // an error and flips to a live assertion the moment GenerateText works — your
8
+ // cue the bet is delivered.
9
+ //
10
+ // To cash the bet, implement GenerateText below, or regenerate against a shipped
11
+ // provider:
12
+ //
13
+ // nx g add-capability --service <this-service> --capability llm --provider anthropic
14
+ package llm
15
+
16
+ import (
17
+ "context"
18
+ "fmt"
19
+
20
+ "<%= moduleName %>/internal/core/service"
21
+ )
22
+
23
+ // Ensure Client implements the service.TextGenerator interface.
24
+ var _ service.TextGenerator = (*Client)(nil)
25
+
26
+ type Client struct{}
27
+
28
+ func NewClient() *Client {
29
+ // No provider client to construct yet — that's the bet.
30
+ return &Client{}
31
+ }
32
+
33
+ func (a *Client) GenerateText(ctx context.Context, prompt string, maxTokens int) (string, error) {
34
+ return "", fmt.Errorf("llm adapter is not implemented: build out Client.GenerateText, or scaffold a provider with `add-capability --capability=llm --provider=anthropic|openai|local`")
35
+ }
@@ -0,0 +1,25 @@
1
+ """Bare LLM adapter — the port is defined, the implementation is NOT YET written.
2
+
3
+ This is a *bet*. The TextGenerator port (src/<%= packageName %>/core/llm.py) fixes the contract
4
+ your domain depends on; this adapter is the slot where you build the
5
+ implementation. The contract test in tests/contracts/test_llm.py is marked
6
+ xfail(strict): the suite stays green while the bet is open and flips red the
7
+ moment you make generate_text work — your cue to remove the marker.
8
+
9
+ To cash the bet, either implement generate_text below, or regenerate against a
10
+ shipped provider:
11
+
12
+ nx g add-capability --service=<this-service> --capability=llm --provider=anthropic
13
+ """
14
+
15
+
16
+ class LLMClient:
17
+ def __init__(self) -> None:
18
+ # No provider client to construct yet — that's the bet.
19
+ pass
20
+
21
+ async def generate_text(self, prompt: str, max_tokens: int = 100) -> str:
22
+ raise NotImplementedError(
23
+ "LLM adapter is not implemented. Build out LLMClient.generate_text, "
24
+ "or scaffold a provider with `add-capability --capability=llm --provider=anthropic|openai|local`."
25
+ )
@@ -0,0 +1,20 @@
1
+ {
2
+ "kind": "runner",
3
+ "summary": "Ollama running as a local host process (`ollama serve`), exposing an OpenAI-compatible API on :11434. Registered as a native runner so `./dev start` brings it up alongside your services — no container. Requires the ollama binary installed on the host; pull a model with `ollama pull <model>`.",
4
+ "env": [
5
+ { "name": "LLM_API_KEY", "required": false, "default": "not-needed" },
6
+ { "name": "LLM_BASE_URL", "required": true, "default": "http://localhost:11434/v1" },
7
+ { "name": "LLM_MODEL", "required": false, "default": "llama3.1" }
8
+ ],
9
+ "runner": {
10
+ "name": "ollama",
11
+ "kind": "sidecar",
12
+ "cmd": "ollama serve",
13
+ "autostart": true,
14
+ "health": { "type": "port", "port": 11434 }
15
+ },
16
+ "stacks": {
17
+ "python": { "dependencies": ["openai>=1.14.0"] },
18
+ "go": { "dependencies": [] }
19
+ }
20
+ }