@polymorphism-tech/morph-spec 8.47.0 → 9.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (377) hide show
  1. package/CLAUDE.md +51 -43
  2. package/README.md +39 -38
  3. package/bin/morph-spec.js +41 -113
  4. package/bin/validate.js +1 -147
  5. package/claude-plugin.json +1 -1
  6. package/docs/CHEATSHEET.md +1 -1
  7. package/docs/QUICKSTART.md +1 -1
  8. package/framework/CLAUDE.md +41 -101
  9. package/framework/MORPH.md +95 -252
  10. package/framework/agents.json +86 -21
  11. package/framework/commands/morph-apply.md +5 -28
  12. package/framework/commands/morph-archive.md +1 -1
  13. package/framework/commands/morph-hotfix.md +8 -8
  14. package/framework/commands/morph-infra.md +1 -1
  15. package/framework/commands/morph-preflight.md +2 -3
  16. package/framework/commands/morph-status.md +4 -4
  17. package/framework/docs/CLI.md +574 -286
  18. package/framework/evals/review-checklist.md +82 -41
  19. package/framework/hooks/README.md +10 -11
  20. package/framework/hooks/claude-code/core/block-destructive-worktree-removal.js +6 -49
  21. package/framework/hooks/claude-code/core/block-raw-worktree-add.js +2 -35
  22. package/framework/hooks/claude-code/core/chain.js +4 -65
  23. package/framework/hooks/claude-code/core/comment-guard.js +3 -17
  24. package/framework/hooks/claude-code/core/denylist.json +33 -3
  25. package/framework/hooks/claude-code/core/enforce-phase-writes.js +15 -63
  26. package/framework/hooks/claude-code/core/gate-guard.js +9 -78
  27. package/framework/hooks/claude-code/core/graph-refresh-kick.js +3 -24
  28. package/framework/hooks/claude-code/core/heavy-gate.js +3 -21
  29. package/framework/hooks/claude-code/core/heavy-release.js +2 -13
  30. package/framework/hooks/claude-code/core/loop-detect.js +2 -31
  31. package/framework/hooks/claude-code/core/pre-bash-denylist.js +36 -2
  32. package/framework/hooks/claude-code/core/protect-spec-files.js +25 -297
  33. package/framework/hooks/claude-code/core/state-sync.js +15 -85
  34. package/framework/hooks/claude-code/core/telemetry-log.js +15 -96
  35. package/framework/hooks/claude-code/core/validate-completion.js +37 -147
  36. package/framework/hooks/claude-code/core/warn-bash-source-write.js +23 -0
  37. package/framework/hooks/claude-code/core/worktree-context.js +15 -114
  38. package/framework/hooks/claude-code/core/worktree-create.js +6 -70
  39. package/framework/hooks/claude-code/core/worktree-env-inject.js +5 -56
  40. package/framework/hooks/claude-code/core/worktree-remove.js +5 -31
  41. package/framework/hooks/claude-code/statusline.py +55 -41
  42. package/framework/hooks/package.json +3 -0
  43. package/framework/hooks/shared/activity-logger.js +9 -89
  44. package/framework/hooks/shared/agent-reap.js +2 -17
  45. package/framework/hooks/shared/build-check.js +11 -76
  46. package/framework/hooks/shared/claim-registry.js +9 -119
  47. package/framework/hooks/shared/command-tokens.js +168 -44
  48. package/framework/hooks/shared/comment-rules.js +5 -20
  49. package/framework/hooks/shared/comment-scanner.js +11 -43
  50. package/framework/hooks/shared/comment-stripper.js +11 -85
  51. package/framework/hooks/shared/e2e-check.js +0 -0
  52. package/framework/hooks/shared/errata.js +59 -0
  53. package/framework/hooks/shared/feature-locator.js +11 -95
  54. package/framework/hooks/shared/frontend-locations.js +4 -0
  55. package/framework/hooks/shared/gate-question.js +12 -0
  56. package/framework/hooks/shared/git-exclude.js +3 -20
  57. package/framework/hooks/shared/git-paths.js +8 -104
  58. package/framework/hooks/shared/graph-freshness.js +22 -166
  59. package/framework/hooks/shared/graph-refresh.js +21 -149
  60. package/framework/hooks/shared/heavy-command.js +4 -12
  61. package/framework/hooks/shared/hook-response.js +8 -83
  62. package/framework/hooks/shared/morph-cli.js +8 -52
  63. package/framework/hooks/shared/payload-utils.js +10 -132
  64. package/framework/hooks/shared/phase-utils.js +14 -72
  65. package/framework/hooks/shared/redact-secrets.js +4 -15
  66. package/framework/hooks/shared/reparse-scan.js +6 -66
  67. package/framework/hooks/shared/slice-progress.js +99 -0
  68. package/framework/hooks/shared/source-files.js +4 -17
  69. package/framework/hooks/shared/spawn-command.js +23 -0
  70. package/framework/hooks/shared/state-reader.js +51 -247
  71. package/framework/hooks/shared/state-writer.js +9 -54
  72. package/framework/hooks/shared/stdin-reader.js +1 -11
  73. package/framework/hooks/shared/telemetry-logger.js +7 -67
  74. package/framework/hooks/shared/transcript-usage.js +7 -29
  75. package/framework/hooks/shared/worktree-root.js +7 -29
  76. package/framework/mcp/registry.json +3 -4
  77. package/framework/phases.json +23 -39
  78. package/framework/rules/csharp-standards.md +1 -1
  79. package/framework/rules/frontend-standards.md +1 -0
  80. package/framework/rules/hangfire-standards.md +1 -1
  81. package/framework/rules/neon-standards.md +1 -1
  82. package/framework/schemas/config.schema.json +14 -9
  83. package/framework/schemas/feature.schema.json +15 -50
  84. package/framework/skills/README.md +3 -4
  85. package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
  86. package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +1 -1
  87. package/framework/skills/core/morph-apply/SKILL.md +149 -222
  88. package/framework/skills/core/morph-hotfix/SKILL.md +33 -42
  89. package/framework/skills/core/morph-machine/SKILL.md +2 -2
  90. package/framework/skills/core/morph-media/SKILL.md +1 -1
  91. package/framework/skills/core/morph-plan/SKILL.md +137 -299
  92. package/framework/skills/core/morph-review/SKILL.md +111 -136
  93. package/framework/skills/core/morph-standards/SKILL.md +27 -39
  94. package/framework/skills/core/morph-uiux/SKILL.md +94 -152
  95. package/framework/standards/STANDARDS.json +109 -1219
  96. package/framework/standards/STANDARDS.meta.json +1319 -0
  97. package/framework/standards/ai-agents/agent-archetypes.md +2 -2
  98. package/framework/standards/ai-agents/agent-session.md +1 -1
  99. package/framework/standards/ai-agents/conversational-agent-with-phases.md +4 -4
  100. package/framework/standards/ai-agents/durable-workflows-hitl.md +3 -3
  101. package/framework/standards/ai-agents/evals-with-cache.md +1 -2
  102. package/framework/standards/ai-agents/guardrails.md +1 -1
  103. package/framework/standards/ai-agents/multi-agent-patterns.md +2 -2
  104. package/framework/standards/ai-agents/observability-patterns.md +1 -1
  105. package/framework/standards/ai-agents/production.md +1 -1
  106. package/framework/standards/ai-agents/prompt-sources.md +2 -2
  107. package/framework/standards/ai-agents/providers/model-registry.md +1 -1
  108. package/framework/standards/ai-agents/rag-custom-pgvector.md +2 -2
  109. package/framework/standards/ai-agents/setup.md +3 -3
  110. package/framework/standards/ai-agents/sweet-spot.md +2 -2
  111. package/framework/standards/ai-agents/tool-adapters.md +0 -2
  112. package/framework/standards/ai-agents/vector-data-extensions.md +4 -4
  113. package/framework/standards/ai-agents/workflows.md +1 -1
  114. package/framework/standards/architecture/code-comments.md +7 -7
  115. package/framework/standards/architecture/vertical-slice/vertical-slice.md +1 -1
  116. package/framework/standards/backend/api/validation.md +1 -1
  117. package/framework/standards/backend/dotnet/vsa-handler-patterns.md +5 -5
  118. package/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +1 -1
  119. package/framework/standards/backend/integrations/neon-auth/neon-auth.md +2 -2
  120. package/framework/standards/data/nosql/cache/redis.md +1 -1
  121. package/framework/standards/data/nosql/cosmos-db.md +3 -3
  122. package/framework/standards/frontend/admin-app/forms.md +1 -1
  123. package/framework/standards/frontend/design-system/art-direction.md +88 -0
  124. package/framework/standards/frontend/design-system/premium-finish.md +77 -2
  125. package/framework/standards/infrastructure/neon/neon-pgvector.md +5 -5
  126. package/framework/standards/integration/mcp/mcp-tools.md +7 -7
  127. package/framework/templates/CLAUDE.md.core.template +3 -3
  128. package/framework/templates/README.md +2 -3
  129. package/framework/templates/REGISTRY.json +15 -179
  130. package/framework/templates/docs/plan.md +72 -0
  131. package/framework/templates/docs/ui-mockups.md +4 -0
  132. package/framework/templates/dotnet/ai-kit/README.md +1 -9
  133. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Morph.AiKit.Tests.csproj +0 -10
  134. package/framework/templates/meta-prompts/squad-leaders/backend-squad.md +1 -1
  135. package/framework/templates/meta-prompts/squad-leaders/frontend-squad.md +1 -1
  136. package/framework/templates/meta-prompts/squad-leaders/squad-leader.md +1 -1
  137. package/framework/templates/meta-prompts/validators/pre-commit-validator.md +3 -4
  138. package/package.json +1 -1
  139. package/src/commands/context/context-refresh.js +0 -16
  140. package/src/commands/dashboard/dashboard.js +2 -8
  141. package/src/commands/e2e/e2e.js +18 -105
  142. package/src/commands/graph/affected.js +0 -14
  143. package/src/commands/graph/build.js +11 -50
  144. package/src/commands/graph/explain.js +0 -16
  145. package/src/commands/graph/status.js +1 -12
  146. package/src/commands/mcp/mcp-setup.js +4 -62
  147. package/src/commands/observability/cost.js +17 -111
  148. package/src/commands/observability/telemetry.js +1 -14
  149. package/src/commands/project/branch.js +4 -45
  150. package/src/commands/project/claim.js +4 -48
  151. package/src/commands/project/doctor-procs.js +1 -1
  152. package/src/commands/project/doctor.js +53 -307
  153. package/src/commands/project/env.js +1 -27
  154. package/src/commands/project/fleet.js +6 -35
  155. package/src/commands/project/heavy.js +3 -3
  156. package/src/commands/project/init.js +8 -68
  157. package/src/commands/project/install-plugin-cmd.js +0 -1
  158. package/src/commands/project/setup-infra-cmd.js +2 -1
  159. package/src/commands/project/stack-scan.js +58 -0
  160. package/src/commands/project/standards.js +65 -72
  161. package/src/commands/project/status.js +28 -121
  162. package/src/commands/project/update.js +31 -223
  163. package/src/commands/project/worktree.js +109 -883
  164. package/src/commands/scaffold/scaffold.js +0 -25
  165. package/src/commands/state/advance.js +65 -120
  166. package/src/commands/state/approve.js +87 -229
  167. package/src/commands/state/archive.js +23 -139
  168. package/src/commands/state/auto-approval.js +65 -0
  169. package/src/commands/state/create.js +49 -109
  170. package/src/commands/state/delete.js +11 -63
  171. package/src/commands/state/finish.js +105 -494
  172. package/src/commands/state/gate-check.js +74 -183
  173. package/src/commands/state/gate-decision.js +8 -42
  174. package/src/commands/state/handoff.js +4 -31
  175. package/src/commands/state/list.js +21 -91
  176. package/src/commands/state/report-check.js +134 -338
  177. package/src/commands/state/retype.js +12 -28
  178. package/src/commands/validation/index.js +0 -3
  179. package/src/commands/validation/mutate.js +79 -19
  180. package/src/commands/validation/plan-check.js +81 -0
  181. package/src/commands/validation/validate-feature.js +52 -216
  182. package/src/commands/validation/verify.js +45 -160
  183. package/src/core/paths/output-schema.js +9 -155
  184. package/src/core/state/feature-identity.js +1 -25
  185. package/src/core/state/gate-order.js +2 -30
  186. package/src/core/state/lifecycle-audit.js +8 -100
  187. package/src/core/state/state-manager.js +32 -395
  188. package/src/core/templates/template-registry.js +2 -97
  189. package/src/core/templates/template-renderer.js +13 -93
  190. package/src/core/templates/template-seed.js +21 -0
  191. package/src/core/work-types.js +10 -45
  192. package/src/dashboard/app/App.jsx +1 -8
  193. package/src/dashboard/app/components/ActivityFeed.jsx +2 -8
  194. package/src/dashboard/app/components/CommandPalette.jsx +4 -11
  195. package/src/dashboard/app/components/DetailPanel.jsx +1 -5
  196. package/src/dashboard/app/components/EntityLink.jsx +0 -12
  197. package/src/dashboard/app/components/ErrorBoundary.jsx +1 -8
  198. package/src/dashboard/app/components/KnowledgeMarkdown.jsx +0 -11
  199. package/src/dashboard/app/components/Markdown.jsx +0 -9
  200. package/src/dashboard/app/components/PhaseRail.jsx +0 -11
  201. package/src/dashboard/app/components/SearchFilter.jsx +0 -4
  202. package/src/dashboard/app/components/Sidebar.jsx +0 -5
  203. package/src/dashboard/app/hooks/useMorphQuery.js +1 -11
  204. package/src/dashboard/app/hooks/usePref.js +1 -5
  205. package/src/dashboard/app/lib/format.js +0 -2
  206. package/src/dashboard/app/lib/phases.js +3 -9
  207. package/src/dashboard/app/lib/project.js +0 -12
  208. package/src/dashboard/app/pages/Activity.jsx +1 -1
  209. package/src/dashboard/app/pages/AgentMap.jsx +1 -8
  210. package/src/dashboard/app/pages/FeatureDetail.jsx +139 -133
  211. package/src/dashboard/app/pages/Features.jsx +9 -16
  212. package/src/dashboard/app/pages/Guide.jsx +2 -3
  213. package/src/dashboard/app/pages/HookInspector.jsx +2 -23
  214. package/src/dashboard/app/pages/PhasePipeline.jsx +3 -7
  215. package/src/dashboard/app/pages/Portfolio.jsx +0 -1
  216. package/src/dashboard/app/pages/RulesMap.jsx +1 -16
  217. package/src/dashboard/app/pages/SkillsLibrary.jsx +1 -16
  218. package/src/dashboard/app/pages/Standards.jsx +2 -17
  219. package/src/dashboard/scanner/activity-scanner.js +14 -83
  220. package/src/dashboard/scanner/agents-scanner.js +1 -23
  221. package/src/dashboard/scanner/docs-scanner.js +1 -7
  222. package/src/dashboard/scanner/feature-status.js +2 -5
  223. package/src/dashboard/scanner/features-scanner.js +92 -113
  224. package/src/dashboard/scanner/hooks-scanner.js +5 -28
  225. package/src/dashboard/scanner/index.js +0 -4
  226. package/src/dashboard/scanner/portfolio.js +5 -29
  227. package/src/dashboard/scanner/project-api.js +8 -54
  228. package/src/dashboard/scanner/rules-scanner.js +1 -2
  229. package/src/dashboard/scanner/skills-scanner.js +2 -12
  230. package/src/dashboard/scanner/standards-scanner.js +4 -7
  231. package/src/dashboard/vite-plugin-morph-data.js +5 -19
  232. package/src/lib/ai/ai-checks.js +7 -52
  233. package/src/lib/ai/ai-project-scan.js +14 -108
  234. package/src/lib/ai/code-audit.js +7 -63
  235. package/src/lib/ai/pin-drift.js +8 -51
  236. package/src/lib/ai/registry-audit.js +11 -90
  237. package/src/lib/ci/ci-verify.js +14 -13
  238. package/src/lib/ci/github-ci.js +9 -37
  239. package/src/lib/ci/workflow-scaffold.js +2 -10
  240. package/src/lib/detectors/claude-config-detector.js +13 -74
  241. package/src/lib/detectors/index.js +8 -59
  242. package/src/lib/e2e/compose-env.js +5 -66
  243. package/src/lib/e2e/stack-teardown.js +6 -40
  244. package/src/lib/generators/architecture-scanner.js +18 -156
  245. package/src/lib/generators/handoff-generator.js +37 -112
  246. package/src/lib/generators/scaffold-generator.js +5 -101
  247. package/src/lib/generators/settings-generator.js +11 -122
  248. package/src/lib/git/branch-classifier.js +11 -84
  249. package/src/lib/git/default-branch.js +14 -169
  250. package/src/lib/git/evidence-staleness.js +2 -1
  251. package/src/lib/git/gh.js +2 -17
  252. package/src/lib/git/pending-prs.js +6 -37
  253. package/src/lib/git/pr-files.js +3 -28
  254. package/src/lib/git/pr-index.js +3 -34
  255. package/src/lib/git/tree-fingerprint.js +17 -17
  256. package/src/lib/git/tree-state.js +6 -33
  257. package/src/lib/graph/god-nodes.js +2 -22
  258. package/src/lib/graph/graph-health.js +3 -24
  259. package/src/lib/graph/graph-loader.js +5 -56
  260. package/src/lib/graph/graphify-runtime.js +7 -37
  261. package/src/lib/graph/graphifyignore.js +8 -74
  262. package/src/lib/graph/sanitize.js +16 -136
  263. package/src/lib/heavy/cleanup.js +2 -6
  264. package/src/lib/installers/effects.js +8 -93
  265. package/src/lib/installers/mcp-installer.js +9 -169
  266. package/src/lib/installers/memory-installer.js +8 -33
  267. package/src/lib/installers/templates-reconcile.js +5 -60
  268. package/src/lib/mutation/commands.js +3 -2
  269. package/src/lib/mutation/dotnet-introspection.js +281 -0
  270. package/src/lib/mutation/plan.js +14 -6
  271. package/src/lib/mutation/runner.js +1 -1
  272. package/src/lib/mutation/subset.js +47 -13
  273. package/src/lib/plan/artifact-vocabulary.js +40 -0
  274. package/src/lib/plan/checks.js +208 -0
  275. package/src/lib/plan/plan-parser.js +204 -0
  276. package/src/lib/plan/plan-template.js +18 -0
  277. package/src/lib/projects/registry.js +7 -44
  278. package/src/lib/review-reports.js +204 -0
  279. package/src/lib/risk-detector.js +131 -274
  280. package/src/lib/specs/adr-index.js +38 -85
  281. package/src/lib/specs/design-seed.js +18 -0
  282. package/src/lib/specs/frontmatter.js +31 -0
  283. package/src/lib/specs/gfm-table.js +11 -0
  284. package/src/lib/specs/revocations.js +31 -102
  285. package/src/lib/specs/screen-checklist.js +56 -132
  286. package/src/lib/stack/dotnet-build-ignores.js +43 -0
  287. package/src/lib/stack/stack-profile.js +1 -28
  288. package/src/lib/stack/stack-scan.js +260 -0
  289. package/src/lib/stack-filter.js +4 -27
  290. package/src/lib/standards/registry.js +37 -0
  291. package/src/lib/standards/sections.js +47 -0
  292. package/src/lib/standards/verified-against.js +19 -191
  293. package/src/lib/tasks/eval-node.js +23 -179
  294. package/src/lib/tasks/linux-runner.js +18 -142
  295. package/src/lib/tasks/test-nodes.js +43 -313
  296. package/src/lib/tasks/test-runner.js +107 -447
  297. package/src/lib/telemetry/metrics.js +13 -103
  298. package/src/lib/telemetry/telemetry-reader.js +13 -238
  299. package/src/lib/telemetry/verify-event.js +4 -34
  300. package/src/lib/validators/code-budget/code-budget-validator.js +4 -44
  301. package/src/lib/validators/code-budget/index.js +0 -7
  302. package/src/lib/validators/contracts/contract-compliance-validator.js +4 -26
  303. package/src/lib/validators/contracts/index.js +0 -6
  304. package/src/lib/validators/nextjs/index.js +0 -5
  305. package/src/lib/validators/nextjs/next-component-validator.js +4 -81
  306. package/src/lib/validators/packages/index.js +0 -6
  307. package/src/lib/validators/packages/package-validator.js +6 -56
  308. package/src/lib/validators/reuse/index.js +0 -8
  309. package/src/lib/validators/reuse/reuse-validator.js +24 -137
  310. package/src/lib/validators/reuse/symbol-scanner.js +6 -62
  311. package/src/lib/validators/traceability-check.js +54 -156
  312. package/src/lib/validators/validation-runner.js +20 -125
  313. package/src/lib/validators/verify-runner.js +152 -575
  314. package/src/lib/work-type-detector.js +5 -67
  315. package/src/lib/worktree/docker-audit.js +17 -137
  316. package/src/lib/worktree/env-allocator.js +10 -98
  317. package/src/lib/worktree/feature-truth.js +12 -115
  318. package/src/lib/worktree/finish-backup.js +32 -242
  319. package/src/lib/worktree/fleet-scanner.js +31 -126
  320. package/src/lib/worktree/ignored-triage.js +15 -91
  321. package/src/lib/worktree/vscode-settings.js +2 -3
  322. package/src/lib/worktree/worktree-audit.js +21 -213
  323. package/src/lib/worktree/worktree-include.js +3 -5
  324. package/src/scripts/global-install.js +3 -9
  325. package/src/scripts/install-plugin.js +1 -13
  326. package/src/scripts/setup-infra.js +17 -138
  327. package/src/utils/agents-installer.js +92 -272
  328. package/src/utils/banner.js +4 -25
  329. package/src/utils/claude-md-injector.js +1 -37
  330. package/src/utils/claude-settings-manager.js +1 -87
  331. package/src/utils/file-copier.js +32 -90
  332. package/src/utils/hooks-installer.js +26 -296
  333. package/src/utils/skills-installer.js +4 -102
  334. package/src/utils/version-checker.js +4 -83
  335. package/framework/commands/morph-proposal.md +0 -57
  336. package/framework/evals/trace-schema.md +0 -67
  337. package/framework/hooks/claude-code/core/tasks-json-guard.js +0 -83
  338. package/framework/hooks/claude-code/core/trace-autogen.js +0 -277
  339. package/framework/hooks/git/pre-commit/specs.sh +0 -50
  340. package/framework/hooks/shared/tasks-validator.js +0 -111
  341. package/framework/rules/morph-task-tracking.md +0 -54
  342. package/framework/rules/morph-workflow.md +0 -244
  343. package/framework/schemas/tasks.schema.json +0 -79
  344. package/framework/skills/core/morph-brainstorming/SKILL.md +0 -161
  345. package/framework/skills/core/morph-implement/SKILL.md +0 -194
  346. package/framework/skills/core/morph-proposal/SKILL.md +0 -152
  347. package/framework/skills/core/morph-stack-scan/SKILL.md +0 -145
  348. package/framework/templates/docs/proposal.md +0 -192
  349. package/framework/templates/docs/spec.md +0 -57
  350. package/framework/templates/docs/ui-components.md +0 -52
  351. package/framework/templates/docs/ui-design-system.md +0 -76
  352. package/framework/templates/docs/ui-flows.md +0 -167
  353. package/framework/templates/examples/spec-examples.md +0 -91
  354. package/framework/templates/feature/decisions.md +0 -124
  355. package/framework/templates/feature/recap.md +0 -145
  356. package/framework/templates/tasks.template.json +0 -17
  357. package/src/commands/state/usecase.js +0 -143
  358. package/src/commands/tasks/dag.js +0 -181
  359. package/src/commands/utils/index.js +0 -3
  360. package/src/lib/agents/output-collector.js +0 -76
  361. package/src/lib/detectors/design-system-detector.js +0 -188
  362. package/src/lib/evaluator-report.js +0 -104
  363. package/src/lib/generators/design-system-generator.js +0 -508
  364. package/src/lib/specs/acervo-format.js +0 -70
  365. package/src/lib/specs/acervo-lifecycle.js +0 -264
  366. package/src/lib/specs/done-criteria-check.js +0 -200
  367. package/src/lib/specs/usecase-check.js +0 -301
  368. package/src/lib/specs/usecase-promoter.js +0 -301
  369. package/src/lib/specs/usecase-registry.js +0 -237
  370. package/src/lib/tasks/dispatch-planner.js +0 -319
  371. package/src/lib/tasks/dotnet-test-introspection.js +0 -632
  372. package/src/lib/tasks/mermaid-renderer.js +0 -132
  373. package/src/lib/tasks/task-classifier.js +0 -30
  374. package/src/lib/tasks/task-parser.js +0 -209
  375. package/src/lib/tasks/tasks-json-parser.js +0 -296
  376. package/src/lib/tasks/test-scope.js +0 -597
  377. package/src/utils/agent-id-mapper.js +0 -11
