@polymorphism-tech/morph-spec 8.4.0 → 8.6.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.
- package/README.md +8 -5
- package/bin/morph-spec.js +13 -10
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +7 -4
- package/docs/QUICKSTART.md +7 -4
- package/framework/CLAUDE.md +11 -8
- package/framework/MORPH.md +24 -4
- package/framework/commands/morph-archive.md +11 -4
- package/framework/evals/rubrics/test-coverage.md +4 -1
- package/framework/hooks/shared/phase-utils.js +1 -0
- package/framework/rules/morph-workflow.md +2 -2
- package/framework/schemas/feature.schema.json +2 -2
- package/framework/schemas/tasks.schema.json +6 -1
- package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
- package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +1 -1
- package/framework/skills/core/morph-apply/SKILL.md +8 -5
- package/framework/skills/core/morph-brainstorming/SKILL.md +4 -3
- package/framework/skills/core/morph-eval/SKILL.md +1 -1
- package/framework/skills/core/morph-hotfix/SKILL.md +3 -3
- package/framework/skills/core/morph-implement/SKILL.md +1 -1
- package/framework/skills/core/morph-plan/SKILL.md +83 -13
- package/framework/skills/core/morph-proposal/SKILL.md +1 -1
- package/framework/skills/core/morph-review/SKILL.md +4 -2
- package/framework/skills/core/morph-stack-scan/SKILL.md +1 -1
- package/framework/skills/core/morph-standards/SKILL.md +1 -1
- package/package.json +1 -1
- package/src/commands/project/worktree.js +154 -357
- package/src/commands/state/archive.js +186 -69
- package/src/commands/state/create.js +46 -2
- package/src/commands/state/finish.js +433 -0
- package/src/commands/tasks/dag.js +25 -2
- package/src/commands/validation/validate-feature.js +9 -2
- package/src/core/paths/output-schema.js +66 -6
- package/src/core/state/state-manager.js +2 -2
- package/src/dashboard/scanner/state-scanner.js +1 -1
- package/src/lib/agents/output-collector.js +5 -0
- package/src/lib/generators/handoff-generator.js +6 -4
- package/src/lib/git/default-branch.js +73 -0
- package/src/lib/specs/usecase-check.js +173 -0
- package/src/lib/specs/usecase-promoter.js +120 -0
- package/src/lib/tasks/tasks-json-parser.js +8 -0
- package/src/lib/worktree/env-allocator.js +1 -1
- package/src/utils/file-copier.js +2 -2
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:** 8.
|
|
6
|
+
**Version:** 8.6.0
|
|
7
7
|
**Requires:** Node.js 22+, Claude Code
|
|
8
8
|
|
|
9
9
|
---
|
|
@@ -140,7 +140,7 @@ These commands are available inside Claude Code after init.
|
|
|
140
140
|
| `/morph-apply {feature}` | Autonomous execution + review (Gate 3) |
|
|
141
141
|
| `/morph-hotfix {feature}` | Surgical hotfix ADW — scout → fix → human Gate 3 → ship |
|
|
142
142
|
| `/morph-status [feature]` | Status of the active (or specified) feature |
|
|
143
|
-
| `/morph-archive {feature}` | Archive
|
|
143
|
+
| `/morph-archive {feature}` | Archive **without integrating** (legacy feature / cleanup); normal close is `morph-spec finish --pr\|--merge` |
|
|
144
144
|
| `/morph-preflight` | Pre-deploy validation (specs, contracts, tests, infra) |
|
|
145
145
|
| `/morph-troubleshoot [error]` | Root-cause diagnosis for .NET/Next.js errors |
|
|
146
146
|
|
|
@@ -167,9 +167,12 @@ morph-spec status {feature} # Feature status dashboard
|
|
|
167
167
|
morph-spec approve {feature} {gate} # Approve a phase gate (proposal, plan, review)
|
|
168
168
|
morph-spec advance {feature} # Approve the current gate and scaffold the next phase folder
|
|
169
169
|
morph-spec approval-status {feature} # Show approval status for all gates
|
|
170
|
-
morph-spec
|
|
170
|
+
morph-spec finish {feature} --pr|--merge # Close a feature: archive + integrate (PR or local merge) + teardown
|
|
171
|
+
morph-spec archive {feature} # Archive WITHOUT integrating (legacy feature / cleanup)
|
|
171
172
|
```
|
|
172
173
|
|
|
174
|
+
`finish` is the normal close for both flows: it archives (committing the move inside `morph/{feature}`), then integrates — `--merge` merges `--no-ff` into the default branch locally; `--pr` pushes the branch and runs `gh pr create` (needs `origin` + authenticated `gh`) — and tears down the worktree if there is one. Plain `archive` is reserved for legacy features (born before every feature had a `morph/{feature}` branch) and cleanup.
|
|
175
|
+
|
|
173
176
|
Task progress within a feature is tracked with the native `TaskCreate`/`TaskUpdate` tools, persisted to `tasks.json` — there is no separate CLI command for starting or completing a task.
|
|
174
177
|
|
|
175
178
|
### Validation
|
|
@@ -196,8 +199,8 @@ morph-spec dag {feature} [--mermaid] # DAG dispatch d
|
|
|
196
199
|
morph-spec create {feature} --description "<what/why>" --worktree # Birth the feature already isolated in its own worktree
|
|
197
200
|
morph-spec worktree setup {feature} # Create .worktrees/{feature}/ on branch morph/{feature}
|
|
198
201
|
morph-spec worktree link [--all] # Relink shared infra (node_modules, .claude, .morph/framework)
|
|
199
|
-
morph-spec worktree finish {feature} # Merge --no-ff back to the primary root, clean up (requires Gate 3)
|
|
200
202
|
morph-spec worktree list [--json] # List active feature worktrees with phase/gate status
|
|
203
|
+
# Close a worktree feature with `morph-spec finish {feature} --pr|--merge` (see Feature workflow) — it absorbed `worktree finish`.
|
|
201
204
|
```
|
|
202
205
|
|
|
203
206
|
---
|
|
@@ -365,4 +368,4 @@ Code generated by morph-spec (contracts, templates, implementation output) belon
|
|
|
365
368
|
|
|
366
369
|
---
|
|
367
370
|
|
|
368
|
-
*morph-spec v8.
|
|
371
|
+
*morph-spec v8.6.0 by [Polymorphism Tech](https://polymorphism.tech)*
|
package/bin/morph-spec.js
CHANGED
|
@@ -23,13 +23,14 @@ import { installPluginCommand } from '../src/commands/project/install-plugin-cmd
|
|
|
23
23
|
import { updateCommand } from '../src/commands/project/update.js';
|
|
24
24
|
import { doctorCommand } from '../src/commands/project/doctor.js';
|
|
25
25
|
import { statusCommand } from '../src/commands/project/status.js';
|
|
26
|
-
import { worktreeSetupCommand, worktreeLinkCommand,
|
|
26
|
+
import { worktreeSetupCommand, worktreeLinkCommand, worktreeListCommand } from '../src/commands/project/worktree.js';
|
|
27
27
|
import { fleetCommand } from '../src/commands/project/fleet.js';
|
|
28
28
|
|
|
29
29
|
// === Approval gates (human-only) ===
|
|
30
30
|
import { approveCommand, approvalStatusCommand, unapproveCommand } from '../src/commands/state/approve.js';
|
|
31
31
|
import { advanceCommand } from '../src/commands/state/advance.js';
|
|
32
32
|
import { archiveCommand } from '../src/commands/state/archive.js';
|
|
33
|
+
import { finishCommand } from '../src/commands/state/finish.js';
|
|
33
34
|
import { scoreCommand } from '../src/commands/state/score.js';
|
|
34
35
|
import { gateDecisionCommand } from '../src/commands/state/gate-decision.js';
|
|
35
36
|
import { createCommand } from '../src/commands/state/create.js';
|
|
@@ -158,11 +159,21 @@ program
|
|
|
158
159
|
|
|
159
160
|
program
|
|
160
161
|
.command('archive <feature>')
|
|
161
|
-
.description('Archive a completed feature (atomic, git-aware): move folder + update state')
|
|
162
|
+
.description('Archive a completed feature (atomic, git-aware): move folder + update state. Archive WITHOUT integrating (legacy features, cleanup) — the close path is `finish`')
|
|
162
163
|
.option('--no-git', 'Skip git staging of the move')
|
|
163
164
|
.option('--force', 'Archive even if Gate 3 (review) is not approved')
|
|
164
165
|
.action((feature, options) => archiveCommand(feature, options));
|
|
165
166
|
|
|
167
|
+
program
|
|
168
|
+
.command('finish <feature>')
|
|
169
|
+
.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')
|
|
170
|
+
.option('--pr', 'Push morph/{feature} and open a PR against the default branch (no local merge)')
|
|
171
|
+
.option('--merge', 'Merge morph/{feature} into the default branch locally (no push)')
|
|
172
|
+
.option('--keep', 'Keep the worktree/branch after integrating (worktree flow only)')
|
|
173
|
+
.option('--force', 'Skip the Gate-3-approved precondition')
|
|
174
|
+
.option('--discard-ignored', 'Allow removing the worktree even though it holds gitignored files that exist nowhere else (e.g. .env) — they are destroyed')
|
|
175
|
+
.action((feature, options) => finishCommand(feature, options));
|
|
176
|
+
|
|
166
177
|
program
|
|
167
178
|
.command('delete <feature>')
|
|
168
179
|
.description('Delete a feature (hard by default; --archive marks it abandoned). Refuses if a gate is approved unless --force')
|
|
@@ -341,14 +352,6 @@ worktreeCommand
|
|
|
341
352
|
.option('--all', 'Link all shared dirs, not just node_modules')
|
|
342
353
|
.action((options) => worktreeLinkCommand(options));
|
|
343
354
|
|
|
344
|
-
worktreeCommand
|
|
345
|
-
.command('finish <feature>')
|
|
346
|
-
.description('Merge the feature branch back into the primary root and clean up the worktree (requires Gate 3 approved)')
|
|
347
|
-
.option('--keep', 'Keep the worktree and branch after merging')
|
|
348
|
-
.option('--force', 'Skip the Gate-3-approved precondition')
|
|
349
|
-
.option('--discard-ignored', 'Allow removing the worktree even though it holds gitignored files that exist nowhere else (e.g. .env) — they are destroyed')
|
|
350
|
-
.action((feature, options) => worktreeFinishCommand(feature, options));
|
|
351
|
-
|
|
352
355
|
worktreeCommand
|
|
353
356
|
.command('list')
|
|
354
357
|
.description('List active feature worktrees with their phase and gate status')
|
package/claude-plugin.json
CHANGED
package/docs/CHEATSHEET.md
CHANGED
|
@@ -46,7 +46,7 @@ proposal → [uiux] → plan → implement → review
|
|
|
46
46
|
| `/morph-hotfix {feature}` | Surgical hotfix ADW (scout → fix → human gate → ship) |
|
|
47
47
|
| `/morph-apply {feature}` | Autonomous execution + review (Gate 3) |
|
|
48
48
|
| `/morph-status [feature]` | Status of the active (or specified) feature |
|
|
49
|
-
| `/morph-archive {feature}` | Archive
|
|
49
|
+
| `/morph-archive {feature}` | Archive **without integrating** (legacy feature / cleanup) — normal close is `morph-spec finish --pr\|--merge` |
|
|
50
50
|
| `/morph-preflight` | Pre-deploy validation (specs, contracts, tests, infra) |
|
|
51
51
|
| `/morph-troubleshoot [error]` | Root-cause diagnosis for .NET/Next.js errors |
|
|
52
52
|
|
|
@@ -59,9 +59,12 @@ morph-spec approve {feature} {gate} [--mode auto] [--approver name] [--notes tex
|
|
|
59
59
|
morph-spec advance {feature} [--design] # approve current gate + scaffold next phase folder in one step
|
|
60
60
|
morph-spec approval-status {feature} [--json]
|
|
61
61
|
morph-spec unapprove {feature} {gate} [--reason text] # recovery only
|
|
62
|
-
morph-spec
|
|
62
|
+
morph-spec finish {feature} --pr|--merge [--keep] [--force] [--discard-ignored] # normal close: archive + integrate + teardown
|
|
63
|
+
morph-spec archive {feature} [--force] [--no-git] # archive WITHOUT integrating (legacy feature / cleanup)
|
|
63
64
|
```
|
|
64
65
|
|
|
66
|
+
`finish` is the normal way to close a feature (both the worktree flow and the common flow): it archives (committing the move inside `morph/{feature}`), then integrates — `--merge` merges `--no-ff` into the default branch locally (no push); `--pr` pushes `morph/{feature}` + `gh pr create` (needs `origin` + authenticated `gh`). It then tears down the worktree and releases the port block. `archive` alone is reserved for legacy features (no `morph/{feature}` branch) and cleanup.
|
|
67
|
+
|
|
65
68
|
---
|
|
66
69
|
|
|
67
70
|
## CLI — feature birth & work-type routing
|
|
@@ -116,8 +119,8 @@ One feature = one git worktree = one Claude Code instance. Each worktree gets it
|
|
|
116
119
|
morph-spec create {feature} --description "<what/why>" --worktree # birth the feature already isolated in its own worktree
|
|
117
120
|
morph-spec worktree setup {feature} # create .worktrees/{feature}/ on branch morph/{feature}
|
|
118
121
|
morph-spec worktree link [--all] # relink shared infra (node_modules[, .claude, .morph/framework])
|
|
119
|
-
morph-spec worktree finish {feature} # merge --no-ff back to the primary root, clean up + release ports (requires Gate 3)
|
|
120
122
|
morph-spec worktree list [--json] # active feature worktrees with phase/gate status
|
|
123
|
+
# Close a worktree feature with `morph-spec finish {feature} --pr|--merge` (see above) — it absorbed `worktree finish`.
|
|
121
124
|
morph-spec handoff {feature} [--json] # regenerate the compressed session-handoff doc (pointers, not copies)
|
|
122
125
|
morph-spec fleet [--json] # every active feature (root + worktrees) with phase/gates/ports/handoff/activity
|
|
123
126
|
```
|
|
@@ -182,4 +185,4 @@ Never edited directly — go through CLI commands or `morph-spec update` instead
|
|
|
182
185
|
|
|
183
186
|
---
|
|
184
187
|
|
|
185
|
-
*morph-spec v8.
|
|
188
|
+
*morph-spec v8.6.0 by Polymorphism Tech*
|
package/docs/QUICKSTART.md
CHANGED
|
@@ -168,13 +168,16 @@ morph-spec create my-feature --description "what & why" --worktree # birth the
|
|
|
168
168
|
morph-spec worktree setup my-feature # creates .worktrees/my-feature/ on branch morph/my-feature
|
|
169
169
|
```
|
|
170
170
|
|
|
171
|
-
Open the new worktree directory in its own Claude Code instance and work normally — a SessionStart hook injects the worktree's feature identity into context automatically. When the feature is done:
|
|
171
|
+
Open the new worktree directory in its own Claude Code instance and work normally — a SessionStart hook injects the worktree's feature identity into context automatically. When the feature is done (Gate 3 approved), close it in one step:
|
|
172
172
|
|
|
173
173
|
```bash
|
|
174
|
-
morph-spec
|
|
175
|
-
|
|
174
|
+
morph-spec finish my-feature --merge # archive + merge --no-ff into the default branch (local), tear down the worktree
|
|
175
|
+
# or, to open a PR instead of merging locally:
|
|
176
|
+
morph-spec finish my-feature --pr # archive + push morph/my-feature + gh pr create (keeps the branch the PR needs)
|
|
176
177
|
```
|
|
177
178
|
|
|
179
|
+
`finish` archives the feature (committing the move inside `morph/my-feature`) *and* integrates *and* tears down the worktree in one step — it replaces the old `worktree finish` + separate `archive`. The same command closes features developed **without** a worktree (they're born on `morph/{feature}` too).
|
|
180
|
+
|
|
178
181
|
List every active worktree with its phase and gate status:
|
|
179
182
|
|
|
180
183
|
```bash
|
|
@@ -246,4 +249,4 @@ morph-spec doctor
|
|
|
246
249
|
|
|
247
250
|
---
|
|
248
251
|
|
|
249
|
-
*morph-spec v8.
|
|
252
|
+
*morph-spec v8.6.0 by Polymorphism Tech*
|
package/framework/CLAUDE.md
CHANGED
|
@@ -15,7 +15,9 @@ Se não houver feature ativa, pergunte ao usuário qual feature trabalhar.
|
|
|
15
15
|
|
|
16
16
|
**NUNCA:**
|
|
17
17
|
- Pular para código sem proposal aprovado (Gate 1) e plano aprovado (Gate 2).
|
|
18
|
-
- Modificar o contrato do plano depois do Gate 2: `spec.md`, `mandate.md`, e os campos de plano de `tasks.json` (`title`, `description`, `dependencies`, `effort`, `doneCriteria`, `group`) estão congelados.
|
|
18
|
+
- Modificar o contrato do plano depois do Gate 2: `spec.md`, `mandate.md`, e os campos de plano de `tasks.json` (`title`, `description`, `dependencies`, `effort`, `doneCriteria`, `group`) estão congelados. **Os use cases (`2-plan/usecases/UC-*.md`) NÃO estão** — são editáveis por design, é assim que se muda o comportamento e se re-roda `implement`; a auditoria fica no git.
|
|
19
|
+
- Escrever critérios de aceite no `proposal.md`. O comportamento verificável mora nos use cases, cuja pós-condição precisa ser **observável em teste** e chega **literal** ao `doneCriteria` da task.
|
|
20
|
+
- Editar `.morph/specs/usecases/` à mão. O acervo só se escreve pela promoção do `finish`, que lê de `2-plan/usecases/` — é ela que carimba `status: implemented` e sobrescreve por ID. Para mudar um UC existente (o caso `bug`), copie-o para o `2-plan/usecases/` da feature e corrija lá.
|
|
19
21
|
- Tocar os campos de contrato do plano em `tasks.json` após o Gate 2 (`title`, `description`, `dependencies`, `effort`, `doneCriteria`, `group`) — o hook `protect-spec-files` faz diff semântico e bloqueia mudanças neles, seja via `Write` ou `Edit`. (Os campos mutáveis `status`/`outputs`/`notes` continuam graváveis por `Write` ou `Edit` — ver SEMPRE.)
|
|
20
22
|
- Listar perguntas em texto simples — sempre use a tool `AskUserQuestion` (1-4 perguntas por chamada).
|
|
21
23
|
- Usar `Guid.NewGuid()`, classes não-sealed sem justificativa, exceptions como fluxo de controle, camada de Service/Manager entre handler e dados, repository genérico (`IRepository<T>`/`IUnitOfWork`), ou SQL cru sem justificativa.
|
|
@@ -36,23 +38,24 @@ Se não houver feature ativa, pergunte ao usuário qual feature trabalhar.
|
|
|
36
38
|
| `/morph-hotfix {feature}` | ADW cirúrgico de hotfix (scout → fix → gate humano → ship) |
|
|
37
39
|
| `/morph-apply {feature}` | Execução autônoma + review (Gate 3) |
|
|
38
40
|
| `/morph-status [feature]` | Status da feature ativa (ou a especificada) |
|
|
39
|
-
| `/morph-archive {feature}` | Arquiva
|
|
41
|
+
| `/morph-archive {feature}` | Arquiva-**sem-integrar** (features legadas/faxina) — wrapper de `morph-spec archive`. Fechamento normal = `morph-spec finish --pr\|--merge` |
|
|
40
42
|
| `/morph-preflight` | Validação pré-deploy (specs, contratos, testes, infra) |
|
|
41
43
|
| `/morph-troubleshoot [erro]` | Diagnóstico de erros .NET/Next.js com root-cause analysis |
|
|
42
44
|
|
|
43
45
|
**Comandos CLI de gate e de estado** (a LLM os usa em vez de editar o estado à mão):
|
|
44
46
|
- `morph-spec approve <feature> <gate> --mode auto` — aprova um gate (`proposal`/`plan`/`review`) em `trust: auto`.
|
|
45
47
|
- `morph-spec advance <feature>` — aprova o gate da fase corrente **e** cria a pasta da próxima fase num passo só (`--design` toma o ramo opcional de uiux a partir da proposta).
|
|
46
|
-
- `morph-spec archive <feature>` — arquiva
|
|
47
|
-
- `morph-spec
|
|
48
|
+
- `morph-spec archive <feature>` — arquiva-**sem-integrar** (atômico, git-aware, commita o move escopado por pathspec): reservado a features legadas (sem branch `morph/{f}`) e faxina. O fechamento normal (arquiva **e** integra num passo) é `morph-spec finish`. É o que `/morph-archive` chama.
|
|
49
|
+
- `morph-spec finish <feature> --pr|--merge` — o **encerramento único** da feature (worktree ou comum): **arquiva** commitando `features/{f} → archive/{f}` dentro de `morph/{f}` — promovendo junto, no mesmo commit, os use cases da feature para o acervo permanente `.morph/specs/usecases/` com `status: implemented` (fail-open: sem `2-plan/usecases/`, no-op silencioso) — depois integra. `--merge` faz merge `--no-ff` **local** na default (sem push); `--pr` faz `push` + `gh pr create` (exige `origin` + `gh`, checados **antes** de arquivar — um `--pr` recusado não deixa meio-estado). Desmonta o worktree (PROVE-or-DECLINE) e libera o bloco de portas; no `--pr` **preserva** a branch (o PR precisa dela) e fica em `morph/{f}`. Flags: `--keep` mantém o worktree, `--force` dispensa o Gate 3, `--discard-ignored` consente descartar gitignored no teardown. Substitui o antigo `worktree finish` + `archive` separados.
|
|
50
|
+
- `morph-spec dag <feature>` — análise do DAG de tasks.json com decisão sequencial vs paralelo **ponderada por effort** (raízes S vão inline, nunca ganham agente próprio). Também cruza `tasks.json` com os use cases: `usecase` apontando para um `UC-{nn}` inexistente é **erro** (exit 1, não despacha); pós-condição órfã e `doneCriteria` que parafraseou em vez de copiar são avisos. `--mermaid` nunca é bloqueado.
|
|
48
51
|
- `morph-spec score <feature> <task> <score> [--dims a,c,q,t]` — grava `taskScores` no feature.json com timestamp server-side; **nunca edite taskScores à mão**. Em PowerShell, cite o valor de `--dims` entre aspas (`--dims "9.5,9,9,9"`) — sem aspas, a lista pode chegar como tokens separados; o parser aceita ambas as formas, mas citar evita qualquer ambiguidade.
|
|
49
52
|
- `morph-spec gate-decision <feature> <gate> --pause <bool> [--reason <txt>] [--signals <json>]` — grava `gateDecisions` no feature.json com timestamp server-side (shape em `framework/schemas/feature.schema.json`); **nunca edite gateDecisions à mão** — o Edit manual colide com o hook state-sync.
|
|
50
|
-
- `morph-spec create <feature> --description "<o quê/porquê>" --type <feature|bug|chore|hotfix> [--request "<txt>"] [--name "<nome>"] [--worktree]` — cria a estrutura da feature + `feature.json` canônico explicitamente (nascimento explícito no início da proposal; o hook state-sync continua cobrindo o caminho implícito como fallback). **Identidade no nascimento:** `name` (default = slug) e `description` são carimbados; a `--description` é **obrigatória** numa feature nova (ou `--request`, que a semeia) — sem nenhuma das duas o `create` recusa (fim dos scaffolds anônimos). `--type` classifica direto; `--request "<pedido>"` roda o detector determinístico (empate/sem sinal sai com exit 2 e candidatos — a LLM decide e re-roda com `--type` + `--request`/`--description`); `--worktree` já nasce a feature no seu worktree próprio.
|
|
53
|
+
- `morph-spec create <feature> --description "<o quê/porquê>" --type <feature|bug|chore|hotfix> [--request "<txt>"] [--name "<nome>"] [--worktree]` — cria a estrutura da feature + `feature.json` canônico explicitamente (nascimento explícito no início da proposal; o hook state-sync continua cobrindo o caminho implícito como fallback). **Identidade no nascimento:** `name` (default = slug) e `description` são carimbados; a `--description` é **obrigatória** numa feature nova (ou `--request`, que a semeia) — sem nenhuma das duas o `create` recusa (fim dos scaffolds anônimos). `--type` classifica direto; `--request "<pedido>"` roda o detector determinístico (empate/sem sinal sai com exit 2 e candidatos — a LLM decide e re-roda com `--type` + `--request`/`--description`); `--worktree` já nasce a feature no seu worktree próprio. **Toda feature nasce numa branch `morph/{f}`** (ramificada da default) mesmo sem `--worktree` — por isso o fechamento por `morph-spec finish` é idêntico nos dois fluxos.
|
|
51
54
|
- `morph-spec list [--all] [--json]` — o quadro de auditoria: uma linha por feature × workType × status × fase × gates G1/G2/G3 × descrição, com `⚠` para inconsistências (sem descrição, ordem de gate). `--all` inclui as arquivadas; `--json` para scripting. É o complemento do `delete` (enxergar o que está morto antes de remover).
|
|
52
55
|
- `morph-spec delete <feature> [--archive] [--force]` — remove uma feature. Hard por padrão (pasta apagada, git-aware, + entrada podada do índice raiz para não ressuscitar); `--archive` move para `.morph/archive` com status `abandoned` em vez de apagar. Recusa se algum gate estiver aprovado, a menos que `--force`. Use para faxina de scaffolds mortos e drafts abandonados (`archive` é para trabalho concluído; `delete` é para trabalho morto).
|
|
53
56
|
- `morph-spec retype <feature> <newType>` — muda o tipo de trabalho mid-flight; desfaz só os gates carimbados por política, preserva aprovações humanas; bloqueado após o Gate 3.
|
|
54
57
|
- `morph-spec verify <feature> [task] [--json]` — cadeia determinística build+testes+validadores (código antes do juiz LLM); escopo de task quando informado, senão a feature inteira.
|
|
55
|
-
- `morph-spec worktree setup|link|
|
|
58
|
+
- `morph-spec worktree setup|link|list` — gerencia o ciclo do worktree por feature (`setup` cria `.worktrees/{f}/` na branch `morph/{f}`, aloca o bloco de portas e escreve `.morph/worktree.env`; `link` religa infra compartilhada; `list` mostra fase/gate de cada worktree ativo). O fechamento saiu daqui — use `morph-spec finish` (acima).
|
|
56
59
|
- `morph-spec handoff <feature>` — regenera o documento de retomada (`.morph/features/{f}/handoff.md`): comprimido, derivado, aponta para os artefatos em vez de copiá-los. Gerado automaticamente em `setup`/`create --worktree`/`advance`.
|
|
57
60
|
- `morph-spec fleet` — visão da frota: toda feature ativa (raiz + worktrees) com fase, gates pendentes, tasks, portas, handoff e atividade. Use entre sessões para decidir onde atuar.
|
|
58
61
|
- `morph-spec telemetry [--json] [--feature <f>] [--limit <n>]` — reconstrói o caminho de execução da sessão a partir de `.morph/logs/events.jsonl` (skills invocadas, personas despachadas + prompts, standards/base de conhecimento lidos, mix de tools, prompts do usuário). Capturado silenciosamente pelo hook `telemetry-log` em todo tool call e todo UserPromptSubmit.
|
|
@@ -63,7 +66,7 @@ Se não houver feature ativa, pergunte ao usuário qual feature trabalhar.
|
|
|
63
66
|
|-------|-------------|
|
|
64
67
|
| `morph-brainstorming` | Entender negócio, escanear stack, produzir proposal.md |
|
|
65
68
|
| `morph-stack-scan` | Detectar desvios de stack em projeto brownfield |
|
|
66
|
-
| `morph-plan` |
|
|
69
|
+
| `morph-plan` | Destilar os use cases (comportamento) e então produzir spec.md + mandate.md + tasks.json |
|
|
67
70
|
| `morph-implement` | Executar uma tarefa com auto-advance entre tasks |
|
|
68
71
|
| `morph-eval` | Aplicar rubricas e produzir score 0-10 |
|
|
69
72
|
| `morph-review` | Produzir review-report.md (Gate 3) |
|
|
@@ -74,7 +77,7 @@ Se não houver feature ativa, pergunte ao usuário qual feature trabalhar.
|
|
|
74
77
|
|
|
75
78
|
Toda feature nasce com um `workType` (`morph-spec create <f> --description "<o quê/porquê>" --type <tipo>` ou classificado de `--request "<pedido>"`, que também semeia a descrição obrigatória) que dimensiona o pipeline: `feature` roda o fluxo completo (proposal → [uiux] → plan → implement → review); `bug` roda uma versão enxuta (proposal/plan lean); `chore` pula direto para implement (Gates 1/2 carimbados por política no nascimento); `hotfix` roda scout → fix cirúrgico → test loop → ship. O Gate 3 do `hotfix` **pausa sempre para um humano**, mesmo em `trust: auto` — o CLI recusa `morph-spec approve <f> review --mode auto` nesse tipo. Detalhes em `.morph/framework/MORPH.md` §2.1 e §5.
|
|
76
79
|
|
|
77
|
-
Features independentes podem rodar em paralelo, cada uma isolada num git worktree (`morph-spec create <f> --description "<o quê/porquê>" --worktree` ou `morph-spec worktree setup <f>`) — uma feature por worktree, uma instância de Claude Code por worktree. Cada worktree tem seu **bloco de portas** próprio (`.morph/worktree.env` — suba dev servers SEMPRE nelas, nunca nas portas padrão) e seu **handoff.md** de retomada. `feature.json` viaja commitado na branch `morph/{f}`; ao fechar, aprove o Gate 3
|
|
80
|
+
Features independentes podem rodar em paralelo, cada uma isolada num git worktree (`morph-spec create <f> --description "<o quê/porquê>" --worktree` ou `morph-spec worktree setup <f>`) — uma feature por worktree, uma instância de Claude Code por worktree. Cada worktree tem seu **bloco de portas** próprio (`.morph/worktree.env` — suba dev servers SEMPRE nelas, nunca nas portas padrão) e seu **handoff.md** de retomada. `feature.json` viaja commitado na branch `morph/{f}`; ao fechar, aprove o Gate 3 e rode `morph-spec finish <f> --pr|--merge` (arquiva dentro da branch, integra e desmonta o worktree num passo só). Visão agregada: `morph-spec fleet`. Detalhes em `.morph/framework/MORPH.md` §2.2.
|
|
78
81
|
|
|
79
82
|
## Personas (em `.claude/agents/`)
|
|
80
83
|
|
package/framework/MORPH.md
CHANGED
|
@@ -112,6 +112,8 @@ Nem todo trabalho merece o pipeline completo. Cada feature nasce com **identidad
|
|
|
112
112
|
|
|
113
113
|
**Compat:** uma feature sem `workType` (criada antes do v8) é tratada como `feature`. Mudança de tipo mid-flight: `morph-spec retype <f> <tipo>` (desfaz só carimbos de política, preserva aprovações humanas; bloqueado após o Gate 3).
|
|
114
114
|
|
|
115
|
+
**Nascimento numa branch:** toda feature — **com ou sem `--worktree`** — nasce numa branch `morph/{f}` ramificada da default. O fluxo comum (sem worktree) desenvolve direto em `morph/{f}` na raiz; o fluxo worktree isola em `.worktrees/{f}`. Por construção o fechamento é simétrico: `morph-spec finish <f> --pr|--merge` (§2.2) fecha os dois do mesmo jeito. Features criadas **antes** deste modelo (sem branch `morph/{f}`) fecham por `morph-spec archive <f>` (arquivar-sem-integrar), não por `finish`.
|
|
116
|
+
|
|
115
117
|
### 2.2 Desenvolvimento paralelo por worktree (frota)
|
|
116
118
|
|
|
117
119
|
Features independentes podem ser desenvolvidas **em paralelo, cada uma no seu git worktree**, com uma instância de Claude Code por worktree. `morph-spec create <f> --description "<o quê/porquê>" --worktree` (ou `morph-spec worktree setup <f>`) cria `.worktrees/{f}/` na branch `morph/{f}`. Contrato:
|
|
@@ -125,7 +127,7 @@ Features independentes podem ser desenvolvidas **em paralelo, cada uma no seu gi
|
|
|
125
127
|
- **Handoff entre sessões:** `.morph/features/{f}/handoff.md` é o documento de retomada — comprimido, derivado e regenerável (`morph-spec handoff <f>`), ele **aponta** para os artefatos em vez de copiá-los. É regenerado automaticamente no `worktree setup`, `create --worktree` e `advance`; o hook de SessionStart aponta para ele. **Ao abrir uma sessão numa feature em andamento, leia o handoff antes de re-derivar contexto à mão.** Nunca o edite manualmente (é git-invisível e sobrescrito na próxima regeneração).
|
|
126
128
|
- **Visão da frota:** `morph-spec fleet` agrega raiz + worktrees (fase, gates pendentes, tasks, portas, handoff, último commit, sujeira) — use entre sessões para decidir onde atuar. `morph-spec worktree list` continua sendo a visão enxuta por worktree.
|
|
127
129
|
- **Ownership de arquivos:** não há lock em runtime, por design — a colisão de escrita se resolve **em plan-time** (`morph-spec dag` detecta overlap de `outputs` e recomenda `isolation: "worktree"`) e **por construção** (uma feature = um worktree = um escritor). Entre features, arquivos compartilhados convergem no merge do `finish` — conflito ali é o sinal honesto de escopo sobreposto, não um bug.
|
|
128
|
-
- **Fechamento:** aprove o Gate 3
|
|
130
|
+
- **Fechamento:** aprove o Gate 3, depois **`morph-spec finish <f> --pr|--merge`** — o encerramento único e simétrico (mesmo comando nos dois fluxos, worktree e comum). Ele **arquiva** a feature commitando o move `features/{f} → archive/{f}` **dentro da branch `morph/{f}`** (o estado arquivado viaja na própria integração, não num commit à parte) e então integra: `--merge` faz o merge `--no-ff` **local** na branch default (sem push; recusa se worktree/raiz estiverem sujos; aborta em conflito) e `--pr` faz `push` de `morph/{f}` + `gh pr create` (sem merge local; exige `origin` + `gh` autenticado — as pré-condições rodam **antes** de arquivar, então um `--pr` recusado não deixa meio-estado). Em ambos o worktree é desmontado (PROVE-or-DECLINE) e o bloco de portas liberado; no `--pr` a branch é **preservada** (o PR aberto precisa dela) e a sessão permanece em `morph/{f}`. Não há mais `worktree finish` nem `archive` separado no caminho feliz — `morph-spec archive` fica reservado a arquivar-sem-integrar (features legadas, faxina).
|
|
129
131
|
|
|
130
132
|
---
|
|
131
133
|
|
|
@@ -136,15 +138,21 @@ Não invente caminhos alternativos.
|
|
|
136
138
|
|
|
137
139
|
### Proposal (`0-proposal/`)
|
|
138
140
|
|
|
139
|
-
- `proposal.md` — descrição da feature, problema que resolve, escopo, critérios de aceite,
|
|
141
|
+
- `proposal.md` — descrição da feature, problema que resolve, escopo, riscos. **Sem critérios de aceite:** o comportamento verificável mora nos use cases (`2-plan/usecases/`), destilados na fase plan. Duplicar aqui produz duas fontes que divergem no primeiro ajuste. Um bom proposal.md tem no máximo 2 páginas: se está crescendo além disso, o escopo provavelmente precisa ser cortado antes de avançar.
|
|
140
142
|
|
|
141
143
|
### Plan (`2-plan/`)
|
|
142
144
|
|
|
143
|
-
- `
|
|
145
|
+
- `usecases/UC-{nn}-{slug}.md` — **um arquivo por use case**, o artefato de comportamento da feature. Frontmatter (`id`, `title`, `actor`, `status`, `entities`) mais as seções `Pré-condições`, `Cenário principal`, `Fluxos alternativos` (A1, A2… — cada alternativa aproxima uma user story), `Pós-condições` (P1, P2…) e `Delta de domínio` (**só o que muda** no modelo; o domínio completo continua sendo o código EF Core mais as migrations).
|
|
146
|
+
|
|
147
|
+
**Pós-condição precisa ser observável em teste** — esta é a regra que sustenta a camada. "O sistema fica consistente" não passa; "a resposta contém todos os veterinários não arquivados" passa. A pós-condição chega **literal** ao `doneCriteria` da task que a realiza: é a tradução manual nesse ponto que hoje perde o requisito.
|
|
148
|
+
|
|
149
|
+
O `id` é sequencial **no projeto**, não na feature — atribuído lendo o acervo `.morph/specs/usecases/` mais os use cases das features ativas, tomando o maior mais um. Ciclo de status: `draft` (nasce) → `approved` (Gate 2) → `implemented` (promoção no `finish`); é descritivo, quem trava fase é o gate. O use case fica **editável depois do Gate 2**, por design — é o que permite mudar o comportamento e re-rodar `implement`, com a auditoria no git. Obrigatoriedade por tipo de trabalho: ver `morph-plan`.
|
|
150
|
+
|
|
151
|
+
- `spec.md` — especificação técnica detalhada: arquitetura, componentes, integrações, fluxos de dados, edge cases **técnicos**. Responde **como** os use cases serão realizados — não repete o comportamento. Um bom spec.md permite que qualquer desenvolvedor comece a implementar sem fazer perguntas básicas. Um spec.md fraco lista tecnologias mas não explica como os componentes se conectam.
|
|
144
152
|
|
|
145
153
|
- `mandate.md` — contrato de implementação: stack exata, standards obrigatórios (com links), patterns explicitamente proibidos, checklist de done com critérios verificáveis. O mandate.md é lido no início de cada tarefa de implementação — deve ser específico o suficiente para resolver ambiguidades sem consultar o Orchestrator.
|
|
146
154
|
|
|
147
|
-
- `tasks.json` — task list estruturada validada contra `framework/schemas/tasks.schema.json`. Cada task tem `id` (T1, T2...), `title`, `description`, `dependencies` (array de IDs), `effort` (S/M/L/XL), `doneCriteria`, `status` (pending/in_progress/done/skipped/blocked)
|
|
155
|
+
- `tasks.json` — task list estruturada validada contra `framework/schemas/tasks.schema.json`. Cada task tem `id` (T1, T2...), `title`, `description`, `dependencies` (array de IDs), `effort` (S/M/L/XL), `doneCriteria`, `status` (pending/in_progress/done/skipped/blocked), `outputs` (paths esperados) e `usecase` (opcional — o **ID** do use case que a task realiza, `UC-07`, nunca o nome do arquivo). O `doneCriteria` de uma task com `usecase` carrega a **pós-condição literal**, com o rótulo (`"P2 — cada veterinário traz..."`). Cada entrada no recap.md deve referenciar um ID do tasks.json.
|
|
148
156
|
|
|
149
157
|
- `decisions.md` — log de decisões técnicas: qual era a alternativa, por que foi descartada, quem decidiu. Criado quando surgir a primeira decisão não trivial. Não é obrigatório — só existe se houver decisões que precisam de rastreabilidade.
|
|
150
158
|
|
|
@@ -156,6 +164,18 @@ Não invente caminhos alternativos.
|
|
|
156
164
|
|
|
157
165
|
- `review-report.md` — relatório de revisão: scores por dimensão (arquitetura, contratos, qualidade, cobertura), feedback priorizado (bloqueantes primeiro, melhorias depois), aprovação ou rejeição com critérios explícitos. Um review-report.md que só diz "aprovado" sem scores não satisfaz o gate.
|
|
158
166
|
|
|
167
|
+
### Acervo de use cases (`.morph/specs/usecases/`)
|
|
168
|
+
|
|
169
|
+
O acervo permanente do projeto: `UC-{nn}-{slug}.md`, **commitado** (nenhuma regra do `.gitignore` o cobre). É a descrição viva do comportamento do sistema e sobrevive ao arquivamento das features — diferente dos traces, ele **faz parte da entrega**.
|
|
170
|
+
|
|
171
|
+
- **Quem escreve:** `morph-spec finish` promove os use cases da feature para cá **dentro do commit de arquivamento**, na branch `morph/{f}`, com `status: implemented`. O acervo viaja na própria integração, como o estado arquivado (§2.2) — não é um passo pós-merge.
|
|
172
|
+
- **O que é cobrado mecanicamente:** `morph-spec dag {feature}` cruza `tasks.json` com os use cases — referência a um `UC-{nn}` inexistente é **erro** (não despacha), pós-condição órfã e `doneCriteria` parafraseado são avisos. Isso cobre o *encanamento*. Se a pós-condição é **observável em teste** nenhum checker decide: continua sendo critério do Gate 2 e da rubrica `test-coverage`.
|
|
173
|
+
- **Via única de escrita:** a promoção lê **só** de `{feature}/2-plan/usecases/`. Nunca edite `.morph/specs/usecases/` à mão — a edição direta pula o `status: implemented`, a sobrescrita por ID e o commit escopado, e o acervo passa a ter duas verdades. Para mudar um UC existente (o caso `bug`), copie-o para o `2-plan/usecases/` da feature, corrija lá, e deixe o `finish` sobrescrever.
|
|
174
|
+
- **Quando chega na default:** em `--merge`, no merge `--no-ff`; em `--pr`, só quando o PR for mergeado. Correto por construção: o acervo descreve o que foi **integrado**, não o que foi proposto.
|
|
175
|
+
- **Sobrescrita por ID:** um `UC-07` que já existe é substituído pela versão que está sendo integrada, mesmo que o slug tenha mudado. Exatamente um arquivo por ID.
|
|
176
|
+
- **Fail-open:** feature sem `2-plan/usecases/` promove nada, em silêncio. A promoção nunca pode impedir o fechamento de uma feature.
|
|
177
|
+
- **Colisão entre features paralelas:** dois worktrees podem alocar `UC-08` sem se enxergar, porque cada `feature.json` viaja na sua branch. A colisão é **aceita e resolvida no merge**, como conflito de arquivo — coerente com o ownership de §2.2 ("conflito ali é o sinal honesto de escopo sobreposto"). Renumere o UC perdedor e atualize as referências `usecase` no `tasks.json` arquivado daquela feature. Não há alocador central, e não deve haver: um lock global de id reintroduziria entre worktrees a coordenação que a arquitetura evita de propósito.
|
|
178
|
+
|
|
159
179
|
### Traces (`.morph/traces/`)
|
|
160
180
|
|
|
161
181
|
Cada fase de implementação produz um trace JSON em `.morph/traces/YYYY-MM-DD-{feature}-{phase}.json`.
|
|
@@ -6,12 +6,18 @@ allowed-tools: Read, Bash
|
|
|
6
6
|
|
|
7
7
|
# Archive MORPH Feature
|
|
8
8
|
|
|
9
|
-
Archive a feature
|
|
10
|
-
|
|
9
|
+
Archive-**without-integrate**: move a feature out of the active set in `.morph/features/` without
|
|
10
|
+
merging or opening a PR. This is the **reserved** path — for **legacy** features (born before the
|
|
11
|
+
"every feature is born on a `morph/{f}` branch" model, so there's no branch to integrate) and for
|
|
12
|
+
**cleanup**. The **normal close** of a feature is `morph-spec finish {feature} --pr|--merge`, which
|
|
13
|
+
archives *and* integrates *and* tears down the worktree in one step (see `MORPH.md` §2.2 and
|
|
14
|
+
`morph-apply` §6). Reach for `/morph-archive` only when integration is not wanted.
|
|
11
15
|
|
|
12
16
|
This is a thin wrapper over the atomic, git-aware CLI command — do **not** move folders or edit state
|
|
13
17
|
by hand. The command moves the folder, stamps the feature `completed` + `archivedAt` in its
|
|
14
|
-
`feature.json`,
|
|
18
|
+
`feature.json`, **commits the move scoped to the feature's own pathspec** (`.morph/features/{f}` +
|
|
19
|
+
`.morph/archive/{f}`, never `commit -a`), and cleans the derivable root index, all-or-nothing. Re-running
|
|
20
|
+
is idempotent: an already-archived feature is reported, not re-moved.
|
|
15
21
|
|
|
16
22
|
## Workflow
|
|
17
23
|
|
|
@@ -28,7 +34,8 @@ by hand. The command moves the folder, stamps the feature `completed` + `archive
|
|
|
28
34
|
```
|
|
29
35
|
The command refuses if Gate 3 isn't approved (override with `--force` only when the user asks).
|
|
30
36
|
It moves `.morph/features/{feature}/` → `.morph/archive/{feature}/` (via `git mv` when possible),
|
|
31
|
-
sets `status: "completed"` + `archivedAt`,
|
|
37
|
+
sets `status: "completed"` + `archivedAt`, commits that move scoped to the feature's pathspec, and
|
|
38
|
+
drops the feature from the thin index.
|
|
32
39
|
|
|
33
40
|
3. **Report** the new path (`.morph/archive/{feature}/`). Do not invent metrics not recorded in
|
|
34
41
|
`feature.json` or `recap.md`.
|
|
@@ -4,7 +4,9 @@ Avalia se os testes cobrem os comportamentos esperados, são isolados e têm nom
|
|
|
4
4
|
|
|
5
5
|
## Score 9-10 — Exemplar
|
|
6
6
|
|
|
7
|
-
-
|
|
7
|
+
- **Cada pós-condição do use case referenciado tem teste correspondente.** Se a task traz `usecase: "UC-07"`, abra `2-plan/usecases/UC-07-*.md` e percorra as pós-condições (P1, P2…): cada uma precisa de ao menos um teste que a verifique. Pós-condição sem teste **impede a faixa 9-10**, por mais completa que a suíte pareça no resto.
|
|
8
|
+
- Happy path coberto para todos os casos de uso relevantes — "relevantes" são os use cases referenciados pelas tasks da feature, não uma lista implícita.
|
|
9
|
+
- Fluxos alternativos do use case (A1, A2…) cobertos: são os edge cases de **comportamento** e foram declarados justamente para serem testados.
|
|
8
10
|
- Edge cases críticos cobertos: null/undefined, string vazia, boundary values, coleção vazia.
|
|
9
11
|
- Casos de erro cobertos: o que acontece quando a operação falha, quando a dependência retorna erro.
|
|
10
12
|
- Testes completamente isolados — cada teste pode rodar sozinho em qualquer ordem.
|
|
@@ -43,6 +45,7 @@ Avalia se os testes cobrem os comportamentos esperados, são isolados e têm nom
|
|
|
43
45
|
|
|
44
46
|
## Perguntas de avaliação
|
|
45
47
|
|
|
48
|
+
0. A task referencia um `usecase`? Se sim: **toda** pós-condição daquele use case tem teste correspondente? (Sem isso, o teto é 8.)
|
|
46
49
|
1. O happy path está coberto para todos os casos de uso da tarefa?
|
|
47
50
|
2. Os edge cases críticos (null, vazio, boundary) estão cobertos?
|
|
48
51
|
3. O que acontece quando uma dependência falha — isso está testado?
|
|
@@ -13,9 +13,9 @@ stacks:
|
|
|
13
13
|
|
|
14
14
|
**NEVER skip to code without a specification.** Every feature must progress through phases:
|
|
15
15
|
|
|
16
|
-
1. **Proposal** — Problem statement +
|
|
16
|
+
1. **Proposal** — Problem statement + scope + risks (`0-proposal/proposal.md`). No acceptance criteria: verifiable behaviour lives in the use cases.
|
|
17
17
|
2. **Design** (optional, UI-heavy) — Design system + mockups + flows (`1-design/`)
|
|
18
|
-
3. **Plan** —
|
|
18
|
+
3. **Plan** — Use cases first, then technical spec + mandate + tasks (`2-plan/usecases/UC-{nn}-{slug}.md`, `spec.md`, `mandate.md`, `tasks.json`). Each use case post-condition must be observable in a test and reaches the task's `doneCriteria` verbatim.
|
|
19
19
|
4. **Implement** — Code + recap (`3-implement/recap.md`)
|
|
20
20
|
5. **Review** — Review report + Gate 3 (`4-review/review-report.md`)
|
|
21
21
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
3
|
"title": "MORPH-SPEC feature.json",
|
|
4
|
-
"description": "Canonical shape of the authoritative, committed per-feature state at .morph/features/{feature}/feature.json (v5 per-feature state model). Born via `morph-spec create` (explicit) or the state-sync hook (implicit fallback). Server-side writers: `morph-spec approve/advance` (approvalGates), `morph-spec score` (taskScores), `morph-spec gate-decision` (gateDecisions), `morph-spec archive` (status/archivedAt). Never hand-edit the CLI-owned fields — manual Edits collide with the state-sync hook. This schema is documentational: additionalProperties stays true so older/newer CLIs interoperate.",
|
|
4
|
+
"description": "Canonical shape of the authoritative, committed per-feature state at .morph/features/{feature}/feature.json (v5 per-feature state model). Born via `morph-spec create` (explicit) or the state-sync hook (implicit fallback). Server-side writers: `morph-spec approve/advance` (approvalGates), `morph-spec score` (taskScores), `morph-spec gate-decision` (gateDecisions), `morph-spec archive`/`finish` (status/archivedAt — `finish` archives internally before integrating). Never hand-edit the CLI-owned fields — manual Edits collide with the state-sync hook. This schema is documentational: additionalProperties stays true so older/newer CLIs interoperate.",
|
|
5
5
|
"type": "object",
|
|
6
6
|
"required": ["status", "approvalGates"],
|
|
7
7
|
"properties": {
|
|
@@ -200,7 +200,7 @@
|
|
|
200
200
|
},
|
|
201
201
|
"worktree": {
|
|
202
202
|
"type": "object",
|
|
203
|
-
"description": "Bookkeeping do worktree ativo desta feature no ROOT feature.json, gravado por `morph-spec worktree setup` (via `create --worktree` ou standalone). Removido por `worktree finish
|
|
203
|
+
"description": "Bookkeeping do worktree ativo desta feature no ROOT feature.json, gravado por `morph-spec worktree setup` (via `create --worktree` ou standalone). Removido no fechamento por `morph-spec finish` (que absorveu o antigo `worktree finish`).",
|
|
204
204
|
"properties": {
|
|
205
205
|
"path": { "type": "string" },
|
|
206
206
|
"branch": { "type": "string" },
|
|
@@ -25,7 +25,12 @@
|
|
|
25
25
|
"status": { "type": "string", "enum": ["pending", "in_progress", "done", "skipped", "blocked"] },
|
|
26
26
|
"outputs": { "type": "array", "items": { "type": "string" } },
|
|
27
27
|
"notes": { "type": "string" },
|
|
28
|
-
"group": { "type": "string", "enum": ["backend", "frontend", "tests", "infra", "docs"] }
|
|
28
|
+
"group": { "type": "string", "enum": ["backend", "frontend", "tests", "infra", "docs"] },
|
|
29
|
+
"usecase": {
|
|
30
|
+
"type": "string",
|
|
31
|
+
"pattern": "^UC-\\d+$",
|
|
32
|
+
"description": "ID of the use case this task realizes (2-plan/usecases/UC-{nn}-{slug}.md). Optional: technical tasks with no observable behaviour have none."
|
|
33
|
+
}
|
|
29
34
|
},
|
|
30
35
|
"additionalProperties": false
|
|
31
36
|
}
|
|
@@ -4,7 +4,7 @@ description: Guia a criação de uma landing page nova ponta-a-ponta a partir do
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao iniciar um novo projeto de LP com o template Umbraco genérico
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.6.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# create-umbraco-lp
|
|
@@ -4,7 +4,7 @@ description: Migra uma landing page existente (React/Vite, Next.js estático ou
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao receber instrução "use /migrate-lp-to-umbraco {projeto}" do usuário, ou quando o usuário descrever necessidade de migrar uma LP para Umbraco
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.6.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# migrate-lp-to-umbraco
|
|
@@ -4,7 +4,7 @@ description: Orquestra a execução autônoma de tasks de uma feature morph-spec
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: após Gate 2 aprovado, ao receber instrução "use /morph-apply" ou "implementar feature"
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.6.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-apply
|
|
@@ -218,11 +218,14 @@ O comando grava `gateDecisions.review = { pause, reason, signals, trust, decided
|
|
|
218
218
|
- Pause: `AskUserQuestion` com options `["aprovado, fechar feature", "preciso ajustar", "rollback"]`.
|
|
219
219
|
- Auto: exibir summary do review-report, aprovar via `morph-spec approve {feature} review --mode auto`, e prosseguir.
|
|
220
220
|
|
|
221
|
-
### 6. Pós Gate 3
|
|
221
|
+
### 6. Pós Gate 3 — encerramento
|
|
222
222
|
|
|
223
223
|
- Aprovar o Gate 3: em auto, `morph-spec approve {feature} review --mode auto`; em manual, o hook state-sync registra a resposta "aprovado" em AskUserQuestion. O gate fica gravado no `feature.json` autoritativo da feature — nunca via Edit à mão de `state.json`.
|
|
224
|
-
-
|
|
225
|
-
-
|
|
224
|
+
- **Fechar a feature** com `morph-spec finish {feature} --pr|--merge` — um passo só: arquiva commitando `features/{f} → archive/{f}` dentro de `morph/{f}`, integra e desmonta o worktree (se houver). Escolha o modo com `AskUserQuestion` (header `"Integração"`):
|
|
225
|
+
- **Abrir PR** (`--pr`): faz `push` de `morph/{f}` + `gh pr create` com base na default — para review por outro humano/CI antes do merge. Exige `origin` + `gh` autenticado (checados **antes** de arquivar; se faltarem, `finish` recusa sem efeito colateral — caia para `--merge`). A branch é preservada e a sessão fica em `morph/{f}`.
|
|
226
|
+
- **Merge local** (`--merge`): merge `--no-ff` na default **localmente**, sem push — para o fluxo single-user direto. Remove a branch e o worktree.
|
|
227
|
+
- Não integre automaticamente sem a escolha do modo: `finish` toca o remoto (`--pr`) ou a branch default (`--merge`) — é uma ação de saída que pede confirmação.
|
|
228
|
+
- Feature **legada** (criada antes do modelo "nasce numa branch", sem `morph/{f}`): `finish` recusa e roteia para `morph-spec archive {feature}` (arquivar-sem-integrar); nesse caso, arquive.
|
|
226
229
|
|
|
227
230
|
## Anti-padrões
|
|
228
231
|
|
|
@@ -240,7 +243,7 @@ O comando grava `gateDecisions.review = { pause, reason, signals, trust, decided
|
|
|
240
243
|
- `.morph/features/{feature}/3-implement/recap.md` produzido por morph-implement.
|
|
241
244
|
- `.morph/features/{feature}/4-review/review-report.md` produzido por morph-review.
|
|
242
245
|
- Gate 3 registrado aprovado em `.morph/features/{feature}/feature.json` (autoritativo) — via `morph-spec approve` em auto, ou pelo hook state-sync no caminho manual.
|
|
243
|
-
- Feature com Gate 3 aprovado e
|
|
246
|
+
- Feature com Gate 3 aprovado e **fechada** por `morph-spec finish --pr|--merge` (arquiva carimbando `status: "completed"` + `archivedAt`, integra e desmonta num passo) — ou, se legada, por `morph-spec archive`.
|
|
244
247
|
|
|
245
248
|
## Referências
|
|
246
249
|
|
|
@@ -4,7 +4,7 @@ description: Entende o negócio, os usuários e a arquitetura antes de qualquer
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao receber um novo request de feature, antes de morph-plan
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.6.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-brainstorming
|
|
@@ -72,12 +72,13 @@ Para `workType: feature` (ou features sem `workType` — compat, ver MORPH.md §
|
|
|
72
72
|
- **Problema:** o que está sendo resolvido e para quem (máx. 2 parágrafos)
|
|
73
73
|
- **Escopo:** o que está incluído e o que está explicitamente excluído
|
|
74
74
|
- **Usuários e fluxos críticos:** quem usa e qual é o caminho principal
|
|
75
|
-
- **Critérios de aceite:** condições verificáveis que indicam que a feature está pronta
|
|
76
75
|
- **Stack:** confirme o stack padrão ou documente desvios aprovados
|
|
77
76
|
- **Riscos e dependências:** o que pode dar errado, o que esta feature depende
|
|
78
77
|
- **Compliance de stack:** "Em compliance" ou lista de desvios detectados e plano de resolução
|
|
79
78
|
|
|
80
|
-
**
|
|
79
|
+
**Não escreva critérios de aceite aqui.** O comportamento verificável mora nos **use cases**, destilados pela `morph-plan` na fase seguinte (`2-plan/usecases/UC-{nn}-{slug}.md`), onde cada pós-condição precisa ser observável em teste e chega literal ao `doneCriteria` das tasks. O `proposal.md` responde **o quê e por quê**; os use cases respondem **como o sistema se comporta**. Duplicar aqui produz duas fontes que divergem no primeiro ajuste.
|
|
80
|
+
|
|
81
|
+
**Se `workType: bug`** (modo bug-lean, ver nota no início da skill), substitua a lista acima pela estrutura enxuta: **Repro** (passos para reproduzir), **Diagnóstico** (o que foi observado/investigado), **Root cause provável** e **Escopo do fix** (o que muda, o que fica de fora) — sem as seções de negócio completas do fluxo `feature`. A condição verificável de que o bug foi corrigido vira a **pós-condição** que faltava no use case do acervo (`.morph/specs/usecases/`), corrigida ou acrescentada na fase plan.
|
|
81
82
|
|
|
82
83
|
Um bom proposal.md tem no máximo 2 páginas. Se está crescendo além disso, o escopo precisa ser cortado.
|
|
83
84
|
|
|
@@ -4,7 +4,7 @@ description: Avalia a qualidade de uma tarefa ou fase com rubricas graduadas 0-1
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao completar uma tarefa ou ao finalizar uma fase de implementação
|
|
6
6
|
user-invokable: false
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.6.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-eval
|
|
@@ -4,7 +4,7 @@ description: ADW cirúrgico de hotfix — resolve uma queda/bug crítico de prod
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao receber "/morph-hotfix {feature}", quando a morph-proposal classifica o pedido como workType hotfix (Passo 0), ou o usuário diz "produção caiu / hotfix / urgente"
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.6.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-hotfix
|
|
@@ -103,8 +103,8 @@ options:
|
|
|
103
103
|
### 8. Pós-gate (o "test loop → ship" de `MORPH.md` §2.1)
|
|
104
104
|
|
|
105
105
|
- Rode a suíte completa uma vez: `morph-spec verify {feature}` (sem escopo de task — cobertura da feature inteira, agora que o Gate 3 está aprovado).
|
|
106
|
-
-
|
|
107
|
-
- Não
|
|
106
|
+
- Feche com `morph-spec finish {feature} --pr|--merge` — o mesmo encerramento único das demais features (arquiva commitando dentro de `morph/{f}`, integra, desmonta). Num hotfix urgente o `--merge` (local, direto na default) costuma ser o caminho; use `--pr` quando o fix precisa passar por CI/review antes do merge. Ver `MORPH.md` §2.2.
|
|
107
|
+
- Não integre automaticamente — o usuário decide quando e por qual modo (`finish` toca a default ou o remoto). Feature legada sem `morph/{f}`: `finish` roteia para `morph-spec archive {feature}`.
|
|
108
108
|
|
|
109
109
|
## Anti-padrões
|
|
110
110
|
|