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,132 @@
1
+ <% if (!surfaces) { -%>
2
+ """Accessibility + console-hygiene smoke for the graphical UI.
3
+
4
+ Loads the frontend root (discovered via conftest.frontend_base_url) and asserts:
5
+
6
+ 1. No severe console errors during initial load — uncaught page errors and
7
+ console.error output both fail the smoke.
8
+ 2. An axe-core scan (injected from CDN — no extra pip dependency) reports
9
+ ZERO critical violations. Lower-impact findings are reported as warnings
10
+ so they surface without blocking the loop.
11
+
12
+ Skips cleanly when no frontend service is discovered (frontend_base_url skips)
13
+ and when the axe-core CDN is unreachable (offline runs must not false-fail).
14
+ """
15
+
16
+ import warnings
17
+
18
+ import pytest
19
+ from playwright.sync_api import Page
20
+
21
+ AXE_CDN_URL = "https://cdn.jsdelivr.net/npm/axe-core@4.10.2/axe.min.js"
22
+
23
+
24
+ def test_frontend_root_a11y_smoke(cluster, frontend_base_url, page: Page):
25
+ console_errors: list[str] = []
26
+ page.on(
27
+ "console",
28
+ lambda msg: console_errors.append(msg.text) if msg.type == "error" else None,
29
+ )
30
+ page.on("pageerror", lambda exc: console_errors.append(f"pageerror: {exc}"))
31
+
32
+ page.goto(frontend_base_url, wait_until="load")
33
+ # Let hydration and deferred requests settle so late errors are captured.
34
+ page.wait_for_load_state("networkidle")
35
+
36
+ assert not console_errors, (
37
+ f"frontend root emitted severe console errors on load:\n "
38
+ + "\n ".join(console_errors)
39
+ )
40
+
41
+ try:
42
+ page.add_script_tag(url=AXE_CDN_URL)
43
+ except Exception as exc: # noqa: BLE001 — any injection failure means no scan
44
+ pytest.skip(f"axe-core CDN unreachable, a11y scan skipped: {exc}")
45
+
46
+ results = page.evaluate(
47
+ "() => axe.run(document, { resultTypes: ['violations'] })"
48
+ )
49
+ violations = results.get("violations", [])
50
+
51
+ non_critical = [v for v in violations if v.get("impact") != "critical"]
52
+ if non_critical:
53
+ summary = ", ".join(f"{v['id']} ({v.get('impact')})" for v in non_critical)
54
+ warnings.warn(f"non-critical a11y violations on frontend root: {summary}")
55
+
56
+ critical = [v for v in violations if v.get("impact") == "critical"]
57
+ assert not critical, (
58
+ "axe-core found CRITICAL accessibility violations on the frontend root:\n "
59
+ + "\n ".join(
60
+ f"{v['id']}: {v['help']} ({len(v.get('nodes', []))} node(s))"
61
+ for v in critical
62
+ )
63
+ )
64
+ <% } else { -%>
65
+ """Accessibility + console-hygiene smoke, one test per graphical surface.
66
+
67
+ Each test loads the surface's root via its generated per-surface page fixture
68
+ (see conftest's surface fixtures) and asserts:
69
+
70
+ 1. No severe console errors during initial load — uncaught page errors and
71
+ console.error output both fail the smoke.
72
+ 2. An axe-core scan (injected from CDN — no extra pip dependency) reports
73
+ ZERO critical violations. Lower-impact findings are reported as warnings
74
+ so they surface without blocking the loop.
75
+
76
+ Skips cleanly when a surface is not reachable (its page fixture skips) and
77
+ when the axe-core CDN is unreachable (offline runs must not false-fail).
78
+ """
79
+
80
+ import warnings
81
+
82
+ import pytest
83
+ from playwright.sync_api import Page
84
+
85
+ AXE_CDN_URL = "https://cdn.jsdelivr.net/npm/axe-core@4.10.2/axe.min.js"
86
+
87
+
88
+ def _root_a11y_smoke(page: Page, surface_slug: str) -> None:
89
+ console_errors: list[str] = []
90
+ page.on(
91
+ "console",
92
+ lambda msg: console_errors.append(msg.text) if msg.type == "error" else None,
93
+ )
94
+ page.on("pageerror", lambda exc: console_errors.append(f"pageerror: {exc}"))
95
+
96
+ page.goto("/", wait_until="load")
97
+ # Let hydration and deferred requests settle so late errors are captured.
98
+ page.wait_for_load_state("networkidle")
99
+
100
+ assert not console_errors, (
101
+ f"{surface_slug} root emitted severe console errors on load:\n "
102
+ + "\n ".join(console_errors)
103
+ )
104
+
105
+ try:
106
+ page.add_script_tag(url=AXE_CDN_URL)
107
+ except Exception as exc: # noqa: BLE001 — any injection failure means no scan
108
+ pytest.skip(f"axe-core CDN unreachable, a11y scan skipped: {exc}")
109
+
110
+ results = page.evaluate(
111
+ "() => axe.run(document, { resultTypes: ['violations'] })"
112
+ )
113
+ violations = results.get("violations", [])
114
+
115
+ non_critical = [v for v in violations if v.get("impact") != "critical"]
116
+ if non_critical:
117
+ summary = ", ".join(f"{v['id']} ({v.get('impact')})" for v in non_critical)
118
+ warnings.warn(f"non-critical a11y violations on {surface_slug} root: {summary}")
119
+
120
+ critical = [v for v in violations if v.get("impact") == "critical"]
121
+ assert not critical, (
122
+ f"axe-core found CRITICAL accessibility violations on the {surface_slug} root:\n "
123
+ + "\n ".join(
124
+ f"{v['id']}: {v['help']} ({len(v.get('nodes', []))} node(s))"
125
+ for v in critical
126
+ )
127
+ )
128
+ <% graphicalSurfaces.forEach((s) => { %>
129
+
130
+ def test_<%= s.ident %>_root_a11y_smoke(cluster, <%= s.ident %>_page: Page):
131
+ _root_a11y_smoke(<%= s.ident %>_page, "<%= s.slug %>")
132
+ <% }) %><% } -%>
@@ -0,0 +1,140 @@
1
+ """Contract conformance: the served API vs the promoted design spec.
2
+
3
+ For each discovered APP service (see conftest.services_manifest) with a
4
+ canonical promoted spec at docs/architecture/api/<service>/openapi.yaml, fetch the spec the
5
+ RUNNING service serves (Huma on Go and FastAPI both expose /openapi.json) and
6
+ structurally compare paths + methods + response codes.
7
+
8
+ Drift taxonomy:
9
+ BREAKING — surface present in the design spec but missing from the served
10
+ spec (a path, method, or response code the design promises and
11
+ the implementation does not deliver). Fails the test.
12
+ ADDITIVE — surface the service serves that the design spec does not declare.
13
+ Reported as a warning: no consumer breaks, but the canonical spec
14
+ is stale and should be re-promoted (see the bet validation phase).
15
+
16
+ Skips cleanly when no design spec is committed for a service, or the service
17
+ does not expose a machine-readable spec.
18
+ """
19
+
20
+ import re
21
+ import warnings
22
+
23
+ import httpx
24
+ import pytest
25
+ import yaml
26
+
27
+ from conftest import WORKSPACE_ROOT, _base_url, _discover_services
28
+
29
+ DESIGN_SPEC_ROOT = WORKSPACE_ROOT / "docs" / "api"
30
+ # Huma serves both; FastAPI serves /openapi.json. Try JSON first.
31
+ SERVED_SPEC_PATHS = ("/openapi.json", "/openapi.yaml")
32
+ HTTP_METHODS = {"get", "put", "post", "delete", "options", "head", "patch", "trace"}
33
+
34
+ # Build params at import time so pytest shows one case per service.
35
+ _SERVICES = _discover_services()
36
+ _PARAMS = [pytest.param(s, id=s["name"]) for s in _SERVICES]
37
+
38
+
39
+ def _normalize_path(path: str) -> str:
40
+ """Collapse path-parameter names so /users/{id} == /users/{userId}.
41
+
42
+ Parameter naming is a spec-authoring choice, not an API surface change —
43
+ comparing it would report false breaking drift.
44
+ """
45
+ return re.sub(r"\{[^}]*\}", "{}", path)
46
+
47
+
48
+ def _surface(spec: dict) -> dict[tuple[str, str], set[str]]:
49
+ """Flatten an OpenAPI document to {(path, method): {response codes}}."""
50
+ surface: dict[tuple[str, str], set[str]] = {}
51
+ for raw_path, item in (spec.get("paths") or {}).items():
52
+ if not isinstance(item, dict):
53
+ continue
54
+ for method, op in item.items():
55
+ if method.lower() not in HTTP_METHODS or not isinstance(op, dict):
56
+ continue
57
+ codes = {str(c) for c in (op.get("responses") or {})}
58
+ surface[(_normalize_path(raw_path), method.lower())] = codes
59
+ return surface
60
+
61
+
62
+ def _load_design_spec(service_name: str) -> dict | None:
63
+ spec_path = DESIGN_SPEC_ROOT / service_name / "openapi.yaml"
64
+ if not spec_path.exists():
65
+ return None
66
+ return yaml.safe_load(spec_path.read_text()) or {}
67
+
68
+
69
+ def _fetch_served_spec(svc: dict) -> dict | None:
70
+ for path in SERVED_SPEC_PATHS:
71
+ try:
72
+ resp = httpx.get(f"{_base_url(svc)}{path}", timeout=5.0)
73
+ except httpx.HTTPError:
74
+ continue
75
+ if resp.status_code != 200:
76
+ continue
77
+ if path.endswith(".json"):
78
+ return resp.json()
79
+ return yaml.safe_load(resp.text)
80
+ return None
81
+
82
+
83
+ def _diff(design: dict, served: dict) -> tuple[list[str], list[str]]:
84
+ """Compare flattened surfaces. Returns (breaking, additive) drift lines."""
85
+ breaking: list[str] = []
86
+ additive: list[str] = []
87
+ for (path, method), designed_codes in design.items():
88
+ label = f"{method.upper()} {path}"
89
+ served_codes = served.get((path, method))
90
+ if served_codes is None:
91
+ breaking.append(f"{label} — designed but not served")
92
+ continue
93
+ missing = designed_codes - served_codes
94
+ if missing:
95
+ breaking.append(
96
+ f"{label} — designed response codes not served: {sorted(missing)}"
97
+ )
98
+ extra = served_codes - designed_codes
99
+ if extra:
100
+ additive.append(f"{label} — served response codes not in design: {sorted(extra)}")
101
+ for path, method in sorted(served.keys() - design.keys()):
102
+ additive.append(f"{method.upper()} {path} — served but not in design spec")
103
+ return breaking, additive
104
+
105
+
106
+ @pytest.mark.parametrize("svc", _PARAMS)
107
+ def test_served_api_conforms_to_design_spec(cluster, svc):
108
+ """The running service implements at least the surface its promoted spec declares."""
109
+ design_doc = _load_design_spec(svc["name"])
110
+ if design_doc is None:
111
+ pytest.skip(
112
+ f"no promoted design spec at docs/architecture/api/{svc['name']}/openapi.yaml — "
113
+ "promote one in bet validation to bring this service under contract test"
114
+ )
115
+ if svc["host_port"] is None:
116
+ pytest.skip(f"{svc['name']} has no published host port")
117
+
118
+ served_doc = _fetch_served_spec(svc)
119
+ if served_doc is None:
120
+ pytest.skip(f"{svc['name']} does not expose a served spec at {SERVED_SPEC_PATHS}")
121
+
122
+ design = _surface(design_doc)
123
+ if not design:
124
+ pytest.skip(f"design spec for {svc['name']} declares no paths — nothing to conform to")
125
+ served = _surface(served_doc)
126
+
127
+ breaking, additive = _diff(design, served)
128
+
129
+ if additive:
130
+ warnings.warn(
131
+ f"ADDITIVE drift for {svc['name']} — the served API exceeds "
132
+ f"docs/architecture/api/{svc['name']}/openapi.yaml; re-promote the spec:\n "
133
+ + "\n ".join(additive)
134
+ )
135
+
136
+ assert not breaking, (
137
+ f"BREAKING drift for {svc['name']} — the design spec at "
138
+ f"docs/architecture/api/{svc['name']}/openapi.yaml promises surface the running "
139
+ "service does not deliver:\n " + "\n ".join(breaking)
140
+ )
@@ -0,0 +1,109 @@
1
+ <% if (!surfaces) { -%>
2
+ """Layout geometry gate — Tier 1 of the visual verification loop.
3
+
4
+ A deliberately small handful of deterministic layout invariants that responsive
5
+ breakage violates — kept narrow to avoid heuristic flakiness. Today it asserts the
6
+ highest-signal one: no horizontal overflow at the mobile breakpoint, the defect that
7
+ ships a sideways-scrolling phone layout unseen. Grow the invariant set per project
8
+ (landmark-in-viewport, no-clipped-primary-content) only where it stays deterministic.
9
+
10
+ Skips cleanly when no frontend service is discovered (frontend_base_url skips).
11
+ """
12
+
13
+ import json
14
+ import pathlib
15
+
16
+ from playwright.sync_api import Page
17
+
18
+ MOBILE = (375, 812)
19
+ # Sub-pixel rounding can add a fraction; a small tolerance avoids false failures.
20
+ _OVERFLOW_TOLERANCE_PX = 2
21
+
22
+
23
+ def _load_routes() -> tuple[str, ...]:
24
+ manifest = pathlib.Path("tests/system/routes.json")
25
+ if manifest.exists():
26
+ try:
27
+ routes = json.loads(manifest.read_text())
28
+ if isinstance(routes, list) and routes:
29
+ return tuple(routes)
30
+ except Exception: # noqa: BLE001 — a malformed manifest falls back to root
31
+ pass
32
+ return ("/",)
33
+
34
+
35
+ ROUTES = _load_routes()
36
+
37
+
38
+ def _no_horizontal_overflow(page: Page, surface_slug: str, base_url: str | None) -> None:
39
+ page.set_viewport_size({"width": MOBILE[0], "height": MOBILE[1]})
40
+ for route in ROUTES:
41
+ target = (base_url.rstrip("/") + route) if base_url else route
42
+ page.goto(target, wait_until="load")
43
+ page.wait_for_load_state("networkidle")
44
+ widths = page.evaluate(
45
+ "() => ({ scroll: document.documentElement.scrollWidth,"
46
+ " client: document.documentElement.clientWidth })"
47
+ )
48
+ assert widths["scroll"] <= widths["client"] + _OVERFLOW_TOLERANCE_PX, (
49
+ f"{surface_slug} {route} overflows horizontally at {MOBILE[0]}px "
50
+ f"(scrollWidth {widths['scroll']} > clientWidth {widths['client']})"
51
+ )
52
+
53
+
54
+ def test_frontend_no_horizontal_overflow(cluster, frontend_base_url, page: Page):
55
+ _no_horizontal_overflow(page, "frontend", frontend_base_url)
56
+ <% } else { -%>
57
+ """Layout geometry gate, one test per graphical surface — Tier 1 of the visual loop.
58
+
59
+ A deliberately small handful of deterministic layout invariants that responsive
60
+ breakage violates — kept narrow to avoid heuristic flakiness. Today it asserts the
61
+ highest-signal one: no horizontal overflow at the mobile breakpoint, the defect that
62
+ ships a sideways-scrolling phone layout unseen. Grow the invariant set per project
63
+ only where it stays deterministic.
64
+
65
+ Skips cleanly when a surface is not reachable (its page fixture skips).
66
+ """
67
+
68
+ import json
69
+ import pathlib
70
+
71
+ from playwright.sync_api import Page
72
+
73
+ MOBILE = (375, 812)
74
+ _OVERFLOW_TOLERANCE_PX = 2
75
+
76
+
77
+ def _load_routes() -> tuple[str, ...]:
78
+ manifest = pathlib.Path("tests/system/routes.json")
79
+ if manifest.exists():
80
+ try:
81
+ routes = json.loads(manifest.read_text())
82
+ if isinstance(routes, list) and routes:
83
+ return tuple(routes)
84
+ except Exception: # noqa: BLE001 — a malformed manifest falls back to root
85
+ pass
86
+ return ("/",)
87
+
88
+
89
+ ROUTES = _load_routes()
90
+
91
+
92
+ def _no_horizontal_overflow(page: Page, surface_slug: str) -> None:
93
+ page.set_viewport_size({"width": MOBILE[0], "height": MOBILE[1]})
94
+ for route in ROUTES:
95
+ page.goto(route, wait_until="load")
96
+ page.wait_for_load_state("networkidle")
97
+ widths = page.evaluate(
98
+ "() => ({ scroll: document.documentElement.scrollWidth,"
99
+ " client: document.documentElement.clientWidth })"
100
+ )
101
+ assert widths["scroll"] <= widths["client"] + _OVERFLOW_TOLERANCE_PX, (
102
+ f"{surface_slug} {route} overflows horizontally at {MOBILE[0]}px "
103
+ f"(scrollWidth {widths['scroll']} > clientWidth {widths['client']})"
104
+ )
105
+ <% graphicalSurfaces.forEach((s) => { %>
106
+
107
+ def test_<%= s.ident %>_no_horizontal_overflow(cluster, <%= s.ident %>_page: Page):
108
+ _no_horizontal_overflow(<%= s.ident %>_page, "<%= s.slug %>")
109
+ <% }) %><% } -%>
@@ -0,0 +1,227 @@
1
+ <% if (!surfaces) { -%>
2
+ """Render-smoke gate for the graphical UI — Tier 1 of the visual verification loop.
3
+
4
+ A behavioural test asserting a selector exists passes while the page is a blank
5
+ screen, throwing a hydration error, unstyled because the CSS 404'd, or showing an
6
+ error-boundary fallback. This gate catches that class: it boots the app and
7
+ asserts the objective facts a broken page violates, across a viewport x theme
8
+ matrix, and writes a screenshot of each (route, viewport, theme) so the delivery
9
+ agent (Tier 2) and the fidelity critic (Tier 3) can read what actually rendered.
10
+
11
+ What this gate sees: render correctness, console/asset hygiene, blank-render, and
12
+ basic theme/viewport breakage. What it does NOT see: motion (easing, durations,
13
+ press physics) and perceived latency — those stay behaviour-tested, never asserted
14
+ from a static screenshot.
15
+
16
+ Skips cleanly when no frontend service is discovered (frontend_base_url skips).
17
+ """
18
+
19
+ import json
20
+ import pathlib
21
+
22
+
23
+ def _load_routes() -> tuple[str, ...]:
24
+ """Route inventory — the screens the route-driven gates sweep. A bet declares
25
+ the routes it touched in tests/system/routes.json (a JSON array of paths);
26
+ absent that file, the gate covers the app root."""
27
+ manifest = pathlib.Path("tests/system/routes.json")
28
+ if manifest.exists():
29
+ try:
30
+ routes = json.loads(manifest.read_text())
31
+ if isinstance(routes, list) and routes:
32
+ return tuple(routes)
33
+ except Exception: # noqa: BLE001 — a malformed manifest falls back to root
34
+ pass
35
+ return ("/",)
36
+
37
+ import pytest
38
+ from playwright.sync_api import Page
39
+
40
+ # The design system commits dual themes and responsive breakpoints; the matrix is
41
+ # the test projection of those commitments. Extend per project as the spec grows.
42
+ VIEWPORTS = {"mobile": (375, 812), "desktop": (1280, 800)}
43
+ THEMES = ("light", "dark")
44
+ # Route inventory: the bet's declared routes (tests/system/routes.json) or the root.
45
+ ROUTES = _load_routes()
46
+ # DOM node floor a non-blank page clears — catches the blank-screen and the
47
+ # dark-mode-invisible-text cases.
48
+ _MIN_DOM_NODES = 8
49
+ _VISUAL_DIR = pathlib.Path(".groundwork/cache/visual/_smoke")
50
+
51
+
52
+ def _render_smoke(page: Page, surface_slug: str, base_url: str | None) -> None:
53
+ console_errors: list[str] = []
54
+ failed_requests: list[str] = []
55
+ page.on(
56
+ "console",
57
+ lambda msg: console_errors.append(msg.text) if msg.type == "error" else None,
58
+ )
59
+ page.on("pageerror", lambda exc: console_errors.append(f"pageerror: {exc}"))
60
+ page.on(
61
+ "response",
62
+ lambda r: failed_requests.append(f"{r.status} {r.url}")
63
+ if r.status >= 400 and (base_url is None or r.url.startswith(base_url))
64
+ else None,
65
+ )
66
+
67
+ for vp_name, (w, h) in VIEWPORTS.items():
68
+ for theme in THEMES:
69
+ page.set_viewport_size({"width": w, "height": h})
70
+ page.emulate_media(color_scheme=theme)
71
+ for route in ROUTES:
72
+ console_errors.clear()
73
+ failed_requests.clear()
74
+ target = (base_url.rstrip("/") + route) if base_url else route
75
+ resp = page.goto(target, wait_until="load")
76
+ page.wait_for_load_state("networkidle")
77
+
78
+ ctx = f"{surface_slug} {route} [{vp_name}/{theme}]"
79
+
80
+ # 1. Navigation succeeded (never a 4xx/5xx document response).
81
+ assert resp is not None and resp.status < 400, (
82
+ f"{ctx}: navigation returned "
83
+ f"{resp.status if resp else 'no response'}"
84
+ )
85
+
86
+ # 2. No severe console output and no uncaught exceptions.
87
+ assert not console_errors, (
88
+ f"{ctx}: severe console output on load:\n "
89
+ + "\n ".join(console_errors)
90
+ )
91
+
92
+ # 3. No failed same-origin asset/API requests (the unstyled-CSS-404 case).
93
+ assert not failed_requests, (
94
+ f"{ctx}: failed same-origin requests:\n "
95
+ + "\n ".join(failed_requests)
96
+ )
97
+
98
+ # 4. No framework error overlay or app error-boundary fallback.
99
+ overlay = page.locator(
100
+ "nextjs-portal, [data-nextjs-dialog], [data-testid='error-boundary']"
101
+ )
102
+ assert overlay.count() == 0, f"{ctx}: an error overlay/boundary is present"
103
+
104
+ # 5. The page rendered meaningful content (blank-screen case).
105
+ metrics = page.evaluate(
106
+ "() => ({ nodes: document.querySelectorAll('*').length,"
107
+ " text: (document.body.innerText || '').trim().length })"
108
+ )
109
+ assert metrics["nodes"] >= _MIN_DOM_NODES and metrics["text"] > 0, (
110
+ f"{ctx}: page rendered blank "
111
+ f"({metrics['nodes']} nodes, {metrics['text']} chars of text)"
112
+ )
113
+
114
+ # On pass, persist the screenshot for Tiers 2-3 to read.
115
+ out = _VISUAL_DIR / surface_slug
116
+ out.mkdir(parents=True, exist_ok=True)
117
+ slug = route.strip("/").replace("/", "_") or "root"
118
+ page.screenshot(path=str(out / f"{slug}__{vp_name}__{theme}.png"))
119
+
120
+
121
+ def test_frontend_root_render_smoke(cluster, frontend_base_url, page: Page):
122
+ _render_smoke(page, "frontend", frontend_base_url)
123
+ <% } else { -%>
124
+ """Render-smoke gate, one test per graphical surface — Tier 1 of the visual loop.
125
+
126
+ A behavioural test asserting a selector exists passes while the page is a blank
127
+ screen, throwing a hydration error, unstyled because the CSS 404'd, or showing an
128
+ error-boundary fallback. This gate catches that class: it boots each surface and
129
+ asserts the objective facts a broken page violates, across a viewport x theme
130
+ matrix, and writes a screenshot of each (route, viewport, theme) so the delivery
131
+ agent (Tier 2) and the fidelity critic (Tier 3) can read what actually rendered.
132
+
133
+ What this gate sees: render correctness, console/asset hygiene, blank-render, and
134
+ basic theme/viewport breakage. What it does NOT see: motion (easing, durations,
135
+ press physics) and perceived latency — those stay behaviour-tested, never asserted
136
+ from a static screenshot.
137
+
138
+ Skips cleanly when a surface is not reachable (its page fixture skips).
139
+ """
140
+
141
+ import json
142
+ import pathlib
143
+
144
+
145
+ def _load_routes() -> tuple[str, ...]:
146
+ """Route inventory — the screens the route-driven gates sweep. A bet declares
147
+ the routes it touched in tests/system/routes.json (a JSON array of paths);
148
+ absent that file, the gate covers the app root."""
149
+ manifest = pathlib.Path("tests/system/routes.json")
150
+ if manifest.exists():
151
+ try:
152
+ routes = json.loads(manifest.read_text())
153
+ if isinstance(routes, list) and routes:
154
+ return tuple(routes)
155
+ except Exception: # noqa: BLE001 — a malformed manifest falls back to root
156
+ pass
157
+ return ("/",)
158
+
159
+ from playwright.sync_api import Page
160
+
161
+ VIEWPORTS = {"mobile": (375, 812), "desktop": (1280, 800)}
162
+ THEMES = ("light", "dark")
163
+ ROUTES = _load_routes()
164
+ _MIN_DOM_NODES = 8
165
+ _VISUAL_DIR = pathlib.Path(".groundwork/cache/visual/_smoke")
166
+
167
+
168
+ def _render_smoke(page: Page, surface_slug: str) -> None:
169
+ console_errors: list[str] = []
170
+ failed_requests: list[str] = []
171
+ page.on(
172
+ "console",
173
+ lambda msg: console_errors.append(msg.text) if msg.type == "error" else None,
174
+ )
175
+ page.on("pageerror", lambda exc: console_errors.append(f"pageerror: {exc}"))
176
+ page.on(
177
+ "response",
178
+ lambda r: failed_requests.append(f"{r.status} {r.url}")
179
+ if r.status >= 400
180
+ else None,
181
+ )
182
+
183
+ for vp_name, (w, h) in VIEWPORTS.items():
184
+ for theme in THEMES:
185
+ page.set_viewport_size({"width": w, "height": h})
186
+ page.emulate_media(color_scheme=theme)
187
+ for route in ROUTES:
188
+ console_errors.clear()
189
+ failed_requests.clear()
190
+ resp = page.goto(route, wait_until="load")
191
+ page.wait_for_load_state("networkidle")
192
+
193
+ ctx = f"{surface_slug} {route} [{vp_name}/{theme}]"
194
+
195
+ assert resp is not None and resp.status < 400, (
196
+ f"{ctx}: navigation returned "
197
+ f"{resp.status if resp else 'no response'}"
198
+ )
199
+ assert not console_errors, (
200
+ f"{ctx}: severe console output on load:\n "
201
+ + "\n ".join(console_errors)
202
+ )
203
+ assert not failed_requests, (
204
+ f"{ctx}: failed requests:\n " + "\n ".join(failed_requests)
205
+ )
206
+ overlay = page.locator(
207
+ "nextjs-portal, [data-nextjs-dialog], [data-testid='error-boundary']"
208
+ )
209
+ assert overlay.count() == 0, f"{ctx}: an error overlay/boundary is present"
210
+ metrics = page.evaluate(
211
+ "() => ({ nodes: document.querySelectorAll('*').length,"
212
+ " text: (document.body.innerText || '').trim().length })"
213
+ )
214
+ assert metrics["nodes"] >= _MIN_DOM_NODES and metrics["text"] > 0, (
215
+ f"{ctx}: page rendered blank "
216
+ f"({metrics['nodes']} nodes, {metrics['text']} chars of text)"
217
+ )
218
+
219
+ out = _VISUAL_DIR / surface_slug
220
+ out.mkdir(parents=True, exist_ok=True)
221
+ slug = route.strip("/").replace("/", "_") or "root"
222
+ page.screenshot(path=str(out / f"{slug}__{vp_name}__{theme}.png"))
223
+ <% graphicalSurfaces.forEach((s) => { %>
224
+
225
+ def test_<%= s.ident %>_render_smoke(cluster, <%= s.ident %>_page: Page):
226
+ _render_smoke(<%= s.ident %>_page, "<%= s.slug %>")
227
+ <% }) %><% } -%>