@polymorphism-tech/morph-spec 9.0.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 (304) hide show
  1. package/CLAUDE.md +8 -9
  2. package/README.md +38 -36
  3. package/bin/morph-spec.js +4 -62
  4. package/bin/validate.js +1 -39
  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 +1 -1
  9. package/framework/MORPH.md +1 -1
  10. package/framework/agents.json +12 -4
  11. package/framework/commands/morph-apply.md +1 -1
  12. package/framework/commands/morph-status.md +1 -1
  13. package/framework/docs/CLI.md +6 -17
  14. package/framework/hooks/claude-code/core/block-destructive-worktree-removal.js +6 -49
  15. package/framework/hooks/claude-code/core/block-raw-worktree-add.js +2 -35
  16. package/framework/hooks/claude-code/core/chain.js +4 -65
  17. package/framework/hooks/claude-code/core/comment-guard.js +2 -16
  18. package/framework/hooks/claude-code/core/enforce-phase-writes.js +6 -50
  19. package/framework/hooks/claude-code/core/gate-guard.js +7 -67
  20. package/framework/hooks/claude-code/core/graph-refresh-kick.js +3 -24
  21. package/framework/hooks/claude-code/core/heavy-gate.js +3 -21
  22. package/framework/hooks/claude-code/core/heavy-release.js +2 -13
  23. package/framework/hooks/claude-code/core/loop-detect.js +2 -31
  24. package/framework/hooks/claude-code/core/pre-bash-denylist.js +0 -4
  25. package/framework/hooks/claude-code/core/protect-spec-files.js +7 -67
  26. package/framework/hooks/claude-code/core/state-sync.js +11 -67
  27. package/framework/hooks/claude-code/core/telemetry-log.js +12 -93
  28. package/framework/hooks/claude-code/core/validate-completion.js +11 -57
  29. package/framework/hooks/claude-code/core/warn-bash-source-write.js +1 -9
  30. package/framework/hooks/claude-code/core/worktree-context.js +10 -110
  31. package/framework/hooks/claude-code/core/worktree-create.js +6 -70
  32. package/framework/hooks/claude-code/core/worktree-env-inject.js +5 -56
  33. package/framework/hooks/claude-code/core/worktree-remove.js +5 -31
  34. package/framework/hooks/shared/activity-logger.js +9 -89
  35. package/framework/hooks/shared/agent-reap.js +2 -17
  36. package/framework/hooks/shared/build-check.js +6 -75
  37. package/framework/hooks/shared/claim-registry.js +9 -119
  38. package/framework/hooks/shared/command-tokens.js +6 -51
  39. package/framework/hooks/shared/comment-rules.js +5 -20
  40. package/framework/hooks/shared/comment-scanner.js +6 -25
  41. package/framework/hooks/shared/comment-stripper.js +11 -85
  42. package/framework/hooks/shared/e2e-check.js +0 -0
  43. package/framework/hooks/shared/errata.js +2 -15
  44. package/framework/hooks/shared/feature-locator.js +11 -95
  45. package/framework/hooks/shared/frontend-locations.js +1 -3
  46. package/framework/hooks/shared/gate-question.js +1 -7
  47. package/framework/hooks/shared/git-exclude.js +3 -20
  48. package/framework/hooks/shared/git-paths.js +8 -104
  49. package/framework/hooks/shared/graph-freshness.js +22 -166
  50. package/framework/hooks/shared/graph-refresh.js +21 -149
  51. package/framework/hooks/shared/heavy-command.js +4 -12
  52. package/framework/hooks/shared/hook-response.js +8 -83
  53. package/framework/hooks/shared/morph-cli.js +8 -52
  54. package/framework/hooks/shared/payload-utils.js +10 -132
  55. package/framework/hooks/shared/phase-utils.js +1 -42
  56. package/framework/hooks/shared/redact-secrets.js +4 -15
  57. package/framework/hooks/shared/reparse-scan.js +6 -66
  58. package/framework/hooks/shared/slice-progress.js +4 -23
  59. package/framework/hooks/shared/source-files.js +4 -17
  60. package/framework/hooks/shared/state-reader.js +13 -183
  61. package/framework/hooks/shared/state-writer.js +8 -52
  62. package/framework/hooks/shared/stdin-reader.js +1 -11
  63. package/framework/hooks/shared/telemetry-logger.js +7 -67
  64. package/framework/hooks/shared/transcript-usage.js +7 -29
  65. package/framework/hooks/shared/worktree-root.js +7 -29
  66. package/framework/rules/csharp-standards.md +1 -1
  67. package/framework/rules/frontend-standards.md +1 -0
  68. package/framework/rules/hangfire-standards.md +1 -1
  69. package/framework/rules/neon-standards.md +1 -1
  70. package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
  71. package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +1 -1
  72. package/framework/skills/core/morph-apply/SKILL.md +2 -2
  73. package/framework/skills/core/morph-hotfix/SKILL.md +1 -1
  74. package/framework/skills/core/morph-machine/SKILL.md +1 -1
  75. package/framework/skills/core/morph-media/SKILL.md +1 -1
  76. package/framework/skills/core/morph-plan/SKILL.md +2 -2
  77. package/framework/skills/core/morph-review/SKILL.md +1 -1
  78. package/framework/skills/core/morph-standards/SKILL.md +1 -1
  79. package/framework/skills/core/morph-uiux/SKILL.md +29 -12
  80. package/framework/standards/STANDARDS.json +34 -12
  81. package/framework/standards/STANDARDS.meta.json +16 -2
  82. package/framework/standards/ai-agents/agent-archetypes.md +2 -2
  83. package/framework/standards/ai-agents/agent-session.md +1 -1
  84. package/framework/standards/ai-agents/conversational-agent-with-phases.md +4 -4
  85. package/framework/standards/ai-agents/durable-workflows-hitl.md +3 -3
  86. package/framework/standards/ai-agents/guardrails.md +1 -1
  87. package/framework/standards/ai-agents/multi-agent-patterns.md +2 -2
  88. package/framework/standards/ai-agents/observability-patterns.md +1 -1
  89. package/framework/standards/ai-agents/production.md +1 -1
  90. package/framework/standards/ai-agents/prompt-sources.md +2 -2
  91. package/framework/standards/ai-agents/providers/model-registry.md +1 -1
  92. package/framework/standards/ai-agents/rag-custom-pgvector.md +2 -2
  93. package/framework/standards/ai-agents/setup.md +2 -2
  94. package/framework/standards/ai-agents/sweet-spot.md +2 -2
  95. package/framework/standards/ai-agents/tool-adapters.md +0 -2
  96. package/framework/standards/ai-agents/vector-data-extensions.md +4 -4
  97. package/framework/standards/ai-agents/workflows.md +1 -1
  98. package/framework/standards/architecture/code-comments.md +1 -1
  99. package/framework/standards/architecture/vertical-slice/vertical-slice.md +1 -1
  100. package/framework/standards/backend/api/validation.md +1 -1
  101. package/framework/standards/backend/dotnet/vsa-handler-patterns.md +5 -5
  102. package/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +1 -1
  103. package/framework/standards/backend/integrations/neon-auth/neon-auth.md +2 -2
  104. package/framework/standards/data/nosql/cache/redis.md +1 -1
  105. package/framework/standards/data/nosql/cosmos-db.md +3 -3
  106. package/framework/standards/frontend/admin-app/forms.md +1 -1
  107. package/framework/standards/frontend/design-system/art-direction.md +88 -0
  108. package/framework/standards/frontend/design-system/premium-finish.md +77 -2
  109. package/framework/standards/infrastructure/neon/neon-pgvector.md +5 -5
  110. package/framework/templates/CLAUDE.md.core.template +3 -3
  111. package/framework/templates/REGISTRY.json +9 -9
  112. package/framework/templates/docs/ui-mockups.md +4 -0
  113. package/package.json +1 -1
  114. package/src/commands/context/context-refresh.js +0 -16
  115. package/src/commands/dashboard/dashboard.js +2 -8
  116. package/src/commands/e2e/e2e.js +17 -104
  117. package/src/commands/graph/affected.js +0 -14
  118. package/src/commands/graph/build.js +11 -50
  119. package/src/commands/graph/explain.js +0 -16
  120. package/src/commands/graph/status.js +1 -12
  121. package/src/commands/mcp/mcp-setup.js +4 -62
  122. package/src/commands/observability/cost.js +5 -57
  123. package/src/commands/observability/telemetry.js +1 -14
  124. package/src/commands/project/branch.js +4 -45
  125. package/src/commands/project/claim.js +4 -48
  126. package/src/commands/project/doctor.js +48 -302
  127. package/src/commands/project/env.js +1 -27
  128. package/src/commands/project/fleet.js +3 -32
  129. package/src/commands/project/init.js +4 -68
  130. package/src/commands/project/install-plugin-cmd.js +0 -1
  131. package/src/commands/project/standards.js +1 -62
  132. package/src/commands/project/status.js +0 -53
  133. package/src/commands/project/update.js +31 -239
  134. package/src/commands/project/worktree.js +108 -882
  135. package/src/commands/scaffold/scaffold.js +0 -25
  136. package/src/commands/state/advance.js +14 -85
  137. package/src/commands/state/approve.js +14 -96
  138. package/src/commands/state/archive.js +12 -64
  139. package/src/commands/state/auto-approval.js +2 -5
  140. package/src/commands/state/create.js +22 -109
  141. package/src/commands/state/delete.js +11 -63
  142. package/src/commands/state/finish.js +98 -475
  143. package/src/commands/state/gate-check.js +22 -132
  144. package/src/commands/state/gate-decision.js +3 -39
  145. package/src/commands/state/handoff.js +3 -30
  146. package/src/commands/state/list.js +14 -84
  147. package/src/commands/state/report-check.js +8 -58
  148. package/src/commands/state/retype.js +4 -26
  149. package/src/commands/validation/index.js +0 -3
  150. package/src/commands/validation/mutate.js +2 -5
  151. package/src/commands/validation/validate-feature.js +5 -94
  152. package/src/commands/validation/verify.js +15 -98
  153. package/src/core/paths/output-schema.js +2 -101
  154. package/src/core/state/feature-identity.js +1 -25
  155. package/src/core/state/gate-order.js +0 -27
  156. package/src/core/state/lifecycle-audit.js +8 -100
  157. package/src/core/state/state-manager.js +22 -304
  158. package/src/core/templates/template-registry.js +2 -97
  159. package/src/core/templates/template-renderer.js +13 -93
  160. package/src/core/templates/template-seed.js +0 -1
  161. package/src/core/work-types.js +1 -36
  162. package/src/dashboard/app/App.jsx +1 -8
  163. package/src/dashboard/app/components/ActivityFeed.jsx +0 -5
  164. package/src/dashboard/app/components/CommandPalette.jsx +0 -7
  165. package/src/dashboard/app/components/DetailPanel.jsx +1 -5
  166. package/src/dashboard/app/components/EntityLink.jsx +0 -12
  167. package/src/dashboard/app/components/ErrorBoundary.jsx +1 -8
  168. package/src/dashboard/app/components/KnowledgeMarkdown.jsx +0 -11
  169. package/src/dashboard/app/components/Markdown.jsx +0 -9
  170. package/src/dashboard/app/components/PhaseRail.jsx +0 -11
  171. package/src/dashboard/app/components/SearchFilter.jsx +0 -4
  172. package/src/dashboard/app/components/Sidebar.jsx +0 -5
  173. package/src/dashboard/app/hooks/useMorphQuery.js +1 -11
  174. package/src/dashboard/app/hooks/usePref.js +1 -5
  175. package/src/dashboard/app/lib/format.js +0 -2
  176. package/src/dashboard/app/lib/phases.js +1 -5
  177. package/src/dashboard/app/lib/project.js +0 -12
  178. package/src/dashboard/app/pages/AgentMap.jsx +1 -8
  179. package/src/dashboard/app/pages/FeatureDetail.jsx +1 -5
  180. package/src/dashboard/app/pages/Features.jsx +1 -8
  181. package/src/dashboard/app/pages/Guide.jsx +0 -1
  182. package/src/dashboard/app/pages/HookInspector.jsx +2 -23
  183. package/src/dashboard/app/pages/PhasePipeline.jsx +0 -3
  184. package/src/dashboard/app/pages/Portfolio.jsx +0 -1
  185. package/src/dashboard/app/pages/RulesMap.jsx +1 -16
  186. package/src/dashboard/app/pages/SkillsLibrary.jsx +1 -16
  187. package/src/dashboard/app/pages/Standards.jsx +2 -17
  188. package/src/dashboard/scanner/activity-scanner.js +10 -69
  189. package/src/dashboard/scanner/agents-scanner.js +1 -23
  190. package/src/dashboard/scanner/docs-scanner.js +0 -6
  191. package/src/dashboard/scanner/feature-status.js +2 -5
  192. package/src/dashboard/scanner/features-scanner.js +10 -66
  193. package/src/dashboard/scanner/hooks-scanner.js +5 -28
  194. package/src/dashboard/scanner/index.js +0 -4
  195. package/src/dashboard/scanner/portfolio.js +5 -29
  196. package/src/dashboard/scanner/project-api.js +8 -54
  197. package/src/dashboard/scanner/rules-scanner.js +1 -2
  198. package/src/dashboard/scanner/skills-scanner.js +2 -12
  199. package/src/dashboard/scanner/standards-scanner.js +2 -6
  200. package/src/dashboard/vite-plugin-morph-data.js +5 -19
  201. package/src/lib/ai/ai-checks.js +7 -52
  202. package/src/lib/ai/ai-project-scan.js +14 -108
  203. package/src/lib/ai/code-audit.js +7 -63
  204. package/src/lib/ai/pin-drift.js +8 -51
  205. package/src/lib/ai/registry-audit.js +11 -90
  206. package/src/lib/ci/ci-verify.js +4 -19
  207. package/src/lib/ci/github-ci.js +9 -37
  208. package/src/lib/ci/workflow-scaffold.js +2 -10
  209. package/src/lib/detectors/claude-config-detector.js +13 -74
  210. package/src/lib/detectors/index.js +4 -50
  211. package/src/lib/e2e/compose-env.js +5 -66
  212. package/src/lib/e2e/stack-teardown.js +6 -40
  213. package/src/lib/generators/architecture-scanner.js +18 -156
  214. package/src/lib/generators/handoff-generator.js +9 -53
  215. package/src/lib/generators/scaffold-generator.js +5 -101
  216. package/src/lib/generators/settings-generator.js +4 -37
  217. package/src/lib/git/branch-classifier.js +11 -84
  218. package/src/lib/git/default-branch.js +14 -169
  219. package/src/lib/git/evidence-staleness.js +1 -0
  220. package/src/lib/git/gh.js +2 -17
  221. package/src/lib/git/pending-prs.js +6 -37
  222. package/src/lib/git/pr-files.js +3 -28
  223. package/src/lib/git/pr-index.js +3 -34
  224. package/src/lib/git/tree-fingerprint.js +3 -15
  225. package/src/lib/git/tree-state.js +6 -33
  226. package/src/lib/graph/god-nodes.js +2 -22
  227. package/src/lib/graph/graph-health.js +3 -24
  228. package/src/lib/graph/graph-loader.js +5 -56
  229. package/src/lib/graph/graphify-runtime.js +7 -37
  230. package/src/lib/graph/graphifyignore.js +8 -74
  231. package/src/lib/graph/sanitize.js +16 -136
  232. package/src/lib/heavy/cleanup.js +1 -1
  233. package/src/lib/installers/effects.js +8 -93
  234. package/src/lib/installers/mcp-installer.js +9 -169
  235. package/src/lib/installers/memory-installer.js +4 -27
  236. package/src/lib/installers/templates-reconcile.js +5 -60
  237. package/src/lib/mutation/dotnet-introspection.js +20 -106
  238. package/src/lib/mutation/subset.js +1 -4
  239. package/src/lib/plan/artifact-vocabulary.js +5 -25
  240. package/src/lib/plan/checks.js +5 -31
  241. package/src/lib/plan/plan-parser.js +1 -6
  242. package/src/lib/projects/registry.js +7 -44
  243. package/src/lib/review-reports.js +5 -23
  244. package/src/lib/risk-detector.js +39 -173
  245. package/src/lib/specs/adr-index.js +6 -34
  246. package/src/lib/specs/frontmatter.js +2 -15
  247. package/src/lib/specs/gfm-table.js +1 -7
  248. package/src/lib/specs/revocations.js +1 -14
  249. package/src/lib/specs/screen-checklist.js +47 -124
  250. package/src/lib/stack/dotnet-build-ignores.js +2 -6
  251. package/src/lib/stack/stack-profile.js +1 -28
  252. package/src/lib/stack/stack-scan.js +1 -8
  253. package/src/lib/stack-filter.js +4 -27
  254. package/src/lib/standards/registry.js +1 -7
  255. package/src/lib/standards/sections.js +2 -13
  256. package/src/lib/standards/verified-against.js +19 -191
  257. package/src/lib/tasks/eval-node.js +21 -169
  258. package/src/lib/tasks/linux-runner.js +18 -142
  259. package/src/lib/tasks/test-nodes.js +43 -240
  260. package/src/lib/tasks/test-runner.js +43 -341
  261. package/src/lib/telemetry/metrics.js +7 -36
  262. package/src/lib/telemetry/telemetry-reader.js +13 -125
  263. package/src/lib/telemetry/verify-event.js +2 -30
  264. package/src/lib/validators/code-budget/code-budget-validator.js +3 -43
  265. package/src/lib/validators/code-budget/index.js +0 -7
  266. package/src/lib/validators/contracts/contract-compliance-validator.js +2 -24
  267. package/src/lib/validators/contracts/index.js +0 -6
  268. package/src/lib/validators/nextjs/index.js +0 -5
  269. package/src/lib/validators/nextjs/next-component-validator.js +4 -81
  270. package/src/lib/validators/packages/index.js +0 -6
  271. package/src/lib/validators/packages/package-validator.js +6 -56
  272. package/src/lib/validators/reuse/index.js +0 -8
  273. package/src/lib/validators/reuse/reuse-validator.js +11 -101
  274. package/src/lib/validators/reuse/symbol-scanner.js +6 -62
  275. package/src/lib/validators/traceability-check.js +5 -63
  276. package/src/lib/validators/validation-runner.js +20 -125
  277. package/src/lib/validators/verify-runner.js +52 -358
  278. package/src/lib/work-type-detector.js +5 -67
  279. package/src/lib/worktree/docker-audit.js +17 -136
  280. package/src/lib/worktree/env-allocator.js +10 -98
  281. package/src/lib/worktree/feature-truth.js +12 -115
  282. package/src/lib/worktree/finish-backup.js +32 -242
  283. package/src/lib/worktree/fleet-scanner.js +13 -95
  284. package/src/lib/worktree/ignored-triage.js +15 -91
  285. package/src/lib/worktree/vscode-settings.js +2 -3
  286. package/src/lib/worktree/worktree-audit.js +21 -213
  287. package/src/lib/worktree/worktree-include.js +3 -5
  288. package/src/scripts/global-install.js +3 -9
  289. package/src/scripts/install-plugin.js +1 -13
  290. package/src/scripts/setup-infra.js +17 -147
  291. package/src/utils/agents-installer.js +28 -275
  292. package/src/utils/banner.js +4 -25
  293. package/src/utils/claude-md-injector.js +1 -37
  294. package/src/utils/claude-settings-manager.js +1 -52
  295. package/src/utils/file-copier.js +11 -95
  296. package/src/utils/hooks-installer.js +21 -298
  297. package/src/utils/skills-installer.js +4 -101
  298. package/src/utils/version-checker.js +4 -83
  299. package/framework/commands/morph-proposal.md +0 -9
  300. package/src/commands/utils/index.js +0 -3
  301. package/src/lib/detectors/design-system-detector.js +0 -188
  302. package/src/lib/generators/design-system-generator.js +0 -508
  303. package/src/lib/specs/old-format.js +0 -68
  304. package/src/utils/agent-id-mapper.js +0 -11
