@polymorphism-tech/morph-spec 9.8.0 → 10.0.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 (185) hide show
  1. package/CLAUDE.md +10 -10
  2. package/README.md +4 -4
  3. package/bin/morph-spec.js +40 -43
  4. package/claude-plugin.json +1 -1
  5. package/docs/CHEATSHEET.md +1 -1
  6. package/docs/QUICKSTART.md +1 -1
  7. package/framework/CLAUDE.md +24 -30
  8. package/framework/MORPH.md +47 -123
  9. package/framework/agents.json +6 -374
  10. package/framework/commands/morph-apply.md +1 -1
  11. package/framework/commands/morph-archive.md +4 -3
  12. package/framework/commands/morph-hotfix.md +8 -30
  13. package/framework/commands/morph-infra.md +2 -2
  14. package/framework/commands/morph-media.md +10 -9
  15. package/framework/commands/morph-review.md +15 -0
  16. package/framework/commands/morph-status.md +1 -1
  17. package/framework/docs/CLI.md +83 -94
  18. package/framework/evals/review-checklist.md +45 -53
  19. package/framework/hooks/README.md +4 -4
  20. package/framework/hooks/claude-code/core/README.md +1 -1
  21. package/framework/hooks/claude-code/core/denylist.json +4 -4
  22. package/framework/hooks/claude-code/core/gate-guard.js +9 -0
  23. package/framework/hooks/claude-code/core/masked-exit.js +49 -0
  24. package/framework/hooks/claude-code/core/state-sync.js +4 -1
  25. package/framework/hooks/claude-code/core/telemetry-log.js +1 -2
  26. package/framework/hooks/claude-code/core/test-budget.js +10 -70
  27. package/framework/hooks/claude-code/core/validate-completion.js +11 -24
  28. package/framework/hooks/claude-code/core/worktree-context.js +5 -22
  29. package/framework/hooks/claude-code/core/worktree-create.js +6 -45
  30. package/framework/hooks/claude-code/core/worktree-env-inject.js +2 -10
  31. package/framework/hooks/shared/e2e-check.js +0 -0
  32. package/framework/hooks/shared/gate-event.js +2 -2
  33. package/framework/hooks/shared/graph-refresh.js +20 -3
  34. package/framework/hooks/shared/heavy-command.js +32 -1
  35. package/framework/hooks/shared/heavy-config.js +1 -1
  36. package/framework/hooks/shared/next-step.js +63 -24
  37. package/framework/hooks/shared/phase-utils.js +6 -9
  38. package/framework/hooks/shared/report-progress.js +86 -0
  39. package/framework/hooks/shared/state-reader.js +3 -2
  40. package/framework/hooks/statusline.js +332 -0
  41. package/framework/phases.json +32 -10
  42. package/framework/rules/ai-agents-standards.md +9 -1
  43. package/framework/rules/csharp-standards.md +4 -0
  44. package/framework/rules/ef-standards.md +20 -0
  45. package/framework/rules/frontend-standards.md +1 -1
  46. package/framework/rules/implement-report.md +25 -0
  47. package/framework/rules/infrastructure-standards.md +2 -0
  48. package/framework/rules/nextjs-standards.md +7 -0
  49. package/framework/rules/plan-grammar.md +53 -0
  50. package/framework/rules/ui-design.md +27 -0
  51. package/framework/schemas/config.schema.json +11 -18
  52. package/framework/schemas/feature.schema.json +7 -1
  53. package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
  54. package/framework/skills/core/create-umbraco-lp/references/umbraco-lp-patterns.md +1 -1
  55. package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +2 -2
  56. package/framework/skills/core/morph-apply/SKILL.md +38 -166
  57. package/framework/skills/core/morph-apply/references/debugging.md +8 -0
  58. package/framework/skills/core/morph-apply/references/hotfix.md +42 -0
  59. package/framework/skills/core/morph-apply/references/machine.md +29 -0
  60. package/framework/skills/core/{morph-media/SKILL.md → morph-apply/references/media.md} +11 -74
  61. package/framework/skills/core/morph-apply/references/review.md +65 -0
  62. package/framework/skills/core/morph-plan/SKILL.md +42 -108
  63. package/framework/skills/core/morph-plan/references/critique.md +40 -0
  64. package/framework/skills/core/morph-plan/references/interview.md +25 -0
  65. package/framework/skills/core/morph-uiux/SKILL.md +47 -64
  66. package/framework/skills/core/morph-uiux/surfaces.json +32 -0
  67. package/framework/standards/STANDARDS.json +32 -5
  68. package/framework/standards/STANDARDS.meta.json +5 -1
  69. package/framework/standards/ai-agents/agent-session.md +2 -3
  70. package/framework/standards/ai-agents/context-providers.md +2 -2
  71. package/framework/standards/ai-agents/durable-workflows-hitl.md +2 -2
  72. package/framework/standards/ai-agents/providers/model-registry.md +2 -2
  73. package/framework/standards/ai-agents/rag-custom-pgvector.md +6 -6
  74. package/framework/standards/ai-agents/setup.md +1 -1
  75. package/framework/standards/ai-agents/tool-adapters.md +2 -2
  76. package/framework/standards/architecture/stack-baseline.md +47 -0
  77. package/framework/standards/backend/integrations/neon-auth/neon-auth.md +2 -4
  78. package/framework/standards/frontend/design-system/ai-image-generation.md +51 -12
  79. package/framework/standards/frontend/design-system/ai-video-generation.md +50 -4
  80. package/framework/standards/frontend/design-system/art-direction.md +2 -2
  81. package/framework/standards/frontend/scroll-driven/frame-scrub.md +12 -2
  82. package/framework/standards/frontend/scroll-driven/scroll-components.md +76 -4
  83. package/framework/templates/REGISTRY.json +1 -2
  84. package/framework/templates/context/ARCHITECTURE.md +1 -1
  85. package/framework/templates/docs/plan.md +12 -12
  86. package/framework/templates/docs/ui-mockups.md +17 -105
  87. package/package.json +1 -1
  88. package/src/commands/e2e/e2e.js +88 -23
  89. package/src/commands/graph/diff.js +74 -0
  90. package/src/commands/graph/status.js +1 -1
  91. package/src/commands/observability/cost.js +2 -4
  92. package/src/commands/observability/telemetry.js +1 -1
  93. package/src/commands/project/doctor.js +23 -39
  94. package/src/commands/project/fleet.js +5 -6
  95. package/src/commands/project/init.js +63 -36
  96. package/src/commands/project/stack-scan.js +3 -42
  97. package/src/commands/project/stack-set.js +26 -0
  98. package/src/commands/project/status.js +12 -13
  99. package/src/commands/project/update.js +39 -3
  100. package/src/commands/project/worktree.js +3 -14
  101. package/src/commands/state/advance.js +17 -17
  102. package/src/commands/state/approve.js +0 -6
  103. package/src/commands/state/archive.js +27 -1
  104. package/src/commands/state/auto-approval.js +1 -1
  105. package/src/commands/state/create.js +0 -5
  106. package/src/commands/state/gate-check.js +37 -30
  107. package/src/commands/state/gate-decision.js +3 -2
  108. package/src/commands/state/next.js +1 -0
  109. package/src/commands/state/recap.js +67 -0
  110. package/src/commands/state/report-check.js +36 -178
  111. package/src/commands/validation/plan-check.js +16 -11
  112. package/src/commands/validation/validate-feature.js +3 -3
  113. package/src/commands/validation/verify.js +3 -6
  114. package/src/core/paths/output-schema.js +3 -3
  115. package/src/core/state/state-manager.js +2 -4
  116. package/src/dashboard/app/components/CommandPalette.jsx +2 -5
  117. package/src/dashboard/app/components/GatePauses.jsx +116 -0
  118. package/src/dashboard/app/components/SessionMap.jsx +77 -0
  119. package/src/dashboard/app/pages/Activity.jsx +4 -0
  120. package/src/dashboard/app/pages/AgentMap.jsx +1 -2
  121. package/src/dashboard/app/pages/FeatureDetail.jsx +129 -186
  122. package/src/dashboard/app/pages/Features.jsx +7 -7
  123. package/src/dashboard/app/pages/PhasePipeline.jsx +1 -1
  124. package/src/dashboard/app/pages/Portfolio.jsx +40 -5
  125. package/src/dashboard/scanner/activity-scanner.js +29 -0
  126. package/src/dashboard/scanner/agents-scanner.js +11 -14
  127. package/src/dashboard/scanner/features-scanner.js +45 -24
  128. package/src/dashboard/scanner/project-api.js +11 -2
  129. package/src/dashboard/scanner/skills-scanner.js +11 -1
  130. package/src/lib/e2e/applicability.js +3 -1
  131. package/src/lib/git/tree-state.js +1 -16
  132. package/src/lib/graph/diff-tree.js +127 -0
  133. package/src/lib/graph/graphify-runtime.js +12 -5
  134. package/src/lib/installers/memory-installer.js +2 -2
  135. package/src/lib/installers/rules-installer.js +57 -0
  136. package/src/lib/installers/stack-assets.js +17 -0
  137. package/src/lib/installers/stack-sync.js +219 -0
  138. package/src/lib/plan/checks.js +55 -110
  139. package/src/lib/plan/critique.js +28 -0
  140. package/src/lib/plan/media.js +42 -0
  141. package/src/lib/plan/plan-html.js +125 -0
  142. package/src/lib/plan/plan-parser.js +34 -45
  143. package/src/lib/recap/piper.js +36 -0
  144. package/src/lib/recap/recap.js +232 -0
  145. package/src/lib/review-reports.js +28 -4
  146. package/src/lib/risk-detector.js +90 -11
  147. package/src/lib/specs/screen-checklist.js +33 -48
  148. package/src/lib/stack/dotnet-build-ignores.js +8 -9
  149. package/src/lib/telemetry/metrics.js +27 -29
  150. package/src/lib/validators/reuse/reuse-validator.js +1 -9
  151. package/src/lib/validators/verify-runner.js +0 -7
  152. package/src/lib/worktree/fleet-scanner.js +7 -20
  153. package/src/lib/worktree/worktree-audit.js +0 -37
  154. package/src/scripts/setup-infra.js +15 -50
  155. package/src/utils/agents-installer.js +27 -201
  156. package/src/utils/hooks-installer.js +11 -95
  157. package/framework/hooks/claude-code/core/warn-bash-source-write.js +0 -23
  158. package/framework/hooks/claude-code/statusline.py +0 -699
  159. package/framework/hooks/claude-code/statusline.sh +0 -11
  160. package/framework/hooks/shared/agent-reap.js +0 -74
  161. package/framework/hooks/shared/slice-progress.js +0 -110
  162. package/framework/skills/core/morph-hotfix/SKILL.md +0 -133
  163. package/framework/skills/core/morph-machine/SKILL.md +0 -46
  164. package/framework/skills/core/morph-review/SKILL.md +0 -129
  165. package/framework/skills/core/morph-standards/SKILL.md +0 -52
  166. package/framework/standards/PROVENANCE.json +0 -119
  167. package/src/commands/project/worktree-reap.js +0 -34
  168. package/src/commands/state/handoff.js +0 -65
  169. package/src/commands/validation/mutate.js +0 -263
  170. package/src/commands/validation/scout-check.js +0 -28
  171. package/src/lib/generators/handoff-generator.js +0 -172
  172. package/src/lib/mutation/adapters.js +0 -79
  173. package/src/lib/mutation/commands.js +0 -61
  174. package/src/lib/mutation/dotnet-introspection.js +0 -281
  175. package/src/lib/mutation/manifest.js +0 -144
  176. package/src/lib/mutation/plan.js +0 -44
  177. package/src/lib/mutation/report.js +0 -68
  178. package/src/lib/mutation/runner.js +0 -301
  179. package/src/lib/mutation/schemata.js +0 -60
  180. package/src/lib/mutation/snapshot.js +0 -65
  181. package/src/lib/mutation/subset.js +0 -109
  182. package/src/lib/mutation/trx.js +0 -50
  183. package/src/lib/scout/scout-check.js +0 -293
  184. package/src/lib/validators/traceability-check.js +0 -103
  185. package/src/lib/worktree/agent-reaper.js +0 -247
