@polymorphism-tech/morph-spec 4.7.0 → 4.7.2

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 (232) hide show
  1. package/.morph/.morphversion +5 -0
  2. package/.morph/analytics/threads-log.jsonl +5 -0
  3. package/.morph/config/config.json +8 -0
  4. package/.morph/framework/agents.json +1815 -0
  5. package/.morph/framework/hooks/README.md +205 -0
  6. package/.morph/framework/hooks/claude-code/notification/approval-reminder.js +54 -0
  7. package/.morph/framework/hooks/claude-code/post-tool-use/dispatch.js +83 -0
  8. package/.morph/framework/hooks/claude-code/post-tool-use/handle-tool-failure.js +42 -0
  9. package/.morph/framework/hooks/claude-code/pre-compact/save-morph-context.js +61 -0
  10. package/.morph/framework/hooks/claude-code/pre-tool-use/enforce-phase-writes.js +71 -0
  11. package/.morph/framework/hooks/claude-code/pre-tool-use/protect-readonly-files.js +58 -0
  12. package/.morph/framework/hooks/claude-code/pre-tool-use/protect-spec-files.js +64 -0
  13. package/.morph/framework/hooks/claude-code/session-start/inject-morph-context.js +94 -0
  14. package/.morph/framework/hooks/claude-code/statusline.py +538 -0
  15. package/.morph/framework/hooks/claude-code/statusline.sh +7 -0
  16. package/.morph/framework/hooks/claude-code/stop/validate-completion.js +88 -0
  17. package/.morph/framework/hooks/claude-code/user-prompt/enrich-prompt.js +91 -0
  18. package/.morph/framework/hooks/git/commit-msg/conventional-commits.sh +33 -0
  19. package/.morph/framework/hooks/git/pre-commit/agents.sh +25 -0
  20. package/.morph/framework/hooks/git/pre-commit/orchestrator.sh +64 -0
  21. package/.morph/framework/hooks/git/pre-commit/specs.sh +50 -0
  22. package/.morph/framework/hooks/git/pre-push/run-tests.sh +44 -0
  23. package/.morph/framework/hooks/shared/hook-response.js +45 -0
  24. package/.morph/framework/hooks/shared/phase-utils.js +129 -0
  25. package/.morph/framework/hooks/shared/state-reader.js +138 -0
  26. package/.morph/framework/hooks/shared/stdin-reader.js +26 -0
  27. package/.morph/framework/standards/STANDARDS.json +933 -0
  28. package/.morph/framework/standards/ai-agents/blazor-ui.md +364 -0
  29. package/.morph/framework/standards/ai-agents/production.md +415 -0
  30. package/.morph/framework/standards/ai-agents/setup.md +418 -0
  31. package/.morph/framework/standards/ai-agents/team-orchestration.md +479 -0
  32. package/.morph/framework/standards/ai-agents/workflows.md +354 -0
  33. package/.morph/framework/standards/architecture/ddd/aggregates.md +120 -0
  34. package/.morph/framework/standards/architecture/ddd/bounded-contexts.md +105 -0
  35. package/.morph/framework/standards/architecture/ddd/complexity-levels.md +108 -0
  36. package/.morph/framework/standards/architecture/ddd/entities.md +99 -0
  37. package/.morph/framework/standards/architecture/ddd/ubiquitous-language.md +58 -0
  38. package/.morph/framework/standards/architecture/ddd/value-objects.md +124 -0
  39. package/.morph/framework/standards/backend/api/minimal-api.md +494 -0
  40. package/.morph/framework/standards/backend/api/rest.md +492 -0
  41. package/.morph/framework/standards/backend/api/validation.md +88 -0
  42. package/.morph/framework/standards/backend/authentication/passkeys.md +428 -0
  43. package/.morph/framework/standards/backend/database/ef-core.md +199 -0
  44. package/.morph/framework/standards/backend/database/migrations.md +393 -0
  45. package/.morph/framework/standards/backend/database/postgresql/database.md +352 -0
  46. package/.morph/framework/standards/backend/database/repository-patterns.md +528 -0
  47. package/.morph/framework/standards/backend/database/vector-search-rag.md +541 -0
  48. package/.morph/framework/standards/backend/dotnet/async.md +366 -0
  49. package/.morph/framework/standards/backend/dotnet/core.md +117 -0
  50. package/.morph/framework/standards/backend/dotnet/di.md +439 -0
  51. package/.morph/framework/standards/backend/dotnet/program-cs-checklist.md +92 -0
  52. package/.morph/framework/standards/backend/integrations/asaas/asaas-api.md +216 -0
  53. package/.morph/framework/standards/backend/integrations/clerk/clerk-auth.md +290 -0
  54. package/.morph/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +350 -0
  55. package/.morph/framework/standards/backend/integrations/resend/resend-email.md +385 -0
  56. package/.morph/framework/standards/context/analytics.md +96 -0
  57. package/.morph/framework/standards/context/bundles.md +110 -0
  58. package/.morph/framework/standards/context/priming.md +78 -0
  59. package/.morph/framework/standards/core/architecture.md +185 -0
  60. package/.morph/framework/standards/core/coding.md +214 -0
  61. package/.morph/framework/standards/core/git-branching-strategy.md +403 -0
  62. package/.morph/framework/standards/core/git.md +185 -0
  63. package/.morph/framework/standards/core/testing.md +295 -0
  64. package/.morph/framework/standards/data/nosql/blob-storage.md +102 -0
  65. package/.morph/framework/standards/data/nosql/cache/redis.md +97 -0
  66. package/.morph/framework/standards/data/nosql/cosmos-db.md +118 -0
  67. package/.morph/framework/standards/data/vector-search/azure-ai-search.md +121 -0
  68. package/.morph/framework/standards/data/vector-search/rag-chunking.md +104 -0
  69. package/.morph/framework/standards/frontend/blazor/design-checklist.md +222 -0
  70. package/.morph/framework/standards/frontend/blazor/fluent-ui-setup.md +595 -0
  71. package/.morph/framework/standards/frontend/blazor/fluent-ui.md +137 -0
  72. package/.morph/framework/standards/frontend/blazor/html-conversion.md +184 -0
  73. package/.morph/framework/standards/frontend/blazor/lifecycle.md +195 -0
  74. package/.morph/framework/standards/frontend/blazor/pitfalls.md +198 -0
  75. package/.morph/framework/standards/frontend/blazor/state.md +191 -0
  76. package/.morph/framework/standards/frontend/design-system/animations.md +151 -0
  77. package/.morph/framework/standards/frontend/design-system/naming.md +64 -0
  78. package/.morph/framework/standards/frontend/nextjs/app-router.md +123 -0
  79. package/.morph/framework/standards/frontend/nextjs/components.md +132 -0
  80. package/.morph/framework/standards/frontend/nextjs/data-fetching.md +126 -0
  81. package/.morph/framework/standards/frontend/nextjs/forms.md +128 -0
  82. package/.morph/framework/standards/frontend/nextjs/naming-conventions.md +67 -0
  83. package/.morph/framework/standards/frontend/nextjs/nextjs-patterns.md +215 -0
  84. package/.morph/framework/standards/frontend/nextjs/project-structure.md +102 -0
  85. package/.morph/framework/standards/frontend/nextjs/state-management.md +72 -0
  86. package/.morph/framework/standards/frontend/nextjs/testing.md +111 -0
  87. package/.morph/framework/standards/infrastructure/azure/azure.md +624 -0
  88. package/.morph/framework/standards/infrastructure/azure/bicep/bicep-patterns.md +422 -0
  89. package/.morph/framework/standards/infrastructure/azure/devops/azure-devops-setup.md +516 -0
  90. package/.morph/framework/standards/infrastructure/azure/devops/local-development.md +520 -0
  91. package/.morph/framework/standards/infrastructure/azure/services/functions.md +486 -0
  92. package/.morph/framework/standards/infrastructure/azure/services/service-bus.md +459 -0
  93. package/.morph/framework/standards/infrastructure/azure/services/storage.md +407 -0
  94. package/.morph/framework/standards/infrastructure/docker/easypanel-deploy.md +196 -0
  95. package/.morph/framework/standards/infrastructure/supabase/mcp-setup.md +252 -0
  96. package/.morph/framework/standards/infrastructure/supabase/supabase-auth.md +176 -0
  97. package/.morph/framework/standards/infrastructure/supabase/supabase-pgvector.md +169 -0
  98. package/.morph/framework/standards/infrastructure/supabase/supabase-rls.md +184 -0
  99. package/.morph/framework/standards/infrastructure/supabase/supabase-storage.md +153 -0
  100. package/.morph/framework/standards/integration/api/graphql.md +91 -0
  101. package/.morph/framework/standards/integration/api/grpc.md +114 -0
  102. package/.morph/framework/standards/integration/api/rest-design.md +95 -0
  103. package/.morph/framework/standards/integration/event-driven/cqrs.md +101 -0
  104. package/.morph/framework/standards/integration/event-driven/event-sourcing.md +124 -0
  105. package/.morph/framework/standards/integration/event-driven/service-bus.md +95 -0
  106. package/.morph/framework/standards/integration/mcp/mcp-tools.md +384 -0
  107. package/.morph/framework/standards/observability/logging.md +131 -0
  108. package/.morph/framework/standards/observability/metrics.md +121 -0
  109. package/.morph/framework/standards/observability/monitoring.md +114 -0
  110. package/.morph/framework/standards/observability/tracing.md +132 -0
  111. package/.morph/framework/standards/workflows/parallel-execution.md +112 -0
  112. package/.morph/framework/standards/workflows/thread-management.md +113 -0
  113. package/.morph/framework/templates/.idea/morph-templates.xml +92 -0
  114. package/.morph/framework/templates/.vscode/morph-templates.code-snippets +186 -0
  115. package/.morph/framework/templates/IDE-SNIPPETS.md +266 -0
  116. package/.morph/framework/templates/README.md +814 -0
  117. package/.morph/framework/templates/REGISTRY.json +1888 -0
  118. package/.morph/framework/templates/code/dotnet/backend/repository.cs +141 -0
  119. package/.morph/framework/templates/code/dotnet/backend/service.cs +139 -0
  120. package/.morph/framework/templates/code/dotnet/contracts/Commands.cs +74 -0
  121. package/.morph/framework/templates/code/dotnet/contracts/Entities.cs +25 -0
  122. package/.morph/framework/templates/code/dotnet/contracts/Queries.cs +74 -0
  123. package/.morph/framework/templates/code/dotnet/contracts/README.md +74 -0
  124. package/.morph/framework/templates/code/dotnet/contracts/api-contracts.cs +173 -0
  125. package/.morph/framework/templates/code/dotnet/contracts/contracts-level1.cs +69 -0
  126. package/.morph/framework/templates/code/dotnet/contracts/contracts-level2.cs +86 -0
  127. package/.morph/framework/templates/code/dotnet/contracts/contracts-level3.cs +41 -0
  128. package/.morph/framework/templates/code/dotnet/database/migration.cs +83 -0
  129. package/.morph/framework/templates/code/dotnet/frontend/component.razor +239 -0
  130. package/.morph/framework/templates/code/dotnet/jobs/agent.cs +163 -0
  131. package/.morph/framework/templates/code/dotnet/jobs/job.cs +171 -0
  132. package/.morph/framework/templates/code/dotnet/test.cs +239 -0
  133. package/.morph/framework/templates/code/sql/rls-policy.sql +57 -0
  134. package/.morph/framework/templates/code/sql/supabase-migration.sql +100 -0
  135. package/.morph/framework/templates/code/sql/supabase-migration.template.sql +113 -0
  136. package/.morph/framework/templates/code/typescript/contracts.ts +168 -0
  137. package/.morph/framework/templates/context/CONTEXT-FEATURE.md +276 -0
  138. package/.morph/framework/templates/context/CONTEXT.md +181 -0
  139. package/.morph/framework/templates/docs/clarifications.md +253 -0
  140. package/.morph/framework/templates/docs/onboarding.md +123 -0
  141. package/.morph/framework/templates/docs/proposal.md +182 -0
  142. package/.morph/framework/templates/docs/schema-analysis.md +119 -0
  143. package/.morph/framework/templates/docs/spec.md +198 -0
  144. package/.morph/framework/templates/docs/ui-components.md +124 -0
  145. package/.morph/framework/templates/docs/ui-design-system.md +76 -0
  146. package/.morph/framework/templates/docs/ui-flows.md +167 -0
  147. package/.morph/framework/templates/docs/ui-mockups.md +98 -0
  148. package/.morph/framework/templates/docs/user-stories.md +34 -0
  149. package/.morph/framework/templates/examples/design-system-examples.md +357 -0
  150. package/.morph/framework/templates/examples/spec-examples.md +90 -0
  151. package/.morph/framework/templates/feature/decisions.md +187 -0
  152. package/.morph/framework/templates/feature/recap.md +146 -0
  153. package/.morph/framework/templates/feature/tasks.md +199 -0
  154. package/.morph/framework/templates/frontend/nextjs/Dockerfile.nextjs.hbs +43 -0
  155. package/.morph/framework/templates/frontend/nextjs/client-component.tsx.hbs +26 -0
  156. package/.morph/framework/templates/frontend/nextjs/env.mjs.hbs +32 -0
  157. package/.morph/framework/templates/frontend/nextjs/feature-form.tsx.hbs +56 -0
  158. package/.morph/framework/templates/frontend/nextjs/page.tsx.hbs +22 -0
  159. package/.morph/framework/templates/frontend/nextjs/tsconfig.json.hbs +26 -0
  160. package/.morph/framework/templates/frontend/nextjs/use-feature.ts.hbs +54 -0
  161. package/.morph/framework/templates/infrastructure/azure/Dockerfile.example +82 -0
  162. package/.morph/framework/templates/infrastructure/azure/README.md +286 -0
  163. package/.morph/framework/templates/infrastructure/azure/app-insights.bicep +63 -0
  164. package/.morph/framework/templates/infrastructure/azure/app-service.bicep +164 -0
  165. package/.morph/framework/templates/infrastructure/azure/container-app-env.bicep +49 -0
  166. package/.morph/framework/templates/infrastructure/azure/container-app.bicep +156 -0
  167. package/.morph/framework/templates/infrastructure/azure/deploy-checklist.md +426 -0
  168. package/.morph/framework/templates/infrastructure/azure/deploy.ps1 +229 -0
  169. package/.morph/framework/templates/infrastructure/azure/deploy.sh +208 -0
  170. package/.morph/framework/templates/infrastructure/azure/key-vault.bicep +91 -0
  171. package/.morph/framework/templates/infrastructure/azure/main.bicep +189 -0
  172. package/.morph/framework/templates/infrastructure/azure/parameters.dev.json +29 -0
  173. package/.morph/framework/templates/infrastructure/azure/parameters.prod.json +29 -0
  174. package/.morph/framework/templates/infrastructure/azure/parameters.staging.json +29 -0
  175. package/.morph/framework/templates/infrastructure/azure/sql-database.bicep +103 -0
  176. package/.morph/framework/templates/infrastructure/azure/storage.bicep +106 -0
  177. package/.morph/framework/templates/infrastructure/docker/Dockerfile.template +58 -0
  178. package/.morph/framework/templates/infrastructure/docker/docker-compose.template.yml +67 -0
  179. package/.morph/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -0
  180. package/.morph/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -0
  181. package/.morph/framework/templates/infrastructure/docker/easypanel.template.json +54 -0
  182. package/.morph/framework/templates/infrastructure/github/README.md +593 -0
  183. package/.morph/framework/templates/infrastructure/github/actions/azure-auth/action.yml.hbs +22 -0
  184. package/.morph/framework/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +45 -0
  185. package/.morph/framework/templates/infrastructure/github/actions/health-check/action.yml.hbs +27 -0
  186. package/.morph/framework/templates/infrastructure/github/workflows/deploy-azure-app-service.yml.hbs +61 -0
  187. package/.morph/framework/templates/infrastructure/github/workflows/deploy-easypanel.yml.hbs +31 -0
  188. package/.morph/framework/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +59 -0
  189. package/.morph/framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +39 -0
  190. package/.morph/framework/templates/integrations/asaas-client.cs +387 -0
  191. package/.morph/framework/templates/integrations/asaas-webhook.cs +351 -0
  192. package/.morph/framework/templates/integrations/azure-identity-config.cs +288 -0
  193. package/.morph/framework/templates/integrations/clerk-config.cs +258 -0
  194. package/.morph/framework/templates/meta-prompts/fusion/fusion-agent.md +76 -0
  195. package/.morph/framework/templates/meta-prompts/fusion/fusion-aggregator.md +100 -0
  196. package/.morph/framework/templates/meta-prompts/hops/hop-retry.md +78 -0
  197. package/.morph/framework/templates/meta-prompts/hops/hop-validation.md +97 -0
  198. package/.morph/framework/templates/meta-prompts/hops/hop-wrapper.md +36 -0
  199. package/.morph/framework/templates/meta-prompts/parallel-workers/parallel-coordinator.md +113 -0
  200. package/.morph/framework/templates/meta-prompts/parallel-workers/parallel-worker.md +80 -0
  201. package/.morph/framework/templates/meta-prompts/squad-leaders/backend-squad.md +90 -0
  202. package/.morph/framework/templates/meta-prompts/squad-leaders/frontend-squad.md +126 -0
  203. package/.morph/framework/templates/meta-prompts/squad-leaders/squad-leader.md +43 -0
  204. package/.morph/framework/templates/meta-prompts/validators/checkpoint-validator.md +107 -0
  205. package/.morph/framework/templates/meta-prompts/validators/pre-commit-validator.md +95 -0
  206. package/.morph/framework/templates/project-structure/dotnet-ddd.md +70 -0
  207. package/.morph/framework/templates/saas/subscription.cs +347 -0
  208. package/.morph/framework/templates/saas/tenant.cs +338 -0
  209. package/.morph/framework/templates/state.template.json +17 -0
  210. package/.morph/framework/templates/ui/FluentDesignTheme.cs +149 -0
  211. package/.morph/framework/templates/ui/MudTheme.cs +281 -0
  212. package/.morph/framework/templates/ui/design-system.css +226 -0
  213. package/.morph/logs/tool-failures.log +17 -0
  214. package/.morph/memory/pre-compact-2026-02-24T17-43-30-049Z.json +16 -0
  215. package/.morph/plans/eager-watching-bunny.md +105 -0
  216. package/.morph/plans/temporal-seeking-nebula.md +45 -0
  217. package/.morph/state.json +48 -0
  218. package/CLAUDE.md +1 -1
  219. package/README.md +119 -99
  220. package/bin/morph-spec.js +0 -9
  221. package/framework/CLAUDE.md +1 -1
  222. package/framework/hooks/README.md +10 -6
  223. package/framework/hooks/claude-code/notification/approval-reminder.js +2 -0
  224. package/framework/hooks/claude-code/post-tool-use/dispatch.js +1 -1
  225. package/framework/hooks/claude-code/stop/validate-completion.js +1 -1
  226. package/framework/hooks/claude-code/user-prompt/enrich-prompt.js +1 -1
  227. package/package.json +1 -1
  228. package/src/commands/project/init.js +15 -42
  229. package/src/commands/project/update.js +22 -37
  230. package/src/lib/installers/mcp-installer.js +18 -3
  231. package/src/utils/hooks-installer.js +5 -15
  232. package/src/commands/project/detect.js +0 -114