package/bin/morph-spec.js CHANGED
@@ -1,14 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- /**
4
- * morph-spec CLI v5
5
- *
6
- * In v5 the CLI is the *installer* — Claude executes everything else
7
- * autonomously based on MORPH.md and the core skills. Commands here are
8
- * limited to actions that humans take or operations Claude needs help with
9
- * (scaffolding, validation, context refresh).
10
- */
11
-
12
3
  import { program } from 'commander';
13
4
  import chalk from 'chalk';
14
5
  import { fileURLToPath } from 'url';
@@ -16,14 +7,9 @@ import { dirname, join } from 'path';
16
7
  import { readFileSync } from 'fs';
17
8
  import { renderLogo, maybePrintFirstRunBanner } from '../src/utils/banner.js';
18
9
 
19
- // Command modules load on demand. Importing all ~45 of them eagerly cost
20
- // ~700 ms on EVERY invocation (init.js alone pulls inquirer: ~550 ms), paid
21
- // by each hook that shells out to the CLI and by each CLI spawn in the suite.
22
- // test/bin/command-modules-import.test.js imports every path below, so a module
23
- // that breaks at import time still fails the suite, not only its own command.
10
+ // Lazy: eager import of every command cost ~700 ms per invocation, paid by each hook that shells out.
24
11
  const lazy = (path, name) => async (...args) => (await import(path))[name](...args);