package/CLAUDE.md CHANGED
@@ -40,7 +40,7 @@ No build step — pure ESM JavaScript, runs directly via Node.js 22+.
40
40
 
41
41
  ### Module Layout
42
42
 
43
- - **`bin/morph-spec.js`** — Commander.js CLI entry point: install/inspect commands plus the deterministic steps of the loop (`create`, `plan-check`, `gate-check`, `approve`/`advance`, `verify`, `report-check`, `mutate`, `finish`).
43
+ - **`bin/morph-spec.js`** — Commander.js CLI entry point: install/inspect commands plus the deterministic steps of the loop (`create`, `plan-check`, `gate-check`, `approve`/`advance`, `verify`, `report-check`, `e2e`, `finish`).
44
44
  - **`src/commands/`** — CLI command handlers organized by domain (project/, state/, validation/, scaffold/, mcp/, context/, dashboard/).
45
45
  - **`src/core/`** — Core domain logic:
46
46
  - `state/state-manager.js` — Atomic state I/O with process-ID temp files
@@ -49,14 +49,14 @@ No build step — pure ESM JavaScript, runs directly via Node.js 22+.
49
49
  - `workflows/` — Workflow type detector
50
50
  - **`src/lib/`** — Libraries and subsystems:
51
51
  - `validators/` — Validators run by the `verify` validators node (code-budget, contracts, nextjs, packages, reuse)
