@polymorphism-tech/morph-spec 8.4.0 → 8.5.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 +6 -5
- package/framework/MORPH.md +3 -1
- package/framework/commands/morph-archive.md +11 -4
- package/framework/schemas/feature.schema.json +2 -2
- 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 +1 -1
- 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 +1 -1
- 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 +148 -70
- package/src/commands/state/create.js +46 -2
- package/src/commands/state/finish.js +422 -0
- package/src/core/state/state-manager.js +2 -2
- package/src/dashboard/scanner/state-scanner.js +1 -1
- package/src/lib/generators/handoff-generator.js +2 -2
- package/src/lib/git/default-branch.js +73 -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.5.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.5.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.5.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.5.0 by Polymorphism Tech*
|
package/framework/CLAUDE.md
CHANGED
|
@@ -36,23 +36,24 @@ Se não houver feature ativa, pergunte ao usuário qual feature trabalhar.
|
|
|
36
36
|
| `/morph-hotfix {feature}` | ADW cirúrgico de hotfix (scout → fix → gate humano → ship) |
|
|
37
37
|
| `/morph-apply {feature}` | Execução autônoma + review (Gate 3) |
|
|
38
38
|
| `/morph-status [feature]` | Status da feature ativa (ou a especificada) |
|
|
39
|
-
| `/morph-archive {feature}` | Arquiva
|
|
39
|
+
| `/morph-archive {feature}` | Arquiva-**sem-integrar** (features legadas/faxina) — wrapper de `morph-spec archive`. Fechamento normal = `morph-spec finish --pr\|--merge` |
|
|
40
40
|
| `/morph-preflight` | Validação pré-deploy (specs, contratos, testes, infra) |
|
|
41
41
|
| `/morph-troubleshoot [erro]` | Diagnóstico de erros .NET/Next.js com root-cause analysis |
|
|
42
42
|
|
|
43
43
|
**Comandos CLI de gate e de estado** (a LLM os usa em vez de editar o estado à mão):
|
|
44
44
|
- `morph-spec approve <feature> <gate> --mode auto` — aprova um gate (`proposal`/`plan`/`review`) em `trust: auto`.
|
|
45
45
|
- `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
|
|
46
|
+
- `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.
|
|
47
|
+
- `morph-spec finish <feature> --pr|--merge` — o **encerramento único** da feature (worktree ou comum): **arquiva** commitando `features/{f} → archive/{f}` dentro de `morph/{f}`, 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.
|
|
47
48
|
- `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).
|
|
48
49
|
- `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
50
|
- `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.
|
|
51
|
+
- `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
52
|
- `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
53
|
- `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
54
|
- `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
55
|
- `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|
|
|
56
|
+
- `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
57
|
- `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
58
|
- `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
59
|
- `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.
|
|
@@ -74,7 +75,7 @@ Se não houver feature ativa, pergunte ao usuário qual feature trabalhar.
|
|
|
74
75
|
|
|
75
76
|
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
77
|
|
|
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
|
|
78
|
+
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
79
|
|
|
79
80
|
## Personas (em `.claude/agents/`)
|
|
80
81
|
|
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
|
|
|
@@ -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`.
|
|
@@ -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" },
|
|
@@ -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.5.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.5.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.5.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.5.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-brainstorming
|
|
@@ -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.5.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.5.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
|
|
|
@@ -4,7 +4,7 @@ description: Guia a produção dos três artefatos de planejamento de uma featur
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao iniciar a fase plan de uma feature, após o Gate 1 (proposal aprovado)
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.5.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-plan
|
|
@@ -4,7 +4,7 @@ description: Orquestra a fase de proposta+plano de uma feature morph-spec. Encad
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao receber instrução "use /morph-proposal" do usuário, ou ao iniciar uma nova feature
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.5.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-proposal
|
|
@@ -4,7 +4,7 @@ description: Conduz a fase de revisão e produz o review-report.md para o Gate 3
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao iniciar a fase review, após todas as tasks de tasks.json estarem com status `done`
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.5.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-review
|
|
@@ -102,7 +102,7 @@ e o `recap.md` estar atualizado. Normalmente invocada pela skill orquestradora `
|
|
|
102
102
|
question: "Gate 3 — Review de {feature} aprovado?{ reason ? ' Sinal: ' + reason : '' }"
|
|
103
103
|
header: "Gate 3"
|
|
104
104
|
options:
|
|
105
|
-
- { label: "aprovado, fechar feature", description: "Marcar
|
|
105
|
+
- { label: "aprovado, fechar feature", description: "Marcar review aprovado; próximo passo é fechar com morph-spec finish --pr|--merge (ver morph-apply §6)" }
|
|
106
106
|
- { label: "preciso ajustar", description: "Apontar correções necessárias antes de fechar" }
|
|
107
107
|
- { label: "rollback", description: "Desfazer e voltar para implement" }
|
|
108
108
|
```
|
|
@@ -120,6 +120,8 @@ e o `recap.md` estar atualizado. Normalmente invocada pela skill orquestradora `
|
|
|
120
120
|
|
|
121
121
|
No caminho manual, o hook state-sync detecta a aprovação em answers de AskUserQuestion e grava `approvalGates.review = { approved: true, timestamp, approvedBy: "manual" }` no `feature.json` autoritativo da feature. Em auto sem AskUserQuestion, aprove via `morph-spec approve {feature} review --mode auto` — nunca via Edit à mão de state.json.
|
|
122
122
|
|
|
123
|
+
**Próximo passo (não é desta skill):** com o Gate 3 aprovado, a feature fecha por `morph-spec finish {feature} --pr|--merge` — a `morph-apply` §6 conduz a escolha PR vs merge. Não arquive nem integre aqui.
|
|
124
|
+
|
|
123
125
|
## Output esperado
|
|
124
126
|
- `.morph/features/{feature}/4-review/evaluator-report.md` — relatório bruto e autoritativo do
|
|
125
127
|
`morph-evaluator` despachado no passo 4 (canal durável, ver MORPH.md §6)
|
|
@@ -4,7 +4,7 @@ description: Varre o codebase existente, detecta stack atual, compara com o stac
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao iniciar uma feature em projeto brownfield (codebase já existente)
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.5.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-stack-scan
|
|
@@ -4,7 +4,7 @@ description: Localiza e carrega um standard específico do STANDARDS.json sob de
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: quando precisar consultar um standard específico durante a implementação
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.5.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-standards
|