@polymorphism-tech/morph-spec 3.0.1 → 3.2.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 (316) hide show
  1. package/CLAUDE.md +561 -63
  2. package/LICENSE +72 -72
  3. package/README.md +275 -79
  4. package/bin/detect-agents.js +3 -1
  5. package/bin/morph-spec.js +60 -1
  6. package/bin/render-template.js +61 -14
  7. package/bin/semantic-detect-agents.js +2 -1
  8. package/bin/{task-manager.js → task-manager.cjs} +113 -8
  9. package/bin/validate-agents-skills.js +10 -4
  10. package/bin/validate-agents.js +4 -3
  11. package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +977 -977
  12. package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1048 -1048
  13. package/docs/api/scripts/collapse.js +38 -38
  14. package/docs/api/scripts/commonNav.js +28 -28
  15. package/docs/api/scripts/linenumber.js +25 -25
  16. package/docs/api/scripts/nav.js +12 -12
  17. package/docs/api/scripts/polyfill.js +3 -3
  18. package/docs/api/scripts/prettify/Apache-License-2.0.txt +202 -202
  19. package/docs/api/scripts/prettify/lang-css.js +2 -2
  20. package/docs/api/scripts/prettify/prettify.js +28 -28
  21. package/docs/api/scripts/search.js +98 -98
  22. package/docs/api/styles/jsdoc.css +776 -776
  23. package/docs/api/styles/prettify.css +80 -80
  24. package/docs/cli-auto-detection.md +219 -0
  25. package/docs/examples.md +328 -328
  26. package/docs/getting-started.md +3 -3
  27. package/docs/llm-interaction-config.md +735 -0
  28. package/docs/templates.md +418 -418
  29. package/docs/troubleshooting.md +269 -0
  30. package/package.json +7 -3
  31. package/scripts/postinstall.js +132 -132
  32. package/scripts/reorganize-skills.cjs +1 -1
  33. package/scripts/validate-agents-structure.cjs +1 -1
  34. package/scripts/validate-skills.cjs +2 -2
  35. package/src/commands/advance-phase.js +93 -2
  36. package/src/commands/analyze-blazor-concurrency.js +193 -193
  37. package/src/commands/approve.js +221 -0
  38. package/src/commands/capture-pattern.js +121 -0
  39. package/src/commands/create-story.js +5 -2
  40. package/src/commands/deploy.js +780 -780
  41. package/src/commands/detect-agents.js +4 -2
  42. package/src/commands/generate.js +276 -149
  43. package/src/commands/init.js +37 -0
  44. package/src/commands/lint-fluent.js +352 -352
  45. package/src/commands/migrate-state.js +158 -0
  46. package/src/commands/rollback-phase.js +185 -185
  47. package/src/commands/search-patterns.js +126 -0
  48. package/src/commands/session-summary.js +291 -291
  49. package/src/commands/shard-spec.js +224 -224
  50. package/src/commands/spawn-team.js +172 -0
  51. package/src/commands/sprint-status.js +250 -250
  52. package/src/commands/task.js +3 -3
  53. package/src/commands/troubleshoot.js +222 -222
  54. package/src/commands/update.js +36 -0
  55. package/src/commands/upgrade.js +346 -0
  56. package/src/commands/validate-blazor-state.js +210 -210
  57. package/src/commands/validate-blazor.js +156 -156
  58. package/src/commands/validate-css.js +84 -84
  59. package/src/commands/validate-phase.js +221 -221
  60. package/src/generator/.gitkeep +0 -0
  61. package/src/generator/config-generator.js +206 -0
  62. package/src/generator/templates/config.json.template +40 -0
  63. package/src/generator/templates/project.md.template +67 -0
  64. package/src/lib/blazor-concurrency-analyzer.js +288 -288
  65. package/src/lib/blazor-state-validator.js +291 -291
  66. package/src/lib/blazor-validator.js +374 -374
  67. package/src/lib/checkpoint-hooks.js +258 -0
  68. package/src/lib/context-generator.js +7 -4
  69. package/src/lib/css-validator.js +352 -352
  70. package/src/lib/design-system-generator.js +298 -298
  71. package/src/lib/hook-executor.js +2 -1
  72. package/src/lib/learning-system.js +520 -520
  73. package/src/lib/metadata-extractor.js +380 -0
  74. package/src/lib/mockup-generator.js +366 -366
  75. package/src/lib/phase-state-machine.js +214 -0
  76. package/src/lib/stack-resolver.js +148 -0
  77. package/src/lib/standards-context-injector.js +4 -3
  78. package/src/lib/state-manager.js +120 -0
  79. package/src/lib/team-orchestrator.js +2 -1
  80. package/src/lib/template-data-sources.js +325 -0
  81. package/src/lib/troubleshoot-grep.js +204 -194
  82. package/src/lib/troubleshoot-index.js +144 -144
  83. package/src/lib/ui-detector.js +350 -350
  84. package/src/lib/validation-runner.js +2 -1
  85. package/src/lib/validators/architecture-validator.js +387 -387
  86. package/src/lib/validators/content-validator.js +351 -0
  87. package/src/lib/validators/package-validator.js +360 -360
  88. package/src/lib/validators/ui-contrast-validator.js +422 -422
  89. package/src/llm/.gitkeep +0 -0
  90. package/src/llm/analyzer.js +215 -0
  91. package/src/llm/environment-detector.js +43 -0
  92. package/src/llm/few-shot-examples.js +216 -0
  93. package/src/llm/project-config-schema.json +188 -0
  94. package/src/llm/prompt-builder.js +96 -0
  95. package/src/llm/schema-validator.js +121 -0
  96. package/src/orchestrator.js +206 -0
  97. package/src/sanitizer/.gitkeep +0 -0
  98. package/src/sanitizer/context-sanitizer.js +221 -0
  99. package/src/sanitizer/patterns.js +163 -0
  100. package/src/scanner/.gitkeep +0 -0
  101. package/src/scanner/project-scanner.js +242 -0
  102. package/src/types/index.js +477 -0
  103. package/src/ui/.gitkeep +0 -0
  104. package/src/ui/diff-display.js +91 -0
  105. package/src/ui/interactive-wizard.js +96 -0
  106. package/src/ui/user-review.js +211 -0
  107. package/src/ui/wizard-questions.js +190 -0
  108. package/src/utils/file-copier.js +3 -1
  109. package/src/utils/logger.js +32 -32
  110. package/src/utils/version-checker.js +175 -175
  111. package/src/writer/.gitkeep +0 -0
  112. package/src/writer/file-writer.js +86 -0
  113. package/{content → stacks/blazor-azure}/.azure/README.md +2 -2
  114. package/{content → stacks/blazor-azure}/.azure/pipelines/pipeline-variables.yml +1 -1
  115. package/{content → stacks/blazor-azure}/.azure/pipelines/prod-pipeline.yml +1 -1
  116. package/{content → stacks/blazor-azure}/.azure/pipelines/staging-pipeline.yml +1 -1
  117. package/{content → stacks/blazor-azure}/.claude/commands/morph-preflight.md +227 -227
  118. package/{content → stacks/blazor-azure}/.claude/commands/morph-troubleshoot.md +122 -122
  119. package/{content → stacks/blazor-azure}/.claude/skills/level-1-workflows/phase-setup.md +1 -1
  120. package/{content → stacks/blazor-azure}/.morph/docs/workflows/enforcement-pipeline.md +3 -3
  121. package/{content → stacks/blazor-azure}/.morph/hooks/README.md +12 -12
  122. package/{content → stacks/blazor-azure}/.morph/standards/agent-teams-workflow.md +2 -2
  123. package/{content → stacks/blazor-azure}/.morph/standards/migration-guide.md +2 -2
  124. package/{content → stacks/blazor-azure}/.morph/templates/infra/deploy-checklist.md +426 -426
  125. package/stacks/nextjs-supabase/.claude/skills/level-2-domains/backend/dotnet-supabase.md +244 -0
  126. package/stacks/nextjs-supabase/.claude/skills/level-2-domains/frontend/nextjs-supabase.md +335 -0
  127. package/stacks/nextjs-supabase/.claude/skills/level-2-domains/infrastructure/easypanel-deployer.md +189 -0
  128. package/stacks/nextjs-supabase/.claude/skills/level-2-domains/integrations/supabase-expert.md +170 -0
  129. package/stacks/nextjs-supabase/.morph/config/agents.json +345 -0
  130. package/stacks/nextjs-supabase/.morph/config/config.template.json +92 -0
  131. package/stacks/nextjs-supabase/.morph/docs/easypanel-setup.md +169 -0
  132. package/stacks/nextjs-supabase/.morph/docs/supabase-mcp-setup.md +247 -0
  133. package/stacks/nextjs-supabase/.morph/examples/crud-nextjs-supabase/README.md +697 -0
  134. package/stacks/nextjs-supabase/.morph/examples/crud-nextjs-supabase/spec.md +85 -0
  135. package/stacks/nextjs-supabase/.morph/examples/crud-nextjs-supabase/tasks.md +86 -0
  136. package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/README.md +498 -0
  137. package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/decisions.md +121 -0
  138. package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/spec.md +138 -0
  139. package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/tasks.md +162 -0
  140. package/stacks/nextjs-supabase/.morph/project.md +168 -0
  141. package/stacks/nextjs-supabase/.morph/standards/easypanel-deploy.md +191 -0
  142. package/stacks/nextjs-supabase/.morph/standards/nextjs-patterns.md +193 -0
  143. package/stacks/nextjs-supabase/.morph/standards/supabase-auth.md +171 -0
  144. package/stacks/nextjs-supabase/.morph/standards/supabase-pgvector.md +164 -0
  145. package/stacks/nextjs-supabase/.morph/standards/supabase-rls.md +179 -0
  146. package/stacks/nextjs-supabase/.morph/standards/supabase-storage.md +148 -0
  147. package/stacks/nextjs-supabase/.morph/templates/contracts.cs +173 -0
  148. package/stacks/nextjs-supabase/.morph/templates/contracts.ts +168 -0
  149. package/stacks/nextjs-supabase/.morph/templates/decisions.md +115 -0
  150. package/stacks/nextjs-supabase/.morph/templates/dockerfile-api.dockerfile +38 -0
  151. package/stacks/nextjs-supabase/.morph/templates/dockerfile-web.dockerfile +48 -0
  152. package/stacks/nextjs-supabase/.morph/templates/proposal.md +145 -0
  153. package/stacks/nextjs-supabase/.morph/templates/recap.md +134 -0
  154. package/stacks/nextjs-supabase/.morph/templates/rls-policy.sql +57 -0
  155. package/stacks/nextjs-supabase/.morph/templates/spec.md +231 -0
  156. package/stacks/nextjs-supabase/.morph/templates/supabase-migration.sql +100 -0
  157. package/stacks/nextjs-supabase/.morph/templates/tasks.md +257 -0
  158. package/stacks/nextjs-supabase/CLAUDE.md +149 -0
  159. package/stacks/nextjs-supabase/README.md +112 -0
  160. /package/{content → stacks/blazor-azure}/.azure/docs/azure-devops-setup.md +0 -0
  161. /package/{content → stacks/blazor-azure}/.azure/docs/branch-strategy.md +0 -0
  162. /package/{content → stacks/blazor-azure}/.azure/docs/local-development.md +0 -0
  163. /package/{content → stacks/blazor-azure}/.azure/pipelines/templates/build-dotnet.yml +0 -0
  164. /package/{content → stacks/blazor-azure}/.azure/pipelines/templates/deploy-app-service.yml +0 -0
  165. /package/{content → stacks/blazor-azure}/.azure/pipelines/templates/deploy-container-app.yml +0 -0
  166. /package/{content → stacks/blazor-azure}/.azure/pipelines/templates/infra-deploy.yml +0 -0
  167. /package/{content → stacks/blazor-azure}/.claude/commands/morph-apply.md +0 -0
  168. /package/{content → stacks/blazor-azure}/.claude/commands/morph-archive.md +0 -0
  169. /package/{content → stacks/blazor-azure}/.claude/commands/morph-deploy.md +0 -0
  170. /package/{content → stacks/blazor-azure}/.claude/commands/morph-infra.md +0 -0
  171. /package/{content → stacks/blazor-azure}/.claude/commands/morph-proposal.md +0 -0
  172. /package/{content → stacks/blazor-azure}/.claude/commands/morph-status.md +0 -0
  173. /package/{content → stacks/blazor-azure}/.claude/settings.local.json +0 -0
  174. /package/{content → stacks/blazor-azure}/.claude/skills/level-0-meta/README.md +0 -0
  175. /package/{content → stacks/blazor-azure}/.claude/skills/level-0-meta/code-review.md +0 -0
  176. /package/{content → stacks/blazor-azure}/.claude/skills/level-0-meta/morph-checklist.md +0 -0
  177. /package/{content → stacks/blazor-azure}/.claude/skills/level-0-meta/simulation-checklist.md +0 -0
  178. /package/{content → stacks/blazor-azure}/.claude/skills/level-1-workflows/README.md +0 -0
  179. /package/{content → stacks/blazor-azure}/.claude/skills/level-1-workflows/morph-replicate.md +0 -0
  180. /package/{content → stacks/blazor-azure}/.claude/skills/level-1-workflows/phase-clarify.md +0 -0
  181. /package/{content → stacks/blazor-azure}/.claude/skills/level-1-workflows/phase-design.md +0 -0
  182. /package/{content → stacks/blazor-azure}/.claude/skills/level-1-workflows/phase-tasks.md +0 -0
  183. /package/{content → stacks/blazor-azure}/.claude/skills/level-1-workflows/phase-uiux.md +0 -0
  184. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/README.md +0 -0
  185. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/ai-agents/ai-system-architect.md +0 -0
  186. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/architecture/po-pm-advisor.md +0 -0
  187. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/architecture/prompt-engineer.md +0 -0
  188. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/architecture/seo-growth-hacker.md +0 -0
  189. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/architecture/standards-architect.md +0 -0
  190. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/backend/dotnet-senior.md +0 -0
  191. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/backend/ef-modeler.md +0 -0
  192. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/backend/hangfire-orchestrator.md +0 -0
  193. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/backend/ms-agent-expert.md +0 -0
  194. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/frontend/blazor-builder.md +0 -0
  195. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/frontend/nextjs-expert.md +0 -0
  196. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/frontend/ui-ux-designer.md +0 -0
  197. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/infrastructure/azure-architect.md +0 -0
  198. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/infrastructure/azure-deploy-specialist.md +0 -0
  199. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/infrastructure/bicep-architect.md +0 -0
  200. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/infrastructure/container-specialist.md +0 -0
  201. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/infrastructure/devops-engineer.md +0 -0
  202. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/integrations/asaas-financial.md +0 -0
  203. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/integrations/azure-identity.md +0 -0
  204. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/integrations/clerk-auth.md +0 -0
  205. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/integrations/resend-email.md +0 -0
  206. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/quality/code-analyzer.md +0 -0
  207. /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/quality/testing-specialist.md +0 -0
  208. /package/{content → stacks/blazor-azure}/.claude/skills/level-3-technologies/README.md +0 -0
  209. /package/{content → stacks/blazor-azure}/.claude/skills/level-4-patterns/README.md +0 -0
  210. /package/{content → stacks/blazor-azure}/.morph/.morphversion +0 -0
  211. /package/{content → stacks/blazor-azure}/.morph/archive/.gitkeep +0 -0
  212. /package/{content → stacks/blazor-azure}/.morph/config/agents.json +0 -0
  213. /package/{content → stacks/blazor-azure}/.morph/config/config.template.json +0 -0
  214. /package/{content → stacks/blazor-azure}/.morph/docs/STORY-DRIVEN-DEVELOPMENT.md +0 -0
  215. /package/{content → stacks/blazor-azure}/.morph/docs/workflows/design-impl.md +0 -0
  216. /package/{content → stacks/blazor-azure}/.morph/docs/workflows/fast-track.md +0 -0
  217. /package/{content → stacks/blazor-azure}/.morph/docs/workflows/full-morph.md +0 -0
  218. /package/{content → stacks/blazor-azure}/.morph/docs/workflows/standard.md +0 -0
  219. /package/{content → stacks/blazor-azure}/.morph/docs/workflows/ui-refresh.md +0 -0
  220. /package/{content → stacks/blazor-azure}/.morph/examples/api-nextjs/README.md +0 -0
  221. /package/{content → stacks/blazor-azure}/.morph/examples/api-nextjs/contracts.ts +0 -0
  222. /package/{content → stacks/blazor-azure}/.morph/examples/api-nextjs/spec.md +0 -0
  223. /package/{content → stacks/blazor-azure}/.morph/examples/api-nextjs/tasks.md +0 -0
  224. /package/{content → stacks/blazor-azure}/.morph/examples/micro-saas/README.md +0 -0
  225. /package/{content → stacks/blazor-azure}/.morph/examples/micro-saas/contracts.cs +0 -0
  226. /package/{content → stacks/blazor-azure}/.morph/examples/micro-saas/decisions.md +0 -0
  227. /package/{content → stacks/blazor-azure}/.morph/examples/micro-saas/spec.md +0 -0
  228. /package/{content → stacks/blazor-azure}/.morph/examples/micro-saas/tasks.md +0 -0
  229. /package/{content → stacks/blazor-azure}/.morph/examples/multi-agent/README.md +0 -0
  230. /package/{content → stacks/blazor-azure}/.morph/examples/multi-agent/contracts.cs +0 -0
  231. /package/{content → stacks/blazor-azure}/.morph/examples/multi-agent/spec.md +0 -0
  232. /package/{content → stacks/blazor-azure}/.morph/examples/multi-agent/tasks.md +0 -0
  233. /package/{content → stacks/blazor-azure}/.morph/examples/scheduled-reports/decisions.md +0 -0
  234. /package/{content → stacks/blazor-azure}/.morph/examples/scheduled-reports/proposal.md +0 -0
  235. /package/{content → stacks/blazor-azure}/.morph/examples/scheduled-reports/spec.md +0 -0
  236. /package/{content → stacks/blazor-azure}/.morph/examples/state-v3.json +0 -0
  237. /package/{content → stacks/blazor-azure}/.morph/features/.gitkeep +0 -0
  238. /package/{content → stacks/blazor-azure}/.morph/hooks/pre-commit-agents.sh +0 -0
  239. /package/{content → stacks/blazor-azure}/.morph/hooks/pre-commit-all.sh +0 -0
  240. /package/{content → stacks/blazor-azure}/.morph/hooks/pre-commit-specs.sh +0 -0
  241. /package/{content → stacks/blazor-azure}/.morph/hooks/pre-commit-tests.sh +0 -0
  242. /package/{content → stacks/blazor-azure}/.morph/hooks/task-completed.js +0 -0
  243. /package/{content → stacks/blazor-azure}/.morph/hooks/teammate-idle.js +0 -0
  244. /package/{content → stacks/blazor-azure}/.morph/project.md +0 -0
  245. /package/{content → stacks/blazor-azure}/.morph/schemas/agent.schema.json +0 -0
  246. /package/{content → stacks/blazor-azure}/.morph/schemas/tasks.schema.json +0 -0
  247. /package/{content → stacks/blazor-azure}/.morph/specs/.gitkeep +0 -0
  248. /package/{content → stacks/blazor-azure}/.morph/standards/agent-framework-blazor-ui.md +0 -0
  249. /package/{content → stacks/blazor-azure}/.morph/standards/agent-framework-production.md +0 -0
  250. /package/{content → stacks/blazor-azure}/.morph/standards/agent-framework-setup.md +0 -0
  251. /package/{content → stacks/blazor-azure}/.morph/standards/agent-framework-workflows.md +0 -0
  252. /package/{content → stacks/blazor-azure}/.morph/standards/architecture.md +0 -0
  253. /package/{content → stacks/blazor-azure}/.morph/standards/azure.md +0 -0
  254. /package/{content → stacks/blazor-azure}/.morph/standards/coding.md +0 -0
  255. /package/{content → stacks/blazor-azure}/.morph/standards/dotnet10-migration.md +0 -0
  256. /package/{content → stacks/blazor-azure}/.morph/standards/fluent-ui-setup.md +0 -0
  257. /package/{content → stacks/blazor-azure}/.morph/standards/passkeys-auth.md +0 -0
  258. /package/{content → stacks/blazor-azure}/.morph/standards/vector-search-rag.md +0 -0
  259. /package/{content → stacks/blazor-azure}/.morph/state.json +0 -0
  260. /package/{content → stacks/blazor-azure}/.morph/templates/CONTEXT-FEATURE.md +0 -0
  261. /package/{content → stacks/blazor-azure}/.morph/templates/CONTEXT.md +0 -0
  262. /package/{content → stacks/blazor-azure}/.morph/templates/FluentDesignTheme.cs +0 -0
  263. /package/{content → stacks/blazor-azure}/.morph/templates/MudTheme.cs +0 -0
  264. /package/{content → stacks/blazor-azure}/.morph/templates/agent.cs +0 -0
  265. /package/{content → stacks/blazor-azure}/.morph/templates/clarify-questions.md +0 -0
  266. /package/{content → stacks/blazor-azure}/.morph/templates/component.razor +0 -0
  267. /package/{content → stacks/blazor-azure}/.morph/templates/contracts/Commands.cs +0 -0
  268. /package/{content → stacks/blazor-azure}/.morph/templates/contracts/Entities.cs +0 -0
  269. /package/{content → stacks/blazor-azure}/.morph/templates/contracts/Queries.cs +0 -0
  270. /package/{content → stacks/blazor-azure}/.morph/templates/contracts/README.md +0 -0
  271. /package/{content → stacks/blazor-azure}/.morph/templates/contracts.cs +0 -0
  272. /package/{content → stacks/blazor-azure}/.morph/templates/decisions.md +0 -0
  273. /package/{content → stacks/blazor-azure}/.morph/templates/design-system.css +0 -0
  274. /package/{content → stacks/blazor-azure}/.morph/templates/infra/.dockerignore.example +0 -0
  275. /package/{content → stacks/blazor-azure}/.morph/templates/infra/Dockerfile.example +0 -0
  276. /package/{content → stacks/blazor-azure}/.morph/templates/infra/README.md +0 -0
  277. /package/{content → stacks/blazor-azure}/.morph/templates/infra/app-insights.bicep +0 -0
  278. /package/{content → stacks/blazor-azure}/.morph/templates/infra/app-service.bicep +0 -0
  279. /package/{content → stacks/blazor-azure}/.morph/templates/infra/azure-pipelines-deploy.yml +0 -0
  280. /package/{content → stacks/blazor-azure}/.morph/templates/infra/container-app-env.bicep +0 -0
  281. /package/{content → stacks/blazor-azure}/.morph/templates/infra/container-app.bicep +0 -0
  282. /package/{content → stacks/blazor-azure}/.morph/templates/infra/deploy.ps1 +0 -0
  283. /package/{content → stacks/blazor-azure}/.morph/templates/infra/deploy.sh +0 -0
  284. /package/{content → stacks/blazor-azure}/.morph/templates/infra/key-vault.bicep +0 -0
  285. /package/{content → stacks/blazor-azure}/.morph/templates/infra/main.bicep +0 -0
  286. /package/{content → stacks/blazor-azure}/.morph/templates/infra/parameters.dev.json +0 -0
  287. /package/{content → stacks/blazor-azure}/.morph/templates/infra/parameters.prod.json +0 -0
  288. /package/{content → stacks/blazor-azure}/.morph/templates/infra/parameters.staging.json +0 -0
  289. /package/{content → stacks/blazor-azure}/.morph/templates/infra/sql-database.bicep +0 -0
  290. /package/{content → stacks/blazor-azure}/.morph/templates/infra/storage.bicep +0 -0
  291. /package/{content → stacks/blazor-azure}/.morph/templates/integrations/asaas-client.cs +0 -0
  292. /package/{content → stacks/blazor-azure}/.morph/templates/integrations/asaas-webhook.cs +0 -0
  293. /package/{content → stacks/blazor-azure}/.morph/templates/integrations/azure-identity-config.cs +0 -0
  294. /package/{content → stacks/blazor-azure}/.morph/templates/integrations/clerk-config.cs +0 -0
  295. /package/{content → stacks/blazor-azure}/.morph/templates/job.cs +0 -0
  296. /package/{content → stacks/blazor-azure}/.morph/templates/migration.cs +0 -0
  297. /package/{content → stacks/blazor-azure}/.morph/templates/proposal.md +0 -0
  298. /package/{content → stacks/blazor-azure}/.morph/templates/recap.md +0 -0
  299. /package/{content → stacks/blazor-azure}/.morph/templates/repository.cs +0 -0
  300. /package/{content → stacks/blazor-azure}/.morph/templates/saas/subscription.cs +0 -0
  301. /package/{content → stacks/blazor-azure}/.morph/templates/saas/tenant.cs +0 -0
  302. /package/{content → stacks/blazor-azure}/.morph/templates/service.cs +0 -0
  303. /package/{content → stacks/blazor-azure}/.morph/templates/simulation.md +0 -0
  304. /package/{content → stacks/blazor-azure}/.morph/templates/spec.md +0 -0
  305. /package/{content → stacks/blazor-azure}/.morph/templates/sprint-status.yaml +0 -0
  306. /package/{content → stacks/blazor-azure}/.morph/templates/state.template.json +0 -0
  307. /package/{content → stacks/blazor-azure}/.morph/templates/story.md +0 -0
  308. /package/{content → stacks/blazor-azure}/.morph/templates/tasks.md +0 -0
  309. /package/{content → stacks/blazor-azure}/.morph/templates/test.cs +0 -0
  310. /package/{content → stacks/blazor-azure}/.morph/templates/ui-components.md +0 -0
  311. /package/{content → stacks/blazor-azure}/.morph/templates/ui-design-system.md +0 -0
  312. /package/{content → stacks/blazor-azure}/.morph/templates/ui-flows.md +0 -0
  313. /package/{content → stacks/blazor-azure}/.morph/templates/ui-mockups.md +0 -0
  314. /package/{content → stacks/blazor-azure}/.morph/test-infra/example.bicep +0 -0
  315. /package/{content → stacks/blazor-azure}/CLAUDE.md +0 -0
  316. /package/{content → stacks/blazor-azure}/README.md +0 -0
