groundwork-method 0.0.1 → 0.10.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 (629) hide show
  1. package/CHANGELOG.md +781 -0
  2. package/LICENSE +21 -0
  3. package/README.md +44 -29
  4. package/bin/groundwork.js +1654 -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 +125 -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 +68 -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 +82 -0
  106. package/src/docs/principles/index.md +23 -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 +118 -0
  128. package/src/engineer-skills/groundwork-electron-engineer/references/ipc-contracts.md +138 -0
  129. package/src/engineer-skills/groundwork-electron-engineer/references/packaging-and-updates.md +82 -0
  130. package/src/engineer-skills/groundwork-electron-engineer/references/process-model.md +94 -0
  131. package/src/engineer-skills/groundwork-electron-engineer/references/security.md +107 -0
  132. package/src/engineer-skills/groundwork-electron-engineer/references/testing-and-smoke.md +107 -0
  133. package/src/engineer-skills/groundwork-electron-engineer/references/theming-and-tokens.md +74 -0
  134. package/src/engineer-skills/groundwork-electron-engineer/sync-anchor.md +14 -0
  135. package/src/engineer-skills/groundwork-flutter-engineer/SKILL.md +108 -0
  136. package/src/engineer-skills/groundwork-flutter-engineer/references/accessibility.md +92 -0
  137. package/src/engineer-skills/groundwork-flutter-engineer/references/architecture.md +189 -0
  138. package/src/engineer-skills/groundwork-flutter-engineer/references/data-and-contracts.md +136 -0
  139. package/src/engineer-skills/groundwork-flutter-engineer/references/navigation.md +122 -0
  140. package/src/engineer-skills/groundwork-flutter-engineer/references/platform-channels.md +93 -0
  141. package/src/engineer-skills/groundwork-flutter-engineer/references/releases-and-distribution.md +84 -0
  142. package/src/engineer-skills/groundwork-flutter-engineer/references/state-management.md +166 -0
  143. package/src/engineer-skills/groundwork-flutter-engineer/references/testing.md +135 -0
  144. package/src/engineer-skills/groundwork-flutter-engineer/references/theming-and-design-tokens.md +109 -0
  145. package/src/engineer-skills/groundwork-flutter-engineer/references/widgets-and-composition.md +123 -0
  146. package/src/engineer-skills/groundwork-flutter-engineer/sync-anchor.md +15 -0
  147. package/src/engineer-skills/groundwork-go-engineer/SKILL.md +171 -0
  148. package/src/engineer-skills/groundwork-go-engineer/references/api-design.md +82 -0
  149. package/src/engineer-skills/groundwork-go-engineer/references/architecture.md +42 -0
  150. package/src/engineer-skills/groundwork-go-engineer/references/capability-ports.md +50 -0
  151. package/src/engineer-skills/groundwork-go-engineer/references/code-craft-security.md +34 -0
  152. package/src/engineer-skills/groundwork-go-engineer/references/concurrency.md +108 -0
  153. package/src/engineer-skills/groundwork-go-engineer/references/go-services.md +77 -0
  154. package/src/engineer-skills/groundwork-go-engineer/references/http-handlers.md +172 -0
  155. package/src/engineer-skills/groundwork-go-engineer/references/implementation-patterns.md +156 -0
  156. package/src/engineer-skills/groundwork-go-engineer/references/integration-realtime-data.md +57 -0
  157. package/src/engineer-skills/groundwork-go-engineer/references/observability.md +49 -0
  158. package/src/engineer-skills/groundwork-go-engineer/references/postgres.md +41 -0
  159. package/src/engineer-skills/groundwork-go-engineer/references/reliability-performance.md +105 -0
  160. package/src/engineer-skills/groundwork-go-engineer/references/testing.md +139 -0
  161. package/src/engineer-skills/groundwork-go-engineer/sync-anchor.md +11 -0
  162. package/src/engineer-skills/groundwork-nextjs-engineer/SKILL.md +107 -0
  163. package/src/engineer-skills/groundwork-nextjs-engineer/references/architecture.md +323 -0
  164. package/src/engineer-skills/groundwork-nextjs-engineer/references/data-fetching.md +458 -0
  165. package/src/engineer-skills/groundwork-nextjs-engineer/references/documentation.md +324 -0
  166. package/src/engineer-skills/groundwork-nextjs-engineer/references/error-boundaries.md +383 -0
  167. package/src/engineer-skills/groundwork-nextjs-engineer/references/mutations-and-forms.md +396 -0
  168. package/src/engineer-skills/groundwork-nextjs-engineer/references/performance-and-deployment.md +947 -0
  169. package/src/engineer-skills/groundwork-nextjs-engineer/references/routing-and-navigation.md +405 -0
  170. package/src/engineer-skills/groundwork-nextjs-engineer/references/server-components.md +394 -0
  171. package/src/engineer-skills/groundwork-nextjs-engineer/references/tailwind-and-styling.md +134 -0
  172. package/src/engineer-skills/groundwork-nextjs-engineer/references/testing.md +433 -0
  173. package/src/engineer-skills/groundwork-nextjs-engineer/references/type-system.md +368 -0
  174. package/src/engineer-skills/groundwork-nextjs-engineer/references/ux-principles.md +278 -0
  175. package/src/engineer-skills/groundwork-nextjs-engineer/references/visual-language.md +69 -0
  176. package/src/engineer-skills/groundwork-nextjs-engineer/sync-anchor.md +9 -0
  177. package/src/engineer-skills/groundwork-python-engineer/SKILL.md +196 -0
  178. package/src/engineer-skills/groundwork-python-engineer/references/api-standards.md +88 -0
  179. package/src/engineer-skills/groundwork-python-engineer/references/architecture.md +57 -0
  180. package/src/engineer-skills/groundwork-python-engineer/references/async-patterns.md +103 -0
  181. package/src/engineer-skills/groundwork-python-engineer/references/capability-ports.md +44 -0
  182. package/src/engineer-skills/groundwork-python-engineer/references/database.md +88 -0
  183. package/src/engineer-skills/groundwork-python-engineer/references/documentation-mcp.md +167 -0
  184. package/src/engineer-skills/groundwork-python-engineer/references/implementation-patterns.md +166 -0
  185. package/src/engineer-skills/groundwork-python-engineer/references/ml-pipelines.md +119 -0
  186. package/src/engineer-skills/groundwork-python-engineer/references/ml-systems-ai-engineering.md +74 -0
  187. package/src/engineer-skills/groundwork-python-engineer/references/observability.md +57 -0
  188. package/src/engineer-skills/groundwork-python-engineer/references/resilience.md +126 -0
  189. package/src/engineer-skills/groundwork-python-engineer/references/testing.md +177 -0
  190. package/src/engineer-skills/groundwork-python-engineer/sync-anchor.md +13 -0
  191. package/src/generators/add-capability/generator.ts +70 -0
  192. package/src/generators/add-capability/schema.json +30 -0
  193. package/src/generators/capabilities/llm/capability.json +28 -0
  194. package/src/generators/capabilities/llm/providers/anthropic/footprint.json +13 -0
  195. package/src/generators/capabilities/llm/providers/anthropic/stacks/go/internal/llm/llm.go.template +102 -0
  196. package/src/generators/capabilities/llm/providers/anthropic/stacks/python/src/__packageName__/adapters/llm.py.template +61 -0
  197. package/src/generators/capabilities/llm/providers/local/footprint.json +13 -0
  198. package/src/generators/capabilities/llm/providers/local/stacks/go/internal/llm/llm.go.template +102 -0
  199. package/src/generators/capabilities/llm/providers/local/stacks/python/src/__packageName__/adapters/llm.py.template +53 -0
  200. package/src/generators/capabilities/llm/providers/localai/footprint.json +29 -0
  201. package/src/generators/capabilities/llm/providers/localai/stacks/go/internal/llm/llm.go.template +102 -0
  202. package/src/generators/capabilities/llm/providers/localai/stacks/python/src/__packageName__/adapters/llm.py.template +53 -0
  203. package/src/generators/capabilities/llm/providers/none/footprint.json +9 -0
  204. package/src/generators/capabilities/llm/providers/none/stacks/go/internal/llm/llm.go.template +35 -0
  205. package/src/generators/capabilities/llm/providers/none/stacks/python/src/__packageName__/adapters/llm.py.template +25 -0
  206. package/src/generators/capabilities/llm/providers/ollama/footprint.json +20 -0
  207. package/src/generators/capabilities/llm/providers/ollama/stacks/go/internal/llm/llm.go.template +102 -0
  208. package/src/generators/capabilities/llm/providers/ollama/stacks/python/src/__packageName__/adapters/llm.py.template +53 -0
  209. package/src/generators/capabilities/llm/providers/openai/footprint.json +13 -0
  210. package/src/generators/capabilities/llm/providers/openai/stacks/go/internal/llm/llm.go.template +98 -0
  211. package/src/generators/capabilities/llm/providers/openai/stacks/python/src/__packageName__/adapters/llm.py.template +60 -0
  212. package/src/generators/capabilities/llm/stacks/go/internal/core/service/llm.go.template +12 -0
  213. package/src/generators/capabilities/llm/stacks/go/internal/llm/llm_test.go.template +33 -0
  214. package/src/generators/capabilities/llm/stacks/python/src/__packageName__/core/llm.py.template +15 -0
  215. package/src/generators/capabilities/llm/stacks/python/tests/contracts/test_llm.py.template +37 -0
  216. package/src/generators/cli-app/files/README.md.template +76 -0
  217. package/src/generators/cli-app/files/build.mjs.template +15 -0
  218. package/src/generators/cli-app/files/package.json.template +21 -0
  219. package/src/generators/cli-app/files/src/cli.ts.template +67 -0
  220. package/src/generators/cli-app/files/src/commands/hello.ts.template +17 -0
  221. package/src/generators/cli-app/files/src/commands/status.ts.template +23 -0
  222. package/src/generators/cli-app/files/src/core/client.test.ts.template +80 -0
  223. package/src/generators/cli-app/files/src/core/client.ts.template +64 -0
  224. package/src/generators/cli-app/files/src/registry.test.ts.template +35 -0
  225. package/src/generators/cli-app/files/src/registry.ts.template +31 -0
  226. package/src/generators/cli-app/files/tsconfig.json.template +16 -0
  227. package/src/generators/cli-app/files/tsconfig.test.json.template +11 -0
  228. package/src/generators/cli-app/generator.ts +138 -0
  229. package/src/generators/cli-app/schema.json +24 -0
  230. package/src/generators/docs-site/files/.gitignore.ejs +40 -0
  231. package/src/generators/docs-site/files/app/docs/__slug__/page.tsx +101 -0
  232. package/src/generators/docs-site/files/app/docs/layout.tsx +14 -0
  233. package/src/generators/docs-site/files/app/docs.css +43 -0
  234. package/src/generators/docs-site/files/app/layout.tsx +24 -0
  235. package/src/generators/docs-site/files/app/page.tsx +135 -0
  236. package/src/generators/docs-site/files/app/source.ts +8 -0
  237. package/src/generators/docs-site/files/components/mermaid.tsx +67 -0
  238. package/src/generators/docs-site/files/next.config.mjs +10 -0
  239. package/src/generators/docs-site/files/package.json +32 -0
  240. package/src/generators/docs-site/files/pnpm-workspace.yaml +7 -0
  241. package/src/generators/docs-site/files/postcss.config.mjs +6 -0
  242. package/src/generators/docs-site/files/source.config.ts +77 -0
  243. package/src/generators/docs-site/files/tailwind.config.js +10 -0
  244. package/src/generators/docs-site/files/tsconfig.json +27 -0
  245. package/src/generators/docs-site/generator.ts +476 -0
  246. package/src/generators/docs-site/schema.json +17 -0
  247. package/src/generators/electron-app/docs/principles/stack/electron/index.md +47 -0
  248. package/src/generators/electron-app/docs/principles/stack/electron/ipc-contracts.md +71 -0
  249. package/src/generators/electron-app/docs/principles/stack/electron/packaging-and-updates.md +59 -0
  250. package/src/generators/electron-app/docs/principles/stack/electron/process-model.md +53 -0
  251. package/src/generators/electron-app/docs/principles/stack/electron/security.md +70 -0
  252. package/src/generators/electron-app/docs/principles/stack/typescript/frontend.md +65 -0
  253. package/src/generators/electron-app/files/.gitignore.template +20 -0
  254. package/src/generators/electron-app/files/README.md.template +125 -0
  255. package/src/generators/electron-app/files/electron.vite.config.ts +31 -0
  256. package/src/generators/electron-app/files/eslint.config.mjs +92 -0
  257. package/src/generators/electron-app/files/forge.config.ts.template +44 -0
  258. package/src/generators/electron-app/files/package.json.template +54 -0
  259. package/src/generators/electron-app/files/playwright.config.ts +18 -0
  260. package/src/generators/electron-app/files/project.json.template +65 -0
  261. package/src/generators/electron-app/files/src/main/core-client.test.ts +81 -0
  262. package/src/generators/electron-app/files/src/main/core-client.ts +55 -0
  263. package/src/generators/electron-app/files/src/main/index.ts +157 -0
  264. package/src/generators/electron-app/files/src/main/ipc.ts +52 -0
  265. package/src/generators/electron-app/files/src/main/policy.test.ts +71 -0
  266. package/src/generators/electron-app/files/src/main/policy.ts +73 -0
  267. package/src/generators/electron-app/files/src/preload/index.ts +23 -0
  268. package/src/generators/electron-app/files/src/renderer/index.html.template +20 -0
  269. package/src/generators/electron-app/files/src/renderer/src/App.test.tsx +61 -0
  270. package/src/generators/electron-app/files/src/renderer/src/App.tsx.template +43 -0
  271. package/src/generators/electron-app/files/src/renderer/src/assets/main.css +40 -0
  272. package/src/generators/electron-app/files/src/renderer/src/env.d.ts +14 -0
  273. package/src/generators/electron-app/files/src/renderer/src/main.tsx +25 -0
  274. package/src/generators/electron-app/files/src/shared/ipc.ts +54 -0
  275. package/src/generators/electron-app/files/tests/smoke/app.spec.ts.template +68 -0
  276. package/src/generators/electron-app/files/tool/electron_exec.sh.template +83 -0
  277. package/src/generators/electron-app/files/tsconfig.json +7 -0
  278. package/src/generators/electron-app/files/tsconfig.node.json +27 -0
  279. package/src/generators/electron-app/files/tsconfig.web.json +22 -0
  280. package/src/generators/electron-app/files/vitest.config.ts +32 -0
  281. package/src/generators/electron-app/files/vitest.setup.ts +1 -0
  282. package/src/generators/electron-app/generator.ts +288 -0
  283. package/src/generators/electron-app/schema.json +23 -0
  284. package/src/generators/flutter-app/docs/principles/stack/flutter/architecture.md +78 -0
  285. package/src/generators/flutter-app/docs/principles/stack/flutter/index.md +38 -0
  286. package/src/generators/flutter-app/docs/principles/stack/flutter/platform-channels.md +51 -0
  287. package/src/generators/flutter-app/docs/principles/stack/flutter/releases-and-distribution.md +59 -0
  288. package/src/generators/flutter-app/docs/principles/stack/flutter/state-management.md +85 -0
  289. package/src/generators/flutter-app/docs/principles/stack/flutter/testing.md +74 -0
  290. package/src/generators/flutter-app/docs/principles/stack/flutter/widgets-and-composition.md +69 -0
  291. package/src/generators/flutter-app/files/.gitignore.template +30 -0
  292. package/src/generators/flutter-app/files/README.md.template +100 -0
  293. package/src/generators/flutter-app/files/analysis_options.yaml.template +18 -0
  294. package/src/generators/flutter-app/files/integration_test/app_test.dart.template +30 -0
  295. package/src/generators/flutter-app/files/lib/app.dart.template +24 -0
  296. package/src/generators/flutter-app/files/lib/config/app_config.dart +15 -0
  297. package/src/generators/flutter-app/files/lib/data/repositories/status_repository.dart +36 -0
  298. package/src/generators/flutter-app/files/lib/data/services/api_client.dart +71 -0
  299. package/src/generators/flutter-app/files/lib/domain/models/health_status.dart +23 -0
  300. package/src/generators/flutter-app/files/lib/main.dart +11 -0
  301. package/src/generators/flutter-app/files/lib/router.dart +23 -0
  302. package/src/generators/flutter-app/files/lib/ui/core/theme/app_theme.dart +110 -0
  303. package/src/generators/flutter-app/files/lib/ui/home/home_view.dart +89 -0
  304. package/src/generators/flutter-app/files/lib/ui/home/home_view_model.dart.template +38 -0
  305. package/src/generators/flutter-app/files/project.json.template +51 -0
  306. package/src/generators/flutter-app/files/pubspec.yaml.template +47 -0
  307. package/src/generators/flutter-app/files/test/api_client_test.dart.template +63 -0
  308. package/src/generators/flutter-app/files/test/fakes/fake_status_repository.dart.template +19 -0
  309. package/src/generators/flutter-app/files/test/home_view_test.dart.template +58 -0
  310. package/src/generators/flutter-app/files/tool/flutter_exec.sh.template +60 -0
  311. package/src/generators/flutter-app/generator.ts +362 -0
  312. package/src/generators/flutter-app/schema.json +23 -0
  313. package/src/generators/go-microservice/docs/principles/stack/go/concurrency.md +123 -0
  314. package/src/generators/go-microservice/docs/principles/stack/go/index.md +70 -0
  315. package/src/generators/go-microservice/docs/principles/stack/go/testing.md +152 -0
  316. package/src/generators/go-microservice/files/.air.toml.template +38 -0
  317. package/src/generators/go-microservice/files/.env.template +4 -0
  318. package/src/generators/go-microservice/files/.golangci.yml.template +82 -0
  319. package/src/generators/go-microservice/files/Dockerfile.dev.template +12 -0
  320. package/src/generators/go-microservice/files/asyncapi-pubsub.yaml.template +33 -0
  321. package/src/generators/go-microservice/files/asyncapi-ws.yaml.template +34 -0
  322. package/src/generators/go-microservice/files/cmd/api/main.go.template +149 -0
  323. package/src/generators/go-microservice/files/cmd/api/main_test.go.template +99 -0
  324. package/src/generators/go-microservice/files/cmd/worker/cleanup/main.go.template +39 -0
  325. package/src/generators/go-microservice/files/db/schema.sql.template +24 -0
  326. package/src/generators/go-microservice/files/go.mod.template +39 -0
  327. package/src/generators/go-microservice/files/internal/config/config.go.template +52 -0
  328. package/src/generators/go-microservice/files/internal/config/otel.go.template +93 -0
  329. package/src/generators/go-microservice/files/internal/core/domain/errors.go.template +16 -0
  330. package/src/generators/go-microservice/files/internal/core/domain/model.go.template +28 -0
  331. package/src/generators/go-microservice/files/internal/core/domain/user.go.template +13 -0
  332. package/src/generators/go-microservice/files/internal/core/pagination.go.template +16 -0
  333. package/src/generators/go-microservice/files/internal/core/service/app_service.go.template +79 -0
  334. package/src/generators/go-microservice/files/internal/core/service/event_hub.go.template +9 -0
  335. package/src/generators/go-microservice/files/internal/core/service/message_queue.go.template +10 -0
  336. package/src/generators/go-microservice/files/internal/core/service/outbox_repository.go.template +31 -0
  337. package/src/generators/go-microservice/files/internal/core/service/repository.go.template +23 -0
  338. package/src/generators/go-microservice/files/internal/core/service/user_repository.go.template +15 -0
  339. package/src/generators/go-microservice/files/internal/core/service/user_service.go.template +43 -0
  340. package/src/generators/go-microservice/files/internal/entrypoints/api/app_handler.go.template +108 -0
  341. package/src/generators/go-microservice/files/internal/entrypoints/api/auth_middleware_test.go.template +52 -0
  342. package/src/generators/go-microservice/files/internal/entrypoints/api/clerk_webhook.go.template +202 -0
  343. package/src/generators/go-microservice/files/internal/entrypoints/api/clerk_webhook_test.go.template +82 -0
  344. package/src/generators/go-microservice/files/internal/entrypoints/api/health_handler.go.template +80 -0
  345. package/src/generators/go-microservice/files/internal/entrypoints/api/idempotency/middleware.go.template +87 -0
  346. package/src/generators/go-microservice/files/internal/entrypoints/api/idempotency/middleware_test.go.template +76 -0
  347. package/src/generators/go-microservice/files/internal/entrypoints/api/idempotency/repository.go.template +37 -0
  348. package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_auth.go.template +40 -0
  349. package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_loadshed.go.template +38 -0
  350. package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_logging.go.template +40 -0
  351. package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_ratelimit.go.template +48 -0
  352. package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_test.go.template +81 -0
  353. package/src/generators/go-microservice/files/internal/entrypoints/api/router.go.template +105 -0
  354. package/src/generators/go-microservice/files/internal/entrypoints/api/types.go.template +70 -0
  355. package/src/generators/go-microservice/files/internal/entrypoints/api/websocket_handler.go.template +39 -0
  356. package/src/generators/go-microservice/files/internal/httpclient/http_client.go.template +87 -0
  357. package/src/generators/go-microservice/files/internal/kafka/kafka.go.template +34 -0
  358. package/src/generators/go-microservice/files/internal/postgres/postgres.go.template +195 -0
  359. package/src/generators/go-microservice/files/internal/postgres/postgres_test.go.template +156 -0
  360. package/src/generators/go-microservice/files/internal/postgres/user_repository.go.template +56 -0
  361. package/src/generators/go-microservice/files/internal/pubsub/gcp_pubsub.go.template +35 -0
  362. package/src/generators/go-microservice/files/internal/websocket/client.go.template +151 -0
  363. package/src/generators/go-microservice/files/internal/websocket/hub.go.template +261 -0
  364. package/src/generators/go-microservice/files/scripts/apply-schema.sh.template +21 -0
  365. package/src/generators/go-microservice/files/tools/tools.go.template +10 -0
  366. package/src/generators/go-microservice/generator.ts +240 -0
  367. package/src/generators/go-microservice/schema.json +63 -0
  368. package/src/generators/nextjs-app/docs/principles/stack/typescript/frontend.md +65 -0
  369. package/src/generators/nextjs-app/files/.dockerignore.template +7 -0
  370. package/src/generators/nextjs-app/files/.env.example.template +24 -0
  371. package/src/generators/nextjs-app/files/.gitignore.template +5 -0
  372. package/src/generators/nextjs-app/files/Dockerfile +53 -0
  373. package/src/generators/nextjs-app/files/app/(auth)/sign-in/__sign-in__/page.tsx.template +9 -0
  374. package/src/generators/nextjs-app/files/app/(auth)/sign-up/__sign-up__/page.tsx.template +9 -0
  375. package/src/generators/nextjs-app/files/app/api/config/route.ts.template +39 -0
  376. package/src/generators/nextjs-app/files/app/api/healthz/route.test.ts +15 -0
  377. package/src/generators/nextjs-app/files/app/api/healthz/route.ts +5 -0
  378. package/src/generators/nextjs-app/files/app/api/proxy/__path__/route.test.ts.template +55 -0
  379. package/src/generators/nextjs-app/files/app/api/proxy/__path__/route.ts.template +126 -0
  380. package/src/generators/nextjs-app/files/app/error.tsx +39 -0
  381. package/src/generators/nextjs-app/files/app/global-error.tsx +68 -0
  382. package/src/generators/nextjs-app/files/app/globals.css +105 -0
  383. package/src/generators/nextjs-app/files/app/layout.tsx +59 -0
  384. package/src/generators/nextjs-app/files/app/loading.tsx +13 -0
  385. package/src/generators/nextjs-app/files/app/not-found.tsx +30 -0
  386. package/src/generators/nextjs-app/files/app/page.tsx +20 -0
  387. package/src/generators/nextjs-app/files/components/providers/default.tsx +19 -0
  388. package/src/generators/nextjs-app/files/components/providers/production.tsx +32 -0
  389. package/src/generators/nextjs-app/files/components/providers/telemetry.tsx +76 -0
  390. package/src/generators/nextjs-app/files/components/render-smoke.test.tsx +29 -0
  391. package/src/generators/nextjs-app/files/components/theme-provider.tsx +11 -0
  392. package/src/generators/nextjs-app/files/components.json +21 -0
  393. package/src/generators/nextjs-app/files/eslint.config.mjs +120 -0
  394. package/src/generators/nextjs-app/files/hooks/use-toast.ts +7 -0
  395. package/src/generators/nextjs-app/files/instrumentation.ts +90 -0
  396. package/src/generators/nextjs-app/files/lib/api/fetcher.ts.template +130 -0
  397. package/src/generators/nextjs-app/files/lib/config.ts +21 -0
  398. package/src/generators/nextjs-app/files/lib/logger.ts +29 -0
  399. package/src/generators/nextjs-app/files/lib/schemas/index.ts +19 -0
  400. package/src/generators/nextjs-app/files/lib/utils.ts +6 -0
  401. package/src/generators/nextjs-app/files/next.config.mjs +9 -0
  402. package/src/generators/nextjs-app/files/package.json +70 -0
  403. package/src/generators/nextjs-app/files/postcss.config.mjs +8 -0
  404. package/src/generators/nextjs-app/files/proxy.test.ts.template +30 -0
  405. package/src/generators/nextjs-app/files/proxy.ts +31 -0
  406. package/src/generators/nextjs-app/files/public/.gitkeep +1 -0
  407. package/src/generators/nextjs-app/files/tsconfig.json +42 -0
  408. package/src/generators/nextjs-app/files/vitest.config.mts +15 -0
  409. package/src/generators/nextjs-app/files/vitest.setup.ts +7 -0
  410. package/src/generators/nextjs-app/generator.ts +307 -0
  411. package/src/generators/nextjs-app/schema.json +44 -0
  412. package/src/generators/python-microservice/docs/principles/stack/python/async.md +168 -0
  413. package/src/generators/python-microservice/docs/principles/stack/python/documentation.md +240 -0
  414. package/src/generators/python-microservice/docs/principles/stack/python/mcp.md +147 -0
  415. package/src/generators/python-microservice/docs/principles/stack/python/resilience.md +193 -0
  416. package/src/generators/python-microservice/docs/principles/stack/python/testing.md +281 -0
  417. package/src/generators/python-microservice/files/.env.example.template +30 -0
  418. package/src/generators/python-microservice/files/Dockerfile.template +36 -0
  419. package/src/generators/python-microservice/files/db/schema.sql.template +19 -0
  420. package/src/generators/python-microservice/files/pyproject.toml.template +76 -0
  421. package/src/generators/python-microservice/files/scripts/apply-schema.sh.template +25 -0
  422. package/src/generators/python-microservice/files/src/__packageName__/adapters/comfyui.py.template +87 -0
  423. package/src/generators/python-microservice/files/src/__packageName__/adapters/config.py.template +48 -0
  424. package/src/generators/python-microservice/files/src/__packageName__/adapters/database.py.template +21 -0
  425. package/src/generators/python-microservice/files/src/__packageName__/adapters/message_queue.py.template +29 -0
  426. package/src/generators/python-microservice/files/src/__packageName__/adapters/repository.py.template +130 -0
  427. package/src/generators/python-microservice/files/src/__packageName__/adapters/telemetry.py.template +68 -0
  428. package/src/generators/python-microservice/files/src/__packageName__/adapters/websocket_hub.py.template +36 -0
  429. package/src/generators/python-microservice/files/src/__packageName__/core/domain/entities.py.template +22 -0
  430. package/src/generators/python-microservice/files/src/__packageName__/core/domain/exceptions.py.template +43 -0
  431. package/src/generators/python-microservice/files/src/__packageName__/core/ports.py.template +42 -0
  432. package/src/generators/python-microservice/files/src/__packageName__/core/service/example_service.py.template +68 -0
  433. package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/dependencies.py.template +50 -0
  434. package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/middleware.py.template +131 -0
  435. package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/router.py.template +37 -0
  436. package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/websocket_handler.py.template +20 -0
  437. package/src/generators/python-microservice/files/src/__packageName__/entrypoints/worker/cleanup.py.template +35 -0
  438. package/src/generators/python-microservice/files/src/__packageName__/entrypoints/worker/worker.py.template +28 -0
  439. package/src/generators/python-microservice/files/src/__packageName__/main.py.template +108 -0
  440. package/src/generators/python-microservice/files/tests/test_main.py.template +74 -0
  441. package/src/generators/python-microservice/files/tests/test_middleware.py.template +109 -0
  442. package/src/generators/python-microservice/files/tests/test_worker.py.template +16 -0
  443. package/src/generators/python-microservice/generator.ts +286 -0
  444. package/src/generators/python-microservice/schema.json +86 -0
  445. package/src/generators/shared/brand-tokens.ts +301 -0
  446. package/src/generators/shared/capabilities.ts +349 -0
  447. package/src/generators/shared/provenance.ts +61 -0
  448. package/src/generators/shared/scaffold-helpers.ts +309 -0
  449. package/src/generators/system-test-runner/files/tests/bets/.gitkeep +0 -0
  450. package/src/generators/system-test-runner/files/tests/bets/_archive/.gitkeep +0 -0
  451. package/src/generators/system-test-runner/files/tests/conftest.py.template +503 -0
  452. package/src/generators/system-test-runner/files/tests/pyproject.toml.template +20 -0
  453. package/src/generators/system-test-runner/files/tests/system/pages/__init__.py.template +9 -0
  454. package/src/generators/system-test-runner/files/tests/system/pages/base_page.py.template +36 -0
  455. package/src/generators/system-test-runner/files/tests/system/test_a11y_smoke.py.template +132 -0
  456. package/src/generators/system-test-runner/files/tests/system/test_contract_conformance.py.template +140 -0
  457. package/src/generators/system-test-runner/files/tests/system/test_layout_geometry.py.template +109 -0
  458. package/src/generators/system-test-runner/files/tests/system/test_render_smoke.py.template +227 -0
  459. package/src/generators/system-test-runner/files/tests/system/test_system.py.template +158 -0
  460. package/src/generators/system-test-runner/files/tests/system/test_token_conformance.py.template +206 -0
  461. package/src/generators/system-test-runner/files/tests/system/test_visual_regression.py.template +104 -0
  462. package/src/generators/system-test-runner/generator.ts +142 -0
  463. package/src/generators/system-test-runner/schema.json +24 -0
  464. package/src/generators/workspace-dev-cli/cli-src/build.mjs +42 -0
  465. package/src/generators/workspace-dev-cli/cli-src/dist/dev-bundle.js +2168 -0
  466. package/src/generators/workspace-dev-cli/cli-src/src/commands/bet.ts +442 -0
  467. package/src/generators/workspace-dev-cli/cli-src/src/commands/completion.ts +87 -0
  468. package/src/generators/workspace-dev-cli/cli-src/src/commands/doctor.ts +139 -0
  469. package/src/generators/workspace-dev-cli/cli-src/src/commands/lifecycle.ts +548 -0
  470. package/src/generators/workspace-dev-cli/cli-src/src/commands/quality.ts +127 -0
  471. package/src/generators/workspace-dev-cli/cli-src/src/commands/surface.ts +214 -0
  472. package/src/generators/workspace-dev-cli/cli-src/src/index.ts +127 -0
  473. package/src/generators/workspace-dev-cli/cli-src/src/registry.ts +194 -0
  474. package/src/generators/workspace-dev-cli/cli-src/src/theme/color.ts +130 -0
  475. package/src/generators/workspace-dev-cli/cli-src/src/theme/render.ts +158 -0
  476. package/src/generators/workspace-dev-cli/cli-src/src/theme/tokens.ts +122 -0
  477. package/src/generators/workspace-dev-cli/cli-src/src/util/context.ts +43 -0
  478. package/src/generators/workspace-dev-cli/cli-src/src/util/extensions.ts +99 -0
  479. package/src/generators/workspace-dev-cli/cli-src/src/util/paths.ts +46 -0
  480. package/src/generators/workspace-dev-cli/cli-src/src/util/proc.ts +106 -0
  481. package/src/generators/workspace-dev-cli/cli-src/src/util/prompt.ts +108 -0
  482. package/src/generators/workspace-dev-cli/cli-src/src/util/runners.ts +70 -0
  483. package/src/generators/workspace-dev-cli/cli-src/src/util/services.ts +221 -0
  484. package/src/generators/workspace-dev-cli/cli-src/src/util/version.ts +21 -0
  485. package/src/generators/workspace-dev-cli/cli-src/tsconfig.json +16 -0
  486. package/src/generators/workspace-dev-cli/files/.agents/skills/workspace-cli/SKILL.md.template +74 -0
  487. package/src/generators/workspace-dev-cli/files/dev.template +16 -0
  488. package/src/generators/workspace-dev-cli/files/docker-compose.yml.template +20 -0
  489. package/src/generators/workspace-dev-cli/files/scripts/cli/templates/milestone-test.pytmpl.template +46 -0
  490. package/src/generators/workspace-dev-cli/files/scripts/cli/templates/slice-test.pytmpl.template +38 -0
  491. package/src/generators/workspace-dev-cli/generator.ts +136 -0
  492. package/src/generators/workspace-dev-cli/schema.json +22 -0
  493. package/src/hidden-skills/code-intelligence.md +129 -0
  494. package/src/hidden-skills/groundwork-architect/SKILL.md +114 -0
  495. package/src/hidden-skills/groundwork-architect/references/agentic-systems.md +44 -0
  496. package/src/hidden-skills/groundwork-architect/references/ai-native-architecture.md +37 -0
  497. package/src/hidden-skills/groundwork-architect/references/api-and-contracts.md +45 -0
  498. package/src/hidden-skills/groundwork-architect/references/core-and-boundaries.md +45 -0
  499. package/src/hidden-skills/groundwork-architect/references/data-architecture.md +33 -0
  500. package/src/hidden-skills/groundwork-architect/references/decision-records.md +34 -0
  501. package/src/hidden-skills/groundwork-architect/references/durable-execution.md +45 -0
  502. package/src/hidden-skills/groundwork-architect/references/evolutionary-architecture.md +37 -0
  503. package/src/hidden-skills/groundwork-architect/references/identity-and-access.md +41 -0
  504. package/src/hidden-skills/groundwork-architect/references/integration-patterns.md +39 -0
  505. package/src/hidden-skills/groundwork-architect/references/observability.md +36 -0
  506. package/src/hidden-skills/groundwork-architect/references/performance-and-scale.md +41 -0
  507. package/src/hidden-skills/groundwork-architect/references/platform-and-delivery.md +47 -0
  508. package/src/hidden-skills/groundwork-architect/references/realtime-and-async.md +28 -0
  509. package/src/hidden-skills/groundwork-architect/references/reliability.md +31 -0
  510. package/src/hidden-skills/groundwork-architect/references/security-and-trust.md +47 -0
  511. package/src/hidden-skills/groundwork-architect/references/surface-architecture.md +40 -0
  512. package/src/hidden-skills/groundwork-architect/sync-anchor.md +34 -0
  513. package/src/hidden-skills/groundwork-architecture/architecture-template.md +50 -0
  514. package/src/hidden-skills/groundwork-architecture/instructions.md +139 -0
  515. package/src/hidden-skills/groundwork-architecture/phases/01-context-ingestion.md +18 -0
  516. package/src/hidden-skills/groundwork-architecture/phases/02-technical-constraints.md +27 -0
  517. package/src/hidden-skills/groundwork-architecture/phases/03-service-design.md +19 -0
  518. package/src/hidden-skills/groundwork-architecture/phases/04-data-flow-communication.md +23 -0
  519. package/src/hidden-skills/groundwork-architecture/phases/05-component-boundaries-contracts.md +17 -0
  520. package/src/hidden-skills/groundwork-architecture/phases/06-draft-review-present.md +38 -0
  521. package/src/hidden-skills/groundwork-architecture/phases/07-commit.md +33 -0
  522. package/src/hidden-skills/groundwork-architecture/templates/architecture-cache.md +43 -0
  523. package/src/hidden-skills/groundwork-architecture-extract/instructions.md +163 -0
  524. package/src/hidden-skills/groundwork-architecture-extract/templates/architecture-extract-cache.md +21 -0
  525. package/src/hidden-skills/groundwork-bet/briefs/slice-worker.md +191 -0
  526. package/src/hidden-skills/groundwork-bet/instructions.md +88 -0
  527. package/src/hidden-skills/groundwork-bet/templates/bet-progress-test.md +126 -0
  528. package/src/hidden-skills/groundwork-bet/templates/change-proposal.md +38 -0
  529. package/src/hidden-skills/groundwork-bet/templates/decomposition/meta.json +4 -0
  530. package/src/hidden-skills/groundwork-bet/templates/decomposition/milestone-index.md +35 -0
  531. package/src/hidden-skills/groundwork-bet/templates/decomposition/slice.md +35 -0
  532. package/src/hidden-skills/groundwork-bet/templates/pitch.md +45 -0
  533. package/src/hidden-skills/groundwork-bet/templates/technical-design/01-ui-design.md +51 -0
  534. package/src/hidden-skills/groundwork-bet/templates/technical-design/02-data-flows.md +36 -0
  535. package/src/hidden-skills/groundwork-bet/templates/technical-design/03-api-design.md +90 -0
  536. package/src/hidden-skills/groundwork-bet/templates/technical-design/04-data-design.md +29 -0
  537. package/src/hidden-skills/groundwork-bet/workflows/01-discovery.md +198 -0
  538. package/src/hidden-skills/groundwork-bet/workflows/02-design.md +168 -0
  539. package/src/hidden-skills/groundwork-bet/workflows/03-decomposition.md +246 -0
  540. package/src/hidden-skills/groundwork-bet/workflows/04-delivery.md +193 -0
  541. package/src/hidden-skills/groundwork-bet/workflows/05-validation.md +199 -0
  542. package/src/hidden-skills/groundwork-design-system/instructions.md +125 -0
  543. package/src/hidden-skills/groundwork-design-system/templates/brand-tokens.md +182 -0
  544. package/src/hidden-skills/groundwork-design-system/templates/design-system-cache.md +64 -0
  545. package/src/hidden-skills/groundwork-design-system/tracks/_foundation.md +136 -0
  546. package/src/hidden-skills/groundwork-design-system/tracks/agentic-protocol.md +269 -0
  547. package/src/hidden-skills/groundwork-design-system/tracks/cli.md +355 -0
  548. package/src/hidden-skills/groundwork-design-system/tracks/graphical-ui.md +330 -0
  549. package/src/hidden-skills/groundwork-design-system-extract/instructions.md +124 -0
  550. package/src/hidden-skills/groundwork-design-system-extract/templates/design-system-extract-cache.md +19 -0
  551. package/src/hidden-skills/groundwork-designer/SKILL.md +108 -0
  552. package/src/hidden-skills/groundwork-designer/references/accessibility.md +33 -0
  553. package/src/hidden-skills/groundwork-designer/references/ai-native-design.md +37 -0
  554. package/src/hidden-skills/groundwork-designer/references/design-review.md +29 -0
  555. package/src/hidden-skills/groundwork-designer/references/design-systems-and-tokens.md +33 -0
  556. package/src/hidden-skills/groundwork-designer/references/interaction-and-motion.md +37 -0
  557. package/src/hidden-skills/groundwork-designer/references/layout-and-space.md +33 -0
  558. package/src/hidden-skills/groundwork-designer/references/usability-and-ux.md +33 -0
  559. package/src/hidden-skills/groundwork-designer/references/visual-craft.md +49 -0
  560. package/src/hidden-skills/groundwork-designer/sync-anchor.md +20 -0
  561. package/src/hidden-skills/groundwork-doc-sync/instructions.md +100 -0
  562. package/src/hidden-skills/groundwork-elicit/instructions.md +66 -0
  563. package/src/hidden-skills/groundwork-elicit/methods.md +65 -0
  564. package/src/hidden-skills/groundwork-infra-adopt/instructions.md +168 -0
  565. package/src/hidden-skills/groundwork-infra-adopt/templates/infra-adopt-cache.md +21 -0
  566. package/src/hidden-skills/groundwork-mvp/instructions.md +223 -0
  567. package/src/hidden-skills/groundwork-mvp/templates/mvp-cache.md +9 -0
  568. package/src/hidden-skills/groundwork-patch/instructions.md +40 -0
  569. package/src/hidden-skills/groundwork-persona/instructions.md +54 -0
  570. package/src/hidden-skills/groundwork-product/SKILL.md +102 -0
  571. package/src/hidden-skills/groundwork-product/references/ai-native-product.md +45 -0
  572. package/src/hidden-skills/groundwork-product/references/discovery-and-opportunity.md +38 -0
  573. package/src/hidden-skills/groundwork-product/references/product-risks.md +52 -0
  574. package/src/hidden-skills/groundwork-product/references/requirements-and-specs.md +39 -0
  575. package/src/hidden-skills/groundwork-product/references/scope-and-sequencing.md +35 -0
  576. package/src/hidden-skills/groundwork-product/references/shaping-and-appetite.md +48 -0
  577. package/src/hidden-skills/groundwork-product/references/success-metrics-and-signals.md +37 -0
  578. package/src/hidden-skills/groundwork-product/sync-anchor.md +19 -0
  579. package/src/hidden-skills/groundwork-product-brief/instructions.md +231 -0
  580. package/src/hidden-skills/groundwork-product-brief-extract/instructions.md +139 -0
  581. package/src/hidden-skills/groundwork-product-brief-extract/templates/product-brief-extract-cache.md +17 -0
  582. package/src/hidden-skills/groundwork-review/checklists/architecture.md +93 -0
  583. package/src/hidden-skills/groundwork-review/checklists/bet-pitch.md +94 -0
  584. package/src/hidden-skills/groundwork-review/checklists/decomposition.md +135 -0
  585. package/src/hidden-skills/groundwork-review/checklists/design-system.md +85 -0
  586. package/src/hidden-skills/groundwork-review/checklists/domain-entity.md +66 -0
  587. package/src/hidden-skills/groundwork-review/checklists/implementation-readiness.md +46 -0
  588. package/src/hidden-skills/groundwork-review/checklists/infrastructure.md +68 -0
  589. package/src/hidden-skills/groundwork-review/checklists/maturity.md +71 -0
  590. package/src/hidden-skills/groundwork-review/checklists/product-brief.md +69 -0
  591. package/src/hidden-skills/groundwork-review/checklists/technical-design.md +112 -0
  592. package/src/hidden-skills/groundwork-review/instructions.md +181 -0
  593. package/src/hidden-skills/groundwork-scaffold/instructions.md +254 -0
  594. package/src/hidden-skills/groundwork-scaffold/phases/01-ingestion-service-mapping.md +87 -0
  595. package/src/hidden-skills/groundwork-scaffold/phases/02-scaffolding-execution.md +15 -0
  596. package/src/hidden-skills/groundwork-scaffold/phases/03-service-documentation-api-stubs.md +100 -0
  597. package/src/hidden-skills/groundwork-scaffold/phases/04-infrastructure-verification.md +17 -0
  598. package/src/hidden-skills/groundwork-scaffold/phases/05-draft-review.md +19 -0
  599. package/src/hidden-skills/groundwork-scaffold/phases/06-commit.md +19 -0
  600. package/src/hidden-skills/groundwork-scaffold/templates/scaffold-cache.md +23 -0
  601. package/src/hidden-skills/groundwork-scan/instructions.md +164 -0
  602. package/src/hidden-skills/groundwork-scan/references/digest-schema.md +66 -0
  603. package/src/hidden-skills/groundwork-scan/references/exclusions.md +44 -0
  604. package/src/hidden-skills/groundwork-scan/templates/architecture-findings.md +42 -0
  605. package/src/hidden-skills/groundwork-scan/templates/design-findings.md +23 -0
  606. package/src/hidden-skills/groundwork-scan/templates/overview.md +26 -0
  607. package/src/hidden-skills/groundwork-scan/templates/product-findings.md +23 -0
  608. package/src/hidden-skills/groundwork-scan/templates/scan-state.json +19 -0
  609. package/src/hidden-skills/groundwork-stack-forge/instructions.md +150 -0
  610. package/src/hidden-skills/groundwork-stack-forge/references/authoring-engineer-skills.md +107 -0
  611. package/src/hidden-skills/groundwork-surface-activation/instructions.md +138 -0
  612. package/src/hidden-skills/groundwork-update/briefs/reconcile-worker.md +196 -0
  613. package/src/hidden-skills/groundwork-update/instructions.md +200 -0
  614. package/src/hidden-skills/groundwork-writer/SKILL.md +278 -0
  615. package/src/hidden-skills/maturity-model.md +125 -0
  616. package/src/hidden-skills/operating-contract.md +400 -0
  617. package/src/hidden-skills/repo-map-schema.md +90 -0
  618. package/src/hidden-skills/templates/adr.md +57 -0
  619. package/src/hidden-skills/templates/capability-ports.md +71 -0
  620. package/src/hidden-skills/templates/discovery-notes.md +33 -0
  621. package/src/hidden-skills/templates/domain-entity.md +80 -0
  622. package/src/hidden-skills/templates/gap-ledger.md +21 -0
  623. package/src/hidden-skills/templates/handoff.md +37 -0
  624. package/src/hidden-skills/templates/maturity.md +39 -0
  625. package/src/hidden-skills/templates/surfaces.md +207 -0
  626. package/src/skills/groundwork-check/SKILL.md +56 -0
  627. package/src/skills/groundwork-check/instructions.md +70 -0
  628. package/src/skills/groundwork-orchestrator/SKILL.md +176 -0
  629. package/src/skills/groundwork-orchestrator/workflow-index.md +50 -0
