@polymorphism-tech/morph-spec 8.47.0 → 9.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (377) hide show
  1. package/CLAUDE.md +51 -43
  2. package/README.md +39 -38
  3. package/bin/morph-spec.js +41 -113
  4. package/bin/validate.js +1 -147
  5. package/claude-plugin.json +1 -1
  6. package/docs/CHEATSHEET.md +1 -1
  7. package/docs/QUICKSTART.md +1 -1
  8. package/framework/CLAUDE.md +41 -101
  9. package/framework/MORPH.md +95 -252
  10. package/framework/agents.json +86 -21
  11. package/framework/commands/morph-apply.md +5 -28
  12. package/framework/commands/morph-archive.md +1 -1
  13. package/framework/commands/morph-hotfix.md +8 -8
  14. package/framework/commands/morph-infra.md +1 -1
  15. package/framework/commands/morph-preflight.md +2 -3
  16. package/framework/commands/morph-status.md +4 -4
  17. package/framework/docs/CLI.md +574 -286
  18. package/framework/evals/review-checklist.md +82 -41
  19. package/framework/hooks/README.md +10 -11
  20. package/framework/hooks/claude-code/core/block-destructive-worktree-removal.js +6 -49
  21. package/framework/hooks/claude-code/core/block-raw-worktree-add.js +2 -35
  22. package/framework/hooks/claude-code/core/chain.js +4 -65
  23. package/framework/hooks/claude-code/core/comment-guard.js +3 -17
  24. package/framework/hooks/claude-code/core/denylist.json +33 -3
  25. package/framework/hooks/claude-code/core/enforce-phase-writes.js +15 -63
  26. package/framework/hooks/claude-code/core/gate-guard.js +9 -78
  27. package/framework/hooks/claude-code/core/graph-refresh-kick.js +3 -24
  28. package/framework/hooks/claude-code/core/heavy-gate.js +3 -21
  29. package/framework/hooks/claude-code/core/heavy-release.js +2 -13
  30. package/framework/hooks/claude-code/core/loop-detect.js +2 -31
  31. package/framework/hooks/claude-code/core/pre-bash-denylist.js +36 -2
  32. package/framework/hooks/claude-code/core/protect-spec-files.js +25 -297
  33. package/framework/hooks/claude-code/core/state-sync.js +15 -85
  34. package/framework/hooks/claude-code/core/telemetry-log.js +15 -96
  35. package/framework/hooks/claude-code/core/validate-completion.js +37 -147
  36. package/framework/hooks/claude-code/core/warn-bash-source-write.js +23 -0
  37. package/framework/hooks/claude-code/core/worktree-context.js +15 -114
  38. package/framework/hooks/claude-code/core/worktree-create.js +6 -70
  39. package/framework/hooks/claude-code/core/worktree-env-inject.js +5 -56
  40. package/framework/hooks/claude-code/core/worktree-remove.js +5 -31
  41. package/framework/hooks/claude-code/statusline.py +55 -41
  42. package/framework/hooks/package.json +3 -0
  43. package/framework/hooks/shared/activity-logger.js +9 -89
  44. package/framework/hooks/shared/agent-reap.js +2 -17
  45. package/framework/hooks/shared/build-check.js +11 -76
  46. package/framework/hooks/shared/claim-registry.js +9 -119
  47. package/framework/hooks/shared/command-tokens.js +168 -44
  48. package/framework/hooks/shared/comment-rules.js +5 -20
  49. package/framework/hooks/shared/comment-scanner.js +11 -43
  50. package/framework/hooks/shared/comment-stripper.js +11 -85
  51. package/framework/hooks/shared/e2e-check.js +0 -0
  52. package/framework/hooks/shared/errata.js +59 -0
  53. package/framework/hooks/shared/feature-locator.js +11 -95
  54. package/framework/hooks/shared/frontend-locations.js +4 -0
  55. package/framework/hooks/shared/gate-question.js +12 -0
  56. package/framework/hooks/shared/git-exclude.js +3 -20
  57. package/framework/hooks/shared/git-paths.js +8 -104
  58. package/framework/hooks/shared/graph-freshness.js +22 -166
  59. package/framework/hooks/shared/graph-refresh.js +21 -149
  60. package/framework/hooks/shared/heavy-command.js +4 -12
  61. package/framework/hooks/shared/hook-response.js +8 -83
  62. package/framework/hooks/shared/morph-cli.js +8 -52
  63. package/framework/hooks/shared/payload-utils.js +10 -132
  64. package/framework/hooks/shared/phase-utils.js +14 -72
  65. package/framework/hooks/shared/redact-secrets.js +4 -15
  66. package/framework/hooks/shared/reparse-scan.js +6 -66
  67. package/framework/hooks/shared/slice-progress.js +99 -0
  68. package/framework/hooks/shared/source-files.js +4 -17
  69. package/framework/hooks/shared/spawn-command.js +23 -0
  70. package/framework/hooks/shared/state-reader.js +51 -247
  71. package/framework/hooks/shared/state-writer.js +9 -54
  72. package/framework/hooks/shared/stdin-reader.js +1 -11
  73. package/framework/hooks/shared/telemetry-logger.js +7 -67
  74. package/framework/hooks/shared/transcript-usage.js +7 -29
  75. package/framework/hooks/shared/worktree-root.js +7 -29
  76. package/framework/mcp/registry.json +3 -4
  77. package/framework/phases.json +23 -39
  78. package/framework/rules/csharp-standards.md +1 -1
  79. package/framework/rules/frontend-standards.md +1 -0
  80. package/framework/rules/hangfire-standards.md +1 -1
  81. package/framework/rules/neon-standards.md +1 -1
  82. package/framework/schemas/config.schema.json +14 -9
  83. package/framework/schemas/feature.schema.json +15 -50
  84. package/framework/skills/README.md +3 -4
  85. package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
  86. package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +1 -1
  87. package/framework/skills/core/morph-apply/SKILL.md +149 -222
  88. package/framework/skills/core/morph-hotfix/SKILL.md +33 -42
  89. package/framework/skills/core/morph-machine/SKILL.md +2 -2
  90. package/framework/skills/core/morph-media/SKILL.md +1 -1
  91. package/framework/skills/core/morph-plan/SKILL.md +137 -299
  92. package/framework/skills/core/morph-review/SKILL.md +111 -136
  93. package/framework/skills/core/morph-standards/SKILL.md +27 -39
  94. package/framework/skills/core/morph-uiux/SKILL.md +94 -152
  95. package/framework/standards/STANDARDS.json +109 -1219
  96. package/framework/standards/STANDARDS.meta.json +1319 -0
  97. package/framework/standards/ai-agents/agent-archetypes.md +2 -2
  98. package/framework/standards/ai-agents/agent-session.md +1 -1
  99. package/framework/standards/ai-agents/conversational-agent-with-phases.md +4 -4
  100. package/framework/standards/ai-agents/durable-workflows-hitl.md +3 -3
  101. package/framework/standards/ai-agents/evals-with-cache.md +1 -2
  102. package/framework/standards/ai-agents/guardrails.md +1 -1
  103. package/framework/standards/ai-agents/multi-agent-patterns.md +2 -2
  104. package/framework/standards/ai-agents/observability-patterns.md +1 -1
  105. package/framework/standards/ai-agents/production.md +1 -1
  106. package/framework/standards/ai-agents/prompt-sources.md +2 -2
  107. package/framework/standards/ai-agents/providers/model-registry.md +1 -1
  108. package/framework/standards/ai-agents/rag-custom-pgvector.md +2 -2
  109. package/framework/standards/ai-agents/setup.md +3 -3
  110. package/framework/standards/ai-agents/sweet-spot.md +2 -2
  111. package/framework/standards/ai-agents/tool-adapters.md +0 -2
  112. package/framework/standards/ai-agents/vector-data-extensions.md +4 -4
  113. package/framework/standards/ai-agents/workflows.md +1 -1
  114. package/framework/standards/architecture/code-comments.md +7 -7
  115. package/framework/standards/architecture/vertical-slice/vertical-slice.md +1 -1
  116. package/framework/standards/backend/api/validation.md +1 -1
  117. package/framework/standards/backend/dotnet/vsa-handler-patterns.md +5 -5
  118. package/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +1 -1
  119. package/framework/standards/backend/integrations/neon-auth/neon-auth.md +2 -2
  120. package/framework/standards/data/nosql/cache/redis.md +1 -1
  121. package/framework/standards/data/nosql/cosmos-db.md +3 -3
  122. package/framework/standards/frontend/admin-app/forms.md +1 -1
  123. package/framework/standards/frontend/design-system/art-direction.md +88 -0
  124. package/framework/standards/frontend/design-system/premium-finish.md +77 -2
  125. package/framework/standards/infrastructure/neon/neon-pgvector.md +5 -5
  126. package/framework/standards/integration/mcp/mcp-tools.md +7 -7
  127. package/framework/templates/CLAUDE.md.core.template +3 -3
  128. package/framework/templates/README.md +2 -3
  129. package/framework/templates/REGISTRY.json +15 -179
  130. package/framework/templates/docs/plan.md +72 -0
  131. package/framework/templates/docs/ui-mockups.md +4 -0
  132. package/framework/templates/dotnet/ai-kit/README.md +1 -9
  133. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Morph.AiKit.Tests.csproj +0 -10
  134. package/framework/templates/meta-prompts/squad-leaders/backend-squad.md +1 -1
  135. package/framework/templates/meta-prompts/squad-leaders/frontend-squad.md +1 -1
  136. package/framework/templates/meta-prompts/squad-leaders/squad-leader.md +1 -1
  137. package/framework/templates/meta-prompts/validators/pre-commit-validator.md +3 -4
  138. package/package.json +1 -1
  139. package/src/commands/context/context-refresh.js +0 -16
  140. package/src/commands/dashboard/dashboard.js +2 -8
  141. package/src/commands/e2e/e2e.js +18 -105
  142. package/src/commands/graph/affected.js +0 -14
  143. package/src/commands/graph/build.js +11 -50
  144. package/src/commands/graph/explain.js +0 -16
  145. package/src/commands/graph/status.js +1 -12
  146. package/src/commands/mcp/mcp-setup.js +4 -62
  147. package/src/commands/observability/cost.js +17 -111
  148. package/src/commands/observability/telemetry.js +1 -14
  149. package/src/commands/project/branch.js +4 -45
  150. package/src/commands/project/claim.js +4 -48
  151. package/src/commands/project/doctor-procs.js +1 -1
  152. package/src/commands/project/doctor.js +53 -307
  153. package/src/commands/project/env.js +1 -27
  154. package/src/commands/project/fleet.js +6 -35
  155. package/src/commands/project/heavy.js +3 -3
  156. package/src/commands/project/init.js +8 -68
  157. package/src/commands/project/install-plugin-cmd.js +0 -1
  158. package/src/commands/project/setup-infra-cmd.js +2 -1
  159. package/src/commands/project/stack-scan.js +58 -0
  160. package/src/commands/project/standards.js +65 -72
  161. package/src/commands/project/status.js +28 -121
  162. package/src/commands/project/update.js +31 -223
  163. package/src/commands/project/worktree.js +109 -883
  164. package/src/commands/scaffold/scaffold.js +0 -25
  165. package/src/commands/state/advance.js +65 -120
  166. package/src/commands/state/approve.js +87 -229
  167. package/src/commands/state/archive.js +23 -139
  168. package/src/commands/state/auto-approval.js +65 -0
  169. package/src/commands/state/create.js +49 -109
  170. package/src/commands/state/delete.js +11 -63
  171. package/src/commands/state/finish.js +105 -494
  172. package/src/commands/state/gate-check.js +74 -183
  173. package/src/commands/state/gate-decision.js +8 -42
  174. package/src/commands/state/handoff.js +4 -31
  175. package/src/commands/state/list.js +21 -91
  176. package/src/commands/state/report-check.js +134 -338
  177. package/src/commands/state/retype.js +12 -28
  178. package/src/commands/validation/index.js +0 -3
  179. package/src/commands/validation/mutate.js +79 -19
  180. package/src/commands/validation/plan-check.js +81 -0
  181. package/src/commands/validation/validate-feature.js +52 -216
  182. package/src/commands/validation/verify.js +45 -160
  183. package/src/core/paths/output-schema.js +9 -155
  184. package/src/core/state/feature-identity.js +1 -25
  185. package/src/core/state/gate-order.js +2 -30
  186. package/src/core/state/lifecycle-audit.js +8 -100
  187. package/src/core/state/state-manager.js +32 -395
  188. package/src/core/templates/template-registry.js +2 -97
  189. package/src/core/templates/template-renderer.js +13 -93
  190. package/src/core/templates/template-seed.js +21 -0
  191. package/src/core/work-types.js +10 -45
  192. package/src/dashboard/app/App.jsx +1 -8
  193. package/src/dashboard/app/components/ActivityFeed.jsx +2 -8
  194. package/src/dashboard/app/components/CommandPalette.jsx +4 -11
  195. package/src/dashboard/app/components/DetailPanel.jsx +1 -5
  196. package/src/dashboard/app/components/EntityLink.jsx +0 -12
  197. package/src/dashboard/app/components/ErrorBoundary.jsx +1 -8
  198. package/src/dashboard/app/components/KnowledgeMarkdown.jsx +0 -11
  199. package/src/dashboard/app/components/Markdown.jsx +0 -9
  200. package/src/dashboard/app/components/PhaseRail.jsx +0 -11
  201. package/src/dashboard/app/components/SearchFilter.jsx +0 -4
  202. package/src/dashboard/app/components/Sidebar.jsx +0 -5
  203. package/src/dashboard/app/hooks/useMorphQuery.js +1 -11
  204. package/src/dashboard/app/hooks/usePref.js +1 -5
  205. package/src/dashboard/app/lib/format.js +0 -2
  206. package/src/dashboard/app/lib/phases.js +3 -9
  207. package/src/dashboard/app/lib/project.js +0 -12
  208. package/src/dashboard/app/pages/Activity.jsx +1 -1
  209. package/src/dashboard/app/pages/AgentMap.jsx +1 -8
  210. package/src/dashboard/app/pages/FeatureDetail.jsx +139 -133
  211. package/src/dashboard/app/pages/Features.jsx +9 -16
  212. package/src/dashboard/app/pages/Guide.jsx +2 -3
  213. package/src/dashboard/app/pages/HookInspector.jsx +2 -23
  214. package/src/dashboard/app/pages/PhasePipeline.jsx +3 -7
  215. package/src/dashboard/app/pages/Portfolio.jsx +0 -1
  216. package/src/dashboard/app/pages/RulesMap.jsx +1 -16
  217. package/src/dashboard/app/pages/SkillsLibrary.jsx +1 -16
  218. package/src/dashboard/app/pages/Standards.jsx +2 -17
  219. package/src/dashboard/scanner/activity-scanner.js +14 -83
  220. package/src/dashboard/scanner/agents-scanner.js +1 -23
  221. package/src/dashboard/scanner/docs-scanner.js +1 -7
  222. package/src/dashboard/scanner/feature-status.js +2 -5
  223. package/src/dashboard/scanner/features-scanner.js +92 -113
  224. package/src/dashboard/scanner/hooks-scanner.js +5 -28
  225. package/src/dashboard/scanner/index.js +0 -4
  226. package/src/dashboard/scanner/portfolio.js +5 -29
  227. package/src/dashboard/scanner/project-api.js +8 -54
  228. package/src/dashboard/scanner/rules-scanner.js +1 -2
  229. package/src/dashboard/scanner/skills-scanner.js +2 -12
  230. package/src/dashboard/scanner/standards-scanner.js +4 -7
  231. package/src/dashboard/vite-plugin-morph-data.js +5 -19
  232. package/src/lib/ai/ai-checks.js +7 -52
  233. package/src/lib/ai/ai-project-scan.js +14 -108
  234. package/src/lib/ai/code-audit.js +7 -63
  235. package/src/lib/ai/pin-drift.js +8 -51
  236. package/src/lib/ai/registry-audit.js +11 -90
  237. package/src/lib/ci/ci-verify.js +14 -13
  238. package/src/lib/ci/github-ci.js +9 -37
  239. package/src/lib/ci/workflow-scaffold.js +2 -10
  240. package/src/lib/detectors/claude-config-detector.js +13 -74
  241. package/src/lib/detectors/index.js +8 -59
  242. package/src/lib/e2e/compose-env.js +5 -66
  243. package/src/lib/e2e/stack-teardown.js +6 -40
  244. package/src/lib/generators/architecture-scanner.js +18 -156
  245. package/src/lib/generators/handoff-generator.js +37 -112
  246. package/src/lib/generators/scaffold-generator.js +5 -101
  247. package/src/lib/generators/settings-generator.js +11 -122
  248. package/src/lib/git/branch-classifier.js +11 -84
  249. package/src/lib/git/default-branch.js +14 -169
  250. package/src/lib/git/evidence-staleness.js +2 -1
  251. package/src/lib/git/gh.js +2 -17
  252. package/src/lib/git/pending-prs.js +6 -37
  253. package/src/lib/git/pr-files.js +3 -28
  254. package/src/lib/git/pr-index.js +3 -34
  255. package/src/lib/git/tree-fingerprint.js +17 -17
  256. package/src/lib/git/tree-state.js +6 -33
  257. package/src/lib/graph/god-nodes.js +2 -22
  258. package/src/lib/graph/graph-health.js +3 -24
  259. package/src/lib/graph/graph-loader.js +5 -56
  260. package/src/lib/graph/graphify-runtime.js +7 -37
  261. package/src/lib/graph/graphifyignore.js +8 -74
  262. package/src/lib/graph/sanitize.js +16 -136
  263. package/src/lib/heavy/cleanup.js +2 -6
  264. package/src/lib/installers/effects.js +8 -93
  265. package/src/lib/installers/mcp-installer.js +9 -169
  266. package/src/lib/installers/memory-installer.js +8 -33
  267. package/src/lib/installers/templates-reconcile.js +5 -60
  268. package/src/lib/mutation/commands.js +3 -2
  269. package/src/lib/mutation/dotnet-introspection.js +281 -0
  270. package/src/lib/mutation/plan.js +14 -6
  271. package/src/lib/mutation/runner.js +1 -1
  272. package/src/lib/mutation/subset.js +47 -13
  273. package/src/lib/plan/artifact-vocabulary.js +40 -0
  274. package/src/lib/plan/checks.js +208 -0
  275. package/src/lib/plan/plan-parser.js +204 -0
  276. package/src/lib/plan/plan-template.js +18 -0
  277. package/src/lib/projects/registry.js +7 -44
  278. package/src/lib/review-reports.js +204 -0
  279. package/src/lib/risk-detector.js +131 -274
  280. package/src/lib/specs/adr-index.js +38 -85
  281. package/src/lib/specs/design-seed.js +18 -0
  282. package/src/lib/specs/frontmatter.js +31 -0
  283. package/src/lib/specs/gfm-table.js +11 -0
  284. package/src/lib/specs/revocations.js +31 -102
  285. package/src/lib/specs/screen-checklist.js +56 -132
  286. package/src/lib/stack/dotnet-build-ignores.js +43 -0
  287. package/src/lib/stack/stack-profile.js +1 -28
  288. package/src/lib/stack/stack-scan.js +260 -0
  289. package/src/lib/stack-filter.js +4 -27
  290. package/src/lib/standards/registry.js +37 -0
  291. package/src/lib/standards/sections.js +47 -0
  292. package/src/lib/standards/verified-against.js +19 -191
  293. package/src/lib/tasks/eval-node.js +23 -179
  294. package/src/lib/tasks/linux-runner.js +18 -142
  295. package/src/lib/tasks/test-nodes.js +43 -313
  296. package/src/lib/tasks/test-runner.js +107 -447
  297. package/src/lib/telemetry/metrics.js +13 -103
  298. package/src/lib/telemetry/telemetry-reader.js +13 -238
  299. package/src/lib/telemetry/verify-event.js +4 -34
  300. package/src/lib/validators/code-budget/code-budget-validator.js +4 -44
  301. package/src/lib/validators/code-budget/index.js +0 -7
  302. package/src/lib/validators/contracts/contract-compliance-validator.js +4 -26
  303. package/src/lib/validators/contracts/index.js +0 -6
  304. package/src/lib/validators/nextjs/index.js +0 -5
  305. package/src/lib/validators/nextjs/next-component-validator.js +4 -81
  306. package/src/lib/validators/packages/index.js +0 -6
  307. package/src/lib/validators/packages/package-validator.js +6 -56
  308. package/src/lib/validators/reuse/index.js +0 -8
  309. package/src/lib/validators/reuse/reuse-validator.js +24 -137
  310. package/src/lib/validators/reuse/symbol-scanner.js +6 -62
  311. package/src/lib/validators/traceability-check.js +54 -156
  312. package/src/lib/validators/validation-runner.js +20 -125
  313. package/src/lib/validators/verify-runner.js +152 -575
  314. package/src/lib/work-type-detector.js +5 -67
  315. package/src/lib/worktree/docker-audit.js +17 -137
  316. package/src/lib/worktree/env-allocator.js +10 -98
  317. package/src/lib/worktree/feature-truth.js +12 -115
  318. package/src/lib/worktree/finish-backup.js +32 -242
  319. package/src/lib/worktree/fleet-scanner.js +31 -126
  320. package/src/lib/worktree/ignored-triage.js +15 -91
  321. package/src/lib/worktree/vscode-settings.js +2 -3
  322. package/src/lib/worktree/worktree-audit.js +21 -213
  323. package/src/lib/worktree/worktree-include.js +3 -5
  324. package/src/scripts/global-install.js +3 -9
  325. package/src/scripts/install-plugin.js +1 -13
  326. package/src/scripts/setup-infra.js +17 -138
  327. package/src/utils/agents-installer.js +92 -272
  328. package/src/utils/banner.js +4 -25
  329. package/src/utils/claude-md-injector.js +1 -37
  330. package/src/utils/claude-settings-manager.js +1 -87
  331. package/src/utils/file-copier.js +32 -90
  332. package/src/utils/hooks-installer.js +26 -296
  333. package/src/utils/skills-installer.js +4 -102
  334. package/src/utils/version-checker.js +4 -83
  335. package/framework/commands/morph-proposal.md +0 -57
  336. package/framework/evals/trace-schema.md +0 -67
  337. package/framework/hooks/claude-code/core/tasks-json-guard.js +0 -83
  338. package/framework/hooks/claude-code/core/trace-autogen.js +0 -277
  339. package/framework/hooks/git/pre-commit/specs.sh +0 -50
  340. package/framework/hooks/shared/tasks-validator.js +0 -111
  341. package/framework/rules/morph-task-tracking.md +0 -54
  342. package/framework/rules/morph-workflow.md +0 -244
  343. package/framework/schemas/tasks.schema.json +0 -79
  344. package/framework/skills/core/morph-brainstorming/SKILL.md +0 -161
  345. package/framework/skills/core/morph-implement/SKILL.md +0 -194
  346. package/framework/skills/core/morph-proposal/SKILL.md +0 -152
  347. package/framework/skills/core/morph-stack-scan/SKILL.md +0 -145
  348. package/framework/templates/docs/proposal.md +0 -192
  349. package/framework/templates/docs/spec.md +0 -57
  350. package/framework/templates/docs/ui-components.md +0 -52
  351. package/framework/templates/docs/ui-design-system.md +0 -76
  352. package/framework/templates/docs/ui-flows.md +0 -167
  353. package/framework/templates/examples/spec-examples.md +0 -91
  354. package/framework/templates/feature/decisions.md +0 -124
  355. package/framework/templates/feature/recap.md +0 -145
  356. package/framework/templates/tasks.template.json +0 -17
  357. package/src/commands/state/usecase.js +0 -143
  358. package/src/commands/tasks/dag.js +0 -181
  359. package/src/commands/utils/index.js +0 -3
  360. package/src/lib/agents/output-collector.js +0 -76
  361. package/src/lib/detectors/design-system-detector.js +0 -188
  362. package/src/lib/evaluator-report.js +0 -104
  363. package/src/lib/generators/design-system-generator.js +0 -508
  364. package/src/lib/specs/acervo-format.js +0 -70
  365. package/src/lib/specs/acervo-lifecycle.js +0 -264
  366. package/src/lib/specs/done-criteria-check.js +0 -200
  367. package/src/lib/specs/usecase-check.js +0 -301
  368. package/src/lib/specs/usecase-promoter.js +0 -301
  369. package/src/lib/specs/usecase-registry.js +0 -237
  370. package/src/lib/tasks/dispatch-planner.js +0 -319
  371. package/src/lib/tasks/dotnet-test-introspection.js +0 -632
  372. package/src/lib/tasks/mermaid-renderer.js +0 -132
  373. package/src/lib/tasks/task-classifier.js +0 -30
  374. package/src/lib/tasks/task-parser.js +0 -209
  375. package/src/lib/tasks/tasks-json-parser.js +0 -296
  376. package/src/lib/tasks/test-scope.js +0 -597
  377. package/src/utils/agent-id-mapper.js +0 -11