52
- - `generators/` — Code generation (architecture context, handoff, scaffold, settings)
52
+ - `generators/` — Code generation (architecture context, scaffold, settings)
53
53
  - `stack-filter.js` — Stack-aware asset filtering via YAML frontmatter `stacks:` tags
54
54
  - `installers/` — Agents, skills, hooks installers
55
55
  - **`src/utils/`** — Shared utilities (logger, banner, file-copier, claude-settings-manager, agents-installer, skills-installer, hooks-installer)
56
56
  - **`framework/`** — Metadata installed into target projects (READ-ONLY at runtime):
57
- - `MORPH.md` — NLH charter (the single source of behavioral truth; ≤ 20k chars, `resident-size` canary)
58
- - `CLAUDE.md` — Runtime instructions injected into target's `.claude/CLAUDE.md` (≤ 4k chars)
59
- - `agents.json` — 10 flat personas (see below); `maxTurns` per persona (ADR-004)
57
+ - `MORPH.md` — NLH charter (the single source of behavioral truth; ≤ 8k chars, `resident-size` canary)
58
+ - `CLAUDE.md` — Runtime instructions injected into target's `.claude/CLAUDE.md` (≤ 3k chars)
59
+ - `agents.json` — the 3 Gate 3 personas (see below); `maxTurns` per persona
60
60
  - `phases.json` — 4 phases (plan, uiux, implement, review)
61
61
  - `standards/STANDARDS.json` — index of available standards
62
62
  - `hooks/claude-code/core/` — fail-open guardrail hooks (+ `hooks/shared/` for what hooks and `src/` both read)
@@ -79,7 +79,7 @@ No build step — pure ESM JavaScript, runs directly via Node.js 22+.
79
79
 
80
80
  **Stack-aware filtering:** Assets declare `stacks: ['dotnet']` in YAML frontmatter or `stack: ['dotnet']` in `agents.json`. `setup-infra.js` reads `config.json → project.stack`, splits into tags, and installs only matching assets.
81
81
 
82
- **Personas, not tiers:** `agents.json` has 10 flat personas — 6 domain implementers (dotnet-senior, ef-modeler, maf-expert, nextjs-expert, ui-designer, infra-engineer), the 3 read-only Gate 3 roles (verifier, reviewer, security) and 1 stage persona (`scout`, read-only). `model` is sized per stage: `sonnet` for implementers, `scout`, `verifier` and `reviewer`; `security` and `ui-designer` (design quality is the deliverable, high effort) are `opus`; the dispatch routes the verifier to `opus` when `verifierModelFor` (risk-detector.js, read by `report-check --before-eval`) sees prompt/model or media (measured against haiku in `docs/specs/scout-evidence/decisions.md`). No tier system — Claude assumes the 3 NLH roles (Orchestrator/Specialist/Evaluator) per MORPH.md.
82
+ **Single loop:** the main session plans, implements the whole plan in one window, fixes and finishes; domain know-how lives in the stack rules `framework/rules/*-standards.md`, loaded by `paths:` when the session touches a matching file and installed by `syncStackRules` from `plan-check`/`verify`/`update` (`docs/specs/single-loop/decisions.md`, ADR-010). `agents.json` has only the 3 read-only Gate 3 roles — `verifier` (executes each `Cn`), `reviewer` (plan.md + diff), `security` (sensitive paths) — dispatched in fresh context in the same response. `reviewer` is `sonnet`, `security` is `opus`; the dispatch routes the verifier to `opus` when `verifierModelFor` (risk-detector.js, read by `report-check --before-eval`) sees prompt/model or media.
83
83
 
84
84
  ### Phase Sequence
85
85
 
@@ -87,7 +87,7 @@ No build step — pure ESM JavaScript, runs directly via Node.js 22+.
87
87
  plan → [uiux] → implement → review
