@polymorphism-tech/morph-spec 4.3.7 → 4.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (394) hide show
  1. package/.morph/.morphversion +3 -3
  2. package/.morph/analytics/threads-log.jsonl +6 -9
  3. package/.morph/config/config.json +2 -3
  4. package/.morph/framework/standards/STANDARDS.json +812 -0
  5. package/.morph/{standards → framework/standards}/ai-agents/team-orchestration.md +3 -3
  6. package/.morph/{standards → framework/standards}/frontend/nextjs/nextjs-patterns.md +17 -0
  7. package/.morph/framework/standards/integration/mcp/mcp-tools.md +384 -0
  8. package/.morph/{templates → framework/templates}/README.md +17 -17
  9. package/.morph/{templates → framework/templates}/REGISTRY.json +48 -233
  10. package/.morph/framework/templates/code/dotnet/contracts/contracts.cs.hbs +172 -0
  11. package/.morph/{templates → framework/templates}/context/CONTEXT-FEATURE.md +1 -1
  12. package/.morph/{templates → framework/templates}/context/CONTEXT.md +3 -3
  13. package/.morph/framework/templates/docs/clarifications.md +253 -0
  14. package/.morph/framework/templates/docs/onboarding.md +123 -0
  15. package/.morph/framework/templates/docs/schema-analysis.md +119 -0
  16. package/.morph/{templates → framework/templates}/docs/spec.md +149 -149
  17. package/.morph/framework/templates/docs/ui-components.md +124 -0
  18. package/.morph/framework/templates/docs/ui-design-system.md +76 -0
  19. package/.morph/framework/templates/docs/ui-flows.md +167 -0
  20. package/.morph/framework/templates/docs/ui-mockups.md +98 -0
  21. package/.morph/framework/templates/docs/user-stories.md +34 -0
  22. package/.morph/{templates → framework/templates}/examples/spec-examples.md +1 -1
  23. package/.morph/{templates → framework/templates}/infrastructure/github/README.md +11 -11
  24. package/.morph/{templates → framework/templates}/infrastructure/github/workflows/deploy-azure-app-service.yml.hbs +2 -2
  25. package/.morph/{templates → framework/templates}/meta-prompts/parallel-workers/parallel-worker.md +2 -2
  26. package/.morph/{templates → framework/templates}/meta-prompts/validators/pre-commit-validator.md +1 -1
  27. package/.morph/logs/tool-failures.log +7 -0
  28. package/.morph/memory/pre-compact-2026-02-23T15-43-03-521Z.json +16 -0
  29. package/.morph/state.json +1 -1
  30. package/CLAUDE.md +77 -155
  31. package/README.md +20 -18
  32. package/bin/detect-agents.js +1 -1
  33. package/bin/morph-spec.js +116 -266
  34. package/bin/task-manager.cjs +2 -2
  35. package/bin/validate.js +1 -1
  36. package/claude-plugin.json +14 -0
  37. package/docs/claude-alignment-report.md +137 -0
  38. package/docs/plans/2026-02-22-claude-docs-morph-alignment-analysis.md +512 -0
  39. package/docs/plans/2026-02-22-claude-settings.md +515 -0
  40. package/docs/plans/2026-02-22-morph-cc-alignment-impl.md +728 -0
  41. package/docs/plans/2026-02-22-morph-spec-next.md +478 -0
  42. package/docs/plans/2026-02-22-native-alignment-design.md +199 -0
  43. package/docs/plans/2026-02-22-native-alignment-impl.md +925 -0
  44. package/docs/plans/2026-02-22-native-enrichment-design.md +244 -0
  45. package/docs/plans/2026-02-22-native-enrichment.md +735 -0
  46. package/framework/CLAUDE.md +77 -0
  47. package/framework/{skills/level-2-domains → agents}/ai-agents/ai-system-architect.md +7 -3
  48. package/framework/{skills/level-2-domains → agents}/architecture/po-pm-advisor.md +7 -1
  49. package/framework/{skills/level-2-domains → agents}/architecture/prompt-engineer.md +7 -1
  50. package/framework/{skills/level-2-domains → agents}/architecture/seo-growth-hacker.md +7 -1
  51. package/framework/{skills/level-2-domains → agents}/architecture/standards-architect.md +10 -6
  52. package/framework/agents/backend/api-designer.md +103 -0
  53. package/framework/{skills/level-2-domains → agents}/backend/dotnet-senior.md +7 -1
  54. package/framework/agents/backend/ef-modeler.md +119 -0
  55. package/framework/{skills/level-2-domains → agents}/backend/hangfire-orchestrator.md +8 -4
  56. package/framework/{skills/level-2-domains → agents}/backend/ms-agent-expert.md +7 -3
  57. package/framework/{skills/level-2-domains → agents}/frontend/blazor-builder.md +7 -3
  58. package/framework/{skills/level-2-domains → agents}/frontend/nextjs-expert.md +7 -3
  59. package/framework/{skills/level-2-domains → agents}/frontend/ui-ux-designer.md +8 -2
  60. package/framework/{skills/level-2-domains → agents}/infrastructure/azure-architect.md +7 -1
  61. package/framework/{skills/level-2-domains → agents}/infrastructure/azure-deploy-specialist.md +7 -1
  62. package/framework/{skills/level-2-domains → agents}/infrastructure/bicep-architect.md +7 -3
  63. package/framework/{skills/level-2-domains → agents}/infrastructure/container-specialist.md +7 -3
  64. package/framework/{skills/level-2-domains → agents}/infrastructure/devops-engineer.md +7 -3
  65. package/framework/{skills/level-2-domains → agents}/integrations/asaas-financial.md +7 -3
  66. package/framework/{skills/level-2-domains → agents}/integrations/azure-identity.md +7 -3
  67. package/framework/{skills/level-2-domains → agents}/integrations/clerk-auth.md +7 -3
  68. package/framework/{skills/level-2-domains/integrations/hangfire-orchestrator.md → agents/integrations/hangfire-integration.md} +7 -1
  69. package/framework/{skills/level-2-domains → agents}/integrations/resend-email.md +7 -3
  70. package/framework/{skills/level-2-domains → agents}/quality/code-analyzer.md +9 -5
  71. package/framework/{skills/level-2-domains → agents}/quality/testing-specialist.md +7 -3
  72. package/framework/commands/morph-apply.md +9 -9
  73. package/framework/commands/morph-archive.md +8 -8
  74. package/framework/commands/morph-infra.md +1 -1
  75. package/framework/commands/morph-proposal.md +9 -9
  76. package/framework/commands/morph-status.md +3 -3
  77. package/framework/commands/morph-troubleshoot.md +1 -1
  78. package/framework/hooks/README.md +201 -282
  79. package/framework/hooks/claude-code/notification/approval-reminder.js +52 -0
  80. package/framework/hooks/claude-code/post-tool-use/dispatch.js +83 -0
  81. package/framework/hooks/claude-code/post-tool-use/handle-tool-failure.js +42 -0
  82. package/framework/hooks/claude-code/pre-compact/save-morph-context.js +61 -0
  83. package/framework/hooks/claude-code/pre-tool-use/enforce-phase-writes.js +71 -0
  84. package/framework/hooks/claude-code/pre-tool-use/protect-readonly-files.js +58 -0
  85. package/framework/hooks/claude-code/pre-tool-use/protect-spec-files.js +64 -0
  86. package/framework/hooks/claude-code/session-start/inject-morph-context.js +94 -0
  87. package/framework/hooks/claude-code/statusline.py +538 -0
  88. package/framework/hooks/claude-code/statusline.sh +7 -0
  89. package/framework/hooks/claude-code/stop/validate-completion.js +88 -0
  90. package/framework/hooks/claude-code/user-prompt/enrich-prompt.js +91 -0
  91. package/framework/hooks/shared/hook-response.js +45 -0
  92. package/framework/hooks/shared/phase-utils.js +129 -0
  93. package/framework/hooks/shared/state-reader.js +138 -0
  94. package/framework/hooks/shared/stdin-reader.js +26 -0
  95. package/framework/phases.json +145 -0
  96. package/framework/rules/csharp-standards.md +10 -0
  97. package/framework/rules/frontend-standards.md +14 -0
  98. package/framework/rules/infrastructure-standards.md +13 -0
  99. package/framework/rules/morph-workflow.md +86 -0
  100. package/framework/rules/testing-standards.md +11 -0
  101. package/framework/skills/README.md +66 -0
  102. package/framework/skills/level-0-meta/brainstorming/SKILL.md +135 -0
  103. package/framework/skills/level-0-meta/brainstorming/references/proposal-example.md +138 -0
  104. package/framework/skills/level-0-meta/{code-review.md → code-review/SKILL.md} +13 -4
  105. package/framework/skills/level-0-meta/code-review/references/review-example.md +164 -0
  106. package/framework/skills/level-0-meta/code-review/scripts/scan-csharp.mjs +121 -0
  107. package/framework/skills/level-0-meta/mcp-registry.json +207 -0
  108. package/framework/skills/level-0-meta/{morph-checklist.md → morph-checklist/SKILL.md} +8 -3
  109. package/framework/skills/{level-1-workflows/morph-replicate.md → level-0-meta/morph-replicate/SKILL.md} +13 -6
  110. package/framework/skills/level-0-meta/{simulation-checklist.md → simulation-checklist/SKILL.md} +9 -4
  111. package/framework/skills/level-0-meta/tool-usage-guide/SKILL.md +334 -0
  112. package/framework/skills/level-0-meta/verification-before-completion/SKILL.md +147 -0
  113. package/framework/skills/level-0-meta/verification-before-completion/scripts/check-phase-outputs.mjs +110 -0
  114. package/framework/skills/level-1-workflows/{phase-clarify.md → phase-clarify/SKILL.md} +65 -4
  115. package/framework/skills/level-1-workflows/phase-clarify/references/clarifications-example.md +117 -0
  116. package/framework/skills/level-1-workflows/phase-codebase-analysis/SKILL.md +181 -0
  117. package/framework/skills/level-1-workflows/phase-design/SKILL.md +303 -0
  118. package/framework/skills/level-1-workflows/phase-design/references/spec-example.md +253 -0
  119. package/framework/skills/level-1-workflows/phase-implement/SKILL.md +254 -0
  120. package/framework/skills/level-1-workflows/phase-implement/references/recap-example.md +132 -0
  121. package/framework/skills/level-1-workflows/phase-setup/SKILL.md +171 -0
  122. package/framework/skills/level-1-workflows/{phase-tasks.md → phase-tasks/SKILL.md} +89 -7
  123. package/framework/skills/level-1-workflows/phase-tasks/references/tasks-example.md +231 -0
  124. package/framework/skills/level-1-workflows/phase-tasks/scripts/validate-tasks.mjs +112 -0
  125. package/framework/skills/level-1-workflows/phase-uiux/SKILL.md +246 -0
  126. package/framework/standards/STANDARDS.json +812 -0
  127. package/framework/standards/ai-agents/team-orchestration.md +3 -3
  128. package/framework/standards/frontend/nextjs/nextjs-patterns.md +17 -0
  129. package/framework/standards/integration/mcp/mcp-tools.md +384 -0
  130. package/framework/templates/README.md +17 -17
  131. package/framework/templates/REGISTRY.json +48 -233
  132. package/framework/templates/code/dotnet/contracts/contracts.cs.hbs +172 -0
  133. package/framework/templates/context/CONTEXT-FEATURE.md +1 -1
  134. package/framework/templates/context/CONTEXT.md +3 -3
  135. package/framework/templates/docs/clarifications.md +253 -0
  136. package/framework/templates/docs/onboarding.md +123 -0
  137. package/framework/templates/docs/schema-analysis.md +119 -0
  138. package/framework/templates/docs/spec.md +149 -149
  139. package/framework/templates/docs/ui-components.md +124 -0
  140. package/framework/templates/docs/ui-design-system.md +76 -0
  141. package/framework/templates/docs/ui-flows.md +167 -0
  142. package/framework/templates/docs/ui-mockups.md +98 -0
  143. package/framework/templates/docs/user-stories.md +34 -0
  144. package/framework/templates/examples/spec-examples.md +1 -1
  145. package/framework/templates/infrastructure/github/README.md +11 -11
  146. package/framework/templates/infrastructure/github/workflows/deploy-azure-app-service.yml.hbs +2 -2
  147. package/framework/templates/meta-prompts/parallel-workers/parallel-worker.md +2 -2
  148. package/framework/templates/meta-prompts/validators/pre-commit-validator.md +1 -1
  149. package/framework/workflows/configs/express.json +45 -0
  150. package/framework/workflows/configs/spec-only.json +43 -0
  151. package/framework/workflows/docs/enforcement-pipeline.md +8 -8
  152. package/framework/workflows/docs/full-morph.md +3 -3
  153. package/package.json +3 -1
  154. package/scripts/generate-refs.js +336 -0
  155. package/scripts/generate-standards-registry.js +44 -0
  156. package/scripts/validate-real.mjs +255 -0
  157. package/src/commands/feature/create-story.js +362 -361
  158. package/src/commands/feature/shard-spec.js +225 -224
  159. package/src/commands/feature/sprint-status.js +1 -1
  160. package/src/commands/generation/generate-onboarding.js +169 -0
  161. package/src/commands/generation/generate.js +2 -2
  162. package/src/commands/mcp/mcp-setup.js +315 -0
  163. package/src/commands/project/changes.js +66 -0
  164. package/src/commands/project/checkpoint.js +209 -0
  165. package/src/commands/project/cost.js +179 -0
  166. package/src/commands/project/diff.js +278 -0
  167. package/src/commands/project/doctor.js +55 -7
  168. package/src/commands/project/init.js +318 -136
  169. package/src/commands/project/revert.js +173 -0
  170. package/src/commands/project/standards.js +80 -0
  171. package/src/commands/project/status.js +376 -0
  172. package/src/commands/project/update-agents.js +23 -0
  173. package/src/commands/project/update.js +60 -88
  174. package/src/commands/state/advance-phase.js +4 -3
  175. package/src/commands/state/state.js +10 -3
  176. package/src/commands/state/validate-phase.js +19 -2
  177. package/src/commands/templates/template-customize.js +4 -4
  178. package/src/commands/templates/template-render.js +1 -1
  179. package/src/commands/templates/template-show.js +1 -1
  180. package/src/commands/validation/validate-feature.js +359 -0
  181. package/src/core/orchestrator.js +3 -38
  182. package/src/core/paths/output-schema.js +135 -0
  183. package/src/core/state/state-manager.js +831 -592
  184. package/src/core/templates/template-registry.js +2 -2
  185. package/src/core/workflows/workflow-detector.js +17 -1
  186. package/src/lib/agents/micro-agent-factory.js +1 -1
  187. package/src/lib/context/context-bundler.js +2 -1
  188. package/src/lib/detectors/claude-config-detector.js +390 -0
  189. package/src/lib/detectors/conversation-analyzer.js +4 -4
  190. package/src/lib/detectors/design-system-detector.js +6 -5
  191. package/src/lib/detectors/standards-generator.js +2 -2
  192. package/src/lib/generators/context-generator.js +539 -538
  193. package/src/lib/generators/recap-generator.js +1 -1
  194. package/src/lib/generators/settings-generator.js +210 -0
  195. package/src/lib/hooks/hook-executor.js +1 -1
  196. package/src/lib/installers/mcp-installer.js +299 -0
  197. package/src/lib/learning/learning-system.js +3 -3
  198. package/src/lib/orchestration/team-orchestrator.js +1 -1
  199. package/src/lib/standards/standards-context-injector.js +7 -7
  200. package/src/lib/threads/thread-coordinator.js +1 -1
  201. package/src/lib/troubleshooting/troubleshoot-grep.js +1 -1
  202. package/src/lib/validators/contracts/contract-compliance-validator.js +274 -273
  203. package/src/lib/validators/design-system/design-system-validator.js +1 -1
  204. package/src/lib/validators/spec-validator.js +258 -258
  205. package/src/lib/validators/validation-runner.js +270 -269
  206. package/src/utils/agents-installer.js +206 -0
  207. package/src/utils/claude-settings-manager.js +258 -0
  208. package/src/utils/file-copier.js +1 -1
  209. package/src/utils/hooks-installer.js +354 -28
  210. package/src/utils/skills-installer.js +118 -0
  211. package/.morph/project/context/README.md +0 -17
  212. package/.morph/project/context/detection-log.md +0 -16
  213. package/.morph/project/standards/inferred.md +0 -59
  214. package/framework/hooks/agent-stop/validate-and-continue.js +0 -96
  215. package/framework/hooks/agent-stop/validate-checkpoints.js +0 -101
  216. package/framework/hooks/agent-stop/validate-tests.js +0 -109
  217. package/framework/hooks/agent-teams/dispatch.js +0 -67
  218. package/framework/hooks/agent-teams/phase-advanced.js +0 -80
  219. package/framework/hooks/agent-teams/task-completed.js +0 -76
  220. package/framework/hooks/agent-teams/teammate-idle.js +0 -70
  221. package/framework/skills/level-1-workflows/phase-design.md +0 -213
  222. package/framework/skills/level-1-workflows/phase-setup.md +0 -106
  223. package/framework/skills/level-1-workflows/phase-uiux.md +0 -169
  224. package/framework/skills/level-2-domains/backend/api-designer.md +0 -59
  225. package/framework/skills/level-2-domains/backend/ef-modeler.md +0 -58
  226. package/framework/skills/level-3-technologies/README.md +0 -7
  227. package/framework/skills/level-4-patterns/README.md +0 -7
  228. package/src/commands/agents/agents-fuse.js +0 -97
  229. package/src/commands/agents/micro-agent.js +0 -112
  230. package/src/commands/agents/spawn-team.js +0 -237
  231. package/src/commands/agents/squad-template.js +0 -146
  232. package/src/commands/analytics/analytics.js +0 -176
  233. package/src/commands/context/context-prime.js +0 -63
  234. package/src/commands/context/core-four.js +0 -54
  235. package/src/commands/generation/generate-context.js +0 -40
  236. package/src/commands/project/detect-agents.js +0 -207
  237. package/src/commands/project/detect-workflow.js +0 -174
  238. package/src/commands/threads/thread-template.js +0 -103
  239. package/src/commands/threads/threads.js +0 -261
  240. package/src/commands/utils/session-summary.js +0 -291
  241. package/src/llm/analyzer.js +0 -215
  242. package/src/llm/few-shot-examples.js +0 -216
  243. package/src/llm/project-config-schema.json +0 -188
  244. package/src/llm/prompt-builder.js +0 -96
  245. /package/.morph/{config → framework}/agents.json +0 -0
  246. /package/.morph/{standards → framework/standards}/ai-agents/blazor-ui.md +0 -0
  247. /package/.morph/{standards → framework/standards}/ai-agents/production.md +0 -0
  248. /package/.morph/{standards → framework/standards}/ai-agents/setup.md +0 -0
  249. /package/.morph/{standards → framework/standards}/ai-agents/workflows.md +0 -0
  250. /package/.morph/{standards → framework/standards}/architecture/ddd/aggregates.md +0 -0
  251. /package/.morph/{standards → framework/standards}/architecture/ddd/entities.md +0 -0
  252. /package/.morph/{standards → framework/standards}/architecture/ddd/value-objects.md +0 -0
  253. /package/.morph/{standards → framework/standards}/backend/api/minimal-api.md +0 -0
  254. /package/.morph/{standards → framework/standards}/backend/api/rest.md +0 -0
  255. /package/.morph/{standards → framework/standards}/backend/api/validation.md +0 -0
  256. /package/.morph/{standards → framework/standards}/backend/authentication/passkeys.md +0 -0
  257. /package/.morph/{standards → framework/standards}/backend/database/ef-core.md +0 -0
  258. /package/.morph/{standards → framework/standards}/backend/database/migrations.md +0 -0
  259. /package/.morph/{standards → framework/standards}/backend/database/postgresql/database.md +0 -0
  260. /package/.morph/{standards → framework/standards}/backend/database/repository-patterns.md +0 -0
  261. /package/.morph/{standards → framework/standards}/backend/database/vector-search-rag.md +0 -0
  262. /package/.morph/{standards → framework/standards}/backend/dotnet/async.md +0 -0
  263. /package/.morph/{standards → framework/standards}/backend/dotnet/core.md +0 -0
  264. /package/.morph/{standards → framework/standards}/backend/dotnet/di.md +0 -0
  265. /package/.morph/{standards → framework/standards}/backend/dotnet/program-cs-checklist.md +0 -0
  266. /package/.morph/{standards → framework/standards}/backend/integrations/asaas/asaas-api.md +0 -0
  267. /package/.morph/{standards → framework/standards}/backend/integrations/clerk/clerk-auth.md +0 -0
  268. /package/.morph/{standards → framework/standards}/backend/integrations/hangfire/hangfire-jobs.md +0 -0
  269. /package/.morph/{standards → framework/standards}/backend/integrations/resend/resend-email.md +0 -0
  270. /package/.morph/{standards → framework/standards}/context/analytics.md +0 -0
  271. /package/.morph/{standards → framework/standards}/context/bundles.md +0 -0
  272. /package/.morph/{standards → framework/standards}/context/priming.md +0 -0
  273. /package/.morph/{standards → framework/standards}/core/architecture.md +0 -0
  274. /package/.morph/{standards → framework/standards}/core/coding.md +0 -0
  275. /package/.morph/{standards → framework/standards}/core/git-branching-strategy.md +0 -0
  276. /package/.morph/{standards → framework/standards}/core/git.md +0 -0
  277. /package/.morph/{standards → framework/standards}/core/testing.md +0 -0
  278. /package/.morph/{standards → framework/standards}/data/nosql/blob-storage.md +0 -0
  279. /package/.morph/{standards → framework/standards}/data/nosql/cache/redis.md +0 -0
  280. /package/.morph/{standards → framework/standards}/data/nosql/cosmos-db.md +0 -0
  281. /package/.morph/{standards → framework/standards}/data/vector-search/azure-ai-search.md +0 -0
  282. /package/.morph/{standards → framework/standards}/data/vector-search/rag-chunking.md +0 -0
  283. /package/.morph/{standards → framework/standards}/frontend/blazor/design-checklist.md +0 -0
  284. /package/.morph/{standards → framework/standards}/frontend/blazor/fluent-ui-setup.md +0 -0
  285. /package/.morph/{standards → framework/standards}/frontend/blazor/fluent-ui.md +0 -0
  286. /package/.morph/{standards → framework/standards}/frontend/blazor/html-conversion.md +0 -0
  287. /package/.morph/{standards → framework/standards}/frontend/blazor/lifecycle.md +0 -0
  288. /package/.morph/{standards → framework/standards}/frontend/blazor/pitfalls.md +0 -0
  289. /package/.morph/{standards → framework/standards}/frontend/blazor/state.md +0 -0
  290. /package/.morph/{standards → framework/standards}/frontend/design-system/animations.md +0 -0
  291. /package/.morph/{standards → framework/standards}/frontend/design-system/naming.md +0 -0
  292. /package/.morph/{standards → framework/standards}/infrastructure/azure/azure.md +0 -0
  293. /package/.morph/{standards → framework/standards}/infrastructure/azure/bicep/bicep-patterns.md +0 -0
  294. /package/.morph/{standards → framework/standards}/infrastructure/azure/devops/azure-devops-setup.md +0 -0
  295. /package/.morph/{standards → framework/standards}/infrastructure/azure/devops/local-development.md +0 -0
  296. /package/.morph/{standards → framework/standards}/infrastructure/azure/services/functions.md +0 -0
  297. /package/.morph/{standards → framework/standards}/infrastructure/azure/services/service-bus.md +0 -0
  298. /package/.morph/{standards → framework/standards}/infrastructure/azure/services/storage.md +0 -0
  299. /package/.morph/{standards → framework/standards}/infrastructure/docker/easypanel-deploy.md +0 -0
  300. /package/.morph/{standards → framework/standards}/infrastructure/supabase/mcp-setup.md +0 -0
  301. /package/.morph/{standards → framework/standards}/infrastructure/supabase/supabase-auth.md +0 -0
  302. /package/.morph/{standards → framework/standards}/infrastructure/supabase/supabase-pgvector.md +0 -0
  303. /package/.morph/{standards → framework/standards}/infrastructure/supabase/supabase-rls.md +0 -0
  304. /package/.morph/{standards → framework/standards}/infrastructure/supabase/supabase-storage.md +0 -0
  305. /package/.morph/{standards → framework/standards}/integration/api/graphql.md +0 -0
  306. /package/.morph/{standards → framework/standards}/integration/api/grpc.md +0 -0
  307. /package/.morph/{standards → framework/standards}/integration/api/rest-design.md +0 -0
  308. /package/.morph/{standards → framework/standards}/integration/event-driven/cqrs.md +0 -0
  309. /package/.morph/{standards → framework/standards}/integration/event-driven/event-sourcing.md +0 -0
  310. /package/.morph/{standards → framework/standards}/integration/event-driven/service-bus.md +0 -0
  311. /package/.morph/{standards → framework/standards}/observability/logging.md +0 -0
  312. /package/.morph/{standards → framework/standards}/observability/metrics.md +0 -0
  313. /package/.morph/{standards → framework/standards}/observability/monitoring.md +0 -0
  314. /package/.morph/{standards → framework/standards}/observability/tracing.md +0 -0
  315. /package/.morph/{standards → framework/standards}/workflows/parallel-execution.md +0 -0
  316. /package/.morph/{standards → framework/standards}/workflows/thread-management.md +0 -0
  317. /package/.morph/{templates → framework/templates}/.idea/morph-templates.xml +0 -0
  318. /package/.morph/{templates → framework/templates}/.vscode/morph-templates.code-snippets +0 -0
  319. /package/.morph/{templates → framework/templates}/IDE-SNIPPETS.md +0 -0
  320. /package/.morph/{templates → framework/templates}/code/dotnet/backend/repository.cs +0 -0
  321. /package/.morph/{templates → framework/templates}/code/dotnet/backend/service.cs +0 -0
  322. /package/.morph/{templates → framework/templates}/code/dotnet/contracts/Commands.cs +0 -0
  323. /package/.morph/{templates → framework/templates}/code/dotnet/contracts/Entities.cs +0 -0
  324. /package/.morph/{templates → framework/templates}/code/dotnet/contracts/Queries.cs +0 -0
  325. /package/.morph/{templates → framework/templates}/code/dotnet/contracts/README.md +0 -0
  326. /package/.morph/{templates → framework/templates}/code/dotnet/contracts/api-contracts.cs +0 -0
  327. /package/.morph/{templates → framework/templates}/code/dotnet/contracts/contracts.cs +0 -0
  328. /package/.morph/{templates → framework/templates}/code/dotnet/database/migration.cs +0 -0
  329. /package/.morph/{templates → framework/templates}/code/dotnet/frontend/component.razor +0 -0
  330. /package/.morph/{templates → framework/templates}/code/dotnet/jobs/agent.cs +0 -0
  331. /package/.morph/{templates → framework/templates}/code/dotnet/jobs/job.cs +0 -0
  332. /package/.morph/{templates → framework/templates}/code/dotnet/test.cs +0 -0
  333. /package/.morph/{templates → framework/templates}/code/sql/rls-policy.sql +0 -0
  334. /package/.morph/{templates → framework/templates}/code/sql/supabase-migration.sql +0 -0
  335. /package/.morph/{templates → framework/templates}/code/sql/supabase-migration.template.sql +0 -0
  336. /package/.morph/{templates → framework/templates}/code/typescript/contracts.ts +0 -0
  337. /package/.morph/{templates → framework/templates}/docs/proposal.md +0 -0
  338. /package/.morph/{templates → framework/templates}/examples/design-system-examples.md +0 -0
  339. /package/.morph/{templates → framework/templates}/feature/decisions.md +0 -0
  340. /package/.morph/{templates → framework/templates}/feature/recap.md +0 -0
  341. /package/.morph/{templates → framework/templates}/feature/tasks.md +0 -0
  342. /package/.morph/{templates → framework/templates}/infrastructure/azure/Dockerfile.example +0 -0
  343. /package/.morph/{templates → framework/templates}/infrastructure/azure/README.md +0 -0
  344. /package/.morph/{templates → framework/templates}/infrastructure/azure/app-insights.bicep +0 -0
  345. /package/.morph/{templates → framework/templates}/infrastructure/azure/app-service.bicep +0 -0
  346. /package/.morph/{templates → framework/templates}/infrastructure/azure/container-app-env.bicep +0 -0
  347. /package/.morph/{templates → framework/templates}/infrastructure/azure/container-app.bicep +0 -0
  348. /package/.morph/{templates → framework/templates}/infrastructure/azure/deploy-checklist.md +0 -0
  349. /package/.morph/{templates → framework/templates}/infrastructure/azure/deploy.ps1 +0 -0
  350. /package/.morph/{templates → framework/templates}/infrastructure/azure/deploy.sh +0 -0
  351. /package/.morph/{templates → framework/templates}/infrastructure/azure/key-vault.bicep +0 -0
  352. /package/.morph/{templates → framework/templates}/infrastructure/azure/main.bicep +0 -0
  353. /package/.morph/{templates → framework/templates}/infrastructure/azure/parameters.dev.json +0 -0
  354. /package/.morph/{templates → framework/templates}/infrastructure/azure/parameters.prod.json +0 -0
  355. /package/.morph/{templates → framework/templates}/infrastructure/azure/parameters.staging.json +0 -0
  356. /package/.morph/{templates → framework/templates}/infrastructure/azure/sql-database.bicep +0 -0
  357. /package/.morph/{templates → framework/templates}/infrastructure/azure/storage.bicep +0 -0
  358. /package/.morph/{templates → framework/templates}/infrastructure/docker/Dockerfile.template +0 -0
  359. /package/.morph/{templates → framework/templates}/infrastructure/docker/docker-compose.template.yml +0 -0
  360. /package/.morph/{templates → framework/templates}/infrastructure/docker/dockerfile-api.dockerfile +0 -0
  361. /package/.morph/{templates → framework/templates}/infrastructure/docker/dockerfile-web.dockerfile +0 -0
  362. /package/.morph/{templates → framework/templates}/infrastructure/docker/easypanel.template.json +0 -0
  363. /package/.morph/{templates → framework/templates}/infrastructure/github/actions/azure-auth/action.yml.hbs +0 -0
  364. /package/.morph/{templates → framework/templates}/infrastructure/github/actions/docker-build-push/action.yml.hbs +0 -0
  365. /package/.morph/{templates → framework/templates}/infrastructure/github/actions/health-check/action.yml.hbs +0 -0
  366. /package/.morph/{templates → framework/templates}/infrastructure/github/workflows/deploy-easypanel.yml.hbs +0 -0
  367. /package/.morph/{templates → framework/templates}/infrastructure/github/workflows/docker-build-push.yml.hbs +0 -0
  368. /package/.morph/{templates → framework/templates}/infrastructure/github/workflows/dotnet-build.yml.hbs +0 -0
  369. /package/.morph/{templates → framework/templates}/integrations/asaas-client.cs +0 -0
  370. /package/.morph/{templates → framework/templates}/integrations/asaas-webhook.cs +0 -0
  371. /package/.morph/{templates → framework/templates}/integrations/azure-identity-config.cs +0 -0
  372. /package/.morph/{templates → framework/templates}/integrations/clerk-config.cs +0 -0
  373. /package/.morph/{templates → framework/templates}/meta-prompts/fusion/fusion-agent.md +0 -0
  374. /package/.morph/{templates → framework/templates}/meta-prompts/fusion/fusion-aggregator.md +0 -0
  375. /package/.morph/{templates → framework/templates}/meta-prompts/hops/hop-retry.md +0 -0
  376. /package/.morph/{templates → framework/templates}/meta-prompts/hops/hop-validation.md +0 -0
  377. /package/.morph/{templates → framework/templates}/meta-prompts/hops/hop-wrapper.md +0 -0
  378. /package/.morph/{templates → framework/templates}/meta-prompts/parallel-workers/parallel-coordinator.md +0 -0
  379. /package/.morph/{templates → framework/templates}/meta-prompts/squad-leaders/backend-squad.md +0 -0
  380. /package/.morph/{templates → framework/templates}/meta-prompts/squad-leaders/frontend-squad.md +0 -0
  381. /package/.morph/{templates → framework/templates}/meta-prompts/squad-leaders/squad-leader.md +0 -0
  382. /package/.morph/{templates → framework/templates}/meta-prompts/validators/checkpoint-validator.md +0 -0
  383. /package/.morph/{templates → framework/templates}/saas/subscription.cs +0 -0
  384. /package/.morph/{templates → framework/templates}/saas/tenant.cs +0 -0
  385. /package/.morph/{templates → framework/templates}/state.template.json +0 -0
  386. /package/.morph/{templates → framework/templates}/ui/FluentDesignTheme.cs +0 -0
  387. /package/.morph/{templates → framework/templates}/ui/MudTheme.cs +0 -0
  388. /package/.morph/{templates → framework/templates}/ui/design-system.css +0 -0
  389. /package/framework/{skills/level-2-domains → agents}/README.md +0 -0
  390. /package/framework/hooks/{commit-msg → git/commit-msg}/conventional-commits.sh +0 -0
  391. /package/framework/hooks/{pre-commit → git/pre-commit}/agents.sh +0 -0
  392. /package/framework/hooks/{pre-commit → git/pre-commit}/orchestrator.sh +0 -0
  393. /package/framework/hooks/{pre-commit → git/pre-commit}/specs.sh +0 -0
  394. /package/framework/hooks/{pre-push → git/pre-push}/run-tests.sh +0 -0
