@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,14 +1,5 @@
1
- /**
2
- * Shared per-feature state writer for Claude Code hooks.
3
- *
4
- * Hooks run inside the user's project and cannot import the CLI's
5
- * src/core/state-manager.js. This module is the hook-side mirror of the core
6
- * writers: it persists a feature to its authoritative `feature.json` (committed)
7
- * and refreshes the thin, gitignored root index (`.morph/state.json`).
8
- *
9
- * Fail-open by contract: every function swallows errors and returns a boolean —
10
- * a hook must never break the agent over a state write.
11
- */
1
+ // Hook-side mirror of the CLI state writers (hooks cannot import `src/`).
2
+ // Fail-open: every function returns a boolean, never throws.
12
3
 
13
4
  import { readFileSync, writeFileSync, renameSync, unlinkSync, existsSync, mkdirSync } from 'fs';
14
5
  import { join, dirname } from 'path';
@@ -17,12 +8,10 @@ import { clearStateCache } from './state-reader.js';
17
8
  const STATE_FILE = '.morph/state.json';
18
9
  const STATE_VERSION = '5.0.0';
19
10
 
20
- /** Absolute path to a feature's authoritative feature.json. */
21
11
  export function featureJsonPath(featureName, projectPath) {
22
12
  return join(projectPath || process.cwd(), '.morph', 'features', featureName, 'feature.json');
23
13
  }
24
14
 
25
- /** Read a feature's feature.json, or null if missing/corrupt. */
26
15
  export function readFeatureFile(featureName, projectPath) {
27
16
  const p = featureJsonPath(featureName, projectPath);
28
17
  if (!existsSync(p)) return null;
@@ -33,7 +22,7 @@ export function readFeatureFile(featureName, projectPath) {
33
22
  }
34
23
  }
35
24
 
36
- /** Atomic JSON write: per-pid temp then rename, with an EPERM retry for Windows. */
25
+ // EPERM retry: Windows rename fails while another process holds the target.
37
26
  function atomicWriteJson(targetPath, data) {
38
27
  const dir = dirname(targetPath);
39
28
  if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
@@ -54,11 +43,6 @@ function atomicWriteJson(targetPath, data) {
54
43
  }
55
44
  }
56
45
 