88
88
  ```
89
89
 
90
- Gates: `plan` (plan.md + `checks.json` from `plan-check`), `uiux` (optional, after the plan gate, `1-design/`), `review` (Gate 3: `verifier.md` + `reviewer.md` [+ `security.md`]). Folders keep their ids: `2-plan/`, `1-design/`, `3-implement/`, `4-review/`. `chore`/`hotfix` are born with `plan` stamped by policy. Implementation unit: the slices `F1..Fn` of plan.md; progress = `3-implement/reports/F{n}.md`.
90
+ Gates: `plan` (plan.md + `checks.json` from `plan-check`), `uiux` (optional, after the plan gate, `1-design/`), `review` (Gate 3: `verifier.md` + `reviewer.md` [+ `security.md`]). Folders keep their ids: `2-plan/`, `1-design/`, `3-implement/`, `4-review/`. `chore`/`hotfix` are born with `plan` stamped by policy. Done-when = the scenarios `C1..Cn` of plan.md; progress = `3-implement/report.md` (one row per `Cn`: `pendente`/`feito`/`bloqueado`). The archive keeps `feature.json` + `2-plan/plan.md`.
91
91
 
92
92
  ### State Schema
93
93
 
@@ -96,7 +96,7 @@ Authoritative, committed state: `.morph/features/{f}/feature.json` (status, appr
96
96
  ## Testing Conventions
97
97
 
98
98
  - **Framework:** Node.js native `node:test` — no Jest or Mocha
99
- - **Concurrency:** files run in parallel (`scripts/run-tests.mjs`) — `node --test` gives each file its own process, so `process.chdir()` stays inside the file. A test never writes a tracked file of this repo: a script under test reads its root from `MORPH_REPO_ROOT`, and the test points it at `copyTrackedRepo()` (`test/helpers/repo-copy.js`, a temp git repo with the tracked files). The runner fails if a run changes the tracked tree
99
+ - **Concurrency:** files run in parallel (`scripts/run-tests.mjs`) — `node --test` gives each file its own process, so `process.chdir()` stays inside the file. A test never writes a tracked file of this repo: a script under test reads its root from `MORPH_REPO_ROOT`, and the test points it at `copyTrackedRepo()` (`test/helpers/repo-copy.js`, a temp git repo with the tracked files). The runner fails if a run changes the tracked tree. Each file has a 10-minute `--test-timeout` (it bounds the whole file under process isolation): a hang fails by name. A test that imports a hook sets `MORPH_HOOK_CHAINED=1` first, or the hook's `runStandalone` waits on stdin, which `node --test` never closes
100
100
  - **Subprocesses:** drive the CLI through `test/helpers/cli.js` (`runCli`, no shell) and git through `test/helpers/git.js` (`git(cwd, ...args)`) — `execSync('git …')` pays a cmd.exe per call on Windows. Hooks that export `run(payload)` can be called in-process (see `test/hooks/loop-detect.test.js`); keep one spawn per hook for the standalone wiring
101
101
  - **Temp dirs:** `createTempDir()` / `cleanupTempDir()` from `test/helpers/test-utils.js`
102
102
  - **Home:** a suite that runs `setupInfra`/`updateCommand`/`initCommand` calls `isolateHome()` (test-utils) at the top — the installers write `~/.claude/settings.json` through `os.homedir()`. Canary: `test/meta/home-isolation.test.js`
@@ -125,8 +125,8 @@ A matriz "mexeu em X → verifique Y" mora em `.claude/rules/matrix-*.md`, uma r
125
125
  | `.claude/rules/matrix-hooks.md` | Hooks, telemetria e comment-guard |
126
126
  | `.claude/rules/matrix-charter.md` | Carta NLH, skills e docs instaláveis |
127
127
  | `.claude/rules/matrix-templates-ai.md` | Fases, templates, ai-kit e CI |
128
- | `.claude/rules/matrix-plan-review.md` | Plano, relatórios de fatia, gates e Gate 3 |
129
- | `.claude/rules/matrix-verify.md` | Verify, testes, mutação e CI |
128
+ | `.claude/rules/matrix-plan-review.md` | Plano, progresso, gates e Gate 3 |
129
+ | `.claude/rules/matrix-verify.md` | Verify, testes e CI |
130
130
  | `.claude/rules/matrix-worktree-git.md` | Worktrees, finish e git |
131
131
  | `.claude/rules/matrix-graph.md` | Grafo de codebase e validador de reuso |
132
132
  | `.claude/rules/matrix-platform.md` | MCP, installers, procs, heavy e dashboard |
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  > Spec-driven development framework for multi-stack projects. Turns feature requests into implementation-ready code through structured, AI-orchestrated phases.
4
4
 
5
5
  **Package:** `@polymorphism-tech/morph-spec`
6
- **Version:** 9.8.0
6
+ **Version:** 10.0.0
7
7
  **Requires:** Node.js 22+, Claude Code
8
8
 
9
9
  ---
@@ -244,11 +244,11 @@ Guardrail hooks are installed into `.claude/settings.local.json` across 13 event
244
244
  | --------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
245
245
  | `SessionStart` | `worktree-context.js` | Injects feature identity (worktree) or active-feature summary (root) |
246
246
  | `PreToolUse` (Write\|Edit) | `protect-spec-files.js`, `enforce-phase-writes.js` | Freezes `plan.md` after the plan gate (only `plan-check` writes `checks.json`); enforces phase folders |
247
- | `PreToolUse` (Bash) | `pre-bash-denylist.js`, `block-destructive-worktree-removal.js`, `block-raw-worktree-add.js`, `warn-bash-source-write.js`, `heavy-gate.js`, `worktree-env-inject.js` | Destructive-command guards, worktree governance, heavy-node semaphore, per-worktree env |
247
+ | `PreToolUse` (Bash) | `pre-bash-denylist.js`, `block-destructive-worktree-removal.js`, `block-raw-worktree-add.js`, `heavy-gate.js`, `worktree-env-inject.js` | Destructive-command guards, worktree governance, heavy-node semaphore, per-worktree env |
248
248
  | `WorktreeCreate` / `WorktreeRemove` | `worktree-create.js`, `worktree-remove.js` | Native worktrees delegate to the CLI |
249
249
  | `PostToolUse` (Write\|Edit) | `comment-guard.js` | Blocks added comments the comment standard forbids |
250
250
  | `PostToolUse` | `state-sync.js`, `gate-guard.js` | Syncs feature state; enforces gate ordering |
251
- | `PostToolUse`, `PostToolUseFailure`, `PostToolBatch`, `SubagentStop`, `UserPromptSubmit` | `telemetry-log.js`, `loop-detect.js`, `graph-refresh-kick.js`, `heavy-release.js` | Telemetry, repeated-action loops, graph refresh, heavy-slot release |
251
+ | `PostToolUse`, `PostToolUseFailure`, `PostToolBatch`, `SubagentStop`, `UserPromptSubmit` | `telemetry-log.js`, `loop-detect.js`, `graph-refresh-kick.js`, `heavy-release.js`, `masked-exit.js` | Telemetry, repeated-action loops, graph refresh, heavy-slot release, masked test exit warning |
252
252
  | `Stop` | `validate-completion.js` | Warns about incomplete tasks, missing outputs, or pending approval gates |
253
253
 
254
254
 
@@ -380,4 +380,4 @@ Code generated by morph-spec (contracts, templates, implementation output) belon
380
380
 
381
381
  ---
382
382
 
383
- *morph-spec v9.8.0 by [Polymorphism Tech](https://polymorphism.tech)*
383
+ *morph-spec v10.0.0 by [Polymorphism Tech](https://polymorphism.tech)*
package/bin/morph-spec.js CHANGED
@@ -23,16 +23,15 @@ const worktreeProvisionCommand = lazy('../src/commands/project/worktree.js', 'wo
23
23
  const worktreeLinkCommand = lazy('../src/commands/project/worktree.js', 'worktreeLinkCommand');
24
24
  const worktreeListCommand = lazy('../src/commands/project/worktree.js', 'worktreeListCommand');
25
25
  const worktreeRemoveCommand = lazy('../src/commands/project/worktree.js', 'worktreeRemoveCommand');
26
- const worktreeReapCommand = lazy('../src/commands/project/worktree-reap.js', 'worktreeReapCommand');
27
26
  const branchPruneCommand = lazy('../src/commands/project/branch.js', 'branchPruneCommand');
28
27
  const fleetCommand = lazy('../src/commands/project/fleet.js', 'fleetCommand');
29
28
  const envCommand = lazy('../src/commands/project/env.js', 'envCommand');
30
29
  const claimCommand = lazy('../src/commands/project/claim.js', 'claimCommand');
31
30
  const standardsCommand = lazy('../src/commands/project/standards.js', 'standardsCommand');
32
31
  const reportCheckCommand = lazy('../src/commands/state/report-check.js', 'reportCheckCommand');
33
- const scoutCheckCommand = lazy('../src/commands/validation/scout-check.js', 'scoutCheckCommand');
34
32
  const planCheckCommand = lazy('../src/commands/validation/plan-check.js', 'planCheckCommand');
35
33
  const stackScanCommand = lazy('../src/commands/project/stack-scan.js', 'stackScanCommand');
34
+ const stackSetCommand = lazy('../src/commands/project/stack-set.js', 'stackSetCommand');
36
35
  const testsAuditCommand = lazy('../src/commands/validation/tests-audit.js', 'testsAuditCommand');
37
36
 
38
37
  const approveCommand = lazy('../src/commands/state/approve.js', 'approveCommand');
@@ -40,12 +39,12 @@ const approvalStatusCommand = lazy('../src/commands/state/approve.js', 'approval
40
39
  const unapproveCommand = lazy('../src/commands/state/approve.js', 'unapproveCommand');
41
40
  const advanceCommand = lazy('../src/commands/state/advance.js', 'advanceCommand');
42
41
  const archiveCommand = lazy('../src/commands/state/archive.js', 'archiveCommand');
42
+ const recapCommand = lazy('../src/commands/state/recap.js', 'recapCommand');
43
43
  const finishCommand = lazy('../src/commands/state/finish.js', 'finishCommand');
44
44
  const gateDecisionCommand = lazy('../src/commands/state/gate-decision.js', 'gateDecisionCommand');
45
45
  const gateCheckCommand = lazy('../src/commands/state/gate-check.js', 'gateCheckCommand');
46
46
  const createCommand = lazy('../src/commands/state/create.js', 'createCommand');
47
47
  const retypeCommand = lazy('../src/commands/state/retype.js', 'retypeCommand');
48
- const handoffCommand = lazy('../src/commands/state/handoff.js', 'handoffCommand');
49
48
  const nextCommand = lazy('../src/commands/state/next.js', 'nextCommand');
50
49
  const listCommand = lazy('../src/commands/state/list.js', 'listCommand');
51
50
  const deleteCommand = lazy('../src/commands/state/delete.js', 'deleteCommand');
@@ -54,14 +53,15 @@ const graphStatusCommand = lazy('../src/commands/graph/status.js', 'graphStatusC
54
53
  const graphBuildCommand = lazy('../src/commands/graph/build.js', 'graphBuildCommand');
55
54
  const graphAffectedCommand = lazy('../src/commands/graph/affected.js', 'graphAffectedCommand');
56
55
  const graphExplainCommand = lazy('../src/commands/graph/explain.js', 'graphExplainCommand');
56
+ const graphDiffCommand = lazy('../src/commands/graph/diff.js', 'graphDiffCommand');
57
57
 
58
58
  const validateCommand = lazy('./validate.js', 'validateCommand');
59
59
  const validateFeatureCommand = lazy('../src/commands/validation/validate-feature.js', 'validateFeatureCommand');
60
60
  const verifyCommand = lazy('../src/commands/validation/verify.js', 'verifyCommand');
61
- const mutateCommand = lazy('../src/commands/validation/mutate.js', 'mutateCommand');
62
61
  const e2eUpCommand = lazy('../src/commands/e2e/e2e.js', 'e2eUpCommand');
63
62
  const e2eStatusCommand = lazy('../src/commands/e2e/e2e.js', 'e2eStatusCommand');
64
63
  const e2eDownCommand = lazy('../src/commands/e2e/e2e.js', 'e2eDownCommand');
64
+ const e2eResetCommand = lazy('../src/commands/e2e/e2e.js', 'e2eResetCommand');
65
65
 
66
66
  const scaffoldDotnetCommand = lazy('../src/commands/scaffold/scaffold.js', 'scaffoldDotnetCommand');
67
67
  const scaffoldNextjsCommand = lazy('../src/commands/scaffold/scaffold.js', 'scaffoldNextjsCommand');
@@ -102,6 +102,8 @@ program
102
102
  .option('-f, --force', 'Overwrite existing MORPH installation')
103
103
  .option('-p, --path <path>', 'Target path (default: current directory)')
104
104
  .option('--skip-mcp', 'Skip MCP server auto-setup')
105
+ .option('--stack <stack>', 'Empty project: declare the stack without asking (dotnet, nextjs or dotnet+nextjs)')
106
+ .option('--with <integrations>', 'With --stack: comma-separated integrations (neon, maf, docker)')
105
107
  .action(initCommand);
106
108
 
107
109
  program
@@ -181,6 +183,14 @@ program
181
183
  .option('--force', 'Archive even if Gate 3 (review) is not approved')
182
184
  .action((feature, options) => archiveCommand(feature, options));
183
185
 
186
+ program
187
+ .command('recap <feature>')
188
+ .description('Recap animado da feature (cenários provados, estados, o que mudou, gates), com legenda e narração; o finish já gera')
189
+ .option('--piper', 'Narra com o Piper local (áudio embutido, gravado no temp); sem ele, voz do sistema')
190
+ .option('-p, --path <path>', 'Target path (default: current directory)')
191
+ .option('--json', 'Output as JSON')
192
+ .action((feature, options) => recapCommand(feature, options));
193
+
184
194
  program
185
195
  .command('finish <feature>')
186
196
  .description('Close a feature: archive → integrate. --merge merges morph/{f} into the default (local); --pr pushes it + opens a PR. Works with and without a worktree')
@@ -259,13 +269,6 @@ program
259
269
  .option('--json', 'Output as JSON')
260
270
  .action((feature, newType, options) => retypeCommand(feature, newType, options));
261
271
 
262
- program
263
- .command('handoff <feature>')
264
- .description('Generate the compressed session-handoff document (.morph/features/{f}/handoff.md) — pointers, not copies. Resolves the tree that owns the feature\'s state (worktree, or morph/{feature} if only committed) and writes there — not necessarily cwd.')
265
- .option('--json', 'Output as JSON')
266
- .option('--here', 'Force building/writing in the current directory, even if another tree owns this feature')
267
- .action((feature, options) => handoffCommand(feature, options));
268
-
269
272
  program
270
273
  .command('next <feature>')
271
274
  .description('The next step of the loop, decided from disk (phase, gates, slice reports, verify stamp, fail streak) in the tree that owns the feature. Read-only.')
@@ -313,6 +316,14 @@ graphCommand
313
316
  .option('--json', 'Output as JSON')
314
317
  .action((symbol, options) => graphExplainCommand(symbol, options));
315
318
 
319
+ graphCommand
320
+ .command('diff')
321
+ .description('Árvore de chamadas do que mudou (+ novo, ~ alterado), do merge-base ao HEAD; recusa grafo que não é deste commit')
322
+ .option('-p, --path <path>', 'Target path (default: current directory)')
323
+ .option('--base <ref>', 'Base do diff (default: merge-base com a branch padrão)')
324
+ .option('--json', 'Output as JSON')
325
+ .action((options) => graphDiffCommand(options));
326
+
316
327
  program
317
328
  .command('validate [validator]')
318
329
  .description('Run project validations (all | packages | next-components | spec-tasks)')
@@ -356,18 +367,6 @@ program
356
367
  verifyCommand(feature, { ...options, noPersist: options.persist === false })
357
368
  );
358
369
 
359
- program
360
- .command('mutate [feature]')
361
- .description('Prova de mutação do Gate 3 em lote: lê o manifesto de mutantes, roda todos (um build de schemata em .NET, subconjunto primeiro, suíte inteira só para sobrevivente), restaura os bytes e imprime a seção `## Mutações`')
362
- .option('--plan <file>', 'Manifesto JSON (default: .morph/features/<feature>/4-review/mutants.json)')
363
- .option('--out <file>', 'Onde gravar a seção `## Mutações` (default: 4-review/mutation-section.md)')
364
- .option('--allow-dirty', 'Permite mutar arquivo com alteração não commitada (o snapshot é o único caminho de volta)')
365
- .option('--jobs <n>', 'Rodadas de subconjunto em paralelo (default 2); cada worker toma um slot heavy livre, e sem slot livre a rodada degrada para sequencial', (v) => Number.parseInt(v, 10))
366
- .option('--timeout <ms>', 'Teto de cada comando de build/teste', (v) => Number.parseInt(v, 10))
367
- .option('--restore', 'Recupera o disco de uma rodada que morreu no meio: restaura os bytes do journal, sem rodar nada')
368
- .option('--json', 'Output as JSON')
369
- .action((feature, options) => mutateCommand(feature, options));
370
-
371
370
  const scaffoldCmd = program