@@ -0,0 +1,336 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * scripts/generate-refs.js
4
+ *
5
+ * Generates derived files from the single source of truth:
6
+ * src/core/paths/output-schema.js
7
+ *
8
+ * Outputs:
9
+ * framework/hooks/shared/phase-utils.js — constants derived from OUTPUT_SCHEMA
10
+ * framework/skills/level-1-workflows/*.md — morph:outputs blocks
11
+ *
12
+ * Usage:
13
+ * node scripts/generate-refs.js # generate files
14
+ * node scripts/generate-refs.js --check # validate only (CI, exit 1 if drift)
15
+ */
16
+
17
+ import { readFileSync, writeFileSync, existsSync } from 'fs';
18
+ import { join, dirname } from 'path';
19
+ import { fileURLToPath } from 'url';
20
+ import { OUTPUT_SCHEMA } from '../src/core/paths/output-schema.js';
21
+
22
+ const __dirname = dirname(fileURLToPath(import.meta.url));
23
+ const ROOT = join(__dirname, '..');
24
+ const CHECK_MODE = process.argv.includes('--check');
25
+
26
+ // ============================================================================
27
+ // Configuration
28
+ // ============================================================================
29
+
30
+ /**
31
+ * Phase entries that cannot be derived from OUTPUT_SCHEMA because they share
32
+ * directories with other phases (no dedicated output type of their own).
33
+ */
34
+ const PHASE_DIRS_EXTRAS = {
35
+ setup: '0-proposal', // setup outputs (proposal.md) go in 0-proposal dir
36
+ sync: '4-implement', // sync updates standards, works in implement space
37
+ };
38
+
39
+ /** Canonical phase ordering for PHASE_ORDER constant. */
40
+ const PHASE_ORDER = ['proposal', 'setup', 'uiux', 'design', 'clarify', 'tasks', 'implement', 'sync'];
41
+
42
+ /**
43
+ * Skill files that contain <!-- morph:outputs:PHASE --> blocks.
44
+ * Keyed by the phase name to inject, value is the file path relative to ROOT.
45
+ */
46
+ const SKILL_FILES = [
47
+ { file: 'framework/skills/level-1-workflows/phase-setup.md', phase: 'proposal' },
48
+ { file: 'framework/skills/level-1-workflows/phase-uiux.md', phase: 'uiux' },
49
+ { file: 'framework/skills/level-1-workflows/phase-design.md', phase: 'design' },
50
+ { file: 'framework/skills/level-1-workflows/phase-tasks.md', phase: 'tasks' },
51
+ { file: 'framework/skills/level-1-workflows/phase-implement.md', phase: 'implement' },
52
+ ];
53
+
54
+ // ============================================================================
55
+ // Derivation helpers
56
+ // ============================================================================
57
+
58
+ function derivePhaseDirs() {
59
+ const dirs = {};
60
+ for (const entry of Object.values(OUTPUT_SCHEMA)) {
61
+ dirs[entry.phase] = entry.phaseDir;
62
+ }
63
+ // Add extras in their canonical order (will be merged after schema-derived entries)
64
+ for (const [phase, dir] of Object.entries(PHASE_DIRS_EXTRAS)) {
65
+ dirs[phase] = dir;
66
+ }
67
+ // Re-order to match PHASE_ORDER
68
+ const ordered = {};
69
+ for (const phase of PHASE_ORDER) {
70
+ if (dirs[phase]) ordered[phase] = dirs[phase];
71
+ }
72
+ return ordered;
73
+ }
74
+
75
+ function deriveOutputPhaseMap() {
76
+ return Object.fromEntries(
77
+ Object.entries(OUTPUT_SCHEMA).map(([key, entry]) => [key, entry.phase])
78
+ );
79
+ }
80
+
81
+ function deriveFilenameToOutput() {
82
+ return Object.fromEntries(
83
+ Object.entries(OUTPUT_SCHEMA).map(([key, entry]) => [entry.filename, key])
84
+ );
85
+ }
86
+
87
+ function deriveProtectedSpecFiles() {
88
+ return Object.fromEntries(
89
+ Object.entries(OUTPUT_SCHEMA)
90
+ .filter(([, entry]) => entry.protected && entry.approvalGate)
91
+ .map(([, entry]) => [entry.filename, entry.approvalGate])
92
+ );
93
+ }
94
+
95
+ // ============================================================================
96
+ // phase-utils.js generator
97
+ // ============================================================================
98
+
99
+ /**
100
+ * Static utility functions that live in phase-utils.js.
101
+ * Not derived from OUTPUT_SCHEMA — they operate on file paths generically.
102
+ */
103
+ const UTIL_FUNCTIONS = `
104
+ /**
105
+ * Extract feature name from a .morph/features/{feature}/... path
106
+ * @param {string} filePath - File path to analyze
107
+ * @returns {string|null} Feature name or null
108
+ */
109
+ export function extractFeatureName(filePath) {
110
+ const normalized = filePath.replace(/\\\\/g, '/');
111
+ const match = normalized.match(/\\.morph\\/features\\/([^/]+)\\//);
112
+ return match ? match[1] : null;
113
+ }
114
+
115
+ /**
116
+ * Extract phase subdirectory from a .morph/features/{feature}/{phaseDir}/... path
117
+ * @param {string} filePath - File path to analyze
118
+ * @returns {string|null} Phase directory (e.g., '0-proposal', '1-design') or null
119
+ */
120
+ export function extractPhaseDir(filePath) {
121
+ const normalized = filePath.replace(/\\\\/g, '/');
122
+ const match = normalized.match(/\\.morph\\/features\\/[^/]+\\/(\\d+-[^/]+)\\//);
123
+ return match ? match[1] : null;
124
+ }
125
+
126
+ /**
127
+ * Check if a file path is inside .morph/features/
128
+ * @param {string} filePath
129
+ * @returns {boolean}
130
+ */
131
+ export function isFeaturePath(filePath) {
132
+ const normalized = filePath.replace(/\\\\/g, '/');
133
+ return normalized.includes('.morph/features/');
134
+ }
135
+
136
+ /**
137
+ * Check if a file path is inside .morph/framework/ (readonly)
138
+ * @param {string} filePath
139
+ * @returns {boolean}
140
+ */
141
+ export function isFrameworkPath(filePath) {
142
+ const normalized = filePath.replace(/\\\\/g, '/');
143
+ return normalized.includes('.morph/framework/');
144
+ }
145
+
146
+ /**
147
+ * Check if a file path is state.json
148
+ * @param {string} filePath
149
+ * @returns {boolean}
150
+ */
151
+ export function isStatePath(filePath) {
152
+ const normalized = filePath.replace(/\\\\/g, '/');
153
+ return normalized.endsWith('.morph/state.json');
154
+ }
155
+
156
+ /**
157
+ * Get the basename of a file path
158
+ * @param {string} filePath
159
+ * @returns {string}
160
+ */
161
+ export function getBasename(filePath) {
162
+ const normalized = filePath.replace(/\\\\/g, '/');
163
+ return normalized.split('/').pop();
164
+ }
165
+ `;
166
+
167
+ function formatJsObject(obj) {
168
+ const needsQuotes = (key) => /[^a-zA-Z0-9_$]/.test(key);
169
+ const entries = Object.entries(obj).map(([k, v]) => {
170
+ const fmtKey = needsQuotes(k) ? `'${k}'` : k;
171
+ return ` ${fmtKey}: '${v}',`;
172
+ });
173
+ return `{\n${entries.join('\n')}\n}`;
174
+ }
175
+
176
+ function generatePhaseUtilsContent() {
177
+ const phaseDirs = derivePhaseDirs();
178
+ const outputPhaseMap = deriveOutputPhaseMap();
179
+ const filenameToOut = deriveFilenameToOutput();
180
+ const protectedFiles = deriveProtectedSpecFiles();
181
+
182
+ return `// GENERATED by scripts/generate-refs.js — DO NOT EDIT manually
183
+ // Source of truth: src/core/paths/output-schema.js
184
+ // Regenerate with: node scripts/generate-refs.js
185
+ /**
186
+ * Shared phase utilities for Claude Code hooks.
187
+ *
188
+ * Maps phases to directories and output types.
189
+ */
190
+
191
+ /** Phase order */
192
+ export const PHASE_ORDER = ${JSON.stringify(PHASE_ORDER)};
193
+
194
+ /** Map phase → allowed output subdirectory */
195
+ export const PHASE_DIRS = ${formatJsObject(phaseDirs)};
196
+
197
+ /** Map output type (camelCase) → phase that produces it */
198
+ export const OUTPUT_PHASE_MAP = ${formatJsObject(outputPhaseMap)};
199
+
200
+ /** Map filename → output type (camelCase) */
201
+ export const FILENAME_TO_OUTPUT = ${formatJsObject(filenameToOut)};
202
+
203
+ /** Protected spec files and the approval gate that locks them */
204
+ export const PROTECTED_SPEC_FILES = ${formatJsObject(protectedFiles)};
205
+ ${UTIL_FUNCTIONS}`;
206
+ }
207
+
208
+ // ============================================================================
209
+ // Markdown block generator
210
+ // ============================================================================
211
+
212
+ function generateOutputTable(phaseName) {
213
+ const entries = Object.entries(OUTPUT_SCHEMA)
214
+ .filter(([, entry]) => entry.phase === phaseName);
215
+
216
+ if (entries.length === 0) return null;
217
+
218
+ const rows = entries
219
+ .map(([key, entry]) =>
220
+ `| \`${key}\` | \`.morph/features/{feature}/${entry.phaseDir}/${entry.filename}\` |`
221
+ )
222
+ .join('\n');
223
+
224
+ return `| Output | Caminho |\n|--------|---------|
225
+ ${rows}`;
226
+ }
227
+
228
+ function replaceMarkdownBlocks(content, phaseName) {
229
+ const table = generateOutputTable(phaseName);
230
+ if (!table) return { changed: false, content };
231
+
232
+ const updated = content.replace(
233
+ /<!-- morph:outputs:(\w+) -->([\s\S]*?)<!-- \/morph:outputs -->/g,
234
+ (_match, blockPhase, _inner) => {
235
+ const blockTable = generateOutputTable(blockPhase);
236
+ if (!blockTable) return _match;
237
+ return `<!-- morph:outputs:${blockPhase} -->\n${blockTable}\n<!-- /morph:outputs -->`;
238
+ }
239
+ );
240
+
241
+ return { changed: updated !== content, content: updated };
242
+ }
243
+
244
+ // ============================================================================
245
+ // Write / check helpers
246
+ // ============================================================================
247
+
248
+ let driftFound = false;
249
+
250
+ function writeOrCheck(filePath, generated, label) {
251
+ const current = existsSync(filePath) ? readFileSync(filePath, 'utf8') : null;
252
+
253
+ if (current === generated) {
254
+ console.log(` ✓ ${label} — up to date`);
255
+ return;
256
+ }
257
+
258
+ if (CHECK_MODE) {
259
+ console.error(` ✗ ${label} — DRIFT DETECTED (run: node scripts/generate-refs.js)`);
260
+ if (current === null) {
261
+ console.error(` File does not exist: ${filePath}`);
262
+ } else {
263
+ // Show first difference line
264
+ const curLines = current.split('\n');
265
+ const genLines = generated.split('\n');
266
+ for (let i = 0; i < Math.max(curLines.length, genLines.length); i++) {
267
+ if (curLines[i] !== genLines[i]) {
268
+ console.error(` First diff at line ${i + 1}:`);
269
+ console.error(` current: ${JSON.stringify(curLines[i] ?? '(missing)')}`);
270
+ console.error(` generated: ${JSON.stringify(genLines[i] ?? '(missing)')}`);
271
+ break;
272
+ }
273
+ }
274
+ }
275
+ driftFound = true;
276
+ } else {
277
+ writeFileSync(filePath, generated, 'utf8');
278
+ console.log(` ✎ ${label} — updated`);
279
+ }
280
+ }
281
+
282
+ // ============================================================================
283
+ // Main
284
+ // ============================================================================
285
+
286
+ console.log(CHECK_MODE ? '\nChecking generated refs...' : '\nGenerating refs from output-schema.js...');
287
+ console.log('');
288
+
289
+ // 1. Generate / check phase-utils.js
290
+ const phaseUtilsPath = join(ROOT, 'framework/hooks/shared/phase-utils.js');
291
+ const phaseUtilsContent = generatePhaseUtilsContent();
292
+ writeOrCheck(phaseUtilsPath, phaseUtilsContent, 'framework/hooks/shared/phase-utils.js');
293
+
294
+ // 2. Update / check morph:outputs blocks in skill markdown files
295
+ console.log('');
296
+ for (const { file, phase } of SKILL_FILES) {
297
+ const filePath = join(ROOT, file);
298
+ if (!existsSync(filePath)) {
299
+ console.log(` - ${file} — not found, skipping`);
300
+ continue;
301
+ }
302
+
303
+ const content = readFileSync(filePath, 'utf8');
304
+ const hasMarker = content.includes(`<!-- morph:outputs:${phase} -->`);
305
+
306
+ if (!hasMarker) {
307
+ console.log(` - ${file} — no morph:outputs:${phase} marker, skipping`);
308
+ continue;
309
+ }
310
+
311
+ const { changed, content: updated } = replaceMarkdownBlocks(content, phase);
312
+
313
+ if (!changed) {
314
+ console.log(` ✓ ${file} — up to date`);
315
+ } else if (CHECK_MODE) {
316
+ console.error(` ✗ ${file} — morph:outputs block DRIFT DETECTED`);
317
+ driftFound = true;
318
+ } else {
319
+ writeFileSync(filePath, updated, 'utf8');
320
+ console.log(` ✎ ${file} — morph:outputs block updated`);
321
+ }
322
+ }
323
+
324
+ console.log('');
325
+
326
+ if (CHECK_MODE) {
327
+ if (driftFound) {
328
+ console.error('FAIL: Generated files are out of sync with output-schema.js');
329
+ console.error(' Run: node scripts/generate-refs.js');
330
+ process.exit(1);
331
+ } else {
332
+ console.log('OK: All generated refs are in sync with output-schema.js');
333
+ }
334
+ } else {
335
+ console.log('Done. Commit any changed files.');
336
+ }
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * One-time script to generate framework/standards/STANDARDS.json
4
+ * by scanning all .md files in framework/standards/.
5
+ *
6
+ * Usage: node scripts/generate-standards-registry.js
7
+ */
8
+
9
+ import { readdirSync, statSync, writeFileSync } from 'fs';
10
+ import { join, relative } from 'path';
11
+ import { fileURLToPath } from 'url';
12
+
13
+ const __dirname = fileURLToPath(new URL('.', import.meta.url));
14
+ const BASE = join(__dirname, '..', 'framework', 'standards');
15
+
16
+ function scanDir(dir) {
17
+ const entries = [];
18
+ for (const f of readdirSync(dir)) {
19
+ const full = join(dir, f);
20
+ const rel = relative(BASE, full).replace(/\\/g, '/');
21
+ if (statSync(full).isDirectory()) {
22
+ entries.push(...scanDir(full));
23
+ } else if (f.endsWith('.md') && f !== 'README.md') {
24
+ const parts = rel.split('/');
25
+ entries.push({
26
+ id: rel.replace(/\//g, '-').replace('.md', ''),
27
+ name: f.replace('.md', '').replace(/-/g, ' '),
28
+ path: rel,
29
+ category: parts[0],
30
+ subcategory: parts.length > 2 ? parts[1] : null,
31
+ tags: parts.slice(0, -1),
32
+ });
33
+ }
34
+ }
35
+ return entries;
36
+ }
37
+
38
+ const standards = scanDir(BASE);
39
+ const registry = { version: '1.0.0', standards };
40
+ const outPath = join(BASE, 'STANDARDS.json');
41
+ writeFileSync(outPath, JSON.stringify(registry, null, 2) + '\n');
42
+ console.log(`Generated ${standards.length} standards entries`);
43
+ console.log(`Categories: ${[...new Set(standards.map(s => s.category))].join(', ')}`);
44
+ console.log(`Written to: ${outPath}`);
@@ -0,0 +1,255 @@
1
+ /**
2
+ * scripts/validate-real.mjs
3
+ *
4
+ * Real-world integration validation for output-schema.js centralization.
5
+ * Creates a temp .morph project, creates a feature, and verifies all paths.
6
+ *
7
+ * Usage: node scripts/validate-real.mjs
8
+ */
9
+
10
+ import { join, dirname } from 'path';
11
+ import { writeFileSync, mkdirSync, existsSync, readFileSync, rmSync } from 'fs';
12
+ import { spawnSync } from 'child_process';
13
+ import { fileURLToPath, pathToFileURL } from 'url';
14
+ import { tmpdir } from 'os';
15
+
16
+ // Helper: convert Windows absolute path to file:// URL for dynamic import
17
+ function toFileUrl(p) { return pathToFileURL(p).href; }
18
+
19
+ const __dirname = dirname(fileURLToPath(import.meta.url));
20
+ const ROOT = join(__dirname, '..');
21
+
22
+ let passed = 0;
23
+ let failed = 0;
24
+
25
+ function ok(label, condition, detail = '') {
26
+ if (condition) {
27
+ console.log(` ✓ ${label}`);
28
+ passed++;
29
+ } else {
30
+ console.error(` ✗ ${label}${detail ? '\n ' + detail : ''}`);
31
+ failed++;
32
+ }
33
+ }
34
+
35
+ function section(title) {
36
+ console.log(`\n── ${title} ──`);
37
+ }
38
+
39
+ // ============================================================================
40
+ // 1. output-schema.js — paths and derived constants
41
+ // ============================================================================
42
+ section('1. output-schema.js exports');
43
+
44
+ const {
45
+ OUTPUT_SCHEMA, getOutputPath, getAbsoluteOutputPath, getFeatureDir, getAllOutputPaths,
46
+ FILENAME_TO_OUTPUT, OUTPUT_PHASE_MAP, PROTECTED_SPEC_FILES,
47
+ } = await import(toFileUrl(join(ROOT, 'src/core/paths/output-schema.js')));
48
+
49
+ ok('OUTPUT_SCHEMA has 12 keys', Object.keys(OUTPUT_SCHEMA).length === 12);
50
+ ok('spec path correct',
51
+ getOutputPath('my-feature', 'spec') === '.morph/features/my-feature/1-design/spec.md');
52
+ ok('contracts path correct',
53
+ getOutputPath('my-feature', 'contracts') === '.morph/features/my-feature/1-design/contracts.cs');
54
+ ok('tasks path correct',
55
+ getOutputPath('my-feature', 'tasks') === '.morph/features/my-feature/3-tasks/tasks.md');
56
+ ok('uiDesignSystem path correct',
57
+ getOutputPath('my-feature', 'uiDesignSystem') === '.morph/features/my-feature/2-ui/design-system.md');
58
+ ok('clarifications path correct',
59
+ getOutputPath('my-feature', 'clarifications') === '.morph/features/my-feature/1-design/clarifications.md');
60
+ ok('recap path correct',
61
+ getOutputPath('my-feature', 'recap') === '.morph/features/my-feature/4-implement/recap.md');
62
+
63
+ const allPaths = Object.keys(OUTPUT_SCHEMA).map(k => getOutputPath('feat', k));
64
+ ok('no backslashes in any getOutputPath() result',
65
+ allPaths.every(p => !p.includes('\\')),
66
+ allPaths.filter(p => p.includes('\\')).join(', ') || 'all clean');
67
+
68
+ const absSpec = getAbsoluteOutputPath('/project', 'my-feature', 'spec');
69
+ ok('getAbsoluteOutputPath ends with spec.md', absSpec.endsWith('spec.md'));
70
+
71
+ const all = getAllOutputPaths('test-feat');
72
+ ok('getAllOutputPaths returns 12 entries', Object.keys(all).length === 12);
73
+ ok('getAllOutputPaths created:false for all', Object.values(all).every(v => v.created === false));
74
+ ok('getAllOutputPaths paths match getOutputPath',
75
+ Object.entries(all).every(([k, v]) => v.path === getOutputPath('test-feat', k)));
76
+
77
+ ok("FILENAME_TO_OUTPUT['spec.md'] === 'spec'", FILENAME_TO_OUTPUT['spec.md'] === 'spec');
78
+ ok("FILENAME_TO_OUTPUT['contracts.cs'] === 'contracts'", FILENAME_TO_OUTPUT['contracts.cs'] === 'contracts');
79
+ ok("OUTPUT_PHASE_MAP['spec'] === 'design'", OUTPUT_PHASE_MAP['spec'] === 'design');
80
+ ok("OUTPUT_PHASE_MAP['tasks'] === 'tasks'", OUTPUT_PHASE_MAP['tasks'] === 'tasks');
81
+ ok("PROTECTED_SPEC_FILES['spec.md'] === 'design'", PROTECTED_SPEC_FILES['spec.md'] === 'design');
82
+ ok("PROTECTED_SPEC_FILES['tasks.md'] === 'tasks'", PROTECTED_SPEC_FILES['tasks.md'] === 'tasks');
83
+ ok("PROTECTED_SPEC_FILES has no 'proposal.md'", !('proposal.md' in PROTECTED_SPEC_FILES));
84
+ ok("getFeatureDir uses forward slashes", !getFeatureDir('x').includes('\\'));
85
+ ok("getFeatureDir correct", getFeatureDir('my-feature') === '.morph/features/my-feature');
86
+
87
+ // ============================================================================
88
+ // 2. state-manager ensureFeature() creates correct paths in state.json
89
+ // ============================================================================
90
+ section('2. state-manager.js ensureFeature()');
91
+
92
+ // Create an isolated temp .morph project
93
+ const tempDir = join(tmpdir(), `morph-val-${Date.now()}`);
94
+ const morphDir = join(tempDir, '.morph');
95
+ const configDir = join(morphDir, 'config');
96
+ mkdirSync(configDir, { recursive: true });
97
+ mkdirSync(join(morphDir, 'features'), { recursive: true });
98
+ mkdirSync(join(morphDir, 'context'), { recursive: true });
99
+
100
+ writeFileSync(join(configDir, 'config.json'), JSON.stringify({
101
+ framework: 'morph-spec', project: { name: 'test-project' }
102
+ }, null, 2));
103
+
104
+ const origCwd = process.cwd();
105
+ process.chdir(tempDir);
106
+
107
+ const { initState, updateFeature, loadState } = await import(toFileUrl(join(ROOT, 'src/core/state/state-manager.js')));
108
+ // initState creates state.json; updateFeature calls ensureFeature internally
109
+ initState({ name: 'test-project', type: 'test' });
110
+ await updateFeature('my-feature', 'status', 'draft');
111
+ const state = loadState();
112
+ const feat = state.features['my-feature'];
113
+
114
+ process.chdir(origCwd);
115
+
116
+ ok('ensureFeature creates outputs block', !!feat?.outputs);
117
+ ok('outputs has 12 keys', Object.keys(feat?.outputs ?? {}).length === 12);
118
+
119
+ let allMatch = true;
120
+ const mismatches = [];
121
+ for (const [key, { path }] of Object.entries(feat?.outputs ?? {})) {
122
+ const expected = getOutputPath('my-feature', key);
123
+ if (path !== expected) {
124
+ allMatch = false;
125
+ mismatches.push(`${key}: got "${path}", expected "${expected}"`);
126
+ }
127
+ }
128
+ ok('ALL output paths match output-schema.js', allMatch, mismatches.join('\n '));
129
+
130
+ ok("spec path in state.json",
131
+ feat.outputs.spec?.path === '.morph/features/my-feature/1-design/spec.md');
132
+ ok("contracts path in state.json",
133
+ feat.outputs.contracts?.path === '.morph/features/my-feature/1-design/contracts.cs');
134
+ ok("uiDesignSystem path in state.json",
135
+ feat.outputs.uiDesignSystem?.path === '.morph/features/my-feature/2-ui/design-system.md');
136
+ ok("no backslashes in state.json output paths",
137
+ Object.values(feat.outputs).every(({ path }) => !path.includes('\\')));
138
+
139
+ // ============================================================================
140
+ // 3. v3 → v4 migration uses getAllOutputPaths
141
+ // ============================================================================
142
+ section('3. v3 → v4 migration');
143
+
144
+ // Write a v3.0.0 state in a fresh temp dir
145
+ const tempDir2 = join(tmpdir(), `morph-val2-${Date.now()}`);
146
+ const morphDir2 = join(tempDir2, '.morph');
147
+ const configDir2 = join(morphDir2, 'config');
148
+ mkdirSync(configDir2, { recursive: true });
149
+ mkdirSync(join(morphDir2, 'features'), { recursive: true });
150
+
151
+ const v3State = {
152
+ version: '3.0.0',
153
+ project: { name: 'legacy', type: 'test' },
154
+ features: {
155
+ 'legacy-feat': {
156
+ status: 'draft', phase: 'design',
157
+ outputs: {
158
+ spec: { created: true, path: '.morph/features/legacy-feat/spec.md' },
159
+ contracts: { created: false, path: '.morph/features/legacy-feat/contracts.cs' },
160
+ tasks: { created: false, path: '.morph/features/legacy-feat/tasks.md' },
161
+ }
162
+ }
163
+ },
164
+ metadata: { totalFeatures: 1, lastUpdated: new Date().toISOString() }
165
+ };
166
+ writeFileSync(join(morphDir2, 'state.json'), JSON.stringify(v3State, null, 2));
167
+
168
+ process.chdir(tempDir2);
169
+ // state-manager is already cached; read the file directly to check migration
170
+ // Re-use the already-imported module (ESM cache) — just call loadState directly
171
+ const migrated = loadState();
172
+ process.chdir(origCwd);
173
+
174
+ ok('version migrated to 4.0.0', migrated.version === '4.0.0');
175
+ ok('spec path migrated to 1-design subfolder',
176
+ migrated.features['legacy-feat'].outputs.spec?.path
177
+ === '.morph/features/legacy-feat/1-design/spec.md');
178
+ ok('contracts path migrated to 1-design subfolder',
179
+ migrated.features['legacy-feat'].outputs.contracts?.path
180
+ === '.morph/features/legacy-feat/1-design/contracts.cs');
181
+ ok('tasks path migrated to 3-tasks subfolder',
182
+ migrated.features['legacy-feat'].outputs.tasks?.path
183
+ === '.morph/features/legacy-feat/3-tasks/tasks.md');
184
+
185
+ // ============================================================================
186
+ // 4. phase-utils.js matches output-schema.js
187
+ // ============================================================================
188
+ section('4. phase-utils.js constants sync');
189
+
190
+ const {
191
+ FILENAME_TO_OUTPUT: PU_FTO,
192
+ OUTPUT_PHASE_MAP: PU_OPM,
193
+ PROTECTED_SPEC_FILES: PU_PSF,
194
+ PHASE_DIRS,
195
+ } = await import(toFileUrl(join(ROOT, 'framework/hooks/shared/phase-utils.js')));
196
+
197
+ ok('FILENAME_TO_OUTPUT matches schema', JSON.stringify(PU_FTO) === JSON.stringify(FILENAME_TO_OUTPUT));
198
+ ok('OUTPUT_PHASE_MAP matches schema', JSON.stringify(PU_OPM) === JSON.stringify(OUTPUT_PHASE_MAP));
199
+ ok('PROTECTED_SPEC_FILES matches schema', JSON.stringify(PU_PSF) === JSON.stringify(PROTECTED_SPEC_FILES));
200
+ ok("PHASE_DIRS['setup'] = '0-proposal' (manual extra)", PHASE_DIRS['setup'] === '0-proposal');
201
+ ok("PHASE_DIRS['sync'] = '4-implement' (manual extra)", PHASE_DIRS['sync'] === '4-implement');
202
+ ok("PHASE_DIRS['clarify'] = '1-design' (from schema)", PHASE_DIRS['clarify'] === '1-design');
203
+
204
+ // ============================================================================
205
+ // 5. generate-refs.js --check exits 0
206
+ // ============================================================================
207
+ section('5. generate-refs.js --check (CI mode)');
208
+
209
+ const checkResult = spawnSync(
210
+ process.execPath,
211
+ [join(ROOT, 'scripts/generate-refs.js'), '--check'],
212
+ { encoding: 'utf8' }
213
+ );
214
+
215
+ ok('exits 0 (no drift)', checkResult.status === 0,
216
+ checkResult.status !== 0 ? (checkResult.stdout + checkResult.stderr).trim() : '');
217
+ ok('reports all up to date',
218
+ (checkResult.stdout || '').includes('OK: All generated refs are in sync'));
219
+
220
+ // ============================================================================
221
+ // 6. Simulate "add new output type" round-trip
222
+ // ============================================================================
223
+ section('6. Error handling: invalid output type');
224
+
225
+ let threw = false;
226
+ try {
227
+ getOutputPath('my-feature', 'nonExistentType');
228
+ } catch (e) {
229
+ threw = e.message.includes('Unknown output type');
230
+ }
231
+ ok('getOutputPath throws on unknown type', threw);
232
+
233
+ let threw2 = false;
234
+ try {
235
+ getAbsoluteOutputPath('/proj', 'feat', 'bogus');
236
+ } catch (e) {
237
+ threw2 = e.message.includes('Unknown output type');
238
+ }
239
+ ok('getAbsoluteOutputPath throws on unknown type', threw2);
240
+
241
+ // ============================================================================
242
+ // Cleanup + summary
243
+ // ============================================================================
244
+ try { rmSync(tempDir, { recursive: true, force: true }); } catch {}
245
+ try { rmSync(tempDir2, { recursive: true, force: true }); } catch {}
246
+
247
+ console.log(`\n${'─'.repeat(52)}`);
248
+ console.log(`Results: ${passed} passed, ${failed} failed`);
249
+ if (failed === 0) {
250
+ console.log('✅ ALL VALIDATIONS PASSED');
251
+ process.exit(0);
252
+ } else {
253
+ console.error('❌ SOME VALIDATIONS FAILED');
254
+ process.exit(1);
255
+ }