@polymorphism-tech/morph-spec 9.0.0 → 9.2.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 (345) hide show
  1. package/CLAUDE.md +8 -9
  2. package/README.md +38 -36
  3. package/bin/morph-spec.js +11 -63
  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 +2 -1
  9. package/framework/MORPH.md +3 -3
  10. package/framework/agents.json +19 -11
  11. package/framework/commands/morph-apply.md +1 -1
  12. package/framework/commands/morph-status.md +1 -1
  13. package/framework/docs/CLI.md +22 -31
  14. package/framework/evals/review-checklist.md +12 -2
  15. package/framework/hooks/README.md +8 -44
  16. package/framework/hooks/claude-code/core/block-destructive-worktree-removal.js +6 -49
  17. package/framework/hooks/claude-code/core/block-raw-worktree-add.js +2 -35
  18. package/framework/hooks/claude-code/core/chain.js +4 -65
  19. package/framework/hooks/claude-code/core/comment-guard.js +2 -16
  20. package/framework/hooks/claude-code/core/enforce-phase-writes.js +6 -50
  21. package/framework/hooks/claude-code/core/gate-guard.js +7 -67
  22. package/framework/hooks/claude-code/core/graph-refresh-kick.js +3 -24
  23. package/framework/hooks/claude-code/core/heavy-gate.js +3 -21
  24. package/framework/hooks/claude-code/core/heavy-release.js +2 -13
  25. package/framework/hooks/claude-code/core/loop-detect.js +2 -31
  26. package/framework/hooks/claude-code/core/pre-bash-denylist.js +0 -4
  27. package/framework/hooks/claude-code/core/protect-spec-files.js +7 -67
  28. package/framework/hooks/claude-code/core/state-sync.js +12 -68
  29. package/framework/hooks/claude-code/core/telemetry-log.js +12 -93
  30. package/framework/hooks/claude-code/core/validate-completion.js +11 -57
  31. package/framework/hooks/claude-code/core/warn-bash-source-write.js +1 -9
  32. package/framework/hooks/claude-code/core/worktree-context.js +10 -110
  33. package/framework/hooks/claude-code/core/worktree-create.js +6 -70
  34. package/framework/hooks/claude-code/core/worktree-env-inject.js +5 -56
  35. package/framework/hooks/claude-code/core/worktree-remove.js +5 -31
  36. package/framework/hooks/claude-code/statusline.sh +11 -11
  37. package/framework/hooks/shared/activity-logger.js +9 -89
  38. package/framework/hooks/shared/agent-reap.js +2 -17
  39. package/framework/hooks/shared/build-check.js +6 -75
  40. package/framework/hooks/shared/claim-registry.js +9 -119
  41. package/framework/hooks/shared/command-tokens.js +6 -51
  42. package/framework/hooks/shared/comment-rules.js +5 -20
  43. package/framework/hooks/shared/comment-scanner.js +6 -25
  44. package/framework/hooks/shared/comment-stripper.js +11 -85
  45. package/framework/hooks/shared/e2e-check.js +0 -0
  46. package/framework/hooks/shared/errata.js +2 -15
  47. package/framework/hooks/shared/feature-locator.js +11 -95
  48. package/framework/hooks/shared/frontend-locations.js +1 -3
  49. package/framework/hooks/shared/gate-question.js +1 -7
  50. package/framework/hooks/shared/git-exclude.js +3 -20
  51. package/framework/hooks/shared/git-paths.js +8 -104
  52. package/framework/hooks/shared/graph-freshness.js +22 -166
  53. package/framework/hooks/shared/graph-refresh.js +21 -149
  54. package/framework/hooks/shared/heavy-command.js +4 -12
  55. package/framework/hooks/shared/hook-response.js +8 -83
  56. package/framework/hooks/shared/morph-cli.js +8 -52
  57. package/framework/hooks/shared/payload-utils.js +10 -132
  58. package/framework/hooks/shared/phase-utils.js +1 -42
  59. package/framework/hooks/shared/redact-secrets.js +4 -15
  60. package/framework/hooks/shared/reparse-scan.js +6 -66
  61. package/framework/hooks/shared/slice-progress.js +4 -23
  62. package/framework/hooks/shared/source-files.js +4 -17
  63. package/framework/hooks/shared/state-reader.js +13 -183
  64. package/framework/hooks/shared/state-writer.js +8 -52
  65. package/framework/hooks/shared/stdin-reader.js +1 -11
  66. package/framework/hooks/shared/telemetry-logger.js +7 -67
  67. package/framework/hooks/shared/transcript-usage.js +7 -29
  68. package/framework/hooks/shared/worktree-root.js +7 -29
  69. package/framework/rules/csharp-standards.md +1 -1
  70. package/framework/rules/frontend-standards.md +1 -0
  71. package/framework/rules/hangfire-standards.md +1 -1
  72. package/framework/rules/neon-standards.md +1 -1
  73. package/framework/rules/nextjs-standards.md +1 -1
  74. package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
  75. package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +1 -1
  76. package/framework/skills/core/morph-apply/SKILL.md +4 -4
  77. package/framework/skills/core/morph-hotfix/SKILL.md +3 -3
  78. package/framework/skills/core/morph-machine/SKILL.md +1 -1
  79. package/framework/skills/core/morph-media/SKILL.md +1 -1
  80. package/framework/skills/core/morph-plan/SKILL.md +9 -7
  81. package/framework/skills/core/morph-review/SKILL.md +9 -6
  82. package/framework/skills/core/morph-standards/SKILL.md +1 -1
  83. package/framework/skills/core/morph-uiux/SKILL.md +29 -12
  84. package/framework/standards/STANDARDS.json +36 -14
  85. package/framework/standards/STANDARDS.meta.json +16 -2
  86. package/framework/standards/ai-agents/agent-archetypes.md +2 -2
  87. package/framework/standards/ai-agents/agent-session.md +1 -1
  88. package/framework/standards/ai-agents/conversational-agent-with-phases.md +4 -4
  89. package/framework/standards/ai-agents/durable-workflows-hitl.md +3 -3
  90. package/framework/standards/ai-agents/guardrails.md +1 -1
  91. package/framework/standards/ai-agents/multi-agent-patterns.md +2 -2
  92. package/framework/standards/ai-agents/observability-patterns.md +1 -1
  93. package/framework/standards/ai-agents/production.md +1 -1
  94. package/framework/standards/ai-agents/prompt-sources.md +2 -2
  95. package/framework/standards/ai-agents/providers/model-registry.md +1 -1
  96. package/framework/standards/ai-agents/rag-custom-pgvector.md +2 -2
  97. package/framework/standards/ai-agents/setup.md +2 -2
  98. package/framework/standards/ai-agents/sweet-spot.md +2 -2
  99. package/framework/standards/ai-agents/tool-adapters.md +0 -2
  100. package/framework/standards/ai-agents/vector-data-extensions.md +4 -4
  101. package/framework/standards/ai-agents/workflows.md +1 -1
  102. package/framework/standards/architecture/code-comments.md +1 -1
  103. package/framework/standards/architecture/vertical-slice/vertical-slice.md +1 -1
  104. package/framework/standards/backend/api/validation.md +1 -1
  105. package/framework/standards/backend/dotnet/testing.md +10 -4
  106. package/framework/standards/backend/dotnet/vsa-handler-patterns.md +5 -5
  107. package/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +1 -1
  108. package/framework/standards/backend/integrations/neon-auth/neon-auth.md +2 -2
  109. package/framework/standards/data/nosql/cache/redis.md +1 -1
  110. package/framework/standards/data/nosql/cosmos-db.md +3 -3
  111. package/framework/standards/frontend/admin-app/forms.md +1 -1
  112. package/framework/standards/frontend/design-system/art-direction.md +88 -0
  113. package/framework/standards/frontend/design-system/premium-finish.md +77 -2
  114. package/framework/standards/frontend/nextjs/testing.md +10 -6
  115. package/framework/standards/infrastructure/neon/neon-pgvector.md +5 -5
  116. package/framework/templates/.idea/morph-templates.xml +92 -0
  117. package/framework/templates/.vscode/morph-templates.code-snippets +186 -0
  118. package/framework/templates/CLAUDE.md.core.template +3 -3
  119. package/framework/templates/IDE-SNIPPETS.md +262 -262
  120. package/framework/templates/REGISTRY.json +9 -9
  121. package/framework/templates/code/dotnet/abstractions/api-endpoint.cs +7 -7
  122. package/framework/templates/code/dotnet/feature/request.cs.hbs +4 -4
  123. package/framework/templates/code/dotnet/feature/response.cs.hbs +4 -4
  124. package/framework/templates/code/sql/ai-agents/pgvector-embeddings-migration.sql.template +91 -91
  125. package/framework/templates/docs/plan.md +3 -1
  126. package/framework/templates/docs/ui-mockups.md +4 -0
  127. package/framework/templates/frontend/nextjs/client-component.tsx.hbs +26 -26
  128. package/framework/templates/frontend/nextjs/feature-form.tsx.hbs +56 -56
  129. package/framework/templates/frontend/nextjs/tsconfig.json.hbs +26 -26
  130. package/framework/templates/infrastructure/docker/Dockerfile.template +58 -58
  131. package/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -38
  132. package/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -48
  133. package/framework/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +45 -45
  134. package/framework/templates/infrastructure/github/actions/health-check/action.yml.hbs +27 -27
  135. package/framework/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +59 -59
  136. package/framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +39 -39
  137. package/framework/templates/meta-prompts/fusion/fusion-agent.md +76 -76
  138. package/framework/templates/meta-prompts/fusion/fusion-aggregator.md +100 -100
  139. package/framework/templates/state.template.json +17 -17
  140. package/framework/templates/ui/design-system.css +226 -226
  141. package/package.json +1 -1
  142. package/src/commands/context/context-refresh.js +0 -16
  143. package/src/commands/dashboard/dashboard.js +2 -8
  144. package/src/commands/e2e/e2e.js +17 -104
  145. package/src/commands/graph/affected.js +0 -14
  146. package/src/commands/graph/build.js +11 -50
  147. package/src/commands/graph/explain.js +0 -16
  148. package/src/commands/graph/status.js +1 -12
  149. package/src/commands/mcp/mcp-setup.js +4 -62
  150. package/src/commands/observability/cost.js +5 -57
  151. package/src/commands/observability/telemetry.js +1 -14
  152. package/src/commands/project/branch.js +4 -45
  153. package/src/commands/project/claim.js +4 -48
  154. package/src/commands/project/doctor.js +48 -302
  155. package/src/commands/project/env.js +1 -27
  156. package/src/commands/project/fleet.js +3 -32
  157. package/src/commands/project/init.js +4 -68
  158. package/src/commands/project/install-plugin-cmd.js +0 -1
  159. package/src/commands/project/standards.js +1 -62
  160. package/src/commands/project/status.js +0 -53
  161. package/src/commands/project/update.js +31 -239
  162. package/src/commands/project/worktree.js +108 -882
  163. package/src/commands/scaffold/scaffold.js +0 -25
  164. package/src/commands/state/advance.js +14 -85
  165. package/src/commands/state/approve.js +15 -97
  166. package/src/commands/state/archive.js +12 -64
  167. package/src/commands/state/auto-approval.js +2 -5
  168. package/src/commands/state/create.js +22 -109
  169. package/src/commands/state/delete.js +11 -63
  170. package/src/commands/state/finish.js +98 -475
  171. package/src/commands/state/gate-check.js +22 -132
  172. package/src/commands/state/gate-decision.js +3 -39
  173. package/src/commands/state/handoff.js +3 -30
  174. package/src/commands/state/list.js +14 -84
  175. package/src/commands/state/report-check.js +8 -58
  176. package/src/commands/state/retype.js +4 -26
  177. package/src/commands/validation/index.js +0 -3
  178. package/src/commands/validation/mutate.js +11 -11
  179. package/src/commands/validation/plan-check.js +4 -2
  180. package/src/commands/validation/tests-audit.js +7 -0
  181. package/src/commands/validation/validate-feature.js +10 -97
  182. package/src/commands/validation/verify.js +30 -113
  183. package/src/core/paths/output-schema.js +2 -101
  184. package/src/core/state/feature-identity.js +1 -25
  185. package/src/core/state/gate-order.js +0 -27
  186. package/src/core/state/lifecycle-audit.js +8 -100
  187. package/src/core/state/state-manager.js +22 -304
  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 +0 -1
  191. package/src/core/work-types.js +1 -36
  192. package/src/dashboard/app/App.jsx +1 -8
  193. package/src/dashboard/app/components/ActivityFeed.jsx +0 -5
  194. package/src/dashboard/app/components/CommandPalette.jsx +0 -7
  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 +1 -5
  207. package/src/dashboard/app/lib/project.js +0 -12
  208. package/src/dashboard/app/main.jsx +13 -13
  209. package/src/dashboard/app/pages/AgentMap.jsx +1 -8
  210. package/src/dashboard/app/pages/FeatureDetail.jsx +1 -5
  211. package/src/dashboard/app/pages/Features.jsx +1 -8
  212. package/src/dashboard/app/pages/Guide.jsx +0 -1
  213. package/src/dashboard/app/pages/HookInspector.jsx +2 -23
  214. package/src/dashboard/app/pages/PhasePipeline.jsx +0 -3
  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 +10 -69
  220. package/src/dashboard/scanner/agents-scanner.js +1 -23
  221. package/src/dashboard/scanner/docs-scanner.js +0 -6
  222. package/src/dashboard/scanner/feature-status.js +2 -5
  223. package/src/dashboard/scanner/features-scanner.js +10 -66
  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 +2 -6
  231. package/src/dashboard/vite-plugin-morph-data.js +5 -19
  232. package/src/dashboard/vite.config.js +24 -24
  233. package/src/lib/ai/ai-checks.js +7 -52
  234. package/src/lib/ai/ai-project-scan.js +14 -108
  235. package/src/lib/ai/code-audit.js +7 -63
  236. package/src/lib/ai/pin-drift.js +8 -51
  237. package/src/lib/ai/registry-audit.js +11 -90
  238. package/src/lib/ci/ci-verify.js +4 -19
  239. package/src/lib/ci/github-ci.js +9 -37
  240. package/src/lib/ci/workflow-scaffold.js +14 -10
  241. package/src/lib/detectors/claude-config-detector.js +13 -74
  242. package/src/lib/detectors/index.js +4 -50
  243. package/src/lib/e2e/applicability.js +37 -0
  244. package/src/lib/e2e/compose-env.js +5 -66
  245. package/src/lib/e2e/stack-teardown.js +6 -40
  246. package/src/lib/generators/architecture-scanner.js +18 -156
  247. package/src/lib/generators/handoff-generator.js +9 -53
  248. package/src/lib/generators/scaffold-generator.js +5 -101
  249. package/src/lib/generators/settings-generator.js +4 -37
  250. package/src/lib/git/branch-classifier.js +11 -84
  251. package/src/lib/git/default-branch.js +14 -169
  252. package/src/lib/git/evidence-staleness.js +1 -0
  253. package/src/lib/git/gh.js +2 -17
  254. package/src/lib/git/pending-prs.js +6 -37
  255. package/src/lib/git/pr-files.js +3 -28
  256. package/src/lib/git/pr-index.js +3 -34
  257. package/src/lib/git/tree-fingerprint.js +3 -15
  258. package/src/lib/git/tree-state.js +6 -33
  259. package/src/lib/graph/god-nodes.js +2 -22
  260. package/src/lib/graph/graph-health.js +3 -24
  261. package/src/lib/graph/graph-loader.js +5 -56
  262. package/src/lib/graph/graphify-runtime.js +7 -37
  263. package/src/lib/graph/graphifyignore.js +8 -74
  264. package/src/lib/graph/sanitize.js +16 -136
  265. package/src/lib/heavy/cleanup.js +1 -1
  266. package/src/lib/installers/effects.js +8 -93
  267. package/src/lib/installers/mcp-installer.js +9 -169
  268. package/src/lib/installers/memory-installer.js +4 -27
  269. package/src/lib/installers/templates-reconcile.js +5 -60
  270. package/src/lib/mutation/adapters.js +6 -17
  271. package/src/lib/mutation/dotnet-introspection.js +20 -106
  272. package/src/lib/mutation/runner.js +23 -75
  273. package/src/lib/mutation/subset.js +1 -4
  274. package/src/lib/mutation/trx.js +0 -1
  275. package/src/lib/plan/artifact-vocabulary.js +5 -25
  276. package/src/lib/plan/checks.js +34 -33
  277. package/src/lib/plan/plan-parser.js +7 -8
  278. package/src/lib/projects/registry.js +7 -44
  279. package/src/lib/review-reports.js +11 -26
  280. package/src/lib/risk-detector.js +41 -173
  281. package/src/lib/specs/adr-index.js +6 -34
  282. package/src/lib/specs/frontmatter.js +2 -15
  283. package/src/lib/specs/gfm-table.js +1 -7
  284. package/src/lib/specs/revocations.js +1 -14
  285. package/src/lib/specs/screen-checklist.js +47 -124
  286. package/src/lib/stack/dotnet-build-ignores.js +2 -6
  287. package/src/lib/stack/stack-profile.js +1 -28
  288. package/src/lib/stack/stack-scan.js +1 -8
  289. package/src/lib/stack-filter.js +4 -27
  290. package/src/lib/standards/registry.js +1 -7
  291. package/src/lib/standards/sections.js +2 -13
  292. package/src/lib/standards/verified-against.js +19 -191
  293. package/src/lib/tasks/eval-node.js +21 -169
  294. package/src/lib/tasks/linux-runner.js +18 -142
  295. package/src/lib/tasks/test-nodes.js +43 -240
  296. package/src/lib/tasks/test-runner.js +43 -341
  297. package/src/lib/telemetry/metrics.js +7 -36
  298. package/src/lib/telemetry/telemetry-reader.js +13 -125
  299. package/src/lib/telemetry/verify-event.js +2 -30
  300. package/src/lib/tests-audit/audit.js +96 -0
  301. package/src/lib/validators/code-budget/code-budget-validator.js +4 -44
  302. package/src/lib/validators/code-budget/index.js +0 -7
  303. package/src/lib/validators/contracts/contract-compliance-validator.js +2 -24
  304. package/src/lib/validators/contracts/index.js +0 -6
  305. package/src/lib/validators/nextjs/index.js +0 -5
  306. package/src/lib/validators/nextjs/next-component-validator.js +4 -81
  307. package/src/lib/validators/packages/index.js +0 -6
  308. package/src/lib/validators/packages/package-validator.js +6 -56
  309. package/src/lib/validators/reuse/index.js +0 -8
  310. package/src/lib/validators/reuse/reuse-validator.js +11 -101
  311. package/src/lib/validators/reuse/symbol-scanner.js +6 -62
  312. package/src/lib/validators/traceability-check.js +5 -63
  313. package/src/lib/validators/validation-runner.js +21 -158
  314. package/src/lib/validators/verify-runner.js +85 -376
  315. package/src/lib/work-type-detector.js +5 -67
  316. package/src/lib/worktree/docker-audit.js +17 -136
  317. package/src/lib/worktree/env-allocator.js +10 -98
  318. package/src/lib/worktree/feature-truth.js +12 -115
  319. package/src/lib/worktree/finish-backup.js +32 -242
  320. package/src/lib/worktree/fleet-scanner.js +13 -95
  321. package/src/lib/worktree/ignored-triage.js +15 -91
  322. package/src/lib/worktree/vscode-settings.js +2 -3
  323. package/src/lib/worktree/worktree-audit.js +21 -213
  324. package/src/lib/worktree/worktree-include.js +3 -5
  325. package/src/scripts/global-install.js +3 -9
  326. package/src/scripts/install-plugin.js +1 -13
  327. package/src/scripts/setup-infra.js +17 -147
  328. package/src/utils/agents-installer.js +29 -276
  329. package/src/utils/banner.js +4 -25
  330. package/src/utils/claude-md-injector.js +1 -37
  331. package/src/utils/claude-settings-manager.js +1 -52
  332. package/src/utils/file-copier.js +11 -95
  333. package/src/utils/hooks-installer.js +21 -298
  334. package/src/utils/skills-installer.js +4 -101
  335. package/src/utils/version-checker.js +4 -83
  336. package/framework/commands/morph-proposal.md +0 -9
  337. package/framework/hooks/git/commit-msg/conventional-commits.sh +0 -33
  338. package/framework/hooks/git/pre-commit/agents.sh +0 -25
  339. package/framework/hooks/git/pre-commit/orchestrator.sh +0 -64
  340. package/framework/hooks/git/pre-push/run-tests.sh +0 -44
  341. package/src/commands/utils/index.js +0 -3
  342. package/src/lib/detectors/design-system-detector.js +0 -188
  343. package/src/lib/generators/design-system-generator.js +0 -508
  344. package/src/lib/specs/old-format.js +0 -68
  345. package/src/utils/agent-id-mapper.js +0 -11
