@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,19 +1,3 @@
1
- /**
2
- * Architecture Scanner - Generates rich architectural context from project filesystem.
3
- *
4
- * Performs fast (<5s) glob-based scanning to produce a snapshot of:
5
- * - .NET entities (sealed class/record)
6
- * - API endpoints (IApiEndpoint implementations)
7
- * - Next.js pages and components
8
- * - Integrations (from appsettings.json)
9
- * - Database schema (from EF migrations)
10
- * - Stack dependencies (.csproj + package.json)
11
- *
12
- * All scanning is regex-based (no AST parsing) for speed.
13
- *
14
- * @module architecture-scanner
15
- */
16
-
17
1
  import fs from 'fs/promises';
18
2
  import path from 'path';
19
3
  import { fileURLToPath } from 'url';
@@ -25,16 +9,6 @@ import { WORKTREE_DIR_NAMES } from '../worktree/dirs.js';
25
9
  export const SKIP_DIRS = new Set(['node_modules', 'bin', 'obj', '.git', '.morph', '.next', 'dist', 'out', ...WORKTREE_DIR_NAMES]);
26
10
  const MAX_FILES_PER_SCANNER = 200;
27
11
 
28
- /**
29
- * Recursively walk a directory, returning files matching a filter.
30
- * Skips known heavy directories for performance.
31
- *
32
- * @param {string} dir - Directory to walk
33
- * @param {function} filter - (relativePath) => boolean
34
- * @param {string} [base] - Base path for relative calculation
35
- * @param {number} [limit] - Max files to return
36
- * @returns {Promise<Array<{abs: string, rel: string}>>}
37
- */
38
12
  async function walkDir(dir, filter, base = dir, limit = MAX_FILES_PER_SCANNER) {
39
13
  const results = [];
40
14
 
@@ -68,12 +42,6 @@ async function walkDir(dir, filter, base = dir, limit = MAX_FILES_PER_SCANNER) {
68
42
  return results;
69
43
  }
70
44
 
71
- /**
72
- * Scan .NET entities from Entities/ or Features/ directories.
73
- *
74
- * @param {string} projectPath
75
- * @returns {Promise<Array<{name: string, type: string, path: string}>>}
76
- */
77
45
  export async function scanEntities(projectPath) {
78
46
  try {
79
47
  const files = await walkDir(
@@ -91,7 +59,6 @@ export async function scanEntities(projectPath) {
91
59
  entityRegex.lastIndex = 0;
92
60
  while ((match = entityRegex.exec(content)) !== null) {
93
61
  const line = content.slice(Math.max(0, match.index - 80), match.index + match[0].length);
94
- // Only capture sealed/record types or classes in entity-like directories
95
62
  if (/sealed|record/.test(line) || file.rel.includes('Entities/')) {
96
63
  entities.push({
97
64
  name: match[2],
@@ -100,7 +67,7 @@ export async function scanEntities(projectPath) {
100
67
  });
101
68
  }
102
69
  }
103
- } catch { /* skip unreadable files */ }
70
+ } catch {}
104
71
  }
105
72
 
106
73
  return entities;
@@ -109,12 +76,6 @@ export async function scanEntities(projectPath) {
109
76
  }
110
77
  }
111
78
 
112
- /**
113
- * Scan API endpoints implementing IApiEndpoint.
114
- *
115
- * @param {string} projectPath
116
- * @returns {Promise<Array<{name: string, route: string, method: string, path: string}>>}
117
- */
118
79
  export async function scanEndpoints(projectPath) {
119
80
  try {
120
81
  const files = await walkDir(
@@ -142,7 +103,7 @@ export async function scanEndpoints(projectPath) {
142
103
  method: methodMatch ? (methodMatch[1] || methodMatch[2] || '').toUpperCase() : '',
143
104
  path: file.rel
144
105
  });
145
- } catch { /* skip */ }
106
+ } catch {}
146
107
  }
147
108
 
148
109
  return endpoints;
@@ -151,17 +112,10 @@ export async function scanEndpoints(projectPath) {
151
112
  }
152
113
  }
153
114
 