@@ -56,7 +56,7 @@
56
56
  proposal → setup → [uiux] → design → clarify → tasks → implement → [sync]
57
57
  ```
58
58
 
59
- Use `morph-spec state show {feature}` to see current phase and pending approval gates.
59
+ Use `morph-spec status {feature}` to see current phase and pending approval gates.
60
60
 
61
61
  ---
62
62
 
@@ -47,13 +47,13 @@ framework/hooks/
47
47
  |-------|------|------|---------|
48
48
  | **SessionStart** | inject-morph-context.js | Inject context | Shows active feature, phase, pending approvals |
49
49
  | **UserPromptSubmit** | enrich-prompt.js | Inject context | Warns about wrong-phase work, injects commands |
50
- | **PreToolUse** (Write\|Edit) | protect-readonly-files.js | Block | Blocks edits to state.json and .morph/framework/ |
50
+ | **PreToolUse** (Write\|Edit) | _(native permissions.deny)_ | Block | Blocks edits to state.json and .morph/framework/ |
51
51
  | **PreToolUse** (Write\|Edit) | protect-spec-files.js | Block | Blocks edits to spec files after approval |
52
52
  | **PreToolUse** (Write\|Edit) | enforce-phase-writes.js | Block | Ensures writes go to current phase directory |
53
53
  | **PreToolUse** (Bash) | _(prompt-type inline guard)_ | Block | Blocks `rm -rf .morph/` and direct state edits via Claude's reasoning |
54
- | **PostToolUse** (Write) | track-output-creation.js | Auto-state | Marks outputs as created when files are written |
55
54
  | **PostToolUse** (Bash) | dispatch.js | Dispatch | Triggers checkpoints on task completion |
56
- | **Stop** | validate-completion.js | Advisory | Warns about incomplete tasks/outputs |
55
+ | **PostToolUseFailure** | handle-tool-failure.js | Logging | Appends structured JSON to .morph/logs/tool-failures.log |
56
+ | **Stop** | validate-completion.js | Advisory | Warns about incomplete tasks/missing outputs/pending gates |
57
57
  | **PreCompact** | save-morph-context.js | Snapshot | Saves state to .morph/memory/ before compaction |
58
58
  | **Notification** | approval-reminder.js | Advisory | Reminds about pending approval gates |
59
59
 
@@ -69,6 +69,10 @@ framework/hooks/
69
69
 
70
70
  Hooks are automatically installed by `morph-spec init` and updated by `morph-spec update`.
71
71
 
72
+ During init/update, the entire `framework/hooks/` directory is copied to `.morph/framework/hooks/`.
73
+ Hook commands in `.claude/settings.local.json` reference `$CLAUDE_PROJECT_DIR/.morph/framework/hooks/`
74
+ so they work correctly in any project regardless of how morph-spec was installed.
75
+
72
76
  The installer writes to `.claude/settings.local.json`:
73
77
 
74
78
  ```json