@@ -1,36 +1,10 @@
1
- /**
2
- * `morph-spec standards --find "<query>" [--category <c>] [--tags <a,b>] [--json]`
3
- *
4
- * Server-side replacement for "read the whole STANDARDS.json to pick 1-3
5
- * standards" (R2 of the performance plan — token cut per task). Today
6
- * morph-implement loads the full 65 KB / 60-entry registry (with a `digest`
7
- * per entry) just to choose a couple of relevant standards: ~16k tokens per
8
- * task. This command searches server-side and returns only the TOP 3 hits —
9
- * `id · path · digest` — where the digest is the FULL text: it is what
10
- * substitutes for actually reading the standard's .md file.
11
- *
12
- * Without `--find` (a bare call): lists categories + counts — a cheap
13
- * orientation view, no scoring.
14
- *
15
- * A query with no hit exits 0 (this is advisory tooling, not a gate) with a
16
- * human-readable warning + category suggestions on stderr, and — under
17
- * `--json` — a stable `{ query, results: [], suggestion }` shape on stdout so
18
- * a JSON consumer never has to special-case "no results" as a parse error.
19
- */
20
-
21
1
  import { existsSync, readFileSync } from 'fs';
22
- import { join } from 'path';
2
+ import { dirname, join } from 'path';
23
3
  import chalk from 'chalk';