@@ -1,32 +1,10 @@
1
- /**
2
- * @fileoverview Project Detector
3
- *
4
- * Scans a project directory for stack, architecture, UI library, and integrations.
5
- * Used by `morph-spec init`, `mcp setup` and the test-node fallback (test-nodes.js).
6
- *
7
- * @module detectors/index
8
- */
9
-
10
1
  import { existsSync, readFileSync, readdirSync } from 'fs';
11
2
  import { join } from 'path';
12
3
 
13
- /**
14
- * Common monorepo locations for a frontend `package.json`, root included.
15
- *
16
- * Exported so `discoverFrontendPackages()` (src/lib/tasks/test-nodes.js, #87
17
- * PR B) scans the SAME candidate list this detector already uses — one
18
- * spelling of "where a frontend package might live", not two that drift.
19
- */
20
- export const PACKAGE_LOCATIONS = ['.', 'src/frontend', 'src/web', 'frontend', 'apps/web', 'packages/app'];
21
-
22
- /**
23
- * Detect project structure from filesystem evidence.
24
- *
25
- * @param {string} targetPath - Root path of the project
26
- * @param {Object} [opts] - Options
27
- * @param {boolean} [opts.generateStandards=false] - Whether to generate inferred markdown
28
- * @returns {{ structure: { stack: string, architecture: string|null, uiLibrary: string|null, integrations: string[], hasVercel: boolean }, inferred: { markdown: string } }}
29
- */
4
+ import { PACKAGE_LOCATIONS } from '../../../framework/hooks/shared/frontend-locations.js';
5
+
6
+ export { PACKAGE_LOCATIONS };
7
+
30
8
  export function detectProject(targetPath, opts = {}) {
31
9
  const structure = {
32
10
  stack: 'unknown',
@@ -37,8 +15,6 @@ export function detectProject(targetPath, opts = {}) {
37
15
  };
38
16
 
39
17
  try {
40
- // ── Package.json analysis ──────────────────────────────────────────────
41
- // Collect deps from root and common monorepo subfolders
42
18
  const allDeps = {};
43
19
  let rootPkg = null;
44
20
  let scripts = [];
@@ -50,17 +26,15 @@ export function detectProject(targetPath, opts = {}) {
50
26
  if (loc === '.') rootPkg = pkg;
51
27
  Object.assign(allDeps, pkg.dependencies, pkg.devDependencies);
52
28
  scripts.push(...Object.keys(pkg.scripts || {}));
53
- // Track frontend path for config
54
29
  if (loc !== '.' && (pkg.dependencies?.next || pkg.dependencies?.react || pkg.dependencies?.vue)) {
55
30
  structure.frontendPath = loc;
56
31
  }
57
- } catch { /* invalid JSON */ }
32
+ } catch {}
58
33
  }
59
34
  const depNames = Object.keys(allDeps);
60
35
 
61
36
  if (depNames.length > 0) {
62
37
 
63
- // Stack detection from deps
64
38
  if (depNames.includes('next')) {
65
39
  structure.stack = 'nextjs';
66
40
  } else if (depNames.includes('react')) {
@@ -73,12 +47,10 @@ export function detectProject(targetPath, opts = {}) {
73
47
  structure.stack = 'nodejs';
74
48
  }
75
49
 
76
- // UI library detection
77
50
  if (existsSync(join(targetPath, 'components.json')) || existsSync(join(targetPath, structure.frontendPath || '.', 'components.json')) || depNames.includes('@shadcn/ui')) {
78
51
  structure.uiLibrary = 'shadcn';
79
52
  }
80
53
 
81
- // Integrations
82
54
  if (depNames.includes('@neondatabase/serverless') || depNames.includes('postgres') || depNames.includes('pg')) {
83
55
  structure.integrations.push('neon');
84
56
  }
@@ -89,13 +61,11 @@ export function detectProject(targetPath, opts = {}) {
89
61
  structure.integrations.push('stripe');
90
62
  }
91
63
 
92
- // Vercel detection
93
64
  if (depNames.includes('vercel') || scripts.includes('vercel')) {
94
65
  structure.hasVercel = true;
95
66
  }
96
67
  }
97
68
 
98
- // ── .csproj detection ──────────────────────────────────────────────────
99
69
  let hasDotnet = false;
100
70
  const csprojLocations = ['.', 'src', 'src/Api', 'src/Web', 'src/backend'];
101
71
 
@@ -110,7 +80,7 @@ export function detectProject(targetPath, opts = {}) {
110
80
  if (content.includes('Npgsql')) {
111
81
  if (!structure.integrations.includes('neon')) structure.integrations.push('neon');
112
82
  }
113
- } catch { /* ignore */ }
83
+ } catch {}
114
84
  }