@@ -122,10 +126,10 @@ Claude calls Write/Edit tool
122
126
 
123
127
  Claude Code sends JSON to stdin: { tool_input: { file_path: "..." } }
124
128
 
125
- protect-readonly-files.js
129
+ [native permissions.deny]
126
130
  ├── Is .morph/state.json? → BLOCK (use CLI)
127
131
  ├── Is .morph/framework/**? → BLOCK (read-only)
128
- └── Other → pass
132
+ └── Other → continue
129
133
 
130
134
  protect-spec-files.js
131
135
  ├── Is in .morph/features/{feature}/?
@@ -198,4 +202,4 @@ morph-spec doctor --reset
198
202
 
199
203
  ---
200
204
 
201
- *MORPH-SPEC v4.3.7 — Hooks Architecture v2*
205
+ *MORPH-SPEC v4.5.0 — Hooks Architecture v2.5*
@@ -26,6 +26,8 @@ try {
26
26
 
27
27
  // Only remind about gates relevant to the current phase
28
28
  const phaseGateRelevance = {
29
+ proposal: ['proposal'],
30
+ setup: ['proposal'],
29
31
  design: ['design'],
30
32
  clarify: ['design'],
31
33
  tasks: ['design', 'tasks'],
@@ -46,7 +46,7 @@ function dispatch(command) {
46
46
  const completed = (feature.tasks.completed || 0) + 1; // +1 because task-done hasn't executed yet
47
47
  if (completed > 0 && completed % 3 === 0) {
48
48
  const checkpointNum = Math.floor(completed / 3);
49
- run(`node bin/morph-spec.js checkpoint-save ${featureName} --note "Auto-checkpoint #${checkpointNum} at task ${completed}"`);
49
+ run(`morph-spec checkpoint-save ${featureName} --note "Auto-checkpoint #${checkpointNum} at task ${completed}"`);
50
50
  }
51
51
  }
52
52
  } catch {
@@ -58,7 +58,7 @@ try {
58
58
  // Check pending approval gates
59
59
  if (feature.approvalGates) {
60
60
  const pendingGates = Object.entries(feature.approvalGates)
61
- .filter(([, gate]) => !gate.approved && gate.timestamp === null)
61
+ .filter(([, gate]) => !gate.approved && !gate.timestamp)
62
62
  .map(([name]) => name);
63
63
 
64
64
  // Only warn about gates relevant to current/past phases
@@ -24,7 +24,7 @@ try {
24
24
  const payload = await readStdin();
25
25
  if (!payload) pass();
26
26
 
27
- const userPrompt = payload?.user_prompt || payload?.content || '';
27
+ const userPrompt = payload?.prompt || payload?.user_prompt || payload?.content || '';
28
28
  if (!userPrompt || userPrompt.length < 3) pass();
29
29
 
30
30
  const promptLower = userPrompt.toLowerCase();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polymorphism-tech/morph-spec",
3
- "version": "4.7.0",
3
+ "version": "4.7.2",
4
4
  "description": "MORPH-SPEC: AI-First development framework with validation pipeline and multi-stack support",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -18,8 +18,6 @@ import { saveProjectMorphVersion, getInstalledCLIVersion } from '../../utils/ver
18
18
  import { installClaudeHooks, installGlobalStatusline } from '../../utils/claude-settings-manager.js';
19
19
  import { installSkills } from '../../utils/skills-installer.js';
20
20
  import { installAgents, installDomainAgents } from '../../utils/agents-installer.js';
21
- import { AutoContextOrchestrator } from '../../core/orchestrator.js';
22
- import { detectClaudeCode } from '../../llm/environment-detector.js';
23
21
  import inquirer from 'inquirer';
24
22
  import { detectProject } from '../../lib/detectors/index.js';
25
23
  import { detectClaudeConfig, mapMcpsToPhases, formatConfigSummary } from '../../lib/detectors/claude-config-detector.js';
@@ -102,11 +100,11 @@ export async function initCommand(options) {
102
100
 
103
101
  ## Overview
104
102
 
105
- This file will be auto-updated by MORPH-SPEC detection system.
103
+ This file describes your project context for MORPH-SPEC agents.
106
104
 
107
105
  ## Stack
108
106
 
109
- Run \`morph-spec detect\` to analyze your project.
107
+ Edit this file to describe your project context.
110
108
 
111
109
  ## Technologies
112
110
 
@@ -139,6 +137,14 @@ Run \`morph-spec detect\` to analyze your project.
139
137
  logger.dim(' ✓ Copied framework standards: core/, backend/, frontend/, infrastructure/');
140
138
  }
141
139
 
140
+ // 6c. Copy hooks to .morph/framework/hooks/ (required for hook commands at runtime)
141
+ spinner.text = 'Copying hooks...';
142
+ const hooksSrc = join(import.meta.dirname, '..', '..', '..', 'framework', 'hooks');
143
+ const hooksDest = join(frameworkDestDir, 'hooks');
144
+ if (await pathExists(hooksSrc)) {
145
+ await copyDirectory(hooksSrc, hooksDest);
146
+ }
147
+
142
148
  // 7. Copy agents.json (sourced from framework/ — canonical single source of truth)
143
149
  spinner.text = 'Copying agents configuration...';
144
150
  const agentsSrc = join(import.meta.dirname, '..', '..', '..', 'framework', 'agents.json');
@@ -467,10 +473,9 @@ Run \`morph-spec detect\` to analyze your project.
467
473
  logger.blank();
468
474
  logger.header('Next Steps');
469
475
 
470
- logger.step(1, 'Run detection: morph-spec detect');
471
- logger.step(2, 'Review .morph/config/config.json and .morph/context/standards.md');
472
- logger.step(3, 'Open project in VS Code with Claude Code');
473
- logger.step(4, 'Start your first feature:');
476
+ logger.step(1, 'Review .morph/config/config.json');
477
+ logger.step(2, 'Open project in VS Code with Claude Code');
478
+ logger.step(3, 'Start your first feature:');
474
479
  logger.blank();
475
480
  logger.box([
476
481
  'Ask Claude Code to implement a feature'
@@ -480,7 +485,7 @@ Run \`morph-spec detect\` to analyze your project.
480
485
  logger.info('Files installed:');
481
486
  logger.dim(` ✓ CLAUDE.md`);
482
487
  logger.dim(` ✓ .morph/config/ (config.json)`);
483
- logger.dim(` ✓ .morph/framework/ (agents.json, standards/, templates/)`);
488
+ logger.dim(` ✓ .morph/framework/ (agents.json, standards/, templates/, hooks/)`);
484
489
  logger.dim(` ✓ .morph/context/ (project context)`);
485
490
  logger.dim(` ✓ .morph/features/ (feature outputs)`);
486
491
  if (commandsCopied) {
@@ -503,42 +508,10 @@ Run \`morph-spec detect\` to analyze your project.
503
508
 
504
509
  logger.dim(' ✓ .claude/skills/ (installed as skill directories)');
505
510
  logger.dim(' ✓ .claude/agents/ (native subagents installed)');
511
+ logger.dim(' ✓ ~/.claude/statusline.sh (global statusline installed)');
506
512
 
507
513
  logger.blank();
508
514
 
509
- // 13. LLM-based auto-detect project context (if Claude Code is available and not --skip-detection)
510
- if (!options.skipDetection && detectClaudeCode()) {
511
- logger.blank();
512
- logger.header('Auto-Detecting Project Context');
513
- logger.dim('Using Claude Code LLM to analyze your project...');
514
- logger.blank();
515
-
516
- try {
517
- const orchestrator = new AutoContextOrchestrator();
518
- const result = await orchestrator.execute(targetPath, {
519
- skipReview: false,
520
- fallbackOnError: true,
521
- wizardMode: options.wizard || false
522
- });
523
-
524
- if (result.success) {
525
- logger.success('Project context detected and saved to .morph/project.md');
526
- } else {
527
- logger.warn('Auto-detection incomplete. Run "morph-spec update" to retry.');
528
- }
529
- } catch (error) {
530
- logger.warn(`Auto-detection failed: ${error.message}`);
531
- logger.dim('You can run "morph-spec update" later to re-analyze your project.');
532
- }
533
- } else if (options.skipDetection) {
534
- logger.dim('\nSkipped auto-detection (--skip-detection flag)');
535
- logger.dim('Run "morph-spec update" later to analyze your project.');
536
- } else {
537
- logger.warn('\n⚠️ Claude Code not detected');
538
- logger.dim('Auto-detection requires Claude Code CLI.');
539
- logger.dim('Run "morph-spec update --wizard" to configure manually.');
540
- }
541
-
542
515
  // Suggest tutorial for first-time users
543
516
  if (integrationsCreated) {
544
517
  logger.blank();
@@ -24,11 +24,9 @@ import {
24
24
  getUpdateInstructions,
25
25
  detectInstallMethod
26
26
  } from '../../utils/version-checker.js';
27
- import { installClaudeHooks } from '../../utils/claude-settings-manager.js';
27
+ import { installClaudeHooks, installGlobalStatusline } from '../../utils/claude-settings-manager.js';
28
28
  import { installSkills } from '../../utils/skills-installer.js';
29
29
  import { installAgents, installDomainAgents } from '../../utils/agents-installer.js';
30
- import { AutoContextOrchestrator } from '../../core/orchestrator.js';
31
- import { detectClaudeCode } from '../../llm/environment-detector.js';
32
30
 
33
31
  /**
34
32
  * Backup user's config.json before cleaning
@@ -57,6 +55,7 @@ async function cleanFrameworkDirs(morphPath, targetPath) {
57
55
  const dirsToClean = [
58
56
  join(morphPath, 'framework', 'templates'),
59
57
  join(morphPath, 'framework', 'standards'),
58
+ join(morphPath, 'framework', 'hooks'),
60
59
  join(morphPath, 'config'),
61
60
  join(targetPath, '.claude')
62
61
  ];
@@ -208,6 +207,14 @@ export async function updateCommand(options) {
208
207
  await copyDirectory(standardsSrc, standardsDest);
209
208
  }
210
209
 
210
+ // Update hooks (runtime hook scripts under .morph/framework/hooks/)
211
+ updateSpinner.text = 'Updating hooks...';
212
+ const hooksSrc = join(__dirname, '..', '..', '..', 'framework', 'hooks');
213
+ const hooksDest = join(morphPath, 'framework', 'hooks');
214
+ if (await pathExists(hooksSrc)) {
215
+ await copyDirectory(hooksSrc, hooksDest);
216
+ }
217
+
211
218
  // Update agents.json (sourced from framework/ — canonical single source of truth)
212
219
  updateSpinner.text = 'Updating agents configuration...';
213
220
  const agentsSrc = join(__dirname, '..', '..', '..', 'framework', 'agents.json');
@@ -279,6 +286,16 @@ export async function updateCommand(options) {
279
286
  await copyFile(runtimeSrc, runtimeDest);
280
287
  }
281
288
 
289
+ // Sync statusline globally to ~/.claude/
290
+ updateSpinner.text = 'Syncing statusline to ~/.claude/...';
291
+ const HOOKS_SRC = join(__dirname, '..', '..', '..', 'framework', 'hooks', 'claude-code');
292
+ try {
293
+ await installGlobalStatusline(HOOKS_SRC);
294
+ } catch {
295
+ // Non-critical: global dir may not be writable in all environments
296
+ logger.dim(' ⚠ Could not install statusline globally (non-critical)');
297
+ }
298
+
282
299
  // Update Claude Code hooks in .claude/settings.local.json
283
300
  updateSpinner.text = 'Updating Claude Code hooks...';
284
301
  const hooksResult = await installClaudeHooks(targetPath);
@@ -314,6 +331,7 @@ export async function updateCommand(options) {
314
331
  logger.info('Updated files:');
315
332
  if (updateTemplates) logger.dim(' ✓ .morph/framework/templates/');
316
333
  if (updateStandards) logger.dim(' ✓ .morph/framework/standards/');
334
+ logger.dim(' ✓ .morph/framework/hooks/');
317
335
  logger.dim(' ✓ .morph/framework/agents.json');
318
336
  if (commandsCopied) logger.dim(' ✓ .claude/commands/');
319
337
 
@@ -322,46 +340,13 @@ export async function updateCommand(options) {
322
340
  logger.dim(' ✓ .claude/agents/ (native subagents refreshed)');
323
341
  logger.dim(' ✓ .claude/rules/ (path-scoped rules synced)');
324
342
  logger.dim(' ✓ .claude/CLAUDE.md (runtime quick reference)');
343
+ logger.dim(' ✓ ~/.claude/statusline.sh (global statusline synced)');
325
344
  logger.dim(' ✓ CLAUDE.md');
326
345
  logger.blank();
327
346
  logger.info('Your config.json was preserved.');
328
347
  logger.dim('Review the updated files for any new features.');
329
348
  logger.blank();
330
349
 
331
- // Re-analyze project context (unless --skip-detection)
332
- if (!options.skipDetection && detectClaudeCode()) {
333
- logger.header('Re-Analyzing Project Context');
334
- logger.dim('Using Claude Code LLM to update project detection...');
335
- logger.blank();
336
-
337
- try {
338
- const orchestrator = new AutoContextOrchestrator();
339
- const result = await orchestrator.execute(targetPath, {
340
- skipReview: false,
341
- fallbackOnError: true,
342
- wizardMode: options.wizard || false
343
- });
344
-
345
- if (result.success) {
346
- logger.success('Project context re-analyzed and updated');
347
- logger.dim(' ✓ .morph/project.md updated with latest detection');
348
- logger.dim(' ✓ .morph/config/config.json updated with stack info');
349
- } else {
350
- logger.warn('Context re-analysis incomplete');
351
- }
352
- } catch (error) {
353
- logger.warn(`Auto-detection failed: ${error.message}`);
354
- logger.dim('Your existing config.json was preserved.');
355
- }
356
-
357
- logger.blank();
358
- } else if (options.skipDetection) {
359
- logger.dim('Skipped auto-detection (--skip-detection flag)');
360
- } else {
361
- logger.warn('⚠️ Claude Code not detected - skipping auto-detection');
362
- logger.dim('Run with --wizard to configure manually.');
363
- }
364
-
365
350
  } catch (error) {
366
351
  updateSpinner.fail('Update failed');
367
352
  logger.error(error.message);
@@ -96,6 +96,21 @@ export function checkPrerequisites(mcpEntry) {
96
96
  return results;
97
97
  }
98
98
 
99
+ /**
100
+ * Patch MCP config for the current platform.
101
+ * On Windows, npx must be invoked via `cmd /C` to avoid ENOENT errors.
102
+ * @param {Object} config - MCP server config { command, args, env? }
103
+ * @returns {Object} Patched config (new object, original unmodified)
104
+ */
105
+ export function patchConfigForPlatform(config) {
106
+ if (process.platform !== 'win32' || config.command !== 'npx') return config;
107
+ return {
108
+ ...config,
109
+ command: 'cmd',
110
+ args: ['/C', 'npx', ...(config.args || [])]
111
+ };
112
+ }
113
+
99
114
  /**
100
115
  * Install auto-installable MCPs (no credentials, no prerequisites)
101
116
  * @param {string} targetPath - Project root directory
@@ -106,12 +121,12 @@ export async function installAutoMcps(targetPath, mcpsToInstall) {
106
121
  const servers = {};
107
122
 
108
123
  for (const [name, entry] of Object.entries(mcpsToInstall)) {
109
- const config = { ...entry.install.config };
124
+ let config = { ...entry.install.config };
110
125
  // Only include env if it has actual values
111
126
  if (config.env && Object.values(config.env).every(v => !v)) {
112
127
  delete config.env;
113
128
  }
114
- servers[name] = config;
129
+ servers[name] = patchConfigForPlatform(config);
115
130
  }
116
131
 
117
132
  return installMcpServers(targetPath, servers);
@@ -126,7 +141,7 @@ export async function installAutoMcps(targetPath, mcpsToInstall) {
126
141
  * @returns {Promise<Object>} Result from installMcpServers
127
142
  */
