@polymorphism-tech/morph-spec 4.7.2 → 4.8.1

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 (346) hide show
  1. package/.morph/analytics/threads-log.jsonl +54 -5
  2. package/.morph/state.json +152 -2
  3. package/LICENSE +1 -2
  4. package/README.md +379 -414
  5. package/bin/morph-spec.js +57 -394
  6. package/bin/validate.js +2 -26
  7. package/claude-plugin.json +2 -2
  8. package/docs/ARCHITECTURE.md +43 -46
  9. package/docs/CHEATSHEET.md +203 -221
  10. package/docs/COMMAND-FLOWS.md +319 -289
  11. package/docs/QUICKSTART.md +2 -8
  12. package/docs/plans/2026-02-22-claude-docs-morph-alignment-analysis.md +2 -0
  13. package/docs/plans/2026-02-22-claude-settings.md +2 -0
  14. package/docs/plans/2026-02-22-morph-cc-alignment-impl.md +2 -0
  15. package/docs/plans/2026-02-22-morph-spec-next.md +2 -0
  16. package/docs/plans/2026-02-22-native-alignment-design.md +2 -0
  17. package/docs/plans/2026-02-22-native-alignment-impl.md +2 -0
  18. package/docs/plans/2026-02-22-native-enrichment-design.md +2 -0
  19. package/docs/plans/2026-02-22-native-enrichment.md +2 -0
  20. package/docs/plans/2026-02-23-ddd-architecture-refactor.md +2 -0
  21. package/docs/plans/2026-02-23-ddd-nextsteps.md +2 -0
  22. package/docs/plans/2026-02-23-infra-architect-refactor.md +2 -0
  23. package/docs/plans/2026-02-23-nextjs-code-review-design.md +2 -1
  24. package/docs/plans/2026-02-23-nextjs-code-review-impl.md +2 -0
  25. package/docs/plans/2026-02-23-nextjs-standards-design.md +2 -1
  26. package/docs/plans/2026-02-23-nextjs-standards-impl.md +2 -0
  27. package/docs/plans/2026-02-24-cli-radical-simplification.md +592 -0
  28. package/docs/plans/2026-02-24-framework-failure-points.md +125 -0
  29. package/docs/plans/2026-02-24-morph-init-design.md +337 -0
  30. package/docs/plans/2026-02-24-morph-init-impl.md +1269 -0
  31. package/docs/plans/2026-02-24-tutorial-command-design.md +71 -0
  32. package/docs/plans/2026-02-24-tutorial-command.md +298 -0
  33. package/framework/CLAUDE.md +1 -1
  34. package/framework/commands/morph-proposal.md +3 -3
  35. package/framework/hooks/README.md +2 -5
  36. package/framework/hooks/claude-code/pre-tool-use/protect-readonly-files.js +4 -55
  37. package/framework/hooks/claude-code/session-start/inject-morph-context.js +20 -5
  38. package/framework/hooks/claude-code/statusline.py +6 -1
  39. package/framework/hooks/dev/check-sync-health.js +117 -0
  40. package/framework/hooks/dev/guard-version-numbers.js +57 -0
  41. package/framework/hooks/dev/sync-standards-registry.js +60 -0
  42. package/framework/hooks/dev/sync-template-registry.js +60 -0
  43. package/framework/hooks/dev/validate-skill-format.js +70 -0
  44. package/framework/hooks/dev/validate-standard-format.js +73 -0
  45. package/framework/hooks/shared/payload-utils.js +39 -0
  46. package/framework/hooks/shared/state-reader.js +25 -1
  47. package/framework/rules/morph-workflow.md +1 -1
  48. package/framework/skills/level-0-meta/morph-init/SKILL.md +216 -0
  49. package/framework/skills/level-0-meta/morph-replicate/SKILL.md +4 -4
  50. package/framework/skills/level-0-meta/tool-usage-guide/SKILL.md +4 -4
  51. package/framework/skills/level-0-meta/verification-before-completion/SKILL.md +1 -1
  52. package/framework/skills/level-1-workflows/phase-clarify/SKILL.md +192 -191
  53. package/framework/skills/level-1-workflows/phase-codebase-analysis/SKILL.md +181 -180
  54. package/framework/skills/level-1-workflows/phase-design/SKILL.md +339 -338
  55. package/framework/skills/level-1-workflows/phase-implement/SKILL.md +254 -253
  56. package/framework/skills/level-1-workflows/phase-setup/SKILL.md +168 -170
  57. package/framework/skills/level-1-workflows/phase-tasks/SKILL.md +284 -283
  58. package/framework/skills/level-1-workflows/phase-uiux/SKILL.md +246 -245
  59. package/framework/templates/examples/design-system-examples.md +1 -1
  60. package/framework/templates/ui/FluentDesignTheme.cs +1 -1
  61. package/framework/templates/ui/MudTheme.cs +1 -1
  62. package/framework/templates/ui/design-system.css +1 -1
  63. package/package.json +4 -2
  64. package/scripts/bump-version.js +248 -0
  65. package/scripts/install-dev-hooks.js +138 -0
  66. package/src/commands/agents/index.js +1 -2
  67. package/src/commands/index.js +13 -16
  68. package/src/commands/project/doctor.js +100 -14
  69. package/src/commands/project/index.js +7 -10
  70. package/src/commands/project/init.js +398 -528
  71. package/src/commands/project/install-plugin-cmd.js +28 -0
  72. package/src/commands/project/setup-infra-cmd.js +12 -0
  73. package/src/commands/project/tutorial.js +115 -0
  74. package/src/commands/state/approve.js +213 -221
  75. package/src/commands/state/index.js +0 -1
  76. package/src/commands/state/state.js +337 -365
  77. package/src/commands/templates/index.js +0 -4
  78. package/src/commands/trust/trust.js +1 -93
  79. package/src/commands/utils/index.js +1 -5
  80. package/src/commands/validation/index.js +1 -5
  81. package/src/core/registry/command-registry.js +11 -285
  82. package/src/core/state/state-manager.js +5 -2
  83. package/src/lib/detectors/index.js +81 -87
  84. package/src/lib/detectors/structure-detector.js +275 -273
  85. package/src/lib/generators/recap-generator.js +232 -225
  86. package/src/scripts/global-install.js +34 -0
  87. package/src/scripts/install-plugin.js +126 -0
  88. package/src/scripts/setup-infra.js +203 -0
  89. package/src/utils/agents-installer.js +10 -1
  90. package/src/utils/hooks-installer.js +66 -3
  91. package/.morph/.morphversion +0 -5
  92. package/.morph/config/config.json +0 -8
  93. package/.morph/framework/agents.json +0 -1815
  94. package/.morph/framework/hooks/README.md +0 -205
  95. package/.morph/framework/hooks/claude-code/notification/approval-reminder.js +0 -54
  96. package/.morph/framework/hooks/claude-code/post-tool-use/dispatch.js +0 -83
  97. package/.morph/framework/hooks/claude-code/post-tool-use/handle-tool-failure.js +0 -42
  98. package/.morph/framework/hooks/claude-code/pre-compact/save-morph-context.js +0 -61
  99. package/.morph/framework/hooks/claude-code/pre-tool-use/enforce-phase-writes.js +0 -71
  100. package/.morph/framework/hooks/claude-code/pre-tool-use/protect-readonly-files.js +0 -58
  101. package/.morph/framework/hooks/claude-code/pre-tool-use/protect-spec-files.js +0 -64
  102. package/.morph/framework/hooks/claude-code/session-start/inject-morph-context.js +0 -94
  103. package/.morph/framework/hooks/claude-code/statusline.py +0 -538
  104. package/.morph/framework/hooks/claude-code/statusline.sh +0 -7
  105. package/.morph/framework/hooks/claude-code/stop/validate-completion.js +0 -88
  106. package/.morph/framework/hooks/claude-code/user-prompt/enrich-prompt.js +0 -91
  107. package/.morph/framework/hooks/git/commit-msg/conventional-commits.sh +0 -33
  108. package/.morph/framework/hooks/git/pre-commit/agents.sh +0 -25
  109. package/.morph/framework/hooks/git/pre-commit/orchestrator.sh +0 -64
  110. package/.morph/framework/hooks/git/pre-commit/specs.sh +0 -50
  111. package/.morph/framework/hooks/git/pre-push/run-tests.sh +0 -44
  112. package/.morph/framework/hooks/shared/hook-response.js +0 -45
  113. package/.morph/framework/hooks/shared/phase-utils.js +0 -129
  114. package/.morph/framework/hooks/shared/state-reader.js +0 -138
  115. package/.morph/framework/hooks/shared/stdin-reader.js +0 -26
  116. package/.morph/framework/standards/STANDARDS.json +0 -933
  117. package/.morph/framework/standards/ai-agents/blazor-ui.md +0 -364
  118. package/.morph/framework/standards/ai-agents/production.md +0 -415
  119. package/.morph/framework/standards/ai-agents/setup.md +0 -418
  120. package/.morph/framework/standards/ai-agents/team-orchestration.md +0 -479
  121. package/.morph/framework/standards/ai-agents/workflows.md +0 -354
  122. package/.morph/framework/standards/architecture/ddd/aggregates.md +0 -120
  123. package/.morph/framework/standards/architecture/ddd/bounded-contexts.md +0 -105
  124. package/.morph/framework/standards/architecture/ddd/complexity-levels.md +0 -108
  125. package/.morph/framework/standards/architecture/ddd/entities.md +0 -99
  126. package/.morph/framework/standards/architecture/ddd/ubiquitous-language.md +0 -58
  127. package/.morph/framework/standards/architecture/ddd/value-objects.md +0 -124
  128. package/.morph/framework/standards/backend/api/minimal-api.md +0 -494
  129. package/.morph/framework/standards/backend/api/rest.md +0 -492
  130. package/.morph/framework/standards/backend/api/validation.md +0 -88
  131. package/.morph/framework/standards/backend/authentication/passkeys.md +0 -428
  132. package/.morph/framework/standards/backend/database/ef-core.md +0 -199
  133. package/.morph/framework/standards/backend/database/migrations.md +0 -393
  134. package/.morph/framework/standards/backend/database/postgresql/database.md +0 -352
  135. package/.morph/framework/standards/backend/database/repository-patterns.md +0 -528
  136. package/.morph/framework/standards/backend/database/vector-search-rag.md +0 -541
  137. package/.morph/framework/standards/backend/dotnet/async.md +0 -366
  138. package/.morph/framework/standards/backend/dotnet/core.md +0 -117
  139. package/.morph/framework/standards/backend/dotnet/di.md +0 -439
  140. package/.morph/framework/standards/backend/dotnet/program-cs-checklist.md +0 -92
  141. package/.morph/framework/standards/backend/integrations/asaas/asaas-api.md +0 -216
  142. package/.morph/framework/standards/backend/integrations/clerk/clerk-auth.md +0 -290
  143. package/.morph/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +0 -350
  144. package/.morph/framework/standards/backend/integrations/resend/resend-email.md +0 -385
  145. package/.morph/framework/standards/context/analytics.md +0 -96
  146. package/.morph/framework/standards/context/bundles.md +0 -110
  147. package/.morph/framework/standards/context/priming.md +0 -78
  148. package/.morph/framework/standards/core/architecture.md +0 -185
  149. package/.morph/framework/standards/core/coding.md +0 -214
  150. package/.morph/framework/standards/core/git-branching-strategy.md +0 -403
  151. package/.morph/framework/standards/core/git.md +0 -185
  152. package/.morph/framework/standards/core/testing.md +0 -295
  153. package/.morph/framework/standards/data/nosql/blob-storage.md +0 -102
  154. package/.morph/framework/standards/data/nosql/cache/redis.md +0 -97
  155. package/.morph/framework/standards/data/nosql/cosmos-db.md +0 -118
  156. package/.morph/framework/standards/data/vector-search/azure-ai-search.md +0 -121
  157. package/.morph/framework/standards/data/vector-search/rag-chunking.md +0 -104
  158. package/.morph/framework/standards/frontend/blazor/design-checklist.md +0 -222
  159. package/.morph/framework/standards/frontend/blazor/fluent-ui-setup.md +0 -595
  160. package/.morph/framework/standards/frontend/blazor/fluent-ui.md +0 -137
  161. package/.morph/framework/standards/frontend/blazor/html-conversion.md +0 -184
  162. package/.morph/framework/standards/frontend/blazor/lifecycle.md +0 -195
  163. package/.morph/framework/standards/frontend/blazor/pitfalls.md +0 -198
  164. package/.morph/framework/standards/frontend/blazor/state.md +0 -191
  165. package/.morph/framework/standards/frontend/design-system/animations.md +0 -151
  166. package/.morph/framework/standards/frontend/design-system/naming.md +0 -64
  167. package/.morph/framework/standards/frontend/nextjs/app-router.md +0 -123
  168. package/.morph/framework/standards/frontend/nextjs/components.md +0 -132
  169. package/.morph/framework/standards/frontend/nextjs/data-fetching.md +0 -126
  170. package/.morph/framework/standards/frontend/nextjs/forms.md +0 -128
  171. package/.morph/framework/standards/frontend/nextjs/naming-conventions.md +0 -67
  172. package/.morph/framework/standards/frontend/nextjs/nextjs-patterns.md +0 -215
  173. package/.morph/framework/standards/frontend/nextjs/project-structure.md +0 -102
  174. package/.morph/framework/standards/frontend/nextjs/state-management.md +0 -72
  175. package/.morph/framework/standards/frontend/nextjs/testing.md +0 -111
  176. package/.morph/framework/standards/infrastructure/azure/azure.md +0 -624
  177. package/.morph/framework/standards/infrastructure/azure/bicep/bicep-patterns.md +0 -422
  178. package/.morph/framework/standards/infrastructure/azure/devops/azure-devops-setup.md +0 -516
  179. package/.morph/framework/standards/infrastructure/azure/devops/local-development.md +0 -520
  180. package/.morph/framework/standards/infrastructure/azure/services/functions.md +0 -486
  181. package/.morph/framework/standards/infrastructure/azure/services/service-bus.md +0 -459
  182. package/.morph/framework/standards/infrastructure/azure/services/storage.md +0 -407
  183. package/.morph/framework/standards/infrastructure/docker/easypanel-deploy.md +0 -196
  184. package/.morph/framework/standards/infrastructure/supabase/mcp-setup.md +0 -252
  185. package/.morph/framework/standards/infrastructure/supabase/supabase-auth.md +0 -176
  186. package/.morph/framework/standards/infrastructure/supabase/supabase-pgvector.md +0 -169
  187. package/.morph/framework/standards/infrastructure/supabase/supabase-rls.md +0 -184
  188. package/.morph/framework/standards/infrastructure/supabase/supabase-storage.md +0 -153
  189. package/.morph/framework/standards/integration/api/graphql.md +0 -91
  190. package/.morph/framework/standards/integration/api/grpc.md +0 -114
  191. package/.morph/framework/standards/integration/api/rest-design.md +0 -95
  192. package/.morph/framework/standards/integration/event-driven/cqrs.md +0 -101
  193. package/.morph/framework/standards/integration/event-driven/event-sourcing.md +0 -124
  194. package/.morph/framework/standards/integration/event-driven/service-bus.md +0 -95
  195. package/.morph/framework/standards/integration/mcp/mcp-tools.md +0 -384
  196. package/.morph/framework/standards/observability/logging.md +0 -131
  197. package/.morph/framework/standards/observability/metrics.md +0 -121
  198. package/.morph/framework/standards/observability/monitoring.md +0 -114
  199. package/.morph/framework/standards/observability/tracing.md +0 -132
  200. package/.morph/framework/standards/workflows/parallel-execution.md +0 -112
  201. package/.morph/framework/standards/workflows/thread-management.md +0 -113
  202. package/.morph/framework/templates/.idea/morph-templates.xml +0 -92
  203. package/.morph/framework/templates/.vscode/morph-templates.code-snippets +0 -186
  204. package/.morph/framework/templates/IDE-SNIPPETS.md +0 -266
  205. package/.morph/framework/templates/README.md +0 -814
  206. package/.morph/framework/templates/REGISTRY.json +0 -1888
  207. package/.morph/framework/templates/code/dotnet/backend/repository.cs +0 -141
  208. package/.morph/framework/templates/code/dotnet/backend/service.cs +0 -139
  209. package/.morph/framework/templates/code/dotnet/contracts/Commands.cs +0 -74
  210. package/.morph/framework/templates/code/dotnet/contracts/Entities.cs +0 -25
  211. package/.morph/framework/templates/code/dotnet/contracts/Queries.cs +0 -74
  212. package/.morph/framework/templates/code/dotnet/contracts/README.md +0 -74
  213. package/.morph/framework/templates/code/dotnet/contracts/api-contracts.cs +0 -173
  214. package/.morph/framework/templates/code/dotnet/contracts/contracts-level1.cs +0 -69
  215. package/.morph/framework/templates/code/dotnet/contracts/contracts-level2.cs +0 -86
  216. package/.morph/framework/templates/code/dotnet/contracts/contracts-level3.cs +0 -41
  217. package/.morph/framework/templates/code/dotnet/database/migration.cs +0 -83
  218. package/.morph/framework/templates/code/dotnet/frontend/component.razor +0 -239
  219. package/.morph/framework/templates/code/dotnet/jobs/agent.cs +0 -163
  220. package/.morph/framework/templates/code/dotnet/jobs/job.cs +0 -171
  221. package/.morph/framework/templates/code/dotnet/test.cs +0 -239
  222. package/.morph/framework/templates/code/sql/rls-policy.sql +0 -57
  223. package/.morph/framework/templates/code/sql/supabase-migration.sql +0 -100
  224. package/.morph/framework/templates/code/sql/supabase-migration.template.sql +0 -113
  225. package/.morph/framework/templates/code/typescript/contracts.ts +0 -168
  226. package/.morph/framework/templates/context/CONTEXT-FEATURE.md +0 -276
  227. package/.morph/framework/templates/context/CONTEXT.md +0 -181
  228. package/.morph/framework/templates/docs/clarifications.md +0 -253
  229. package/.morph/framework/templates/docs/onboarding.md +0 -123
  230. package/.morph/framework/templates/docs/proposal.md +0 -182
  231. package/.morph/framework/templates/docs/schema-analysis.md +0 -119
  232. package/.morph/framework/templates/docs/spec.md +0 -198
  233. package/.morph/framework/templates/docs/ui-components.md +0 -124
  234. package/.morph/framework/templates/docs/ui-design-system.md +0 -76
  235. package/.morph/framework/templates/docs/ui-flows.md +0 -167
  236. package/.morph/framework/templates/docs/ui-mockups.md +0 -98
  237. package/.morph/framework/templates/docs/user-stories.md +0 -34
  238. package/.morph/framework/templates/examples/design-system-examples.md +0 -357
  239. package/.morph/framework/templates/examples/spec-examples.md +0 -90
  240. package/.morph/framework/templates/feature/decisions.md +0 -187
  241. package/.morph/framework/templates/feature/recap.md +0 -146
  242. package/.morph/framework/templates/feature/tasks.md +0 -199
  243. package/.morph/framework/templates/frontend/nextjs/Dockerfile.nextjs.hbs +0 -43
  244. package/.morph/framework/templates/frontend/nextjs/client-component.tsx.hbs +0 -26
  245. package/.morph/framework/templates/frontend/nextjs/env.mjs.hbs +0 -32
  246. package/.morph/framework/templates/frontend/nextjs/feature-form.tsx.hbs +0 -56
  247. package/.morph/framework/templates/frontend/nextjs/page.tsx.hbs +0 -22
  248. package/.morph/framework/templates/frontend/nextjs/tsconfig.json.hbs +0 -26
  249. package/.morph/framework/templates/frontend/nextjs/use-feature.ts.hbs +0 -54
  250. package/.morph/framework/templates/infrastructure/azure/Dockerfile.example +0 -82
  251. package/.morph/framework/templates/infrastructure/azure/README.md +0 -286
  252. package/.morph/framework/templates/infrastructure/azure/app-insights.bicep +0 -63
  253. package/.morph/framework/templates/infrastructure/azure/app-service.bicep +0 -164
  254. package/.morph/framework/templates/infrastructure/azure/container-app-env.bicep +0 -49
  255. package/.morph/framework/templates/infrastructure/azure/container-app.bicep +0 -156
  256. package/.morph/framework/templates/infrastructure/azure/deploy-checklist.md +0 -426
  257. package/.morph/framework/templates/infrastructure/azure/deploy.ps1 +0 -229
  258. package/.morph/framework/templates/infrastructure/azure/deploy.sh +0 -208
  259. package/.morph/framework/templates/infrastructure/azure/key-vault.bicep +0 -91
  260. package/.morph/framework/templates/infrastructure/azure/main.bicep +0 -189
  261. package/.morph/framework/templates/infrastructure/azure/parameters.dev.json +0 -29
  262. package/.morph/framework/templates/infrastructure/azure/parameters.prod.json +0 -29
  263. package/.morph/framework/templates/infrastructure/azure/parameters.staging.json +0 -29
  264. package/.morph/framework/templates/infrastructure/azure/sql-database.bicep +0 -103
  265. package/.morph/framework/templates/infrastructure/azure/storage.bicep +0 -106
  266. package/.morph/framework/templates/infrastructure/docker/Dockerfile.template +0 -58
  267. package/.morph/framework/templates/infrastructure/docker/docker-compose.template.yml +0 -67
  268. package/.morph/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +0 -38
  269. package/.morph/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +0 -48
  270. package/.morph/framework/templates/infrastructure/docker/easypanel.template.json +0 -54
  271. package/.morph/framework/templates/infrastructure/github/README.md +0 -593
  272. package/.morph/framework/templates/infrastructure/github/actions/azure-auth/action.yml.hbs +0 -22
  273. package/.morph/framework/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +0 -45
  274. package/.morph/framework/templates/infrastructure/github/actions/health-check/action.yml.hbs +0 -27
  275. package/.morph/framework/templates/infrastructure/github/workflows/deploy-azure-app-service.yml.hbs +0 -61
  276. package/.morph/framework/templates/infrastructure/github/workflows/deploy-easypanel.yml.hbs +0 -31
  277. package/.morph/framework/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +0 -59
  278. package/.morph/framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +0 -39
  279. package/.morph/framework/templates/integrations/asaas-client.cs +0 -387
  280. package/.morph/framework/templates/integrations/asaas-webhook.cs +0 -351
  281. package/.morph/framework/templates/integrations/azure-identity-config.cs +0 -288
  282. package/.morph/framework/templates/integrations/clerk-config.cs +0 -258
  283. package/.morph/framework/templates/meta-prompts/fusion/fusion-agent.md +0 -76
  284. package/.morph/framework/templates/meta-prompts/fusion/fusion-aggregator.md +0 -100
  285. package/.morph/framework/templates/meta-prompts/hops/hop-retry.md +0 -78
  286. package/.morph/framework/templates/meta-prompts/hops/hop-validation.md +0 -97
  287. package/.morph/framework/templates/meta-prompts/hops/hop-wrapper.md +0 -36
  288. package/.morph/framework/templates/meta-prompts/parallel-workers/parallel-coordinator.md +0 -113
  289. package/.morph/framework/templates/meta-prompts/parallel-workers/parallel-worker.md +0 -80
  290. package/.morph/framework/templates/meta-prompts/squad-leaders/backend-squad.md +0 -90
  291. package/.morph/framework/templates/meta-prompts/squad-leaders/frontend-squad.md +0 -126
  292. package/.morph/framework/templates/meta-prompts/squad-leaders/squad-leader.md +0 -43
  293. package/.morph/framework/templates/meta-prompts/validators/checkpoint-validator.md +0 -107
  294. package/.morph/framework/templates/meta-prompts/validators/pre-commit-validator.md +0 -95
  295. package/.morph/framework/templates/project-structure/dotnet-ddd.md +0 -70
  296. package/.morph/framework/templates/saas/subscription.cs +0 -347
  297. package/.morph/framework/templates/saas/tenant.cs +0 -338
  298. package/.morph/framework/templates/state.template.json +0 -17
  299. package/.morph/framework/templates/ui/FluentDesignTheme.cs +0 -149
  300. package/.morph/framework/templates/ui/MudTheme.cs +0 -281
  301. package/.morph/framework/templates/ui/design-system.css +0 -226
  302. package/.morph/logs/tool-failures.log +0 -17
  303. package/.morph/memory/pre-compact-2026-02-24T17-43-30-049Z.json +0 -16
  304. package/.morph/plans/eager-watching-bunny.md +0 -105
  305. package/.morph/plans/temporal-seeking-nebula.md +0 -45
  306. package/CLAUDE.md +0 -77
  307. package/docs/claude-alignment-report.md +0 -137
  308. package/docs/examples/order-management/contracts.cs +0 -84
  309. package/docs/examples/order-management/proposal.md +0 -24
  310. package/docs/examples/order-management/spec.md +0 -162
  311. package/src/commands/feature/create-story.js +0 -362
  312. package/src/commands/feature/index.js +0 -6
  313. package/src/commands/feature/shard-spec.js +0 -225
  314. package/src/commands/feature/sprint-status.js +0 -250
  315. package/src/commands/generation/generate-onboarding.js +0 -169
  316. package/src/commands/generation/generate.js +0 -276
  317. package/src/commands/generation/index.js +0 -5
  318. package/src/commands/learning/capture-pattern.js +0 -121
  319. package/src/commands/learning/index.js +0 -5
  320. package/src/commands/learning/search-patterns.js +0 -126
  321. package/src/commands/mcp/mcp.js +0 -102
  322. package/src/commands/project/changes.js +0 -66
  323. package/src/commands/project/cost.js +0 -179
  324. package/src/commands/project/diff.js +0 -278
  325. package/src/commands/project/revert.js +0 -173
  326. package/src/commands/project/standards.js +0 -80
  327. package/src/commands/project/sync.js +0 -167
  328. package/src/commands/project/update-agents.js +0 -23
  329. package/src/commands/state/rollback-phase.js +0 -185
  330. package/src/commands/templates/template-customize.js +0 -87
  331. package/src/commands/templates/template-list.js +0 -114
  332. package/src/commands/templates/template-show.js +0 -129
  333. package/src/commands/templates/template-validate.js +0 -91
  334. package/src/commands/utils/troubleshoot.js +0 -222
  335. package/src/commands/validation/analyze-blazor-concurrency.js +0 -193
  336. package/src/commands/validation/lint-fluent.js +0 -352
  337. package/src/commands/validation/validate-blazor-state.js +0 -210
  338. package/src/commands/validation/validate-blazor.js +0 -156
  339. package/src/commands/validation/validate-css.js +0 -84
  340. package/src/lib/detectors/conversation-analyzer.js +0 -163
  341. package/src/lib/learning/index.js +0 -7
  342. package/src/lib/learning/learning-system.js +0 -520
  343. package/src/lib/troubleshooting/index.js +0 -8
  344. package/src/lib/troubleshooting/troubleshoot-grep.js +0 -198
  345. package/src/lib/troubleshooting/troubleshoot-index.js +0 -144
  346. package/src/llm/environment-detector.js +0 -43