154
- /**
155
- * Scan Next.js pages and components.
156
- *
157
- * @param {string} projectPath
158
- * @returns {Promise<{pages: Array<{route: string, path: string}>, layouts: Array<{path: string}>, components: Array<{name: string, path: string}>}>}
159
- */
160
115
  export async function scanNextjsComponents(projectPath) {
161
116
  try {
162
117
  const result = { pages: [], layouts: [], components: [] };
163
118
 
164
- // Scan pages and layouts from app directory
165
119
  const appFiles = await walkDir(
166
120
  projectPath,
167
121
  (rel, name) =>
@@ -181,7 +135,6 @@ export async function scanNextjsComponents(projectPath) {
181
135
  }
182
136
  }
183
137
 
184
- // Scan components
185
138
  const componentFiles = await walkDir(
186
139
  projectPath,
187
140
  (rel, name) =>
@@ -191,7 +144,6 @@ export async function scanNextjsComponents(projectPath) {
191
144
 
192
145
  for (const file of componentFiles) {
193
146
  const name = path.basename(file.rel, path.extname(file.rel));
194
- // Skip index files and test files
195
147
  if (name === 'index' || name.includes('.test') || name.includes('.spec')) continue;
196
148
  result.components.push({ name, path: file.rel });
197
149
  }
@@ -202,12 +154,6 @@ export async function scanNextjsComponents(projectPath) {
202
154
  }
203
155
  }
204
156
 
205
- /**
206
- * Scan integrations from appsettings*.json files.
207
- *
208
- * @param {string} projectPath
209
- * @returns {Promise<Array<{name: string, type: string, configured: boolean}>>}
210
- */
211
157
  export async function scanIntegrations(projectPath) {
212
158
  try {
213
159
  const files = await walkDir(
@@ -217,7 +163,6 @@ export async function scanIntegrations(projectPath) {
217
163
  20
218
164
  );
219
165
 
220
- // Also check .env files for common integrations
221
166
  const envFiles = await walkDir(
222
167
  projectPath,
223
168
  (rel, name) => name === '.env' || name === '.env.local' || name === '.env.production',
@@ -242,7 +187,6 @@ export async function scanIntegrations(projectPath) {
242
187
 
243
188
  const detected = new Map();
244
189
 
245
- // Scan appsettings files
246
190
  for (const file of files) {
247
191
  try {
248
192
  const content = JSON.parse(await fs.readFile(file.abs, 'utf8'));
@@ -256,7 +200,6 @@ export async function scanIntegrations(projectPath) {
256
200
  }
257
201
  }
258
202
  }
259
- // Check ConnectionStrings specifically
260
203
  if (content.ConnectionStrings) {
261
204
  for (const [key, val] of Object.entries(content.ConnectionStrings)) {
262
205
  if (val && !String(val).startsWith('{{')) {
@@ -264,10 +207,9 @@ export async function scanIntegrations(projectPath) {
264
207
  }
265
208
  }
266
209
  }
267
- } catch { /* skip invalid JSON */ }
210
+ } catch {}
268
211
  }
269
212
 
270
- // Scan .env files for known prefixes
271
213
  const envPrefixes = {
272
214
  'NEON_AUTH_': 'NeonAuth',
273
215
  'DATABASE_URL': 'Neon',
@@ -289,7 +231,7 @@ export async function scanIntegrations(projectPath) {
289
231
  }
290
232
  }
291
233
  }
292
- } catch { /* skip */ }
234
+ } catch {}
293
235
  }
294
236
 
295
237
  return Array.from(detected.values());
@@ -298,12 +240,6 @@ export async function scanIntegrations(projectPath) {
298
240
  }
299
241
  }
300
242
 
301
- /**
302
- * Scan database schema from EF Core migrations.
303
- *
304
- * @param {string} projectPath
305
- * @returns {Promise<Array<{table: string, migration: string}>>}
306
- */
307
243
  export async function scanDatabaseSchema(projectPath) {
308
244
  try {
309
245
  const files = await walkDir(
@@ -331,10 +267,9 @@ export async function scanDatabaseSchema(projectPath) {
331
267
  }
332
268
  }
333
269
  }
334
- } catch { /* skip */ }
270
+ } catch {}
335
271
  }