372
371
  .command('scaffold')
373
372
  .description('Generate feature files from templates');
@@ -443,6 +442,12 @@ e2eCommand
443
442
  .option('--json', 'Output as JSON')
444
443
  .action((feature, options) => e2eDownCommand(feature, options));
445
444
 
445
+ e2eCommand
446
+ .command('reset <feature>')
447
+ .description('Put the running stack\'s data back in a known state between verification flows: e2e.resetCommand, or recreate the non-built services that own a named volume; then the auth seed. App services and e2e.hostServices are not restarted. Exit 1 when the stack is not up')
448
+ .option('--json', 'Output as JSON')
449
+ .action((feature, options) => e2eResetCommand(feature, options));
450
+
446
451
  const heavyCommand = program
447
452
  .command('heavy')
448
453
  .description('Slots por usuário para os nós pesados (build, testes, e2e), compartilhados entre as sessões');
@@ -496,14 +501,6 @@ worktreeCommand
496
501
  .option('--json', 'Output as JSON (always JSON)')
497
502
  .action((feature, options) => worktreeRemoveCommand(feature, options));
498
503
 
499
- worktreeCommand
500
- .command('reap')
501
- .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')
502
- .option('--dry-run', 'Report what would be removed without touching anything')
503
- .option('--grace <minutes>', 'Minutes a stopped agent must stay quiet before its tree is reaped (default 30, or worktree.reap.graceMinutes)')
504
- .option('--json', 'Output as a single JSON line')
505
- .action((options) => worktreeReapCommand(options));
506
-
507
504
  worktreeCommand
