@polymorphism-tech/morph-spec 4.7.2 → 4.8.4

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 (342) hide show
  1. package/LICENSE +1 -2
  2. package/README.md +379 -414
  3. package/bin/morph-spec.js +57 -394
  4. package/bin/validate.js +2 -26
  5. package/claude-plugin.json +2 -2
  6. package/docs/CHEATSHEET.md +203 -221
  7. package/docs/QUICKSTART.md +2 -8
  8. package/framework/CLAUDE.md +1 -1
  9. package/framework/commands/morph-proposal.md +3 -3
  10. package/framework/hooks/README.md +2 -5
  11. package/framework/hooks/claude-code/pre-tool-use/protect-readonly-files.js +4 -55
  12. package/framework/hooks/claude-code/session-start/inject-morph-context.js +20 -5
  13. package/framework/hooks/claude-code/statusline.py +6 -1
  14. package/framework/hooks/dev/check-sync-health.js +117 -0
  15. package/framework/hooks/dev/guard-version-numbers.js +57 -0
  16. package/framework/hooks/dev/sync-standards-registry.js +60 -0
  17. package/framework/hooks/dev/sync-template-registry.js +60 -0
  18. package/framework/hooks/dev/validate-skill-format.js +70 -0
  19. package/framework/hooks/dev/validate-standard-format.js +73 -0
  20. package/framework/hooks/shared/payload-utils.js +39 -0
  21. package/framework/hooks/shared/state-reader.js +25 -1
  22. package/framework/rules/morph-workflow.md +1 -1
  23. package/framework/skills/level-0-meta/morph-init/SKILL.md +216 -0
  24. package/framework/skills/level-0-meta/morph-replicate/SKILL.md +4 -4
  25. package/framework/skills/level-0-meta/tool-usage-guide/SKILL.md +4 -4
  26. package/framework/skills/level-0-meta/verification-before-completion/SKILL.md +1 -1
  27. package/framework/skills/level-1-workflows/phase-clarify/SKILL.md +192 -191
  28. package/framework/skills/level-1-workflows/phase-codebase-analysis/SKILL.md +181 -180
  29. package/framework/skills/level-1-workflows/phase-design/SKILL.md +339 -338
  30. package/framework/skills/level-1-workflows/phase-implement/SKILL.md +254 -253
  31. package/framework/skills/level-1-workflows/phase-setup/SKILL.md +168 -170
  32. package/framework/skills/level-1-workflows/phase-tasks/SKILL.md +284 -283
  33. package/framework/skills/level-1-workflows/phase-uiux/SKILL.md +246 -245
  34. package/framework/templates/examples/design-system-examples.md +1 -1
  35. package/framework/templates/ui/FluentDesignTheme.cs +1 -1
  36. package/framework/templates/ui/MudTheme.cs +1 -1
  37. package/framework/templates/ui/design-system.css +1 -1
  38. package/package.json +7 -5
  39. package/src/commands/agents/index.js +1 -2
  40. package/src/commands/index.js +13 -16
  41. package/src/commands/project/doctor.js +100 -14
  42. package/src/commands/project/index.js +7 -10
  43. package/src/commands/project/init.js +398 -528
  44. package/src/commands/project/install-plugin-cmd.js +28 -0
  45. package/src/commands/project/setup-infra-cmd.js +12 -0
  46. package/src/commands/project/tutorial.js +115 -0
  47. package/src/commands/state/approve.js +213 -221
  48. package/src/commands/state/index.js +0 -1
  49. package/src/commands/state/state.js +337 -365
  50. package/src/commands/templates/index.js +0 -4
  51. package/src/commands/trust/trust.js +1 -93
  52. package/src/commands/utils/index.js +1 -5
  53. package/src/commands/validation/index.js +1 -5
  54. package/src/core/registry/command-registry.js +11 -285
  55. package/src/core/state/state-manager.js +5 -2
  56. package/src/lib/detectors/index.js +81 -87
  57. package/src/lib/detectors/structure-detector.js +275 -273
  58. package/src/lib/generators/recap-generator.js +232 -225
  59. package/src/scripts/global-install.js +34 -0
  60. package/src/scripts/install-plugin.js +126 -0
  61. package/src/scripts/setup-infra.js +203 -0
  62. package/src/utils/agents-installer.js +10 -1
  63. package/src/utils/hooks-installer.js +66 -3
  64. package/.morph/.morphversion +0 -5
  65. package/.morph/analytics/threads-log.jsonl +0 -5
  66. package/.morph/config/config.json +0 -8
  67. package/.morph/framework/agents.json +0 -1815
  68. package/.morph/framework/hooks/README.md +0 -205
  69. package/.morph/framework/hooks/claude-code/notification/approval-reminder.js +0 -54
  70. package/.morph/framework/hooks/claude-code/post-tool-use/dispatch.js +0 -83
  71. package/.morph/framework/hooks/claude-code/post-tool-use/handle-tool-failure.js +0 -42
  72. package/.morph/framework/hooks/claude-code/pre-compact/save-morph-context.js +0 -61
  73. package/.morph/framework/hooks/claude-code/pre-tool-use/enforce-phase-writes.js +0 -71
  74. package/.morph/framework/hooks/claude-code/pre-tool-use/protect-readonly-files.js +0 -58
  75. package/.morph/framework/hooks/claude-code/pre-tool-use/protect-spec-files.js +0 -64
  76. package/.morph/framework/hooks/claude-code/session-start/inject-morph-context.js +0 -94
  77. package/.morph/framework/hooks/claude-code/statusline.py +0 -538
  78. package/.morph/framework/hooks/claude-code/statusline.sh +0 -7
  79. package/.morph/framework/hooks/claude-code/stop/validate-completion.js +0 -88
  80. package/.morph/framework/hooks/claude-code/user-prompt/enrich-prompt.js +0 -91
  81. package/.morph/framework/hooks/git/commit-msg/conventional-commits.sh +0 -33
  82. package/.morph/framework/hooks/git/pre-commit/agents.sh +0 -25
  83. package/.morph/framework/hooks/git/pre-commit/orchestrator.sh +0 -64
  84. package/.morph/framework/hooks/git/pre-commit/specs.sh +0 -50
  85. package/.morph/framework/hooks/git/pre-push/run-tests.sh +0 -44
  86. package/.morph/framework/hooks/shared/hook-response.js +0 -45
  87. package/.morph/framework/hooks/shared/phase-utils.js +0 -129
  88. package/.morph/framework/hooks/shared/state-reader.js +0 -138
  89. package/.morph/framework/hooks/shared/stdin-reader.js +0 -26
  90. package/.morph/framework/standards/STANDARDS.json +0 -933
  91. package/.morph/framework/standards/ai-agents/blazor-ui.md +0 -364
  92. package/.morph/framework/standards/ai-agents/production.md +0 -415
  93. package/.morph/framework/standards/ai-agents/setup.md +0 -418
  94. package/.morph/framework/standards/ai-agents/team-orchestration.md +0 -479
  95. package/.morph/framework/standards/ai-agents/workflows.md +0 -354
  96. package/.morph/framework/standards/architecture/ddd/aggregates.md +0 -120
  97. package/.morph/framework/standards/architecture/ddd/bounded-contexts.md +0 -105
  98. package/.morph/framework/standards/architecture/ddd/complexity-levels.md +0 -108
  99. package/.morph/framework/standards/architecture/ddd/entities.md +0 -99
  100. package/.morph/framework/standards/architecture/ddd/ubiquitous-language.md +0 -58
  101. package/.morph/framework/standards/architecture/ddd/value-objects.md +0 -124
  102. package/.morph/framework/standards/backend/api/minimal-api.md +0 -494
  103. package/.morph/framework/standards/backend/api/rest.md +0 -492
  104. package/.morph/framework/standards/backend/api/validation.md +0 -88
  105. package/.morph/framework/standards/backend/authentication/passkeys.md +0 -428
  106. package/.morph/framework/standards/backend/database/ef-core.md +0 -199
  107. package/.morph/framework/standards/backend/database/migrations.md +0 -393
  108. package/.morph/framework/standards/backend/database/postgresql/database.md +0 -352
  109. package/.morph/framework/standards/backend/database/repository-patterns.md +0 -528
  110. package/.morph/framework/standards/backend/database/vector-search-rag.md +0 -541
  111. package/.morph/framework/standards/backend/dotnet/async.md +0 -366
  112. package/.morph/framework/standards/backend/dotnet/core.md +0 -117
  113. package/.morph/framework/standards/backend/dotnet/di.md +0 -439
  114. package/.morph/framework/standards/backend/dotnet/program-cs-checklist.md +0 -92
  115. package/.morph/framework/standards/backend/integrations/asaas/asaas-api.md +0 -216
  116. package/.morph/framework/standards/backend/integrations/clerk/clerk-auth.md +0 -290
  117. package/.morph/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +0 -350
  118. package/.morph/framework/standards/backend/integrations/resend/resend-email.md +0 -385
  119. package/.morph/framework/standards/context/analytics.md +0 -96
  120. package/.morph/framework/standards/context/bundles.md +0 -110
  121. package/.morph/framework/standards/context/priming.md +0 -78
  122. package/.morph/framework/standards/core/architecture.md +0 -185
  123. package/.morph/framework/standards/core/coding.md +0 -214
  124. package/.morph/framework/standards/core/git-branching-strategy.md +0 -403
  125. package/.morph/framework/standards/core/git.md +0 -185
  126. package/.morph/framework/standards/core/testing.md +0 -295
  127. package/.morph/framework/standards/data/nosql/blob-storage.md +0 -102
  128. package/.morph/framework/standards/data/nosql/cache/redis.md +0 -97
  129. package/.morph/framework/standards/data/nosql/cosmos-db.md +0 -118
  130. package/.morph/framework/standards/data/vector-search/azure-ai-search.md +0 -121
  131. package/.morph/framework/standards/data/vector-search/rag-chunking.md +0 -104
  132. package/.morph/framework/standards/frontend/blazor/design-checklist.md +0 -222
  133. package/.morph/framework/standards/frontend/blazor/fluent-ui-setup.md +0 -595
  134. package/.morph/framework/standards/frontend/blazor/fluent-ui.md +0 -137
  135. package/.morph/framework/standards/frontend/blazor/html-conversion.md +0 -184
  136. package/.morph/framework/standards/frontend/blazor/lifecycle.md +0 -195
  137. package/.morph/framework/standards/frontend/blazor/pitfalls.md +0 -198
  138. package/.morph/framework/standards/frontend/blazor/state.md +0 -191
  139. package/.morph/framework/standards/frontend/design-system/animations.md +0 -151
  140. package/.morph/framework/standards/frontend/design-system/naming.md +0 -64
  141. package/.morph/framework/standards/frontend/nextjs/app-router.md +0 -123
  142. package/.morph/framework/standards/frontend/nextjs/components.md +0 -132
  143. package/.morph/framework/standards/frontend/nextjs/data-fetching.md +0 -126
  144. package/.morph/framework/standards/frontend/nextjs/forms.md +0 -128
  145. package/.morph/framework/standards/frontend/nextjs/naming-conventions.md +0 -67
  146. package/.morph/framework/standards/frontend/nextjs/nextjs-patterns.md +0 -215
  147. package/.morph/framework/standards/frontend/nextjs/project-structure.md +0 -102
  148. package/.morph/framework/standards/frontend/nextjs/state-management.md +0 -72
  149. package/.morph/framework/standards/frontend/nextjs/testing.md +0 -111
  150. package/.morph/framework/standards/infrastructure/azure/azure.md +0 -624
  151. package/.morph/framework/standards/infrastructure/azure/bicep/bicep-patterns.md +0 -422
  152. package/.morph/framework/standards/infrastructure/azure/devops/azure-devops-setup.md +0 -516
  153. package/.morph/framework/standards/infrastructure/azure/devops/local-development.md +0 -520
  154. package/.morph/framework/standards/infrastructure/azure/services/functions.md +0 -486
  155. package/.morph/framework/standards/infrastructure/azure/services/service-bus.md +0 -459
  156. package/.morph/framework/standards/infrastructure/azure/services/storage.md +0 -407
  157. package/.morph/framework/standards/infrastructure/docker/easypanel-deploy.md +0 -196
  158. package/.morph/framework/standards/infrastructure/supabase/mcp-setup.md +0 -252
  159. package/.morph/framework/standards/infrastructure/supabase/supabase-auth.md +0 -176
  160. package/.morph/framework/standards/infrastructure/supabase/supabase-pgvector.md +0 -169
  161. package/.morph/framework/standards/infrastructure/supabase/supabase-rls.md +0 -184
  162. package/.morph/framework/standards/infrastructure/supabase/supabase-storage.md +0 -153
  163. package/.morph/framework/standards/integration/api/graphql.md +0 -91
  164. package/.morph/framework/standards/integration/api/grpc.md +0 -114
  165. package/.morph/framework/standards/integration/api/rest-design.md +0 -95
  166. package/.morph/framework/standards/integration/event-driven/cqrs.md +0 -101
  167. package/.morph/framework/standards/integration/event-driven/event-sourcing.md +0 -124
  168. package/.morph/framework/standards/integration/event-driven/service-bus.md +0 -95
  169. package/.morph/framework/standards/integration/mcp/mcp-tools.md +0 -384
  170. package/.morph/framework/standards/observability/logging.md +0 -131
  171. package/.morph/framework/standards/observability/metrics.md +0 -121
  172. package/.morph/framework/standards/observability/monitoring.md +0 -114
  173. package/.morph/framework/standards/observability/tracing.md +0 -132
  174. package/.morph/framework/standards/workflows/parallel-execution.md +0 -112
  175. package/.morph/framework/standards/workflows/thread-management.md +0 -113
  176. package/.morph/framework/templates/.idea/morph-templates.xml +0 -92
  177. package/.morph/framework/templates/.vscode/morph-templates.code-snippets +0 -186
  178. package/.morph/framework/templates/IDE-SNIPPETS.md +0 -266
  179. package/.morph/framework/templates/README.md +0 -814
  180. package/.morph/framework/templates/REGISTRY.json +0 -1888
  181. package/.morph/framework/templates/code/dotnet/backend/repository.cs +0 -141
  182. package/.morph/framework/templates/code/dotnet/backend/service.cs +0 -139
  183. package/.morph/framework/templates/code/dotnet/contracts/Commands.cs +0 -74
  184. package/.morph/framework/templates/code/dotnet/contracts/Entities.cs +0 -25
  185. package/.morph/framework/templates/code/dotnet/contracts/Queries.cs +0 -74
  186. package/.morph/framework/templates/code/dotnet/contracts/README.md +0 -74
  187. package/.morph/framework/templates/code/dotnet/contracts/api-contracts.cs +0 -173
  188. package/.morph/framework/templates/code/dotnet/contracts/contracts-level1.cs +0 -69
  189. package/.morph/framework/templates/code/dotnet/contracts/contracts-level2.cs +0 -86
  190. package/.morph/framework/templates/code/dotnet/contracts/contracts-level3.cs +0 -41
  191. package/.morph/framework/templates/code/dotnet/database/migration.cs +0 -83
  192. package/.morph/framework/templates/code/dotnet/frontend/component.razor +0 -239
  193. package/.morph/framework/templates/code/dotnet/jobs/agent.cs +0 -163
  194. package/.morph/framework/templates/code/dotnet/jobs/job.cs +0 -171
  195. package/.morph/framework/templates/code/dotnet/test.cs +0 -239
  196. package/.morph/framework/templates/code/sql/rls-policy.sql +0 -57
  197. package/.morph/framework/templates/code/sql/supabase-migration.sql +0 -100
  198. package/.morph/framework/templates/code/sql/supabase-migration.template.sql +0 -113
  199. package/.morph/framework/templates/code/typescript/contracts.ts +0 -168
  200. package/.morph/framework/templates/context/CONTEXT-FEATURE.md +0 -276
  201. package/.morph/framework/templates/context/CONTEXT.md +0 -181
  202. package/.morph/framework/templates/docs/clarifications.md +0 -253
  203. package/.morph/framework/templates/docs/onboarding.md +0 -123
  204. package/.morph/framework/templates/docs/proposal.md +0 -182
  205. package/.morph/framework/templates/docs/schema-analysis.md +0 -119
  206. package/.morph/framework/templates/docs/spec.md +0 -198
  207. package/.morph/framework/templates/docs/ui-components.md +0 -124
  208. package/.morph/framework/templates/docs/ui-design-system.md +0 -76
  209. package/.morph/framework/templates/docs/ui-flows.md +0 -167
  210. package/.morph/framework/templates/docs/ui-mockups.md +0 -98
  211. package/.morph/framework/templates/docs/user-stories.md +0 -34
  212. package/.morph/framework/templates/examples/design-system-examples.md +0 -357
  213. package/.morph/framework/templates/examples/spec-examples.md +0 -90
  214. package/.morph/framework/templates/feature/decisions.md +0 -187
  215. package/.morph/framework/templates/feature/recap.md +0 -146
  216. package/.morph/framework/templates/feature/tasks.md +0 -199
  217. package/.morph/framework/templates/frontend/nextjs/Dockerfile.nextjs.hbs +0 -43
  218. package/.morph/framework/templates/frontend/nextjs/client-component.tsx.hbs +0 -26
  219. package/.morph/framework/templates/frontend/nextjs/env.mjs.hbs +0 -32
  220. package/.morph/framework/templates/frontend/nextjs/feature-form.tsx.hbs +0 -56
  221. package/.morph/framework/templates/frontend/nextjs/page.tsx.hbs +0 -22
  222. package/.morph/framework/templates/frontend/nextjs/tsconfig.json.hbs +0 -26
  223. package/.morph/framework/templates/frontend/nextjs/use-feature.ts.hbs +0 -54
  224. package/.morph/framework/templates/infrastructure/azure/Dockerfile.example +0 -82
  225. package/.morph/framework/templates/infrastructure/azure/README.md +0 -286
  226. package/.morph/framework/templates/infrastructure/azure/app-insights.bicep +0 -63
  227. package/.morph/framework/templates/infrastructure/azure/app-service.bicep +0 -164
  228. package/.morph/framework/templates/infrastructure/azure/container-app-env.bicep +0 -49
  229. package/.morph/framework/templates/infrastructure/azure/container-app.bicep +0 -156
  230. package/.morph/framework/templates/infrastructure/azure/deploy-checklist.md +0 -426
  231. package/.morph/framework/templates/infrastructure/azure/deploy.ps1 +0 -229
  232. package/.morph/framework/templates/infrastructure/azure/deploy.sh +0 -208
  233. package/.morph/framework/templates/infrastructure/azure/key-vault.bicep +0 -91
  234. package/.morph/framework/templates/infrastructure/azure/main.bicep +0 -189
  235. package/.morph/framework/templates/infrastructure/azure/parameters.dev.json +0 -29
  236. package/.morph/framework/templates/infrastructure/azure/parameters.prod.json +0 -29
  237. package/.morph/framework/templates/infrastructure/azure/parameters.staging.json +0 -29
  238. package/.morph/framework/templates/infrastructure/azure/sql-database.bicep +0 -103
  239. package/.morph/framework/templates/infrastructure/azure/storage.bicep +0 -106
  240. package/.morph/framework/templates/infrastructure/docker/Dockerfile.template +0 -58
  241. package/.morph/framework/templates/infrastructure/docker/docker-compose.template.yml +0 -67
  242. package/.morph/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +0 -38
  243. package/.morph/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +0 -48
  244. package/.morph/framework/templates/infrastructure/docker/easypanel.template.json +0 -54
  245. package/.morph/framework/templates/infrastructure/github/README.md +0 -593
  246. package/.morph/framework/templates/infrastructure/github/actions/azure-auth/action.yml.hbs +0 -22
  247. package/.morph/framework/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +0 -45
  248. package/.morph/framework/templates/infrastructure/github/actions/health-check/action.yml.hbs +0 -27
  249. package/.morph/framework/templates/infrastructure/github/workflows/deploy-azure-app-service.yml.hbs +0 -61
  250. package/.morph/framework/templates/infrastructure/github/workflows/deploy-easypanel.yml.hbs +0 -31
  251. package/.morph/framework/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +0 -59
  252. package/.morph/framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +0 -39
  253. package/.morph/framework/templates/integrations/asaas-client.cs +0 -387
  254. package/.morph/framework/templates/integrations/asaas-webhook.cs +0 -351
  255. package/.morph/framework/templates/integrations/azure-identity-config.cs +0 -288
  256. package/.morph/framework/templates/integrations/clerk-config.cs +0 -258
  257. package/.morph/framework/templates/meta-prompts/fusion/fusion-agent.md +0 -76
  258. package/.morph/framework/templates/meta-prompts/fusion/fusion-aggregator.md +0 -100
  259. package/.morph/framework/templates/meta-prompts/hops/hop-retry.md +0 -78
  260. package/.morph/framework/templates/meta-prompts/hops/hop-validation.md +0 -97
  261. package/.morph/framework/templates/meta-prompts/hops/hop-wrapper.md +0 -36
  262. package/.morph/framework/templates/meta-prompts/parallel-workers/parallel-coordinator.md +0 -113
  263. package/.morph/framework/templates/meta-prompts/parallel-workers/parallel-worker.md +0 -80
  264. package/.morph/framework/templates/meta-prompts/squad-leaders/backend-squad.md +0 -90
  265. package/.morph/framework/templates/meta-prompts/squad-leaders/frontend-squad.md +0 -126
  266. package/.morph/framework/templates/meta-prompts/squad-leaders/squad-leader.md +0 -43
  267. package/.morph/framework/templates/meta-prompts/validators/checkpoint-validator.md +0 -107
  268. package/.morph/framework/templates/meta-prompts/validators/pre-commit-validator.md +0 -95
  269. package/.morph/framework/templates/project-structure/dotnet-ddd.md +0 -70
  270. package/.morph/framework/templates/saas/subscription.cs +0 -347
  271. package/.morph/framework/templates/saas/tenant.cs +0 -338
  272. package/.morph/framework/templates/state.template.json +0 -17
  273. package/.morph/framework/templates/ui/FluentDesignTheme.cs +0 -149
  274. package/.morph/framework/templates/ui/MudTheme.cs +0 -281
  275. package/.morph/framework/templates/ui/design-system.css +0 -226
  276. package/.morph/logs/tool-failures.log +0 -17
  277. package/.morph/memory/pre-compact-2026-02-24T17-43-30-049Z.json +0 -16
  278. package/.morph/plans/eager-watching-bunny.md +0 -105
  279. package/.morph/plans/temporal-seeking-nebula.md +0 -45
  280. package/.morph/state.json +0 -48
  281. package/CLAUDE.md +0 -77
  282. package/docs/ARCHITECTURE.md +0 -331
  283. package/docs/COMMAND-FLOWS.md +0 -368
  284. package/docs/claude-alignment-report.md +0 -137
  285. package/docs/examples/order-management/contracts.cs +0 -84
  286. package/docs/examples/order-management/proposal.md +0 -24
  287. package/docs/examples/order-management/spec.md +0 -162
  288. package/docs/plans/2026-02-22-claude-docs-morph-alignment-analysis.md +0 -512
  289. package/docs/plans/2026-02-22-claude-settings.md +0 -515
  290. package/docs/plans/2026-02-22-morph-cc-alignment-impl.md +0 -728
  291. package/docs/plans/2026-02-22-morph-spec-next.md +0 -478
  292. package/docs/plans/2026-02-22-native-alignment-design.md +0 -199
  293. package/docs/plans/2026-02-22-native-alignment-impl.md +0 -925
  294. package/docs/plans/2026-02-22-native-enrichment-design.md +0 -244
  295. package/docs/plans/2026-02-22-native-enrichment.md +0 -735
  296. package/docs/plans/2026-02-23-ddd-architecture-refactor.md +0 -1153
  297. package/docs/plans/2026-02-23-ddd-nextsteps.md +0 -682
  298. package/docs/plans/2026-02-23-infra-architect-refactor.md +0 -437
  299. package/docs/plans/2026-02-23-nextjs-code-review-design.md +0 -156
  300. package/docs/plans/2026-02-23-nextjs-code-review-impl.md +0 -1254
  301. package/docs/plans/2026-02-23-nextjs-standards-design.md +0 -149
  302. package/docs/plans/2026-02-23-nextjs-standards-impl.md +0 -1846
  303. package/scripts/generate-refs.js +0 -336
  304. package/scripts/generate-standards-registry.js +0 -44
  305. package/scripts/scan-nextjs.mjs +0 -169
  306. package/scripts/validate-real.mjs +0 -255
  307. package/src/commands/feature/create-story.js +0 -362
  308. package/src/commands/feature/index.js +0 -6
  309. package/src/commands/feature/shard-spec.js +0 -225
  310. package/src/commands/feature/sprint-status.js +0 -250
  311. package/src/commands/generation/generate-onboarding.js +0 -169
  312. package/src/commands/generation/generate.js +0 -276
  313. package/src/commands/generation/index.js +0 -5
  314. package/src/commands/learning/capture-pattern.js +0 -121
  315. package/src/commands/learning/index.js +0 -5
  316. package/src/commands/learning/search-patterns.js +0 -126
  317. package/src/commands/mcp/mcp.js +0 -102
  318. package/src/commands/project/changes.js +0 -66
  319. package/src/commands/project/cost.js +0 -179
  320. package/src/commands/project/diff.js +0 -278
  321. package/src/commands/project/revert.js +0 -173
  322. package/src/commands/project/standards.js +0 -80
  323. package/src/commands/project/sync.js +0 -167
  324. package/src/commands/project/update-agents.js +0 -23
  325. package/src/commands/state/rollback-phase.js +0 -185
  326. package/src/commands/templates/template-customize.js +0 -87
  327. package/src/commands/templates/template-list.js +0 -114
  328. package/src/commands/templates/template-show.js +0 -129
  329. package/src/commands/templates/template-validate.js +0 -91
  330. package/src/commands/utils/troubleshoot.js +0 -222
  331. package/src/commands/validation/analyze-blazor-concurrency.js +0 -193
  332. package/src/commands/validation/lint-fluent.js +0 -352
  333. package/src/commands/validation/validate-blazor-state.js +0 -210
  334. package/src/commands/validation/validate-blazor.js +0 -156
  335. package/src/commands/validation/validate-css.js +0 -84
  336. package/src/lib/detectors/conversation-analyzer.js +0 -163
  337. package/src/lib/learning/index.js +0 -7
  338. package/src/lib/learning/learning-system.js +0 -520
  339. package/src/lib/troubleshooting/index.js +0 -8
  340. package/src/lib/troubleshooting/troubleshoot-grep.js +0 -198
  341. package/src/lib/troubleshooting/troubleshoot-index.js +0 -144
  342. package/src/llm/environment-detector.js +0 -43