115
85
 
116
86
  for (const loc of csprojLocations) {
@@ -118,41 +88,34 @@ export function detectProject(targetPath, opts = {}) {
118
88
  const dir = join(targetPath, loc);
119
89
  if (!existsSync(dir)) continue;
120
90
  const entries = readdirSyncSafe(dir);
121
- // Direct .csproj files
122
91
  for (const e of entries.filter(f => f.endsWith('.csproj'))) {
123
92
  checkCsproj(join(dir, e));
124
93
  }
125
- // One level deeper (e.g., src/backend/MyProject/*.csproj)
126
94
  for (const sub of entries) {
127
95
  const subDir = join(dir, sub);
128
96
  for (const e of readdirSyncSafe(subDir).filter(f => f.endsWith('.csproj'))) {
129
97
  checkCsproj(join(subDir, e));
130
98
  }
131
99
  }
132
- } catch { /* ignore */ }
100
+ } catch {}
133
101
  }
134
102
 
135
- // Determine stack: monorepo (nextjs+dotnet), dotnet, or keep frontend stack
136
103
  if (hasDotnet) {
137
104
  if (structure.stack === 'nextjs' || structure.stack === 'react' || structure.stack === 'vue') {
138
- // Monorepo: frontend + .NET backend
139
105
  structure.stack = `${structure.stack}+dotnet`;
140
106
  } else if (structure.stack === 'unknown') {
141
107
  structure.stack = 'dotnet';
142
108
  }
143
109
  }
