@polymorphism-tech/morph-spec 4.12.0 → 4.14.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 +7 -7
  2. package/README.md +28 -34
  3. package/bin/morph-spec.js +41 -24
  4. package/bin/task-manager.js +962 -1341
  5. package/bin/validate.js +1 -1
  6. package/claude-plugin.json +1 -1
  7. package/docs/CHEATSHEET.md +14 -16
  8. package/docs/QUICKSTART.md +15 -15
  9. package/framework/CLAUDE.md +5 -2
  10. package/framework/agents/README.md +3 -4
  11. package/framework/agents/ai-agents/ai-system-architect.md +6 -10
  12. package/framework/agents/architecture/seo-growth-hacker.md +166 -326
  13. package/framework/agents/architecture/standards-architect.md +21 -31
  14. package/framework/agents/backend/dotnet-senior.md +160 -86
  15. package/framework/agents/backend/ef-modeler.md +2 -6
  16. package/framework/agents/backend/hangfire-orchestrator.md +8 -9
  17. package/framework/agents/backend/ms-agent-expert.md +1 -1
  18. package/framework/agents/frontend/nextjs-expert.md +198 -133
  19. package/framework/agents/frontend/ui-ux-designer.md +226 -267
  20. package/framework/agents/infrastructure/infra-architect.md +191 -27
  21. package/framework/agents/integrations/clerk-auth.md +19 -26
  22. package/framework/agents/integrations/hangfire-integration.md +1 -4
  23. package/framework/agents.json +1084 -2278
  24. package/framework/commands/morph-apply.md +4 -6
  25. package/framework/commands/morph-preflight.md +192 -269
  26. package/framework/commands/morph-proposal.md +210 -238
  27. package/framework/commands/morph-status.md +72 -92
  28. package/framework/commands/morph-troubleshoot.md +6 -13
  29. package/framework/hooks/README.md +1 -6
  30. package/framework/hooks/claude-code/post-tool-use/validator-feedback.js +4 -6
  31. package/framework/hooks/claude-code/pre-compact/save-morph-context.js +12 -7
  32. package/framework/hooks/claude-code/pre-tool-use/enforce-phase-writes.js +2 -2
  33. package/framework/hooks/claude-code/pre-tool-use/protect-spec-files.js +2 -2
  34. package/framework/hooks/claude-code/pre-tool-use/task-tracking-guard.js +5 -10
  35. package/framework/hooks/claude-code/session-start/inject-morph-context.js +63 -30
  36. package/framework/hooks/claude-code/session-start/resume-context.js +77 -0
  37. package/framework/hooks/claude-code/statusline.py +4 -5
  38. package/framework/hooks/claude-code/stop/validate-completion.js +4 -4
  39. package/framework/hooks/claude-code/user-prompt/enrich-prompt.js +8 -8
  40. package/framework/hooks/shared/compact-restore.js +28 -5
  41. package/framework/hooks/shared/phase-utils.js +4 -8
  42. package/framework/hooks/shared/state-reader.js +34 -3
  43. package/framework/phases.json +162 -200
  44. package/framework/rules/ai-agents-standards.md +15 -0
  45. package/framework/rules/asaas-standards.md +13 -0
  46. package/framework/rules/clerk-standards.md +13 -0
  47. package/framework/rules/csharp-standards.md +8 -4
  48. package/framework/rules/data-standards.md +18 -0
  49. package/framework/rules/dotnet-templates.md +87 -0
  50. package/framework/rules/frontend-standards.md +13 -13
  51. package/framework/rules/hangfire-standards.md +13 -0
  52. package/framework/rules/infrastructure-standards.md +27 -16
  53. package/framework/rules/morph-workflow.md +73 -13
  54. package/framework/rules/nextjs-standards.md +1 -0
  55. package/framework/rules/nextjs-templates.md +40 -0
  56. package/framework/rules/resend-standards.md +12 -0
  57. package/framework/rules/supabase-standards.md +29 -0
  58. package/framework/skills/README.md +6 -8
  59. package/framework/skills/level-0-meta/mcp-registry.json +21 -99
  60. package/framework/{standards/ai-agents/team-orchestration.md → skills/level-0-meta/morph-agent-teams/SKILL.md} +472 -479
  61. package/framework/skills/level-0-meta/morph-brainstorming/SKILL.md +28 -1
  62. package/framework/skills/level-0-meta/morph-checklist/SKILL.md +2 -2
  63. package/framework/skills/level-0-meta/morph-code-review/SKILL.md +1 -5
  64. package/framework/skills/level-0-meta/morph-code-review/scripts/scan-csharp.mjs +1 -1
  65. package/framework/skills/level-0-meta/morph-frontend-review/SKILL.md +23 -41
  66. package/framework/skills/level-0-meta/morph-init/SKILL.md +18 -14
  67. package/framework/skills/level-0-meta/morph-parallel-dispatch/SKILL.md +225 -0
  68. package/framework/skills/level-0-meta/morph-post-implementation/SKILL.md +20 -0
  69. package/framework/skills/level-0-meta/morph-tool-usage-guide/SKILL.md +4 -8
  70. package/framework/skills/level-0-meta/morph-tool-usage-guide/references/tools-per-phase.md +15 -59
  71. package/framework/skills/level-0-meta/morph-verification-before-completion/SKILL.md +7 -19
  72. package/framework/skills/level-0-meta/morph-verification-before-completion/scripts/check-phase-outputs.mjs +8 -8
  73. package/framework/skills/level-1-workflows/README.md +1 -1
  74. package/framework/skills/level-1-workflows/morph-phase-codebase-analysis/SKILL.md +49 -50
  75. package/framework/skills/level-1-workflows/morph-phase-design/SKILL.md +57 -123
  76. package/framework/skills/level-1-workflows/morph-phase-design/references/architecture-analysis-guide.md +5 -50
  77. package/framework/skills/level-1-workflows/morph-phase-design/references/spec-example.md +1 -1
  78. package/framework/skills/level-1-workflows/morph-phase-implement/SKILL.md +127 -159
  79. package/framework/skills/level-1-workflows/morph-phase-implement/prompts/code-quality-reviewer-prompt.md +1 -1
  80. package/framework/skills/level-1-workflows/morph-phase-implement/prompts/implementer-prompt.md +4 -3
  81. package/framework/skills/level-1-workflows/morph-phase-implement/prompts/spec-reviewer-prompt.md +2 -2
  82. package/framework/skills/level-1-workflows/morph-phase-implement/references/recap-example.md +1 -1
  83. package/framework/skills/level-1-workflows/morph-phase-plan/SKILL.md +17 -13
  84. package/framework/skills/level-1-workflows/morph-phase-tasks/SKILL.md +22 -40
  85. package/framework/skills/level-1-workflows/morph-phase-tasks/references/task-planning-patterns.md +143 -172
  86. package/framework/skills/level-1-workflows/morph-phase-tasks/references/tasks-example.md +5 -5
  87. package/framework/skills/level-1-workflows/morph-phase-uiux/SKILL.md +57 -77
  88. package/framework/skills/level-1-workflows/morph-scope-escalation/SKILL.md +1 -1
  89. package/framework/squad-templates/backend-only.json +6 -6
  90. package/framework/squad-templates/frontend-only.json +17 -8
  91. package/framework/squad-templates/full-stack.json +29 -24
  92. package/framework/standards/STANDARDS.json +1021 -2369
  93. package/framework/standards/backend/dotnet/fluent-validation-vsa.md +200 -0
  94. package/framework/standards/backend/dotnet/result-pattern.md +213 -0
  95. package/framework/standards/backend/dotnet/scalar-ui.md +172 -0
  96. package/framework/standards/backend/dotnet/scrutor.md +158 -0
  97. package/framework/standards/backend/dotnet/vsa-handler-patterns.md +274 -0
  98. package/framework/standards/frontend/nextjs/motion-patterns.md +1 -1
  99. package/framework/standards/infrastructure/supabase/mcp-setup.md +83 -193
  100. package/framework/standards/integration/mcp/mcp-tools.md +91 -77
  101. package/framework/templates/IDE-SNIPPETS.md +2 -6
  102. package/framework/templates/README.md +709 -814
  103. package/framework/templates/REGISTRY.json +223 -762
  104. package/framework/templates/code/dotnet/abstractions/api-endpoint.cs +7 -0
  105. package/framework/templates/code/dotnet/abstractions/error.cs +60 -0
  106. package/framework/templates/code/dotnet/abstractions/handler.cs +12 -0
  107. package/framework/templates/code/dotnet/abstractions/result.cs +74 -0
  108. package/framework/templates/code/dotnet/backend/repository.cs +148 -141
  109. package/framework/templates/code/dotnet/constants/api-tags.cs +6 -0
  110. package/framework/templates/code/dotnet/exceptions/exception-handler.cs +32 -0
  111. package/framework/templates/code/dotnet/extensions/database-extensions.cs +20 -0
  112. package/framework/templates/code/dotnet/extensions/handler-registration.cs +38 -0
  113. package/framework/templates/code/dotnet/extensions/health-checks.cs +24 -0
  114. package/framework/templates/code/dotnet/extensions/map-endpoints.cs +35 -0
  115. package/framework/templates/code/dotnet/extensions/result-extensions.cs +29 -0
  116. package/framework/templates/code/dotnet/feature/endpoint.cs.hbs +21 -0
  117. package/framework/templates/code/dotnet/feature/entity.cs.hbs +8 -0
  118. package/framework/templates/code/dotnet/feature/errors.cs.hbs +8 -0
  119. package/framework/templates/code/dotnet/feature/handler.cs.hbs +24 -0
  120. package/framework/templates/code/dotnet/feature/request.cs.hbs +4 -0
  121. package/framework/templates/code/dotnet/feature/response.cs.hbs +4 -0
  122. package/framework/templates/code/dotnet/feature/validator.cs.hbs +15 -0
  123. package/framework/templates/code/dotnet/jobs/job.cs +21 -17
  124. package/framework/templates/code/dotnet/pipelines/logging-decorator.cs +31 -0
  125. package/framework/templates/code/dotnet/pipelines/validation-decorator.cs +97 -0
  126. package/framework/templates/code/dotnet/test.cs +192 -106
  127. package/framework/templates/context/ARCHITECTURE.md +89 -0
  128. package/framework/templates/context/CONTEXT-FEATURE.md +2 -2
  129. package/framework/templates/context/CONTEXT.md +180 -181
  130. package/framework/templates/context/design-system.md +1 -5
  131. package/framework/templates/docs/onboarding.md +2 -3
  132. package/framework/templates/docs/proposal.md +171 -182
  133. package/framework/templates/docs/spec.md +1 -3
  134. package/framework/templates/docs/ui-components.md +0 -72
  135. package/framework/templates/examples/design-system-examples.md +4 -4
  136. package/framework/templates/feature/decisions.md +0 -66
  137. package/framework/templates/feature/recap.md +1 -2
  138. package/framework/templates/infrastructure/github/README.md +56 -593
  139. package/framework/templates/integrations/clerk-config.cs +0 -41
  140. package/framework/templates/meta-prompts/parallel-workers/parallel-worker.md +2 -2
  141. package/framework/templates/meta-prompts/squad-leaders/backend-squad.md +1 -2
  142. package/framework/templates/meta-prompts/squad-leaders/frontend-squad.md +83 -126
  143. package/framework/templates/meta-prompts/validators/pre-commit-validator.md +2 -2
  144. package/framework/templates/project/validate.js +2 -4
  145. package/framework/templates/ui/design-system.css +1 -1
  146. package/framework/workflows/README.md +8 -8
  147. package/framework/workflows/configs/fast-track.json +51 -0
  148. package/framework/workflows/configs/full.json +68 -0
  149. package/framework/workflows/configs/standard.json +7 -3
  150. package/framework/workflows/docs/STORY-DRIVEN-DEVELOPMENT.md +1 -1
  151. package/framework/workflows/docs/enforcement-pipeline.md +18 -19
  152. package/framework/workflows/docs/full-morph.md +69 -76
  153. package/framework/workflows/docs/standard.md +49 -44
  154. package/framework/workflows/docs/ui-refresh.md +1 -1
  155. package/package.json +3 -3
  156. package/src/commands/agents/dispatch-agents.js +55 -116
  157. package/src/commands/context/context-refresh.js +79 -0
  158. package/src/commands/phase/phase-reset.js +1 -1
  159. package/src/commands/project/doctor.js +10 -32
  160. package/src/commands/project/init.js +12 -0
  161. package/src/commands/project/status.js +6 -12
  162. package/src/commands/scaffold/scaffold.js +131 -0
  163. package/src/commands/scope/escalate.js +1 -1
  164. package/src/commands/state/advance-phase.js +15 -29
  165. package/src/commands/state/state.js +20 -5
  166. package/src/commands/tasks/task.js +0 -30
  167. package/src/commands/validation/validate-feature.js +3 -10
  168. package/src/core/paths/output-schema.js +12 -13
  169. package/src/core/state/phase-state-machine.js +211 -217
  170. package/src/core/state/state-manager.js +9 -9
  171. package/src/lib/agents/agents-manager.js +2 -2
  172. package/src/lib/agents/output-collector.js +1 -2
  173. package/src/lib/detectors/design-system-detector.js +4 -4
  174. package/src/lib/detectors/index.js +1 -11
  175. package/src/lib/generators/architecture-scanner.js +640 -0
  176. package/src/lib/generators/context-generator.js +3 -3
  177. package/src/lib/generators/design-system-generator.js +508 -587
  178. package/src/lib/generators/index.js +12 -10
  179. package/src/lib/generators/metadata-extractor.js +386 -387
  180. package/src/lib/generators/recap-generator.js +4 -4
  181. package/src/lib/generators/scaffold-generator.js +317 -0
  182. package/src/lib/generators/settings-generator.js +0 -1
  183. package/src/lib/phase-chain/phase-validator.js +64 -42
  184. package/src/lib/stack/stack-profile.js +2 -2
  185. package/src/lib/standards/digest-builder.js +72 -285
  186. package/src/lib/tasks/task-parser.js +11 -5
  187. package/src/lib/validators/architecture/architecture-validator.js +259 -387
  188. package/src/lib/validators/content/content-validator.js +287 -287
  189. package/src/lib/validators/css/css-validator.js +340 -352
  190. package/src/lib/validators/packages/package-validator.js +347 -360
  191. package/src/lib/validators/shared/issue-counter.js +14 -18
  192. package/src/lib/validators/validation-runner.js +3 -19
  193. package/src/scripts/setup-infra.js +1 -1
  194. package/src/utils/agents-installer.js +61 -10
  195. package/src/utils/file-copier.js +1 -0
  196. package/src/utils/hooks-installer.js +11 -19
  197. package/src/utils/skills-installer.js +178 -178
  198. package/framework/agents/architecture/prompt-engineer.md +0 -195
  199. package/framework/agents/backend/api-designer.md +0 -106
  200. package/framework/agents/frontend/blazor-builder.md +0 -229
  201. package/framework/agents/frontend/nextjs-ui-specialist.md +0 -218
  202. package/framework/agents/infrastructure/azure-architect.md +0 -150
  203. package/framework/agents/infrastructure/azure-deploy-specialist.md +0 -707
  204. package/framework/agents/infrastructure/bicep-architect.md +0 -132
  205. package/framework/agents/infrastructure/container-specialist.md +0 -137
  206. package/framework/agents/infrastructure/devops-engineer.md +0 -126
  207. package/framework/agents/integrations/azure-identity.md +0 -148
  208. package/framework/agents/quality/code-analyzer.md +0 -239
  209. package/framework/agents/quality/testing-specialist.md +0 -130
  210. package/framework/hooks/claude-code/notification/approval-reminder.js +0 -57
  211. package/framework/hooks/claude-code/post-tool-use/context-refresh.js +0 -109
  212. package/framework/hooks/claude-code/post-tool-use/skill-reminder.js +0 -78
  213. package/framework/index/troubleshooting-index.json +0 -184
  214. package/framework/rules/testing-standards.md +0 -14
  215. package/framework/skills/level-0-meta/morph-replicate/SKILL.md +0 -230
  216. package/framework/skills/level-0-meta/morph-replicate/references/blazor-html-mapping.md +0 -70
  217. package/framework/skills/level-1-workflows/morph-phase-clarify/SKILL.md +0 -256
  218. package/framework/skills/level-1-workflows/morph-phase-clarify/references/clarifications-example.md +0 -117
  219. package/framework/skills/level-1-workflows/morph-phase-setup/SKILL.md +0 -269
  220. package/framework/standards/ai-agents/blazor-ui.md +0 -364
  221. package/framework/standards/architecture/ddd/aggregates.md +0 -120
  222. package/framework/standards/architecture/ddd/bounded-contexts.md +0 -105
  223. package/framework/standards/architecture/ddd/complexity-levels.md +0 -108
  224. package/framework/standards/architecture/ddd/entities.md +0 -99
  225. package/framework/standards/architecture/ddd/ubiquitous-language.md +0 -58
  226. package/framework/standards/architecture/ddd/value-objects.md +0 -124
  227. package/framework/standards/backend/api/minimal-api.md +0 -494
  228. package/framework/standards/backend/api/rest.md +0 -492
  229. package/framework/standards/backend/authentication/passkeys.md +0 -428
  230. package/framework/standards/backend/database/ef-core.md +0 -199
  231. package/framework/standards/backend/database/migrations.md +0 -393
  232. package/framework/standards/backend/database/repository-patterns.md +0 -528
  233. package/framework/standards/backend/dotnet/async.md +0 -366
  234. package/framework/standards/backend/dotnet/core.md +0 -117
  235. package/framework/standards/backend/dotnet/di.md +0 -439
  236. package/framework/standards/backend/dotnet/program-cs-checklist.md +0 -92
  237. package/framework/standards/context/analytics.md +0 -96
  238. package/framework/standards/context/bundles.md +0 -110
  239. package/framework/standards/context/priming.md +0 -78
  240. package/framework/standards/core/architecture.md +0 -185
  241. package/framework/standards/core/coding.md +0 -214
  242. package/framework/standards/core/git-branching-strategy.md +0 -403
  243. package/framework/standards/core/git.md +0 -185
  244. package/framework/standards/core/testing.md +0 -295
  245. package/framework/standards/data/nosql/blob-storage.md +0 -102
  246. package/framework/standards/data/vector-search/azure-ai-search.md +0 -121
  247. package/framework/standards/frontend/blazor/design-checklist.md +0 -222
  248. package/framework/standards/frontend/blazor/fluent-ui-setup.md +0 -595
  249. package/framework/standards/frontend/blazor/fluent-ui.md +0 -137
  250. package/framework/standards/frontend/blazor/html-conversion.md +0 -184
  251. package/framework/standards/frontend/blazor/lifecycle.md +0 -195
  252. package/framework/standards/frontend/blazor/pitfalls.md +0 -198
  253. package/framework/standards/frontend/blazor/state.md +0 -191
  254. package/framework/standards/frontend/design-system/aesthetic-direction.md +0 -266
  255. package/framework/standards/frontend/design-system/design-trends.md +0 -171
  256. package/framework/standards/infrastructure/azure/azure.md +0 -624
  257. package/framework/standards/infrastructure/azure/bicep/bicep-patterns.md +0 -422
  258. package/framework/standards/infrastructure/azure/devops/azure-devops-setup.md +0 -516
  259. package/framework/standards/infrastructure/azure/devops/local-development.md +0 -520
  260. package/framework/standards/infrastructure/azure/services/functions.md +0 -486
  261. package/framework/standards/infrastructure/azure/services/service-bus.md +0 -459
  262. package/framework/standards/infrastructure/azure/services/storage.md +0 -407
  263. package/framework/standards/infrastructure/vercel/vercel-database.md +0 -106
  264. package/framework/standards/integration/api/graphql.md +0 -91
  265. package/framework/standards/integration/api/grpc.md +0 -114
  266. package/framework/standards/integration/api/rest-design.md +0 -95
  267. package/framework/standards/integration/event-driven/cqrs.md +0 -101
  268. package/framework/standards/integration/event-driven/event-sourcing.md +0 -124
  269. package/framework/standards/integration/event-driven/service-bus.md +0 -95
  270. package/framework/standards/observability/logging.md +0 -131
  271. package/framework/standards/observability/metrics.md +0 -121
  272. package/framework/standards/observability/monitoring.md +0 -114
  273. package/framework/standards/observability/tracing.md +0 -132
  274. package/framework/standards/workflows/parallel-execution.md +0 -112
  275. package/framework/standards/workflows/thread-management.md +0 -113
  276. package/framework/templates/code/dotnet/backend/service.cs +0 -139
  277. package/framework/templates/code/dotnet/contracts/Commands.cs +0 -74
  278. package/framework/templates/code/dotnet/contracts/Entities.cs +0 -25
  279. package/framework/templates/code/dotnet/contracts/Queries.cs +0 -74
  280. package/framework/templates/code/dotnet/contracts/api-contracts.cs +0 -173
  281. package/framework/templates/code/dotnet/contracts/contracts-level1.cs +0 -69
  282. package/framework/templates/code/dotnet/contracts/contracts-level2.cs +0 -86
  283. package/framework/templates/code/dotnet/contracts/contracts-level3.cs +0 -41
  284. package/framework/templates/code/dotnet/frontend/component.razor +0 -239
  285. package/framework/templates/infrastructure/azure/Dockerfile.example +0 -82
  286. package/framework/templates/infrastructure/azure/README.md +0 -286
  287. package/framework/templates/infrastructure/azure/app-insights.bicep +0 -63
  288. package/framework/templates/infrastructure/azure/app-service.bicep +0 -164
  289. package/framework/templates/infrastructure/azure/container-app-env.bicep +0 -49
  290. package/framework/templates/infrastructure/azure/container-app.bicep +0 -156
  291. package/framework/templates/infrastructure/azure/deploy-checklist.md +0 -426
  292. package/framework/templates/infrastructure/azure/deploy.ps1 +0 -229
  293. package/framework/templates/infrastructure/azure/deploy.sh +0 -208
  294. package/framework/templates/infrastructure/azure/key-vault.bicep +0 -91
  295. package/framework/templates/infrastructure/azure/main.bicep +0 -189
  296. package/framework/templates/infrastructure/azure/parameters.dev.json +0 -29
  297. package/framework/templates/infrastructure/azure/parameters.prod.json +0 -29
  298. package/framework/templates/infrastructure/azure/parameters.staging.json +0 -29
  299. package/framework/templates/infrastructure/azure/sql-database.bicep +0 -103
  300. package/framework/templates/infrastructure/azure/storage.bicep +0 -106
  301. package/framework/templates/infrastructure/github/actions/azure-auth/action.yml.hbs +0 -22
  302. package/framework/templates/infrastructure/github/workflows/deploy-azure-app-service.yml.hbs +0 -61
  303. package/framework/templates/integrations/azure-identity-config.cs +0 -288
  304. package/framework/templates/project-structure/dotnet-ddd.md +0 -70
  305. package/framework/templates/saas/subscription.cs +0 -347
  306. package/framework/templates/saas/tenant.cs +0 -338
  307. package/framework/templates/ui/FluentDesignTheme.cs +0 -149
  308. package/framework/templates/ui/MudTheme.cs +0 -281
  309. package/framework/workflows/configs/nodejs-cli.json +0 -40
  310. package/src/commands/standards/context-budget.js +0 -89
  311. package/src/lib/standards/index.js +0 -7
  312. package/src/lib/standards/standards-context-injector.js +0 -302
  313. package/src/lib/validators/blazor/blazor-concurrency-analyzer.js +0 -316
  314. package/src/lib/validators/blazor/blazor-state-validator.js +0 -279
  315. package/src/lib/validators/blazor/blazor-validator.js +0 -369
  316. package/src/lib/validators/blazor/index.js +0 -9