@@ -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
+ <% } %>
@@ -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
+ }
@@ -0,0 +1,80 @@
1
+ // The core-access seam is proven without a network: fetch is injected, so
2
+ // every reachability outcome (ok, non-200, thrown) is a deterministic case.
3
+ // Runs on node:test — the CLI's test layer adds no dependencies, like the
4
+ // CLI itself.
5
+ import { describe, it } from 'node:test';
6
+ import assert from 'node:assert/strict';
7
+ import {
8
+ DEFAULT_CORE_BASE_URL,
9
+ coreAuthHeaders,
10
+ coreBaseUrl,
11
+ fetchCoreHealth,
12
+ } from './client';
13
+
14
+ function fetchReturning(status: number, body: unknown): typeof fetch {
15
+ return (async () =>
16
+ new Response(JSON.stringify(body), {
17
+ status,
18
+ headers: { 'Content-Type': 'application/json' },
19
+ })) as typeof fetch;
20
+ }
21
+
22
+ describe('coreBaseUrl', () => {
23
+ it('defaults to the workspace gateway', () => {
24
+ assert.equal(coreBaseUrl({}), DEFAULT_CORE_BASE_URL);
25
+ });
26
+
27
+ it('honours API_BASE_URL from the environment', () => {
28
+ assert.equal(coreBaseUrl({ API_BASE_URL: 'http://10.0.0.5:4000' }), 'http://10.0.0.5:4000');
29
+ });
30
+
31
+ it('treats a blank API_BASE_URL as unset', () => {
32
+ assert.equal(coreBaseUrl({ API_BASE_URL: ' ' }), DEFAULT_CORE_BASE_URL);
33
+ });
34
+ });
35
+
36
+ describe('coreAuthHeaders', () => {
37
+ it('is unauthenticated by default', () => {
38
+ assert.deepEqual(coreAuthHeaders(), {});
39
+ });
40
+
41
+ it('carries a supplied token as a Bearer header', () => {
42
+ assert.deepEqual(coreAuthHeaders('jwt-123'), { Authorization: 'Bearer jwt-123' });
43
+ });
44
+ });
45
+
46
+ describe('fetchCoreHealth', () => {
47
+ it('maps a healthy core to reachable + its reported status', async () => {
48
+ const health = await fetchCoreHealth(
49
+ 'http://core.test',
50
+ fetchReturning(200, { status: 'ok', checks: { db: 'ok' } }),
51
+ );
52
+ assert.deepEqual(health, { reachable: true, status: 'ok' });
53
+ });
54
+
55
+ it('requests the /health route of the configured base URL', async () => {
56
+ let requested: string | undefined;
57
+ const probe = (async (input: Parameters<typeof fetch>[0]) => {
58
+ requested = String(input);
59
+ return new Response('{"status":"ok"}', { status: 200 });
60
+ }) as typeof fetch;
61
+ await fetchCoreHealth('http://core.test:4000', probe);
62
+ assert.equal(requested, 'http://core.test:4000/health');
63
+ });
64
+
65
+ it('maps a non-200 to unreachable with the code as the status', async () => {
66
+ const health = await fetchCoreHealth(
67
+ 'http://core.test',
68
+ fetchReturning(503, { error: 'overloaded' }),
69
+ );
70
+ assert.deepEqual(health, { reachable: false, status: 'http 503' });
71
+ });
72
+
73
+ it('maps a network failure to a value, never a throw', async () => {
74
+ const down = (async () => {
75
+ throw new Error('ECONNREFUSED');
76
+ }) as typeof fetch;
77
+ const health = await fetchCoreHealth('http://core.test', down);
78
+ assert.deepEqual(health, { reachable: false, status: 'unreachable' });
79
+ });
80
+ });
@@ -0,0 +1,64 @@
1
+ // The core-access seam: the ONLY place this CLI talks to the workspace
2
+ // gateway. Commands consume these functions and never carry transport
3
+ // detail themselves — the terminal twin of the desktop scaffold's
4
+ // main-process core client and the mobile scaffold's thin dio client.
5
+ //
6
+ // Contract-client stance (O8): hand-rolled and deliberately thin — one
7
+ // function per promoted-contract operation, typed results beside them.
8
+ // When the promoted openapi.yaml grows past a handful of operations, switch
9
+ // to a generated TypeScript client and keep this module as the seam the
10
+ // commands consume — nothing above it changes.
11
+
12
+ /** The workspace core's health as commands render it. An unreachable core
13
+ * is a value, not an exception: a CLI fronting a down service reports it
14
+ * through output and exit code, never a stack trace. */
15
+ export type CoreHealth = {
16
+ reachable: boolean;
17
+ status: string;
18
+ };
19
+
20
+ export const DEFAULT_CORE_BASE_URL = 'http://localhost:4000';
21
+
22
+ /** Where the workspace core lives. The system-test harness (and any
23
+ * deployed environment) overrides via the API_BASE_URL environment
24
+ * variable. Standalone use never reaches this module — the seam only
25
+ * exists when the CLI fronts workspace services. */
26
+ export function coreBaseUrl(env: NodeJS.ProcessEnv = process.env): string {
27
+ const configured = env['API_BASE_URL']?.trim();
28
+ return configured ? configured : DEFAULT_CORE_BASE_URL;
29
+ }
30
+
31
+ /** The auth seam: headers attached to every core request. Unauthenticated
32
+ * by default — wire your identity provider here (e.g. a service token from
33
+ * the environment becomes `Authorization: Bearer <token>`); the core's
34
+ * /health route stays public. */
35
+ export function coreAuthHeaders(token?: string): Record<string, string> {
36
+ return token ? { Authorization: `Bearer ${token}` } : {};
37
+ }
38
+
39
+ /** Probe the gateway's health endpoint — the wiring proof the `status`
40
+ * command renders. `/health` is what GroundWork's Go and Python cores
41
+ * serve; a Next.js BFF would be `/api/healthz` — adjust to your gateway.
42
+ * Failures map to a value, never a throw: an unreachable core is a state
43
+ * the command reports (exit 1), not an exception that kills the process. */
44
+ export async function fetchCoreHealth(
45
+ baseUrl: string = coreBaseUrl(),
46
+ fetchImpl: typeof fetch = fetch,
47
+ ): Promise<CoreHealth> {
48
+ try {
49
+ const response = await fetchImpl(new URL('/health', baseUrl), {
50
+ headers: { Accept: 'application/json', ...coreAuthHeaders() },
51
+ signal: AbortSignal.timeout(5_000),
52
+ });
53
+ if (!response.ok) {
54
+ return { reachable: false, status: `http ${response.status}` };
55
+ }
56
+ const body = (await response.json()) as { status?: unknown };
57
+ return {
58
+ reachable: true,
59
+ status: typeof body.status === 'string' ? body.status : 'ok',
60
+ };
61
+ } catch {
62
+ return { reachable: false, status: 'unreachable' };
63
+ }
64
+ }
@@ -0,0 +1,35 @@
1
+ // The registry is the single source of truth for dispatch and help — these
2
+ // tests keep it honest as commands accrete. Runs on node:test (zero deps).
3
+ import { describe, it } from 'node:test';
4
+ import assert from 'node:assert/strict';
5
+ import { COMMANDS, findCommand } from './registry';
6
+
7
+ describe('command registry', () => {
8
+ it('registers at least one command', () => {
9
+ assert.ok(COMMANDS.length > 0);
10
+ });
11
+
12
+ it('has no duplicate command names', () => {
13
+ const names = COMMANDS.map((c) => c.name);
14
+ assert.equal(new Set(names).size, names.length);
15
+ });
16
+
17
+ it('gives every command a group and a summary (help renders from these)', () => {
18
+ for (const c of COMMANDS) {
19
+ assert.ok(c.summary.length > 0, `command ${c.name} has no summary`);
20
+ assert.ok(['CORE', 'META'].includes(c.group), `command ${c.name} has an unknown group`);
21
+ }
22
+ });
23
+
24
+ it('resolves a registered command', () => {
25
+ assert.ok(findCommand('hello'));
26
+ });
27
+
28
+ it('returns undefined for an unknown command (cli.ts exits 2 on this)', () => {
29
+ assert.equal(findCommand('no-such-command'), undefined);
30
+ });
31
+ <% if (core) { %>
32
+ it('registers the core status probe — the wiring proof to the workspace core', () => {
33
+ assert.ok(findCommand('status'));
34
+ });
35
+ <% } %>});