144
110
 
145
- // ── vercel.json detection ──────────────────────────────────────────────
146
111
  if (existsSync(join(targetPath, 'vercel.json'))) {
147
112
  structure.hasVercel = true;
148
113
  }
149
114
 
150
- // ── tsconfig.json detection (fallback for stack) ────────────────────────
151
115
  if (structure.stack === 'unknown' && existsSync(join(targetPath, 'tsconfig.json'))) {
152
116
  structure.stack = 'nodejs';
153
117
  }
154
118
 
155
- // ── Architecture detection ─────────────────────────────────────────────
156
119
  try {
157
120
  const configPath = join(targetPath, '.morph/config/config.json');
158
121
  if (existsSync(configPath)) {
@@ -161,16 +124,14 @@ export function detectProject(targetPath, opts = {}) {
161
124
  structure.architecture = config.architecture.style;
162
125
  }
163
126
  }
164
- } catch { /* ignore */ }
127
+ } catch {}
165
128
 
166
- // ── Docker detection ───────────────────────────────────────────────────
167
129
  if (existsSync(join(targetPath, 'docker-compose.yml')) ||
168
130
  existsSync(join(targetPath, 'docker-compose.yaml')) ||
169
131
  existsSync(join(targetPath, 'Dockerfile'))) {
170
132
  if (!structure.integrations.includes('docker')) structure.integrations.push('docker');
171
133
  }