336
272
 
337
- // Also scan database migrations (SQL)
338
273
  const sqlFiles = await walkDir(
339
274
  projectPath,
340
275
  (rel, name) => name.endsWith('.sql') && rel.includes('migrations/'),
@@ -355,7 +290,7 @@ export async function scanDatabaseSchema(projectPath) {
355
290
  tables.set(match[1], { table: match[1], migration: migrationName });
356
291
  }
357
292
  }
358
- } catch { /* skip */ }
293
+ } catch {}
359
294
  }
360
295
 
361
296
  return Array.from(tables.values());
@@ -364,17 +299,10 @@ export async function scanDatabaseSchema(projectPath) {
364
299
  }
365
300
  }
366
301
 
367
- /**
368
- * Detect stack from .csproj PackageReference and package.json dependencies.
369
- *
370
- * @param {string} projectPath
371
- * @returns {Promise<{dotnet: Array<{name: string, version: string}>, npm: Array<{name: string, version: string}>}>}
372
- */
373
302
  export async function scanStackDependencies(projectPath) {
374
303
  try {
375
304
  const result = { dotnet: [], npm: [] };
376
305
 
377
- // Scan .csproj files
378
306
  const csprojFiles = await walkDir(
379
307
  projectPath,
380
308
  (rel, name) => name.endsWith('.csproj'),
@@ -392,10 +320,9 @@ export async function scanStackDependencies(projectPath) {
392
320
  while ((match = packageRefRegex.exec(content)) !== null) {
393
321
  result.dotnet.push({ name: match[1], version: match[2] });
394
322
  }
395
- } catch { /* skip */ }
323
+ } catch {}
396
324
  }
397
325
 
398
- // Scan package.json (root only)
399
326
  const pkgPath = path.join(projectPath, 'package.json');
400
327
  if (existsSync(pkgPath)) {
401
328
  try {
@@ -404,10 +331,9 @@ export async function scanStackDependencies(projectPath) {
404
331
  for (const [name, version] of Object.entries(allDeps)) {
405
332
  result.npm.push({ name, version: String(version) });
406
333
  }
407
- } catch { /* skip */ }
334
+ } catch {}
408
335
  }
409
336
 
410
- // Also check web/ or frontend/ subdirectory package.json
411
337
  for (const subdir of ['web', 'frontend', 'client', 'src']) {
412
338
  const subPkgPath = path.join(projectPath, subdir, 'package.json');
413
339
  if (existsSync(subPkgPath)) {
@@ -415,12 +341,11 @@ export async function scanStackDependencies(projectPath) {
415
341
  const pkg = JSON.parse(await fs.readFile(subPkgPath, 'utf8'));
416
342
  const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
417
343
  for (const [name, version] of Object.entries(allDeps)) {
418
- // Avoid duplicates
419
344
  if (!result.npm.some(d => d.name === name)) {
420
345
  result.npm.push({ name, version: String(version) });
421
346
  }
422
347
  }
423
- } catch { /* skip */ }
348
+ } catch {}
424
349
  }
425
350
  }
426
351
 
@@ -430,12 +355,6 @@ export async function scanStackDependencies(projectPath) {
430
355
  }
431
356
  }
432
357
 