508
505
  .command('list')
509
506
  .description('List active feature worktrees with their phase and gate status')
@@ -532,7 +529,7 @@ program
532
529
 
533
530
  program
534
531
  .command('fleet')
535
- .description('Fleet view — every active feature across primary root and worktrees (phase, gates, tasks, ports, handoff, activity)')
532
+ .description('Fleet view — every active feature across primary root and worktrees (phase, gates, scenarios, ports, activity)')
536
533
  .option('--json', 'Output as JSON')
537
534
  .action((options) => fleetCommand(options));
538
535
 
@@ -556,18 +553,11 @@ program
556
553
  .action((options) => standardsCommand(options));
557
554
 
558
555
  program
559
- .command('report-check <feature> [slices...]')
560
- .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')
556
+ .command('report-check <feature>')
557
+ .description('State of the Gate 3 reports (4-review/), scenario progress of 3-implement/report.md and the tree they were written against')
561
558
  .option('--before-eval', 'Save a snapshot of the tree before dispatching the review agents and print their models; later runs report what changed since')
562
559
  .option('--json', 'Output as JSON')
563
- .action((feature, slices, options) => reportCheckCommand(feature, slices, options));
564
-
565
- program
566
- .command('scout-check <map>')
567
- .description('Audit a scout map: every path:line citation must exist and carry the literal line it quotes (±2 lines); absence/liveness verdicts only as hypotheses with the search command and its raw count. Exits 0 only when nothing failed')
568
- .option('--root <dir>', 'Tree the citations are relative to (default: top of the current worktree)')
569
- .option('--json', 'Output as JSON')
570
- .action((map, options) => scoutCheckCommand(map, options));
560
+ .action((feature, options) => reportCheckCommand(feature, options));
571
561
 