@@ -1,32 +1,5 @@
1
- /**
2
- * `morph-spec cost [feature] [--by phase] [--all-trees] [--metrics [--top n]] [--json]`
3
- *
4
- * A cost-facing view over the same harness event stream `telemetry` reads
5
- * (.morph/logs/events.jsonl): how many context bytes were re-ingested (grouped by kind: rubric/standard/skill/agents/plan-artifact/
6
- * code), and how many sub-agent dispatches happened (with total prompt
7
- * chars). When the stream has `SessionUsage` events (real, hook-observed
8
- * token counts), those are summed and shown too — see the sessionUsage
9
- * caveat below.
10
- *
11
- * IMPORTANT: bytes re-ingested is a DETERMINISTIC PROXY for cost, not a
12
- * token count. Hooks only see what tools read off disk — never the model's
13
- * actual token usage — so this measures re-ingestion pressure, not spend.
14
- * `sessionUsage` (when present) is the exception: real tokens, observed
15
- * directly, not a proxy — see aggregateCost's docstring for the contract.
16
- *
17
- * `--all-trees` widens the source from "just the current tree" to every git
18
- * worktree that has its own events.jsonl plus the logs `finish` saved before
19
- * removing a worktree, deduplicated by eventId.
20
- *
21
- * `--metrics` measures the loop instead: turns, tool calls by orchestrator and
22
- * sub-agent, time per command class, identical reruns and why, rereads, how
23
- * many verifies each feature ran, git calls and whether
24
- * the reuse validator ran in root and worktree (see lib/telemetry/metrics.js).
25
- *
26
- * Read-only, always exits 0 on a normal (even empty) run — fail-open, an
27
- * empty stream is an answer, not an error. Only `--by` with an unknown value
28
- * is a usage error (exit 1).
29
- */
1
+ // Bytes re-ingested is a deterministic proxy for cost, not a token count: hooks only see what
2
+ // tools read off disk. `sessionUsage` is the exception, real hook-observed tokens.
30
3
 