57
- /**
58
- * Persist a feature to its authoritative feature.json and refresh the thin root
59
- * index entry (status + updatedAt) + aggregate metadata. Returns true on
60
- * success, false fail-open.
61
- */
62
46
  export function persistFeature(featureName, feature, projectPath) {
63
47
  try {
64
48
  atomicWriteJson(featureJsonPath(featureName, projectPath), feature);
@@ -75,19 +59,8 @@ export function persistFeature(featureName, feature, projectPath) {
75
59
  root.metadata.totalFeatures = Object.keys(root.features).length;
76
60
  atomicWriteJson(statePath, root);
77
61
 
78
- // R1's loadState() memoizes per projectPath for the lifetime of the
79
- // process. That was always safe when every hook was its own short-lived
80
- // process (README history), but core/chain.js now runs multiple hooks
81
- // — e.g. state-sync then gate-guard — IN ONE process. Without this,
82
- // a loadState() call earlier in that same process (state-sync's
83
- // handleWriteEdit reads via loadState before this write) would leave a
84
- // stale snapshot cached, and gate-guard's loadState() right after this
85
- // write would silently read the PRE-write state instead of what was
86
- // just persisted — inverting the "gate-guard runs after state-sync so it
87
- // sees the gate state-sync just recorded" ordering guarantee the
88
- // registry comment documents. Invalidating here (the one place
89
- // feature.json/state.json are actually written) covers every current
90
- // and future caller, not just this one chain.
62
+ // chain.js runs several hooks in one process: the next link must not read
63
+ // the memoized pre-write snapshot.
91
64
  clearStateCache();
92
65
  return true;
93
66
  } catch {
@@ -95,16 +68,7 @@ export function persistFeature(featureName, feature, projectPath) {
95
68
  }
96
69
  }
97
70
 
98
- /**
99
- * Canonical gate-approval writer (hook-side mirror of CLI setApprovalGate).
100
- * Stamps approvalGates[gate] = { approved, timestamp, approvedBy } — the single
101
- * canonical shape — onto the feature and persists it. Returns true on success.
102
- *
103
- * @param {string} featureName
104
- * @param {string} gate - 'proposal'|'uiux'|'plan'|'review'
105
- * @param {{ approvedBy?: string, timestamp?: string }} [meta]
106
- * @param {string} [projectPath]
107
- */
71
+ /** @param {{ approvedBy?: string, timestamp?: string, selfAssessed?: boolean }} [meta] */
108
72
  export function setGateApproved(featureName, gate, meta = {}, projectPath) {
109
73
  try {
110
74
  const feature = readFeatureFile(featureName, projectPath) || createDefaultFeature(featureName);
@@ -123,16 +87,8 @@ export function setGateApproved(featureName, gate, meta = {}, projectPath) {
123
87
  }
124
88
  }
125
89
 
126
- /**
127
- * Default feature shape (canonical object-form gates, incl. optional uiux).
128
- * Stamps identity — name (the slug), workType, createdAt — so the implicit
129
- * birth path (state-sync registering a feature on the first Write) never
130
- * produces an anonymous {status,updatedAt} shell. `description` stays absent
131
- * (a hook can't invent it); `list`/`doctor` flag its absence. Mirrors the CLI
132
- * createFeature's stamping.
133
- *
134
- * @param {string} [featureName] - the feature slug, stamped as `name`
135
- */
90
+ // Stamps identity so a feature born implicitly by a hook is never an anonymous
91
+ // shell; `description` stays absent because a hook cannot invent it.
136
92
  export function createDefaultFeature(featureName) {
137
93
  const now = new Date().toISOString();
138
94
  return {
@@ -142,9 +98,8 @@ export function createDefaultFeature(featureName) {
142
98
  createdAt: now,
143
99
  updatedAt: now,
144
100
  approvalGates: {
145
- proposal: { approved: false, timestamp: null, approvedBy: null },
146
- uiux: { approved: false, timestamp: null, approvedBy: null },
147
101
  plan: { approved: false, timestamp: null, approvedBy: null },
102
+ uiux: { approved: false, timestamp: null, approvedBy: null },
148
103
  review: { approved: false, timestamp: null, approvedBy: null },
149
104
  },
150
105
  outputs: {},
@@ -1,14 +1,4 @@
1
- /**
2
- * Shared stdin reader for Claude Code hooks.
3
- *
4
- * Reads JSON payload from stdin (provided by Claude Code to hooks).
5
- * Returns parsed object or null on failure.
6
- */
7
-
8
- /**
9
- * Read and parse JSON from stdin
10
- * @returns {Promise<Object|null>} Parsed JSON or null
11
- */
1
+ /** @returns {Promise<Object|null>} the hook payload, or null when stdin is not JSON */
12
2
  export function readStdin() {
13
3
  return new Promise((resolve) => {
14
4
  let input = '';
@@ -1,20 +1,5 @@
1
- /**
2
- * Telemetry Logger — append-only harness event stream
3
- *
4
- * Writes one JSON line per event to .morph/logs/events.jsonl. This is the sink
5
- * for the `telemetry-log` hook, which fires on every tool call (PostToolUse,
6
- * all tools) and on every user prompt (UserPromptSubmit) — the only vantage
7
- * points an NLH exposes. The whole execution path (skills, sub-agent dispatch,
8
- * knowledge-base reads, prompts) is reconstructable by reading this file.
9
- *
10
- * Design constraints (same discipline as activity-logger, plus one):
11
- * - Synchronous only (hooks run in process, no async overhead)
12
- * - Fail-silent (never throws — hooks must not be blocked by the logger)
13
- * - APPEND-ONLY: one `appendFileSync` line per event, O(1) per call. The
14
- * read-modify-write of a whole JSON doc (activity-logger) is O(n²) across a
15
- * session and blows the ≤5ms budget once tool calls number in the hundreds.
16
- * - Windows-safe paths via path.join
17
- */
1
+ // Append-only on purpose: rewriting a whole JSON doc per event is O(n²) across
2
+ // a session, and this runs on every tool call. Fail-silent: never blocks a hook.
18
3
 
19
4
  import {
20
5
  appendFileSync, readFileSync, mkdirSync, existsSync, statSync, renameSync,
@@ -26,13 +11,7 @@ import { redactSecrets } from './redact-secrets.js';
26
11
  const LOGS_DIR = '.morph/logs';
27
12
  export const EVENTS_FILE = join(LOGS_DIR, 'events.jsonl');
28
13
 
29
- // SessionStart (worktree-context.js) rotates events.jsonl once it crosses
30
- // this size, alongside the pre-existing activity.jsonl rotation — same
31
- // call site, same "between sessions" checkpoint. events.jsonl has no natural
32
- // per-turn cap (prompts/commands are truncated at the write site, but the
33
- // LINE COUNT itself grows unbounded across a long-lived project), so without
34
- // this it grows forever the way activity.jsonl used to before R1.2.
35
- export const ROTATE_THRESHOLD_BYTES = 5 * 1024 * 1024; // 5 MB
14
+ export const ROTATE_THRESHOLD_BYTES = 5 * 1024 * 1024;
36
15
 
37
16
  // Bumped when a field changes meaning. Readers key legacy handling off its
38
17
  // absence (v1 events carry no schemaVersion and no eventId).
@@ -49,15 +28,7 @@ function getEventsPath(projectPath) {
49
28
  return join(projectPath || process.cwd(), EVENTS_FILE);
50
29
  }
51
30
 
52
- /**
53
- * Append a single telemetry event as one JSON line.
54
- * Stamps `ts` (unless given), `schemaVersion` and a unique `eventId` — the
55
- * dedupe key when the same line is read back from a rotated archive or a
56
- * finish backup — and redacts secrets in the free-text fields.
57
- *
58
- * @param {Object} event - Event payload (tool, skill/persona/target/prompt, feature, phase…)
59
- * @param {string} [projectPath] - Project root (defaults to cwd)
60
- */
31
+ // `eventId` dedupes the same line read back from a rotated archive or a finish backup.
61
32
  export function appendTelemetryEvent(event, projectPath) {
62
33
  try {
63
34
  const eventsPath = getEventsPath(projectPath);
@@ -75,17 +46,9 @@ export function appendTelemetryEvent(event, projectPath) {
75
46
  }
76
47
  appendFileSync(eventsPath, JSON.stringify(stamped) + '\n', 'utf-8');
77
48
  } catch {
78
- // Fail-silent — never block hooks
79
49
  }
80
50
  }
81
51
 
82
- /**
83
- * Read the full event stream back into an array. A corrupt/truncated line
84
- * (e.g. a killed process mid-write) is skipped, not fatal.
85
- *
86
- * @param {string} [projectPath]
87
- * @returns {Object[]} events in write order (may be empty)
88
- */
89
52
  export function readTelemetryEvents(projectPath) {
90
53
  try {
91
54
  const eventsPath = getEventsPath(projectPath);
@@ -98,7 +61,7 @@ export function readTelemetryEvents(projectPath) {
98
61
  try {
99
62
  events.push(JSON.parse(trimmed));
100
63
  } catch {
101
- // skip a single corrupt line — don't lose the whole stream
64
+ // a process killed mid-write leaves a truncated line
102
65
  }
103
66
  }
104
67
  return events;
@@ -107,19 +70,7 @@ export function readTelemetryEvents(projectPath) {
107
70
  }
108
71
  }
109
72
 
110
- /**
111
- * Archive the current events.jsonl to `.morph/logs/sessions/`, mirroring
112
- * activity-logger.js's `archiveSession()` — same directory, same rename-not-
113
- * rewrite mechanics (O(1) even at multi-MB sizes). Named with an `events-`
114
- * prefix (activity-logger's archives carry no prefix) so the two streams
115
- * never collide inside the shared `sessions/` directory and stay
116
- * distinguishable at a glance.
117
- *
118
- * Fail-silent — called only from `rotateEventsLogIfLarge` below, which has
119
- * already confirmed the file exists.
120
- *
121
- * @param {string} [projectPath]
122
- */
73
+ // `events-` prefix: activity-logger archives share `sessions/` without one.
123
74
  function archiveEvents(projectPath) {
124
75
  try {
125
76
  const eventsPath = getEventsPath(projectPath);
@@ -132,21 +83,10 @@ function archiveEvents(projectPath) {
132
83
  const archivePath = join(sessionsDir, `events-${stamp}.jsonl`);
133
84
  renameSync(eventsPath, archivePath);
134
85
  } catch {
135
- // Fail-silent
136
86
  }
137
87
  }
138
88
 
139
- /**
140
- * Rotate events.jsonl when it crosses `thresholdBytes`. Called from
141
- * worktree-context.js on SessionStart, right next to the existing
142
- * `rotateActivityLogIfLarge()` call — the only reliable "between sessions"
143
- * checkpoint the harness gets. `thresholdBytes` is injectable so a test can
144
- * force rotation without writing multiple megabytes.
145
- *
146
- * @param {string} [projectPath] - Project root (defaults to cwd)
147
- * @param {number} [thresholdBytes] - Rotate once the log is at least this large
148
- * @returns {boolean} true if a rotation was performed
149
- */
89
+ /** @returns {boolean} true if a rotation was performed */
150
90
  export function rotateEventsLogIfLarge(projectPath, thresholdBytes = ROTATE_THRESHOLD_BYTES) {
151
91
  try {
152
92
  const eventsPath = getEventsPath(projectPath);
@@ -1,28 +1,15 @@
1
- /**
2
- * Real token usage read from a Claude Code transcript (JSONL), shared by the
3
- * Stop hook (the main session's transcript) and SubagentStop (each
4
- * sub-agent's own transcript, which the main one does not include).
5
- */
1
+ // Shared by Stop and SubagentStop: the main transcript does not include the
2
+ // sub-agents' usage.
6
3
 
7
4
  import { readFileSync, existsSync, statSync } from 'fs';
8
5
 
9
- // A 45 MB / ~16k-line transcript parses in ~350 ms; above this, skip rather
10
- // than risk an unbounded read inside a hook.
6
+ // Skip rather than risk an unbounded read inside a hook.
11
7
  const MAX_TRANSCRIPT_BYTES = 50 * 1024 * 1024;
12
8
 
13
9
  export const USAGE_KEYS = ['inputTokens', 'outputTokens', 'cacheReadTokens', 'cacheCreationTokens'];
14
10
 
15
- /**
16
- * Sum `message.usage` over the assistant turns of a transcript.
17
- *
18
- * One turn is written as several lines (one per content block), each repeating
19
- * the same usage under the same `message.id`: summing lines double-counts, so
20
- * the sum is deduplicated by message id.
21
- *
22
- * @param {string} [transcriptPath]
23
- * @returns {{inputTokens:number,outputTokens:number,cacheReadTokens:number,cacheCreationTokens:number}|null}
24
- * null when there is nothing to report (no/oversized/unreadable file, no usage)
25
- */
11
+ // One turn spans several lines repeating the same usage under the same
12
+ // `message.id`: summing lines double-counts, so the sum dedups by id.
26
13
  export function readTranscriptUsage(transcriptPath) {
27
14
  if (!transcriptPath || typeof transcriptPath !== 'string') return null;
28
15
  try {
@@ -61,17 +48,8 @@ export function readTranscriptUsage(transcriptPath) {
61
48
  }
62
49
  }
63
50
 
64
- /**
65
- * The usage added since the previous sample of the same transcript.
66
- *
67
- * A counter going DOWN means the transcript restarted (a new file under the
68
- * same key), so the whole current total is new usage — subtracting would
69
- * produce negative spend.
70
- *
71
- * @param {object|null|undefined} previous - last recorded totals for this key
72
- * @param {object} current - totals just read
73
- * @returns {{delta: object, changed: boolean}}
74
- */
51
+ // A counter going DOWN means the transcript restarted: the whole current
52
+ // total is new usage, and subtracting would produce negative spend.
75
53
  export function usageDelta(previous, current) {
76
54
  const reset = !previous || USAGE_KEYS.some((k) => (current[k] ?? 0) < (previous[k] ?? 0));
77
55
  const delta = {};
@@ -1,29 +1,13 @@
1
- /**
2
- * worktree-root.js — onde as worktrees do morph-spec moram, num lugar só.
3
- *
4
- * Padrão: `<raiz>/worktrees/<nome>` (mais o legado `.worktrees/`). Com `worktree.root` na
5
- * config (ou `MORPH_WORKTREE_ROOT`), as novas nascem em `<root>/<chave-do-repo>/<nome>`, FORA da
6
- * árvore aberta no editor. A chave é `basename-<hash da raiz>`: só o basename colidiria entre dois
7
- * repositórios de mesmo nome que dividem o mesmo root.
8
- *
9
- * Um root DENTRO da raiz é recusado: toda lista que se orienta pelo nome do container
10
- * (.gitignore, graphifyignore, descoberta de testes, tar do --linux, globs do editor) deixaria de
11
- * enxergá-lo, em silêncio. Recusado, vale o padrão e o motivo volta em `warning`.
12
- *
13
- * O predicado "está no container" é a UNIÃO do layout configurado com o padrão e o legado: uma
14
- * worktree que já existe continua reconhecida depois que a chave muda. Mora em `hooks/shared`
15
- * porque hook não importa `src/`; o `src/` importa daqui.
16
- *
17
- * @module worktree-root
18
- */
1
+ // "Está no container" é a UNIÃO do layout configurado com o padrão e o legado:
2
+ // uma worktree antiga segue reconhecida. Root dentro da raiz é recusado, porque as
3
+ // listas orientadas pelo nome `worktrees/` deixariam de enxergá-lo.
19
4
 
20
5
  import { createHash } from 'crypto';
21
6
  import { readFileSync } from 'fs';
22
7
  import { homedir } from 'os';
23
8
  import { basename, isAbsolute, join, relative, resolve } from 'path';
24
9
 
25
- // No leading dot (C1): Jest escapes it inside an absolute `rootDir` glob, so `.worktrees/` made a whole
26
- // frontend suite report 0 tests without an error. `.worktrees/` is the pre-C1 name, still read everywhere.
10
+ // No leading dot: Jest escapes it inside an absolute `rootDir` glob and reports 0 tests.
27
11
  export const WORKTREES_DIR = 'worktrees';
28
12
  export const LEGACY_WORKTREES_DIR = '.worktrees';
29
13
  export const WORKTREE_DIR_NAMES = [WORKTREES_DIR, LEGACY_WORKTREES_DIR];
@@ -31,7 +15,7 @@ export const WORKTREE_DIR_NAMES = [WORKTREES_DIR, LEGACY_WORKTREES_DIR];
31
15
  const fwd = (p) => String(p).replace(/\\/g, '/');
32
16
  const foldCase = (p) => (process.platform === 'win32' ? p.toLowerCase() : p);
33
17
 
34
- /** `basename-<8 hex do hash da raiz>` — estável entre `R:` e `r:` no Windows. */
18
+ // Só o basename colidiria entre repositórios; o hash é estável entre `R:` e `r:`.
35
19
  export function repoKey(primaryRoot) {
36
20
  const root = fwd(resolve(primaryRoot));
37
21
  const hash = createHash('sha1').update(foldCase(root)).digest('hex').slice(0, 8);
@@ -54,11 +38,7 @@ function isInside(root, path) {
54
38
  return rel === '' || (!rel.startsWith('..') && !isAbsolute(rel));
55
39
  }
56
40
 
57
- /**
58
- * @param {string} primaryRoot
59
- * @param {{ env?: NodeJS.ProcessEnv }} [opts]
60
- * @returns {{ dir: string|null, base?: string, warning?: string }} `dir` = `<root>/<repoKey>`
61
- */
41
+ /** @returns {{ dir: string|null, base?: string, warning?: string }} `dir` = `<root>/<repoKey>` */
62
42
  export function externalContainer(primaryRoot, { env = process.env } = {}) {
63
43
  const configured = configuredRoot(primaryRoot, env);
64
44
  if (!configured) return { dir: null };
@@ -70,19 +50,17 @@ export function externalContainer(primaryRoot, { env = process.env } = {}) {
70
50
  return { dir: fwd(join(base, repoKey(primaryRoot))), base: fwd(base) };
71
51
  }
72
52
 
73
- /** Where a NEW worktree lands. */
74
53
  export function newWorktreesDir(primaryRoot, opts) {
75
54
  return externalContainer(primaryRoot, opts).dir ?? `${fwd(resolve(primaryRoot))}/${WORKTREES_DIR}`;
76
55
  }
77
56
 
78
- /** Every directory that counts as "the container", external first. Forward slashes. */
79
57
  export function containerDirs(primaryRoot, opts) {
80
58
  const root = fwd(resolve(primaryRoot));
81
59
  const external = externalContainer(primaryRoot, opts).dir;
82
60
  return [...(external ? [external] : []), ...WORKTREE_DIR_NAMES.map((name) => `${root}/${name}`)];
83
61
  }
84
62
 
85
- /** Is `path` under any of `dirs` (a `containerDirs` result)? Ask `containerDirs` once per audit, not once per path. */
63
+ // Ask `containerDirs` once per audit, not once per path.
86
64
  export function isUnder(dirs, path) {
87
65
  const target = foldCase(fwd(resolve(path)));
88
66
  return dirs.some((dir) => target.startsWith(`${foldCase(dir)}/`));
@@ -3,7 +3,7 @@
3
3
  "description": "Centralized MCP registry with phase relevance and install configuration for morph-spec workflows",
4
4
  "mcps": {
5
5
  "context7": {
6
- "phases": ["proposal", "plan", "implement"],
6
+ "phases": ["plan", "implement"],
7
7
  "tools": ["resolve-library-id", "query-docs"],
8
8
  "serverNames": ["context7", "plugin_context7_context7"],
9
9
  "detection": "enabledPlugins includes context7 or mcpServers includes context7",
@@ -216,7 +216,7 @@
216
216
  }
217
217
  },
218
218
  "graphify": {
219
- "phases": ["proposal", "plan", "implement", "review"],
219
+ "phases": ["plan", "implement", "review"],
220
220
  "tools": ["query_graph", "get_node", "get_neighbors", "get_community", "god_nodes", "graph_stats", "shortest_path", "list_prs", "get_pr_impact", "triage_prs"],
221
221
  "detection": "graphify-out/graph.json exists in the project root (written by morph-spec graph build, or by the graphify post-commit hook)",
222
222
  "fallback": "Comportamento atual: Grep/Glob/Read. O grafo é um subconjunto estrito do grep — no eval não encontrou um único arquivo que o grep perderia — então cair para grep não perde recall, só devolve mais ruído",
@@ -281,9 +281,8 @@
281
281
  },
282
282
  "_phaseMatrixNote": "Keys must be the v5 phases from framework/phases.json. The v4 keys 'design' and 'tasks' both collapsed into 'plan'; 'review' was absent entirely, so a project in review resolved to undefined. Stack-scoped MCPs (asaas, neon) stay out of this matrix on purpose — only universal ones are listed.",
283
283
  "phaseMatrix": {
284
- "proposal": ["context7", "graphify"],
285
- "uiux": ["playwright", "context7", "stitch", "morph-assets"],
286
284
  "plan": ["context7", "graphify"],
285
+ "uiux": ["playwright", "context7", "stitch", "morph-assets"],
287
286
  "implement": ["context7", "playwright", "vercel", "morph-assets", "graphify"],
288
287
  "review": ["playwright", "context7", "graphify"]
289
288
  }
@@ -1,22 +1,22 @@
1
1
  {
2
2
  "version": "5.0.0",
3
3
  "phases": {
4
- "proposal": {
5
- "id": "proposal",
4
+ "plan": {
5
+ "id": "plan",
6
6
  "index": 0,
7
- "folder": "0-proposal",
8
- "displayName": "Proposal",
7
+ "folder": "2-plan",
8
+ "displayName": "Plan",
9
9
  "goals": [
10
- "Understand the business problem and user flows",
11
- "Detect existing stack (brownfield) or assume default stack (greenfield)",
12
- "Produce proposal.md and reach Gate 1"
10
+ "Understand the business problem and scan the stack (brownfield) or assume the default (greenfield)",
11
+ "Write plan.md — scenarios with proof, decisions, reuse and slices",
12
+ "Run plan-check to produce checks.json and reach the plan gate"
13
13
  ],
14
- "requiredOutputs": ["proposal"],
15
- "optionalOutputs": ["stackScan"],
14
+ "requiredOutputs": ["plan", "checks"],
15
+ "optionalOutputs": [],
16
16
  "pausePoints": [
17
- { "id": "proposal", "label": "Gate 1 — Approve proposal" }
17
+ { "id": "plan", "label": "Gate do plano — Approve plan.md + checks.json" }
18
18
  ],
19
- "skill": "morph-brainstorming"
19
+ "skill": "morph-plan"
20
20
  },
21
21
  "uiux": {
22
22
  "id": "uiux",
@@ -35,50 +35,34 @@
35
35
  ],
36
36
  "skill": "morph-uiux"
37
37
  },
38
- "plan": {
39
- "id": "plan",
40
- "index": 2,
41
- "folder": "2-plan",
42
- "displayName": "Plan",
43
- "goals": [
44
- "Write spec.md (technical spec)",
45
- "Write tasks.json (ordered task breakdown)"
46
- ],
47
- "requiredOutputs": ["spec", "tasks"],
48
- "optionalOutputs": ["decisions"],
49
- "pausePoints": [
50
- { "id": "plan", "label": "Gate 2 — Approve spec + tasks" }
51
- ],
52
- "skill": "morph-plan"
53
- },
54
38
  "implement": {
55
39
  "id": "implement",
56
- "index": 3,
40
+ "index": 2,
57
41
  "folder": "3-implement",
58
42
  "displayName": "Implementation",
59
43
  "goals": [
60
- "Execute tasks in order with auto-advance between tasks",
61
- "Advance a task only on verify green and its doneCriteria met",
62
- "Maintain recap.md and execution trace"
44
+ "Execute the slices of plan.md, in parallel waves when plan-check allows",
45
+ "Close a slice only on verify green and its scenarios proven",
46
+ "One report per slice (3-implement/reports/F{n}.md, with **Arquivos:** and **Standards:**) — the implementation record"
63
47
  ],
64
- "requiredOutputs": ["recap"],
48
+ "requiredOutputs": [],
65
49
  "optionalOutputs": ["evidencias"],
66
50
  "pausePoints": [],
67
- "skill": "morph-implement"
51
+ "skill": "morph-apply"
68
52
  },
69
53
  "review": {
70
54
  "id": "review",
71
- "index": 4,
55
+ "index": 3,
72
56
  "folder": "4-review",
73
57
  "displayName": "Review",
74
58
  "goals": [
75
- "Independent evaluator verdict (SHIP/FIX) with evidence-typed blockers",
76
- "Produce review-report.md and present Gate 3"
59
+ "Verifier proves every scenario; reviewer (and security, when required) judge the diff at a fixed SHA",
60
+ "verifier.md + reviewer.md (+ security.md) with SHIP/FIX and evidence-typed blockers, then Gate 3"
77
61
  ],
78
- "requiredOutputs": ["reviewReport"],
79
- "optionalOutputs": [],
62
+ "requiredOutputs": ["verifierReport", "reviewerReport"],
63
+ "optionalOutputs": ["securityReport"],
80
64
  "pausePoints": [
81
- { "id": "review", "label": "Gate 3 — Approve review-report" }
65
+ { "id": "review", "label": "Gate 3 — Approve the review reports" }
82
66
  ],
83
67
  "skill": "morph-review"
84
68
  }
@@ -9,7 +9,7 @@ stacks:
9
9
  # C# and .NET VSA Standards
10
10
 
11
11
  - **architecture-vertical-slice-vertical-slice** (`architecture/vertical-slice/vertical-slice.md`) — Uma slice por operação em `Features/{Entity}Feature/{Verb}{Entity}/`: Request/Response `sealed record`, Handler, Validator e Endpoint `IApiEndpoint` `internal sealed`. Decorators Scrutor: Logging → Validation → Handler. PROIBIDO: MediatR/`IRequest`, AggregateRoot, DomainEvent, CQRS formal, camada Application Service, DTO compartilhado entre features, `IRepository<T>`/`IUnitOfWork`.
12
- - **backend-dotnet-vsa-handler-patterns** (`backend/dotnet/vsa-handler-patterns.md`) — Handler `sealed class` com primary constructor implementando `IHandler<TRequest, TResponse>` (não MediatR): injeta `ApplicationDbContext` direto, usa `Guid.CreateVersion7()` (nunca `Guid.NewGuid()`), passa `CancellationToken` em tudo e devolve `Result<T>`. Erros em `{Feature}Errors.cs`. SQL cru ou store dedicado só com justificativa em `decisions.md`.
12
+ - **backend-dotnet-vsa-handler-patterns** (`backend/dotnet/vsa-handler-patterns.md`) — Handler `sealed class` com primary constructor implementando `IHandler<TRequest, TResponse>` (não MediatR): injeta `ApplicationDbContext` direto, usa `Guid.CreateVersion7()` (nunca `Guid.NewGuid()`), passa `CancellationToken` em tudo e devolve `Result<T>`. Erros em `{Feature}Errors.cs`. SQL cru ou store dedicado só com justificativa em `plan.md` (`## Decisões`).
13
13
  - **backend-dotnet-result-pattern** (`backend/dotnet/result-pattern.md`) — Falha esperada é `Result`/`Result<T>`, nunca exceção. Endpoint: `result.Match(value => Results.Ok(value), error => error.ToHttpResult())`; nunca leia `.Value` fora do `Match`. Status pelo `ErrorType` (Validation 400, NotFound 404, Conflict 409, Unauthorized 401, Forbidden 403, Unexpected 500), nunca BadRequest para tudo. PROIBIDO: try/catch no handler, retornar null, erro string sem código.
14
14
  - **backend-dotnet-fluent-validation-vsa** (`backend/dotnet/fluent-validation-vsa.md`) — Um `sealed AbstractValidator<TRequest>` (FluentValidation 12) por request, na pasta da slice; o `ValidationDecorator` roda antes do handler e devolve `Result.Failure(ValidationError)`. `AddValidatorsFromAssembly()` ANTES de `AddHandlersFromAssembly()`. Sempre `.WithMessage()`; tempo via `TimeProvider` lido DENTRO da regra. Nunca lance `ValidationException`.
15
15
  - **backend-dotnet-scrutor** (`backend/dotnet/scrutor.md`) — `AddHandlersFromAssembly` registra cada `IHandler<,>` como Scoped (filtro `!t.ContainsGenericParameters`) e depois `Decorate` Validation e então Logging (o último registrado é o mais externo). Endpoints `IApiEndpoint` via `TryAddEnumerable` Transient + `MapApiEndpoints`. Nunca registre handler um a um.
@@ -11,5 +11,6 @@ stacks:
11
11
 
12
12
  - **frontend-design-system-naming** (`frontend/design-system/naming.md`) — BEM para componente reutilizável (`.card`, `.card__header`, `.card--featured`); prefixo de página para elemento específico (`.home-hero`). Custom properties em `:root` com namespace `--app-`. Estado por sufixo fixo: `--active`, `--disabled`, `--loading`, `--error`.
13
13
  - **frontend-design-system-animations** (`frontend/design-system/animations.md`) — Classes `.animate-*`, `.duration-fast/normal/slow`, `.stagger-1..10`. Lista escalonada exige `animation-delay` E `animation-fill-mode: backwards`. Sempre o bloco `prefers-reduced-motion: reduce`. Além do CSS: Motion (`motion/react`) para enter/exit/layout; GSAP só para ScrollTrigger, SVG morph e timelines.
14
+ - **frontend-design-system-art-direction** (`frontend/design-system/art-direction.md`) — Tela nova ou alterada segue a direção escrita em `1-design/direcao.md` e o protótipo de `1-design/prototipos/`: celular composto (folha inferior, alvos de 44px), movimento só em `transform`/`opacity` com versão estática em `prefers-reduced-motion`, nenhum número inventado em cena ilustrativa.
14
15
 
15
16
  > Resumo injetado quando você lê ou edita um arquivo casado por `paths:`. Texto completo: `morph-spec standards --find "<id>"` e leia só a seção necessária de `.morph/framework/standards/<path>`.
@@ -10,6 +10,6 @@ stacks:
10
10
 
11
11
  # Hangfire Background Jobs Standards
12
12
 
13
- - **backend-integrations-hangfire-hangfire-jobs** (`backend/integrations/hangfire/hangfire-jobs.md`) — Hangfire 1.8.25 só com razão real em `decisions.md`; o que cabe no request fica no handler. Storage `Hangfire.PostgreSql` 1.21.1 com `UseNpgsqlConnection` no endpoint DIRETO do Neon; referencie `Newtonsoft.Json` 13.0.4. Job é classe fina e idempotente que chama o handler; `[AutomaticRetry]`, sem try/catch nem retry manual. Dashboard exige Admin autenticado.
13
+ - **backend-integrations-hangfire-hangfire-jobs** (`backend/integrations/hangfire/hangfire-jobs.md`) — Hangfire 1.8.25 só com razão real em `plan.md` (`## Decisões`); o que cabe no request fica no handler. Storage `Hangfire.PostgreSql` 1.21.1 com `UseNpgsqlConnection` no endpoint DIRETO do Neon; referencie `Newtonsoft.Json` 13.0.4. Job é classe fina e idempotente que chama o handler; `[AutomaticRetry]`, sem try/catch nem retry manual. Dashboard exige Admin autenticado.
14
14
 
15
15
  > Resumo injetado quando você lê ou edita um arquivo casado por `paths:`. Texto completo: `morph-spec standards --find "<id>"` e leia só a seção necessária de `.morph/framework/standards/<path>`.
@@ -11,7 +11,7 @@ stacks:
11
11
  # Neon PostgreSQL Standards
12
12
 
13
13
  - **infrastructure-neon-setup** (`infrastructure/neon/neon-setup.md`) — Duas connection strings: `DefaultConnection` (pooled `-pooler`) para a app e `MigrationConnection` (direta) para migrations e advisory locks; nunca commitadas (user-secrets / env do Coolify). Formato keyword (`Host=...;SSL Mode=Require`), não URI. `EnableRetryOnFailure(5, 10s)` por causa do scale-to-zero. Branch sempre com `--expires-at`.
14
- - **infrastructure-neon-pgvector** (`infrastructure/neon/neon-pgvector.md`) — `Npgsql.EntityFrameworkCore.PostgreSQL` 10.0.3 + `Pgvector.EntityFrameworkCore` 0.3.0; coluna `Vector` (`vector(1536)`) e `UseVector()` no `UseNpgsql`. SEMPRE índice HNSW com operator class casando a função LINQ (senão seq scan); distância em ordem ASC. PROIBIDO: DocumentRepository, SQL cru do C# sem `decisions.md`, default `gen_random_uuid()`.
14
+ - **infrastructure-neon-pgvector** (`infrastructure/neon/neon-pgvector.md`) — `Npgsql.EntityFrameworkCore.PostgreSQL` 10.0.3 + `Pgvector.EntityFrameworkCore` 0.3.0; coluna `Vector` (`vector(1536)`) e `UseVector()` no `UseNpgsql`. SEMPRE índice HNSW com operator class casando a função LINQ (senão seq scan); distância em ordem ASC. PROIBIDO: DocumentRepository, SQL cru do C# sem `plan.md` (`## Decisões`), default `gen_random_uuid()`.
15
15
  - **infrastructure-neon-pgrag** (`infrastructure/neon/neon-pgrag.md`) — A extensão `rag` é EXPERIMENTAL: protótipo e RAG só-SQL, não produção sem teste. Nunca misture modelos de embedding numa coluna (bge-small 384 × text-embedding-3-small 1536). Índice HNSW depois da carga inicial. Produção .NET com lógica própria: tool MAF tipada sobre pgvector.
16
16
  - **backend-integrations-neon-auth-neon-auth** (`backend/integrations/neon-auth/neon-auth.md`) — SDK `@neondatabase/auth`: `createNeonAuth()` no server, `createAuthClient()` no client, `auth.middleware()` com `runtime='nodejs'`. Duas constantes de prefixo (`BACKEND_API_PREFIX`/`PROXY_API_PREFIX`), nunca uma só. O front não consulta o Neon para dado de negócio. .NET: token EdDSA/Ed25519, verificado pelo JWKS com BouncyCastle + `SignatureValidator` devolvendo `JsonWebToken`.
17
17
 
@@ -9,6 +9,18 @@
9
9
  "type": "object",
10
10
  "additionalProperties": true,
11
11
  "properties": {
12
+ "stack": {
13
+ "type": "string",
14
+ "description": "Stack tags joined by `+` (e.g. `dotnet+nextjs`). Decides the build node's commands, which assets install, and that bin/ and obj/ go into .gitignore."
15
+ },
16
+ "frontendPath": {
17
+ "type": "string",
18
+ "description": "Folder of the frontend, relative to the project root: where the build node runs `tsc`. Absent: the root."
19
+ },
20
+ "backendPath": {
21
+ "type": "string",
22
+ "description": "Folder of the .NET solution, relative to the project root: where the build node runs `dotnet build`. Absent: the root, or the repository's single .sln/.slnx (else single .csproj) when the root has none."
23
+ },
12
24
  "ci": {
13
25
  "type": "boolean",
14
26
  "description": "false turns `verify {f} --ci` into the local verify (with the reason printed). Absent or true: the Gate 3 proof comes from the GitHub Actions workflow that runs `morph-spec verify` (created on first use), whenever origin is GitHub and gh is authenticated."
@@ -60,20 +72,13 @@
60
72
  "e2e": {
61
73
  "type": "boolean",
62
74
  "default": false,
63
- "description": "Requires the application stack to be up. Runs at feature scope only, never in the per-task loop."
75
+ "description": "Requires the application stack to be up."
64
76
  },
65
77
  "linuxImage": {
66
78
  "type": "string",
67
79
  "minLength": 1,
68
80
  "description": "Overrides the container image used by `verify --linux` for this node."
69
81
  },
70
- "groups": {
71
- "type": "array",
72
- "minItems": 1,
73
- "uniqueItems": true,
74
- "items": { "type": "string", "enum": ["backend", "frontend", "tests", "infra", "docs"] },
75
- "description": "Which task group(s) (tasks.json `group`) this node verifies. Absent means the runner's own default applies (RUNNER_DEFAULT_GROUPS in src/lib/tasks/test-nodes.js) — `none`/`evals` have no default and are unscoped unless declared here."
76
- },
77
82
  "evals": {
78
83
  "type": "object",
79
84
  "additionalProperties": false,
@@ -191,7 +196,7 @@
191
196
  "shutdownBuildServer": {
192
197
  "type": "boolean",
193
198
  "default": true,
194
- "description": "Run `dotnet build-server shutdown` at the end of a feature-scope `verify` and of `e2e down`, only when no slot is held and no dotnet build/test is alive. Never at the end of a task-scope verify: every task would pay a cold compiler."
199
+ "description": "Run `dotnet build-server shutdown` at the end of a `verify` and of `e2e down`, only when no slot is held and no dotnet build/test is alive."
195
200
  },
196
201
  "disableNodeReuse": {
197
202
  "type": "boolean",