572
562
  program
573
563
  .command('plan-check <feature>')
@@ -579,10 +569,17 @@ program
579
569
 
580
570
  program
581
571
  .command('stack-scan [feature]')
582
- .description('Audit the code against config.project.stack, judging only the configured stacks (runtime, ORM, database, Guid.NewGuid, generic repository, service layer, raw SQL, sealed, router, UI library) by severity. With a feature, write .morph/features/<f>/2-plan/stack-scan.md; without, print the report')
572
+ .description('Audit the code against config.project.stack, judging only the configured stacks (runtime, ORM, database, Guid.NewGuid, generic repository, service layer, raw SQL, sealed, router, UI library) by severity. Prints the report (markdown, or --json); never writes a file')
583
573
  .option('--json', 'Output as JSON')
584
574
  .action((feature, options) => stackScanCommand(feature, options));
585
575
 
576
+ program
577
+ .command('stack-set <stack>')
578
+ .description('Declare the project stack (dotnet, nextjs or dotnet+nextjs) in config.json and install its domain rules into .claude/rules/; rules load when a Claude Code session starts')
579
+ .option('--with <integrations>', 'Comma-separated integrations (neon, maf, docker)')
580
+ .option('--json', 'Output as JSON')
581
+ .action((stack, options) => stackSetCommand(stack, options));
582
+
586
583
  program
587
584
  .command('tests-audit')
588
585
  .description('Read-only audit of the tracked test files: case count, largest files, tests that pin prose or a constant, [Fact] families that are [Theory] candidates, and one subject tested in several layers — candidates to delete or merge, never verdicts')
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "morph-spec",
3
- "version": "9.8.0",
3
+ "version": "10.0.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.8.0 by Polymorphism Tech*
188
+ *morph-spec v10.0.0 by Polymorphism Tech*
@@ -249,4 +249,4 @@ morph-spec doctor
249
249
 
250
250
  ---
251
251
 
252
- *morph-spec v9.8.0 by Polymorphism Tech*
252
+ *morph-spec v10.0.0 by Polymorphism Tech*
@@ -4,47 +4,41 @@
4
4
 
5
5
  ## Início de cada sessão
6
6
 
7
- 1. Leia `.morph/framework/MORPH.md` uma vez (de novo após `/compact`): papéis, fases, gates, dispatch.
8
- 2. O SessionStart injeta a feature ativa e `▶ próximo:`; sem ele, `morph-spec next <f>`. Estado autoritativo: `.morph/features/{f}/feature.json` (`state.json` é índice — nunca edite).
9
- 3. Feature em andamento → faça o que o `next` manda, entre gates, sem esperar instrução. Nenhuma ativa → pergunte qual trabalhar.
7
+ 1. Leia `.morph/framework/MORPH.md` uma vez (de novo após `/compact`).
8
+ 2. O SessionStart injeta a feature ativa e `▶ próximo:`; sem ele, `morph-spec next <f>`. Estado autoritativo: `.morph/features/{f}/feature.json` — só pela CLI.
9
+ 3. Feature em andamento → faça o que o `next` manda, sem esperar instrução. Nenhuma → pergunte qual.
10
10
 
11
11
  ## Regras
12
12
 
