@polymorphism-tech/morph-spec 4.11.1 → 4.13.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 (317) hide show
  1. package/README.md +21 -29
  2. package/bin/morph-spec.js +41 -24
  3. package/bin/task-manager.js +962 -1341
  4. package/bin/validate.js +1 -1
  5. package/claude-plugin.json +1 -1
  6. package/docs/CHEATSHEET.md +10 -11
  7. package/docs/QUICKSTART.md +15 -15
  8. package/framework/CLAUDE.md +5 -2
  9. package/framework/agents/README.md +3 -4
  10. package/framework/agents/ai-agents/ai-system-architect.md +6 -10
  11. package/framework/agents/architecture/seo-growth-hacker.md +166 -326
  12. package/framework/agents/architecture/standards-architect.md +21 -31
  13. package/framework/agents/backend/dotnet-senior.md +160 -86
  14. package/framework/agents/backend/ef-modeler.md +2 -6
  15. package/framework/agents/backend/hangfire-orchestrator.md +8 -9
  16. package/framework/agents/backend/ms-agent-expert.md +1 -1
  17. package/framework/agents/frontend/nextjs-expert.md +198 -133
  18. package/framework/agents/frontend/ui-ux-designer.md +226 -267
  19. package/framework/agents/infrastructure/infra-architect.md +191 -27
  20. package/framework/agents/integrations/clerk-auth.md +19 -26
  21. package/framework/agents/integrations/hangfire-integration.md +1 -4
  22. package/framework/agents.json +226 -1454
  23. package/framework/commands/morph-apply.md +4 -4
  24. package/framework/commands/morph-preflight.md +4 -26
  25. package/framework/commands/morph-proposal.md +19 -19
  26. package/framework/commands/morph-status.md +2 -2
  27. package/framework/commands/morph-troubleshoot.md +6 -13
  28. package/framework/hooks/README.md +1 -6
  29. package/framework/hooks/claude-code/post-tool-use/agent-complete.js +122 -0
  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/dispatch-helpers.js +17 -0
  42. package/framework/hooks/shared/phase-utils.js +4 -8
  43. package/framework/hooks/shared/state-reader.js +34 -3
  44. package/framework/phases.json +7 -45
  45. package/framework/rules/ai-agents-standards.md +15 -0
  46. package/framework/rules/asaas-standards.md +13 -0
  47. package/framework/rules/clerk-standards.md +13 -0
  48. package/framework/rules/csharp-standards.md +8 -4
  49. package/framework/rules/data-standards.md +18 -0
  50. package/framework/rules/dotnet-templates.md +87 -0
  51. package/framework/rules/frontend-standards.md +13 -13
  52. package/framework/rules/hangfire-standards.md +13 -0
  53. package/framework/rules/infrastructure-standards.md +27 -16
  54. package/framework/rules/morph-workflow.md +73 -13
  55. package/framework/rules/nextjs-standards.md +1 -0
  56. package/framework/rules/nextjs-templates.md +40 -0
  57. package/framework/rules/resend-standards.md +12 -0
  58. package/framework/rules/supabase-standards.md +29 -0
  59. package/framework/skills/README.md +6 -8
  60. package/framework/skills/level-0-meta/mcp-registry.json +21 -99
  61. package/framework/{standards/ai-agents/team-orchestration.md → skills/level-0-meta/morph-agent-teams/SKILL.md} +472 -479
  62. package/framework/skills/level-0-meta/morph-brainstorming/SKILL.md +28 -1
  63. package/framework/skills/level-0-meta/morph-checklist/SKILL.md +2 -2
  64. package/framework/skills/level-0-meta/morph-code-review/SKILL.md +1 -5
  65. package/framework/skills/level-0-meta/morph-code-review/scripts/scan-csharp.mjs +1 -1
  66. package/framework/skills/level-0-meta/morph-frontend-review/SKILL.md +23 -41
  67. package/framework/skills/level-0-meta/morph-init/SKILL.md +18 -14
  68. package/framework/skills/level-0-meta/morph-parallel-dispatch/SKILL.md +225 -0
  69. package/framework/skills/level-0-meta/morph-post-implementation/SKILL.md +20 -0
  70. package/framework/skills/level-0-meta/morph-tool-usage-guide/SKILL.md +4 -8
  71. package/framework/skills/level-0-meta/morph-tool-usage-guide/references/tools-per-phase.md +15 -59
  72. package/framework/skills/level-0-meta/morph-verification-before-completion/SKILL.md +7 -19
  73. package/framework/skills/level-0-meta/morph-verification-before-completion/scripts/check-phase-outputs.mjs +8 -8
  74. package/framework/skills/level-1-workflows/README.md +1 -1
  75. package/framework/skills/level-1-workflows/morph-phase-codebase-analysis/SKILL.md +49 -50
  76. package/framework/skills/level-1-workflows/morph-phase-design/SKILL.md +58 -124
  77. package/framework/skills/level-1-workflows/morph-phase-design/references/architecture-analysis-guide.md +5 -50
  78. package/framework/skills/level-1-workflows/morph-phase-design/references/spec-example.md +1 -1
  79. package/framework/skills/level-1-workflows/morph-phase-implement/SKILL.md +127 -159
  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 +0 -2
  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 +275 -61
  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 -2338
  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 +342 -211
  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/mcp/mcp-setup.js +28 -6
  159. package/src/commands/phase/phase-reset.js +1 -1
  160. package/src/commands/project/doctor.js +10 -32
  161. package/src/commands/project/init.js +32 -1
  162. package/src/commands/project/status.js +6 -12
  163. package/src/commands/scaffold/scaffold.js +131 -0
  164. package/src/commands/scope/escalate.js +1 -1
  165. package/src/commands/state/advance-phase.js +15 -29
  166. package/src/commands/state/state.js +20 -5
  167. package/src/commands/tasks/task.js +0 -30
  168. package/src/commands/validation/validate-feature.js +3 -10
  169. package/src/core/paths/output-schema.js +12 -13
  170. package/src/core/state/phase-state-machine.js +211 -217
  171. package/src/core/state/state-manager.js +9 -9
  172. package/src/lib/agents/agents-manager.js +2 -2
  173. package/src/lib/agents/output-collector.js +1 -2
  174. package/src/lib/detectors/design-system-detector.js +4 -4
  175. package/src/lib/detectors/index.js +1 -11
  176. package/src/lib/generators/architecture-scanner.js +640 -0
  177. package/src/lib/generators/context-generator.js +3 -3
  178. package/src/lib/generators/design-system-generator.js +508 -298
  179. package/src/lib/generators/index.js +12 -10
  180. package/src/lib/generators/metadata-extractor.js +386 -387
  181. package/src/lib/generators/recap-generator.js +4 -4
  182. package/src/lib/generators/scaffold-generator.js +317 -0
  183. package/src/lib/generators/settings-generator.js +0 -1
  184. package/src/lib/phase-chain/phase-validator.js +64 -42
  185. package/src/lib/stack/stack-profile.js +2 -2
  186. package/src/lib/standards/digest-builder.js +72 -285
  187. package/src/lib/tasks/task-parser.js +11 -5
  188. package/src/lib/validators/architecture/architecture-validator.js +259 -387
  189. package/src/lib/validators/content/content-validator.js +287 -287
  190. package/src/lib/validators/css/css-validator.js +340 -352
  191. package/src/lib/validators/design-system/design-system-validator.js +11 -5
  192. package/src/lib/validators/packages/package-validator.js +347 -360
  193. package/src/lib/validators/shared/issue-counter.js +14 -18
  194. package/src/lib/validators/validation-runner.js +3 -19
  195. package/src/scripts/setup-infra.js +1 -1
  196. package/src/utils/agents-installer.js +24 -3
  197. package/src/utils/file-copier.js +1 -0
  198. package/src/utils/hooks-installer.js +21 -19
  199. package/src/utils/skills-installer.js +178 -178
  200. package/framework/agents/architecture/prompt-engineer.md +0 -195
  201. package/framework/agents/backend/api-designer.md +0 -106
  202. package/framework/agents/frontend/blazor-builder.md +0 -229
  203. package/framework/agents/frontend/nextjs-ui-specialist.md +0 -218
  204. package/framework/agents/infrastructure/azure-architect.md +0 -150
  205. package/framework/agents/infrastructure/azure-deploy-specialist.md +0 -707
  206. package/framework/agents/infrastructure/bicep-architect.md +0 -132
  207. package/framework/agents/infrastructure/container-specialist.md +0 -137
  208. package/framework/agents/infrastructure/devops-engineer.md +0 -126
  209. package/framework/agents/integrations/azure-identity.md +0 -148
  210. package/framework/agents/quality/code-analyzer.md +0 -239
  211. package/framework/agents/quality/testing-specialist.md +0 -130
  212. package/framework/hooks/claude-code/notification/approval-reminder.js +0 -57
  213. package/framework/hooks/claude-code/post-tool-use/context-refresh.js +0 -109
  214. package/framework/hooks/claude-code/post-tool-use/skill-reminder.js +0 -78
  215. package/framework/index/troubleshooting-index.json +0 -184
  216. package/framework/rules/testing-standards.md +0 -14
  217. package/framework/skills/level-0-meta/morph-replicate/SKILL.md +0 -230
  218. package/framework/skills/level-0-meta/morph-replicate/references/blazor-html-mapping.md +0 -70
  219. package/framework/skills/level-1-workflows/morph-phase-clarify/SKILL.md +0 -256
  220. package/framework/skills/level-1-workflows/morph-phase-clarify/references/clarifications-example.md +0 -117
  221. package/framework/skills/level-1-workflows/morph-phase-setup/SKILL.md +0 -269
  222. package/framework/standards/ai-agents/blazor-ui.md +0 -364
  223. package/framework/standards/architecture/ddd/aggregates.md +0 -120
  224. package/framework/standards/architecture/ddd/bounded-contexts.md +0 -105
  225. package/framework/standards/architecture/ddd/complexity-levels.md +0 -108
  226. package/framework/standards/architecture/ddd/entities.md +0 -99
  227. package/framework/standards/architecture/ddd/ubiquitous-language.md +0 -58
  228. package/framework/standards/architecture/ddd/value-objects.md +0 -124
  229. package/framework/standards/backend/api/minimal-api.md +0 -494
  230. package/framework/standards/backend/api/rest.md +0 -492
  231. package/framework/standards/backend/authentication/passkeys.md +0 -428
  232. package/framework/standards/backend/database/ef-core.md +0 -199
  233. package/framework/standards/backend/database/migrations.md +0 -393
  234. package/framework/standards/backend/database/repository-patterns.md +0 -528
  235. package/framework/standards/backend/dotnet/async.md +0 -366
  236. package/framework/standards/backend/dotnet/core.md +0 -117
  237. package/framework/standards/backend/dotnet/di.md +0 -439
  238. package/framework/standards/backend/dotnet/program-cs-checklist.md +0 -92
  239. package/framework/standards/context/analytics.md +0 -96
  240. package/framework/standards/context/bundles.md +0 -110
  241. package/framework/standards/context/priming.md +0 -78
  242. package/framework/standards/core/architecture.md +0 -185
  243. package/framework/standards/core/coding.md +0 -214
  244. package/framework/standards/core/git-branching-strategy.md +0 -403
  245. package/framework/standards/core/git.md +0 -185
  246. package/framework/standards/core/testing.md +0 -295
  247. package/framework/standards/data/nosql/blob-storage.md +0 -102
  248. package/framework/standards/data/vector-search/azure-ai-search.md +0 -121
  249. package/framework/standards/frontend/blazor/design-checklist.md +0 -222
  250. package/framework/standards/frontend/blazor/fluent-ui-setup.md +0 -595
  251. package/framework/standards/frontend/blazor/fluent-ui.md +0 -137
  252. package/framework/standards/frontend/blazor/html-conversion.md +0 -184
  253. package/framework/standards/frontend/blazor/lifecycle.md +0 -195
  254. package/framework/standards/frontend/blazor/pitfalls.md +0 -198
  255. package/framework/standards/frontend/blazor/state.md +0 -191
  256. package/framework/standards/frontend/design-system/aesthetic-direction.md +0 -213
  257. package/framework/standards/infrastructure/azure/azure.md +0 -624
  258. package/framework/standards/infrastructure/azure/bicep/bicep-patterns.md +0 -422
  259. package/framework/standards/infrastructure/azure/devops/azure-devops-setup.md +0 -516
  260. package/framework/standards/infrastructure/azure/devops/local-development.md +0 -520
  261. package/framework/standards/infrastructure/azure/services/functions.md +0 -486
  262. package/framework/standards/infrastructure/azure/services/service-bus.md +0 -459
  263. package/framework/standards/infrastructure/azure/services/storage.md +0 -407
  264. package/framework/standards/infrastructure/vercel/vercel-database.md +0 -106
  265. package/framework/standards/integration/api/graphql.md +0 -91
  266. package/framework/standards/integration/api/grpc.md +0 -114
  267. package/framework/standards/integration/api/rest-design.md +0 -95
  268. package/framework/standards/integration/event-driven/cqrs.md +0 -101
  269. package/framework/standards/integration/event-driven/event-sourcing.md +0 -124
  270. package/framework/standards/integration/event-driven/service-bus.md +0 -95
  271. package/framework/standards/observability/logging.md +0 -131
  272. package/framework/standards/observability/metrics.md +0 -121
  273. package/framework/standards/observability/monitoring.md +0 -114
  274. package/framework/standards/observability/tracing.md +0 -132
  275. package/framework/standards/workflows/parallel-execution.md +0 -112
  276. package/framework/standards/workflows/thread-management.md +0 -113
  277. package/framework/templates/code/dotnet/backend/service.cs +0 -139
  278. package/framework/templates/code/dotnet/contracts/Commands.cs +0 -74
  279. package/framework/templates/code/dotnet/contracts/Entities.cs +0 -25
  280. package/framework/templates/code/dotnet/contracts/Queries.cs +0 -74
  281. package/framework/templates/code/dotnet/contracts/api-contracts.cs +0 -173
  282. package/framework/templates/code/dotnet/contracts/contracts-level1.cs +0 -69
  283. package/framework/templates/code/dotnet/contracts/contracts-level2.cs +0 -86
  284. package/framework/templates/code/dotnet/contracts/contracts-level3.cs +0 -41
  285. package/framework/templates/code/dotnet/frontend/component.razor +0 -239
  286. package/framework/templates/infrastructure/azure/Dockerfile.example +0 -82
  287. package/framework/templates/infrastructure/azure/README.md +0 -286
  288. package/framework/templates/infrastructure/azure/app-insights.bicep +0 -63
  289. package/framework/templates/infrastructure/azure/app-service.bicep +0 -164
  290. package/framework/templates/infrastructure/azure/container-app-env.bicep +0 -49
  291. package/framework/templates/infrastructure/azure/container-app.bicep +0 -156
  292. package/framework/templates/infrastructure/azure/deploy-checklist.md +0 -426
  293. package/framework/templates/infrastructure/azure/deploy.ps1 +0 -229
  294. package/framework/templates/infrastructure/azure/deploy.sh +0 -208
  295. package/framework/templates/infrastructure/azure/key-vault.bicep +0 -91
  296. package/framework/templates/infrastructure/azure/main.bicep +0 -189
  297. package/framework/templates/infrastructure/azure/parameters.dev.json +0 -29
  298. package/framework/templates/infrastructure/azure/parameters.prod.json +0 -29
  299. package/framework/templates/infrastructure/azure/parameters.staging.json +0 -29
  300. package/framework/templates/infrastructure/azure/sql-database.bicep +0 -103
  301. package/framework/templates/infrastructure/azure/storage.bicep +0 -106
  302. package/framework/templates/infrastructure/github/actions/azure-auth/action.yml.hbs +0 -22
  303. package/framework/templates/infrastructure/github/workflows/deploy-azure-app-service.yml.hbs +0 -61
  304. package/framework/templates/integrations/azure-identity-config.cs +0 -288
  305. package/framework/templates/project-structure/dotnet-ddd.md +0 -70
  306. package/framework/templates/saas/subscription.cs +0 -347
  307. package/framework/templates/saas/tenant.cs +0 -338
  308. package/framework/templates/ui/FluentDesignTheme.cs +0 -149
  309. package/framework/templates/ui/MudTheme.cs +0 -281
  310. package/framework/workflows/configs/nodejs-cli.json +0 -40
  311. package/src/commands/standards/context-budget.js +0 -89
  312. package/src/lib/standards/index.js +0 -7
  313. package/src/lib/standards/standards-context-injector.js +0 -302
  314. package/src/lib/validators/blazor/blazor-concurrency-analyzer.js +0 -316
  315. package/src/lib/validators/blazor/blazor-state-validator.js +0 -279
  316. package/src/lib/validators/blazor/blazor-validator.js +0 -369
  317. 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