@polymorphism-tech/morph-spec 4.7.2 → 4.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (342) hide show
  1. package/LICENSE +1 -2
  2. package/README.md +379 -414
  3. package/bin/morph-spec.js +57 -394
  4. package/bin/validate.js +2 -26
  5. package/claude-plugin.json +2 -2
  6. package/docs/CHEATSHEET.md +203 -221
  7. package/docs/QUICKSTART.md +2 -8
  8. package/framework/CLAUDE.md +1 -1
  9. package/framework/commands/morph-proposal.md +3 -3
  10. package/framework/hooks/README.md +2 -5
  11. package/framework/hooks/claude-code/pre-tool-use/protect-readonly-files.js +4 -55
  12. package/framework/hooks/claude-code/session-start/inject-morph-context.js +20 -5
  13. package/framework/hooks/claude-code/statusline.py +6 -1
  14. package/framework/hooks/dev/check-sync-health.js +117 -0
  15. package/framework/hooks/dev/guard-version-numbers.js +57 -0
  16. package/framework/hooks/dev/sync-standards-registry.js +60 -0
  17. package/framework/hooks/dev/sync-template-registry.js +60 -0
  18. package/framework/hooks/dev/validate-skill-format.js +70 -0
  19. package/framework/hooks/dev/validate-standard-format.js +73 -0
  20. package/framework/hooks/shared/payload-utils.js +39 -0
  21. package/framework/hooks/shared/state-reader.js +25 -1
  22. package/framework/rules/morph-workflow.md +1 -1
  23. package/framework/skills/level-0-meta/morph-init/SKILL.md +216 -0
  24. package/framework/skills/level-0-meta/morph-replicate/SKILL.md +4 -4
  25. package/framework/skills/level-0-meta/tool-usage-guide/SKILL.md +4 -4
  26. package/framework/skills/level-0-meta/verification-before-completion/SKILL.md +1 -1
  27. package/framework/skills/level-1-workflows/phase-clarify/SKILL.md +192 -191
  28. package/framework/skills/level-1-workflows/phase-codebase-analysis/SKILL.md +181 -180
  29. package/framework/skills/level-1-workflows/phase-design/SKILL.md +339 -338
  30. package/framework/skills/level-1-workflows/phase-implement/SKILL.md +254 -253
  31. package/framework/skills/level-1-workflows/phase-setup/SKILL.md +168 -170
  32. package/framework/skills/level-1-workflows/phase-tasks/SKILL.md +284 -283
  33. package/framework/skills/level-1-workflows/phase-uiux/SKILL.md +246 -245
  34. package/framework/templates/examples/design-system-examples.md +1 -1
  35. package/framework/templates/ui/FluentDesignTheme.cs +1 -1
  36. package/framework/templates/ui/MudTheme.cs +1 -1
  37. package/framework/templates/ui/design-system.css +1 -1
  38. package/package.json +7 -5
  39. package/src/commands/agents/index.js +1 -2
  40. package/src/commands/index.js +13 -16
  41. package/src/commands/project/doctor.js +100 -14
  42. package/src/commands/project/index.js +7 -10
  43. package/src/commands/project/init.js +398 -528
  44. package/src/commands/project/install-plugin-cmd.js +28 -0
  45. package/src/commands/project/setup-infra-cmd.js +12 -0
  46. package/src/commands/project/tutorial.js +115 -0
  47. package/src/commands/state/approve.js +213 -221
  48. package/src/commands/state/index.js +0 -1
  49. package/src/commands/state/state.js +337 -365
  50. package/src/commands/templates/index.js +0 -4
  51. package/src/commands/trust/trust.js +1 -93
  52. package/src/commands/utils/index.js +1 -5
  53. package/src/commands/validation/index.js +1 -5
  54. package/src/core/registry/command-registry.js +11 -285
  55. package/src/core/state/state-manager.js +5 -2
  56. package/src/lib/detectors/index.js +81 -87
  57. package/src/lib/detectors/structure-detector.js +275 -273
  58. package/src/lib/generators/recap-generator.js +232 -225
  59. package/src/scripts/global-install.js +34 -0
  60. package/src/scripts/install-plugin.js +126 -0
  61. package/src/scripts/setup-infra.js +203 -0
  62. package/src/utils/agents-installer.js +10 -1
  63. package/src/utils/hooks-installer.js +66 -3
  64. package/.morph/.morphversion +0 -5
  65. package/.morph/analytics/threads-log.jsonl +0 -5
  66. package/.morph/config/config.json +0 -8
  67. package/.morph/framework/agents.json +0 -1815
  68. package/.morph/framework/hooks/README.md +0 -205
  69. package/.morph/framework/hooks/claude-code/notification/approval-reminder.js +0 -54
  70. package/.morph/framework/hooks/claude-code/post-tool-use/dispatch.js +0 -83
  71. package/.morph/framework/hooks/claude-code/post-tool-use/handle-tool-failure.js +0 -42
  72. package/.morph/framework/hooks/claude-code/pre-compact/save-morph-context.js +0 -61
  73. package/.morph/framework/hooks/claude-code/pre-tool-use/enforce-phase-writes.js +0 -71
  74. package/.morph/framework/hooks/claude-code/pre-tool-use/protect-readonly-files.js +0 -58
  75. package/.morph/framework/hooks/claude-code/pre-tool-use/protect-spec-files.js +0 -64
  76. package/.morph/framework/hooks/claude-code/session-start/inject-morph-context.js +0 -94
  77. package/.morph/framework/hooks/claude-code/statusline.py +0 -538
  78. package/.morph/framework/hooks/claude-code/statusline.sh +0 -7
  79. package/.morph/framework/hooks/claude-code/stop/validate-completion.js +0 -88
  80. package/.morph/framework/hooks/claude-code/user-prompt/enrich-prompt.js +0 -91
  81. package/.morph/framework/hooks/git/commit-msg/conventional-commits.sh +0 -33
  82. package/.morph/framework/hooks/git/pre-commit/agents.sh +0 -25
  83. package/.morph/framework/hooks/git/pre-commit/orchestrator.sh +0 -64
  84. package/.morph/framework/hooks/git/pre-commit/specs.sh +0 -50
  85. package/.morph/framework/hooks/git/pre-push/run-tests.sh +0 -44
  86. package/.morph/framework/hooks/shared/hook-response.js +0 -45
  87. package/.morph/framework/hooks/shared/phase-utils.js +0 -129
  88. package/.morph/framework/hooks/shared/state-reader.js +0 -138
  89. package/.morph/framework/hooks/shared/stdin-reader.js +0 -26
  90. package/.morph/framework/standards/STANDARDS.json +0 -933
  91. package/.morph/framework/standards/ai-agents/blazor-ui.md +0 -364
  92. package/.morph/framework/standards/ai-agents/production.md +0 -415
  93. package/.morph/framework/standards/ai-agents/setup.md +0 -418
  94. package/.morph/framework/standards/ai-agents/team-orchestration.md +0 -479
  95. package/.morph/framework/standards/ai-agents/workflows.md +0 -354
  96. package/.morph/framework/standards/architecture/ddd/aggregates.md +0 -120
  97. package/.morph/framework/standards/architecture/ddd/bounded-contexts.md +0 -105
  98. package/.morph/framework/standards/architecture/ddd/complexity-levels.md +0 -108
  99. package/.morph/framework/standards/architecture/ddd/entities.md +0 -99
  100. package/.morph/framework/standards/architecture/ddd/ubiquitous-language.md +0 -58
  101. package/.morph/framework/standards/architecture/ddd/value-objects.md +0 -124
  102. package/.morph/framework/standards/backend/api/minimal-api.md +0 -494
  103. package/.morph/framework/standards/backend/api/rest.md +0 -492
  104. package/.morph/framework/standards/backend/api/validation.md +0 -88
  105. package/.morph/framework/standards/backend/authentication/passkeys.md +0 -428
  106. package/.morph/framework/standards/backend/database/ef-core.md +0 -199
  107. package/.morph/framework/standards/backend/database/migrations.md +0 -393
  108. package/.morph/framework/standards/backend/database/postgresql/database.md +0 -352
  109. package/.morph/framework/standards/backend/database/repository-patterns.md +0 -528
  110. package/.morph/framework/standards/backend/database/vector-search-rag.md +0 -541
  111. package/.morph/framework/standards/backend/dotnet/async.md +0 -366
  112. package/.morph/framework/standards/backend/dotnet/core.md +0 -117
  113. package/.morph/framework/standards/backend/dotnet/di.md +0 -439
  114. package/.morph/framework/standards/backend/dotnet/program-cs-checklist.md +0 -92
  115. package/.morph/framework/standards/backend/integrations/asaas/asaas-api.md +0 -216
  116. package/.morph/framework/standards/backend/integrations/clerk/clerk-auth.md +0 -290
  117. package/.morph/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +0 -350
  118. package/.morph/framework/standards/backend/integrations/resend/resend-email.md +0 -385
  119. package/.morph/framework/standards/context/analytics.md +0 -96
  120. package/.morph/framework/standards/context/bundles.md +0 -110
  121. package/.morph/framework/standards/context/priming.md +0 -78
  122. package/.morph/framework/standards/core/architecture.md +0 -185
  123. package/.morph/framework/standards/core/coding.md +0 -214
  124. package/.morph/framework/standards/core/git-branching-strategy.md +0 -403
  125. package/.morph/framework/standards/core/git.md +0 -185
  126. package/.morph/framework/standards/core/testing.md +0 -295
  127. package/.morph/framework/standards/data/nosql/blob-storage.md +0 -102
  128. package/.morph/framework/standards/data/nosql/cache/redis.md +0 -97
  129. package/.morph/framework/standards/data/nosql/cosmos-db.md +0 -118
  130. package/.morph/framework/standards/data/vector-search/azure-ai-search.md +0 -121
  131. package/.morph/framework/standards/data/vector-search/rag-chunking.md +0 -104
  132. package/.morph/framework/standards/frontend/blazor/design-checklist.md +0 -222
  133. package/.morph/framework/standards/frontend/blazor/fluent-ui-setup.md +0 -595
  134. package/.morph/framework/standards/frontend/blazor/fluent-ui.md +0 -137
  135. package/.morph/framework/standards/frontend/blazor/html-conversion.md +0 -184
  136. package/.morph/framework/standards/frontend/blazor/lifecycle.md +0 -195
  137. package/.morph/framework/standards/frontend/blazor/pitfalls.md +0 -198
  138. package/.morph/framework/standards/frontend/blazor/state.md +0 -191
  139. package/.morph/framework/standards/frontend/design-system/animations.md +0 -151
  140. package/.morph/framework/standards/frontend/design-system/naming.md +0 -64
  141. package/.morph/framework/standards/frontend/nextjs/app-router.md +0 -123
  142. package/.morph/framework/standards/frontend/nextjs/components.md +0 -132
  143. package/.morph/framework/standards/frontend/nextjs/data-fetching.md +0 -126
  144. package/.morph/framework/standards/frontend/nextjs/forms.md +0 -128
  145. package/.morph/framework/standards/frontend/nextjs/naming-conventions.md +0 -67
  146. package/.morph/framework/standards/frontend/nextjs/nextjs-patterns.md +0 -215
  147. package/.morph/framework/standards/frontend/nextjs/project-structure.md +0 -102
  148. package/.morph/framework/standards/frontend/nextjs/state-management.md +0 -72
  149. package/.morph/framework/standards/frontend/nextjs/testing.md +0 -111
  150. package/.morph/framework/standards/infrastructure/azure/azure.md +0 -624
  151. package/.morph/framework/standards/infrastructure/azure/bicep/bicep-patterns.md +0 -422
  152. package/.morph/framework/standards/infrastructure/azure/devops/azure-devops-setup.md +0 -516
  153. package/.morph/framework/standards/infrastructure/azure/devops/local-development.md +0 -520
  154. package/.morph/framework/standards/infrastructure/azure/services/functions.md +0 -486
  155. package/.morph/framework/standards/infrastructure/azure/services/service-bus.md +0 -459
  156. package/.morph/framework/standards/infrastructure/azure/services/storage.md +0 -407
  157. package/.morph/framework/standards/infrastructure/docker/easypanel-deploy.md +0 -196
  158. package/.morph/framework/standards/infrastructure/supabase/mcp-setup.md +0 -252
  159. package/.morph/framework/standards/infrastructure/supabase/supabase-auth.md +0 -176
  160. package/.morph/framework/standards/infrastructure/supabase/supabase-pgvector.md +0 -169
  161. package/.morph/framework/standards/infrastructure/supabase/supabase-rls.md +0 -184
  162. package/.morph/framework/standards/infrastructure/supabase/supabase-storage.md +0 -153
  163. package/.morph/framework/standards/integration/api/graphql.md +0 -91
  164. package/.morph/framework/standards/integration/api/grpc.md +0 -114
  165. package/.morph/framework/standards/integration/api/rest-design.md +0 -95
  166. package/.morph/framework/standards/integration/event-driven/cqrs.md +0 -101
  167. package/.morph/framework/standards/integration/event-driven/event-sourcing.md +0 -124
  168. package/.morph/framework/standards/integration/event-driven/service-bus.md +0 -95
  169. package/.morph/framework/standards/integration/mcp/mcp-tools.md +0 -384
  170. package/.morph/framework/standards/observability/logging.md +0 -131
  171. package/.morph/framework/standards/observability/metrics.md +0 -121
  172. package/.morph/framework/standards/observability/monitoring.md +0 -114
  173. package/.morph/framework/standards/observability/tracing.md +0 -132
  174. package/.morph/framework/standards/workflows/parallel-execution.md +0 -112
  175. package/.morph/framework/standards/workflows/thread-management.md +0 -113
  176. package/.morph/framework/templates/.idea/morph-templates.xml +0 -92
  177. package/.morph/framework/templates/.vscode/morph-templates.code-snippets +0 -186
  178. package/.morph/framework/templates/IDE-SNIPPETS.md +0 -266
  179. package/.morph/framework/templates/README.md +0 -814
  180. package/.morph/framework/templates/REGISTRY.json +0 -1888
  181. package/.morph/framework/templates/code/dotnet/backend/repository.cs +0 -141
  182. package/.morph/framework/templates/code/dotnet/backend/service.cs +0 -139
  183. package/.morph/framework/templates/code/dotnet/contracts/Commands.cs +0 -74
  184. package/.morph/framework/templates/code/dotnet/contracts/Entities.cs +0 -25
  185. package/.morph/framework/templates/code/dotnet/contracts/Queries.cs +0 -74
  186. package/.morph/framework/templates/code/dotnet/contracts/README.md +0 -74
  187. package/.morph/framework/templates/code/dotnet/contracts/api-contracts.cs +0 -173
  188. package/.morph/framework/templates/code/dotnet/contracts/contracts-level1.cs +0 -69
  189. package/.morph/framework/templates/code/dotnet/contracts/contracts-level2.cs +0 -86
  190. package/.morph/framework/templates/code/dotnet/contracts/contracts-level3.cs +0 -41
  191. package/.morph/framework/templates/code/dotnet/database/migration.cs +0 -83
  192. package/.morph/framework/templates/code/dotnet/frontend/component.razor +0 -239
  193. package/.morph/framework/templates/code/dotnet/jobs/agent.cs +0 -163
  194. package/.morph/framework/templates/code/dotnet/jobs/job.cs +0 -171
  195. package/.morph/framework/templates/code/dotnet/test.cs +0 -239
  196. package/.morph/framework/templates/code/sql/rls-policy.sql +0 -57
  197. package/.morph/framework/templates/code/sql/supabase-migration.sql +0 -100
  198. package/.morph/framework/templates/code/sql/supabase-migration.template.sql +0 -113
  199. package/.morph/framework/templates/code/typescript/contracts.ts +0 -168
  200. package/.morph/framework/templates/context/CONTEXT-FEATURE.md +0 -276
  201. package/.morph/framework/templates/context/CONTEXT.md +0 -181
  202. package/.morph/framework/templates/docs/clarifications.md +0 -253
  203. package/.morph/framework/templates/docs/onboarding.md +0 -123
  204. package/.morph/framework/templates/docs/proposal.md +0 -182
  205. package/.morph/framework/templates/docs/schema-analysis.md +0 -119
  206. package/.morph/framework/templates/docs/spec.md +0 -198
  207. package/.morph/framework/templates/docs/ui-components.md +0 -124
  208. package/.morph/framework/templates/docs/ui-design-system.md +0 -76
  209. package/.morph/framework/templates/docs/ui-flows.md +0 -167
  210. package/.morph/framework/templates/docs/ui-mockups.md +0 -98
  211. package/.morph/framework/templates/docs/user-stories.md +0 -34
  212. package/.morph/framework/templates/examples/design-system-examples.md +0 -357
  213. package/.morph/framework/templates/examples/spec-examples.md +0 -90
  214. package/.morph/framework/templates/feature/decisions.md +0 -187
  215. package/.morph/framework/templates/feature/recap.md +0 -146
  216. package/.morph/framework/templates/feature/tasks.md +0 -199
  217. package/.morph/framework/templates/frontend/nextjs/Dockerfile.nextjs.hbs +0 -43
  218. package/.morph/framework/templates/frontend/nextjs/client-component.tsx.hbs +0 -26
  219. package/.morph/framework/templates/frontend/nextjs/env.mjs.hbs +0 -32
  220. package/.morph/framework/templates/frontend/nextjs/feature-form.tsx.hbs +0 -56
  221. package/.morph/framework/templates/frontend/nextjs/page.tsx.hbs +0 -22
  222. package/.morph/framework/templates/frontend/nextjs/tsconfig.json.hbs +0 -26
  223. package/.morph/framework/templates/frontend/nextjs/use-feature.ts.hbs +0 -54
  224. package/.morph/framework/templates/infrastructure/azure/Dockerfile.example +0 -82
  225. package/.morph/framework/templates/infrastructure/azure/README.md +0 -286
  226. package/.morph/framework/templates/infrastructure/azure/app-insights.bicep +0 -63
  227. package/.morph/framework/templates/infrastructure/azure/app-service.bicep +0 -164
  228. package/.morph/framework/templates/infrastructure/azure/container-app-env.bicep +0 -49
  229. package/.morph/framework/templates/infrastructure/azure/container-app.bicep +0 -156
  230. package/.morph/framework/templates/infrastructure/azure/deploy-checklist.md +0 -426
  231. package/.morph/framework/templates/infrastructure/azure/deploy.ps1 +0 -229
  232. package/.morph/framework/templates/infrastructure/azure/deploy.sh +0 -208
  233. package/.morph/framework/templates/infrastructure/azure/key-vault.bicep +0 -91
  234. package/.morph/framework/templates/infrastructure/azure/main.bicep +0 -189
  235. package/.morph/framework/templates/infrastructure/azure/parameters.dev.json +0 -29
  236. package/.morph/framework/templates/infrastructure/azure/parameters.prod.json +0 -29
  237. package/.morph/framework/templates/infrastructure/azure/parameters.staging.json +0 -29
  238. package/.morph/framework/templates/infrastructure/azure/sql-database.bicep +0 -103
  239. package/.morph/framework/templates/infrastructure/azure/storage.bicep +0 -106
  240. package/.morph/framework/templates/infrastructure/docker/Dockerfile.template +0 -58
  241. package/.morph/framework/templates/infrastructure/docker/docker-compose.template.yml +0 -67
  242. package/.morph/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +0 -38
  243. package/.morph/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +0 -48
  244. package/.morph/framework/templates/infrastructure/docker/easypanel.template.json +0 -54
  245. package/.morph/framework/templates/infrastructure/github/README.md +0 -593
  246. package/.morph/framework/templates/infrastructure/github/actions/azure-auth/action.yml.hbs +0 -22
  247. package/.morph/framework/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +0 -45
  248. package/.morph/framework/templates/infrastructure/github/actions/health-check/action.yml.hbs +0 -27
  249. package/.morph/framework/templates/infrastructure/github/workflows/deploy-azure-app-service.yml.hbs +0 -61
  250. package/.morph/framework/templates/infrastructure/github/workflows/deploy-easypanel.yml.hbs +0 -31
  251. package/.morph/framework/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +0 -59
  252. package/.morph/framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +0 -39
  253. package/.morph/framework/templates/integrations/asaas-client.cs +0 -387
  254. package/.morph/framework/templates/integrations/asaas-webhook.cs +0 -351
  255. package/.morph/framework/templates/integrations/azure-identity-config.cs +0 -288
  256. package/.morph/framework/templates/integrations/clerk-config.cs +0 -258
  257. package/.morph/framework/templates/meta-prompts/fusion/fusion-agent.md +0 -76
  258. package/.morph/framework/templates/meta-prompts/fusion/fusion-aggregator.md +0 -100
  259. package/.morph/framework/templates/meta-prompts/hops/hop-retry.md +0 -78
  260. package/.morph/framework/templates/meta-prompts/hops/hop-validation.md +0 -97
  261. package/.morph/framework/templates/meta-prompts/hops/hop-wrapper.md +0 -36
  262. package/.morph/framework/templates/meta-prompts/parallel-workers/parallel-coordinator.md +0 -113
  263. package/.morph/framework/templates/meta-prompts/parallel-workers/parallel-worker.md +0 -80
  264. package/.morph/framework/templates/meta-prompts/squad-leaders/backend-squad.md +0 -90
  265. package/.morph/framework/templates/meta-prompts/squad-leaders/frontend-squad.md +0 -126
  266. package/.morph/framework/templates/meta-prompts/squad-leaders/squad-leader.md +0 -43
  267. package/.morph/framework/templates/meta-prompts/validators/checkpoint-validator.md +0 -107
  268. package/.morph/framework/templates/meta-prompts/validators/pre-commit-validator.md +0 -95
  269. package/.morph/framework/templates/project-structure/dotnet-ddd.md +0 -70
  270. package/.morph/framework/templates/saas/subscription.cs +0 -347
  271. package/.morph/framework/templates/saas/tenant.cs +0 -338
  272. package/.morph/framework/templates/state.template.json +0 -17
  273. package/.morph/framework/templates/ui/FluentDesignTheme.cs +0 -149
  274. package/.morph/framework/templates/ui/MudTheme.cs +0 -281
  275. package/.morph/framework/templates/ui/design-system.css +0 -226
  276. package/.morph/logs/tool-failures.log +0 -17
  277. package/.morph/memory/pre-compact-2026-02-24T17-43-30-049Z.json +0 -16
  278. package/.morph/plans/eager-watching-bunny.md +0 -105
  279. package/.morph/plans/temporal-seeking-nebula.md +0 -45
  280. package/.morph/state.json +0 -48
  281. package/CLAUDE.md +0 -77
  282. package/docs/ARCHITECTURE.md +0 -331
  283. package/docs/COMMAND-FLOWS.md +0 -368
  284. package/docs/claude-alignment-report.md +0 -137
  285. package/docs/examples/order-management/contracts.cs +0 -84
  286. package/docs/examples/order-management/proposal.md +0 -24
  287. package/docs/examples/order-management/spec.md +0 -162
  288. package/docs/plans/2026-02-22-claude-docs-morph-alignment-analysis.md +0 -512
  289. package/docs/plans/2026-02-22-claude-settings.md +0 -515
  290. package/docs/plans/2026-02-22-morph-cc-alignment-impl.md +0 -728
  291. package/docs/plans/2026-02-22-morph-spec-next.md +0 -478
  292. package/docs/plans/2026-02-22-native-alignment-design.md +0 -199
  293. package/docs/plans/2026-02-22-native-alignment-impl.md +0 -925
  294. package/docs/plans/2026-02-22-native-enrichment-design.md +0 -244
  295. package/docs/plans/2026-02-22-native-enrichment.md +0 -735
  296. package/docs/plans/2026-02-23-ddd-architecture-refactor.md +0 -1153
  297. package/docs/plans/2026-02-23-ddd-nextsteps.md +0 -682
  298. package/docs/plans/2026-02-23-infra-architect-refactor.md +0 -437
  299. package/docs/plans/2026-02-23-nextjs-code-review-design.md +0 -156
  300. package/docs/plans/2026-02-23-nextjs-code-review-impl.md +0 -1254
  301. package/docs/plans/2026-02-23-nextjs-standards-design.md +0 -149
  302. package/docs/plans/2026-02-23-nextjs-standards-impl.md +0 -1846
  303. package/scripts/generate-refs.js +0 -336
  304. package/scripts/generate-standards-registry.js +0 -44
  305. package/scripts/scan-nextjs.mjs +0 -169
  306. package/scripts/validate-real.mjs +0 -255
  307. package/src/commands/feature/create-story.js +0 -362
  308. package/src/commands/feature/index.js +0 -6
  309. package/src/commands/feature/shard-spec.js +0 -225
  310. package/src/commands/feature/sprint-status.js +0 -250
  311. package/src/commands/generation/generate-onboarding.js +0 -169
  312. package/src/commands/generation/generate.js +0 -276
  313. package/src/commands/generation/index.js +0 -5
  314. package/src/commands/learning/capture-pattern.js +0 -121
  315. package/src/commands/learning/index.js +0 -5
  316. package/src/commands/learning/search-patterns.js +0 -126
  317. package/src/commands/mcp/mcp.js +0 -102
  318. package/src/commands/project/changes.js +0 -66
  319. package/src/commands/project/cost.js +0 -179
  320. package/src/commands/project/diff.js +0 -278
  321. package/src/commands/project/revert.js +0 -173
  322. package/src/commands/project/standards.js +0 -80
  323. package/src/commands/project/sync.js +0 -167
  324. package/src/commands/project/update-agents.js +0 -23
  325. package/src/commands/state/rollback-phase.js +0 -185
  326. package/src/commands/templates/template-customize.js +0 -87
  327. package/src/commands/templates/template-list.js +0 -114
  328. package/src/commands/templates/template-show.js +0 -129
  329. package/src/commands/templates/template-validate.js +0 -91
  330. package/src/commands/utils/troubleshoot.js +0 -222
  331. package/src/commands/validation/analyze-blazor-concurrency.js +0 -193
  332. package/src/commands/validation/lint-fluent.js +0 -352
  333. package/src/commands/validation/validate-blazor-state.js +0 -210
  334. package/src/commands/validation/validate-blazor.js +0 -156
  335. package/src/commands/validation/validate-css.js +0 -84
  336. package/src/lib/detectors/conversation-analyzer.js +0 -163
  337. package/src/lib/learning/index.js +0 -7
  338. package/src/lib/learning/learning-system.js +0 -520
  339. package/src/lib/troubleshooting/index.js +0 -8
  340. package/src/lib/troubleshooting/troubleshoot-grep.js +0 -198
  341. package/src/lib/troubleshooting/troubleshoot-index.js +0 -144
  342. package/src/llm/environment-detector.js +0 -43