@@ -182,14 +182,14 @@ function buildRecapMarkdown(data) {
182
182
  // Suggested Quality Verification
183
183
  const agents = agentsSummary;
184
184
  const hasNextjs = agents.some(a => ['nextjs-expert', 'css-specialist', 'ui-designer'].includes(a));
185
- const hasBlazor = agents.some(a => ['blazor-builder', 'blazor-specialist', 'dotnet-senior'].includes(a));
186
- if (hasNextjs || hasBlazor) {
185
+ const hasDotnet = agents.some(a => ['dotnet-senior', 'ef-modeler'].includes(a));
186
+ if (hasNextjs || hasDotnet) {
187
187
  md += `## Suggested Quality Verification\n\n`;
188
188
  if (hasNextjs) {
189
189
  md += `**Next.js / TypeScript:**\n\`\`\`bash\nnpx tsc --noEmit\nnpx eslint . --max-warnings 0\n\`\`\`\n\n`;
190
190
  }
191
- if (hasBlazor) {
192
- md += `**Blazor / .NET:**\n\`\`\`bash\ndotnet build\ndotnet test\n\`\`\`\n\n`;
191
+ if (hasDotnet) {
192
+ md += `**.NET:**\n\`\`\`bash\ndotnet build\ndotnet test\n\`\`\`\n\n`;
193
193
  }
194
194
  }
195
195
 
@@ -0,0 +1,317 @@
1
+ /**
2
+ * Scaffold Generator - Generates VSA feature slice (.NET) and feature page (Next.js) files.
3
+ *
4
+ * Uses existing Handlebars templates from framework/templates/ to generate
5
+ * complete feature structures with one command.
6
+ *
7
+ * @module scaffold-generator
8
+ */
9
+
10
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync } from 'fs';
11
+ import { join, dirname, basename } from 'path';
12
+ import { fileURLToPath } from 'url';
13
+ import { renderTemplate } from '../../core/templates/template-renderer.js';
14
+
15
+ const __filename = fileURLToPath(import.meta.url);
16
+ const __dirname = dirname(__filename);
17
+
18
+ /** Framework templates root (relative to this file) */
19
+ const FRAMEWORK_TEMPLATES_DIR = join(__dirname, '../../../framework/templates');
20
+
21
+ /**
22
+ * Convert kebab-case to PascalCase.
23
+ * @param {string} str
24
+ * @returns {string}
25
+ */
26
+ function toPascalCase(str) {
27
+ return str
28
+ .split('-')
29
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
30
+ .join('');
31
+ }
32
+
33
+ /**
34
+ * Convert kebab-case to camelCase.
35
+ * @param {string} str
36
+ * @returns {string}
37
+ */
38
+ function toCamelCase(str) {
39
+ return str
40
+ .split('-')
41
+ .map((word, i) => i === 0 ? word.toLowerCase() : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
42
+ .join('');
43
+ }
44
+
45
+ /**
46
+ * Normalize a namespace to kebab-case so Handlebars {{pascalCase}} reconstructs it correctly.
47
+ * Handles: PascalCase ("MyBookStore" → "my-book-store"), dot-separated ("My.App" → "my-app"),
48
+ * and already kebab-case pass-through.
49
+ * @param {string} ns
50
+ * @returns {string}
51
+ */
52
+ export function normalizeNamespaceToKebab(ns) {
53
+ // Split on dots first (My.BookStore → ["My", "BookStore"])
54
+ // Then split PascalCase on uppercase boundaries (BookStore → Book-Store)
55
+ return ns
56
+ .split('.')
57
+ .map(segment =>
58
+ segment
59
+ .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
60
+ .replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')
61
+ .toLowerCase()
62
+ )
63
+ .join('-');
64
+ }
65
+
66
+ // ─────────────────────────────────────────────────────────────────────────────
67
+ // .NET VSA Scaffold
68
+ // ─────────────────────────────────────────────────────────────────────────────
69
+
70
+ /** Template IDs for .NET slice-level files */
71
+ const DOTNET_SLICE_TEMPLATES = [
72
+ { id: 'endpoint', file: 'endpoint.cs.hbs', suffix: 'Endpoint' },
73
+ { id: 'handler', file: 'handler.cs.hbs', suffix: 'Handler' },
74
+ { id: 'request', file: 'request.cs.hbs', suffix: 'Request' },
75
+ { id: 'response', file: 'response.cs.hbs', suffix: 'Response' },
76
+ { id: 'validator', file: 'validator.cs.hbs', suffix: 'Validator' },
77
+ ];
78
+
79
+ /** Template IDs for .NET feature-level files */
80
+ const DOTNET_FEATURE_TEMPLATES = [
81
+ { id: 'entity', file: 'entity.cs.hbs', suffix: '', dir: 'entities' },
82
+ { id: 'errors', file: 'errors.cs.hbs', suffix: 'Errors', dir: 'feature' },
83
+ ];
84
+
85
+ /**
86
+ * Scaffold a .NET VSA feature slice.
87
+ *
88
+ * @param {Object} options
89
+ * @param {string} options.feature - Entity/feature name in kebab-case (e.g., "book")
90
+ * @param {string} options.sliceName - Slice name in kebab-case (e.g., "create-book")
91
+ * @param {string} options.namespace - Root namespace (e.g., "MyApp")
92
+ * @param {string} [options.outputDir] - Base output directory (default: cwd)
93
+ * @param {boolean} [options.dryRun] - Preview without writing
94
+ * @returns {{ files: Array<{path: string, content: string, skipped: boolean}> }}
95
+ */
96
+ export function scaffoldDotnetSlice(options) {
97
+ const { feature, sliceName, namespace, outputDir = process.cwd(), dryRun = false } = options;
98
+
99
+ const pascalFeature = toPascalCase(feature);
100
+ const pascalSlice = toPascalCase(sliceName);
101
+ const templateDir = join(FRAMEWORK_TEMPLATES_DIR, 'code/dotnet/feature');
102
+
103
+ const variables = {
104
+ PROJECT_NAME: normalizeNamespaceToKebab(namespace),
105
+ FEATURE_NAME: feature,
106
+ SLICE_NAME: sliceName,
107
+ DATE: new Date().toISOString().split('T')[0],
108
+ YEAR: new Date().getFullYear().toString(),
109
+ };
110
+
111
+ const files = [];
112
+
113
+ // 1. Render slice-level templates
114
+ for (const tmpl of DOTNET_SLICE_TEMPLATES) {
115
+ const templatePath = join(templateDir, tmpl.file);
116
+ const outputPath = join(
117
+ outputDir,
118
+ 'Features',
119
+ `${pascalFeature}Feature`,
120
+ pascalSlice,
121
+ `${pascalSlice}${tmpl.suffix}.cs`
122
+ );
123
+
124
+ const content = renderTemplate(templatePath, variables);
125
+
126
+ if (!dryRun) {
127
+ mkdirSync(dirname(outputPath), { recursive: true });
128
+ writeFileSync(outputPath, content, 'utf-8');
129
+ }
130
+
131
+ files.push({ path: outputPath, content, skipped: false });
132
+ }
133
+
134
+ // 2. Render feature-level templates (skip if already exist)
135
+ for (const tmpl of DOTNET_FEATURE_TEMPLATES) {
136
+ const templatePath = join(templateDir, tmpl.file);
137
+ let outputPath;
138
+
139
+ if (tmpl.dir === 'entities') {
140
+ outputPath = join(outputDir, 'Entities', `${pascalFeature}${tmpl.suffix}.cs`);
141
+ } else {
142
+ outputPath = join(outputDir, 'Features', `${pascalFeature}Feature`, `${pascalFeature}${tmpl.suffix}.cs`);
143
+ }
144
+
145
+ if (existsSync(outputPath)) {
146
+ files.push({ path: outputPath, content: '', skipped: true });
147
+ continue;
148
+ }
149
+
150
+ const content = renderTemplate(templatePath, variables);
151
+
152
+ if (!dryRun) {
153
+ mkdirSync(dirname(outputPath), { recursive: true });
154
+ writeFileSync(outputPath, content, 'utf-8');
155
+ }
156
+
157
+ files.push({ path: outputPath, content, skipped: false });
158
+ }
159
+
160
+ return { files };
161
+ }
162
+
163
+ // ─────────────────────────────────────────────────────────────────────────────
164
+ // Next.js Scaffold
165
+ // ─────────────────────────────────────────────────────────────────────────────
166
+
167
+ /** Template mappings for Next.js feature */
168
+ const NEXTJS_TEMPLATES = [
169
+ {
170
+ file: 'page.tsx.hbs',
171
+ outputFn: (kebab) => join('app', '(dashboard)', kebab, 'page.tsx'),
172
+ },
173
+ {
174
+ file: 'client-component.tsx.hbs',
175
+ outputFn: (kebab) => join('features', kebab, 'components', `${kebab}-list.tsx`),
176
+ },
177
+ {
178
+ file: 'feature-form.tsx.hbs',
179
+ outputFn: (kebab) => join('features', kebab, 'components', `create-${kebab}-form.tsx`),
180
+ },
181
+ {
182
+ file: 'use-feature.ts.hbs',
183
+ outputFn: (kebab) => join('features', kebab, 'hooks', `use-${kebab}s.ts`),
184
+ },
185
+ ];
186
+
187
+ /**
188
+ * Scaffold a Next.js feature page with components and hooks.
189
+ *
190
+ * @param {Object} options
191
+ * @param {string} options.featureName - Feature name in kebab-case (e.g., "book")
192
+ * @param {string} [options.outputDir] - Base output directory (default: cwd)
193
+ * @param {boolean} [options.dryRun] - Preview without writing
194
+ * @returns {{ files: Array<{path: string, content: string, skipped: boolean}> }}
195
+ */
196
+ export function scaffoldNextjsFeature(options) {
197
+ const { featureName, outputDir = process.cwd(), dryRun = false } = options;
198
+
199
+ const kebab = featureName.toLowerCase();
200
+ const templateDir = join(FRAMEWORK_TEMPLATES_DIR, 'frontend/nextjs');
201
+
202
+ // Next.js templates use camelCase variable name `featureName`
203
+ const variables = {
204
+ featureName: featureName,
205
+ };
206
+
207
+ const files = [];
208
+
209
+ for (const tmpl of NEXTJS_TEMPLATES) {
210
+ const templatePath = join(templateDir, tmpl.file);
211
+ const relativePath = tmpl.outputFn(kebab);
212
+ const outputPath = join(outputDir, relativePath);
213
+
214
+ if (existsSync(outputPath)) {
215
+ files.push({ path: outputPath, content: '', skipped: true });
216
+ continue;
217
+ }
218
+
219
+ const content = renderTemplate(templatePath, variables);
220
+
221
+ if (!dryRun) {
222
+ mkdirSync(dirname(outputPath), { recursive: true });
223
+ writeFileSync(outputPath, content, 'utf-8');
224
+ }
225
+
226
+ files.push({ path: outputPath, content, skipped: false });
227
+ }
228
+
229
+ return { files };
230
+ }
231
+
232
+ // ─────────────────────────────────────────────────────────────────────────────
233
+ // Namespace Detection
234
+ // ─────────────────────────────────────────────────────────────────────────────
235
+
236
+ /**
237
+ * Detect the .NET root namespace from .csproj or config.json.
238
+ *
239
+ * Search order:
240
+ * 1. *.csproj in dir (extract <RootNamespace>)
241
+ * 2. *.csproj in dir (use filename without extension)
242
+ * 3. *.csproj one level deep
243
+ * 4. .morph/config.json → project.name
244
+ *
245
+ * @param {string} dir - Directory to search in
246
+ * @returns {string|null} Detected namespace or null
247
+ */
248
+ export function detectNamespace(dir) {
249
+ // 1. Search for .csproj in current dir
250
+ const csprojInDir = findCsproj(dir);
251
+ if (csprojInDir) {
252
+ const ns = extractNamespaceFromCsproj(csprojInDir);
253
+ if (ns) return ns;
254
+ // Fallback: use filename
255
+ return basename(csprojInDir, '.csproj');
256
+ }
257
+
258
+ // 2. Search one level deep
259
+ try {
260
+ const entries = readdirSync(dir, { withFileTypes: true });
261
+ for (const entry of entries) {
262
+ if (entry.isDirectory()) {
263
+ const subCsproj = findCsproj(join(dir, entry.name));
264
+ if (subCsproj) {
265
+ const ns = extractNamespaceFromCsproj(subCsproj);
266
+ if (ns) return ns;
267
+ return basename(subCsproj, '.csproj');
268
+ }
269
+ }
270
+ }
271
+ } catch {
272
+ // ignore read errors
273
+ }
274
+
275
+ // 3. Fall back to config.json
276
+ const configPath = join(dir, '.morph', 'config.json');
277
+ if (existsSync(configPath)) {
278
+ try {
279
+ const config = JSON.parse(readFileSync(configPath, 'utf-8'));
280
+ if (config.project?.name) return config.project.name;
281
+ } catch {
282
+ // ignore parse errors
283
+ }
284
+ }
285
+
286
+ return null;
287
+ }
288
+
289
+ /**
290
+ * Find the first .csproj file in a directory.
291
+ * @param {string} dir
292
+ * @returns {string|null}
293
+ */
294
+ function findCsproj(dir) {
295
+ try {
296
+ const entries = readdirSync(dir);
297
+ const csproj = entries.find(f => f.endsWith('.csproj'));
298
+ return csproj ? join(dir, csproj) : null;
299
+ } catch {
300
+ return null;
301
+ }
302
+ }
303
+
304
+ /**
305
+ * Extract <RootNamespace> from a .csproj file.
306
+ * @param {string} csprojPath
307
+ * @returns {string|null}
308
+ */
309
+ function extractNamespaceFromCsproj(csprojPath) {
310
+ try {
311
+ const content = readFileSync(csprojPath, 'utf-8');
312
+ const match = content.match(/<RootNamespace>([^<]+)<\/RootNamespace>/);
313
+ return match ? match[1] : null;
314
+ } catch {
315
+ return null;
316
+ }
317
+ }
@@ -80,7 +80,6 @@ export function buildPermissions(stack, detectedConfig = {}) {
80
80
  react: ['Bash(node:*)', 'Bash(npm:*)', 'Bash(npx:*)'],
81
81
  vue: ['Bash(node:*)', 'Bash(npm:*)', 'Bash(npx:*)'],
82
82
  dotnet: ['Bash(dotnet:*)', 'Bash(nuget:*)'],
83
- blazor: ['Bash(dotnet:*)', 'Bash(nuget:*)'],
84
83
  python: ['Bash(python:*)', 'Bash(pip:*)', 'Bash(pytest:*)'],
85
84
  go: ['Bash(go:*)']
86
85
  };
@@ -26,53 +26,41 @@ export const PHASES = {
26
26
  requiredOutputs: [],
27
27
  description: 'Initial proposal and agent detection'
28
28
  },
29
- 'setup': {
30
- order: 1,
31
- name: 'FASE 1: SETUP',
32
- requiredOutputs: ['proposal.md'],
33
- description: 'Load context and standards'
34
- },
35
29
  'uiux': {
36
- order: 2,
37
- name: 'FASE 1.5: UI/UX DESIGN',
30
+ order: 1,
31
+ name: 'FASE 1: UI/UX DESIGN',
38
32
  requiredOutputs: ['proposal.md'],
39
- optionalOutputs: ['ui-design-system.md', 'ui-mockups.md', 'ui-components.md', 'ui-flows.md'],
33
+ optionalOutputs: ['design-system.md', 'mockups.md', 'components.md', 'flows.md'],
40
34
  description: 'UI/UX design (conditional - only if frontend)',
41
35
  optional: true
42
36
  },
43
37
  'design': {
44
- order: 3,
38
+ order: 2,
45
39
  name: 'FASE 2: DESIGN',
46
40
  requiredOutputs: ['proposal.md'],
47
- description: 'Technical specification and contracts'
48
- },
49
- 'clarify': {
50
- order: 4,
51
- name: 'FASE 3: CLARIFY',
52
- requiredOutputs: ['proposal.md', 'spec.md'],
53
- description: 'Clarify ambiguities and edge cases'
41
+ description: 'Technical specification, contracts, and clarification'
54
42
  },
55
43
  'plan': {
56
- order: 5,
57
- name: 'FASE 4: PLAN',
44
+ order: 3,
45
+ name: 'FASE 3: PLAN',
58
46
  requiredOutputs: ['proposal.md', 'spec.md'],
59
47
  description: 'Planning phase before task breakdown'
60
48
  },
61
49
  'tasks': {
62
- order: 6,
63
- name: 'FASE 5: TASKS',
50
+ order: 4,
51
+ name: 'FASE 4: TASKS',
64
52
  requiredOutputs: ['proposal.md', 'spec.md', 'plan.md'],
65
53
  description: 'Break down into executable tasks'
66
54
  },
67
55
  'implement': {
68
- order: 7,
69
- name: 'FASE 6: IMPLEMENT',
56
+ order: 5,
57
+ name: 'FASE 5: IMPLEMENT',
70
58
  requiredOutputs: ['proposal.md', 'spec.md', 'tasks.md'],
71
59
  description: 'Execute tasks and implement code'
72
60
  },
73
61
  'sync': {
74
- order: 8,
75
- name: 'FASE 7: SYNC',
62
+ order: 6,
63
+ name: 'FASE 6: SYNC',
76
64
  requiredOutputs: ['proposal.md', 'spec.md', 'decisions.md', 'recap.md'],
77
65
  description: 'Sync decisions to project standards',
78
66
  optional: true
@@ -82,15 +70,14 @@ export const PHASES = {
82
70
  // Map output filenames to their phase subfolders
83
71
  const OUTPUT_PHASE_MAP = {
84
72
  'proposal.md': '0-proposal',
85
- 'schema-analysis.md': '1-design',
86
- 'spec.md': '1-design',
87
- 'clarifications.md': '1-design',
88
- 'contracts.cs': '1-design',
89
- 'decisions.md': '1-design',
90
- 'ui-design-system.md': '2-ui',
91
- 'ui-mockups.md': '2-ui',
92
- 'ui-components.md': '2-ui',
93
- 'ui-flows.md': '2-ui',
73
+ 'schema-analysis.md': '2-design',
74
+ 'spec.md': '2-design',
75
+ 'contracts.cs': '2-design',
76
+ 'decisions.md': '2-design',
77
+ 'design-system.md': '1-ui',
78
+ 'mockups.md': '1-ui',
79
+ 'components.md': '1-ui',
80
+ 'flows.md': '1-ui',
94
81
  'plan.md': '3-plan',
95
82
  'tasks.md': '4-tasks',
96
83
  'recap.md': '5-implement'
@@ -135,8 +122,24 @@ export function validatePhase(featureName, targetPhase) {
135
122
  };
136
123
  }
137
124
 
125
+ // Workflow-aware: only require outputs that the workflow declares as required.
126
+ // Fast-track skips design/plan, so spec.md and plan.md won't exist.
127
+ let requiredOutputs = phaseDefinition.requiredOutputs;
128
+ try {
129
+ const feature = getFeature(featureName);
130
+ if (feature?.workflow && feature.workflow !== 'auto') {
131
+ const wfConfig = getWorkflowConfig(feature.workflow);
132
+ if (wfConfig?.outputs?.required) {
133
+ const workflowRequired = new Set(wfConfig.outputs.required);
134
+ requiredOutputs = requiredOutputs.filter(o => workflowRequired.has(o));
135
+ }
136
+ }
137
+ } catch {
138
+ // Fall through to default requiredOutputs
139
+ }
140
+
138
141
  const missingOutputs = [];
139
- for (const output of phaseDefinition.requiredOutputs) {
142
+ for (const output of requiredOutputs) {
140
143
  if (!checkOutput(featurePath, output)) {
141
144
  missingOutputs.push(output);
142
145
  }
@@ -183,12 +186,31 @@ export function validatePhase(featureName, targetPhase) {
183
186
  // Phase eligibility
184
187
  // ─────────────────────────────────────────────────────────────────────────────
185
188
 
186
- const PHASE_ORDER = ['proposal', 'setup', 'uiux', 'design', 'clarify', 'plan', 'tasks', 'implement', 'sync'];
189
+ const PHASE_ORDER = ['proposal', 'uiux', 'design', 'plan', 'tasks', 'implement', 'sync'];
187
190
 
188
- function getNextPhase(currentPhase) {
191
+ function getNextPhase(currentPhase, featureName) {
189
192
  const idx = PHASE_ORDER.indexOf(currentPhase);
190
193
  if (idx === -1 || idx >= PHASE_ORDER.length - 1) return null;
191
- return PHASE_ORDER[idx + 1];
194
+
195
+ // Workflow-aware: skip phases not in the workflow's run list
196
+ let workflowConfig = null;
197
+ if (featureName) {
198
+ try {
199
+ const feature = getFeature(featureName);
200
+ if (feature?.workflow && feature.workflow !== 'auto') {
201
+ workflowConfig = getWorkflowConfig(feature.workflow);
202
+ }
203
+ } catch { /* fall through */ }
204
+ }
205
+
206
+ for (let i = idx + 1; i < PHASE_ORDER.length; i++) {
207
+ const candidate = PHASE_ORDER[i];
208
+ if (workflowConfig?.phases?.run && !workflowConfig.phases.run.includes(candidate)) {
209
+ continue;
210
+ }
211
+ return candidate;
212
+ }
213
+ return null;
192
214
  }
193
215
 
194
216
  /**
@@ -205,10 +227,10 @@ export function computePassRate(validationHistory) {
205
227
  // Map output type names to file paths for eligibility checks
206
228
  const OUTPUT_PATH_MAP = {
207
229
  'proposal': '0-proposal/proposal.md',
208
- 'spec': '1-design/spec.md',
209
- 'contracts': '1-design/contracts.cs',
230
+ 'spec': '2-design/spec.md',
231
+ 'contracts': '2-design/contracts.cs',
210
232
  'tasks': '4-tasks/tasks.md',
211
- 'schemaAnalysis': '1-design/schema-analysis.md',
233
+ 'schemaAnalysis': '2-design/schema-analysis.md',
212
234
  };
213
235
 
214
236
  function getMissingRequiredOutputs(featureName, phase, projectPath) {
@@ -266,7 +288,7 @@ export function checkPhaseEligibility(featureName, opts = {}) {
266
288
 
267
289
  const featureFolderPath = join(projectPath, '.morph', 'features', featureName);
268
290
  const currentPhase = feature.phase || derivePhase(featureFolderPath);
269
- const nextPhase = getNextPhase(currentPhase);
291
+ const nextPhase = getNextPhase(currentPhase, featureName);
270
292
 
271
293
  if (!nextPhase) {
272
294
  return {
@@ -1,7 +1,7 @@
1
1
  import { readFileSync, existsSync } from 'fs';
2
2
  import { join } from 'path';
3
3
 
4
- /** @typedef {'nextjs'|'blazor'|'dotnet'|'nodejs-cli'|'unknown'} StackName */
4
+ /** @typedef {'nextjs'|'dotnet'|'nodejs-cli'|'unknown'} StackName */
5
5
 
6
6
  /**
7
7
  * @typedef {Object} StackProfile
@@ -15,7 +15,7 @@ import { join } from 'path';
15
15
  * @property {'csharp'|'typescript'} contractsLanguage
16
16
  */
17
17
 
18
- const DOTNET_STACKS = new Set(['dotnet', 'blazor', 'aspnet', 'dotnet-blazor']);
18
+ const DOTNET_STACKS = new Set(['dotnet', 'aspnet']);
19
19
  const NEXTJS_STACKS = new Set(['nextjs', 'next', 'next.js']);
20
20
  const NO_VALIDATOR_STACKS = new Set(['nodejs-cli', 'node-cli', 'cli']);
21
21