128
143
  export async function installMcpWithCredentials(targetPath, name, mcpEntry, credentialValues) {
129
- const config = { ...mcpEntry.install.config };
144
+ const config = patchConfigForPlatform({ ...mcpEntry.install.config });
130
145
  config.env = { ...config.env, ...credentialValues };
131
146
  return installMcpServers(targetPath, { [name]: config });
132
147
  }
@@ -14,7 +14,7 @@ import { existsSync, chmodSync } from 'fs';
14
14
  import { homedir } from 'os';
15
15
 
16
16
  /** Current hooks schema version — bump when hook definitions change */
17
- const HOOKS_VERSION = '2.4.0';
17
+ const HOOKS_VERSION = '2.5.0';
18
18
 
19
19
  /** Marker for old dispatch.js (v1) */
20
20
  const OLD_DISPATCH_COMMAND = 'node framework/hooks/agent-teams/dispatch.js';
@@ -104,19 +104,8 @@ Otherwise respond: {"ok": true}`
104
104
  event: 'Stop',
105
105
  matcher: null,
106
106
  hooks: [{
107
- type: 'agent',
108
- prompt: `Check if the active morph-spec feature phase outputs are complete.
109
- 1. Read the file .morph/state.json to find features with status "in_progress".
110
- 2. For each in_progress feature, check if required output files for the current phase exist and are non-empty.
111
- - proposal phase: .morph/features/{feature}/0-proposal/proposal.md
112
- - design phase: .morph/features/{feature}/1-design/spec.md
113
- - tasks phase: .morph/features/{feature}/3-tasks/tasks.md
114
- - implement phase: check tasks.completed vs tasks.total from state.json
115
- 3. If all required outputs exist and tasks are complete, return {"ok": true}.
116
- 4. If any required output is missing or empty, return {"ok": false, "reason": "Missing output: <path>"}.
117
- 5. If state.json does not exist or no feature is in_progress, return {"ok": true}.
118
- Do NOT modify any files. Read only.`,
119
- timeout: 60
107
+ type: 'command',
108
+ command: 'node framework/hooks/claude-code/stop/validate-completion.js'
120
109
  }]
121
110
  },
122
111
 
@@ -209,9 +198,10 @@ export async function installClaudeHooks(targetPath) {
209
198
  return agentHook;
210
199
  }
211
200
  // Command hooks: transform path to use $CLAUDE_PROJECT_DIR
201
+ // Hooks are copied to .morph/framework/hooks/ during `morph-spec init/update`
212
202
  return {
213
203
  type: h.type,
214
- command: `node "$CLAUDE_PROJECT_DIR/framework/hooks/claude-code/${getHookSubpath(h.command)}"`,
204
+ command: `node "$CLAUDE_PROJECT_DIR/.morph/framework/hooks/claude-code/${getHookSubpath(h.command)}"`,
215
205
  ...(h.timeout !== undefined ? { timeout: h.timeout } : {})
216
206
  };
217
207
  });
@@ -1,114 +0,0 @@
1
- import { join } from 'path';
2
- import ora from 'ora';
3
- import chalk from 'chalk';
4
- import { logger } from '../../utils/logger.js';
5
- import { detectProject, getDetectionSummary } from '../../lib/detectors/index.js';
6
- import { ensureDir, writeFile, readJson, writeJson, pathExists } from '../../utils/file-copier.js';
7
-
8
- export async function detectCommand(options) {
9
- const targetPath = options.path || process.cwd();
10
-
11
- logger.header('MORPH-SPEC Project Detection');
12
- logger.dim(`Analyzing: ${targetPath}`);
13
- logger.blank();
14
-
15
- const spinner = ora('Detecting project structure...').start();
16
-
17
- try {
18
- // Run detection
19
- const results = await detectProject(targetPath, {
20
- structure: true,
21
- config: true,
22
- conversation: true,
23
- generateStandards: true
24
- });
25
-
26
- spinner.succeed('Detection complete!');
27
- logger.blank();
28
-
29
- // Display summary
30
- logger.header('Detection Results');
31
- logger.blank();
32
-
33
- // Stack
34
- logger.info(`Stack: ${chalk.cyan(results.structure.stack)}`);
35
- logger.info(`Architecture: ${chalk.cyan(results.structure.architecture)}`);
36
- if (results.structure.uiLibrary) {
37
- logger.info(`UI Library: ${chalk.cyan(results.structure.uiLibrary)}`);
38
- }
39
- logger.blank();
40
-
41
- // Technologies
42
- if (results.config.technologies.length > 0) {
43
- logger.header('Technologies:');
44
- results.config.technologies.forEach(tech => {
45
- logger.dim(` - ${tech}`);
46
- });
47
- logger.blank();
48
- }
49
-
50
- // Patterns
51
- if (results.structure.patterns.length > 0) {
52
- logger.header('Patterns:');
53
- results.structure.patterns.forEach(pattern => {
54
- logger.dim(` - ${pattern}`);
55
- });
56
- logger.blank();
57
- }
58
-
59
- // Recommendations
60
- if (results.inferred.recommendations.length > 0) {
61
- logger.header('Recommendations:');
62
- results.inferred.recommendations.forEach(rec => {
63
- logger.warn(` ⚠ ${rec}`);
64
- });
65
- logger.blank();
66
- }
67
-
68
- // Save results if requested
69
- if (options.save !== false) {
70
- spinner.start('Saving detection results...');
71
-
72
- const outputDir = join(targetPath, '.morph', 'project', 'context');
73
- await ensureDir(outputDir);
74
-
75
- // Save detection log
76
- const logPath = join(outputDir, 'detection-log.md');
77
- const summary = getDetectionSummary(results);
78
- await writeFile(logPath, summary);
79
-
80
- // Save inferred standards
81
- const standardsDir = join(targetPath, '.morph', 'project', 'standards');
82
- await ensureDir(standardsDir);
83
-
84
- const standardsPath = join(standardsDir, 'inferred.md');
85
- await writeFile(standardsPath, results.inferred.markdown);
86
-
87
- // Update config.json with detected stack and architecture
88
- const configPath = join(targetPath, '.morph', 'config', 'config.json');
89
- if (await pathExists(configPath)) {
90
- const projectConfig = await readJson(configPath);
91
- projectConfig.project = projectConfig.project || {};
92
- projectConfig.project.stack = results.structure.stack;
93
- projectConfig.project.architecture = results.structure.architecture;
94
- await writeJson(configPath, projectConfig);
95
- }
96
-
97
- spinner.succeed('Results saved!');
98
- logger.dim(` - ${logPath}`);
99
- logger.dim(` - ${standardsPath}`);
100
- }
101
-
102
- // Verbose output
103
- if (options.verbose) {
104
- logger.blank();
105
- logger.header('Detailed Results (JSON):');
106
- console.log(JSON.stringify(results, null, 2));
107
- }
108
-
109
- } catch (error) {
110
- spinner.fail('Detection failed');
111
- logger.error(error.message);
112
- process.exit(1);
113
- }
114
- }