@@ -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;
@@ -1,80 +0,0 @@
1
- /**
2
- * Standards CLI Commands
3
- *
4
- * Provides browsable access to the framework standards registry.
5
- * Usage:
6
- * morph-spec standards --list
7
- * morph-spec standards --search <query>
8
- * morph-spec standards --show <id>
9
- * morph-spec standards --category <cat>
10
- */
11
-
12
- import { readFileSync } from 'fs';
13
- import { join } from 'path';
14
- import { fileURLToPath } from 'url';
15
- import { logger } from '../../utils/logger.js';
16
-
17
- const __dirname = fileURLToPath(new URL('.', import.meta.url));
18
- const REGISTRY_PATH = join(__dirname, '..', '..', '..', 'framework', 'standards', 'STANDARDS.json');
19
-
20
- function loadRegistry() {
21
- return JSON.parse(readFileSync(REGISTRY_PATH, 'utf8')).standards;
22
- }
23
-
24
- /**
25
- * List all standards, optionally filtered by category.
26
- * @param {{ json?: boolean, category?: string }} opts
27
- * @returns {Promise<Array>}
28
- */
29
- export async function listStandards({ json, category } = {}) {
30
- let standards = loadRegistry();
31
- if (category) {
32
- standards = standards.filter(s => s.category === category);
33
- }
34
- if (json) return standards;
35
- standards.forEach(s =>
36
- logger.info(`${s.id.padEnd(55)} ${s.category}`)
37
- );
38
- return standards;
39
- }
40
-
41
- /**
42
- * Search standards by query string (matches id, name, or tags).
43
- * @param {string} query
44
- * @param {{ json?: boolean }} opts
45
- * @returns {Promise<Array>}
46
- */
47
- export async function searchStandards(query, { json } = {}) {
48
- const q = query.toLowerCase();
49
- const results = loadRegistry().filter(s =>
50
- s.name.toLowerCase().includes(q) ||
51
- s.id.toLowerCase().includes(q) ||
52
- s.tags.some(t => t.toLowerCase().includes(q))
53
- );
54
- if (json) return results;
55
- if (results.length === 0) {
56
- logger.warn(`No standards found matching "${query}"`);
57
- } else {
58
- results.forEach(s => logger.info(`${s.id}: ${s.name} [${s.category}]`));
59
- }
60
- return results;
61
- }
62
-
63
- /**
64
- * Show the full content of a standard by its id.
65
- * @param {string} id
66
- * @returns {Promise<string|null>}
67
- */
68
- export async function showStandard(id) {
69
- const standard = loadRegistry().find(s => s.id === id);
70
- if (!standard) {
71
- logger.error(`Standard '${id}' not found. Use --list to see available standards.`);
72
- return null;
73
- }
74
- const content = readFileSync(
75
- join(__dirname, '..', '..', '..', 'framework', 'standards', standard.path),
76
- 'utf8'
77
- );
78
- logger.info(content);
79
- return content;
80
- }
@@ -1,167 +0,0 @@
1
- import { join } from 'path';
2
- import { readdirSync, existsSync } from 'fs';
3
- import ora from 'ora';
4
- import chalk from 'chalk';
5
- import { logger } from '../../utils/logger.js';
6
- import { readFile, writeFile, ensureDir } from '../../utils/file-copier.js';
7
- import { analyzeConversation } from '../../lib/detectors/conversation-analyzer.js';
8
-
9
- export async function syncCommand(options) {
10
- const targetPath = options.path || process.cwd();
11
-
12
- logger.header('MORPH-SPEC Standards Sync');
13
- logger.dim(`Project: ${targetPath}`);
14
- logger.blank();
15
-
16
- const spinner = ora('Analyzing feature decisions...').start();
17
-
18
- try {
19
- // 1. Find all decisions.md files
20
- const outputsPath = join(targetPath, '.morph', 'project', 'outputs');
21
-
22
- if (!existsSync(outputsPath)) {
23
- spinner.warn('No features found');
24
- logger.dim('Create features first using MORPH workflow.');
25
- return;
26
- }
27
-
28
- const features = readdirSync(outputsPath, { withFileTypes: true })
29
- .filter(dirent => dirent.isDirectory())
30
- .map(dirent => dirent.name);
31
-
32
- if (features.length === 0) {
33
- spinner.warn('No features found');
34
- return;
35
- }
36
-
37
- spinner.text = `Found ${features.length} features, analyzing decisions...`;
38
-
39
- // 2. Analyze all decisions
40
- const conversation = await analyzeConversation(targetPath);
41
-
42
- if (conversation.decisions.length === 0) {
43
- spinner.warn('No decisions found to sync');
44
- logger.dim('Features may not have decisions.md files yet.');
45
- return;
46
- }
47
-
48
- spinner.succeed(`Found ${conversation.decisions.length} decisions`);
49
- logger.blank();
50
-
51
- // 3. Group by category
52
- const byCategory = groupByCategory(conversation.decisions);
53
-
54
- // 4. Display candidates
55
- logger.header('Decisions by Category:');
56
- logger.blank();
57
-
58
- let totalCandidates = 0;
59
-
60
- for (const [category, decisions] of Object.entries(byCategory)) {
61
- if (decisions.length > 0) {
62
- logger.info(chalk.cyan(`${formatCategory(category)} (${decisions.length})`));
63
- decisions.slice(0, 3).forEach(d => {
64
- const preview = d.text.split('\n')[0].substring(0, 70);
65
- logger.dim(` - ${preview}...`);
66
- });
67
- if (decisions.length > 3) {
68
- logger.dim(` ... and ${decisions.length - 3} more`);
69
- }
70
- logger.blank();
71
- totalCandidates += decisions.length;
72
- }
73
- }
74
-
75
- // 5. Sync (for now, just report - interactive approval would be added later)
76
- if (options.dryRun) {
77
- logger.warn('Dry run mode - no files updated');
78
- logger.dim(`Would update ${Object.keys(byCategory).length} standard files`);
79
- return;
80
- }
81
-
82
- spinner.start('Updating standards...');
83
-
84
- const standardsDir = join(targetPath, '.morph', 'project', 'standards');
85
- await ensureDir(standardsDir);
86
-
87
- let updatedFiles = [];
88
-
89
- for (const [category, decisions] of Object.entries(byCategory)) {
90
- if (decisions.length === 0) continue;
91
-
92
- const fileName = `${category}.md`;
93
- const filePath = join(standardsDir, fileName);
94
-
95
- // Read existing or create new
96
- let content = '';
97
- if (existsSync(filePath)) {
98
- content = await readFile(filePath);
99
- } else {
100
- content = `# ${formatCategory(category)} Standards\n\n> Project-specific standards for ${category}\n\n`;
101
- }
102
-
103
- // Append new decisions
104
- content += `\n## Decisions from Features (${new Date().toISOString().split('T')[0]})\n\n`;
105
-
106
- decisions.forEach((d, idx) => {
107
- const preview = d.text.split('\n').slice(0, 5).join('\n');
108
- content += `### Decision ${idx + 1}\n\n${preview}\n\n`;
109
- });
110
-
111
- await writeFile(filePath, content);
112
- updatedFiles.push(fileName);
113
- }
114
-
115
- spinner.succeed(`Updated ${updatedFiles.length} standard files`);
116
-
117
- updatedFiles.forEach(file => {
118
- logger.dim(` - ${file}`);
119
- });
120
-
121
- logger.blank();
122
- logger.success('Standards sync complete!');
123
- logger.dim('Commit these changes with a sync: message.');
124
-
125
- } catch (error) {
126
- spinner.fail('Sync failed');
127
- logger.error(error.message);
128
- process.exit(1);
129
- }
130
- }
131
-
132
- /**
133
- * Group decisions by category
134
- */
135
- function groupByCategory(decisions) {
136
- const categories = {
137
- 'coding': [],
138
- 'architecture': [],
139
- 'azure': [],
140
- 'integrations': [],
141
- 'ui-ux': []
142
- };
143
-
144
- decisions.forEach(decision => {
145
- const category = decision.category || 'coding';
146
- if (categories[category]) {
147
- categories[category].push(decision);
148
- }
149
- });
150
-
151
- return categories;
152
- }
153
-
154
- /**
155
- * Format category name
156
- */
157
- function formatCategory(category) {
158
- const names = {
159
- 'coding': 'Coding Standards',
160
- 'architecture': 'Architecture Patterns',
161
- 'azure': 'Azure & Infrastructure',
162
- 'integrations': 'Integration Patterns',
163
- 'ui-ux': 'UI/UX Standards'
164
- };
165
-
166
- return names[category] || category;
167
- }