@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,307 +1,145 @@
1
1
  ---
2
2
  name: morph-plan
3
- description: Guia a produção dos artefatos de planejamento de uma feature (use cases, spec.md, tasks.json) e apresenta o Gate 2 trust-aware.
3
+ description: Leva uma feature do pedido ao plano aprovado — roteia o tipo de trabalho, varre o ambiente, conduz a entrevista pela árvore de decisões, escreve 2-plan/plan.md, extrai checks.json com plan-check e apresenta o gate do plano.
4
4
  version: core
5
- when_to_use: Use quando a fase plan de uma feature começar, após o Gate 1 (proposal aprovado)
5
+ when_to_use: Use quando uma feature, bug ou chore começar ("/morph-plan {feature}", "vamos planejar X"), ou ao retomar uma feature cujo gate plan ainda não foi aprovado
6
6
  user-invocable: true
7
- cliVersion: "8.47.0"
7
+ cliVersion: "9.1.0"
8
8
  ---
9
9
 
10
10
  # morph-plan
11
11
 
12
- ## Objetivo
13
-
14
- Produzir os **use cases**, o `spec.md` e o `tasks.json` com qualidade para abrir o Gate 2. Os use
15
- cases definem o **comportamento**; o spec diz **como**; as tasks dizem **em que ordem** e **quando
16
- cada uma está pronta**. Comportamento antes de solução técnica — sempre nessa ordem.
17
-
18
- ## Quando invocar
19
-
20
- Fase plan, depois do Gate 1. Normalmente chamada pela `morph-proposal`.
21
-
22
- ## O que fazer
23
-
24
- 1. **Garanta que `proposal.md` e `stack-scan.md` estão no seu contexto antes de planejar** (Read se
25
- a sessão é fresca). Em brownfield, o stack-scan manda: não invente padrão que conflita com o
26
- detectado.
27
-
28
- **E `.morph/features/{feature}/1-design/*.md`, quando o diretório existe** — leia todos os `.md`:
29
- descrevem comportamento de interface que o proposal não carrega. **Diretório ausente NÃO é erro**
30
- — a fase uiux é opcional (MORPH.md §2.1) e o plano segue igual.
31
-
32
- 1b. **Scout — mapa do território (default em feature grande ou brownfield).**
33
- Despache `subagent_type: "morph-scout"`: os arquivos que a feature vai tocar, o blast radius dos símbolos centrais e o que
34
- quebra junto. O scout começa por `morph-spec graph affected|explain` e **cai para grep sozinho
35
- quando não há grafo**. Não registrado: `general-purpose` com o campo `persona` do `scout`.
36
- Grave a resposta em `2-plan/scout-map.md` e audite:
37
- ```
38
- morph-spec scout-check .morph/features/{feature}/2-plan/scout-map.md --json
39
- ```
40
- Exit ≠ 0 → o mapa é descartado; re-despache **uma** vez com as `failures` coladas. Segunda
41
- reprovação: faça você o grep dos fatos que o plano precisa. Mapa aprovado prova que as citações
42
- existem, não que a conclusão está certa — confira com grep próprio o Inferido que muda o plano.
43
- Pular o scout em feature pequena no domínio carregado: uma linha em `decisions.md`.
44
-
45
- 1c. **Reuso — o que desta feature JÁ EXISTE.** Para cada conceito central que a feature introduz
46
- (entidade, DTO, componente, hook, serviço, helper, dublê de teste): `morph-spec graph explain
47
- <nome> --json` (existe? onde?) e `morph-spec graph affected <conceito> --uses-only --json` (quem
48
- usa de verdade). Antes, `morph-spec graph status --json`: stale numa worktree, ou sem refresh em
49
- andamento, `morph-spec graph refresh`. O inventário `.morph/context/README.md` (`morph-spec context
50
- refresh`) dá componentes e endpoints por path. **Sem grafo** (`no-graph`, `not-found` num grafo
51
- stale), caia para `grep -rn "<nome>"` e siga — a ausência de grafo nunca bloqueia.
52
-
53
- O veredito vai direto para a task que realiza o conceito (passo 5b): `REUSAR`, `ESTENDER` ou
54
- `CRIAR`. **`CRIAR` exige `why`** — uma linha com a consulta que respondeu "não existe" (`graph
55
- explain X → not-found; grep -rn X → 0`). Conceito de duas features vai para um módulo comum, nunca
56
- import cruzado entre slices. O validador `reuse` do `verify` cobra o resultado: símbolo novo
57
- homônimo de um existente reprova na mesma feature e avisa entre features; `CRIAR` declarado no
58
- plano rebaixa o achado a aviso.
59
-
60
- 1d. **O que esta feature supera no acervo.** Insumos: `Conflitos com o acervo` do `proposal.md`,
61
- `.morph/specs/usecases/` e o índice `.morph/specs/adrs/`. UC `status: superseded` não é o
62
- comportamento vigente — o `superseded_by` é. Cada conflito decidido vira uma linha na seção de
63
- revogação do `spec.md` (passo 3) e um ADR em `decisions.md`; ADR que vale além desta feature leva
64
- `**Alcance:** projeto` (é por ela que o `finish` o copia para o índice):
65
- ```markdown
66
- ## ADR-{nnn}: {a regra que vale no projeto}
67
-
68
- **Status:** Accepted
69
- **Alcance:** projeto
70
- ```
71
-
72
- 2. **Destile os use cases — ANTES de escrever `spec.md` e `tasks.json`.**
73
-
74
- Um arquivo por use case em `.morph/features/{feature}/2-plan/usecases/UC-{nn}-{slug}.md`:
75
-
76
- ```markdown
77
- ---
78
- id: UC-07
79
- title: Listar veterinários com suas especialidades
80
- actor: Visitante
81
- status: draft
82
- entities: [Vet, Specialty]
83
- ---
84
-
85
- ## Pré-condições
86
- - Existe ao menos um veterinário cadastrado
87
-
88
- ## Cenário principal
89
- 1. Visitante acessa a listagem de veterinários
90
- 2. Sistema retorna os veterinários ordenados por sobrenome
91
-
92
- ## Pós-condições
93
- - **P1** — A resposta contém todos os veterinários não arquivados
94
- - **P2** — Cada veterinário traz suas especialidades em lista, nunca string concatenada
95
-
96
- ## Fluxos alternativos (opcional)
97
- - **A1** — Nenhum veterinário cadastrado → sistema exibe estado vazio
98
- ```
99
-
100
- **A regra que sustenta a camada inteira: pós-condição precisa ser observável em teste.** Pergunte:
101
- *que asserção eu escreveria para verificar isto?* Sem resposta, reescreva ou descarte.
102
-
103
- **Artefato não é comportamento.** Pós-condição que cita arquivo, pasta, `grep`, "contém a
104
- string" ou "o binário" descreve o texto do repositório, não o que o sistema faz. Primeiro tente
105
- o efeito observável em runtime ("publicar tenant com `criterion_overrides` é recusado, nomeando a
106
- chave"). Se o artefato É o entregável, justifique **na linha logo abaixo**:
107
-
108
- ```markdown
109
- - **P4** — Nenhum arquivo em `tenants/**` contém a chave `criterion_overrides`
110
- > [!note] Por que artefato: a chave saiu do contrato; nenhum leitor de runtime a consulta.
111
- ```
112
-
113
- Nunca na mesma linha: a pós-condição viaja literal ao `doneCriteria`. Task sem `usecase`
114
- justifica no próprio `doneCriteria` (`… — Por que artefato: …`). Pós-condição sobre o que um
115
- **modelo** responde é observável em runtime, nunca no texto do prompt (passo 5).
116
-
117
- **Numeração:** `morph-spec usecase reserve --count {n} --feature {feature}` — nunca o maior
118
- `UC-{nn}` do disco: cada worktree vê só a sua cópia, e dois planos paralelos mintariam o mesmo id.
119
-
120
- **Seções:** obrigatórias `Pré-condições`, `Cenário principal` (curto) e `Pós-condições` (**P1**,
121
- **P2**…). Opcionais, só quando pedem: `Fluxos alternativos` (**A1**…) e `Delta de domínio`.
122
-
123
- | Tipo | Use case |
124
- |---|---|
125
- | `feature` | Obrigatório com comportamento observável; feature puramente técnica dispensa (registre em `decisions.md`). |
126
- | `bug` | Copie o `UC-{nn}-*.md` do acervo para `2-plan/usecases/` **com o mesmo nome de arquivo** e corrija ou adicione a pós-condição — não reserve número novo. |
127
- | `chore` | Nenhum. |
128
- | `hotfix` | Referencia se existir. |
129
-
130
- **Nunca edite `.morph/specs/usecases/` à mão** — a única escrita no acervo é a promoção do
131
- `finish`, que lê de `2-plan/usecases/`. O use case segue editável depois do Gate 2.
132
-
133
- 3. Produza `spec.md` em `2-plan/`:
134
- - Arquitetura: componentes, como se conectam, fluxos de dados. Edge cases **técnicos** (os de
135
- comportamento estão nos use cases) e integrações externas. Não repita o comportamento.
136
- - **UCs e ADRs que esta feature altera ou revoga** — seção obrigatória com este título; `Nenhum.`
137
- quando nada muda, senão:
138
-
139
- ```markdown
140
- ## UCs e ADRs que esta feature altera ou revoga
141
-
142
- | Id | Mudança | Substituto | Escopo em que o antigo ainda vale |
143
- |---|---|---|---|
144
- | UC-{nn} | parcial | UC-{nn} | {onde o antigo ainda vale} |
145
- | {feature}/ADR-{nnn} | total | — | — |
146
- ```
147
-
148
- `Id` é `UC-{nn}` ou `{feature}/ADR-{nnn}`. UC revogado exige `Substituto`; `parcial` exige
149
- `Escopo`. O `finish` aplica as linhas válidas e devolve as malformadas em `revocationProblems`.
150
- **Rode `morph-spec usecase check {feature}` logo depois de escrever a seção** — o spec congela no
151
- Gate 2.
152
-
153
- 4. **Seção `## Contrato de implementação` do `spec.md`** — o que quem implementa precisa saber e o
154
- código não diz. Curta; o resto já está nos standards que cada task carrega.
155
- - **Standards:** `morph-spec standards --find "<domínio>"` por domínio tocado (o digest decide);
156
- liste os ids. Inclua `architecture-code-comments` e o standard de teste do stack. Feature com
157
- agente MAF: os `standards/ai-agents/*.md` que ela exige (`--category ai-agents`) — convenção de
158
- projeto vem deles; superfície da API pode vir do context7.
159
- - **Proibições desta feature** além das de `MORPH.md` § "Stack baked-in", quando houver.
160
- - **Verificação de runtime** — como se prova que a feature funciona rodando:
161
- - O stack sobe pelo `docker compose` do projeto (`morph-spec e2e up {feature}`). Projeto que
162
- containeriza sem compose: **isso é uma task**.
163
- - Os fluxos que o avaliador vai navegar, nos verbos das pós-condições; quais viram spec
164
- Playwright (caminho crítico e bug corrigido).
165
- - Base URL do ambiente: `process.env.PLAYWRIGHT_BASE_URL ?? \`http://localhost:${process.env.PORT ?? 3000}\``,
166
- compose publicando `"${PORT:-3000}:3000"` e sem `container_name` (standard
167
- `infrastructure/docker/local-compose-isolation`). Cravado: **isso é uma task**.
168
- - App com login: `e2e.auth` em `config.json` (`mode: seed|storageState|bypass|none`,
169
- `seedCommand`, `storageStatePath`, `envFile`), credenciais num `.env.e2e` gitignored.
170
- **`mode` é obrigatório sempre que houver `seedCommand`** — sem ele o seed fica inerte. Sem setup de
171
- login, crie a task.
172
- - Não se aplica (biblioteca pura): registre a dispensa e o porquê.
173
- - **Baseline é um COMANDO, nunca um número.** O spec congela no Gate 2 e é lido por dias: número
174
- cravado (`2366 passando`) está errado na primeira task, e quem confia nele "conserta" o que não
175
- quebrou. Registre como medir (`npm test`, `dotnet test`); o `expectedCount` de `project.tests[]`
176
- é gravado por `morph-spec verify {feature} --record-baseline`, nunca digitado.
177
- - **Pré-requisito é um PREDICADO, nunca um SHA literal**: "`git merge-base --is-ancestor
178
- origin/main HEAD` sai 0", não "confirme que main contém `49dfba2`" — o SHA muda no primeiro
179
- squash.
180
-
181
- 5. Produza `tasks.json` em `.morph/features/{feature}/2-plan/` seguindo o schema
182
- `.morph/framework/schemas/tasks.schema.json` (o hook `tasks-json-guard` valida cada write):
183
-
184
- ```json
185
- {
186
- "version": "1.0",
187
- "feature": "{feature-name}",
188
- "tasks": [
189
- {
190
- "id": "T1",
191
- "title": "Título curto",
192
- "description": "O que esta task realiza e por quê",
193
- "dependencies": [],
194
- "effort": "S",
195
- "doneCriteria": "P2 — Cada veterinário traz suas especialidades em lista, nunca string concatenada",
196
- "status": "pending",
197
- "outputs": ["src/Vets/ListVets.cs", "tests/Vets/ListVetsTests.cs"],
198
- "group": "backend",
199
- "usecase": "UC-07",
200
- "agent": "dotnet-senior",
201
- "standards": ["standards/backend/dotnet/vsa-handler-patterns.md"],
202
- "reuse": [{ "concept": "VetDto", "verdict": "CRIAR", "why": "graph explain VetDto → not-found; grep -rn VetDto → 0" }]
203
- }
204
- ]
205
- }
206
- ```
207
-
208
- - `id` `T\d+`; `dependencies` com ids Tn; `effort` S (≤30min) | M (≤1h) | L (≤2h) | XL (>2h);
209
- `status` nasce `pending`; `group` backend | frontend | tests | infra | docs.
210
- - `usecase`: o **id** (`UC-07`), nunca o nome do arquivo.
211
- - `outputs`: paths planejados — o `dag` detecta colisão entre fluxos paralelos por eles.
212
- **No máximo 8 `outputs` por task** (testes incluídos): acima disso o sub-agente bate no teto de
213
- turnos; o `dag` recusa antes do Gate 2.
214
-
215
- **5a. Carimbe `agent` e `standards`** com UMA leitura de `.morph/framework/agents.json`: `agent` é
216
- o id da persona (sem `morph-`) cujo `domains` cobre o domínio da task; `standards`, o array dela
217
- mais o que a task exige. **Persona com `surfaces`** (a `ui-designer`): some a lista da superfície
218
- que o checklist de tela do `1-design/mockups.md` declara em `Superfície`, nunca de outra; sem
219
- mockup, escolha pela tela e registre em `decisions.md`. Task que cria ou altera UI carimba
220
- `agent: "ui-designer"` mesmo sem o ramo uiux. Task sem persona clara (config, docs) fica sem `agent`.
221
-
222
- **5b. Carimbe `reuse`** na task que escreve cada conceito do passo 1c: `concept`, `verdict`,
223
- `target` (o que reusar ou estender) e, em `CRIAR`, `why`. Conceito sem task: falta task ou o
224
- conceito não é desta feature — resolva antes do Gate 2.
225
-
226
- **O `doneCriteria` carrega a pós-condição LITERAL**, prefixada pelo rótulo (`"P2 — Cada
227
- veterinário traz..."`). Reescrever com outras palavras é onde o requisito se perde. Toda
228
- pós-condição de todo UC tem ao menos uma task.
229
-
230
- **`morph-spec dag {feature}` cobra o encanamento.** Ele reporta UC inexistente (erro), pós-condição sem task e `doneCriteria` parafraseado (avisos), e `doneCriteria` com vocabulário de artefato (`grep`, "contém a string", "o binário", "nenhum arquivo", "arquivo/pasta/diretório em", glob `**/`) sem `Por que artefato:` (aviso). Também aponta task sobre UC `superseded` e linha de revogação que o `finish` não aplicaria.
231
-
232
- **Orçamento de teste por task.** Cada pós-condição compra **um** teste, cada bug corrigido **um** de
233
- regressão; acima disso, uma linha de justificativa na `description`. Cenários do mesmo
234
- comportamento são linhas de tabela (`[Theory]`/`it.each`). **Nenhum teste que só fixa texto**
235
- (copy, config, prosa). O `verify` avisa quando o teste adicionado passa de 1,5× a produção.
236
-
237
- **Critério sobre saída de LLM vira eval de runtime — nunca "suíte estrutural".** Vale quando a seção
238
- de contrato cita um standard `ai-agents` e o `doneCriteria` julga o que o modelo *responde*:
239
- - a prova é um **eval de runtime**; a evidência vai em
240
- `.morph/features/{feature}/3-implement/evidencias/{taskId}.md`, e esse path entra em
241
- `outputs` — é por ele que implementador e avaliador sabem que ela é devida. Com nó
242
- `runner: "evals"` (standard `ai-agents-evals-with-cache`), o cenário mora no dataset do nó;
243
- - **no máximo 1 teste de estrutura** da fonte do prompt — nunca vocabulário do que o modelo
244
- deveria dizer;
245
- - as duas coisas vão na `description` da task.
246
-
247
- **5c. Cross-check do `1-design/` — todo aviso de capacidade tem destino.** Com o diretório
248
- presente, antes de fechar o array `tasks`:
249
-
250
- ```bash
251
- grep -riE "capacidade nova|precisa de backend|dimensionar junto" .morph/features/{feature}/1-design/
252
- ```
253
-
254
- Cada ocorrência vira **task irmã** ou exclusão registrada em `decisions.md` com o motivo —
255
- **nunca fica sem destino**. Sem hits, ou sem `1-design/`, o passo é um no-op.
256
-
257
- **5d. O checklist de tela vira critério.** A task que entrega uma `## Tela:` do
258
- `1-design/mockups.md` carrega no `doneCriteria` as decisões do `### Checklist de tela` (volume,
259
- paginação, ordenação, filtro, os três estados, mobile, abas), citando a seção por path
260
- (`1-design/mockups.md#tela-…`) — "lista pagina no servidor, 25 por página" é critério; "conforme
261
- o mockup" não é. Item "não se aplica" não vira critério.
262
-
263
- Antes de retornar, valide rodando `morph-spec dag {feature}` — schema do tasks.json (ids, enums,
264
- dependências) e a análise de DAG que a `/morph-apply` vai usar.
265
-
266
- 6. Apresente o Gate 2 segundo trust mode.
267
-
268
- Rode `morph-spec gate-check {feature} plan [--json]` — decide pelos sinais do disco e persiste
269
- `gateDecisions.plan`. Divergência de design system do Gate 1 sem resolução, ou violação de
270
- standard, entram por `--signals` (as únicas chaves aceitas):
271
- ```
272
- morph-spec gate-check {feature} plan --signals '{"designSystemDivergence":true,"standardsViolations":["<id>"]}'
273
- ```
274
- Risco que nenhuma chave representa: `gate-decision` direto. Nunca edite `feature.json` à mão.
275
- `morph-spec dag {feature} --mermaid` dá o diagrama do plano para o gate.
276
-
277
- **Se `pause === true`**, `AskUserQuestion`:
278
-
279
- ```
280
- question: "Gate 2 — Plano de {feature} aprovado?{ reason ? ' Sinal: ' + reason : '' }"
281
- header: "Gate 2"
282
- options:
283
- - { label: "aprovado, prosseguir", description: "Aceitar use cases, spec e tasks e habilitar /morph-apply" }
284
- - { label: "preciso ajustar", description: "Apontar mudanças no plano antes de prosseguir" }
285
- - { label: "cancelar feature", description: "Abortar" }
286
- ```
287
-
288
- **Se `pause === false`**: resumo de 3 linhas (problema → solução; tasks e esforço; caminho
289
- crítico) e `morph-spec approve {feature} plan --mode auto` (ou `advance {feature}`). A pergunta
290
- nomeia a feature — é por ela que o hook `state-sync` grava a aprovação.
291
-
292
- Aprovado o Gate 2, o frontmatter de cada use case passa de `status: draft` a `status: approved`.
293
- O `finish` os promove ao acervo com `status: implemented`.
294
-
295
- ## Output esperado
296
-
297
- - `2-plan/usecases/UC-{nn}-{slug}.md` — pós-condições testáveis
298
- - `2-plan/spec.md` — arquitetura, seção de revogação e `## Contrato de implementação`
299
- - `2-plan/tasks.json` — válido contra o schema, `doneCriteria` literal, `agent`/`standards`/`reuse`
300
- carimbados, `3-implement/evidencias/{taskId}.md` em `outputs` nas tasks de critério sobre LLM
301
- - Gate 2 registrado em `feature.json`
302
-
303
- ## Referências
304
-
305
- - `.morph/framework/MORPH.md` — §2 (fases), §3 (contratos de output), §5 (gates)
306
- - `morph-spec standards --find|graph explain|graph affected --uses-only|usecase reserve|usecase check|dag` — `.morph/framework/CLI.md`
307
- - `.morph/framework/schemas/tasks.schema.json`
12
+ ## 0. Contrato
13
+
14
+ Saída: `.morph/features/{feature}/2-plan/plan.md` (fonte única da feature) e `2-plan/checks.json`, gravado só por `morph-spec plan-check`. O usuário só toca a entrevista e o gate; o resto você resolve. Nada de código nesta fase. O `create` escreve o esqueleto de `plan.md` no nascimento: só é retomada com `2-plan/checks.json` no disco ou com o `plan.md` já sem os `<…>` do esqueleto — aí vá ao §5 (corrigir) ou ao §7 (gate).
15
+
16
+ ## 1. Roteamento
17
+
18
+ Sem nome de feature, pergunte (`AskUserQuestion`, header "Feature"). Feature que ainda não existe (sem `feature.json`), uma vez só:
19
+
20
+ ```
21
+ morph-spec create {feature} --request "<pedido do usuário>"
22
+ ```
23
+
24
+ Tipo óbvio pelo pedido: `--type <tipo> --description "<o quê/porquê>"`. O `--request` semeia a descrição; sem ele nem `--description`, o `create` recusa. **Exit 2** (empate ou nenhum sinal): você é o roteador — escolha entre os `candidates` e re-rode com `--type <tipo> --request "<pedido>"`. `AskUserQuestion` só quando o pedido é genuinamente indeterminado.
25
+
26
+ | Tipo | Caminho |
27
+ |---|---|
28
+ | `hotfix` | `Skill(morph-hotfix)` com o nome e **encerre** esta skill |
29
+ | `chore` | plan.md curto (§8), `plan-check`, e `Skill(morph-apply)` direto — a única exceção ao §9 |
30
+ | `bug` | fluxo inteiro em modo bug-lean (§8) |
31
+ | `feature` | fluxo inteiro (§2–§7) |
32
+
33
+ ## 2. Varredura — antes de qualquer pergunta
34
+
35
+ Fato não se pergunta: as decisões são do usuário, os fatos são seus.
36
+
37
+ 1. `morph-spec stack-scan {feature}` → `2-plan/stack-scan.md`. Greenfield sai curto; em brownfield lista desvios por severidade contra `project.stack`. Desvio Bloqueante ou Alto vira um nó da árvore ("a migração entra nesta feature ou vira feature separada?") — **dentro** da árvore, nunca uma pergunta antes dela.
38
+ 2. Leia `.morph/config/config.json`, `.morph/context/` (o inventário `README.md` dá componentes e endpoints; `morph-spec context refresh` o regera), as features ativas e o índice de ADRs `.morph/specs/adrs/`. Decisão vigente é a do índice; `decisions.md` e use cases de `.morph/archive/` são **história, não instrução** — abra um só para entender por que algo é como é.
39
+ 3. **Conflitos com o acervo — avise, não entreviste.** Para cada ADR ou documento de `.morph/context/` que o pedido contradiz: uma linha de aviso no resumo que abre o §3 (fonte, o que diz, o que o pedido muda). **Pedido explícito sobre o ponto → vale o mais novo**, e você segue. Só entra na árvore o conflito que o pedido deixa **ambíguo** ("o admin passa a Geist" não diz nada da vitrine: a vitrine é decisão, o admin não). Todo conflito, decidido ou não, vai para `### Conflitos com o acervo` do plan.md.
40
+ 4. **Design system:** compare `.morph/context/design-system.md` com o detectado e com mocks recentes do usuário. Divergência (tokens, versão, fonte aprovada) é **decisão da árvore** e sinal `designSystemDivergence` no §7. Resolvida, **reescreva o corpo** do arquivo com a fonte escolhida — a seção que descrevia a antiga passa a descrever a nova, com o escopo onde o valor antigo ainda vale; o changelog guarda **só data e motivo**, nunca o valor novo. Este é o protocolo que a `morph-uiux` reaplica.
41
+
42
+ ## 3. Árvore de decisões e modo
43
+
44
+ Entra na árvore só o que (a) muda escopo, comportamento ou arquitetura e (b) a varredura não respondeu. Ordene pelo que **poda**: "síncrono ou assíncrono?" vem antes de "qual política de retry". Publique a árvore ao usuário antes de perguntar.
45
+
46
+ **Pergunta de abertura** (só `feature` e `bug`; `chore` e `hotfix` não passam por aqui): uma `AskUserQuestion`, header "Descoberta", com a árvore resumida e o modo recomendado em primeiro lugar com `(Recomendado)` no label. Muitas decisões, ou decisões acopladas → entrevista; árvore rasa → automático.
47
+
48
+ - **Entrevista:** **uma pergunta por chamada** de `AskUserQuestion` — lote desorienta e impede que uma resposta pode ramos. Cada pergunta traz a resposta recomendada como primeira opção, `(Recomendado)`. Mostre a árvore quando ela mudar de forma. Termina quando a árvore zera; o usuário pode encerrar antes, e o que ficou aberto vira `## Fora de escopo`. O gate do plano pausa sempre neste modo (§7).
49
+ - **Automático:** até 4 perguntas, **só sobre nós abertos** da árvore — nunca uma lista fixa. Árvore vazia → nenhuma pergunta.
50
+
51
+ **Headless** (`AskUserQuestion` indisponível ou negada, como sob `claude -p`): nunca decida você os nós abertos. Escreva-os em texto, numerados, cada um com a resposta recomendada; rode `morph-spec gate-decision {feature} plan --pause true --reason "entrevista headless"` e **encerre o turno**. Retome quando o usuário responder.
52
+
53
+ ## 4. Território
54
+
55
+ Feature grande ou brownfield: despache `subagent_type: "morph-scout"` (não registrado: `general-purpose` com o campo `persona` do `scout` de `.morph/framework/agents.json`) para os arquivos que a feature toca e o blast radius dos símbolos centrais. Grave em `2-plan/scout-map.md` e audite:
56
+
57
+ ```
58
+ morph-spec scout-check .morph/features/{feature}/2-plan/scout-map.md --json
59
+ ```
60
+
61
+ Exit ≠ 0 → descarte o mapa e re-despache **uma** vez com as `failures` coladas; segunda reprovação: grep você mesmo. Mapa aprovado prova que as citações existem, não que a conclusão está certa — confira com grep próprio o Inferido que muda o plano. Pular o scout numa feature pequena no domínio carregado: uma linha em `## Arquitetura`.
62
+
63
+ **Reuso — o que já existe.** Para cada conceito central (entidade, DTO, componente, hook, helper, dublê de teste): `morph-spec graph explain <nome> --json` e `morph-spec graph affected <nome> --uses-only --json`. Antes, `morph-spec graph status --json`; stale numa worktree → `morph-spec graph refresh`. `--uses-only` importa: o grep conta herança como uso — no ProspectPRO apontou 23 arquivos onde 20 eram interfaces filhas herdando o contrato e só 2 usavam de verdade. **Sem grafo** (`no-graph`, `not-found` num grafo stale), caia para `grep -rn "<nome>"` e registre que a contagem veio do grep, que superestima consumidores. A ausência de grafo nunca bloqueia.
64
+
65
+ ## 5. plan.md
66
+
67
+ O `create` já escreveu o esqueleto em `2-plan/plan.md` (leia e preencha; `chore` e `hotfix` nascem com o gate carimbado e criam o arquivo numa única escrita); gramática completa: `morph-spec plan-check --help`. `plan-check` é o único leitor; o que ele não reconhece, ninguém lê.
68
+
69
+ **Cenários** (`## Cenários`): `- **Cn** — Dado …, quando …, então …`, com `prova:` (`teste` | `e2e` | `eval` | `manual`) **na linha seguinte, sem linha em branco** — linha vazia encerra o cenário.
70
+ - **Observável em teste**: que asserção eu escreveria? Sem resposta, reescreva ou descarte.
71
+ - **Artefato não é comportamento.** Cenário que cita `grep`, "contém a string", "o binário", "nenhum arquivo", "arquivo/pasta/diretório em" ou glob `**/` descreve o repositório. Tente o efeito em runtime; se o artefato É o entregável, justifique em `> Por que artefato:` logo abaixo (nunca na mesma linha, nunca `> [!note]`).
72
+ - **Saída de LLM** (o que o modelo responde) prova-se por `eval` de runtime, nunca pelo texto do prompt: evidência em `3-implement/evidencias/{Cn}.md`, path listado em `arquivos:` da fatia; com nó `runner: "evals"` (standard `ai-agents-evals-with-cache`) o cenário mora no dataset. No máximo 1 teste de estrutura da fonte do prompt.
73
+ - **"O comando de teste da raiz roda de ponta a ponta"** prova-se pelo `verify {feature}` (o nó `e2e` e o nó de teste `e2e: true` já percorrem a cadeia): nomeie essa rodada como a prova, nunca uma execução avulsa. Precisando mesmo rodar fora dele, numa linha só (o Bash não guarda o env entre chamadas): `eval "$(morph-spec env {feature})" && morph-spec heavy run -- <comando>` — o `COMPOSE_PROJECT_NAME` da feature é o que o `finish` derruba com os volumes. `prova: manual` registra passo e resultado em `3-implement/evidencias/{Cn}.md`.
74
+ - **Orçamento de teste**: um teste por cenário, um de regressão por bug; acima disso, uma linha de porquê. Cenários do mesmo comportamento são linhas de tabela (`[Theory]`/`it.each`); nenhum teste que só fixa texto. O `verify` avisa quando o teste passa de 1,5× a produção.
75
+
76
+ ```markdown
77
+ ## Cenários
78
+ - **C1** — Dado um tenant com `criterion_overrides`, quando ele é publicado, então a publicação é recusada nomeando a chave.
79
+ prova: teste
80
+ - **C2** — Nenhum arquivo em `tenants/**` contém a chave `criterion_overrides`.
81
+ prova: teste
82
+ > Por que artefato: a chave saiu do contrato; nenhum leitor de runtime a consulta.
83
+
84
+ ## Fatias
85
+ ### F1 — Recusar a chave na publicação
86
+ - persona: dotnet-senior
87
+ - standards: backend-dotnet-vsa-handler-patterns, backend-dotnet-testing, architecture-code-comments
88
+ - arquivos: src/Tenants/Publish.cs, tests/Tenants/PublishTests.cs
89
+ - cobre: C1, C2
90
+ ```
91
+
92
+ **Decisões** (`## Decisões`): uma `### ADR-001 — título` por decisão não trivial (alternativa descartada, motivo, quem decidiu), com `**Alcance:** feature` ou `projeto` — `projeto` quando vale além desta feature. Em projeto greenfield, a decisão que fixa stack, layout, infraestrutura ou test runner é `projeto`: a próxima feature a herda, e só o índice de ADRs a mostra. `### Conflitos com o acervo` existe sempre; "nenhum" vale. Proibição além das de `MORPH.md` § "Stack baked-in" é ADR.
93
+
94
+ **Arquitetura**: componentes, fluxo de dados, edge cases **técnicos** e integrações; não repita os cenários.
95
+
96
+ **Reuso**: tabela `| conceito | veredito | alvo | why |`, veredito `REUSAR` | `ESTENDER` | `CRIAR`. **`CRIAR` exige `why`** — a consulta que respondeu "não existe" (`graph explain X → not-found; grep -rn X → 0`). Conceito de duas features vai para um módulo comum, nunca import cruzado entre slices. O validador `reuse` do `verify` cobra: símbolo novo homônimo de um existente reprova na mesma feature e avisa entre features; `CRIAR` declarado rebaixa a aviso. Conceito sem fatia que o escreva: falta fatia ou o conceito não é desta feature — resolva antes do gate.
97
+
98
+ **Fatias** (`### Fn — título`): a unidade de entrega e de relatório (`3-implement/reports/Fn.md`).
99
+ - `persona:` obrigatório — o id sem `morph-`, cujo `domains` cobre a fatia (uma leitura de `agents.json`). Fatia que cria ou altera UI é `ui-designer`, mesmo sem o ramo de design; com `superfície:`, os standards são os daquela chave de `surfaces`.
100
+ - `standards:` — `morph-spec standards --find "<domínio>"` por domínio (o digest decide): os da persona mais o que a fatia exige, sempre `architecture-code-comments` e o de teste do stack; agente MAF soma `--category ai-agents`.
101
+ - `arquivos:` — os paths planejados, testes incluídos, **no máximo 8**: acima disso o sub-agente bate no teto de turnos.
102
+ - `depende:` opcional; `cobre:` lista os Cn — todo cenário é coberto por alguma fatia. Fatias sem `depende:` comum e sem arquivo em comum rodam em paralelo; o `plan-check` imprime as ondas.
103
+ - Cenário que se observa por um artefato de outra fatia (rota, endpoint, componente que ela cria) faz da fatia que o cobre um `depende:` daquela — senão as duas caem na mesma onda e o teste do cenário não tem por onde provar. O `plan-check` não vê de quem é a rota: a regra é sua.
104
+
105
+ **Contrato de implementação**: o que quem implementa precisa e o código não diz.
106
+ - **Verificação de runtime:** o stack sobe por `morph-spec e2e up {feature}` (compose do projeto; sem compose, isso é uma fatia); os fluxos que o verificador navega, nos verbos dos cenários; base URL `process.env.PLAYWRIGHT_BASE_URL ?? \`http://localhost:${process.env.PORT ?? 3000}\``, compose com `"${PORT:-3000}:3000"` e sem `container_name` (standard `infrastructure/docker/local-compose-isolation`). App com login: `e2e.auth` em `config.json` (`mode: seed|storageState|bypass|none`, `seedCommand`, `storageStatePath`, `envFile`), credenciais num `.env.e2e` gitignored — **`mode` é obrigatório sempre que houver `seedCommand`**, sem ele o seed fica inerte. Biblioteca pura: registre a dispensa e o porquê.
107
+ - **Baseline é um COMANDO, nunca um número.** O plano congela e é lido por dias: um número cravado está errado na primeira fatia, e quem confia nele "conserta" o que não quebrou. Registre como medir (`npm test`, `dotnet test`); o `expectedCount` sai de `morph-spec verify {feature} --record-baseline`, nunca digitado. Sem `project.stack`/`project.tests` no `config.json`, a `morph-apply` os declara a partir destes comandos antes do primeiro verify.
108
+ - **Pré-requisito é um PREDICADO, nunca um SHA literal:** "`git merge-base --is-ancestor origin/main HEAD` sai 0" — o SHA muda no primeiro squash.
109
+
110
+ Plano bom cabe em duas páginas; crescendo além, corte escopo. Feche com `morph-spec plan-check {feature}` até zero erro. Ele também recusa veredito de reuso fora do enum, id `C`/`F`/`ADR` duplicado, `## Errata` fora do fim, `## Cenários` vazio e fatia sem `persona:`; avisa chave de fatia desconhecida, superfície fora da `ui-designer`, ADR sem **Alcance**, fatia sem `cobre:` e mais de 12 fatias.
111
+
112
+ ## 6. Ramo de design
113
+
114
+ Critério objetivo, decidido **uma vez**, aqui: a feature cria ou altera superfície de UI (componente, página, tela, estilo, fluxo de navegação)? Sim → `morph-spec advance {feature} --design`, sempre por ele e nunca criando `1-design/` à mão: no gate auto-aprovado ele aprova `plan`; com o gate já aprovado pelo humano, só abre o ramo. Nos dois casos escreve `1-design/mockups.md` do template e, se faltar, `.morph/context/design-system.md`. Depois, `Skill(morph-uiux)`. Não → `morph-spec advance {feature}` leva a implement. Ninguém redecide adiante.
115
+
116
+ ## 7. Gate do plano
117
+
118
+ ```
119
+ morph-spec gate-check {feature} plan [--json]
120
+ ```
121
+
122
+ Divergência de design system ou violação de standard que o disco não vê entram por `--signals '{"designSystemDivergence":true,"standardsViolations":["<id>"]}'` (as únicas chaves aceitas). **Modo entrevista** pausa sempre, e `shouldPauseGate` não conhece isso — registre direto: `morph-spec gate-decision {feature} plan --pause true --reason "modo entrevista — entendimento compartilhado" --signals '{"discoveryMode":"interview"}'`. Outro risco que nenhuma chave representa: `gate-decision` também. Nunca edite `feature.json` à mão.
123
+
124
+ **`pause === true`**: apresente o entendimento compartilhado (problema, fora de escopo, cenários, fatias, riscos) e uma `AskUserQuestion`, header "Gate plano":
125
+
126
+ ```
127
+ question: "Gate do plano — Plano de {feature} aprovado?{ reason ? ' Sinal: ' + reason : '' }"
128
+ options: "aprovado, prosseguir" | "preciso ajustar" | "cancelar feature"
129
+ ```
130
+
131
+ A pergunta **nomeia a feature**: é por ela que o hook `state-sync` grava a aprovação; sem o nome, com mais de uma feature na árvore, ele recusa. O hook só aceita resposta que começa com "aprovado" ou contém "pode avançar", "pode implementar" ou "pode prosseguir" — "lgtm" não grava. Sem `AskUserQuestion` (headless): `morph-spec approve {feature} plan --approver <quem>`. "Preciso ajustar" → edite, `plan-check`, reapresente.
132
+
133
+ **`pause === false`**: resumo de 3 linhas (problema → solução; fatias e ondas; risco principal) e `morph-spec advance {feature}` (ou `--design`, §6).
134
+
135
+ **Congelamento:** aprovado o gate, o corpo do plan.md trava — fato errado sobre o código vai num bloco `## Errata` append-only no fim (não muda o `planHash`); `checks.json` só se regrava por `plan-check`. Mudança de escopo: `morph-spec unapprove {feature} plan`, editar, `plan-check`, reapresentar o gate.
136
+
137
+ ## 8. Deltas por tipo
138
+
139
+ - **`bug` (bug-lean):** a varredura roda inteira; a árvore é de repro, diagnóstico e comportamento do sistema, não de negócio; no modo automático, no máximo 1 pergunta de repro, e só se o pedido não deixar claro. `## Problema` traz repro, diagnóstico e causa provável; os cenários são o sintoma ausente e a regressão; `### Conflitos com o acervo` continua presente.
140
+ - **`chore`:** nasce com o gate `plan` carimbado por política. Escreva o plan.md curto numa única escrita (o gate já aprovado congela o arquivo depois de criado): `## Problema`, um ou dois cenários, `## Decisões` só com `### Conflitos com o acervo`, uma fatia. `plan-check` e `Skill(morph-apply)`.
141
+ - **`hotfix`:** é da `morph-hotfix`.
142
+
143
+ ## 9. Encerramento
144
+
145
+ Diga ao usuário: "Plano aprovado. Rode `/morph-apply {feature}` para implementar." Não despache a `morph-apply` — o usuário decide quando começar (exceção: `chore`).