25
12
 
26
- // === Project / install ===
27
13
  const initCommand = lazy('../src/commands/project/init.js', 'initCommand');
28
14
  const setupInfraCommand = lazy('../src/commands/project/setup-infra-cmd.js', 'setupInfraCommand');
29
15
  const installPluginCommand = lazy('../src/commands/project/install-plugin-cmd.js', 'installPluginCommand');
@@ -48,7 +34,6 @@ const scoutCheckCommand = lazy('../src/commands/validation/scout-check.js', 'sco
48
34
  const planCheckCommand = lazy('../src/commands/validation/plan-check.js', 'planCheckCommand');
49
35
  const stackScanCommand = lazy('../src/commands/project/stack-scan.js', 'stackScanCommand');
50
36
 
51
- // === Approval gates (human-only) ===
52
37
  const approveCommand = lazy('../src/commands/state/approve.js', 'approveCommand');
53
38
  const approvalStatusCommand = lazy('../src/commands/state/approve.js', 'approvalStatusCommand');
54
39
  const unapproveCommand = lazy('../src/commands/state/approve.js', 'unapproveCommand');
@@ -63,15 +48,11 @@ const handoffCommand = lazy('../src/commands/state/handoff.js', 'handoffCommand'
63
48
  const listCommand = lazy('../src/commands/state/list.js', 'listCommand');
64
49
  const deleteCommand = lazy('../src/commands/state/delete.js', 'deleteCommand');
65
50
 
66
- // === Tasks ===
67
-
68
- // === Codebase graph ===
69
51
  const graphStatusCommand = lazy('../src/commands/graph/status.js', 'graphStatusCommand');
70
52
  const graphBuildCommand = lazy('../src/commands/graph/build.js', 'graphBuildCommand');
71
53
  const graphAffectedCommand = lazy('../src/commands/graph/affected.js', 'graphAffectedCommand');
72
54
  const graphExplainCommand = lazy('../src/commands/graph/explain.js', 'graphExplainCommand');
73
55
 
74
- // === Validation ===
75
56
  const validateCommand = lazy('./validate.js', 'validateCommand');
76
57
  const validateFeatureCommand = lazy('../src/commands/validation/validate-feature.js', 'validateFeatureCommand');
77
58
  const verifyCommand = lazy('../src/commands/validation/verify.js', 'verifyCommand');
@@ -80,20 +61,15 @@ const e2eUpCommand = lazy('../src/commands/e2e/e2e.js', 'e2eUpCommand');
80
61
  const e2eStatusCommand = lazy('../src/commands/e2e/e2e.js', 'e2eStatusCommand');
81
62
  const e2eDownCommand = lazy('../src/commands/e2e/e2e.js', 'e2eDownCommand');
82
63
 
83
- // === Scaffolding ===
84
64
  const scaffoldDotnetCommand = lazy('../src/commands/scaffold/scaffold.js', 'scaffoldDotnetCommand');
85
65
  const scaffoldNextjsCommand = lazy('../src/commands/scaffold/scaffold.js', 'scaffoldNextjsCommand');
86
66
 
87
- // === MCP setup ===
88
67
  const mcpSetupCommand = lazy('../src/commands/mcp/mcp-setup.js', 'mcpSetupCommand');
89
68
 
90
- // === Context refresh ===
91
69
  const contextRefreshCommand = lazy('../src/commands/context/context-refresh.js', 'contextRefreshCommand');
92
70
 
93
- // === Dashboard ===
94
71
  const dashboardCommand = lazy('../src/commands/dashboard/dashboard.js', 'dashboardCommand');
95
72
 
96
- // === Observability ===
97
73
  const telemetryCommand = lazy('../src/commands/observability/telemetry.js', 'telemetryCommand');
98
74
  const costCommand = lazy('../src/commands/observability/cost.js', 'costCommand');
99
75
 
@@ -104,9 +80,7 @@ const banner = `${renderLogo(pkg.version)}
104
80
  ${chalk.dim('Spec-driven development harness for Claude Code — by Polymorphism Tech')}
105
81
  `;
106
82
 
107
- // First run after an install/upgrade: show the install banner (npm ≥7 hides
108
- // postinstall output). Skipped for --version/--help (parsed/already-bannered)
109
- // and for non-TTY output — see maybePrintFirstRunBanner.
83
+ // npm >=7 hides postinstall output, so the first run after an install shows the banner.
110
84
  const argvRest = process.argv.slice(2);
111
85
  const skipFirstRun = argvRest.length === 0 ||
112
86
  argvRest.some(a => ['-V', '--version', '-h', '--help'].includes(a));
@@ -120,7 +94,6 @@ program
120
94
  .version(pkg.version)
121
95
  .addHelpText('beforeAll', banner);
122
96
 
123
- // ─── Install ──────────────────────────────────────────────────────────────
124
97
  program
125
98
  .command('init')
126
99
  .description('Initialize MORPH-SPEC in current directory')
@@ -163,7 +136,6 @@ program
163
136
  .option('--reset', 'Remove morph-managed entries from .claude/settings.local.json')
164
137
  .action(doctorCommand);
165
138
 
166
- // ─── Status / inspection ──────────────────────────────────────────────────
167
139
  program
168
140
  .command('status <feature>')
169
141
  .description('Show feature status (phase, gate state, task counts)')
@@ -180,7 +152,6 @@ program
180
152
  .option('--json', 'Output as JSON')
181
153
  .action((options) => listCommand(options));
182
154
 
183
- // ─── Approval gates (dev-only) ────────────────────────────────────────────
184
155
  program
185
156
  .command('approve <feature> <gate>')
186
157
  .description('Approve a phase gate (plan, uiux, review). Enforces gate order (uiux and review require plan)')
@@ -293,7 +264,6 @@ program
293
264
  .option('--here', 'Force building/writing in the current directory, even if another tree owns this feature')
294
265
  .action((feature, options) => handoffCommand(feature, options));
295
266
 
296
- // ─── Codebase graph ───────────────────────────────────────────────────────
297
267
  const graphCommand = program
298
268
  .command('graph')
299
269
  .description('Grafo de codebase (graphify) com saneamento determinístico — fail-open: sem grafo, tudo segue por grep');
@@ -335,7 +305,6 @@ graphCommand
335
305
  .option('--json', 'Output as JSON')
336
306
  .action((symbol, options) => graphExplainCommand(symbol, options));
337
307
 
338
- // ─── Validation ───────────────────────────────────────────────────────────
339
308
  program
340
309
  .command('validate [validator]')
341
310
  .description('Run project validations (all | packages | next-components | spec-tasks)')
@@ -392,7 +361,6 @@ program
392
361
  .option('--json', 'Output as JSON')
393
362
  .action((feature, options) => mutateCommand(feature, options));
394
363
 
395
- // ─── Scaffolding ──────────────────────────────────────────────────────────
396
364
  const scaffoldCmd = program
397
365
  .command('scaffold')
398
366
  .description('Generate feature files from templates');
@@ -414,7 +382,6 @@ scaffoldCmd
414
382
  .option('-v, --verbose', 'Show detailed output')
415
383
  .action(scaffoldNextjsCommand);
416
384
 
417
- // ─── MCP setup ────────────────────────────────────────────────────────────
418
385
  const mcpCommand = program
419
386
  .command('mcp')
420
387
  .description('MCP server setup and configuration');
@@ -426,7 +393,6 @@ mcpCommand
426
393
  .option('--auto', 'Auto-install credential-free MCPs without prompts')
427
394
  .action((name, options) => mcpSetupCommand(name, options));
428
395
 
429
- // ─── Context refresh ──────────────────────────────────────────────────────
430
396
  const contextCommand = program
431
397
  .command('context')
432
398
  .description('Project context management (refresh)');
@@ -439,7 +405,6 @@ contextCommand
439
405
  .option('--json', 'Output scan result as JSON')
440
406
  .action((options) => contextRefreshCommand(options));
441
407
 
442
- // ─── E2E stack (Docker bring-up for runtime verification) ─────────────────
443
408
  const e2eCommand = program
444
409
  .command('e2e')
445
410
  .description("Lifecycle of the feature's verification stack (docker compose)");
@@ -464,7 +429,6 @@ e2eCommand
464
429
  .option('--json', 'Output as JSON')
465
430
  .action((feature, options) => e2eDownCommand(feature, options));
466
431
 
467
- // ─── Heavy nodes (build, tests, e2e) ─────────────────────────────────────
468
432
  const heavyCommand = program
469
433
  .command('heavy')
470
434
  .description('Slots por usuário para os nós pesados (build, testes, e2e), compartilhados entre as sessões');
@@ -481,7 +445,6 @@ heavyCommand
481
445
  .option('--label <label>', 'Nome do que roda, mostrado a quem espera pelo slot')
482
446
  .action((command, options) => heavyRunCommand(command, options));
483
447
 
484
- // ─── Worktree (optional, isolation) ───────────────────────────────────────
485
448
  const worktreeCommand = program
486
449
  .command('worktree')
487
450
  .description('Manage git worktrees for feature isolation');
@@ -493,10 +456,6 @@ worktreeCommand
493
456
  .option('--json', 'Output as JSON (always JSON — accepted so the WorktreeCreate hook can call setup and provision uniformly)')
494
457
  .action((feature, options) => worktreeSetupCommand(feature, options));
495
458
 
496
- // Task isolation — the tree `claude -w`, EnterWorktree and Agent
497
- // isolation:"worktree" ask for when the name is NOT a feature. Same infra as
498
- // setup (junctions, port block, git-invisible manifest, primary-root landing),
499
- // no feature identity. The WorktreeCreate hook is its main caller.
500
459
  worktreeCommand
501
460
  .command('provision <name>')
502
461
  .description('Create a task-isolation worktree at worktrees/{name}/ on branch morph-task/{name} — full morph infra, no feature identity')
@@ -511,10 +470,8 @@ worktreeCommand
511
470
  .option('--all', 'Link all shared dirs, not just node_modules')
512
471
  .action((options) => worktreeLinkCommand(options));
513
472
 
514
- // The SAFE removal — it drops the infra junctions before letting git near the
515
- // directory. Raw `git worktree remove` follows them out and empties the primary
516
- // root's .claude/ and .morph/framework/, so nothing in this repo (message, doc,
517
- // or skill) may point at it; they all point here.
473
+ // Raw `git worktree remove` follows the infra junctions and empties the primary root's .claude/
474
+ // and .morph/framework/: nothing in this repo may point at it, only at this command.
518
475
  worktreeCommand
519
476
  .command('remove [feature]')
520
477
  .description('Safely tear down a worktree (drops infra junctions first, PROVE-or-DECLINE) — does NOT close the feature; that is `finish`')
@@ -525,9 +482,6 @@ worktreeCommand
525
482
  .option('--json', 'Output as JSON (always JSON)')
526
483
  .action((feature, options) => worktreeRemoveCommand(feature, options));
527
484
 
528
- // Sub-agent trees (`agent-<hex>` on `morph-task/agent-<hex>`) outlive the agent: nothing
529
- // tells the harness the agent is done with its worktree. The reaper removes only what it can prove
530
- // is finished and lost-proof; the rest is listed with the reason.
531
485
  worktreeCommand
532
486
  .command('reap')
533
487
  .description('Remove the worktrees and branches of sub-agents that stopped clean (nothing uncommitted, no commit only they hold); everything else is listed with the reason and left alone')
@@ -542,11 +496,6 @@ worktreeCommand
542
496
  .option('--json', 'Output as JSON')
543
497
  .action((options) => worktreeListCommand(options));
544
498
 
545
- // ─── Branch housekeeping ──────────────────────────────────────────────────
546
- // `git branch --merged` cannot see a squash-merge, so the only command left for
547
- // a squash-merged branch is `git branch -D` — indistinguishable from discarding
548
- // real work. `prune` makes the distinction itself and deletes only what it
549
- // proved is already integrated.
550
499
  const branchCommand = program
551
500
  .command('branch')
552
501
  .description('Local branch housekeeping');
@@ -559,7 +508,6 @@ branchCommand
559
508
  .option('--json', 'Output as JSON')
560
509
  .action((options) => branchPruneCommand(options));
561
510
 
562
- // ─── Worktree env (shell-loadable port block) ─────────────────────────────
563
511
  program
564
512
  .command('env [feature]')
565
513
  .description('Print the worktree\'s dedicated environment (port block + COMPOSE_PROJECT_NAME), shell-loadable: eval "$(morph-spec env)" outside Claude Code; feature defaults to the morph/{f} or morph-task/{n} branch of cwd')
@@ -567,14 +515,12 @@ program
567
515
  .option('--powershell', 'Emit $env:K="V" lines instead of POSIX exports')
568
516
  .action((feature, options) => envCommand(feature, options));
569
517
 
570
- // ─── Fleet ────────────────────────────────────────────────────────────────
571
518
  program
572
519
  .command('fleet')
573
520
  .description('Fleet view — every active feature across primary root and worktrees (phase, gates, tasks, ports, handoff, activity)')
574
521
  .option('--json', 'Output as JSON')
575
522
  .action((options) => fleetCommand(options));
576
523
 
577
- // ─── Claims (advisory feature ownership) ──────────────────────────────────
578
524
  program
579
525
  .command('claim [feature]')
580
526
  .description('claim [feature] acquires it (moves this tree\'s previous claim in the same step); no args shows the board (claims are advisory warnings, never locks)')
@@ -584,7 +530,6 @@ program
584
530
  .option('--json', 'Output as JSON')
585
531
  .action((feature, options) => claimCommand(feature, options));
586
532
 
587
- // ─── Standards search (server-side, R2 token cut) ─────────────────────────
588
533
  program
589
534
  .command('standards')
590
535
  .description('Search STANDARDS.json server-side (top 3, digest + anchors) or print one section, instead of reading the whole registry. Bare: categories + counts')
@@ -595,7 +540,6 @@ program
595
540
  .option('--json', 'Output as JSON')
596
541
  .action((options) => standardsCommand(options));
597
542
 
598
- // ─── Sub-agent report protocol ────────────────────────────────────────────
599
543
  program
600
544
  .command('report-check <feature> [slices...]')
601
545
  .description('Audit slice report files (3-implement/reports/{slice}.md) against the work the dispatch actually wrote (telemetry, keyed by the agent that wrote the report). Exits 0 only when every audited slice is intact; naming slices audits only those')
@@ -624,7 +568,6 @@ program
624
568
  .option('--json', 'Output as JSON')
625
569
  .action((feature, options) => stackScanCommand(feature, options));
626
570
 
627
- // ─── Dashboard ────────────────────────────────────────────────────────────
628
571
  program
629
572
  .command('dashboard')
630
573
  .description('Open the morph-spec inspector dashboard')
@@ -632,7 +575,6 @@ program
632
575
  .option('--no-open', 'Don\'t auto-open browser')
633
576
  .action(dashboardCommand);
634
577
 
635
- // ─── Observability ────────────────────────────────────────────────────────
636
578
  program
637
579
  .command('telemetry')
638
580
  .description('Summarize the harness execution path from .morph/logs/events.jsonl (skills, personas, standards read, tool mix, prompts)')
package/bin/validate.js CHANGED
@@ -1,26 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- /**
4
- * Validation CLI
5
- *
6
- * Runs validators for the current project stack (detected from .morph/config/config.json).
7
- *
8
- * .NET stacks: packages
9
- * Next.js stack: next-components
10
- *
11
- * Usage:
12
- * morph-spec validate [options]
13
- * morph-spec validate all
14
- * morph-spec validate next-components (Next.js projects)
15
- * morph-spec validate packages (.NET projects)
16
- *
17
- * MORPH-SPEC 3.0
18
- */
19
-
20
3
  import chalk from 'chalk';
21
4
  import { getStackProfile } from '../src/lib/stack/stack-profile.js';
22
5
 
23
- /** The validators of the current stack: .NET → packages, Next.js → next-components. */
24
6
  async function buildValidators(stack) {
25
7
  const validators = {};
26
8
 
@@ -49,9 +31,6 @@ async function buildValidators(stack) {
49
31
  return validators;
50
32
  }
51
33
 
52
- /**
53
- * Main validation command
54
- */
55
34
  export async function validateCommand(args = []) {
56
35
  const validatorName = args[0] || 'all';
57
36
  const options = parseOptions(args);
@@ -79,9 +58,6 @@ export async function validateCommand(args = []) {
79
58
  }
80
59
  }
81
60
 
82
- /**
83
- * Run all validators
84
- */
85
61
  async function runAllValidators(VALIDATORS, options) {
86
62
  const results = {};
87
63
  let totalErrors = 0;
@@ -101,12 +77,10 @@ async function runAllValidators(VALIDATORS, options) {
101
77
 
102
78
  results[name] = result;
103
79
 
104
- // Count errors/warnings
105
80
  if (result.errors !== undefined) {
106
81
  totalErrors += result.errors;
107
82
  totalWarnings += result.warnings || 0;
108
83
  } else if (result.results) {
109
- // Count issues in results array
110
84
  const issues = result.results.flatMap(r => r.issues || []);
111
85
  totalErrors += issues.filter(i => i.level === 'error').length;
112
86
  totalWarnings += issues.filter(i => i.level === 'warning').length;
@@ -118,7 +92,6 @@ async function runAllValidators(VALIDATORS, options) {
118
92
  }
119
93
  }
120
94
 
121
- // Summary
122
95
  console.log(chalk.bold.cyan('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'));
123
96
  console.log(chalk.bold('📊 Validation Summary\n'));
124
97
 
@@ -135,15 +108,11 @@ async function runAllValidators(VALIDATORS, options) {
135
108
 
136
109
  console.log('');
137
110
 
138
- // Exit with error code if errors found
139
111
  if (totalErrors > 0 && !options.noFail) {
140
112
  process.exit(1);
141
113
  }
142
114
  }
143
115
 
144
- /**
145
- * Run single validator
146
- */
147
116
  async function runValidator(VALIDATORS, name, options) {
148
117
  const validator = VALIDATORS[name];
149
118
 
@@ -152,7 +121,7 @@ async function runValidator(VALIDATORS, name, options) {
152
121
 
153
122
  try {
154
123
  const result = await validator.run('.', {
155
- verbose: true, // Always verbose for single validator
124
+ verbose: true,
156
125
  autoFix: options.autoFix
157
126
  });
158
127
 
@@ -174,9 +143,6 @@ async function runValidator(VALIDATORS, name, options) {
174
143
  }
175
144
  }
176
145
 
177
- /**
178
- * Parse command-line options
179
- */
180
146
  function parseOptions(args) {
181
147
  const options = {
182
148
  verbose: false,
@@ -197,9 +163,6 @@ function parseOptions(args) {
197
163
  return options;
198
164
  }
199
165
 
200
- /**
201
- * Show help
202
- */
203
166
  export function showValidateHelp() {
204
167
  console.log(`
205
168
  ${chalk.bold.cyan('morph-spec validate')} - Run project validations
@@ -234,7 +197,6 @@ ${chalk.bold('INTEGRATION')}
234
197
  `);
235
198
  }
236
199
 
237
- // Run if called directly
238
200
  if (import.meta.url === `file://${process.argv[1]}`) {
239
201
  const args = process.argv.slice(2);
240
202
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "morph-spec",
3
- "version": "9.0.0",
3
+ "version": "9.1.0",
4
4
  "displayName": "MORPH-SPEC Framework",
5
5
  "description": "Spec-driven development with 38 agents and 8-phase workflow for .NET/Blazor/Next.js/Azure",
6
6
  "publisher": "polymorphism-tech",
@@ -185,4 +185,4 @@ Never edited directly — go through CLI commands or `morph-spec update` instead
185
185
 
186
186
  ---
187
187
 
188
- *morph-spec v9.0.0 by Polymorphism Tech*
188
+ *morph-spec v9.1.0 by Polymorphism Tech*
@@ -249,4 +249,4 @@ morph-spec doctor
249
249
 
250
250
  ---
251
251
 
252
- *morph-spec v9.0.0 by Polymorphism Tech*
252
+ *morph-spec v9.1.0 by Polymorphism Tech*
@@ -39,7 +39,7 @@ Prefixo `morph-spec`; flags e porquês em `.morph/framework/CLI.md` (um `###` po
39
39
 
40
40
  ## Slash commands
41
41
 
42
- `/morph-proposal {f}` (plano), `/morph-apply {f}` (execução + Gate 3), `/morph-hotfix {f}`, `/morph-status [f]`.
42
+ `/morph-plan {f}` (plano), `/morph-apply {f}` (execução + Gate 3), `/morph-hotfix {f}`, `/morph-status [f]`.
43
43
 
44
44
  ## Personas (em `.claude/agents/`)
45
45
 
@@ -199,4 +199,4 @@ Relatório ausente não prova que o agente falhou, e relatório presente não pr
199
199
 
200
200
  **Skills core** (`.claude/skills/{nome}/SKILL.md`, invocadas no momento indicado na descrição de cada uma): `morph-plan` (entrada: roteia, varre, entrevista, `plan.md`, gate do plano) · `morph-apply` (fatias → verify → review) · `morph-uiux` · `morph-review` · `morph-hotfix` · `morph-standards` · `morph-media` · `morph-machine`.
201
201
 
202
- `/morph-proposal` → `morph-plan`, `/morph-apply` e `/morph-hotfix` são atalhos da skill. Desvio do passo a passo vai justificado no relatório.
202
+ `/morph-plan` invoca a skill direto; `/morph-apply` e `/morph-hotfix` são atalhos da skill homônima. Desvio do passo a passo vai justificado no relatório.
@@ -242,6 +242,8 @@
242
242
  ],
243
243
  "standards": [
244
244
  "frontend-design-system-naming",
245
+ "frontend-design-system-art-direction",
246
+ "frontend-design-system-premium-finish",
245
247
  "frontend-design-system-animations",
246
248
  "frontend-nextjs-motion-patterns",
247
249
  "architecture-code-comments",
@@ -251,7 +253,6 @@
251
253
  "marketing-site": {
252
254
  "when": "site de marketing: landing page, institucional, campanha — narrativa, conversão, movimento e SEO",
253
255
  "standards": [
254
- "frontend-design-system-premium-finish",
255
256
  "frontend-design-system-ai-image-generation",
256
257
  "frontend-design-system-ai-video-generation",
257
258
  "frontend-scroll-driven-frame-scrub",
@@ -271,6 +272,13 @@
271
272
  "frontend-admin-app-feedback",
272
273
  "frontend-admin-app-page-structure"
273
274
  ]
275
+ },
276
+ "brand-moment": {
277
+ "when": "momento de marca dentro do produto: login e auth, onboarding, primeira tela, estado vazio de destaque, sucesso, vitrine — direção, cena e movimento",
278
+ "standards": [
279
+ "frontend-gsap-core",
280
+ "frontend-gsap-scrolltrigger"
281
+ ]
274
282
  }
275
283
  },
276
284
  "mcp": [
@@ -280,10 +288,10 @@
280
288
  "playwright",
281
289
  "graphify"
282
290
  ],
283
- "model": "sonnet",
291
+ "model": "opus",
284
292
  "maxTurns": 120,
285
- "effort": "medium",
286
- "persona": "Você desenha sistemas, não telas isoladas. Pensa em tokens (cor, espaço, tipografia), componentes reutilizáveis, estados (default/hover/focus/disabled/loading/error), acessibilidade WCAG AA. Mockups em Tailwind direto, sem Figma intermediário. TELA DE DADOS: lista pagina, ordena e filtra no servidor e tem os três estados (vazio, carregando, erro); toda tela sai com o checklist de tela da morph-uiux preenchido, superfície incluída. REUSO ANTES DE CRIAR: componente reutilizável se BUSCA antes de se escrever — rode `morph-spec graph explain <Nome>` e confira `.morph/context/design-system.md` (sem grafo: `grep -rn`); criar um novo exige justificativa em uma linha no relatório da fatia, a mesma regra que já vale para token de design. COMENTÁRIO E TESTE: nenhum comentário, mesmo com vizinho comentado: nome, tipo e teste explicam (pós-condição no nome do teste); só o porquê invisível, sem `///`/JSDoc, id de cenário/fatia ou banner; um teste por pós-condição, cenários do mesmo comportamento em tabela, nenhum teste que só fixa texto."
293
+ "effort": "high",
294
+ "persona": "Você desenha sistemas E telas que alguém lembra. As duas réguas valem juntas: a de sistema (tokens de cor, espaço e tipografia, componentes reutilizáveis, estados default/hover/focus/disabled/loading/error, WCAG AA) e a estética, que é o que separa um design correto de um design aprovado. DIREÇÃO ANTES DE COMPONENTE: antes de qualquer componente, escreva em `1-design/direcao.md` o conceito em uma frase, a metáfora visual, o que torna a tela memorável e o que ela NÃO pode parecer (template shadcn cru, card branco centralizado, lista de ícones genérica). Tela nova ou momento de marca: explore 2 ou 3 direções distintas, recomende uma e justifique — o standard `frontend-design-system-art-direction` é a régua. SKILLS: carregue `frontend-design:frontend-design` sempre; `high-end-visual-design` em momento de marca; `redesign-existing-projects` em tela existente — cada uma só se instalada (a lista de skills da sessão diz); ausente, o standard de direção de arte é a régua e o relatório registra a ausência. CELULAR PRIMEIRO E NATIVO: folha inferior, zona do polegar, alvos de 44px, navegação que o polegar alcança; o celular é desenhado, nunca o desktop empilhado. MOVIMENTO COM INTENÇÃO: a ferramenta mais leve que entrega o efeito (CSS transition e `@keyframes` → animação por scroll em CSS → Framer Motion → GSAP com ScrollTrigger e timeline), orçamento de 60 fps, só `transform` e `opacity`, nada de layout thrash; `prefers-reduced-motion` tem versão estática digna, composta, nunca só a animação desligada. ACABAMENTO: camadas, luz (gradiente radial, trama discreta), vidro com moderação, sombra com a cor do tema, ritmo tipográfico (escala modular, tracking negativo no display), microinteração em foco, hover e envio. PROTÓTIPO E AUTOCRÍTICA: toda tela nova ou alterada vira `1-design/prototipos/{tela}.html` autossuficiente, com os tokens REAIS do projeto lidos do CSS de tokens (o `design-system.md` pode estar velho), desktop e celular lado a lado em moldura de aparelho, com controles animado, estático e pausar. Sirva por HTTP local (o Playwright MCP recusa `file:`), tire print em 1280 e em 390 (`{tela}-1280.png`, `{tela}-390.png` ao lado do HTML), avalie contra as duas réguas (hierarquia, contraste, ritmo, celular, \"parece template?\"), corrija e repita até passar; o relatório lista as rodadas e o que cada uma corrigiu. PROIBIDO: número ou dado inventado em tela real (cena ilustrativa não traz métrica), cópia de marca de terceiros, efeito que quebra contraste AA. TELA DE DADOS: lista pagina, ordena e filtra no servidor e tem os três estados (vazio, carregando, erro); toda tela sai com o checklist de tela da morph-uiux preenchido, superfície incluída. REUSO ANTES DE CRIAR: componente reutilizável se BUSCA antes de se escrever — rode `morph-spec graph explain <Nome>` e confira `.morph/context/design-system.md` (sem grafo: `grep -rn`); criar um novo exige justificativa em uma linha no relatório da fatia, a mesma regra que já vale para token de design. COMENTÁRIO E TESTE: nenhum comentário, mesmo com vizinho comentado: nome, tipo e teste explicam (pós-condição no nome do teste); só o porquê invisível, sem `///`/JSDoc, id de cenário/fatia ou banner; um teste por pós-condição, cenários do mesmo comportamento em tabela, nenhum teste que só fixa texto."
287
295
  },
288
296
  "infra-engineer": {
289
297
  "title": "Infrastructure / Jobs Engineer",
@@ -9,6 +9,6 @@ allowed-tools: Read, Write, Edit, Bash, Glob, Grep, Agent, AskUserQuestion, Skil
9
9
  Atalho: invoque `Skill(morph-apply)` com o nome da feature.
10
10
 
11
11
  Pré-requisito: o gate do plano aprovado, com `.morph/features/{feature}/2-plan/plan.md` e
12
- `2-plan/checks.json` (gravado por `morph-spec plan-check`). Faltando, rode `/morph-proposal {feature}`.
12
+ `2-plan/checks.json` (gravado por `morph-spec plan-check`). Faltando, rode `/morph-plan {feature}`.
13
13
 
14
14
  **Feature:** $ARGUMENTS
@@ -34,7 +34,7 @@ output completion (X/N outputs), slice progress (reports in `3-implement/reports
34
34
  After running the CLI, summarize:
35
35
  - Current phase and which gate (if any) is open
36
36
  - Outstanding outputs for the current phase
37
- - Recommended next slash command (`/morph-proposal`, `/morph-apply`, or a gate approval)
37
+ - Recommended next slash command (`/morph-plan`, `/morph-apply`, or a gate approval)
38
38
 
39
39
  ---
40
40
 
@@ -16,7 +16,7 @@
16
16
 
17
17
  **Exceção `hotfix`:** esse tipo nunca despacha (`morph-hotfix` §7); o Gate 3 exige só `4-review/verifier.md`, escrito pelo orquestrador, e a assinatura humana continua obrigatória via `--approver` (o backstop de `--mode auto` acima permanece recusando).
18
18
 
19
- **No `uiux`, a assinatura `auto` é recusada (exit 1) onde o `gate-check uiux` pausaria pelo checklist de tela** — o mesmo predicado do `advance` (`uiuxChecklistPause`, em `risk-detector.js`), lido mesmo sem gate-check antes. Destravam: uma decisão gravada com `pause: false` (`gate-decision {f} uiux --pause false --reason …`, ou um gate-check que não pausou) e a assinatura humana (`--approver`); `--force` não. A decisão vale para o mockup que viu: ela grava `mockupsHash` (o `mockups.md` por conteúdo), e um mockup escrito ou mudado depois dela volta a ser conferido.
19
+ **No `uiux`, a assinatura `auto` é recusada (exit 1) onde o `gate-check uiux` pausaria pelo checklist de tela ou pelo protótipo** — o mesmo predicado do `advance` (`uiuxChecklistPause`, em `risk-detector.js`), lido mesmo sem gate-check antes. Destravam: uma decisão gravada com `pause: false` (`gate-decision {f} uiux --pause false --reason …`, ou um gate-check que não pausou) e a assinatura humana (`--approver`); `--force` não. A decisão vale para o mockup que viu: ela grava `mockupsHash` (o `mockups.md` por conteúdo), e um mockup escrito ou mudado depois dela volta a ser conferido.
20
20
 
21
21
  **O hook state-sync.js** cobre o caminho manual: `AskUserQuestion` respondida com frase de aprovação (abaixo) → registra o gate no `feature.json` autoritativo com `approvedBy: "manual"`. **A feature é identificada pelo nome que a pergunta cita** — grava na árvore dona dela, nunca na "feature ativa" da sessão. Pergunta sem nome numa árvore com mais de uma feature: o hook **recusa gravar** e avisa — aprove por `morph-spec approve`.
22
22
 
@@ -42,7 +42,7 @@ Um stamp de `verification` com status `fail` (último `morph-spec verify` vermel
42
42
 
43
43
  **Prova de mídia:** do MESMO relatório e pelo MESMO leitor, o `gate-check` grava `signals.mediaClaims = {section, featureGeneratesMedia}`. `featureGeneratesMedia` é determinístico do disco — existe ao menos uma fatia do `checks.json` cujo `standards` cita `ai-agents-modalities-image-gen`, `ai-agents-media-video` ou `ai-agents-media-pipeline` — pelo id de STANDARDS.json ou pelo caminho, com ou sem `framework/`/`standards/` na frente, porque uma grafia não prevista desarmaria o guardrail sem uma linha de erro (`featureGeneratesMedia`, função exportada de `gate-check.js`, é onde essa normalização mora e é testada). Nessa condição, relatório **sem** a seção `## Mídia gerada` **pausa o Gate 3**: as quatro afirmações de mídia (custo, revisão humana, marcação, hot path não bloqueado) não foram provadas (`framework/evals/review-checklist.md`, "Feature que gera mídia").
44
44
 
45
- **Checklist de tela:** na `uiux` e no `review`, o `gate-check` grava `signals.screenChecklist` lido do `1-design/mockups.md` (`mockups`, `legacy`, `screens`, `problems`). Na **uiux**, checklist incompleto **pausa** nomeando a tela e o item, e um mockup sem nenhuma `## Tela:` é o problema "nenhuma tela declarada". No **review**, o que se cobra é o item **devido** — decidido, nem "não se aplica" nem a superfície (`uncovered`): cada um exige uma linha na seção `## Checklist de tela` do `verifier.md`, e a linha que o verificador marca como não verificável conta. Com item devido, relatório sem a seção ou com linha faltando (`section`, `uncovered`) **pausa** o Gate 3 (`evals/review-checklist.md`, "Contrato de tela"); tela toda "não se aplica" não deve nada e não pausa. **Mockup legado** — telas no formato antigo (`## S001: …`) e nenhuma `## Tela:`, o que o template anterior gerava — é **isento nas duas fases**, com a isenção à vista: o sinal grava `exempt: "checklist dispensado: mockup no formato antigo"` e a mesma razão aparece em "risk signals present". Mockup ausente não pausa. `screenChecklist` **não** é sobrescrevível por `--signals`.
45
+ **Checklist de tela:** na `uiux` e no `review`, o `gate-check` grava `signals.screenChecklist` lido do `1-design/mockups.md` (`mockups`, `legacy`, `screens`, `problems`). Na **uiux**, checklist incompleto **pausa** nomeando a tela e o item, e um mockup sem nenhuma `## Tela:` é o problema "nenhuma tela declarada". Com o checklist completo, cada tela ainda deve o **protótipo** (`prototypes`, só na uiux): a linha `**Protótipo:** 1-design/prototipos/<tela>.html` dentro da `## Tela:`, o HTML e os prints `<tela>-1280.png` e `<tela>-390.png` ao lado dele; faltando um, **pausa** nomeando a tela e o arquivo ("protótipo incompleto"), pelo mesmo predicado. No **review**, o que se cobra é o item **devido** — decidido, nem "não se aplica" nem a superfície (`uncovered`): cada um exige uma linha na seção `## Checklist de tela` do `verifier.md`, e a linha que o verificador marca como não verificável conta. Com item devido, relatório sem a seção ou com linha faltando (`section`, `uncovered`) **pausa** o Gate 3 (`evals/review-checklist.md`, "Contrato de tela"); tela toda "não se aplica" não deve nada e não pausa. **Mockup legado** — telas no formato antigo (`## S001: …`) e nenhuma `## Tela:`, o que o template anterior gerava — é **isento nas duas fases**, com a isenção à vista: o sinal grava `exempt: "checklist dispensado: mockup no formato antigo"` e a mesma razão aparece em "risk signals present". Mockup ausente não pausa. `screenChecklist` **não** é sobrescrevível por `--signals`.
46
46
 
47
47
  **Por quê.** Fora do review a regra não vale (pausar o Gate 1/2 numa máquina sem docker travaria planejamento legítimo). Feature que não pina standard de mídia é **isenta automaticamente** — a regra não pede cerimônia de quem não gera mídia. `mediaClaims` **não** é sobrescrevível por `--signals`, pela mesma razão anti-spoof dos demais sinais de disco.
48
48
 
@@ -61,7 +61,7 @@ A tabela é a mesma régua que `shouldPauseGate` aplica e que o `gate-check` imp
61
61
  | `e2eSkipClass` (derivada) | environment/requested/unknown | e2e pulou sem dispensa legítima (só `project`). Só no **ship** |
62
62
  | `promptModel` | prompt/modelo tocado | Sem nó `evals` declarado, ou eval pulado neste verify. Só no **ship** |
63
63
  | `mediaClaims` | seção ausente | Feature que gera mídia, relatório sem `## Mídia gerada`. Só no **ship** |
64
- | `screenChecklist` | item em aberto | **uiux**: tela sem checklist completo, ou nenhuma `## Tela:`. **ship**: item decidido sem linha em `## Checklist de tela` |
64
+ | `screenChecklist` | item em aberto | **uiux**: tela sem checklist completo, nenhuma `## Tela:`, ou tela sem protótipo e prints 1280/390. **ship**: item decidido sem linha em `## Checklist de tela` |
65
65
  | `planChecks` | ≠ `fresh` | `checks.json` ausente ou de outra versão do `plan.md`: rode `plan-check`. Só no **plano**; `approve`/`advance` automáticos recusam |
66
66
  | `sliceCount` | > 12 | Plano grande demais para uma feature |
67
67
  | `workType` | === 'hotfix' | Gate 3 pausa SEMPRE (ver "Gates por tipo de trabalho") |
@@ -268,7 +268,7 @@ Fail-open: uma poda que falha nunca derruba o comando. PROVE-or-DECLINE como o r
268
268
 
269
269
  ### claim
270
270
 
271
- **`morph-spec claim [feature] [--release] [--list] [--all] [--json]`** — posse **advisory** de feature. Cada sessão reclama sua feature ativa automaticamente (hook SessionStart) e renova o heartbeat a cada tool call; o registro vive em `<git-common-dir>/morph-spec/claims.json`, compartilhado por todos os worktrees. **`morph-spec claim <feature>` (sem flags) ADQUIRE** — se esta árvore já tinha claim vivo em outra feature, ele é liberado no mesmo passo (o CLI reporta "movido de X para Y"); é o jeito de trocar de feature no meio da tarefa sem a dança de dois passos `--release` + reclamar. `--list` força a leitura sem adquirir mesmo passando uma feature. **Claims avisam, nunca bloqueiam** — mas se o SessionStart avisar que outra sessão tem claim vivo, **confirme antes de `finish`/`archive`/`delete`**: duas sessões na mesma feature já custaram um recap.md inteiro e um sub-agent (o worktree sumiu debaixo dele). Claim órfão de sessão morta: `morph-spec claim <f> --release`. **O board mostra só claims VIVOS** (dentro do TTL de 30 min): um claim morto não avisa mais nada, e deixá-lo listado transformava o quadro em ruído (features encerradas há 20h e 73h ainda aparecendo). `--all` mostra o registro inteiro; a contagem dos omitidos sai no rodapé, nunca em silêncio.
271
+ **`morph-spec claim [feature] [--release] [--list] [--all] [--json]`** — posse **advisory** de feature. Cada sessão reclama sua feature ativa automaticamente (hook SessionStart) e renova o heartbeat a cada tool call; o registro vive em `<git-common-dir>/morph-spec/claims.json`, compartilhado por todos os worktrees. **`morph-spec claim <feature>` (sem flags) ADQUIRE** — se esta árvore já tinha claim vivo em outra feature, ele é liberado no mesmo passo (o CLI reporta "movido de X para Y"); é o jeito de trocar de feature no meio da tarefa sem a dança de dois passos `--release` + reclamar. `--list` força a leitura sem adquirir mesmo passando uma feature. **Claims avisam, nunca bloqueiam** — mas se o SessionStart avisar que outra sessão tem claim vivo, **confirme antes de `finish`/`archive`/`delete`**: duas sessões na mesma feature já custaram o trabalho de uma fatia e um sub-agent (o worktree sumiu debaixo dele). Claim órfão de sessão morta: `morph-spec claim <f> --release`. **O board mostra só claims VIVOS** (dentro do TTL de 30 min): um claim morto não avisa mais nada, e deixá-lo listado transformava o quadro em ruído (features encerradas há 20h e 73h ainda aparecendo). `--all` mostra o registro inteiro; a contagem dos omitidos sai no rodapé, nunca em silêncio.
272
272
 
273
273
  ## Validação
274
274
 
@@ -735,7 +735,7 @@ Falhas do `--show` saem 1: id inexistente (`Standard "<id>" não existe.` com at
735
735
  **`--dry-run` prevê sem tocar em nada.** Previsão e execução são o **mesmo percurso**, com os **mesmos filtros** e o **mesmo coletor de efeitos**: em modo normal cada verbo executa *e* registra, em dry apenas registra.
736
736
 
737
737
  O relatório agrupa por natureza do efeito (apagar, criar diretório, copiar, escrever, mesclar, executar, índice do git) e **nomeia separadamente três grupos que ninguém adivinha da palavra "update"**:
738
- - **apagados por inteiro antes da reinstalação** — `.claude/{commands,rules,skills,agents}` e `.morph/{framework/standards,framework/hooks,framework/schemas,framework/rubrics,framework/evals,config}`, com a contagem de arquivos que hoje moram em cada um (`framework/rubrics` não é mais instalado: entra na lista só para sumir de instalações antigas);
738
+ - **apagados por inteiro antes da reinstalação** — `.claude/{commands,rules,skills,agents}` e `.morph/{framework/standards,framework/hooks,framework/schemas,framework/evals,config}`, com a contagem de arquivos que hoje moram em cada um;
739
739
  - **fora do projeto** — `~/.claude/statusline.sh`, `~/.claude/statusline.py` e a mesclagem de `~/.claude/settings.json`;
740
740
  - **dentro do pacote da CLI** — `generate-refs.js` escrevendo `framework/hooks/shared/phase-utils.js` do pacote, que num `npm link` de desenvolvimento é o próprio repositório do framework. Em dry roda a variante `--check`, que verifica e não escreve.
741
741
 
@@ -743,17 +743,6 @@ O `--dry-run` **passa por cima** da saída antecipada de "CLI desatualizada": bl
743
743
 
744
744
  **Freio de major.** Um salto de **dois majors ou mais** é recusado sem `--force`, **antes de qualquer mutação** — recusar depois de mutar é meio-estado. A versão instalada vem de `.morph/.morphversion → morphVersion`, o mesmo registro que o `update` já lê; **nunca** de `config.json → frameworkVersion`, que o `update` escreve e jamais lê para decidir (medido: os dois divergem por um major inteiro num projeto real). Quando os dois discordam, a mensagem imprime **os dois** e diz qual decidiu — escolher em silêncio é acertar metade das vezes e nunca saber qual metade. `.morphversion` ausente ou ilegível é tratado como salto grande, com motivo próprio (`versão instalada indeterminável`) distinto do salto medido: "não sei quão velho isto é" é precisamente quando sobrescrever às cegas é mais perigoso. `--force` dispensa o freio e o relatório final **registra a dispensa**. `--dry-run` combinado com uma recusa **imprime o relatório**, com a recusa como primeiro item.
745
745
 
746
- **Feature em voo no formato anterior.** Antes de qualquer mutação, o `update` varre `.morph/features/` da raiz e de cada worktree que o `git worktree list` conhece; uma feature não encerrada (`status` diferente de `completed`/`abandoned`) com `2-plan/tasks.json` ou `0-proposal/` e sem `2-plan/plan.md` é do formato que esta versão não conduz, e o `update` recusa (exit 1, nada escrito):
747
-
748
- ```
749
- Recusado: N feature(s) em voo no formato anterior ao plan.md (proposal/spec/tasks.json), que esta versão não conduz:
750
- - <feature> (raiz | <caminho da worktree>)
751
- Termine cada uma na 8.47: `npx @polymorphism-tech/morph-spec@8.47 <comando>` (por exemplo `finish <feature> --pr`),
752
- ou arquive sem integrar: `morph-spec archive <feature> --force` (o Gate 3 dela não foi aprovado). Depois rode o `update` de novo.
753
- ```
754
-
755
- `--force` **não** dispensa esta recusa (o freio de major, sim): a CLI nova não sabe conduzir essas features. Feature em `.morph/archive/` não conta. `--dry-run` põe as mesmas linhas no topo da previsão. A mesma regra roda no `init --force` e no `setup-infra` (inclusive `--reinstall`), que sobrescrevem `.morph/` e `.claude/` sem passar pelo `update`: recusam com as mesmas linhas e saem 1. No retorno programático, `{ refused: true, reason: 'old-format-features', features }`.
756
-
757
746
  **Por quê.** Não há travessia paralela — o resumo de uma execução real também sai do coletor, de modo que um ponto de emissão esquecido some das duas saídas ao mesmo tempo, em vez de mentir só no `--dry-run`.
758
747
 
759
748
  ## Grafo de codebase
@@ -810,7 +799,7 @@ O servidor MCP (`graphify-mcp`, 10 tools, todas aceitando `project_path`) está
810
799
 
811
800
  ### cost
812
801
 
813
- **`morph-spec cost [feature] [--by phase] [--all-trees] [--json]`** — custo da execução a partir do mesmo `events.jsonl`: bytes de contexto lidos por tipo (`rubric`/`standard`/`skill`/`agents`/`plan-artifact`/`code` — a janela `offset`/`limit` que o Read trouxe, quando o evento a tem), dispatches + tamanho de prompt e mix de tools. Bytes são **proxy determinística** de custo de token; os tokens reais vêm à parte: `SessionUsage` (sessão principal) e `AgentUsage` (cada sub-agent, lido do transcript dele), somados **só pelo `delta`** de cada amostra — o total de topo é acumulado e se repete a cada Stop, e amostra antiga sem `delta` fica fora da soma e é contada como legada. `--all-trees` agrega **toda árvore git** com log, mais os logs que o `finish` guardou em `.git/morph-spec/finish-backup/` antes de desmontar a worktree, deduplicados por `eventId`.
802
+ **`morph-spec cost [feature] [--by phase] [--all-trees] [--json]`** — custo da execução a partir do mesmo `events.jsonl`: bytes de contexto lidos por tipo (`checklist`/`standard`/`skill`/`agents`/`plan-artifact`/`code` — a janela `offset`/`limit` que o Read trouxe, quando o evento a tem), dispatches + tamanho de prompt e mix de tools. Bytes são **proxy determinística** de custo de token; os tokens reais vêm à parte: `SessionUsage` (sessão principal) e `AgentUsage` (cada sub-agent, lido do transcript dele), somados **só pelo `delta`** de cada amostra — o total de topo é acumulado e se repete a cada Stop, e amostra antiga sem `delta` fica fora da soma e é contada como legada. `--all-trees` agrega **toda árvore git** com log, mais os logs que o `finish` guardou em `.git/morph-spec/finish-backup/` antes de desmontar a worktree, deduplicados por `eventId`.
814
803
 
815
804
  ### cost --metrics
816
805