4
+ import { loadStandardsRegistry } from '../../lib/standards/registry.js';
5
+ import { markdownHeadings, sectionBySlug } from '../../lib/standards/sections.js';
24
6
 
25
- /**
26
- * Resolve STANDARDS.json the same way doctor.js resolves the standards root:
27
- * an installed project first (`.morph/framework/standards/`), falling back
28
- * to this package's own bundled copy (`framework/standards/`) — the framework
29
- * repo in dev, or the npm package's own copy before `setup-infra` has run.
30
- *
31
- * @param {string} targetPath - project root to look for `.morph/` under
32
- * @returns {string|null} absolute path to STANDARDS.json, or null if neither exists
33
- */
7
+ /** Installed project first, else this package's bundled copy (dev repo, or before `setup-infra` ran). */
34
8
  export function resolveStandardsJsonPath(targetPath) {
35
9
  const installed = join(targetPath, '.morph', 'framework', 'standards', 'STANDARDS.json');
36
10
  if (existsSync(installed)) return installed;
@@ -41,17 +15,62 @@ export function resolveStandardsJsonPath(targetPath) {
41
15
  return null;
42
16
  }
43
17
 
44
- /** Load + parse STANDARDS.json. Throws on missing/invalid file — caller decides how to report it. */
45
- function loadRegistry(standardsJsonPath) {
46
- const raw = readFileSync(standardsJsonPath, 'utf8');
47
- return JSON.parse(raw);
18
+ export function resolveStandardSection(standard, mdText, anchor) {
19
+ if (mdText === null) return { status: 'unreadable' };
20
+ const anchors = standard.anchors || {};
21
+ const slug = String(anchors[anchor] ?? anchor).replace(/^#/, '');
22
+ const section = sectionBySlug(mdText, slug);
23
+ if (section) return { status: 'ok', section, slug };
24
+ return { status: 'unknown-anchor', anchors, headings: markdownHeadings(mdText).map((h) => h.slug) };
25
+ }
26
+
27
+ function readStandardMd(standardsJsonPath, standard) {
28
+ try {
29
+ return readFileSync(join(dirname(standardsJsonPath), standard.path), 'utf8');
30
+ } catch {
31
+ return null;
32
+ }
33
+ }
34
+
35
+ function showStandard(standards, standardsJsonPath, target, json) {
36
+ const hash = String(target).indexOf('#');
37
+ const id = hash === -1 ? String(target) : String(target).slice(0, hash);
38
+ const anchor = hash === -1 ? '' : String(target).slice(hash + 1).replace(/^#+/, '');
39
+ const standard = standards.find((s) => s.id === id);
40
+ if (!standard) {
41
+ const near = findStandards(standards, id.replace(/-/g, ' ')).map((s) => s.id);
42
+ if (json) console.log(JSON.stringify({ id, error: 'unknown-id', suggestions: near }));
43
+ else console.error(chalk.red(`\n❌ Standard "${id}" não existe.`) + (near.length ? chalk.gray(` Talvez: ${near.join(', ')}`) : '') + '\n');
44
+ process.exit(1);
45
+ }
46
+ const anchors = standard.anchors || {};
47
+
48
+ if (!anchor) {
49
+ if (json) {
50
+ console.log(JSON.stringify({ id: standard.id, path: standard.path, digest: standard.digest, anchors }));
51
+ process.exit(0);
52
+ }
53
+ console.log(chalk.cyan(`\n${standard.id}`) + chalk.gray(` (${standard.path})`));
54
+ console.log(`\n${standard.digest || '(sem digest)'}\n`);
55
+ console.log(chalk.bold('Âncoras') + chalk.gray(` — morph-spec standards --show ${standard.id}#<âncora>`));
56
+ for (const [key, slug] of Object.entries(anchors)) console.log(` ${key.padEnd(16)}${slug}`);
57
+ console.log('');
58
+ process.exit(0);
59
+ }
60
+
61
+ const result = resolveStandardSection(standard, readStandardMd(standardsJsonPath, standard), anchor);
62
+ if (result.status === 'ok') {
63
+ if (json) console.log(JSON.stringify({ id: standard.id, anchor, slug: result.slug, section: result.section }));
64
+ else process.stdout.write(result.section);
65
+ process.exit(0);
66
+ }
67
+ if (json) console.log(JSON.stringify({ id: standard.id, anchor, error: result.status, anchors }));
68
+ else if (result.status === 'unreadable') console.error(chalk.red(`\n❌ ${standard.path} não pôde ser lido.\n`));
69
+ else console.error(chalk.red(`\n❌ "${anchor}" não é âncora nem heading de ${standard.id}.`)
70
+ + chalk.gray(` Âncoras: ${Object.keys(anchors).join(', ') || '(nenhuma)'}\n`));
71
+ process.exit(1);
48
72
  }
49
73
 
50
- /**
51
- * category → count, sorted by count desc then name asc.
52
- * @param {object[]} standards
53
- * @returns {{ category: string, count: number }[]}
54
- */
55
74
  export function categoryCounts(standards) {
56
75
  const counts = {};
57
76
  for (const std of standards) {
@@ -63,16 +82,6 @@ export function categoryCounts(standards) {
63
82
  .sort((a, b) => b.count - a.count || a.category.localeCompare(b.category));
64
83
  }
65
84
 
66
- /**
67
- * Simple weighted relevance score for one standard against a query.
68
- * Tiers, as specified: name/id > tags(+aliases) > digest. category/subcategory
69
- * ride alongside the tags tier (lighter). A token-level fallback keeps
70
- * multi-word queries findable even without a verbatim phrase match anywhere.
71
- *
72
- * @param {object} std - one STANDARDS.json entry
73
- * @param {string} query - raw user query (already trimmed, non-empty)
74
- * @returns {number} score, 0 = no match
75
- */
76
85
  export function scoreStandard(std, query) {
77
86
  const q = query.toLowerCase();
78
87
  const tokens = q.split(/\s+/).filter((t) => t.length >= 3);
@@ -87,19 +96,15 @@ export function scoreStandard(std, query) {
87
96
 
88
97
  let score = 0;
89
98
 
90
- // Tier 1: name / id — the strongest signal.
91
99
  if (id === q || name === q) score += 20;
92
100
  else if (id.includes(q) || name.includes(q)) score += 12;
93
101
 
94
- // Tier 2: tags / aliases (curated search terms) + category/subcategory.
95
102
  if (tags.includes(q) || aliases.includes(q)) score += 8;
96
103
  else if (tags.some((t) => t.includes(q)) || aliases.some((a) => a.includes(q))) score += 5;
97
104
  if (category === q || subcategory === q) score += 4;
98
105
 
99
- // Tier 3: digest — weakest signal, full-phrase substring only.
100
106
  if (digest.includes(q)) score += 2;
101
107
 
102
- // Token-level fallback for multi-word queries with no verbatim match above.
103
108
  for (const tok of tokens) {
104
109
  if (name.includes(tok) || id.includes(tok)) score += 2;
105
110
  if (tags.some((t) => t.includes(tok)) || aliases.some((a) => a.includes(tok))) score += 1;
@@ -109,15 +114,6 @@ export function scoreStandard(std, query) {
109
114
  return score;
110
115
  }
111
116
 
112
- /**
113
- * Rank standards against a query, applying optional category/tags filters
114
- * first. Returns the TOP 3 with score > 0, sorted desc (ties broken by id).
115
- *
116
- * @param {object[]} standards
117
- * @param {string} query
118
- * @param {{ category?: string, tags?: string[] }} [filters]
119
- * @returns {Array<object & { score: number }>}
120
- */
121
117
  export function findStandards(standards, query, filters = {}) {
122
118
  const category = filters.category?.toLowerCase();
123
119
  const tags = (filters.tags || []).map((t) => t.toLowerCase());
@@ -138,15 +134,11 @@ export function findStandards(standards, query, filters = {}) {
138
134
  .slice(0, 3);
139
135
  }
140
136
 
141
- /** Parse `--tags a,b,c` into a trimmed, non-empty array. */
142
137
  function parseTagsOption(raw) {
143
138
  if (!raw) return [];
144
139
  return String(raw).split(',').map((t) => t.trim()).filter(Boolean);
145
140
  }
146
141
 
147
- /**
148
- * @param {{ find?: string, category?: string, tags?: string, json?: boolean, cwd?: string }} [options]
149
- */
150
142
  export function standardsCommand(options = {}) {
151
143
  const cwd = options.cwd || process.cwd();
152
144
  const standardsJsonPath = resolveStandardsJsonPath(cwd);
@@ -159,16 +151,16 @@ export function standardsCommand(options = {}) {
159
151
 
160
152
  let registry;
161
153
  try {
162
- registry = loadRegistry(standardsJsonPath);
154
+ registry = loadStandardsRegistry(standardsJsonPath);
163
155
  } catch (err) {
164
156
  console.error(chalk.red(`\n❌ STANDARDS.json inválido em ${standardsJsonPath}: ${err.message}\n`));
165
157
  process.exit(1);
166
158
  }
167
159
 
168
- const standards = Array.isArray(registry.standards) ? registry.standards : [];
160
+ const standards = registry.standards;
161
+ if (options.show) showStandard(standards, standardsJsonPath, options.show, options.json);
169
162
  const query = (options.find || '').trim();
170
163
 
171
- // ── Bare call (no --find): categories + counts, cheap orientation ────────
172
164
  if (!query) {
173
165
  const counts = categoryCounts(standards);
174
166
  if (options.json) {
@@ -180,11 +172,10 @@ export function standardsCommand(options = {}) {
180
172
  for (const { category, count } of counts) {
181
173
  console.log(` ${col(category, 20)}${count}`);
182
174
  }
183
- console.log(chalk.gray('\nUse --find "<query>" para buscar (top 3, com digest completo).\n'));
175
+ console.log(chalk.gray('\nUse --find "<query>" para buscar (top 3, com digest e âncoras) e --show <id>#<âncora> para ler uma seção.\n'));
184
176
  process.exit(0);
185
177
  }
186
178
 
187
- // ── --find: score + filter ────────────────────────────────────────────
188
179
  const filters = { category: options.category, tags: parseTagsOption(options.tags) };
189
180
  const results = findStandards(standards, query, filters);
190
181
 
@@ -201,7 +192,8 @@ export function standardsCommand(options = {}) {
201
192
  }
202
193
 
203
194
  const shaped = results.map((r) => ({
204
- id: r.id, name: r.name, path: r.path, category: r.category, digest: r.digest, score: r.score,
195
+ id: r.id, name: r.name, path: r.path, category: r.category, digest: r.digest,
196
+ anchors: Object.keys(r.anchors || {}), score: r.score,
205
197
  }));
206
198
 
207
199
  if (options.json) {
@@ -214,6 +206,7 @@ export function standardsCommand(options = {}) {
214
206
  console.log(chalk.cyan(`${i + 1}. ${r.id}`) + chalk.gray(` (${r.category})`));
215
207
  console.log(` ${r.path}`);
216
208
  console.log(chalk.gray(` ${r.digest}`));
209
+ if (r.anchors.length) console.log(` âncoras: ${r.anchors.join(', ')}` + chalk.gray(` → morph-spec standards --show ${r.id}#<âncora>`));
217
210
  console.log('');
218
211
  });
219
212
  process.exit(0);
@@ -1,23 +1,7 @@
1
- /**
2
- * MORPH-SPEC Feature Status Command
3
- *
4
- * Displays a comprehensive dashboard showing feature progress, phase status,
5
- * outputs, tasks, approvals, and next steps.
6
- *
7
- * Usage:
8
- * morph-spec status <feature-name>
9
- * morph-spec status <feature-name> --json
10
- *
11
- * Example:
12
- * morph-spec status user-portal
13
- */
14
-
15
1
  import chalk from 'chalk';
16
2
  import { loadState, getFeature, derivePhase, deriveOutputs } from '../../core/state/state-manager.js';
3
+ import { sliceProgress } from '../../../framework/hooks/shared/slice-progress.js';
17
4
 
18
- /**
19
- * Phase symbols for visual representation
20
- */
21
5
  const PHASE_SYMBOLS = {
22
6
  completed: '✅',
23
7
  current: '⏸️',
@@ -25,29 +9,27 @@ const PHASE_SYMBOLS = {
25
9
  skipped: '⊘'
26
10
  };
27
11
 
28
- /**
29
- * Phase definitions with order
30
- */
31
12
  const PHASE_ORDER = [
32
- { key: 'proposal', name: 'FASE 0: PROPOSAL', order: 0 },
33
- { key: 'uiux', name: 'FASE 1: UI/UX', order: 1, optional: true },
34
- { key: 'plan', name: 'FASE 2: PLAN', order: 2 },
35
- { key: 'implement', name: 'FASE 3: IMPLEMENT', order: 3 },
36
- { key: 'review', name: 'FASE 4: REVIEW', order: 4 }
13
+ { key: 'plan', name: 'FASE 1: PLAN', order: 0 },
14
+ { key: 'uiux', name: 'FASE 2: UI/UX', order: 1, optional: true },
15
+ { key: 'implement', name: 'FASE 3: IMPLEMENT', order: 2 },
16
+ { key: 'review', name: 'FASE 4: REVIEW', order: 3 }
37
17
  ];
38
18
 
39
- /**
40
- * Calculate phase status (completed, current, pending, skipped)
41
- */
19
+ const PHASE_OUTPUTS = {
20
+ plan: ['plan', 'checks'],
21
+ uiux: ['uiDesignSystem', 'uiMockups', 'uiComponents', 'uiFlows'],
22
+ implement: [],
23
+ review: ['verifierReport', 'reviewerReport']
24
+ };
25
+
42
26
  function getPhaseStatus(phaseKey, currentPhase, feature) {
43
27
  const phase = PHASE_ORDER.find(p => p.key === phaseKey);
44
28
  const current = PHASE_ORDER.find(p => p.key === currentPhase);
45
29
 
46
30
  if (!phase || !current) return 'pending';
47
31
 
48
- // Check if phase was skipped (optional phases)
49
32
  if (phase.optional && phase.order < current.order) {
50
- // Check if any outputs were created for this phase
51
33
  const hasOutputs = checkPhaseOutputs(phaseKey, feature);
52
34
  if (!hasOutputs) return 'skipped';
53
35
  }
@@ -57,25 +39,11 @@ function getPhaseStatus(phaseKey, currentPhase, feature) {
57
39
  return 'pending';
58
40
  }
59
41
 
60
- /**
61
- * Check if phase has any outputs created
62
- */
63
42
  function checkPhaseOutputs(phaseKey, feature) {
64
- const phaseOutputMap = {
65
- proposal: ['proposal', 'stackScan'],
66
- uiux: ['uiDesignSystem', 'uiMockups', 'uiComponents', 'uiFlows'],
67
- plan: ['spec', 'tasks', 'decisions'],
68
- implement: ['recap'],
69
- review: ['reviewReport']
70
- };
71
-
72
- const outputs = phaseOutputMap[phaseKey] || [];
43
+ const outputs = PHASE_OUTPUTS[phaseKey] || [];
73
44
  return outputs.some(output => feature.outputs[output]?.created);
74
45
  }
75
46
 
76
- /**
77
- * Format phase display with symbol and status
78
- */
79
47
  function formatPhase(phaseKey, currentPhase, feature, options = {}) {
80
48
  const phase = PHASE_ORDER.find(p => p.key === phaseKey);
81
49
  const status = getPhaseStatus(phaseKey, currentPhase, feature);
@@ -97,17 +65,8 @@ function formatPhase(phaseKey, currentPhase, feature, options = {}) {
97
65
  display = chalk.gray(display);
98
66
  }
99
67
 
100
- // Add output files if verbose
101
68
  if (options.verbose && status !== 'pending' && status !== 'skipped') {
102
- const phaseOutputMap = {
103
- proposal: ['proposal', 'stackScan'],
104
- uiux: ['uiDesignSystem', 'uiMockups', 'uiComponents', 'uiFlows'],
105
- plan: ['spec', 'tasks', 'decisions'],
106
- implement: ['recap'],
107
- review: ['reviewReport']
108
- };
109
-
110
- const outputs = phaseOutputMap[phaseKey] || [];
69
+ const outputs = PHASE_OUTPUTS[phaseKey] || [];
111
70
  const created = outputs.filter(o => feature.outputs[o]?.created);
112
71
  if (created.length > 0) {
113
72
  display += chalk.gray(`\n Files: ${created.length}/${outputs.length}`);
@@ -117,11 +76,8 @@ function formatPhase(phaseKey, currentPhase, feature, options = {}) {
117
76
  return display;
118
77
  }
119
78
 
120
- /**
121
- * Calculate completion percentage
122
- */
123
79
  function calculateCompletionPercentage(feature) {
124
- const totalPhases = PHASE_ORDER.filter(p => !p.optional).length; // 6 required phases
80
+ const totalPhases = PHASE_ORDER.filter(p => !p.optional).length;
125
81
  const completedPhases = PHASE_ORDER.filter(p => {
126
82
  if (p.optional) return false;
127
83
  const status = getPhaseStatus(p.key, feature.phase, feature);
@@ -131,17 +87,12 @@ function calculateCompletionPercentage(feature) {
131
87
  return Math.round((completedPhases / totalPhases) * 100);
132
88
  }
133
89
 
134
- /**
135
- * Get next steps based on current phase
136
- */
137
90
  function getNextSteps(feature) {
138
91
  const steps = [];
139
92
 
140
- // Check for pending approvals relevant to current phase
141
93
  const phaseApprovalMap = {
142
- proposal: 'proposal',
143
- uiux: 'uiux',
144
94
  plan: 'plan',
95
+ uiux: 'uiux',
145
96
  implement: 'plan',
146
97
  review: 'review'
147
98
  };
@@ -157,15 +108,7 @@ function getNextSteps(feature) {
157
108
  });
158
109
  }
159
110
 
160
- // Check for missing outputs in current phase
161
- const phaseOutputMap = {
162
- proposal: ['proposal'],
163
- plan: ['spec', 'tasks'],
164
- implement: ['recap'],
165
- review: ['reviewReport']
166
- };
167
-
168
- const requiredOutputs = phaseOutputMap[feature.phase] || [];
111
+ const requiredOutputs = feature.phase === 'uiux' ? [] : PHASE_OUTPUTS[feature.phase] || [];
169
112
  const missingOutputs = requiredOutputs.filter(o => !feature.outputs[o]?.created);
170
113
 
171
114
  if (missingOutputs.length > 0) {
@@ -176,7 +119,6 @@ function getNextSteps(feature) {
176
119
  });
177
120
  }
178
121
 
179
- // Suggest next phase if current is complete
180
122
  const hasApprovalPending = relevantGate && approvalGates[relevantGate] && !approvalGates[relevantGate].approved;
181
123
  if (missingOutputs.length === 0 && !hasApprovalPending) {
182
124
  const currentPhaseIndex = PHASE_ORDER.findIndex(p => p.key === feature.phase);
@@ -199,28 +141,6 @@ function getNextSteps(feature) {
199
141
  return steps;
200
142
  }
201
143
 
202
- /**
203
- * Estimate remaining time based on tasks
204
- */
205
- function estimateRemainingTime(feature) {
206
- if (!feature.tasks || feature.tasks.total === 0) {
207
- return 'Not estimated';
208
- }
209
-
210
- const remaining = feature.tasks.total - feature.tasks.completed;
211
- const avgHoursPerTask = 2; // Configurable estimate
212
- const hours = remaining * avgHoursPerTask;
213
-
214
- if (hours < 1) return '< 1 hour';
215
- if (hours === 1) return '1 hour';
216
- if (hours < 8) return `${hours} hours`;
217
- const days = Math.ceil(hours / 8);
218
- return `~${days} day${days > 1 ? 's' : ''} (${hours}h)`;
219
- }
220
-
221
- /**
222
- * Main status command
223
- */
224
144
  export async function statusCommand(featureName, options = {}) {
225
145
  if (!featureName) {
226
146
  console.error(chalk.red('✗ Error: Feature name required'));
@@ -242,7 +162,6 @@ export async function statusCommand(featureName, options = {}) {
242
162
  process.exit(1);
243
163
  }
244
164
 
245
- // Derive phase and outputs from filesystem if not stored in state
246
165
  const { join } = await import('path');
247
166
  const featurePath = join(process.cwd(), '.morph', 'features', featureName);
248
167
  if (!feature.phase) {
@@ -251,8 +170,8 @@ export async function statusCommand(featureName, options = {}) {
251
170
  if (!feature.outputs) {
252
171
  feature.outputs = deriveOutputs(featureName, process.cwd());
253
172
  }
173
+ const slices = sliceProgress(featurePath);
254
174
 
255
- // JSON output mode
256
175
  if (options.json) {
257
176
  const status = {
258
177
  feature: featureName,
@@ -270,28 +189,24 @@ export async function statusCommand(featureName, options = {}) {
270
189
  created: output.created,
271
190
  path: output.path
272
191
  })),
273
- tasks: feature.tasks || { total: 0, completed: 0, inProgress: 0, pending: 0 },
192
+ slices,
274
193
  approvals: feature.approvalGates || {},
275
- nextSteps: getNextSteps(feature),
276
- estimatedTimeRemaining: estimateRemainingTime(feature)
194
+ nextSteps: getNextSteps(feature)
277
195
  };
278
196
 
279
197
  console.log(JSON.stringify(status, null, 2));
280
198
  return;
281
199
  }
282
200
 
283
- // Visual dashboard output
284
201
  console.log(chalk.cyan('\n┌────────────────────────────────────────────────────────────┐'));
285
202
  console.log(chalk.cyan('│ MORPH-SPEC STATUS │'));
286
203
  console.log(chalk.cyan('└────────────────────────────────────────────────────────────┘\n'));
287
204
 
288
- // Feature info
289
205
  console.log(chalk.white.bold(`Feature: ${featureName}`));
290
206
  console.log(chalk.gray(`Status: ${feature.status || 'unknown'}`));
291
207
  console.log(chalk.gray(`Completion: ${calculateCompletionPercentage(feature)}%`));
292
208
  console.log('');
293
209
 
294
- // Phase progression
295
210
  console.log(chalk.white.bold('Phases:'));
296
211
  console.log(chalk.cyan('├─────────────────────────────────────────────────────────────┤'));
297
212
  PHASE_ORDER.forEach(phase => {
@@ -300,7 +215,6 @@ export async function statusCommand(featureName, options = {}) {
300
215
  console.log(chalk.cyan('└─────────────────────────────────────────────────────────────┘'));
301
216
  console.log('');
302
217
 
303
- // Outputs summary
304
218
  const totalOutputs = Object.keys(feature.outputs).length;
305
219
  const createdOutputs = Object.values(feature.outputs).filter(o => o.created).length;
306
220
  console.log(chalk.white.bold(`Outputs: ${createdOutputs}/${totalOutputs} complete`));
@@ -315,21 +229,16 @@ export async function statusCommand(featureName, options = {}) {
315
229
  }
316
230
  console.log('');
317
231
 
318
- // Tasks progress
319
- if (feature.tasks && feature.tasks.total > 0) {
320
- console.log(chalk.white.bold('Tasks Progress:'));
321
- const { total, completed, inProgress, pending } = feature.tasks;
322
- const percentage = total > 0 ? Math.round((completed / total) * 100) : 0;
323
-
324
- console.log(` Total: ${total}`);
325
- console.log(chalk.green(` ✓ Completed: ${completed} (${percentage}%)`));
326
- if (inProgress > 0) console.log(chalk.cyan(` ▶ In Progress: ${inProgress}`));
327
- if (pending > 0) console.log(chalk.gray(` ⬜ Pending: ${pending}`));
328
- console.log(` Estimated time remaining: ${estimateRemainingTime(feature)}`);
232
+ if (slices && slices.total > 0) {
233
+ console.log(chalk.white.bold('Fatias:'));
234
+ const percentage = Math.round((slices.done / slices.total) * 100);
235
+ console.log(` Total: ${slices.total}`);
236
+ console.log(chalk.green(` ✓ Feitas: ${slices.done} (${percentage}%)`));
237
+ if (slices.partial > 0) console.log(chalk.cyan(` ▶ Parciais: ${slices.partial}`));
238
+ if (slices.pending > 0) console.log(chalk.gray(` ⬜ Pendentes: ${slices.pending}`));
329
239
  console.log('');
330
240
  }
331
241
 
332
- // Approval gates
333
242
  if (feature.approvalGates) {
334
243
  const gates = Object.entries(feature.approvalGates);
335
244
  const approved = gates.filter(([_, g]) => g.approved).length;
@@ -349,7 +258,6 @@ export async function statusCommand(featureName, options = {}) {
349
258
  console.log('');
350
259
  }
351
260
 
352
- // Next steps
353
261
  const nextSteps = getNextSteps(feature);
354
262
  if (nextSteps.length > 0) {
355
263
  console.log(chalk.white.bold('Next Steps:'));
@@ -361,10 +269,9 @@ export async function statusCommand(featureName, options = {}) {
361
269
  });
362
270
  console.log('');
363
271
  } else {
364
- console.log(chalk.green('✓ All tasks complete!\n'));
272
+ console.log(chalk.green('✓ Nada pendente.\n'));
365
273
  }
366
274
 
367
- // Footer
368
275
  console.log(chalk.gray('─'.repeat(60)));
369
276
  console.log(chalk.gray('Run with --verbose for detailed output'));
370
277
  console.log(chalk.gray('Run with --json for JSON output\n'));