433
- /**
434
- * Master scan — runs all scanners in parallel.
435
- *
436
- * @param {string} projectPath
437
- * @returns {Promise<Object>} ArchitectureScanResult
438
- */
439
358
  export async function scanArchitecture(projectPath) {
440
359
  const [entities, endpoints, nextjs, integrations, database, stack, graph] = await Promise.all([
441
360
  scanEntities(projectPath),
@@ -444,9 +363,7 @@ export async function scanArchitecture(projectPath) {
444
363
  scanIntegrations(projectPath),
445
364
  scanDatabaseSchema(projectPath),
446
365
  scanStackDependencies(projectPath),
447
- // Aditivo: sem grafo devolve listas vazias e nada muda no README. O
448
- // inventário acima continua sendo a espinha do arquivo — ele tem
449
- // exaustividade que o grafo não tem.
366
+ // Aditivo: sem grafo devolve listas vazias; o inventário acima tem a exaustividade que o grafo não tem.
450
367
  scanGraph(projectPath)
451
368
  ]);
452
369
 
@@ -462,20 +379,11 @@ export async function scanArchitecture(projectPath) {
462
379
  };
463
380
  }
464
381
 
465
- /**
466
- * Resolve a template path: check .morph/framework/templates/ first, then framework/templates/,
467
- * then fall back to the CLI package's own framework/templates/.
468
- *
469
- * @param {string} projectPath
470
- * @param {string} templateRelPath
471
- * @returns {string|null}
472
- */
382
+ // Project-local `.morph/framework/templates/` override first, then the CLI package's own.
473
383
  function resolveTemplatePath(projectPath, templateRelPath) {
474
- // 1. Project-local override
475
384
  const projectLocal = path.join(projectPath, '.morph/framework/templates', templateRelPath);
476
385
  if (existsSync(projectLocal)) return projectLocal;
477
386
 
478
- // 2. CLI package framework/ (for running from source or during init)
479
387
  const cliFramework = path.join(
480
388
  cliRootDir(), 'framework', 'templates', templateRelPath
481
389
  );
@@ -484,103 +392,64 @@ function resolveTemplatePath(projectPath, templateRelPath) {
484
392
  return null;
485
393
  }
486
394
 
487
- /**
488
- * The CLI package root, as a real filesystem path.
489
- *
490
- * fileURLToPath, not `new URL(...).pathname`: the latter leaves the path
491
- * percent-encoded, so an install under a directory with a space resolved to
492
- * ".../Program%20Files/..." — a path that never exists. `resolveTemplatePath`
493
- * then returned null and the caller fell through to its plain-text fallback
494
- * WITHOUT any warning. The first lines of that fallback are identical to the
495
- * template's, which is why nobody noticed the tables were gone. On Windows a
496
- * global npm install lives under a spaced path by default, so this was the
497
- * common case, not the edge one.
498
- */
395
+ // fileURLToPath, not `new URL(...).pathname`: the latter stays percent-encoded, so a path with a space
396
+ // (the default global npm install on Windows) never resolves and the template is silently dropped.
499
397
  function cliRootDir() {
500
398
  return path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '..');
501
399
  }
502
400
 
503
- /**
504
- * Render architecture context to .morph/context/README.md
505
- *
506
- * QUEM LÊ ESTE ARQUIVO, E QUANDO: o passo 1c da skill `morph-plan` (mapa de
507
- * reuso), antes de decidir REUSAR/ESTENDER/CRIAR cada conceito da feature. É a
508
- * granularidade de CONCEITO — entidades, endpoints com rota, componentes com
509
- * path — que o grafo de codebase, que casa por símbolo, não dá; e é o único
510
- * inventário legível num projeto sem grafo (sem Python), antes do grep.
511
- *
512
- * Até 2026-08-27 este arquivo era gerado e NUNCA lido por skill nenhuma
513
- * (docs/specs/code-reuse-gap/analysis.md §2.5). Se um dia o consumidor acima
514
- * desaparecer do `morph-plan`, este gerador volta a queimar tempo por nada —
515
- * a decisão então é remover os dois, não deixar o arquivo órfão de novo.
516
- *
517
- * @param {string} projectPath
518
- * @param {Object} scanResult - Result from scanArchitecture()
519
- * @param {Object} [options]
520
- * @param {string} [options.projectName] - Override project name
521
- * @returns {Promise<string>} Path to written file
522
- */
401
+ // Read by `morph-plan` for the concept-level inventory the graph doesn't give. If that reader goes away,
402
+ // remove this generator too.
523
403
  export async function renderArchitectureContext(projectPath, scanResult, options = {}) {
524
404
  const templatePath = resolveTemplatePath(projectPath, 'context/ARCHITECTURE.md');
525
405
 
526
- // Determine project name
527
406
  let projectName = options.projectName;
528
407
  if (!projectName) {
529
- // Try config.json
530
408
  const configPath = path.join(projectPath, '.morph/config/config.json');
531
409
  if (existsSync(configPath)) {
532
410
  try {
533
411
  const config = JSON.parse(readFileSync(configPath, 'utf8'));
534
412
  projectName = config.project?.name;
535
- } catch { /* ignore */ }
413
+ } catch {}
536
414
  }
537
- // Fallback to directory name
538
415
  if (!projectName) {
539
416
  projectName = path.basename(projectPath);
540
417
  }
541
418
  }
542
419
 
543
- // Get morph-spec version
544
420
  let morphVersion = 'unknown';
545
421
  try {
546
422
  const pkgPath = path.join(cliRootDir(), 'package.json');
547
423
  if (existsSync(pkgPath)) {
548
424
  morphVersion = JSON.parse(readFileSync(pkgPath, 'utf8')).version;
549
425
  }
550
- } catch { /* ignore */ }
426
+ } catch {}
551
427
 