@@ -1,735 +0,0 @@
1
- # Claude Code Native Enrichment Implementation Plan
2
-
3
- > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
4
-
5
- **Goal:** Enrich morph-spec's use of Claude Code native primitives — richer agent frontmatter, Stop hook upgrade, level-2 skill installation, and SubagentStart telemetry.
6
-
7
- **Architecture:** Four independent improvements to `agents-installer.js`, `skills-installer.js`, `hooks-installer.js`, and a new `log-agent-start.js` hook. Each follows TDD with tests first. All are self-contained and can be committed independently.
8
-
9
- **Tech Stack:** Node.js ESM, node:test, fs/promises, Claude Code settings.json schema
10
-
11
- **Design doc:** `docs/plans/2026-02-22-native-enrichment-design.md`
12
-
13
- ---
14
-
15
- ## Task 1: Richer agent frontmatter
16
-
17
- **Context:** Currently generated `.claude/agents/morph-*.md` files have only `name` and `description` in YAML. Claude Code supports `model`, `tools`, `maxTurns`, `skills`, and `memory`. This task adds tier-based defaults to the installer.
18
-
19
- **Files:**
20
- - Modify: `src/utils/agents-installer.js`
21
- - Modify: `test/utils/agents-installer.test.js`
22
-
23
- **Tier defaults:**
24
-
25
- | Tier | model | tools | maxTurns | skills | memory |
26
- |------|-------|-------|----------|--------|--------|
27
- | 1 (Orchestrators) | `inherit` | `Read, Grep, Glob, Bash, Task` | `30` | `morph-checklist` | `project` |
28
- | 2 (Domain Leaders) | `inherit` | `Read, Grep, Glob, Bash` | `20` | `morph-checklist` | `local` |
29
-
30
- `morph-checklist` refers to `.claude/skills/morph-checklist.md` (installed from `framework/skills/level-0-meta/morph-checklist.md`).
31
-
32
- ---
33
-
34
- ### Step 1: Write failing tests
35
-
36
- Add to the bottom of `test/utils/agents-installer.test.js`:
37
-
38
- ```js
39
- describe('installAgents — richer frontmatter', () => {
40
- let tmpDir;
41
-
42
- before(async () => {
43
- tmpDir = await mkdtemp(join(tmpdir(), 'morph-agents-rich-'));
44
- await installAgents(tmpDir, FRAMEWORK_DIR);
45
- });
46
-
47
- after(async () => {
48
- await rm(tmpDir, { recursive: true, force: true });
49
- });
50
-
51
- test('tier-1 agent has model field', async () => {
52
- const files = await readdir(join(tmpDir, '.claude', 'agents'));
53
- const tier1File = files.find(f => f.includes('standards-architect') || f.includes('ai-system'));
54
- assert.ok(tier1File, 'should have a tier-1 agent file');
55
- const content = await readFile(join(tmpDir, '.claude', 'agents', tier1File), 'utf-8');
56
- assert.ok(content.includes('model:'), `${tier1File} should have model field`);
57
- });
58
-
59
- test('tier-1 agent has tools field including Task', async () => {
60
- const files = await readdir(join(tmpDir, '.claude', 'agents'));
61
- const tier1File = files.find(f => f.includes('standards-architect'));
62
- assert.ok(tier1File);
63
- const content = await readFile(join(tmpDir, '.claude', 'agents', tier1File), 'utf-8');
64
- assert.ok(content.includes('tools:'), `${tier1File} should have tools field`);
65
- assert.ok(content.includes('Task'), `${tier1File} tier-1 should have Task tool`);
66
- });
67
-
68
- test('tier-2 agent has tools field without Task', async () => {
69
- const files = await readdir(join(tmpDir, '.claude', 'agents'));
70
- // tier-2 agents don't have Task in their tools
71
- const tier2File = files.find(f => f.includes('thread-orchestrator'));
72
- if (tier2File) {
73
- const content = await readFile(join(tmpDir, '.claude', 'agents', tier2File), 'utf-8');
74
- assert.ok(content.includes('tools:'), `${tier2File} should have tools field`);
75
- }
76
- // At minimum, all files should have a tools: field
77
- for (const file of files) {
78
- const content = await readFile(join(tmpDir, '.claude', 'agents', file), 'utf-8');
79
- assert.ok(content.includes('tools:'), `${file} should have tools field`);
80
- }
81
- });
82
-
83
- test('all agents have maxTurns field', async () => {
84
- const files = await readdir(join(tmpDir, '.claude', 'agents'));
85
- for (const file of files) {
86
- const content = await readFile(join(tmpDir, '.claude', 'agents', file), 'utf-8');
87
- assert.ok(content.includes('maxTurns:'), `${file} should have maxTurns field`);
88
- }
89
- });
90
-
91
- test('all agents have memory field', async () => {
92
- const files = await readdir(join(tmpDir, '.claude', 'agents'));
93
- for (const file of files) {
94
- const content = await readFile(join(tmpDir, '.claude', 'agents', file), 'utf-8');
95
- assert.ok(content.includes('memory:'), `${file} should have memory field`);
96
- }
97
- });
98
-
99
- test('all agents have skills field with morph-checklist', async () => {
100
- const files = await readdir(join(tmpDir, '.claude', 'agents'));
101
- for (const file of files) {
102
- const content = await readFile(join(tmpDir, '.claude', 'agents', file), 'utf-8');
103
- assert.ok(content.includes('skills:'), `${file} should have skills field`);
104
- assert.ok(content.includes('morph-checklist'), `${file} should reference morph-checklist skill`);
105
- }
106
- });
107
- });
108
- ```
109
-
110
- ### Step 2: Run test to verify it fails
111
-
112
- ```bash
113
- npm test -- test/utils/agents-installer.test.js
114
- ```
115
-
116
- Expected: FAIL — `model:` / `tools:` / `maxTurns:` / `memory:` / `skills:` not found in generated files.
117
-
118
- ### Step 3: Implement the changes in `agents-installer.js`
119
-
120
- In `buildDescription()` — no change.
121
-
122
- Replace the content generation line in `installAgents()`:
123
-
124
- ```js
125
- // BEFORE (line 46):
126
- const content = `---\nname: ${agent.title ?? agent.name}\ndescription: ${description}\n---\n\n${body}\n`;
127
-
128
- // AFTER:
129
- const frontmatter = buildFrontmatter(agent, description);
130
- const content = `---\n${frontmatter}---\n\n${body}\n`;
131
- ```
132
-
133
- Add `buildFrontmatter()` function after `buildDescription()`:
134
-
135
- ```js
136
- function buildFrontmatter(agent, description) {
137
- const isOrchestrator = agent.tier === 1;
138
- const tools = isOrchestrator
139
- ? 'Read, Grep, Glob, Bash, Task'
140
- : 'Read, Grep, Glob, Bash';
141
- const maxTurns = isOrchestrator ? 30 : 20;
142
- const memory = isOrchestrator ? 'project' : 'local';
143
- const name = agent.title ?? agent.name;
144
-
145
- return [
146
- `name: ${name}`,
147
- `description: ${description}`,
148
- `model: inherit`,
149
- `tools: ${tools}`,
150
- `maxTurns: ${maxTurns}`,
151
- `skills:`,
152
- ` - morph-checklist`,
153
- `memory: ${memory}`,
154
- ``
155
- ].join('\n');
156
- }
157
- ```
158
-
159
- ### Step 4: Run tests to verify they pass
160
-
161
- ```bash
162
- npm test -- test/utils/agents-installer.test.js
163
- ```
164
-
165
- Expected: All 11 tests pass (5 original + 6 new).
166
-
167
- ### Step 5: Run full suite to verify no regressions
168
-
169
- ```bash
170
- npm test
171
- ```
172
-
173
- Expected: All existing tests pass, 6 new tests pass.
174
-
175
- ### Step 6: Commit
176
-
177
- ```bash
178
- git add src/utils/agents-installer.js test/utils/agents-installer.test.js
179
- git commit -m "feat(agents): add tier-based model/tools/maxTurns/skills/memory to agent frontmatter"
180
- ```
181
-
182
- ---
183
-
184
- ## Task 2: Upgrade Stop hook to `type: "agent"`
185
-
186
- **Context:** The current Stop hook runs `validate-completion.js`, a Node.js script that reads `state.json` and injects advisory context. The docs support `type: "agent"` — a subagent with tool access that makes a `{"ok": true/false}` decision. This replaces the Node.js script with an inline LLM-based check.
187
-
188
- **Key difference:** The current hook is *advisory* (injects context, always exits 0). The new hook is *blocking* (returns `ok: false` to continue Claude working). This changes behavior — Claude will be asked to continue if work is incomplete, rather than just warned.
189
-
190
- **Marker problem:** `removeMorphHooks()` identifies morph hooks by path pattern in `command`. Agent hooks have no `command`. We must add `_morph: true` to all morph hook entries so the cleanup logic can identify them regardless of type.
191
-
192
- **Files:**
193
- - Modify: `src/utils/hooks-installer.js`
194
- - Test: `test/hooks/hooks-installer.test.js`
195
-
196
- ---
197
-
198
- ### Step 1: Write failing tests
199
-
200
- Add to `test/hooks/hooks-installer.test.js` inside the `describe('installClaudeHooks', ...)` block:
201
-
202
- ```js
203
- test('Stop hook uses type "agent" not type "command"', async () => {
204
- await installClaudeHooks(tempDir);
205
- const settings = readSettings();
206
-
207
- const stopHooks = settings.hooks.Stop;
208
- assert.ok(stopHooks, 'Stop event should exist');
209
- assert.ok(stopHooks.length > 0);
210
- const stopHook = stopHooks[0];
211
- assert.ok(stopHook.hooks?.length > 0);
212
- assert.strictEqual(stopHook.hooks[0].type, 'agent', 'Stop hook should use type: agent');
213
- });
214
-
215
- test('Stop hook has prompt and timeout fields', async () => {
216
- await installClaudeHooks(tempDir);
217
- const settings = readSettings();
218
-
219
- const stopHook = settings.hooks.Stop[0].hooks[0];
220
- assert.ok(typeof stopHook.prompt === 'string', 'agent hook should have prompt');
221
- assert.ok(stopHook.prompt.includes('.morph/state.json'), 'prompt should reference state.json');
222
- assert.ok(typeof stopHook.timeout === 'number', 'agent hook should have timeout');
223
- });
224
-
225
- test('SubagentStart hook is installed with morph-.* matcher', async () => {
226
- await installClaudeHooks(tempDir);
227
- const settings = readSettings();
228
-
229
- assert.ok(settings.hooks.SubagentStart, 'SubagentStart event should exist');
230
- const entry = settings.hooks.SubagentStart[0];
231
- assert.strictEqual(entry.matcher, 'morph-.*');
232
- });
233
-
234
- test('morph hook entries have _morph marker for cleanup identification', async () => {
235
- await installClaudeHooks(tempDir);
236
- const settings = readSettings();
237
-
238
- // Check a known morph hook event
239
- const preToolUse = settings.hooks.PreToolUse;
240
- const morphEntry = preToolUse.find(e => e._morph === true);
241
- assert.ok(morphEntry, 'at least one PreToolUse entry should have _morph: true');
242
- });
243
- ```
244
-
245
- ### Step 2: Run tests to verify they fail
246
-
247
- ```bash
248
- npm test -- test/hooks/hooks-installer.test.js
249
- ```
250
-
251
- Expected: FAIL — Stop hook still uses `type: "command"`, no `SubagentStart`, no `_morph` marker.
252
-
253
- ### Step 3: Update `MORPH_HOOKS` in `hooks-installer.js`
254
-
255
- **3a.** Add `_morph: true` to each hook entry in `MORPH_HOOKS`. Change every `hooks: [...]` array item wrapper to include the marker. Example — the SessionStart entry becomes:
256
-
257
- ```js
258
- {
259
- event: 'SessionStart',
260
- matcher: 'startup|resume|compact',
261
- _morph: true,
262
- hooks: [{ type: 'command', command: 'node framework/hooks/claude-code/session-start/inject-morph-context.js' }]
263
- },
264
- ```
265
-
266
- Do this for ALL entries in `MORPH_HOOKS` (9 existing entries).
267
-
268
- **3b.** Replace the Stop entry:
269
-
270
- ```js
271
- // BEFORE:
272
- {
273
- event: 'Stop',
274
- matcher: null,
275
- hooks: [{
276
- type: 'command',
277
- command: 'node framework/hooks/claude-code/stop/validate-completion.js'
278
- }]
279
- },
280
-
281
- // AFTER:
282
- {
283
- event: 'Stop',
284
- matcher: null,
285
- _morph: true,
286
- hooks: [{
287
- type: 'agent',
288
- prompt: `Check if the active morph-spec feature phase outputs are complete.
289
- 1. Read the file .morph/state.json to find features with status "in_progress".
290
- 2. For each in_progress feature, check if required output files for the current phase exist and are non-empty.
291
- - proposal phase: .morph/features/{feature}/0-proposal/proposal.md
292
- - design phase: .morph/features/{feature}/1-design/spec.md
293
- - tasks phase: .morph/features/{feature}/3-tasks/tasks.md
294
- - implement phase: check tasks.completed vs tasks.total from state.json
295
- 3. If all required outputs exist and tasks are complete, return {"ok": true}.
296
- 4. If any required output is missing or empty, return {"ok": false, "reason": "Missing output: <path>"}.
297
- 5. If state.json does not exist or no feature is in_progress, return {"ok": true}.
298
- Do NOT modify any files. Read only.`,
299
- timeout: 60
300
- }]
301
- },
302
- ```
303
-
304
- **3c.** Add SubagentStart entry (after the Notification entry):
305
-
306
- ```js
307
- // === SubagentStart ===
308
- {
309
- event: 'SubagentStart',
310
- matcher: 'morph-.*',
311
- _morph: true,
312
- hooks: [{
313
- type: 'command',
314
- command: 'node framework/hooks/claude-code/subagent/log-agent-start.js'
315
- }]
316
- },
317
- ```
318
-
319
- **3d.** Update `removeMorphHooks()` to detect `_morph: true` marker (not just command path):
320
-
321
- ```js
322
- function removeMorphHooks(settings) {
323
- const morphPathPattern = /framework\/hooks\/claude-code\//;
324
-
325
- for (const [event, entries] of Object.entries(settings.hooks)) {
326
- if (!Array.isArray(entries)) continue;
327
-
328
- settings.hooks[event] = entries.filter(entry => {
329
- // Remove if marked with _morph flag
330
- if (entry._morph === true) return false;
331
-
332
- if (!Array.isArray(entry.hooks)) return true;
333
- // Legacy detection: remove if all hooks are morph-managed command hooks
334
- const nonMorphHooks = entry.hooks.filter(h =>
335
- typeof h.command !== 'string' || !morphPathPattern.test(h.command)
336
- );
337
- return nonMorphHooks.length > 0;
338
- });
339
-
340
- if (settings.hooks[event].length === 0) {
341
- delete settings.hooks[event];
342
- }
343
- }
344
- }
345
- ```
346
-
347
- **3e.** Update the install loop to propagate `_morph: true` to the installed entry:
348
-
349
- ```js
350
- // In the for loop inside installClaudeHooks():
351
- const entry = { _morph: true }; // ← add this flag
352
- if (matcher) {
353
- entry.matcher = matcher;
354
- }
355
- entry.hooks = hooks.map(h => {
356
- // For agent/prompt type hooks, pass through as-is (no command path transform)
357
- if (h.type === 'agent' || h.type === 'prompt') {
358
- return { type: h.type, prompt: h.prompt, timeout: h.timeout };
359
- }
360
- return {
361
- type: h.type,
362
- command: `node "$CLAUDE_PROJECT_DIR/framework/hooks/claude-code/${getHookSubpath(h.command)}"`,
363
- ...(h.timeout ? { timeout: h.timeout } : {})
364
- };
365
- });
366
- ```
367
-
368
- ### Step 4: Run tests to verify they pass
369
-
370
- ```bash
371
- npm test -- test/hooks/hooks-installer.test.js
372
- ```
373
-
374
- Expected: All tests pass, including the 4 new ones.
375
-
376
- ### Step 5: Run full suite
377
-
378
- ```bash
379
- npm test
380
- ```
381
-
382
- Expected: All existing tests pass. Note: the `installs all hook events` test checks `settings.hooks.Stop` — this still passes since Stop still exists, just uses type:agent now.
383
-
384
- ### Step 6: Commit
385
-
386
- ```bash
387
- git add src/utils/hooks-installer.js test/hooks/hooks-installer.test.js
388
- git commit -m "feat(hooks): upgrade Stop hook to type:agent; add SubagentStart hook; add _morph marker"
389
- ```
390
-
391
- ---
392
-
393
- ## Task 3: Create `framework/hooks/claude-code/subagent/log-agent-start.js`
394
-
395
- **Context:** The SubagentStart hook added in Task 2 references this script. It needs to exist and be a simple, fail-open logger.
396
-
397
- **Files:**
398
- - Create: `framework/hooks/claude-code/subagent/log-agent-start.js`
399
-
400
- ---
401
-
402
- ### Step 1: Write the hook script
403
-
404
- ```js
405
- #!/usr/bin/env node
406
-
407
- /**
408
- * SubagentStart Hook: Log Morph Agent Activation
409
- *
410
- * Event: SubagentStart (matcher: morph-.*)
411
- *
412
- * Appends a JSON line to .morph/logs/agents.log whenever a morph
413
- * native subagent is activated. Fail-open: exits 0 on any error.
414
- */
415
-
416
- import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
417
- import { join } from 'path';
418
-
419
- try {
420
- const input = readFileSync('/dev/stdin', 'utf-8');
421
- const data = JSON.parse(input);
422
-
423
- const logDir = join(process.cwd(), '.morph', 'logs');
424
- if (!existsSync(logDir)) {
425
- mkdirSync(logDir, { recursive: true });
426
- }
427
-
428
- const logPath = join(logDir, 'agents.log');
429
- const entry = JSON.stringify({
430
- timestamp: new Date().toISOString(),
431
- agentType: data.agent_type ?? data.agentType ?? 'unknown',
432
- sessionId: data.session_id ?? null
433
- }) + '\n';
434
-
435
- writeFileSync(logPath, entry, { flag: 'a', encoding: 'utf-8' });
436
- } catch {
437
- // Fail-open: never block agent activation
438
- }
439
-
440
- process.exit(0);
441
- ```
442
-
443
- **Windows note:** `/dev/stdin` does not exist on Windows. Use `process.stdin` with a streaming approach. For cross-platform support, replace the stdin read with:
444
-
445
- ```js
446
- import { readFileSync } from 'node:fs';
447
-
448
- function readStdin() {
449
- try {
450
- // Unix
451
- return readFileSync('/dev/stdin', 'utf-8');
452
- } catch {
453
- // Windows fallback: read from fd 0
454
- return readFileSync(0, 'utf-8');
455
- }
456
- }
457
- ```
458
-
459
- Actually, use the pattern already used by the other hooks. Check `framework/hooks/shared/stdin-reader.js` for the correct stdin reading utility.
460
-
461
- ### Step 2: Check the existing stdin pattern
462
-
463
- ```bash
464
- cat framework/hooks/shared/stdin-reader.js
465
- ```
466
-
467
- Use whatever pattern it exports (likely `readStdin()` or similar). Import and use it.
468
-
469
- ### Step 3: Run full test suite (no new unit tests for this hook — it's a simple I/O script)
470
-
471
- ```bash
472
- npm test
473
- ```
474
-
475
- Expected: All tests still pass. No regressions.
476
-
477
- ### Step 4: Commit
478
-
479
- ```bash
480
- git add framework/hooks/claude-code/subagent/log-agent-start.js
481
- git commit -m "feat(hooks): add SubagentStart log-agent-start.js hook script"
482
- ```
483
-
484
- ---
485
-
486
- ## Task 4: Install level-2 skills in `skills-installer.js`
487
-
488
- **Context:** Level-2 domain skills (`level-2-domains/`) contain 17 `.md` files across 7 subdirectories. The skills-installer currently only handles flat directories (level-0 and level-1). Level-2 requires recursive walk. Level-3 and level-4 only have README.md — no content to install yet.
489
-
490
- **Duplicate file warning:** `hangfire-orchestrator.md` exists in both `backend/` and `integrations/` subdirectories. The flat install will overwrite with whichever comes last. This is acceptable — they likely have different content, but users get one version. Document this in comments.
491
-
492
- **Files:**
493
- - Modify: `src/utils/skills-installer.js`
494
- - Create: `test/utils/skills-installer.test.js`
495
-
496
- ---
497
-
498
- ### Step 1: Write failing tests
499
-
500
- Create `test/utils/skills-installer.test.js`:
501
-
502
- ```js
503
- /**
504
- * Tests for src/utils/skills-installer.js
505
- */
506
-
507
- import { test, describe, before, after } from 'node:test';
508
- import assert from 'node:assert/strict';
509
- import { mkdtemp, rm, readdir } from 'node:fs/promises';
510
- import { join } from 'path';
511
- import { tmpdir } from 'os';
512
- import { fileURLToPath } from 'url';
513
- import { dirname } from 'path';
514
- import { installSkills } from '../../src/utils/skills-installer.js';
515
-
516
- const __dirname = dirname(fileURLToPath(import.meta.url));
517
- // skills-installer uses FRAMEWORK_SKILLS_DIR hardcoded from __dirname
518
- // So we can only test with the real framework directory
519
-
520
- describe('installSkills', () => {
521
- let tmpDir;
522
-
523
- before(async () => {
524
- tmpDir = await mkdtemp(join(tmpdir(), 'morph-skills-'));
525
- });
526
-
527
- after(async () => {
528
- await rm(tmpDir, { recursive: true, force: true });
529
- });
530
-
531
- test('creates .claude/skills/ directory', async () => {
532
- await installSkills(tmpDir);
533
- const files = await readdir(join(tmpDir, '.claude', 'skills'));
534
- assert.ok(files.length > 0, 'should have skill files installed');
535
- });
536
-
537
- test('installs level-0-meta skills', async () => {
538
- await installSkills(tmpDir);
539
- const files = await readdir(join(tmpDir, '.claude', 'skills'));
540
- // morph-checklist comes from level-0-meta
541
- assert.ok(files.some(f => f === 'morph-checklist.md'), 'morph-checklist.md should be installed');
542
- assert.ok(files.some(f => f === 'code-review.md'), 'code-review.md should be installed');
543
- });
544
-
545
- test('installs level-1-workflows skills', async () => {
546
- await installSkills(tmpDir);
547
- const files = await readdir(join(tmpDir, '.claude', 'skills'));
548
- assert.ok(files.some(f => f === 'phase-design.md'), 'phase-design.md should be installed');
549
- assert.ok(files.some(f => f === 'phase-implement.md'), 'phase-implement.md should be installed');
550
- });
551
-
552
- test('installs level-2-domains skills from subdirectories', async () => {
553
- await installSkills(tmpDir);
554
- const files = await readdir(join(tmpDir, '.claude', 'skills'));
555
- // These come from level-2-domains subdirectories
556
- assert.ok(files.some(f => f === 'blazor-builder.md'), 'blazor-builder.md should be installed');
557
- assert.ok(files.some(f => f === 'dotnet-senior.md'), 'dotnet-senior.md should be installed');
558
- assert.ok(files.some(f => f === 'azure-architect.md'), 'azure-architect.md should be installed');
559
- assert.ok(files.some(f => f === 'testing-specialist.md'), 'testing-specialist.md should be installed');
560
- });
561
-
562
- test('does not install README.md files', async () => {
563
- await installSkills(tmpDir);
564
- const files = await readdir(join(tmpDir, '.claude', 'skills'));
565
- assert.ok(!files.includes('README.md'), 'README.md should not be installed');
566
- });
567
-
568
- test('installs more than 20 skills total (level-0 + level-1 + level-2)', async () => {
569
- await installSkills(tmpDir);
570
- const files = await readdir(join(tmpDir, '.claude', 'skills'));
571
- // level-0: 6, level-1: 8, level-2: ~17 = ~31 total
572
- assert.ok(files.length > 20, `should install more than 20 skills, got ${files.length}`);
573
- });
574
-
575
- test('is idempotent — running twice produces same result', async () => {
576
- await installSkills(tmpDir);
577
- const firstCount = (await readdir(join(tmpDir, '.claude', 'skills'))).length;
578
- await installSkills(tmpDir);
579
- const secondCount = (await readdir(join(tmpDir, '.claude', 'skills'))).length;
580
- assert.strictEqual(firstCount, secondCount, 'file count should not change on second run');
581
- });
582
- });
583
- ```
584
-
585
- ### Step 2: Run tests to verify they fail
586
-
587
- ```bash
588
- npm test -- test/utils/skills-installer.test.js
589
- ```
590
-
591
- Expected: FAIL — `blazor-builder.md`, `dotnet-senior.md`, `azure-architect.md`, `testing-specialist.md` not found (level-2 not installed). Also fails on `> 20 skills` count.
592
-
593
- ### Step 3: Update `skills-installer.js`
594
-
595
- Replace the `SKILL_LEVELS_TO_INSTALL` constant and add a recursive walk helper:
596
-
597
- ```js
598
- /**
599
- * Skill levels to install as flat files in .claude/skills/.
600
- * Level-0 (meta), Level-1 (workflows), Level-2 (domain specialists).
601
- * Level-3 and Level-4 only contain README.md — no content to install.
602
- * For Level-2, subdirectories are walked recursively and files are installed flat.
603
- * Note: if two subdirs have a file with the same name, last-write wins.
604
- */
605
- const SKILL_LEVELS_TO_INSTALL = ['level-0-meta', 'level-1-workflows', 'level-2-domains'];
606
- ```
607
-
608
- Replace the install loop to handle subdirectories:
609
-
610
- ```js
611
- export async function installSkills(projectDir) {
612
- const claudeSkillsDir = join(projectDir, '.claude', 'skills');
613
- mkdirSync(claudeSkillsDir, { recursive: true });
614
-
615
- for (const level of SKILL_LEVELS_TO_INSTALL) {
616
- const levelDir = join(FRAMEWORK_SKILLS_DIR, level);
617
- if (!existsSync(levelDir)) continue;
618
-
619
- installSkillsFromDir(levelDir, claudeSkillsDir);
620
- }
621
- }
622
-
623
- /**
624
- * Recursively copy all .md skill files (excluding README.md) from srcDir
625
- * to destDir as flat files.
626
- * @param {string} srcDir
627
- * @param {string} destDir
628
- */
629
- function installSkillsFromDir(srcDir, destDir) {
630
- const entries = readdirSync(srcDir);
631
- for (const entry of entries) {
632
- const srcPath = join(srcDir, entry);
633
- const stat = statSync(srcPath);
634
-
635
- if (stat.isDirectory()) {
636
- // Recurse into subdirectory
637
- installSkillsFromDir(srcPath, destDir);
638
- } else if (entry.endsWith('.md') && entry !== 'README.md') {
639
- const destPath = join(destDir, basename(entry));
640
- copyFileSync(srcPath, destPath);
641
- }
642
- }
643
- }
644
- ```
645
-
646
- ### Step 4: Run tests to verify they pass
647
-
648
- ```bash
649
- npm test -- test/utils/skills-installer.test.js
650
- ```
651
-
652
- Expected: All 7 tests pass.
653
-
654
- ### Step 5: Run full suite
655
-
656
- ```bash
657
- npm test
658
- ```
659
-
660
- Expected: All existing tests pass, 7 new tests pass.
661
-
662
- ### Step 6: Commit
663
-
664
- ```bash
665
- git add src/utils/skills-installer.js test/utils/skills-installer.test.js
666
- git commit -m "feat(skills): install level-2 domain skills to .claude/skills/ with recursive walk"
667
- ```
668
-
669
- ---
670
-
671
- ## Task 5: Final verification
672
-
673
- ### Step 1: Confirm test counts
674
-
675
- ```bash
676
- npm run test:coverage:summary
677
- ```
678
-
679
- Expected: More tests than before Task 1 (was ~588). Verify no regressions.
680
-
681
- ### Step 2: Smoke test with `morph-spec init`
682
-
683
- ```bash
684
- node bin/morph-spec.js init --force --skip-mcp --skip-detection
685
- ```
686
-
687
- Verify:
688
- ```bash
689
- # Check agents have new frontmatter
690
- head -15 .claude/agents/morph-standards-architect.md
691
- # Expected: model:, tools:, maxTurns:, skills:, memory: all present
692
-
693
- # Check Stop hook type
694
- node -e "const s=JSON.parse(require('fs').readFileSync('.claude/settings.local.json')); console.log('Stop type:', s.hooks.Stop[0].hooks[0].type)"
695
- # Expected: Stop type: agent
696
-
697
- # Check SubagentStart hook exists
698
- node -e "const s=JSON.parse(require('fs').readFileSync('.claude/settings.local.json')); console.log('SubagentStart:', !!s.hooks.SubagentStart)"
699
- # Expected: SubagentStart: true
700
-
701
- # Check level-2 skills installed
702
- ls .claude/skills/ | grep -E "blazor|dotnet|azure" | head
703
- # Expected: blazor-builder.md, dotnet-senior.md, azure-architect.md etc.
704
-
705
- # Check total skill count
706
- ls .claude/skills/*.md | wc -l
707
- # Expected: > 20
708
- ```
709
-
710
- ### Step 3: Commit any final cleanup
711
-
712
- If any cleanup needed:
713
- ```bash
714
- git add <changed files>
715
- git commit -m "chore: native enrichment cleanup after smoke test"
716
- ```
717
-
718
- ---
719
-
720
- ## Summary of Files Changed
721
-
722
- | File | Change |
723
- |------|--------|
724
- | `src/utils/agents-installer.js` | Add `buildFrontmatter()` with tier-based model/tools/maxTurns/skills/memory |
725
- | `test/utils/agents-installer.test.js` | 6 new tests for richer frontmatter |
726
- | `src/utils/hooks-installer.js` | Stop→type:agent, SubagentStart hook, `_morph` marker, updated `removeMorphHooks()` |
727
- | `test/hooks/hooks-installer.test.js` | 4 new tests for Stop type, SubagentStart, `_morph` marker |
728
- | `framework/hooks/claude-code/subagent/log-agent-start.js` | **NEW** — fail-open agent activation logger |
729
- | `src/utils/skills-installer.js` | Add level-2 to install list, add recursive `installSkillsFromDir()` |
730
- | `test/utils/skills-installer.test.js` | **NEW** — 7 tests for skills installation |
731
-
732
- ---
733
-
734
- *Plan saved: 2026-02-22*
735
- *Design doc: `docs/plans/2026-02-22-native-enrichment-design.md`*