@@ -1,221 +1,221 @@
1
- /**
2
- * MORPH-SPEC Phase Validator Command
3
- *
4
- * Validates that required previous phases have been completed before advancing.
5
- * Prevents skipping phases accidentally.
6
- *
7
- * Usage:
8
- * morph-spec validate-phase <feature-name> <target-phase>
9
- *
10
- * Example:
11
- * morph-spec validate-phase scheduled-reports implement
12
- */
13
-
14
- import fs from 'fs';
15
- import path from 'path';
16
- import chalk from 'chalk';
17
- import { loadState, getFeature } from '../lib/state-manager.js';
18
-
19
- // Phase definitions with requirements
20
- const PHASES = {
21
- 'proposal': {
22
- order: 0,
23
- name: 'FASE 0: PROPOSAL',
24
- requiredOutputs: [],
25
- description: 'Initial proposal and agent detection'
26
- },
27
- 'setup': {
28
- order: 1,
29
- name: 'FASE 1: SETUP',
30
- requiredOutputs: ['proposal.md'],
31
- description: 'Load context and standards'
32
- },
33
- 'uiux': {
34
- order: 2,
35
- name: 'FASE 1.5: UI/UX DESIGN',
36
- requiredOutputs: ['proposal.md'],
37
- optionalOutputs: ['ui-design-system.md', 'ui-mockups.md', 'ui-components.md', 'ui-flows.md'],
38
- description: 'UI/UX design (conditional - only if frontend)',
39
- optional: true
40
- },
41
- 'design': {
42
- order: 3,
43
- name: 'FASE 2: DESIGN',
44
- requiredOutputs: ['proposal.md'],
45
- description: 'Technical specification and contracts'
46
- },
47
- 'clarify': {
48
- order: 4,
49
- name: 'FASE 3: CLARIFY',
50
- requiredOutputs: ['proposal.md', 'spec.md'],
51
- description: 'Clarify ambiguities and edge cases'
52
- },
53
- 'tasks': {
54
- order: 5,
55
- name: 'FASE 4: TASKS',
56
- requiredOutputs: ['proposal.md', 'spec.md'],
57
- description: 'Break down into executable tasks'
58
- },
59
- 'implement': {
60
- order: 6,
61
- name: 'FASE 5: IMPLEMENT',
62
- requiredOutputs: ['proposal.md', 'spec.md'],
63
- description: 'Execute tasks and implement code'
64
- },
65
- 'sync': {
66
- order: 7,
67
- name: 'FASE 6: SYNC',
68
- requiredOutputs: ['proposal.md', 'spec.md', 'decisions.md'],
69
- description: 'Sync decisions to project standards',
70
- optional: true
71
- }
72
- };
73
-
74
- /**
75
- * Check if output file exists
76
- */
77
- function checkOutput(featurePath, outputFile) {
78
- const filePath = path.join(featurePath, outputFile);
79
- return fs.existsSync(filePath);
80
- }
81
-
82
- /**
83
- * Validate phase requirements
84
- */
85
- function validatePhase(featureName, targetPhase) {
86
- const featurePath = path.join(process.cwd(), '.morph/project/outputs', featureName);
87
-
88
- // Check if feature directory exists
89
- if (!fs.existsSync(featurePath)) {
90
- return {
91
- valid: false,
92
- error: `Feature directory not found: ${featurePath}`,
93
- suggestion: `Run 'morph-spec state set ${featureName} phase proposal' to start`,
94
- missingOutputs: [],
95
- phase: null
96
- };
97
- }
98
-
99
- // Get target phase definition
100
- const phaseDefinition = PHASES[targetPhase];
101
- if (!phaseDefinition) {
102
- return {
103
- valid: false,
104
- error: `Unknown phase: ${targetPhase}`,
105
- validPhases: Object.keys(PHASES),
106
- missingOutputs: [],
107
- phase: null
108
- };
109
- }
110
-
111
- // Check required outputs
112
- const missingOutputs = [];
113
- for (const output of phaseDefinition.requiredOutputs) {
114
- if (!checkOutput(featurePath, output)) {
115
- missingOutputs.push(output);
116
- }
117
- }
118
-
119
- // Check state.json for current phase
120
- let stateWarning = null;
121
- try {
122
- const feature = getFeature(featureName);
123
- if (feature) {
124
- const currentPhaseOrder = PHASES[feature.phase]?.order ?? -1;
125
- const targetPhaseOrder = phaseDefinition.order;
126
-
127
- if (targetPhaseOrder > currentPhaseOrder + 1) {
128
- stateWarning = `Skipping phases: current is '${feature.phase}' (order ${currentPhaseOrder}), target is '${targetPhase}' (order ${targetPhaseOrder})`;
129
- }
130
- }
131
- } catch {
132
- // State file may not exist, that's OK
133
- }
134
-
135
- // Special validation: if target is 'implement', check tasks exist in state
136
- if (targetPhase === 'implement') {
137
- try {
138
- const feature = getFeature(featureName);
139
- if (feature && (!feature.tasks || feature.tasks.total === 0)) {
140
- missingOutputs.push('tasks in state.json (run morph-spec task to add tasks)');
141
- }
142
- } catch {
143
- // State file may not exist
144
- }
145
- }
146
-
147
- return {
148
- valid: missingOutputs.length === 0,
149
- error: null,
150
- missingOutputs,
151
- phase: phaseDefinition,
152
- featurePath,
153
- stateWarning
154
- };
155
- }
156
-
157
- /**
158
- * Main command handler
159
- */
160
- export async function validatePhaseCommand(feature, phase, options = {}) {
161
- console.log(chalk.cyan('\n╔════════════════════════════════════════════════╗'));
162
- console.log(chalk.cyan('║ MORPH-SPEC PHASE VALIDATOR ║'));
163
- console.log(chalk.cyan('╚════════════════════════════════════════════════╝\n'));
164
-
165
- const result = validatePhase(feature, phase);
166
-
167
- console.log(chalk.gray('Feature:'), feature);
168
- console.log(chalk.gray('Target Phase:'), result.phase ? result.phase.name : phase);
169
-
170
- if (result.phase) {
171
- console.log(chalk.gray('Description:'), result.phase.description);
172
- }
173
-
174
- if (result.stateWarning) {
175
- console.log(chalk.yellow(`\n⚠️ Warning: ${result.stateWarning}`));
176
- }
177
-
178
- if (result.valid) {
179
- console.log(chalk.green('\n✓ VALIDATION PASSED'));
180
- console.log(chalk.green(' All required outputs are present.'));
181
- console.log(chalk.green(` Safe to proceed to ${result.phase.name}\n`));
182
-
183
- if (options.verbose) {
184
- console.log(chalk.gray('Required outputs found:'));
185
- result.phase.requiredOutputs.forEach(output => {
186
- console.log(chalk.gray(` ✓ ${output}`));
187
- });
188
- console.log('');
189
- }
190
- } else {
191
- console.log(chalk.red('\n✗ VALIDATION FAILED'));
192
-
193
- if (result.error) {
194
- console.log(chalk.red(` Error: ${result.error}\n`));
195
-
196
- if (result.suggestion) {
197
- console.log(chalk.yellow(` Suggestion: ${result.suggestion}\n`));
198
- }
199
-
200
- if (result.validPhases) {
201
- console.log(chalk.yellow('Valid phases:'));
202
- result.validPhases.forEach(p => {
203
- const def = PHASES[p];
204
- console.log(chalk.gray(` - ${p}: ${def.name}${def.optional ? ' (optional)' : ''}`));
205
- });
206
- }
207
- } else {
208
- console.log(chalk.red(' Missing required outputs:'));
209
- result.missingOutputs.forEach(output => {
210
- console.log(chalk.gray(` - ${output}`));
211
- });
212
-
213
- console.log(chalk.yellow(`\n Action required:`));
214
- console.log(chalk.yellow(` Complete the missing outputs before advancing to ${result.phase.name}`));
215
- }
216
- console.log('');
217
- process.exit(1);
218
- }
219
- }
220
-
221
- export { PHASES, validatePhase };
1
+ /**
2
+ * MORPH-SPEC Phase Validator Command
3
+ *
4
+ * Validates that required previous phases have been completed before advancing.
5
+ * Prevents skipping phases accidentally.
6
+ *
7
+ * Usage:
8
+ * morph-spec validate-phase <feature-name> <target-phase>
9
+ *
10
+ * Example:
11
+ * morph-spec validate-phase scheduled-reports implement
12
+ */
13
+
14
+ import fs from 'fs';
15
+ import path from 'path';
16
+ import chalk from 'chalk';
17
+ import { loadState, getFeature } from '../lib/state-manager.js';
18
+
19
+ // Phase definitions with requirements
20
+ const PHASES = {
21
+ 'proposal': {
22
+ order: 0,
23
+ name: 'FASE 0: PROPOSAL',
24
+ requiredOutputs: [],
25
+ description: 'Initial proposal and agent detection'
26
+ },
27
+ 'setup': {
28
+ order: 1,
29
+ name: 'FASE 1: SETUP',
30
+ requiredOutputs: ['proposal.md'],
31
+ description: 'Load context and standards'
32
+ },
33
+ 'uiux': {
34
+ order: 2,
35
+ name: 'FASE 1.5: UI/UX DESIGN',
36
+ requiredOutputs: ['proposal.md'],
37
+ optionalOutputs: ['ui-design-system.md', 'ui-mockups.md', 'ui-components.md', 'ui-flows.md'],
38
+ description: 'UI/UX design (conditional - only if frontend)',
39
+ optional: true
40
+ },
41
+ 'design': {
42
+ order: 3,
43
+ name: 'FASE 2: DESIGN',
44
+ requiredOutputs: ['proposal.md'],
45
+ description: 'Technical specification and contracts'
46
+ },
47
+ 'clarify': {
48
+ order: 4,
49
+ name: 'FASE 3: CLARIFY',
50
+ requiredOutputs: ['proposal.md', 'spec.md'],
51
+ description: 'Clarify ambiguities and edge cases'
52
+ },
53
+ 'tasks': {
54
+ order: 5,
55
+ name: 'FASE 4: TASKS',
56
+ requiredOutputs: ['proposal.md', 'spec.md'],
57
+ description: 'Break down into executable tasks'
58
+ },
59
+ 'implement': {
60
+ order: 6,
61
+ name: 'FASE 5: IMPLEMENT',
62
+ requiredOutputs: ['proposal.md', 'spec.md'],
63
+ description: 'Execute tasks and implement code'
64
+ },
65
+ 'sync': {
66
+ order: 7,
67
+ name: 'FASE 6: SYNC',
68
+ requiredOutputs: ['proposal.md', 'spec.md', 'decisions.md'],
69
+ description: 'Sync decisions to project standards',
70
+ optional: true
71
+ }
72
+ };
73
+
74
+ /**
75
+ * Check if output file exists
76
+ */
77
+ function checkOutput(featurePath, outputFile) {
78
+ const filePath = path.join(featurePath, outputFile);
79
+ return fs.existsSync(filePath);
80
+ }
81
+
82
+ /**
83
+ * Validate phase requirements
84
+ */
85
+ function validatePhase(featureName, targetPhase) {
86
+ const featurePath = path.join(process.cwd(), '.morph/project/outputs', featureName);
87
+
88
+ // Check if feature directory exists
89
+ if (!fs.existsSync(featurePath)) {
90
+ return {
91
+ valid: false,
92
+ error: `Feature directory not found: ${featurePath}`,
93
+ suggestion: `Run 'morph-spec state set ${featureName} phase proposal' to start`,
94
+ missingOutputs: [],
95
+ phase: null
96
+ };
97
+ }
98
+
99
+ // Get target phase definition
100
+ const phaseDefinition = PHASES[targetPhase];
101
+ if (!phaseDefinition) {
102
+ return {
103
+ valid: false,
104
+ error: `Unknown phase: ${targetPhase}`,
105
+ validPhases: Object.keys(PHASES),
106
+ missingOutputs: [],
107
+ phase: null
108
+ };
109
+ }
110
+
111
+ // Check required outputs
112
+ const missingOutputs = [];
113
+ for (const output of phaseDefinition.requiredOutputs) {
114
+ if (!checkOutput(featurePath, output)) {
115
+ missingOutputs.push(output);
116
+ }
117
+ }
118
+
119
+ // Check state.json for current phase
120
+ let stateWarning = null;
121
+ try {
122
+ const feature = getFeature(featureName);
123
+ if (feature) {
124
+ const currentPhaseOrder = PHASES[feature.phase]?.order ?? -1;
125
+ const targetPhaseOrder = phaseDefinition.order;
126
+
127
+ if (targetPhaseOrder > currentPhaseOrder + 1) {
128
+ stateWarning = `Skipping phases: current is '${feature.phase}' (order ${currentPhaseOrder}), target is '${targetPhase}' (order ${targetPhaseOrder})`;
129
+ }
130
+ }
131
+ } catch {
132
+ // State file may not exist, that's OK
133
+ }
134
+
135
+ // Special validation: if target is 'implement', check tasks exist in state
136
+ if (targetPhase === 'implement') {
137
+ try {
138
+ const feature = getFeature(featureName);
139
+ if (feature && (!feature.tasks || feature.tasks.total === 0)) {
140
+ missingOutputs.push('tasks in state.json (run morph-spec task to add tasks)');
141
+ }
142
+ } catch {
143
+ // State file may not exist
144
+ }
145
+ }
146
+
147
+ return {
148
+ valid: missingOutputs.length === 0,
149
+ error: null,
150
+ missingOutputs,
151
+ phase: phaseDefinition,
152
+ featurePath,
153
+ stateWarning
154
+ };
155
+ }
156
+
157
+ /**
158
+ * Main command handler
159
+ */
160
+ export async function validatePhaseCommand(feature, phase, options = {}) {
161
+ console.log(chalk.cyan('\n╔════════════════════════════════════════════════╗'));
162
+ console.log(chalk.cyan('║ MORPH-SPEC PHASE VALIDATOR ║'));
163
+ console.log(chalk.cyan('╚════════════════════════════════════════════════╝\n'));
164
+
165
+ const result = validatePhase(feature, phase);
166
+
167
+ console.log(chalk.gray('Feature:'), feature);
168
+ console.log(chalk.gray('Target Phase:'), result.phase ? result.phase.name : phase);
169
+
170
+ if (result.phase) {
171
+ console.log(chalk.gray('Description:'), result.phase.description);
172
+ }
173
+
174
+ if (result.stateWarning) {
175
+ console.log(chalk.yellow(`\n⚠️ Warning: ${result.stateWarning}`));
176
+ }
177
+
178
+ if (result.valid) {
179
+ console.log(chalk.green('\n✓ VALIDATION PASSED'));
180
+ console.log(chalk.green(' All required outputs are present.'));
181
+ console.log(chalk.green(` Safe to proceed to ${result.phase.name}\n`));
182
+
183
+ if (options.verbose) {
184
+ console.log(chalk.gray('Required outputs found:'));
185
+ result.phase.requiredOutputs.forEach(output => {
186
+ console.log(chalk.gray(` ✓ ${output}`));
187
+ });
188
+ console.log('');
189
+ }
190
+ } else {
191
+ console.log(chalk.red('\n✗ VALIDATION FAILED'));
192
+
193
+ if (result.error) {
194
+ console.log(chalk.red(` Error: ${result.error}\n`));
195
+
196
+ if (result.suggestion) {
197
+ console.log(chalk.yellow(` Suggestion: ${result.suggestion}\n`));
198
+ }
199
+
200
+ if (result.validPhases) {
201
+ console.log(chalk.yellow('Valid phases:'));
202
+ result.validPhases.forEach(p => {
203
+ const def = PHASES[p];
204
+ console.log(chalk.gray(` - ${p}: ${def.name}${def.optional ? ' (optional)' : ''}`));
205
+ });
206
+ }
207
+ } else {
208
+ console.log(chalk.red(' Missing required outputs:'));
209
+ result.missingOutputs.forEach(output => {
210
+ console.log(chalk.gray(` - ${output}`));
211
+ });
212
+
213
+ console.log(chalk.yellow(`\n Action required:`));
214
+ console.log(chalk.yellow(` Complete the missing outputs before advancing to ${result.phase.name}`));
215
+ }
216
+ console.log('');
217
+ process.exit(1);
218
+ }
219
+ }
220
+
221
+ export { PHASES, validatePhase };
File without changes
@@ -0,0 +1,206 @@
1
+ /**
2
+ * @fileoverview ConfigGenerator - Renders templates and generates config files
3
+ * @module morph-spec/generator/config-generator
4
+ */
5
+
6
+ import { readFile, access, copyFile } from 'fs/promises';
7
+ import { join, dirname } from 'path';
8
+ import Handlebars from 'handlebars';
9
+ import { fileURLToPath } from 'url';
10
+ import Ajv from 'ajv';
11
+
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = dirname(__filename);
14
+
15
+ /**
16
+ * @typedef {import('../types/index.js').ProjectConfig} ProjectConfig
17
+ * @typedef {import('../types/index.js').GeneratedConfigs} GeneratedConfigs
18
+ */
19
+
20
+ /**
21
+ * Validation Error
22
+ */
23
+ export class ValidationError extends Error {
24
+ constructor(message, field, value) {
25
+ super(message);
26
+ this.name = 'ValidationError';
27
+ this.field = field;
28
+ this.value = value;
29
+ }
30
+ }
31
+
32
+ /**
33
+ * ConfigGenerator - Generates configuration files from ProjectConfig
34
+ * @class
35
+ */
36
+ export class ConfigGenerator {
37
+ constructor() {
38
+ this.projectMdTemplate = null;
39
+ this.configJsonTemplate = null;
40
+ this.ajv = new Ajv({ allErrors: true });
41
+ }
42
+
43
+ /**
44
+ * Load templates from filesystem
45
+ * @private
46
+ */
47
+ async loadTemplates() {
48
+ if (this.projectMdTemplate && this.configJsonTemplate) {
49
+ return; // Already loaded
50
+ }
51
+
52
+ const templatesDir = join(__dirname, 'templates');
53
+
54
+ const [projectMdSource, configJsonSource] = await Promise.all([
55
+ readFile(join(templatesDir, 'project.md.template'), 'utf-8'),
56
+ readFile(join(templatesDir, 'config.json.template'), 'utf-8')
57
+ ]);
58
+
59
+ this.projectMdTemplate = Handlebars.compile(projectMdSource);
60
+ this.configJsonTemplate = Handlebars.compile(configJsonSource);
61
+ }
62
+
63
+ /**
64
+ * Generate configuration files from project config
65
+ * @param {ProjectConfig} projectConfig - Detected project config
66
+ * @returns {Promise<GeneratedConfigs>}
67
+ */
68
+ async generate(projectConfig) {
69
+ // Load templates if not already loaded
70
+ await this.loadTemplates();
71
+
72
+ // Add generation timestamp
73
+ const context = {
74
+ ...projectConfig,
75
+ generatedAt: new Date().toISOString()
76
+ };
77
+
78
+ // Render templates
79
+ const projectMd = this.renderProjectMd(context);
80
+ const configJson = this.renderConfigJson(context);
81
+
82
+ // Parse config.json to object
83
+ const configObject = JSON.parse(configJson);
84
+
85
+ // Validate config.json (optional, but good practice)
86
+ // Note: agent-schema.json validation would happen here if we had the schema
87
+ // For now, we just ensure it's valid JSON
88
+
89
+ return {
90
+ projectMd,
91
+ configJson,
92
+ configObject
93
+ };
94
+ }
95
+
96
+ /**
97
+ * Render project.md template
98
+ * @param {ProjectConfig} config - Project config
99
+ * @returns {string} Rendered markdown
100
+ */
101
+ renderProjectMd(config) {
102
+ if (!this.projectMdTemplate) {
103
+ throw new Error('Templates not loaded. Call loadTemplates() first.');
104
+ }
105
+
106
+ return this.projectMdTemplate(config);
107
+ }
108
+
109
+ /**
110
+ * Render config.json template
111
+ * @param {ProjectConfig} config - Project config
112
+ * @returns {string} Rendered JSON string
113
+ */
114
+ renderConfigJson(config) {
115
+ if (!this.configJsonTemplate) {
116
+ throw new Error('Templates not loaded. Call loadTemplates() first.');
117
+ }
118
+
119
+ const rendered = this.configJsonTemplate(config);
120
+
121
+ // Validate that rendered output is valid JSON
122
+ try {
123
+ JSON.parse(rendered);
124
+ return rendered;
125
+ } catch (error) {
126
+ throw new ValidationError(
127
+ `Rendered config.json is not valid JSON: ${error.message}`,
128
+ 'configJson',
129
+ rendered
130
+ );
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Validate config.json against agent schema
136
+ * @param {string} configJson - JSON string
137
+ * @returns {boolean} True if valid
138
+ * @throws {ValidationError} If validation fails
139
+ */
140
+ validateConfigJson(configJson) {
141
+ // Parse JSON
142
+ let parsed;
143
+ try {
144
+ parsed = JSON.parse(configJson);
145
+ } catch (error) {
146
+ throw new ValidationError(
147
+ `Invalid JSON: ${error.message}`,
148
+ 'configJson',
149
+ configJson
150
+ );
151
+ }
152
+
153
+ // Basic validation - ensure required fields exist
154
+ const requiredFields = ['name', 'type', 'description', 'stack', 'architecture'];
155
+ for (const field of requiredFields) {
156
+ if (!parsed[field]) {
157
+ throw new ValidationError(
158
+ `Missing required field: ${field}`,
159
+ field,
160
+ parsed
161
+ );
162
+ }
163
+ }
164
+
165
+ // Validate stack.backend is required
166
+ if (!parsed.stack || !parsed.stack.backend) {
167
+ throw new ValidationError(
168
+ 'stack.backend is required',
169
+ 'stack.backend',
170
+ parsed
171
+ );
172
+ }
173
+
174
+ return true;
175
+ }
176
+
177
+ /**
178
+ * Backup existing configuration files
179
+ * @param {string} cwd - Current working directory
180
+ * @returns {Promise<void>}
181
+ */
182
+ async backupExisting(cwd) {
183
+ const projectMdPath = join(cwd, '.morph', 'project.md');
184
+ const configJsonPath = join(cwd, '.morph', 'config', 'config.json');
185
+
186
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
187
+
188
+ // Backup project.md if exists
189
+ try {
190
+ await access(projectMdPath);
191
+ const backupPath = join(cwd, '.morph', `project.md.${timestamp}.backup`);
192
+ await copyFile(projectMdPath, backupPath);
193
+ } catch (error) {
194
+ // File doesn't exist, no need to backup
195
+ }
196
+
197
+ // Backup config.json if exists
198
+ try {
199
+ await access(configJsonPath);
200
+ const backupPath = join(cwd, '.morph', 'config', `config.json.${timestamp}.backup`);
201
+ await copyFile(configJsonPath, backupPath);
202
+ } catch (error) {
203
+ // File doesn't exist, no need to backup
204
+ }
205
+ }
206
+ }
@@ -0,0 +1,40 @@
1
+ {
2
+ "$schema": "../schema/agent-schema.json",
3
+ "name": "{{name}}",
4
+ "type": "{{type}}",
5
+ "description": "{{description}}",
6
+ "stack": {
7
+ {{#if stack.frontend}}
8
+ "frontend": {
9
+ "tech": "{{stack.frontend.tech}}",
10
+ "version": "{{stack.frontend.version}}"{{#if stack.frontend.details}},
11
+ "details": "{{stack.frontend.details}}"{{/if}}
12
+ },
13
+ {{/if}}
14
+ "backend": {
15
+ "tech": "{{stack.backend.tech}}",
16
+ "version": "{{stack.backend.version}}"{{#if stack.backend.details}},
17
+ "details": "{{stack.backend.details}}"{{/if}}
18
+ }{{#if stack.database}},
19
+ "database": {
20
+ "tech": "{{stack.database.tech}}",
21
+ "version": "{{stack.database.version}}"{{#if stack.database.details}},
22
+ "details": "{{stack.database.details}}"{{/if}}
23
+ }{{/if}}{{#if stack.hosting}},
24
+ "hosting": "{{stack.hosting}}"{{/if}}
25
+ },
26
+ "architecture": "{{architecture}}",
27
+ "conventions": "{{conventions}}",
28
+ "infrastructure": {
29
+ "azure": {{hasAzure}},
30
+ "docker": {{hasDocker}},
31
+ "devops": {{hasDevOps}}
32
+ }{{#if repository}},
33
+ "repository": "{{repository}}"{{/if}},
34
+ "meta": {
35
+ "generatedBy": "morph-spec-cli",
36
+ "generatedAt": "{{generatedAt}}",
37
+ "llmConfidence": {{confidence}},
38
+ "autoDetected": true
39
+ }
40
+ }