@@ -1,66 +0,0 @@
1
- /**
2
- * Changes Command
3
- *
4
- * Lists files created/modified by a feature, grouped by phase.
5
- */
6
-
7
- import chalk from 'chalk';
8
- import { logger } from '../../utils/logger.js';
9
- import { getFileChanges } from '../../core/state/state-manager.js';
10
-
11
- export async function changesCommand(feature, options = {}) {
12
- if (!feature) {
13
- logger.error('Usage: morph-spec changes <feature>');
14
- process.exit(1);
15
- }
16
-
17
- try {
18
- const grouped = getFileChanges(feature, { groupByPhase: true });
19
-
20
- if (options.json) {
21
- console.log(JSON.stringify(grouped, null, 2));
22
- return;
23
- }
24
-
25
- const phases = Object.keys(grouped);
26
-
27
- if (phases.length === 0) {
28
- logger.warn(`No file changes tracked for feature '${feature}'.`);
29
- return;
30
- }
31
-
32
- logger.header(`File Changes — ${feature}`);
33
-
34
- let totalFiles = 0;
35
-
36
- for (const phase of phases) {
37
- const changes = grouped[phase];
38
- totalFiles += changes.length;
39
-
40
- console.log(chalk.cyan(`\n Phase: ${phase} (${changes.length} files)`));
41
- console.log(' ' + '─'.repeat(50));
42
-
43
- for (const change of changes) {
44
- const actionIcon = {
45
- created: chalk.green('+'),
46
- modified: chalk.yellow('~'),
47
- deleted: chalk.red('-')
48
- }[change.action] || ' ';
49
-
50
- const timestamp = change.timestamp
51
- ? chalk.dim(` (${new Date(change.timestamp).toLocaleDateString()})`)
52
- : '';
53
-
54
- console.log(` ${actionIcon} ${change.path}${timestamp}`);
55
- }
56
- }
57
-
58
- logger.blank();
59
- logger.dim(`Total: ${totalFiles} file(s) across ${phases.length} phase(s)`);
60
- logger.blank();
61
-
62
- } catch (error) {
63
- logger.error(error.message);
64
- process.exit(1);
65
- }
66
- }
@@ -1,179 +0,0 @@
1
- /**
2
- * MORPH-SPEC Cost Tracking Command
3
- *
4
- * Track and estimate costs (token usage, Azure resources) across phases.
5
- *
6
- * Usage:
7
- * morph-spec cost <feature-name>
8
- * morph-spec cost <feature-name> --json
9
- */
10
-
11
- import chalk from 'chalk';
12
- import { getFeature, loadState, saveState } from '../../core/state/state-manager.js';
13
-
14
- /**
15
- * Phase cost weights (relative token usage)
16
- */
17
- const PHASE_COST_WEIGHTS = {
18
- proposal: 5,
19
- setup: 3,
20
- uiux: 12,
21
- design: 18,
22
- clarify: 20,
23
- tasks: 17,
24
- implement: 80
25
- };
26
-
27
- /**
28
- * Cost per 1K tokens (approximate for Claude models)
29
- */
30
- const COST_PER_1K_INPUT = 0.003;
31
- const COST_PER_1K_OUTPUT = 0.015;
32
-
33
- /**
34
- * Record token usage for a phase
35
- */
36
- export function recordPhaseUsage(featureName, phase, inputTokens, outputTokens) {
37
- const state = loadState();
38
- const feature = state.features[featureName];
39
- if (!feature) return;
40
-
41
- if (!feature.costs) {
42
- feature.costs = { phases: {}, estimated: 0, approved: false };
43
- }
44
-
45
- if (!feature.costs.phases[phase]) {
46
- feature.costs.phases[phase] = { inputTokens: 0, outputTokens: 0, usd: 0 };
47
- }
48
-
49
- feature.costs.phases[phase].inputTokens += inputTokens;
50
- feature.costs.phases[phase].outputTokens += outputTokens;
51
- feature.costs.phases[phase].usd =
52
- (feature.costs.phases[phase].inputTokens / 1000 * COST_PER_1K_INPUT) +
53
- (feature.costs.phases[phase].outputTokens / 1000 * COST_PER_1K_OUTPUT);
54
-
55
- saveState(state);
56
- }
57
-
58
- /**
59
- * Calculate estimated remaining cost
60
- */
61
- function estimateRemaining(feature) {
62
- const currentPhaseIndex = Object.keys(PHASE_COST_WEIGHTS).indexOf(feature.phase);
63
- const completedWeight = Object.entries(PHASE_COST_WEIGHTS)
64
- .filter(([_, __], i) => i <= currentPhaseIndex)
65
- .reduce((sum, [_, w]) => sum + w, 0);
66
-
67
- const totalWeight = Object.values(PHASE_COST_WEIGHTS).reduce((a, b) => a + b, 0);
68
- const remainingWeight = totalWeight - completedWeight;
69
-
70
- // Estimate based on actual usage so far
71
- const actualSpent = Object.values(feature.costs?.phases || {})
72
- .reduce((sum, p) => sum + p.usd, 0);
73
-
74
- if (completedWeight === 0 || actualSpent === 0) {
75
- // No data yet, use default estimates
76
- const estimatedTokens = remainingWeight * 1000;
77
- return (estimatedTokens / 1000 * COST_PER_1K_INPUT) + (estimatedTokens / 1000 * COST_PER_1K_OUTPUT);
78
- }
79
-
80
- const costPerWeight = actualSpent / completedWeight;
81
- return costPerWeight * remainingWeight;
82
- }
83
-
84
- /**
85
- * Main cost command
86
- */
87
- export async function costCommand(featureName, options = {}) {
88
- if (!featureName) {
89
- console.error(chalk.red('Error: Feature name required'));
90
- console.error(chalk.gray('Usage: morph-spec cost <feature-name>'));
91
- process.exit(1);
92
- }
93
-
94
- const feature = getFeature(featureName);
95
- if (!feature) {
96
- console.error(chalk.red(`Error: Feature '${featureName}' not found`));
97
- process.exit(1);
98
- }
99
-
100
- const costs = feature.costs || { phases: {} };
101
- const totalSpent = Object.values(costs.phases)
102
- .reduce((sum, p) => sum + (p.usd || 0), 0);
103
- const estimatedRemaining = estimateRemaining(feature);
104
- const totalTokens = Object.values(costs.phases)
105
- .reduce((sum, p) => sum + (p.inputTokens || 0) + (p.outputTokens || 0), 0);
106
-
107
- // JSON output
108
- if (options.json) {
109
- const output = {
110
- feature: featureName,
111
- currentPhase: feature.phase,
112
- totalTokens,
113
- totalSpentUsd: Math.round(totalSpent * 100) / 100,
114
- estimatedRemainingUsd: Math.round(estimatedRemaining * 100) / 100,
115
- estimatedTotalUsd: Math.round((totalSpent + estimatedRemaining) * 100) / 100,
116
- phases: Object.entries(costs.phases).map(([phase, data]) => ({
117
- phase,
118
- inputTokens: data.inputTokens,
119
- outputTokens: data.outputTokens,
120
- usd: Math.round(data.usd * 100) / 100
121
- })),
122
- infraCosts: {
123
- estimated: costs.estimated || 0,
124
- approved: costs.approved || false
125
- }
126
- };
127
- console.log(JSON.stringify(output, null, 2));
128
- return;
129
- }
130
-
131
- // Visual output
132
- console.log(chalk.cyan('\n┌────────────────────────────────────────────────────────────┐'));
133
- console.log(chalk.cyan('│ MORPH-SPEC COST TRACKER │'));
134
- console.log(chalk.cyan('└────────────────────────────────────────────────────────────┘\n'));
135
-
136
- console.log(chalk.white.bold(`Feature: ${featureName}`));
137
- console.log(chalk.gray(`Current Phase: ${feature.phase}\n`));
138
-
139
- console.log(chalk.white.bold('Token usage by phase:'));
140
-
141
- const allPhases = Object.keys(PHASE_COST_WEIGHTS);
142
- for (const phase of allPhases) {
143
- const data = costs.phases[phase];
144
- const weight = PHASE_COST_WEIGHTS[phase];
145
- const phaseIndex = allPhases.indexOf(phase);
146
- const currentIndex = allPhases.indexOf(feature.phase);
147
- const isLast = phaseIndex === allPhases.length - 1;
148
- const prefix = isLast ? '└─' : '├─';
149
-
150
- if (data) {
151
- const tokens = (data.inputTokens || 0) + (data.outputTokens || 0);
152
- const usd = Math.round((data.usd || 0) * 100) / 100;
153
- const tokensStr = tokens >= 1000 ? `${Math.round(tokens / 1000)}k` : `${tokens}`;
154
- console.log(`${prefix} ${phase.toUpperCase()}: ${chalk.white(tokensStr)} tokens ${chalk.gray(`($${usd})`)}`);
155
- } else if (phaseIndex <= currentIndex) {
156
- console.log(`${prefix} ${phase.toUpperCase()}: ${chalk.gray('(no data recorded)')}`);
157
- } else {
158
- console.log(`${prefix} ${phase.toUpperCase()}: ${chalk.gray(`~${weight}k tokens (estimated)`)}`);
159
- }
160
- }
161
-
162
- console.log('');
163
- console.log(chalk.gray('─'.repeat(60)));
164
-
165
- const totalTokensStr = totalTokens >= 1000 ? `${Math.round(totalTokens / 1000)}k` : `${totalTokens}`;
166
- console.log(chalk.white(`Total spent: ${totalTokensStr} tokens ($${Math.round(totalSpent * 100) / 100})`));
167
- console.log(chalk.yellow(`Estimated remaining: ~$${Math.round(estimatedRemaining * 100) / 100}`));
168
- console.log(chalk.white.bold(`Estimated total: ~$${Math.round((totalSpent + estimatedRemaining) * 100) / 100}`));
169
-
170
- // Infrastructure costs
171
- if (costs.estimated > 0) {
172
- console.log(chalk.white(`\nInfra costs (monthly): $${costs.estimated}`));
173
- console.log(costs.approved ? chalk.green(' ✓ Approved') : chalk.yellow(' ⚠ Not yet approved'));
174
- }
175
-
176
- console.log('');
177
- }
178
-
179
- export default costCommand;
@@ -1,278 +0,0 @@
1
- /**
2
- * MORPH-SPEC Diff Command
3
- *
4
- * Track changes to specifications since last approval.
5
- * Shows added/removed functional requirements, entity changes, and new decisions.
6
- *
7
- * Usage:
8
- * morph-spec diff <feature-name> [output-file]
9
- * morph-spec diff <feature-name> spec.md
10
- * morph-spec diff <feature-name> --json
11
- */
12
-
13
- import fs from 'fs';
14
- import path from 'path';
15
- import chalk from 'chalk';
16
- import { getFeature } from '../../core/state/state-manager.js';
17
-
18
- /**
19
- * Load snapshot from checkpoints directory
20
- */
21
- function loadSnapshot(featureName, outputFile) {
22
- const snapshotDir = path.join(process.cwd(), '.morph/checkpoints', featureName);
23
- const snapshotPath = path.join(snapshotDir, outputFile);
24
-
25
- if (!fs.existsSync(snapshotPath)) {
26
- return null;
27
- }
28
-
29
- return fs.readFileSync(snapshotPath, 'utf8');
30
- }
31
-
32
- /**
33
- * Load current version of output file
34
- */
35
- function loadCurrent(featureName, outputFile) {
36
- const currentPath = path.join(process.cwd(), '.morph/features', featureName, outputFile);
37
-
38
- if (!fs.existsSync(currentPath)) {
39
- return null;
40
- }
41
-
42
- return fs.readFileSync(currentPath, 'utf8');
43
- }
44
-
45
- /**
46
- * Extract functional requirements from spec content
47
- */
48
- function extractRequirements(content) {
49
- const requirements = [];
50
- const regex = /###\s+(FR[-_]?\d+):?\s*(.+)/gi;
51
- let match;
52
- while ((match = regex.exec(content)) !== null) {
53
- requirements.push({ id: match[1], title: match[2].trim() });
54
- }
55
- return requirements;
56
- }
57
-
58
- /**
59
- * Extract entities from spec or contracts
60
- */
61
- function extractEntities(content) {
62
- const entities = [];
63
- // Markdown entities
64
- const mdRegex = /###\s+(?:Entity|Table):?\s*(.+)/gi;
65
- let match;
66
- while ((match = mdRegex.exec(content)) !== null) {
67
- entities.push(match[1].trim());
68
- }
69
- // C# records
70
- const csRegex = /public\s+record\s+(\w+)/g;
71
- while ((match = csRegex.exec(content)) !== null) {
72
- entities.push(match[1]);
73
- }
74
- return entities;
75
- }
76
-
77
- /**
78
- * Extract ADRs from decisions
79
- */
80
- function extractDecisions(content) {
81
- const decisions = [];
82
- const regex = /###\s+ADR[-_]?\d*:?\s*(.+)/gi;
83
- let match;
84
- while ((match = regex.exec(content)) !== null) {
85
- decisions.push(match[1].trim());
86
- }
87
- return decisions;
88
- }
89
-
90
- /**
91
- * Compute diff between two content versions
92
- */
93
- function computeDiff(oldContent, newContent, outputFile) {
94
- const diff = {
95
- file: outputFile,
96
- added: [],
97
- removed: [],
98
- modified: []
99
- };
100
-
101
- if (!oldContent) {
102
- diff.added.push('(entire file is new)');
103
- return diff;
104
- }
105
-
106
- if (!newContent) {
107
- diff.removed.push('(file was deleted)');
108
- return diff;
109
- }
110
-
111
- // Compare requirements
112
- if (outputFile.endsWith('spec.md')) {
113
- const oldReqs = extractRequirements(oldContent);
114
- const newReqs = extractRequirements(newContent);
115
-
116
- const oldIds = new Set(oldReqs.map(r => r.id));
117
- const newIds = new Set(newReqs.map(r => r.id));
118
-
119
- for (const req of newReqs) {
120
- if (!oldIds.has(req.id)) {
121
- diff.added.push(`${req.id}: ${req.title}`);
122
- }
123
- }
124
- for (const req of oldReqs) {
125
- if (!newIds.has(req.id)) {
126
- diff.removed.push(`${req.id}: ${req.title}`);
127
- }
128
- }
129
-
130
- // Compare entities
131
- const oldEntities = new Set(extractEntities(oldContent));
132
- const newEntities = new Set(extractEntities(newContent));
133
-
134
- for (const entity of newEntities) {
135
- if (!oldEntities.has(entity)) {
136
- diff.added.push(`Entity: ${entity}`);
137
- }
138
- }
139
- for (const entity of oldEntities) {
140
- if (!newEntities.has(entity)) {
141
- diff.removed.push(`Entity: ${entity}`);
142
- }
143
- }
144
- }
145
-
146
- // Compare decisions
147
- if (outputFile.endsWith('decisions.md')) {
148
- const oldDecisions = new Set(extractDecisions(oldContent));
149
- const newDecisions = new Set(extractDecisions(newContent));
150
-
151
- for (const decision of newDecisions) {
152
- if (!oldDecisions.has(decision)) {
153
- diff.added.push(`ADR: ${decision}`);
154
- }
155
- }
156
- for (const decision of oldDecisions) {
157
- if (!newDecisions.has(decision)) {
158
- diff.removed.push(`ADR: ${decision}`);
159
- }
160
- }
161
- }
162
-
163
- // Line count change
164
- const oldLines = oldContent.split('\n').length;
165
- const newLines = newContent.split('\n').length;
166
- if (oldLines !== newLines) {
167
- const delta = newLines - oldLines;
168
- diff.modified.push(`${delta > 0 ? '+' : ''}${delta} lines (${oldLines} → ${newLines})`);
169
- }
170
-
171
- return diff;
172
- }
173
-
174
- /**
175
- * Save current version as snapshot for future diffs
176
- */
177
- export function saveSnapshot(featureName) {
178
- const outputDir = path.join(process.cwd(), '.morph/features', featureName);
179
- const snapshotDir = path.join(process.cwd(), '.morph/checkpoints', featureName);
180
-
181
- if (!fs.existsSync(outputDir)) return;
182
-
183
- fs.mkdirSync(snapshotDir, { recursive: true });
184
-
185
- const files = fs.readdirSync(outputDir).filter(f => f.endsWith('.md') || f.endsWith('.cs') || f.endsWith('.json'));
186
- for (const file of files) {
187
- const src = path.join(outputDir, file);
188
- const dest = path.join(snapshotDir, file);
189
- fs.copyFileSync(src, dest);
190
- }
191
- }
192
-
193
- /**
194
- * Main diff command
195
- */
196
- export async function diffCommand(featureName, outputFile, options = {}) {
197
- if (!featureName) {
198
- console.error(chalk.red('Error: Feature name required'));
199
- console.error(chalk.gray('Usage: morph-spec diff <feature-name> [output-file]'));
200
- process.exit(1);
201
- }
202
-
203
- const outputDir = path.join(process.cwd(), '.morph/features', featureName);
204
- if (!fs.existsSync(outputDir)) {
205
- console.error(chalk.red(`Error: Feature directory not found: ${outputDir}`));
206
- process.exit(1);
207
- }
208
-
209
- // Determine which files to diff
210
- let files;
211
- if (outputFile) {
212
- files = [outputFile];
213
- } else {
214
- files = fs.readdirSync(outputDir).filter(f => f.endsWith('.md') || f.endsWith('.cs'));
215
- }
216
-
217
- const diffs = files.map(file => {
218
- const oldContent = loadSnapshot(featureName, file);
219
- const newContent = loadCurrent(featureName, file);
220
- return computeDiff(oldContent, newContent, file);
221
- }).filter(d => d.added.length > 0 || d.removed.length > 0 || d.modified.length > 0);
222
-
223
- // JSON output
224
- if (options.json) {
225
- console.log(JSON.stringify({ feature: featureName, diffs }, null, 2));
226
- return;
227
- }
228
-
229
- // Visual output
230
- console.log(chalk.cyan('\n┌────────────────────────────────────────────────────────────┐'));
231
- console.log(chalk.cyan('│ MORPH-SPEC DIFF │'));
232
- console.log(chalk.cyan('└────────────────────────────────────────────────────────────┘\n'));
233
-
234
- console.log(chalk.white.bold(`Feature: ${featureName}`));
235
- console.log(chalk.gray('Changes since last snapshot:\n'));
236
-
237
- if (diffs.length === 0) {
238
- console.log(chalk.green(' No changes detected since last snapshot.'));
239
- console.log(chalk.gray(' Run "morph-spec diff-save <feature>" to create a snapshot.\n'));
240
- return;
241
- }
242
-
243
- for (const diff of diffs) {
244
- console.log(chalk.white.bold(` ${diff.file}:`));
245
-
246
- for (const item of diff.added) {
247
- console.log(chalk.green(` + ${item}`));
248
- }
249
- for (const item of diff.removed) {
250
- console.log(chalk.red(` - ${item}`));
251
- }
252
- for (const item of diff.modified) {
253
- console.log(chalk.yellow(` ~ ${item}`));
254
- }
255
- console.log('');
256
- }
257
-
258
- const totalAdded = diffs.reduce((sum, d) => sum + d.added.length, 0);
259
- const totalRemoved = diffs.reduce((sum, d) => sum + d.removed.length, 0);
260
- console.log(chalk.gray('─'.repeat(60)));
261
- console.log(chalk.gray(`${totalAdded} addition(s), ${totalRemoved} removal(s) across ${diffs.length} file(s)\n`));
262
- }
263
-
264
- /**
265
- * Save snapshot command
266
- */
267
- export async function diffSaveCommand(featureName) {
268
- if (!featureName) {
269
- console.error(chalk.red('Error: Feature name required'));
270
- process.exit(1);
271
- }
272
-
273
- saveSnapshot(featureName);
274
- console.log(chalk.green(`✓ Snapshot saved for '${featureName}'`));
275
- console.log(chalk.gray(' Future "morph-spec diff" will compare against this snapshot.\n'));
276
- }
277
-
278
- export default diffCommand;
@@ -1,173 +0,0 @@
1
- /**
2
- * MORPH-SPEC Revert Command
3
- *
4
- * Revert a feature to a previous phase, optionally deleting later-phase outputs.
5
- *
6
- * Usage:
7
- * morph-spec revert <feature-name> --to <phase>
8
- * morph-spec revert <feature-name> --to design
9
- * morph-spec revert <feature-name> --to design --delete-outputs
10
- */
11
-
12
- import fs from 'fs';
13
- import path from 'path';
14
- import chalk from 'chalk';
15
- import { loadState, saveState, getFeature } from '../../core/state/state-manager.js';
16
-
17
- /**
18
- * Phase order for revert logic
19
- */
20
- const PHASE_ORDER = [
21
- { key: 'proposal', order: 0, outputs: ['proposal.md'] },
22
- { key: 'setup', order: 1, outputs: [] },
23
- { key: 'uiux', order: 2, outputs: ['ui-design-system.md', 'ui-mockups.md', 'ui-components.md', 'ui-flows.md'] },
24
- { key: 'design', order: 3, outputs: ['spec.md', 'schema-analysis.md', 'contracts.cs', 'decisions.md'] },
25
- { key: 'clarify', order: 4, outputs: ['clarifications.md'] },
26
- { key: 'tasks', order: 5, outputs: ['tasks.md', 'tasks.json'] },
27
- { key: 'implement', order: 6, outputs: ['recap.md'] },
28
- { key: 'sync', order: 7, outputs: [] }
29
- ];
30
-
31
- /**
32
- * Get outputs that would be affected by reverting to a phase
33
- */
34
- function getAffectedOutputs(targetPhase) {
35
- const targetOrder = PHASE_ORDER.find(p => p.key === targetPhase)?.order ?? -1;
36
- const affected = [];
37
-
38
- for (const phase of PHASE_ORDER) {
39
- if (phase.order > targetOrder) {
40
- affected.push(...phase.outputs.map(o => ({ phase: phase.key, file: o })));
41
- }
42
- }
43
-
44
- return affected;
45
- }
46
-
47
- /**
48
- * Main revert command
49
- */
50
- export async function revertCommand(featureName, options = {}) {
51
- if (!featureName) {
52
- console.error(chalk.red('Error: Feature name required'));
53
- console.error(chalk.gray('Usage: morph-spec revert <feature-name> --to <phase>'));
54
- process.exit(1);
55
- }
56
-
57
- const targetPhase = options.to;
58
- if (!targetPhase) {
59
- console.error(chalk.red('Error: Target phase required (--to <phase>)'));
60
- console.error(chalk.gray(`Valid phases: ${PHASE_ORDER.map(p => p.key).join(', ')}`));
61
- process.exit(1);
62
- }
63
-
64
- const targetDef = PHASE_ORDER.find(p => p.key === targetPhase);
65
- if (!targetDef) {
66
- console.error(chalk.red(`Error: Unknown phase: ${targetPhase}`));
67
- console.error(chalk.gray(`Valid phases: ${PHASE_ORDER.map(p => p.key).join(', ')}`));
68
- process.exit(1);
69
- }
70
-
71
- const feature = getFeature(featureName);
72
- if (!feature) {
73
- console.error(chalk.red(`Error: Feature '${featureName}' not found`));
74
- process.exit(1);
75
- }
76
-
77
- const currentDef = PHASE_ORDER.find(p => p.key === feature.phase);
78
- if (currentDef && targetDef.order >= currentDef.order) {
79
- console.error(chalk.red(`Error: Cannot revert forward. Current phase: ${feature.phase}, target: ${targetPhase}`));
80
- process.exit(1);
81
- }
82
-
83
- // Get affected outputs
84
- const affected = getAffectedOutputs(targetPhase);
85
- const outputDir = path.join(process.cwd(), '.morph/features', featureName);
86
- const existingAffected = affected.filter(a =>
87
- fs.existsSync(path.join(outputDir, a.file))
88
- );
89
-
90
- // Show what will happen
91
- console.log(chalk.cyan('\n┌────────────────────────────────────────────────────────────┐'));
92
- console.log(chalk.cyan('│ MORPH-SPEC REVERT │'));
93
- console.log(chalk.cyan('└────────────────────────────────────────────────────────────┘\n'));
94
-
95
- console.log(chalk.white.bold(`Feature: ${featureName}`));
96
- console.log(chalk.gray(`Current phase: ${feature.phase} → Reverting to: ${targetPhase}\n`));
97
-
98
- if (existingAffected.length > 0) {
99
- if (options.deleteOutputs) {
100
- console.log(chalk.yellow('The following files will be DELETED:'));
101
- } else {
102
- console.log(chalk.yellow('The following outputs will be marked as draft (files preserved):'));
103
- }
104
- for (const item of existingAffected) {
105
- console.log(chalk.gray(` - ${item.file} (from ${item.phase} phase)`));
106
- }
107
- console.log('');
108
- }
109
-
110
- // Update state
111
- const state = loadState();
112
- const stateFeature = state.features[featureName];
113
-
114
- // Revert phase
115
- stateFeature.phase = targetPhase;
116
- stateFeature.updatedAt = new Date().toISOString();
117
-
118
- // Mark affected outputs as not created in state
119
- const outputKeyMap = {
120
- 'proposal.md': 'proposal',
121
- 'spec.md': 'spec',
122
- 'schema-analysis.md': 'schemaAnalysis',
123
- 'contracts.cs': 'contracts',
124
- 'decisions.md': 'decisions',
125
- 'clarifications.md': 'clarifications',
126
- 'tasks.md': 'tasks',
127
- 'tasks.json': 'tasks',
128
- 'ui-design-system.md': 'uiDesignSystem',
129
- 'ui-mockups.md': 'uiMockups',
130
- 'ui-components.md': 'uiComponents',
131
- 'ui-flows.md': 'uiFlows',
132
- 'recap.md': 'recap'
133
- };
134
-
135
- for (const item of affected) {
136
- const key = outputKeyMap[item.file];
137
- if (key && stateFeature.outputs[key]) {
138
- stateFeature.outputs[key].created = false;
139
- }
140
- }
141
-
142
- // Reset approval gates for later phases
143
- for (const phase of PHASE_ORDER) {
144
- if (phase.order > targetDef.order && stateFeature.approvalGates?.[phase.key]) {
145
- stateFeature.approvalGates[phase.key].approved = false;
146
- stateFeature.approvalGates[phase.key].timestamp = null;
147
- stateFeature.approvalGates[phase.key].approvedBy = null;
148
- }
149
- }
150
-
151
- // Reset tasks if reverting before tasks phase
152
- if (targetDef.order < 5) {
153
- stateFeature.tasks = { total: 0, completed: 0, inProgress: 0, pending: 0 };
154
- }
155
-
156
- saveState(state);
157
-
158
- // Delete files if requested
159
- if (options.deleteOutputs && existingAffected.length > 0) {
160
- for (const item of existingAffected) {
161
- const filePath = path.join(outputDir, item.file);
162
- if (fs.existsSync(filePath)) {
163
- fs.unlinkSync(filePath);
164
- }
165
- }
166
- console.log(chalk.yellow(`Deleted ${existingAffected.length} file(s).`));
167
- }
168
-
169
- console.log(chalk.green(`✓ Feature '${featureName}' reverted to phase: ${targetPhase}`));
170
- console.log(chalk.gray(` State updated. Run 'morph-spec status ${featureName}' to see current status.\n`));
171
- }
172
-
173
- export default revertCommand;