13
- - Perguntas ao usuário só por `AskUserQuestion` (1-4 por chamada), nunca em texto solto. Na entrevista da `morph-plan`, **uma pergunta por chamada**: lote impede que uma resposta pode os ramos seguintes. Única exceção: ferramenta indisponível ou negada (headless) — texto numerado com a resposta recomendada e gate pausado (`morph-plan` §3).
14
- - A pergunta de gate nomeia a feature ("Gate do plano — Plano de {feature} aprovado?"): é por esse nome que o hook `state-sync` grava a aprovação no `feature.json` certo; sem nome, com mais de uma feature, ele recusa e você aprova por `morph-spec approve <feature> <gate>`.
15
- - Estado só pela CLI, nunca à mão: `feature.json`, `gateDecisions`, `checks.json` (escrito só por `plan-check`) e o corpo do `plan.md` depois do gate (fato errado → `## Errata` no fim; escopo mudou → `unapprove`).
16
- - SessionStart avisou claim vivo de outra sessão na mesma feature → confirme com o usuário antes de `finish`/`archive`/`delete`.
17
- - Depois de um dispatch, leia o arquivo de relatório da fatia, não a mensagem final, que pode não chegar.
13
+ - Perguntas só por `AskUserQuestion`; na entrevista do plano, uma por chamada. Headless: texto numerado com a recomendada e gate pausado.
14
+ - A pergunta de gate nomeia a feature ("Gate do plano — Plano de {f} aprovado?"): é por ela que o hook `state-sync` grava a aprovação.
15
+ - "Não li" ou "não entendi" depois de uma saída longa → refaça do zero, sem supor que a anterior foi lida: até 5 passos numerados, uma frase cada, o primeiro sendo o que mudou para o usuário.
16
+ - Plano aprovado congela: fato errado → `## Errata` no fim; escopo mudou → `unapprove`.
17
+ - SessionStart avisou claim de outra sessão na feature → confirme antes de `finish`/`archive`/`delete`.
18
18
 
19
19
  ## CLI do loop
20
20
 
21
- Prefixo `morph-spec`; flags e porquês em `.morph/framework/CLI.md` (um `###` por comando).
21
+ Prefixo `morph-spec`; detalhe em `.morph/framework/CLI.md`.
22
22
 
23
23
  | Comando | Para quê |
24
24
  |---|---|
25
- | `create <f> --description "…" --type <t> [--worktree]` | nasce a feature; exit 2 = você escolhe o tipo |
26
- | `next <f>` | o próximo passo, decidido do disco |
27
- | `stack-scan [f]` | desvios do código contra `project.stack` |
28
- | `tests-audit` | candidatos a apagar/fundir na suíte (só lê) |
29
- | `plan-check <f>` | valida `plan.md`, grava `checks.json`, imprime as ondas |
30
- | `gate-check <f> <gate>` | decide a pausa pelos sinais do disco |
31
- | `approve <f> <gate> --mode auto` / `advance <f>` | aprova (advance também abre a próxima fase) |
25
+ | `create <f> --request "…" [--worktree]` | nasce a feature |
26
+ | `next <f>` | o próximo passo, do disco |
27
+ | `plan-check <f>` | valida o plano, grava `checks.json` |
28
+ | `gate-check <f> <gate>` / `approve` / `advance` | decide e aprova gates |
32
29
  | `verify <f> [--ci]` | build + testes + validadores + e2e, sem filtro |
33
- | `report-check <f> [F1 …]` | audita o relatório de cada fatia e diz a ação |
34
- | `mutate <f>` | mutação dirigida do Gate 3 (até 3 mutantes) |
35
- | `finish <f> --pr\|--merge` | encerra; só o `--merge` integra |
36
- | `standards --find "<tema>"` / `--show <id>#<âncora>` | digest do standard / uma seção |
37
- | `heavy status\|run -- <cmd>` | fila de build/teste; exit 3 = fila cheia |
38
- | `worktree setup\|provision\|link\|remove\|list\|reap` | ciclo da worktree; `remove` é a única remoção segura |
39
- | `graph affected\|explain <sym>` | blast radius; sem grafo, caia para grep |
30
+ | `report-check <f> [--before-eval]` | estado dos relatórios do Gate 3 |
31
+ | `e2e up\|status\|reset\|down <f>` | stack da feature |
32
+ | `finish <f> --pr\|--merge` | encerra; grava o recap animado no archive |
33
+ | `standards --find "<tema>"` | digest do standard |
34
+ | `heavy run -- <cmd>` | build/teste pesado na fila |
35
+ | `worktree setup\|provision\|link\|remove\|list` | ciclo da worktree; `remove` é a única remoção segura |
36
+ | `graph affected\|explain <sym>` | blast radius; sem grafo, grep |
37
+ | `graph diff [--base <ref>]` | árvore de chamadas do que mudou; recusa grafo velho |
40
38
 
41
- ## Slash commands
39
+ ## Gate 3 (sub-agents)
42
40
 
43
- `/morph-plan {f}` (plano), `/morph-apply {f}` (execução + Gate 3), `/morph-hotfix {f}`, `/morph-status [f]`.
44
-
45
- ## Personas (em `.claude/agents/`)
46
-
47
- Despache fatias com `subagent_type: "morph-{id}"` — a persona, gerada de `agents.json`, é o system prompt. Tipo não registrado: `general-purpose` com o `persona` colado, registrado no relatório da fatia. Nunca edite `.claude/agents/morph-*.md` à mão (`morph-spec doctor` acusa o drift).
41
+ `morph-verifier`, `morph-reviewer`, `morph-security` em `.claude/agents/`, gerados de `agents.json` — nunca edite à mão. Com a crítica do plano (`Plan` nativo, `morph-plan`), são os únicos sub-agents do fluxo; o resto é feito nesta sessão. Leia o relatório que gravam, não a mensagem final.
48
42
 
49
43
  <!-- morph-agents:start -->
50
44
  _Lista derivada na instalação. Bloco vazio → `morph-spec setup-infra --reinstall`._
@@ -52,4 +46,4 @@ _Lista derivada na instalação. Bloco vazio → `morph-spec setup-infra --reins
52
46
 
53
47
  ## Precedência de skills
54
48
 
55
- Com o plugin superpowers ativo, `morph-*` vence o equivalente genérico (aplica os gates e os paths de `.morph/`), e `using-git-worktrees`→`morph-spec worktree setup|provision`.
49
+ `morph-*` vence o equivalente genérico; `using-git-worktrees` → `morph-spec worktree setup|provision`.