552
428
  const variables = {
553
429
  projectName,
554
430
  timestamp: new Date().toISOString().replace('T', ' ').split('.')[0],
555
431
  morphVersion,
556
- // Entities
557
432
  hasDotnet: scanResult.entities.length > 0 || scanResult.endpoints.length > 0,
558
433
  entities: scanResult.entities,
559
434
  entityCount: scanResult.entities.length,
560
435
  endpoints: scanResult.endpoints,
561
436
  endpointCount: scanResult.endpoints.length,
562
- // Next.js
563
437
  hasNextjs: scanResult.nextjs.pages.length > 0 || scanResult.nextjs.components.length > 0,
564
438
  pages: scanResult.nextjs.pages,
565
439
  pageCount: scanResult.nextjs.pages.length,
566
440
  layouts: scanResult.nextjs.layouts,
567
441
  components: scanResult.nextjs.components,
568
442
  componentCount: scanResult.nextjs.components.length,
569
- // Integrations
570
443
  hasIntegrations: scanResult.integrations.length > 0,
571
444
  integrations: scanResult.integrations,
572
- // Database
573
445
  hasTables: scanResult.database.length > 0,
574
446
  tables: scanResult.database,
575
447
  tableCount: scanResult.database.length,
576
- // Stack
577
448
  hasDotnetPackages: scanResult.stack.dotnet.length > 0,
578
449
  dotnetPackages: scanResult.stack.dotnet,
579
450
  hasNpmPackages: scanResult.stack.npm.length > 0,
580
451
  npmPackages: scanResult.stack.npm,
581
- // Centralidade (grafo de codebase) — ACRESCENTA, nunca substitui.
582
- // Comunidade ainda com rótulo Community_N fica de fora: sem
583
- // `graphify label` ela é ruído puro (441 páginas assim no eval).
452
+ // Comunidade ainda rotulada Community_N fica de fora: sem `graphify label` é ruído puro.
584
453
  hasGraph: scanResult.graph?.available === true && (scanResult.graph.godNodes?.length ?? 0) > 0,
585
454
  godNodes: scanResult.graph?.godNodes ?? [],
586
455
  communities: (scanResult.graph?.communities ?? []).filter((c) => c.labeled),
@@ -591,11 +460,9 @@ export async function renderArchitectureContext(projectPath, scanResult, options
591
460
  if (templatePath) {
592
461
  content = renderTemplate(templatePath, variables);
593
462
  } else {
594
- // Fallback: generate minimal markdown without template
595
463
  content = generateFallbackMarkdown(variables);
596
464
  }
597
465
 
598
- // Write to .morph/context/README.md
599
466
  const contextDir = path.join(projectPath, '.morph/context');
600
467
  await fs.mkdir(contextDir, { recursive: true });
601
468
  const outputPath = path.join(contextDir, 'README.md');
@@ -604,11 +471,6 @@ export async function renderArchitectureContext(projectPath, scanResult, options
604
471
  return outputPath;
605
472
  }
606
473
 
607
- /**
608
- * Generate minimal markdown when template is not available.
609
- * @param {Object} vars
610
- * @returns {string}
611
- */
612
474
  function generateFallbackMarkdown(vars) {
613
475
  const lines = [`# ${vars.projectName} — Architecture Context\n`];
614
476
  lines.push(`> Auto-generated by morph-spec context refresh`);