172
134
 
173
- // ── Azure detection ────────────────────────────────────────────────────
174
135
  const azureSignals = [
175
136
  '.azure',
176
137
  'azure-pipelines.yml',
@@ -181,7 +142,6 @@ export function detectProject(targetPath, opts = {}) {
181
142
  const p = join(targetPath, signal);
182
143
  if (!existsSync(p)) return false;
183
144
  if (signal === 'infra') {
184
- // Check for .bicep files inside infra/
185
145
  return readdirSyncSafe(p).some(f => f.endsWith('.bicep'));
186
146
  }
187
147
  return true;
@@ -190,7 +150,6 @@ export function detectProject(targetPath, opts = {}) {
190
150
  structure.integrations.push('azure');
191
151
  }
192
152
  } catch {
193
- // Fail-safe — return defaults
194
153
  }
195
154
 
196
155
  return {
@@ -201,11 +160,6 @@ export function detectProject(targetPath, opts = {}) {
201
160
  };
202
161
  }
203
162
 
204
- /**
205
- * Safe readdir that returns [] on error.
206
- * @param {string} dir
207
- * @returns {string[]}
208
- */
209
163
  function readdirSyncSafe(dir) {
210
164
  try {
211
165
  return readdirSync(dir);
@@ -214,11 +168,6 @@ function readdirSyncSafe(dir) {
214
168
  }
215
169
  }
216
170
 
217
- /**
218
- * Generate a markdown summary from detected structure.
219
- * @param {Object} structure
220
- * @returns {string}
221
- */
222
171
  function generateInferredMarkdown(structure) {
223
172
  const lines = [`## Detected Stack: ${structure.stack}`];
224
173
  if (structure.architecture) lines.push(`Architecture: ${structure.architecture}`);
@@ -1,22 +1,5 @@
1
- /**
2
- * Compose environment for the e2e stack — the port block a feature owns, plus
3
- * the credentials its auth setup needs.
4
- *
5
- * This lives in ONE place because it has two callers that must never disagree:
6
- * `morph-spec e2e up` (manual) and the `e2e` node inside `morph-spec verify`
7
- * (the one that actually runs in the loop). When only the manual path built the
8
- * port block, the isolation was real in the command nobody runs and absent in
9
- * the one everybody runs — two worktrees would get distinct container names via
10
- * COMPOSE_PROJECT_NAME and then collide on host port 3000 anyway, surfacing as
11
- * "port is already allocated" and pausing a gate over an infrastructure clash
12
- * rather than a defect.
13
- *
14
- * It sits in src/lib rather than framework/hooks/shared because it depends on
15
- * env-allocator.js: hooks are installed standalone into target projects, where
16
- * `src/` does not exist, so the dependency may only point this way.
17
- *
18
- * @module lib/e2e/compose-env
19
- */
1
+ // One place for `e2e up` and the `e2e` node of `verify`, which must never disagree on ports. Lives in
2
+ // src/lib, not hooks/shared, because it depends on env-allocator.js and hooks run without `src/`.
20
3
 
21
4
  import { join } from 'path';
22
5
 
@@ -25,43 +8,11 @@ import chalk from 'chalk';
25
8
  import { loadEnvFile } from '../../../framework/hooks/shared/e2e-check.js';
26
9
  import { allocateEnvBlock, portLayout, resolveFleetConfig, resolvePortAliases } from '../worktree/env-allocator.js';
27
10
 
28
- /**
29
- * Build the environment a `docker compose` invocation should carry.
30
- *
31
- * Port variables come from `portLayout()` in env-allocator.js — the SAME
32
- * function that renders `.morph/worktree.env` — so a compose file and the
33
- * worktree manifest describe the same world by construction (`PORT`,
34
- * `API_PORT`/`ASPNETCORE_URLS`, `POSTGRES_PORT`, `COMPOSE_PROJECT_NAME`).
35
- *
36
- * `PLAYWRIGHT_BASE_URL` is derived here rather than left to the spec config —
37
- * the suite has to be told where the app actually landed, otherwise a feature
38
- * on port 4020 gets tested against a hardcoded localhost:3000 and fails with
39
- * ECONNREFUSED that looks exactly like a broken app.
40
- *
41
- * The credentials env file loads AFTER the layout but cannot outrank it: a
42
- * `.env.e2e` copied from a sibling worktree carries THAT worktree's block, and
43
- * letting it win points this stack at the neighbour's postgres while every
44
- * other surface still reports the allocated port. The protected keys are the
45
- * ones actually assigned above — never a second literal list, which is exactly
46
- * how an offset lands in one writer and not the other. A key that gets ignored
47
- * is announced on stderr (never stdout: `morph-spec env` writes shell-eval
48
- * output there), because swapping a silent override for a silent discard just
49
- * moves the debugging session.
50
- *
51
- * Fail-open throughout: with no git dir (or a corrupt registry) the caller gets
52
- * default ports, which only matters when two stacks run at once. With no layout
53
- * applied nothing is filtered — there the env file is the only port source.
54
- *
55
- * @param {object} params
56
- * @param {string} params.cwd - project root
57
- * @param {object|null} [params.config] - .morph/config/config.json contents
58
- * @param {string} params.featureName
59
- * @param {string|null} [params.gitCommonDir]
60
- * @returns {Record<string,string>}
61
- */
11
+ // Ports come from `portLayout()`, the same function that renders `.morph/worktree.env`. The credentials
12
+ // file loads after the layout but cannot outrank it: a `.env.e2e` copied from a sibling worktree carries
13
+ // that worktree's block. Ignored keys are announced on stderr; stdout carries `morph-spec env` output.
62
14
  export function buildComposeEnv({ cwd, config, featureName, gitCommonDir }) {
63
15
  const env = {};
64
- /** @type {Set<string>|null} - null while no layout has been applied */
65
16
  let layoutKeys = null;
66
17
 
67
18
  if (gitCommonDir) {
@@ -97,18 +48,6 @@ export function buildComposeEnv({ cwd, config, featureName, gitCommonDir }) {
97
48
  return env;
98
49
  }
99
50
 
100
- /**
101
- * Tell the caller — `e2e up`, the `e2e` node of `verify`, `stack-teardown` and
102
- * `morph-spec env` all reach this through `buildComposeEnv` — which keys of the
103
- * credentials file were dropped and what won instead.
104
- *
105
- * stderr, always: `morph-spec env` prints `export K=v` on stdout for a
106
- * shell to eval, and `verify` prints JSON there.
107
- *
108
- * @param {string} envFile
109
- * @param {string[]} ignored
110
- * @param {Record<string,string>} env - the layout that won
111
- */
112
51
  function reportIgnoredLayoutKeys(envFile, ignored, env) {
113
52
  const shown = ignored.map((key) => `${key}=${env[key]}`).join(', ');
114
53
  console.warn(chalk.yellow(
@@ -1,27 +1,6 @@
1
- /**
2
- * Reclaim a feature's verification stack — containers, ports, named volumes
3
- * and the freshness stamp — from the tree that owns the feature.
4
- *
5
- * `morph-spec verify` leaves the stack UP on purpose (cold-starting a
6
- * container per task is what makes the loop unusable), so something has to be
7
- * the one place that brings it down when the feature closes. That place is
8
- * this module, shared by `finish` and `delete --with-worktree`.
9
- *
10
- * Three things the old root-side teardown got wrong, each pinned by a test:
11
- * 1. It ran from the ROOT. A compose that exists only in the worktree was
12
- * never found, and a bind mount resolved to the wrong checkout.
13
- * 2. It passed a bare `COMPOSE_PROJECT_NAME`. Without the port block
14
- * (`PORT`, `POSTGRES_PORT`, …) compose resolves a different config than
15
- * the one that came up, and `down` misses the containers.
16
- * 3. It never removed volumes or the stamp. Postgres data and a stamp saying
17
- * "source unchanged since build" outlived the feature.
18
- *
19
- * Entirely fail-open: no compose, no docker, or a stubborn container are all
20
- * non-events for the caller — a stack that refuses to come down must never
21
- * fail a finish that already merged.
22
- *
23
- * @module lib/e2e/stack-teardown
24
- */
1
+ // `verify` leaves the stack up on purpose, so this is the one place that brings it down. Runs from the
2
+ // owning tree with the full port block, or compose resolves a different config and `down` misses it.
3
+ // Fail-open: a stack that refuses to come down must never fail a finish that already merged.
25
4
 
26
5
  import { execFileSync } from 'child_process';
27
6
  import { existsSync, readFileSync } from 'fs';
@@ -36,15 +15,6 @@ import {
36
15
  } from '../../../framework/hooks/shared/e2e-check.js';
37
16
  import { buildComposeEnv } from './compose-env.js';
38
17
 
39
- /**
40
- * @param {string} feature
41
- * @param {object} params
42
- * @param {string} params.root - primary root (absolute)
43
- * @param {string|null} [params.worktreePath] - the feature's live worktree, if any
44
- * @param {boolean} [params.volumes=true] - also remove named volumes (`down -v`)
45
- * @param {Function} [params._exec] - injectable executor (testing)
46
- * @returns {{ attempted: boolean, cwd: string, status: 'pass'|'fail'|'skip', stampDeleted: boolean, output?: string }}
47
- */
48
18
  export function tearDownFeatureStack(feature, { root, worktreePath = null, volumes = true, _exec = defaultExec } = {}) {
49
19
  const cwd = worktreePath && existsSync(worktreePath) ? worktreePath : root;
50
20
  const projectName = composeProjectName(feature);
@@ -53,8 +23,7 @@ export function tearDownFeatureStack(feature, { root, worktreePath = null, volum
53
23
  try {
54
24
  const config = readConfig(cwd) ?? readConfig(root);
55
25
 
56
- // The owning tree's compose first; the root's copy is the fallback for a
57
- // worktree already half torn down (versioned file, so equivalent).
26
+ // The owning tree's compose first; the root's copy is the fallback for a worktree already half torn down.
58
27
  let composeCwd = cwd;
59
28
  let composeFile = resolveComposeFile(cwd, config);
60
29
  if (!composeFile && cwd !== root) {
@@ -63,8 +32,7 @@ export function tearDownFeatureStack(feature, { root, worktreePath = null, volum
63
32
  }
64
33
 
65
34
  if (!composeFile) {
66
- // Nothing to bring down — but a stamp left behind would tell the next
67
- // `up` that a stack it cannot see is still fresh.
35
+ // Nothing to bring down, but a stamp left behind would tell the next `up` a stack it cannot see is fresh.
68
36
  return { attempted: false, cwd, status: 'skip', stampDeleted: deleteStamp(gitCommonDir, projectName) };
69
37
  }
70
38
 
@@ -82,13 +50,11 @@ export function tearDownFeatureStack(feature, { root, worktreePath = null, volum
82
50
  ...(result.status === 'fail' && result.output ? { output: result.output } : {}),
83
51
  };
84
52
  } catch {
85
- // Unconditional even when the teardown itself blew up: the stamp must not
86
- // outlive the stack it described.
53
+ // The stamp must not outlive the stack it described, even when the teardown itself blew up.
87
54
  return { attempted: false, cwd, status: 'fail', stampDeleted: deleteStamp(gitCommonDir, projectName) };
88
55
  }
89
56
  }
90
57
 
91
- /** BOM-tolerant config read; null when absent or malformed. */
92
58
  function readConfig(dir) {
93
59
  try {
94
60
  const path = join(dir, '.morph', 'config', 'config.json');