31
4
  import chalk from 'chalk';
32
5
  import { loadTelemetry, loadTelemetryAllTrees, aggregateCost, dedupeEvents } from '../../lib/telemetry/telemetry-reader.js';
@@ -79,10 +52,6 @@ function tokenLine(u) {
79
52
  + `cacheRead=${u.cacheReadTokens} cacheCreation=${u.cacheCreationTokens}`;
80
53
  }
81
54
 
82
- /**
83
- * Real (hook-observed) token counts — the non-proxy sibling of the bytes
84
- * above: the main sessions and, separately, the sub-agents.
85
- */
86
55
  function printSessionUsage(summary) {
87
56
  const { sessionUsage, agentUsage, sessionUsageLegacySamples } = summary;
88
57
  if (sessionUsage) {
@@ -178,10 +147,6 @@ function printMetricsBody(m) {
178
147
  for (const [reason, n] of Object.entries(m.reuse.skipReasons)) console.log(chalk.gray(` pulou ${n}×: ${reason}`));
179
148
  }
180
149
 
181
- /**
182
- * `--metrics`: the loop measurements over the current tree (and, with
183
- * `--all-trees`, every tree plus the finish backups, deduplicated).
184
- */
185
150
  function printMetrics(feature, options, cwd) {
186
151
  const events = options.allTrees
187
152
  ? dedupeEvents(loadTelemetryAllTrees(cwd).flatMap((t) => t.events))
@@ -202,16 +167,6 @@ function printMetrics(feature, options, cwd) {
202
167
  printMetricsBody(metrics);
203
168
  }
204
169
 
205
- /**
206
- * `--all-trees` rendering: a short line per tree (so a fleet operator can
207
- * spot which tree is expensive) followed by the COMBINED aggregate — full
208
- * detail (the phase breakdown honors `--by` here too, same as the
209
- * single-tree path; a typeable flag combination is never a silent no-op).
210
- *
211
- * @param {string} [feature]
212
- * @param {{ json?: boolean, by?: 'phase' }} options
213
- * @param {string} cwd
214
- */
215
170
  function printAllTrees(feature, options, cwd) {
216
171
  const treesData = loadTelemetryAllTrees(cwd);
217
172
  const perTree = treesData.map(({ tree, path, events }) => ({
@@ -254,10 +209,6 @@ function printAllTrees(feature, options, cwd) {
254
209
  }
255
210
  }
256
211
 
257
- /**
258
- * @param {string} [feature] - narrow to a single feature
259
- * @param {{ json?: boolean, by?: 'phase', allTrees?: boolean, cwd?: string }} [options]
260
- */
261
212
  export function costCommand(feature, options = {}) {
262
213
  if (options.by && !BY_MODES.includes(options.by)) {
263
214
  console.error(chalk.red(`\n❌ Invalid --by: "${options.by}"`));
@@ -274,8 +225,7 @@ export function costCommand(feature, options = {}) {
274
225
  }
275
226
 
276
227
  if (options.allTrees) {
277
- // Same fail-open + Windows-flush discipline as the single-tree path
278
- // below — no forced process.exit(), --json included.
228
+ // No process.exit() here either, --json included.
279
229
  printAllTrees(feature, options, cwd);
280
230
  return;
281
231
  }
@@ -284,10 +234,8 @@ export function costCommand(feature, options = {}) {
284
234
  const summary = aggregateCost(events, { feature });
285
235
 
286
236
  if (options.json) {
287
- // No forced process.exit() here: on Windows a piped stdout write is
288
- // async, and exit()ing right after a large console.log can race the
289
- // flush and truncate output. Letting the event loop drain naturally
290
- // (nothing else keeps it alive in this command) exits 0 without risk.
237
+ // No process.exit(): on Windows a piped stdout write is async, and exiting right after a
238
+ // large console.log can truncate the output.
291
239
  console.log(JSON.stringify(summary));
292
240
  return;
293
241
  }
@@ -1,14 +1,3 @@
1
- /**
2
- * `morph-spec telemetry [--json] [--feature <name>] [--limit <n>]`
3
- *
4
- * The reader surface over the harness event stream (.morph/logs/events.jsonl,
5
- * written by the telemetry-log hook). Reconstructs the whole execution path of
6
- * an NLH session: top skills, personas dispatched, standards (knowledge base)
7
- * read, the tool mix, and the recent prompts (user + sub-agent).
8
- *
9
- * Read-only, always exits 0 (fail-open — an empty stream is an answer).
10
- */
11
-
12
1
  import chalk from 'chalk';
13
2
  import { loadTelemetry, aggregateTelemetry } from '../../lib/telemetry/telemetry-reader.js';
14
3
 
@@ -23,9 +12,7 @@ function section(title, rows, fmt) {
23
12
  for (const r of rows) console.log(' ' + fmt(r));
24
13
  }
25
14
 
26
- /**
27
- * @param {{ json?: boolean, feature?: string, limit?: number, cwd?: string }} [options]
28
- */
15
+ // Read-only and always exits 0: an empty stream is an answer.
29
16
  export function telemetryCommand(options = {}) {
30
17
  const events = loadTelemetry(options.cwd || process.cwd());
31
18
  const summary = aggregateTelemetry(events, { feature: options.feature });
@@ -1,23 +1,3 @@
1
- /**
2
- * branch.js — `morph-spec branch prune`.
3
- *
4
- * The gap this closes: after a few features close by squash-merge, the local
5
- * repo accumulates branches git considers unmerged. `git branch --merged` lists
6
- * none of them, `git branch -d` refuses each one, and the only command left is
7
- * `git branch -D` — which is EXACTLY the command for throwing away real work.
8
- * Once a user has typed `-D` on five safe branches, the sixth (an actual
9
- * unintegrated feature) gets the same keystroke.
10
- *
11
- * So this command never asks the user to make that distinction: it makes it
12
- * itself, prints the evidence for each branch, and deletes only what it PROVED
13
- * is already integrated (see branch-classifier.js for the five classes and
14
- * their order). Everything else is listed with the reason it survives.
15
- *
16
- * The remote is a separate decision: `--remote` is required to touch
17
- * `origin/<branch>`, because a local branch is a local artifact while the remote
18
- * one may be what someone else, or an open review, is looking at.
19
- */
20
-
21
1
  import { execFileSync } from 'child_process';
22
2
  import chalk from 'chalk';
23
3
  import { isGitRepo, resolvePrimaryRoot } from './worktree.js';
@@ -25,15 +5,8 @@ import { detectDefaultBranch } from '../../lib/git/default-branch.js';
25
5
  import { buildPrIndex } from '../../lib/git/pr-index.js';
26
6
  import { classifyBranches } from '../../lib/git/branch-classifier.js';
27
7
 
28
- /**
29
- * Delete one local branch.
30
- *
31
- * `-D`, not `-d`, and that is the whole point of the classifier: `-d` refuses
32
- * every squash-merged branch, so a command that used it would be unable to do
33
- * its one job. The safety does not come from git's own check (which cannot see
34
- * a squash-merge) — it comes from only ever reaching this function with a
35
- * branch whose integration was positively proven.
36
- */
8
+ // `-D`, not `-d`: `-d` refuses every squash-merged branch. Safety comes from only
9
+ // reaching here with integration positively proven.
37
10
  function deleteLocal(name, cwd) {
38
11
  try {
39
12
  execFileSync('git', ['branch', '-D', name], { cwd, stdio: 'pipe' });
@@ -52,7 +25,6 @@ function deleteRemote(name, cwd) {
52
25
  }
53
26
  }
54
27
 
55
- /** Does `origin/<name>` exist locally as a remote-tracking ref? */
56
28
  function remoteRefExists(name, cwd) {
57
29
  try {
58
30
  execFileSync('git', ['show-ref', '--verify', '--quiet', `refs/remotes/origin/${name}`], { cwd, stdio: 'pipe' });
@@ -62,15 +34,6 @@ function remoteRefExists(name, cwd) {
62
34
  }
63
35
  }
64
36
 
65
- /**
66
- * Command handler for `morph-spec branch prune [--remote] [--dry-run] [--json]`.
67
- *
68
- * Fail-open outside a git repo (exit 0, empty result) — the same discipline the
69
- * rest of the worktree suite follows: a housekeeping command must never be the
70
- * reason a script dies.
71
- *
72
- * @param {{ remote?: boolean, dryRun?: boolean, json?: boolean, cwd?: string }} [options]
73
- */
74
37
  export function branchPruneCommand(options = {}) {
75
38
  const cwd = options.cwd || process.cwd();
76
39
  const emit = (payload, code = 0) => {
@@ -85,9 +48,7 @@ export function branchPruneCommand(options = {}) {
85
48
  }
86
49
  const root = resolvePrimaryRoot(cwd);
87
50
  const defaultBranch = detectDefaultBranch(root);
88
- // null = UNKNOWN, never "no PR" — the classifier treats a branch with no
89
- // positive evidence as unmerged, so a missing `gh` costs conservatism, not
90
- // safety. Reported so the user can tell "no PR" from "could not ask".
51
+ // null = UNKNOWN, never "no PR": a missing `gh` costs conservatism, not safety.
91
52
  const prIndex = buildPrIndex(root);
92
53
 
93
54
  const classified = classifyBranches({ cwd: root, defaultBranch, prIndex });
@@ -139,9 +100,7 @@ function printReport(payload, options) {
139
100
  const verb = payload.dryRun ? 'seriam apagadas' : 'apagadas';
140
101
  console.log(chalk.bold(`\nbranch prune — default: ${payload.defaultBranch || chalk.red('não resolvida')}`));
141
102
  if (!payload.prIndexAvailable) {
142
- // Load-bearing caveat, not noise: without `gh` a squash-merge is only
143
- // detectable by the tree comparison, so branches that WERE merged may
144
- // legitimately show up as unmerged here.
103
+ // Without `gh`, squash-merged branches may legitimately show as unmerged.
145
104
  console.log(chalk.gray(' (sem `gh`/GitHub: squash-merge só é detectado por árvore idêntica)'));
146
105
  }
147
106
 
@@ -1,24 +1,3 @@
1
- /**
2
- * `morph-spec claim [feature] [--release] [--list]` — the manual half of
3
- * advisory feature ownership (B1).
4
- *
5
- * Claims are acquired and heartbeaten AUTOMATICALLY (SessionStart hook +
6
- * telemetry hook), so the operator never has to remember anything. This command
7
- * exists for the two cases automation cannot cover:
8
- * - a session that died without releasing, leaving a claim that keeps
9
- * warning everyone until its TTL expires (`--release`);
10
- * - an operator switching this SAME session/tree to a different feature
11
- * mid-task. `morph-spec claim <feature>` (no flags) ACQUIRES it, moving
12
- * the tree's previous claim in the same step — a manual release-then-
13
- * reclaim was observed to just not happen mid-task, and the silent no-op
14
- * this used to be (any unclaimed feature name printed "nothing here" and
15
- * changed nothing) was worse: it looked like a query, not a skipped write.
16
- *
17
- * `--list` forces the read-only view even when a feature is named. `--release`
18
- * is the only other mutation. Always exits 0 except on a genuine misuse — the
19
- * claim system is advisory and must never become a source of hard failures.
20
- */
21
-
22
1
  import chalk from 'chalk';
23
2
  import { execSync } from 'child_process';
24
3
  import { resolve } from 'path';
@@ -31,7 +10,6 @@ import {
31
10
  claimAge,
32
11
  } from '../../../framework/hooks/shared/claim-registry.js';
33
12
 
34
- /** Resolve the repo's shared git common dir — where claims live. */
35
13
  function gitCommonDirOf(cwd) {
36
14
  const root = resolvePrimaryRoot(cwd);
37
15
  const common = execSync('git rev-parse --git-common-dir', { cwd: root, stdio: 'pipe' }).toString().trim();
@@ -41,15 +19,8 @@ function gitCommonDirOf(cwd) {
41
19
  const norm = (p) => String(p ?? '').replace(/\\/g, '/');
42
20
 
43
21
  /**
44
- * Acquire `feature`'s claim, moving it in the same step if this tree already
45
- * holds a live claim on a different feature.
46
- *
47
- * "This tree's own claim" is identified by PATH, not session id: the CLI has
48
- * no access to the Claude Code session id SessionStart stamps (that only
49
- * reaches hooks, via stdin JSON) — path is the one honest signal a manual
50
- * invocation shares with the automatic claim it may be replacing. Re-using
51
- * that claim's session id when re-acquiring keeps the move from reading as a
52
- * takeover of a stranger.
22
+ * Moves this tree's live claim, identified by PATH: the CLI never sees the session id
23
+ * SessionStart stamps. Reusing that claim's session id keeps the move from reading as a takeover.
53
24
  */
54
25
  function acquireOrMove(feature, { cwd, gitCommonDir, json }) {
55
26
  const here = norm(cwd);
@@ -84,10 +55,6 @@ function acquireOrMove(feature, { cwd, gitCommonDir, json }) {
84
55
  process.exit(0);
85
56
  }
86
57
 
87
- /**
88
- * @param {string|undefined} feature
89
- * @param {{ release?: boolean, list?: boolean, json?: boolean, cwd?: string }} [options]
90
- */
91
58
  export function claimCommand(feature, options = {}) {
92
59
  const cwd = options.cwd || process.cwd();
93
60
  if (!isGitRepo(cwd)) {
@@ -120,27 +87,16 @@ export function claimCommand(feature, options = {}) {
120
87
  process.exit(0);
121
88
  }
122
89
 
123
- // `morph-spec claim <feature>` (no --release, no --list) is the manual
124
- // acquire/move half of B1 — automation (SessionStart + heartbeat) covers the
125
- // common case; this covers switching this session to a different feature
126
- // mid-task without a release-then-reclaim dance. `--list` forces the
127
- // read-only view below even when a feature is named.
128
90
  if (feature && !options.list) {
129
91
  acquireOrMove(feature, { cwd, gitCommonDir, json: options.json });
130
92
  return;
131
93
  }
132
94
 
133
- // No feature (or explicit --list): the read-only board, whole or filtered.
134
95
  const all = listClaims(gitCommonDir);
135
96
  const scoped = feature ? all.filter((c) => c.feature === feature) : all;
136
97
 
137
- // Um claim morto NÃO é limpo do registro — ele só para de avisar (o TTL de
138
- // 30 min o mata, `live` é computado na leitura). O efeito colateral é que o
139
- // board acumula: features encerradas há 20h e 73h apareciam no `--list` como
140
- // se fossem informação. Um quadro de avisos onde quase nada é aviso ensina a
141
- // não olhar o quadro. Por padrão mostramos só o que ainda avisa; `--all`
142
- // devolve o registro inteiro, e o rodapé conta o que ficou de fora para a
143
- // omissão nunca ser silenciosa.
98
+ // Claim morto segue no registro (`live` é computado na leitura): por padrão só o que ainda
99
+ // avisa; `--all` devolve tudo e o rodapé conta o que ficou de fora.
144
100
  const rows = options.all ? scoped : scoped.filter((c) => c.live);
145
101
  const hidden = scoped.length - rows.length;
146
102