@polymorphism-tech/morph-spec 8.17.0 → 8.19.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 +2 -2
- package/bin/morph-spec.js +9 -0
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/CLAUDE.md +46 -43
- package/framework/MORPH.md +120 -168
- package/framework/commands/morph-hotfix.md +1 -1
- package/framework/docs/CLI.md +41 -0
- package/framework/hooks/shared/phase-utils.js +0 -2
- package/framework/phases.json +1 -1
- package/framework/rules/morph-workflow.md +1 -1
- package/framework/schemas/feature.schema.json +12 -0
- package/framework/skills/README.md +1 -1
- package/framework/skills/core/create-umbraco-lp/SKILL.md +3 -1
- package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +3 -1
- package/framework/skills/core/morph-apply/SKILL.md +12 -20
- package/framework/skills/core/morph-brainstorming/SKILL.md +11 -32
- package/framework/skills/core/morph-eval/SKILL.md +1 -1
- package/framework/skills/core/morph-hotfix/SKILL.md +4 -4
- package/framework/skills/core/morph-implement/SKILL.md +1 -1
- package/framework/skills/core/morph-plan/SKILL.md +13 -27
- package/framework/skills/core/morph-proposal/SKILL.md +3 -15
- package/framework/skills/core/morph-review/SKILL.md +15 -8
- package/framework/skills/core/morph-stack-scan/SKILL.md +10 -26
- package/framework/skills/core/morph-standards/SKILL.md +1 -1
- package/package.json +1 -1
- package/src/commands/project/doctor.js +11 -4
- package/src/commands/project/init.js +1 -1
- package/src/commands/project/status.js +2 -2
- package/src/commands/project/update.js +91 -7
- package/src/commands/state/gate-check.js +223 -0
- package/src/commands/state/gate-decision.js +46 -10
- package/src/commands/validation/verify.js +18 -1
- package/src/core/paths/output-schema.js +0 -1
- package/src/lib/agents/output-collector.js +0 -1
- package/src/lib/git/default-branch.js +65 -0
- package/src/lib/risk-detector.js +13 -0
- package/src/lib/stack-filter.js +7 -2
- package/src/scripts/setup-infra.js +27 -8
- package/src/utils/skills-installer.js +28 -15
- package/src/lib/standards/digest-builder.js +0 -72
package/framework/MORPH.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
> Ele define papéis, fases, outputs, standards, gates e skills do morph-spec.
|
|
5
5
|
> Não procure instruções em hooks — o harness vive aqui.
|
|
6
6
|
>
|
|
7
|
-
> **Depois de ler:** leia `.morph/state.json`
|
|
7
|
+
> **Depois de ler:** leia `.morph/state.json` — **índice fino e gitignored** (status + updatedAt por feature, reconstruído dos `feature.json` a cada load) — só para descobrir a feature ativa; **nunca o edite à mão** (perdido no próximo load). O estado autoritativo e commitado vive em `.morph/features/{feature}/feature.json`. Feature `in_progress` → assuma o papel da fase e continue sem esperar instrução. Sem feature ativa → pergunte qual trabalhar.
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -21,16 +21,14 @@ Entre gates, você opera com autonomia total. O dev valida. Você executa.
|
|
|
21
21
|
| Sub-agent retornou relatório (qualquer auto-score) | Auto-score é triagem, não aprovação: a task só avança com morph-eval ≥ 9 |
|
|
22
22
|
| Sub-agent com auto-score < 7 | Re-despachar com feedback específico (ou corrigir inline) antes do morph-eval |
|
|
23
23
|
| Build/typecheck quebra | Corrigir antes de marcar tarefa como done |
|
|
24
|
-
| Task implementada (código escrito)
|
|
24
|
+
| Task implementada (código escrito) | `morph-spec verify <feature> <task>` ANTES do juiz: vermelho = feedback ao loop sem gastar o morph-eval; verde → morph-eval avalia o que o código não pega |
|
|
25
25
|
| Score morph-eval ≥ 9 | Silêncio (aprovação implícita), próxima tarefa |
|
|
26
|
-
| Score morph-eval < 9 numa task | Loop de correção autônomo: re-implementar com
|
|
27
|
-
| Score morph-eval < 9 após 3 tentativas | Escalar ao usuário (aceitar
|
|
26
|
+
| Score morph-eval < 9 numa task | Loop de correção autônomo: re-implementar com feedback priorizado, até 3 tentativas, sem pausa humana |
|
|
27
|
+
| Score morph-eval < 9 após 3 tentativas | Escalar ao usuário (aceitar/continuar/pular) — único ponto de pausa do loop |
|
|
28
28
|
|
|
29
|
-
**Regra de ouro:**
|
|
29
|
+
**Regra de ouro:** dúvida que não bloqueia → resolver e registrar; dúvida que bloqueia → uma pergunta, máximo. Vale **entre gates** (plan/implement/review) — **não** vale na abertura da feature: a fase proposal pode rodar em **modo entrevista** (escolhido na pergunta de abertura, `morph-brainstorming` Parte 2), onde perguntar até fechar o entendimento é o comportamento desejado.
|
|
30
30
|
|
|
31
|
-
**
|
|
32
|
-
|
|
33
|
-
**Código antes do juiz:** o `morph-spec verify` é a barreira determinística e barata — build, testes e validadores estáticos rodam primeiro, sempre igual, sem custo de tokens. O juiz LLM (morph-eval) só é acionado quando o verify passa. Código é o herói não-celebrado do loop: ele pega o que pega de graça; o juiz gasta tokens só no que o código não consegue ver.
|
|
31
|
+
**Código antes do juiz:** `morph-spec verify` (build+testes+validadores) é a barreira determinística e barata, sempre roda primeiro; o juiz LLM (morph-eval) só é acionado quando o verify passa — ele gasta tokens só no que o código não pega sozinho.
|
|
34
32
|
|
|
35
33
|
---
|
|
36
34
|
|
|
@@ -57,34 +55,27 @@ Padrões proibidos automaticamente injetados no mandate:
|
|
|
57
55
|
- Repository genérico (`IRepository<T>`/`IUnitOfWork`) — redundante sobre EF Core: `DbSet<T>` já é repository, `DbContext` já é unit of work
|
|
58
56
|
- SQL cru (`FromSqlRaw`, `ExecuteQuery(string)`) sem justificativa em `decisions.md` — use LINQ
|
|
59
57
|
|
|
60
|
-
Acesso a dados em VSA:
|
|
58
|
+
Acesso a dados em VSA: `ApplicationDbContext` direto no slice (`DbSet<T>` já é repository, `DbContext` já é unit of work). Concorrência ou SQL específico → store dedicado hand-written com justificativa em `decisions.md`.
|
|
61
59
|
|
|
62
60
|
---
|
|
63
61
|
|
|
64
62
|
## 1. Papéis
|
|
65
63
|
|
|
66
|
-
O morph-spec opera com três papéis que você assume conforme o contexto
|
|
64
|
+
O morph-spec opera com três papéis que você assume conforme o contexto:
|
|
67
65
|
|
|
68
|
-
**Orchestrator** — ativo na abertura de uma feature e nas transições de fase.
|
|
69
|
-
Responsabilidades: ler o mandato, entender o escopo, propor o plano de ataque, identificar dependências entre tarefas, garantir que gates sejam respeitados antes de avançar.
|
|
70
|
-
Anti-padrão: o Orchestrator não escreve código. Se você está no papel de Orchestrator e percebe que começou a implementar algo, pare — você transitou de papel sem intenção, e o plano provavelmente ainda não está fechado.
|
|
66
|
+
**Orchestrator** — ativo na abertura de uma feature e nas transições de fase. Lê o mandato, entende o escopo, propõe o plano de ataque, identifica dependências entre tarefas, garante que gates sejam respeitados antes de avançar. Anti-padrão: não escreve código — se percebe que começou a implementar, pare, você transitou de papel sem intenção.
|
|
71
67
|
|
|
72
|
-
**Specialist** — ativo durante a
|
|
73
|
-
Responsabilidades: executar tarefas do tasks.json em ordem, consultar standards relevantes antes de cada tarefa, registrar decisões e desvios no decisions.md, manter o recap.md atualizado ao final de cada tarefa.
|
|
74
|
-
Anti-padrão: o Specialist não cria novas tarefas. Descobertas de escopo durante a implementação vão para o decisions.md com flag "escopo expandido" — o Orchestrator avalia se o tasks.json precisa ser atualizado.
|
|
68
|
+
**Specialist** — ativo durante a implementação. Executa tarefas do tasks.json em ordem, consulta standards antes de cada uma, registra decisões/desvios no decisions.md, mantém o recap.md atualizado ao final de cada tarefa. Anti-padrão: não cria novas tarefas — descoberta de escopo vai para decisions.md com flag "escopo expandido", o Orchestrator avalia se o tasks.json precisa mudar.
|
|
75
69
|
|
|
76
|
-
**Evaluator** — ativo após uma tarefa ou fase
|
|
77
|
-
Responsabilidades: aplicar as rubricas em `.morph/framework/evals/rubrics/`, produzir score 0-10, emitir feedback priorizado quando score < 9 (que alimenta o loop de correção autônomo do morph-apply), escalar para revisão humana apenas quando o loop de correção se esgotar (3 tentativas sem atingir 9).
|
|
78
|
-
No **Gate 3** o Evaluator é obrigatoriamente um sub-agent independente: a `morph-review` despacha o subagent registrado `morph-evaluator` (gerado de `agents.json`, tools read-only) com contexto fresco — mandate + diff da implementação + saída real dos testes — e o score composto da feature vem desse retorno, nunca de auto-avaliação de quem implementou. **A regra é enforced server-side:** `morph-spec approve {feature} review` recusa (exit 1) enquanto `4-review/evaluator-report.md` não existir. Se o dispatch for genuinamente impossível nesta sessão, aprove com `--self-assessed` — a degradação é gravada em `approvalGates.review.selfAssessed` e aparece marcada no `morph-spec list`. `--force` não dispensa a regra (é só para ordem de gate). **Exceção `hotfix`:** o tipo nunca despacha o avaliador (velocidade é o ponto do hotfix); o Gate 3 exige `4-review/review-report.md` — o artefato que a `morph-hotfix` de fato produz — e a assinatura humana continua obrigatória (§2.1/§5), sem afrouxar nada para os demais tipos.
|
|
79
|
-
Anti-padrão: o Evaluator não reescreve o código que avaliou. Se o score está abaixo de 6, o relatório vai para o humano — não para uma segunda rodada de tentativa automática.
|
|
70
|
+
**Evaluator** — ativo após uma tarefa ou fase concluída. Aplica as rubricas em `.morph/framework/evals/rubrics/`, produz score 0-10, emite feedback priorizado quando < 9 (alimenta o loop de correção autônomo do morph-apply), escala ao humano só quando o loop se esgotar (3 tentativas sem atingir 9). No **Gate 3** é obrigatoriamente um sub-agent independente com contexto fresco — nunca auto-avaliação de quem implementou (enforcement: relatório obrigatório, `--self-assessed`, exceção `hotfix` — **§5**). Anti-padrão: não reescreve o código avaliado; score < 6 vai para o humano, não para retry automático.
|
|
80
71
|
|
|
81
|
-
Os papéis não são exclusivos — numa sessão longa você transita entre
|
|
72
|
+
Os papéis não são exclusivos — numa sessão longa você transita entre eles. A transição deve ser explícita: conclua o que estava fazendo ou registre o estado no recap.md antes de mudar.
|
|
82
73
|
|
|
83
74
|
---
|
|
84
75
|
|
|
85
76
|
## 2. Fases
|
|
86
77
|
|
|
87
|
-
O fluxo padrão de uma feature tem quatro fases
|
|
78
|
+
O fluxo padrão de uma feature tem quatro fases, cada uma com pasta dedicada em `.morph/features/{feature}/`. Estado autoritativo e commitado: `.morph/features/{feature}/feature.json` (status, approvalGates, outputs, tasks, gateDecisions, taskScores, archivedAt); `.morph/state.json` na raiz é só índice fino gitignored derivado dele; identidade do projeto em `.morph/config/config.json` (commitado).
|
|
88
79
|
|
|
89
80
|
| Fase | Pasta | Gate | O que termina a fase |
|
|
90
81
|
|-------------|----------------|-----------------------|-------------------------------------------------|
|
|
@@ -93,15 +84,15 @@ O fluxo padrão de uma feature tem quatro fases. Cada fase tem uma pasta dedicad
|
|
|
93
84
|
| implement | `3-implement/` | Nenhum | Todas as tasks do tasks.json com status `done` |
|
|
94
85
|
| review | `4-review/` | Gate 3 (trust-aware) | `review-report.md` aprovado e commitado |
|
|
95
86
|
|
|
96
|
-
A fase `proposal` tem dois **modos de descoberta**, escolhidos pelo usuário na abertura (só `workType: feature
|
|
87
|
+
A fase `proposal` tem dois **modos de descoberta**, escolhidos pelo usuário na abertura (só `workType: feature`/`bug` — `chore`/`hotfix` nascem em `implement`): **entrevista** (uma pergunta por vez até a árvore de decisões abertas zerar; Gate 1 pausa sempre) e **automático** (até 4 perguntas em lote; Gate 1 trust-aware). Nos dois modos a varredura do ambiente roda **antes** de qualquer pergunta — fato que `morph-stack-scan` ou o acervo de use cases responde não vira pergunta. Detalhes em `morph-brainstorming`.
|
|
97
88
|
|
|
98
|
-
A fase `1-design/` (design system, mockups, flows) é opcional —
|
|
89
|
+
A fase `1-design/` (design system, mockups, flows) é opcional — só para features com UI nova, requisitada explicitamente pelo usuário.
|
|
99
90
|
|
|
100
91
|
Não avance de fase sem o gate correspondente ter sido confirmado.
|
|
101
92
|
|
|
102
93
|
### 2.1 Roteamento por tipo de trabalho
|
|
103
94
|
|
|
104
|
-
Nem todo trabalho merece o pipeline completo. Cada feature nasce com **identidade** (`name` = slug
|
|
95
|
+
Nem todo trabalho merece o pipeline completo. Cada feature nasce com **identidade** (`name` = slug + `description` obrigatória) e um **workType** (`morph-spec create <f> --description "<o quê/porquê>" --type <tipo>`, ou classificado de `--request "<pedido>"`, que também semeia a descrição) que dimensiona o pipeline:
|
|
105
96
|
|
|
106
97
|
| Tipo | Pipeline | Gates |
|
|
107
98
|
|------|----------|-------|
|
|
@@ -110,29 +101,29 @@ Nem todo trabalho merece o pipeline completo. Cada feature nasce com **identidad
|
|
|
110
101
|
| `chore` | fast-track: direto para implement (Gates 1/2 carimbados por política no nascimento) → review leve | só 3 |
|
|
111
102
|
| `hotfix` | scout (diagnóstico read-only) → fix cirúrgico → **aprovação humana obrigatória** → test loop → ship | 3 (humano sempre) |
|
|
112
103
|
|
|
113
|
-
**Como classificar (router):** sinais determinísticos primeiro —
|
|
104
|
+
**Como classificar (router):** sinais determinísticos primeiro — `morph-spec create --request "<texto>"` roda o detector por keywords (hotfix: "produção caiu/urgente/incident/p0"; bug: "bug/corrigir/exception/regressão"; chore: "typo/rename/bump/config/docs/cleanup"). As keywords casam como **palavra inteira** ("group0" não é `p0`, "prefix" não é `fix`, "debug" não é `bug`) — casar demais pularia gates num pedido inócuo; por isso plural e flexão são listados explicitamente ("bugs", "incidentes", "configs"). Confiança `high` → usa o tipo. Empate (`tie`) ou nenhum sinal (`none`) → o comando sai com código 2 e os candidatos; **você decide como roteador** e re-roda com `--type`. Só vale uma `AskUserQuestion` quando o pedido é genuinamente indeterminado.
|
|
114
105
|
|
|
115
|
-
**Como o skip funciona
|
|
106
|
+
**Como o skip funciona:** `chore`/`hotfix` têm os gates `proposal`/`plan` carimbados no nascimento com `approvedBy: "policy:{tipo}"`. Como `derivePhase` é gate-aware, o trabalho já nasce em `implement` — sem tocar `phases.json`. Artefatos reutilizam os nomes canônicos (hotfix escreve brief curto em `proposal.md`; ambos escrevem `2-plan/tasks.json` mínimo de 1-3 tasks para ligar trace/score/dag).
|
|
116
107
|
|
|
117
|
-
**Compat:**
|
|
108
|
+
**Compat:** feature sem `workType` (pré-v8) é tratada como `feature`. Mudança mid-flight: `morph-spec retype <f> <tipo>` (desfaz só carimbos de política, preserva aprovações humanas; bloqueado após o Gate 3).
|
|
118
109
|
|
|
119
|
-
**Nascimento numa branch:** toda feature —
|
|
110
|
+
**Nascimento numa branch:** toda feature — com ou sem `--worktree` — nasce em `morph/{f}` ramificada da default (comum: desenvolve direto na raiz; worktree: isola em `worktrees/{f}`). Fechamento simétrico: `morph-spec finish <f> --pr|--merge` (§2.2) fecha os dois igual. Features pré-modelo (sem branch `morph/{f}`) fecham por `morph-spec archive <f>`, não por `finish`.
|
|
120
111
|
|
|
121
112
|
### 2.2 Desenvolvimento paralelo por worktree (frota)
|
|
122
113
|
|
|
123
|
-
Features independentes podem ser desenvolvidas **em paralelo, cada uma no seu git worktree**,
|
|
114
|
+
Features independentes podem ser desenvolvidas **em paralelo, cada uma no seu git worktree**, 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:
|
|
124
115
|
|
|
125
|
-
- **Uma feature = um worktree = uma instância.** Nunca abra duas instâncias na mesma feature (
|
|
126
|
-
-
|
|
127
|
-
- Infra compartilhada (`node_modules`, `.claude`, `.morph/framework`)
|
|
128
|
-
- **Nunca apague um worktree à mão** (`rm -rf`, `Remove-Item -Recurse -Force`,
|
|
129
|
-
- **Ambiente separado (portas):** o setup aloca um **bloco de portas determinístico** por feature
|
|
130
|
-
- **Banco de dados:**
|
|
131
|
-
- **Limitação conhecida:** `node_modules`
|
|
132
|
-
- **Handoff entre sessões:** `.morph/features/{f}/handoff.md`
|
|
133
|
-
- **Visão da frota:** `morph-spec fleet` agrega raiz + worktrees (fase, gates
|
|
134
|
-
- **Ownership de arquivos:**
|
|
135
|
-
- **Fechamento:** aprove o Gate 3, depois **`morph-spec finish <f> --pr|--merge`** —
|
|
116
|
+
- **Uma feature = um worktree = uma instância.** Nunca abra duas instâncias na mesma feature (setup recusa, exit 3).
|
|
117
|
+
- `feature.json` viaja **commitado na branch** `morph/{f}`. `state.json` local do worktree é índice derivável — materializado por self-heal, nunca sincronizado à mão.
|
|
118
|
+
- Infra compartilhada (`node_modules`, `.claude`, `.morph/framework`) linkada por junction; `memory/`/`logs/` são locais de cada worktree. Faltou infra (worktree aberto com `git worktree add` puro) → `morph-spec worktree link --all`.
|
|
119
|
+
- **Nunca apague um worktree à mão** (`rm -rf`, `Remove-Item -Recurse -Force`, explorador/IDE). `morph-spec finish`/`worktree remove` desmonta a junction ANTES de remover (PROVE-or-DECLINE); uma remoção genérica não sabe disso e, em várias implementações (inclusive `Remove-Item -Recurse` no Windows), **atravessa a junction** e apaga o conteúdo real compartilhado (`.claude`/`node_modules`/`.morph/framework`), não só o link. Use sempre `morph-spec finish <f> --pr|--merge` (ou `git worktree remove`, sem fechar a feature).
|
|
120
|
+
- **Ambiente separado (portas):** o setup aloca um **bloco de portas determinístico** por feature em `.morph/worktree.env` (`PORT`, `MORPH_PORT_RANGE`; `ASPNETCORE_URLS` se dotnet). **Suba dev servers SEMPRE nas portas do bloco** — as portas padrão (3000/5000) pertencem à raiz. Arquivo local, git-invisível; SessionStart injeta as portas. Overrides em `config.json → fleet.basePort/blockSize`.
|
|
121
|
+
- **Banco de dados:** compartilhado por padrão. Isolamento real (Neon MCP): branch de DB `morph/{f}` + connection string no `.morph/worktree.env`; sem Neon, prefixe schema/DB local pelo nome da feature. Migration destrutiva compartilhando banco → integre antes de abrir worktrees irmãos.
|
|
122
|
+
- **Limitação conhecida:** `node_modules` compartilhado (junction) — mudança de dependência afeta os irmãos. Mudou dependência: conclua e integre (`finish`) antes de seguir em paralelo.
|
|
123
|
+
- **Handoff entre sessões:** `.morph/features/{f}/handoff.md` — documento de retomada comprimido, regenerável (`morph-spec handoff <f>`), **aponta** para os artefatos em vez de copiá-los. Regenerado em `worktree setup`/`create --worktree`/`advance`. **Leia-o antes de re-derivar contexto à mão.** Nunca edite manualmente.
|
|
124
|
+
- **Visão da frota:** `morph-spec fleet` agrega raiz + worktrees (fase, gates, tasks, portas, handoff, último commit, sujeira). `morph-spec worktree list` é a visão enxuta por worktree.
|
|
125
|
+
- **Ownership de arquivos:** sem lock em runtime — colisão se resolve **em plan-time** (`morph-spec dag` detecta overlap de `outputs`, recomenda `isolation: "worktree"`) e **por construção** (uma feature = um worktree = um escritor). Arquivos compartilhados convergem no merge do `finish`; conflito ali é escopo sobreposto, não bug.
|
|
126
|
+
- **Fechamento:** aprove o Gate 3, depois **`morph-spec finish <f> --pr|--merge`** — encerramento único e simétrico. **Arquiva** commitando `features/{f} → archive/{f}` **dentro de `morph/{f}`** e integra: `--merge` faz `--no-ff` **local** (sem push; recusa se sujo; aborta em conflito); `--pr` faz `push` + `gh pr create` (exige `origin`+`gh`, checados **antes** de arquivar). Worktree desmontado (PROVE-or-DECLINE), portas liberadas; no `--pr` a branch é **preservada**. `morph-spec archive` fica para arquivar-sem-integrar (features legadas, faxina).
|
|
136
127
|
|
|
137
128
|
---
|
|
138
129
|
|
|
@@ -143,80 +134,74 @@ Não invente caminhos alternativos.
|
|
|
143
134
|
|
|
144
135
|
### Proposal (`0-proposal/`)
|
|
145
136
|
|
|
146
|
-
- `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
|
|
137
|
+
- `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. Máximo ~2 páginas; além disso, o escopo provavelmente precisa ser cortado antes de avançar.
|
|
147
138
|
|
|
148
139
|
### Plan (`2-plan/`)
|
|
149
140
|
|
|
150
|
-
- `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
|
|
141
|
+
- `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 obrigatórias `Pré-condições`, `Cenário principal` (curto) e `Pós-condições` (P1, P2…). `Fluxos alternativos` (A1, A2…) e `Delta de domínio` são **opcionais** — só quando o comportamento não-trivial exigir (detalhe: `morph-plan`).
|
|
151
142
|
|
|
152
|
-
**Pós-condição precisa ser observável em teste** —
|
|
143
|
+
**Pós-condição precisa ser observável em teste** — 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. Chega **literal** ao `doneCriteria` da task que a realiza — tradução manual nesse ponto é o que hoje perde o requisito.
|
|
153
144
|
|
|
154
|
-
|
|
145
|
+
`id` sequencial **no projeto**, não na feature — leia o acervo `.morph/specs/usecases/` mais os use cases das features ativas, tome o maior mais um. Status: `draft` → `approved` (Gate 2) → `implemented` (promoção no `finish`) — descritivo, quem trava fase é o gate. **Editável depois do Gate 2**, por design (muda comportamento, re-roda `implement`, auditoria no git). Obrigatoriedade por tipo de trabalho: ver `morph-plan`.
|
|
155
146
|
|
|
156
|
-
- `spec.md` — especificação técnica
|
|
147
|
+
- `spec.md` — especificação técnica: arquitetura, componentes, integrações, fluxos de dados, edge cases **técnicos**. Responde **como** os use cases serão realizados — não repete o comportamento. Deve bastar para implementar sem perguntas básicas: tecnologia listada sem explicar como os componentes se conectam é um spec.md fraco.
|
|
157
148
|
|
|
158
|
-
- `mandate.md` — contrato de implementação: stack exata, standards obrigatórios (com links), patterns
|
|
149
|
+
- `mandate.md` — contrato de implementação: stack exata, standards obrigatórios (com links), patterns proibidos, checklist de done verificável. Lido no início de cada task — específico o bastante para resolver ambiguidades sem consultar o Orchestrator.
|
|
159
150
|
|
|
160
|
-
- `tasks.json` —
|
|
151
|
+
- `tasks.json` — validada contra `framework/schemas/tasks.schema.json`. Cada task: `id` (T1, T2...), `title`, `description`, `dependencies` (IDs), `effort` (S/M/L/XL), `doneCriteria`, `status` (pending/in_progress/done/skipped/blocked), `outputs` (paths esperados), `usecase` (opcional — **ID** do use case, `UC-07`, nunca o nome do arquivo). `doneCriteria` de task com `usecase` carrega a **pós-condição literal**, com rótulo (`"P2 — cada veterinário traz..."`). Toda entrada do recap.md referencia um ID do tasks.json.
|
|
161
152
|
|
|
162
|
-
- `decisions.md` — log de decisões técnicas
|
|
153
|
+
- `decisions.md` — log de decisões técnicas (alternativa descartada, motivo, quem decidiu). Só existe se houver decisão não trivial a rastrear.
|
|
163
154
|
|
|
164
155
|
### Implement (`3-implement/`)
|
|
165
156
|
|
|
166
|
-
- `recap.md` — atualizado ao fim de cada
|
|
157
|
+
- `recap.md` — atualizado ao fim de cada task: ID, o que foi feito, arquivos modificados, problemas e resolução, standard consultado. Categoria sem nada a registrar → escreva "nenhum" (recap vazio é pior que mínimo).
|
|
167
158
|
|
|
168
159
|
### Review (`4-review/`)
|
|
169
160
|
|
|
170
|
-
- `review-report.md` —
|
|
161
|
+
- `review-report.md` — scores por dimensão (arquitetura, contratos, qualidade, cobertura), feedback priorizado (bloqueantes primeiro), aprovação/rejeição com critérios explícitos. "Aprovado" sem scores não satisfaz o gate.
|
|
171
162
|
|
|
172
163
|
### Acervo de use cases (`.morph/specs/usecases/`)
|
|
173
164
|
|
|
174
|
-
O acervo permanente do projeto: `UC-{nn}-{slug}.md`, **commitado
|
|
165
|
+
O acervo permanente do projeto: `UC-{nn}-{slug}.md`, **commitado**. Descrição viva do comportamento do sistema, sobrevive ao arquivamento — diferente dos traces, **faz parte da entrega**.
|
|
175
166
|
|
|
176
|
-
- **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
|
|
177
|
-
- **O que é cobrado mecanicamente:** `morph-spec dag {feature}` cruza `tasks.json` com os use cases —
|
|
178
|
-
- **Via única de escrita:** a promoção lê **só** de `{feature}/2-plan/usecases/`. Nunca edite `.morph/specs/usecases/` à mão —
|
|
179
|
-
- **Quando chega na default:** em `--merge`, no merge `--no-ff`; em `--pr`, só quando
|
|
180
|
-
- **Sobrescrita por ID:**
|
|
181
|
-
- **Fail-open:** feature sem `2-plan/usecases/` promove nada, em silêncio
|
|
182
|
-
- **Colisão entre features paralelas:** dois worktrees podem alocar `UC-08` sem se enxergar
|
|
167
|
+
- **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` — junto com o estado arquivado (§2.2), não um passo pós-merge.
|
|
168
|
+
- **O que é cobrado mecanicamente:** `morph-spec dag {feature}` cruza `tasks.json` com os use cases — `UC-{nn}` inexistente é **erro** (não despacha); pós-condição órfã e `doneCriteria` parafraseado são avisos. Cobre o *encanamento*; se a pós-condição é observável em teste continua sendo critério do Gate 2 e da rubrica `test-coverage`.
|
|
169
|
+
- **Via única de escrita:** a promoção lê **só** de `{feature}/2-plan/usecases/`. Nunca edite `.morph/specs/usecases/` à mão — pula `status: implemented`, a sobrescrita por ID e o commit escopado, criando duas verdades. Mudar um UC existente (caso `bug`): copie para `2-plan/usecases/` da feature, corrija lá, deixe o `finish` sobrescrever.
|
|
170
|
+
- **Quando chega na default:** em `--merge`, no merge `--no-ff`; em `--pr`, só quando mergeado — o acervo descreve o que foi **integrado**, não proposto.
|
|
171
|
+
- **Sobrescrita por ID:** `UC-07` existente é substituído pela versão integrada, mesmo com slug novo — exatamente um arquivo por ID.
|
|
172
|
+
- **Fail-open:** feature sem `2-plan/usecases/` promove nada, em silêncio — a promoção nunca impede o fechamento.
|
|
173
|
+
- **Colisão entre features paralelas:** dois worktrees podem alocar `UC-08` sem se enxergar. Aceita e resolvida no merge, como conflito de arquivo (§2.2) — renumere o UC perdedor e atualize `usecase` no `tasks.json` arquivado. Sem alocador central por design.
|
|
183
174
|
|
|
184
175
|
### Traces (`.morph/traces/`)
|
|
185
176
|
|
|
186
|
-
Cada fase
|
|
187
|
-
O trace registra tarefas, scores de eval, standards consultados e sub-agents despachados.
|
|
188
|
-
O formato canônico está em `.morph/framework/evals/trace-schema.md` (criado na issue #17).
|
|
189
|
-
**O trace é gerado automaticamente pelo hook `trace-autogen`** a cada write de `tasks.json`, a partir de tasks.json + recap.md + `taskScores` do feature.json — as skills não o escrevem à mão (a escrita manual foi removida da cerimônia por task).
|
|
190
|
-
Traces são ignorados pelo git (`.gitignore`) e servem para análise do harness — não fazem parte da entrega da feature.
|
|
177
|
+
Cada fase produz um trace JSON em `.morph/traces/YYYY-MM-DD-{feature}-{phase}.json` (tarefas, scores de eval, standards consultados, sub-agents despachados; formato em `.morph/framework/evals/trace-schema.md`). **Gerado automaticamente pelo hook `trace-autogen`** a cada write de `tasks.json` — as skills não o escrevem à mão. Ignorado pelo git; serve para análise do harness, não é entrega da feature.
|
|
191
178
|
|
|
192
179
|
---
|
|
193
180
|
|
|
194
181
|
## 4. Como consultar Standards
|
|
195
182
|
|
|
196
|
-
|
|
183
|
+
**Nunca carregue todos os standards de uma vez** — custa tokens sem benefício, você não sabe quais serão relevantes antes de começar. Consulte sob demanda, por tarefa.
|
|
197
184
|
|
|
198
|
-
|
|
185
|
+
Índice em `framework/standards/STANDARDS.json` (`id`, `name`, `path`, `category`, `tags`).
|
|
199
186
|
|
|
200
187
|
**Fluxo de consulta:**
|
|
201
188
|
|
|
202
|
-
1. Antes de iniciar uma tarefa, identifique
|
|
203
|
-
2. Leia apenas o arquivo `.md` daquele standard
|
|
204
|
-
3. Aplique
|
|
189
|
+
1. Antes de iniciar uma tarefa, identifique 1-3 standards relevantes — rode `morph-spec standards --find "<domínio/tecnologia da task>"` (devolve o top 3 como `id · path · digest`) em vez de filtrar `id`/`tags` à mão no JSON.
|
|
190
|
+
2. Leia apenas o arquivo `.md` daquele standard (campo `path`).
|
|
191
|
+
3. Aplique durante a implementação. Se precisar de mais contexto, leia mais um standard.
|
|
205
192
|
4. Registre no recap.md qual standard foi consultado e como foi aplicado.
|
|
206
193
|
|
|
207
|
-
**
|
|
208
|
-
|
|
209
|
-
**Como identificar o standard certo:** filtre por `category` primeiro (ex: "architecture", "contracts", "testing"), depois por `tags` (ex: "dotnet", "nextjs", "blazor"). Se dois standards parecem relevantes e há conflito, adote o mais específico ao stack do projeto — e registre o conflito no decisions.md.
|
|
194
|
+
**Como identificar o standard certo:** filtre por `category` primeiro (ex: "architecture", "contracts", "testing"), depois por `tags` (ex: "dotnet", "nextjs", "blazor"). Dois standards relevantes em conflito → adote o mais específico ao stack do projeto e registre o conflito no decisions.md.
|
|
210
195
|
|
|
211
|
-
O agente responsável por um domínio está
|
|
196
|
+
O agente responsável por um domínio está em `.morph/framework/agents.json` (fonte única — os subagents `morph-{id}` são gerados dele). O campo `persona` define o ponto de vista e o nível de rigor a adotar ao aplicar os standards daquele domínio trabalhando inline (um agente de arquitetura é mais rígido que um de suporte mensal).
|
|
212
197
|
|
|
213
|
-
**Quando não há standard adequado:** registre no decisions.md que nenhum
|
|
198
|
+
**Quando não há standard adequado:** registre no decisions.md que nenhum cobre o caso, descreva o critério adotado, sinalize para revisão futura. Não invente um standard — padrão não documentado é dívida técnica disfarçada.
|
|
214
199
|
|
|
215
200
|
---
|
|
216
201
|
|
|
217
202
|
## 5. Gates de Aprovação (Trust Mode)
|
|
218
203
|
|
|
219
|
-
Gates são pontos de **pausa potencial**. Em `trust: "auto"` (default),
|
|
204
|
+
Gates são pontos de **pausa potencial**. Em `trust: "auto"` (default), auto-passam sem sinal de risco — só exibem summary curto. Em `trust: "manual"` OU com sinal de risco, o gate pausa via `AskUserQuestion` com options padrão:
|
|
220
205
|
|
|
221
206
|
```
|
|
222
207
|
- "aprovado, prosseguir"
|
|
@@ -224,102 +209,78 @@ Gates são pontos de **pausa potencial**. Em `trust: "auto"` (default), gates **
|
|
|
224
209
|
- "cancelar feature" (Gate 3 usa "rollback" em vez de "cancelar")
|
|
225
210
|
```
|
|
226
211
|
|
|
227
|
-
**Sinais de risco que forçam pausa em auto** (
|
|
212
|
+
**Sinais de risco que forçam pausa em auto** (`gate-check` aplica esta tabela via `shouldPauseGate` — fonte única; sinal que só a sessão conhece escala via `gate-decision` manual):
|
|
228
213
|
|
|
229
214
|
| Sinal | Threshold | Quando aplica |
|
|
230
215
|
|-------|-----------|---------------|
|
|
231
216
|
| `designSystemDivergence` | true | Brainstorming detecta fontes conflitantes (spec antigo vs bundle local) |
|
|
232
217
|
| `standardsViolations` | array.length > 0 | Mandate ou implementation viola padrões proibidos |
|
|
233
|
-
| `evalScore` | < 9 |
|
|
218
|
+
| `evalScore` | < 9 | score composto da feature (via morph-review) abaixo do mínimo |
|
|
234
219
|
| `taskCount` | > 20 | Escopo grande — provavelmente vale revisar antes de implementar |
|
|
235
|
-
| `workType` | === 'hotfix' | Gate 3 pausa SEMPRE
|
|
236
|
-
|
|
237
|
-
**Gate 1 — Proposta**
|
|
238
|
-
- Sinais: `designSystemDivergence`, `standardsViolations` (improvável).
|
|
239
|
-
- Skill responsável: `morph-brainstorming`.
|
|
240
|
-
|
|
241
|
-
**Gate 2 — Plano**
|
|
242
|
-
- Sinais: todos do Gate 1 + `taskCount`, `standardsViolations` em mandate.
|
|
243
|
-
- Skill responsável: `morph-plan`.
|
|
220
|
+
| `workType` | === 'hotfix' | Gate 3 pausa SEMPRE (detalhe abaixo, "Gates por tipo de trabalho") |
|
|
244
221
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
222
|
+
| Gate | Sinais | Skill responsável |
|
|
223
|
+
|------|--------|--------------------|
|
|
224
|
+
| 1 — Proposta | `designSystemDivergence`, `standardsViolations` (improvável) | `morph-brainstorming` |
|
|
225
|
+
| 2 — Plano | Gate 1 + `taskCount`, `standardsViolations` em mandate | `morph-plan` |
|
|
226
|
+
| 3 — Review | `evalScore` composite, `standardsViolations` em implementation | `morph-review` |
|
|
248
227
|
|
|
249
|
-
**Gates por tipo de trabalho:** `chore
|
|
228
|
+
**Gates por tipo de trabalho:** `chore`/`hotfix` pulam Gates 1 e 2 — carimbados por política no nascimento (`approvedBy: "policy:{tipo}"`, nunca `"auto"`, para não colidir com o gate-guard); a barra do morph-eval e o Gate 3 valem para todos os tipos. `hotfix`: Gate 3 **sempre humano** (mesmo em `trust: auto` — `morph-hotfix` pausa via `AskUserQuestion`, o `risk-detector` força, o backstop server-side recusa `approve ... review --mode auto`) e exige `4-review/review-report.md` em vez de `evaluator-report.md`. Demais tipos exigem `evaluator-report.md`, **enforced server-side** (`morph-spec approve {feature} review` recusa exit 1 sem ele; `--force` não dispensa) — ou `--self-assessed` registrado (`approvalGates.review.selfAssessed`, marcado no `morph-spec list`).
|
|
250
229
|
|
|
251
230
|
Para alterar o modo: editar `.morph/config/config.json → trust` (`"auto"` ou `"manual"`). Configs sem o campo `trust` defaultam para `"auto"`.
|
|
252
231
|
|
|
253
|
-
**Comportamento padrão fora de gate:**
|
|
232
|
+
**Comportamento padrão fora de gate:** autonomia total — gates só existem nestes três pontos. Não pause no meio de implementação a menos que encontre ambiguidade de escopo que o mandate não cobre — registre em decisions.md, resolva conservadoramente, sinalize na entrega da task.
|
|
254
233
|
|
|
255
|
-
**A aprovação de gate é unificada nos comandos da CLI —
|
|
234
|
+
**A aprovação de gate é unificada nos comandos da CLI — nunca edite o estado à mão.** Em `trust: "auto"` (sem `AskUserQuestion`): `morph-spec approve <feature> <gate> --mode auto`; `morph-spec advance <feature>` aprova o gate corrente **e** já cria a pasta da próxima fase (`--design` para o ramo opcional de uiux). Scores por task: `morph-spec score <feature> <task> <score> [--dims a,c,q,t]` — nunca edite `taskScores` à mão. **O hook state-sync.js** cobre o caminho manual: `AskUserQuestion` respondida com label "aprovado" → registra o gate no `feature.json` autoritativo com `approvedBy: "manual"`. **A feature é identificada pelo nome que a pergunta cita** — grava na árvore que a possui (raiz ou worktree), nunca na "feature ativa" de quem rodou a sessão. Pergunta sem nome, árvore com mais de uma feature: o hook **recusa gravar** e avisa — aprove por `morph-spec approve <feature> <gate>`. Gate sempre gravado em `.morph/features/{feature}/feature.json` — nunca via Edit de `state.json`.
|
|
256
235
|
|
|
257
|
-
**Registre quem aprovou
|
|
258
|
-
- `approvedBy: "auto"` — gate avançado por política `trust: auto` sem decisão humana.
|
|
259
|
-
- `approvedBy: "manual"` — um humano aprovou explicitamente (via `AskUserQuestion`, ou, quando `AskUserQuestion` está indisponível em contexto headless, via mensagem em texto do usuário começando em "aprovado"). Em `trust: manual`, todo gate é `"manual"` — nunca grave `"auto"` num gate que um humano aprovou em conversa.
|
|
236
|
+
**Registre quem aprovou (`approvedBy`):** objeto `{ approved, timestamp, approvedBy }`. `"auto"` — política `trust: auto` sem decisão humana. `"manual"` — humano aprovou explicitamente (via `AskUserQuestion`, ou, sem ela em headless, via texto começando em "aprovado"); em `trust: manual` todo gate é `"manual"` — nunca grave `"auto"` num gate que um humano aprovou. Mantém o audit trail honesto nos contextos headless (CI, `claude -p`) onde mais importa.
|
|
260
237
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
**O hook gate-guard.js** confere, sem bloquear, se a ação tomada num gate (pausar via `AskUserQuestion` vs auto-aprovar) bateu com a decisão de trust que a skill computou via `shouldPauseGate`. Para isso, a skill **persiste** a decisão no `feature.json` autoritativo da feature antes de agir — via `morph-spec gate-decision <feature> <gate> --pause <bool> [--reason <txt>] [--signals <json>]`, que grava `gateDecisions[gate] = { pause, reason, signals, trust, decidedAt }` com timestamp server-side (shape canônico em `framework/schemas/feature.schema.json`). **Nunca edite `gateDecisions` à mão:** o Edit manual de feature.json colide com o hook state-sync, que reescreve o arquivo entre o Read e o Edit ("file modified since read"). Se a ação observada divergir do registro (pausou um gate auto-aprovável, ou auto-aprovou um gate que exigia pausa), o guard injeta um aviso no contexto — a LLM corrige. É um guardrail que nunca bloqueia: a cada conferência ele registra uma linha no activity log (`.morph/logs/activity.json`) com o resultado — `coherent` ou `divergent` — e só injeta aviso quando diverge; sem registro ou erro → silêncio.
|
|
238
|
+
**O hook gate-guard.js** confere, sem bloquear, se a ação tomada num gate (pausar vs auto-aprovar) bateu com a decisão persistida. **Default:** `gate-check <feature> <gate> [--signals <json>] [--json]` decide via `shouldPauseGate`; `--signals` sobrescreve só o que o disco não expõe sozinho (`designSystemDivergence`, `standardsViolations`, `evalScore`). **Escape manual** (sinal que `shouldPauseGate` nem representa, ex.: modo de descoberta): `gate-decision <feature> <gate> --pause <bool> [--reason <txt>] [--signals <json>]`. Ambos gravam `gateDecisions[gate] = { pause, reason, signals, trust, decidedAt }` server-side (shape em `framework/schemas/feature.schema.json`). **Nunca edite `gateDecisions` à mão** — colide com state-sync. Divergência → o guard injeta aviso no contexto; cada conferência registra `coherent`/`divergent` em `.morph/logs/activity.json` — nunca bloqueia.
|
|
264
239
|
|
|
265
240
|
---
|
|
266
241
|
|
|
267
242
|
## 6. Sub-agents
|
|
268
243
|
|
|
269
|
-
A thread principal é o **Orchestrator**. Trabalho
|
|
244
|
+
A thread principal é o **Orchestrator**. Trabalho pesado ou fora do domínio corrente **deve** ser delegado a um sub-agent com persona e standard escopados — é o modo padrão de operação, não uma exceção. Implementar tudo inline porque "eu já sei o padrão" contamina o contexto principal e desperdiça o sistema de personas.
|
|
270
245
|
|
|
271
246
|
**Despache um sub-agent por padrão quando a tarefa atende a pelo menos um destes gatilhos:**
|
|
272
247
|
|
|
273
|
-
- **Domínio diferente do contexto corrente**
|
|
274
|
-
- **Esforço L ou XL** (
|
|
248
|
+
- **Domínio diferente do contexto corrente** (ver `agents.json → domains`) — ex: backend agora, próxima task é frontend/UI/dados. Gatilho mais importante: cada domínio tem sua persona e standards, e o sub-agent escopado os carrega sem inchar seu contexto.
|
|
249
|
+
- **Esforço L ou XL** (> 5 minutos).
|
|
275
250
|
- Mais de 3 tentativas de correção falharam no mesmo problema.
|
|
276
251
|
- Análise de arquivo com mais de 500 linhas.
|
|
277
252
|
- Tarefa repetitiva com mais de 3 instâncias do mesmo padrão.
|
|
278
|
-
- Risco de "contaminar" o contexto principal com detalhes de baixo nível irrelevantes
|
|
253
|
+
- Risco de "contaminar" o contexto principal com detalhes de baixo nível irrelevantes.
|
|
279
254
|
|
|
280
|
-
Inline (sem dispatch) é aceitável para tasks curtas (
|
|
255
|
+
Inline (sem dispatch) é aceitável para tasks curtas (S/M) **dentro do domínio já carregado em contexto**. Inline numa task que dispara um gatilho acima → **registre a justificativa em uma linha no decisions.md** — inline silencioso numa task pesada/multi-domínio é o anti-padrão.
|
|
281
256
|
|
|
282
|
-
**Mecanismo de dispatch:**
|
|
257
|
+
**Mecanismo de dispatch:** agents de domínio são subagents **registrados** (`.claude/agents/morph-{id}.md`, gerados de `agents.json` na instalação). Despache com `subagent_type: "morph-{id}"` (ex.: `morph-dotnet-senior`) — persona é o **system prompt**, tools/model/MCPs por domínio em `agents.json` (ex.: `context7` nos implementadores; Stitch/Gemini/Playwright no `morph-ui-designer`; `morph-evaluator` é read-only). **Fallback** (tipo não registrado): `general-purpose` com `persona` colado no prompt, **registrado nas `notes` da task**. O `**Persona:**` do recap registra sempre o mecanismo real — nunca auto-declaração.
|
|
283
258
|
|
|
284
|
-
**Persona de estágio — scout:**
|
|
259
|
+
**Persona de estágio — scout:** `morph-scout` (read-only: Read/Glob/Grep/Bash somente-leitura). Despache para um mapa do território sem contaminar a thread principal — obrigatório no início de um hotfix (root cause + blast radius), opcional antes do plan de uma feature grande. Devolve um mapa curto como relatório final; não escreve código.
|
|
285
260
|
|
|
286
|
-
**
|
|
287
|
-
- Especificação da tarefa (do tasks.json)
|
|
288
|
-
- Path do standard relevante (apenas um)
|
|
289
|
-
- Lista de arquivos que ele precisa ler ou modificar
|
|
290
|
-
- Critério de done claro e verificável
|
|
261
|
+
**Passe ao sub-agent:** especificação da tarefa (tasks.json), path do standard relevante (só um), arquivos a ler/modificar, critério de done claro e verificável.
|
|
291
262
|
|
|
292
|
-
**
|
|
293
|
-
- Histórico da conversa principal
|
|
294
|
-
- Contexto de outras tarefas não relacionadas
|
|
295
|
-
- Outputs de ferramentas não pertinentes à tarefa
|
|
263
|
+
**NÃO passe:** histórico da conversa principal, contexto de outras tarefas não relacionadas, outputs de ferramentas não pertinentes.
|
|
296
264
|
|
|
297
|
-
**O ARQUIVO é o retorno, a última mensagem é cortesia.** Em uso real
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
texto **pode não chegar** inteira ao orquestrador; por isso ela deixou de ser o canal
|
|
302
|
-
autoritativo. O sub-agent **sempre** grava o relatório também em um arquivo canônico:
|
|
265
|
+
**O ARQUIVO é o retorno, a última mensagem é cortesia.** Em uso real, o evento recebido de volta do
|
|
266
|
+
sub-agent às vezes é só um `idle_notification` sem texto — a última mensagem **pode não chegar**
|
|
267
|
+
inteira ao orquestrador, por isso ela deixou de ser o canal autoritativo. O sub-agent **sempre**
|
|
268
|
+
grava o relatório também em um arquivo canônico:
|
|
303
269
|
|
|
304
|
-
- Task de implementação: `.morph/features/{feature}/3-implement/reports/{taskId}.md` (um arquivo
|
|
305
|
-
|
|
306
|
-
- Avaliador do Gate 3 (`morph-evaluator`): `.morph/features/{feature}/4-review/evaluator-report.md`
|
|
307
|
-
— o relatório BRUTO do avaliador; a `morph-review` o lê e sintetiza o `review-report.md`
|
|
308
|
-
apresentado no Gate 3 (os dois nunca colidem: um é saída crua do sub-agent, o outro é a curadoria
|
|
309
|
-
do orquestrador).
|
|
270
|
+
- Task de implementação: `.morph/features/{feature}/3-implement/reports/{taskId}.md` (um arquivo por task concluída, mesmo quando uma sessão de sub-agent cobre várias tasks de um fluxo).
|
|
271
|
+
- Avaliador do Gate 3 (`morph-evaluator`): `.morph/features/{feature}/4-review/evaluator-report.md` — relatório BRUTO; a `morph-review` o lê e sintetiza o `review-report.md` do Gate 3 (nunca colidem: um é saída crua do sub-agent, o outro é curadoria do orquestrador).
|
|
310
272
|
|
|
311
|
-
O orquestrador **lê o arquivo** ao retomar controle após o dispatch — nunca confia
|
|
312
|
-
|
|
313
|
-
leitura); se não chegou, o arquivo já está lá.
|
|
273
|
+
O orquestrador **lê o arquivo** ao retomar controle após o dispatch — nunca confia só na mensagem
|
|
274
|
+
de retorno da tool (que, se chegou inteira, só economiza a leitura).
|
|
314
275
|
|
|
315
276
|
### Protocolo de ausência de relatório
|
|
316
277
|
|
|
317
278
|
**"Relatório ausente = o agente falhou" é a leitura errada.** O sub-agent pode ter feito todo o
|
|
318
|
-
trabalho e perdido o meio de gravá-lo
|
|
319
|
-
|
|
279
|
+
trabalho e perdido o meio de gravá-lo (ex.: o worktree sumiu debaixo dele em execução). Tratar isso
|
|
280
|
+
como falha joga fora trabalho real.
|
|
320
281
|
|
|
321
|
-
A pergunta que decide não é "o relatório chegou?", é **"o TRABALHO entrou?"** —
|
|
322
|
-
|
|
282
|
+
A pergunta que decide não é "o relatório chegou?", é **"o TRABALHO entrou?"** — respondida por
|
|
283
|
+
evidência, não pela palavra do agente:
|
|
323
284
|
|
|
324
285
|
```
|
|
325
286
|
morph-spec report-check <feature> [task] --json
|
|
@@ -337,29 +298,26 @@ Sai 0 só em `ok`. Em qualquer caminho degradado a degradação é **registrada*
|
|
|
337
298
|
`notes` da task —, nunca aceita em silêncio. Segunda ausência sem trabalho entregue é falha real:
|
|
338
299
|
escale ao humano.
|
|
339
300
|
|
|
340
|
-
**O que receber de volta (no arquivo, e na mensagem final quando ela chega)
|
|
301
|
+
**O que receber de volta** (no arquivo, e na mensagem final quando ela chega) — os **4 itens obrigatórios** de todo relatório de dispatch:
|
|
341
302
|
- O que foi feito (2-3 frases)
|
|
342
303
|
- Arquivos modificados (lista)
|
|
343
304
|
- Problemas encontrados e como foram resolvidos
|
|
344
305
|
- Auto-score 0-10 com justificativa em uma linha
|
|
345
306
|
|
|
346
307
|
**Contrato do relatório final** (cláusulas que todo prompt de dispatch inclui — ver templates em `morph-implement` §4 e `morph-apply` §3b):
|
|
347
|
-
1. **GRAVE o relatório no arquivo canônico
|
|
348
|
-
2. Não tocar em `tasks.json`, `feature.json`, `state.json` nem no board de sessão
|
|
349
|
-
3. **Verificação
|
|
308
|
+
1. **GRAVE o relatório no arquivo canônico ANTES de encerrar**, com os 4 itens acima — é o retorno autoritativo, não a sua última mensagem (cortesia best-effort, pode não chegar inteira). Ausente/oco/incompleto é **falha de protocolo** — registrada no recap. **Não chame `SendMessage`**: gera um evento a mais além da notificação de término.
|
|
309
|
+
2. Não tocar em `tasks.json`, `feature.json`, `state.json` nem no board de sessão — todo estado é do orquestrador.
|
|
310
|
+
3. **Verificação condicional ao isolamento:** **sem isolamento** → não rode build/test compartilhado, verificação é do orquestrador pós-batch. **Com `isolation: "worktree"`** (`dag` recomenda por colisão de `outputs`) → build/test **dentro do worktree**, commite na branch como último ato, reporte a branch, **nunca** faça merge.
|
|
350
311
|
|
|
351
|
-
|
|
312
|
+
Sub-agent deve ser autossuficiente com o que você passou — se precisar de mais contexto, a tarefa não estava bem especificada; refine antes de despachar.
|
|
352
313
|
|
|
353
|
-
**Quando NÃO despachar
|
|
354
|
-
- Tarefas curtas onde o overhead de contexto do dispatch custa mais do que a economia de contexto principal.
|
|
355
|
-
- Quando o feedback do sub-agent precisaria ser discutido em tempo real — dispatch é assíncrono.
|
|
356
|
-
- Quando a tarefa envolve mudanças de arquitetura que o Orchestrator precisa validar antes de executar.
|
|
314
|
+
**Quando NÃO despachar:** tarefas curtas onde o overhead do dispatch custa mais que a economia de contexto principal; quando o feedback precisaria ser discutido em tempo real (dispatch é assíncrono); quando a task envolve mudança de arquitetura que o Orchestrator precisa validar antes de executar.
|
|
357
315
|
|
|
358
|
-
**Após receber o retorno do sub-agent:** leia o auto-score — ele é **triagem, não aprovação**. Se for < 7, re-despache com o feedback específico (ou corrija inline) antes de avaliar.
|
|
316
|
+
**Após receber o retorno do sub-agent:** leia o auto-score — ele é **triagem, não aprovação**. Se for < 7, re-despache com o feedback específico (ou corrija inline) antes de avaliar. A task só avança quando `morph-eval` der score ≥ 9 (barra única do §0); integre ao recap.md e siga para a próxima tarefa.
|
|
359
317
|
|
|
360
|
-
> **Anti-padrão
|
|
318
|
+
> **Anti-padrão:** implementar múltiplas tasks de domínios diferentes inline em sequência ("eu já sei o padrão de cada uma") é o sinal de que a delegação foi ignorada. Feature cruzando ≥2 domínios → o default é despachar especialistas, não o Orchestrator virar faz-tudo.
|
|
361
319
|
|
|
362
|
-
**Dispatch em paralelo (multi-agent):**
|
|
320
|
+
**Dispatch em paralelo (multi-agent):** fluxos **genuinamente independentes** (ex: backend ‖ frontend, convergindo só no fim) → despache múltiplos sub-agents **ao mesmo tempo**, um por fluxo, em vez de série. `morph-spec dag {feature}` analisa o DAG (`dependencies`/`group`), **pondera o esforço** (raízes/fluxos só de tasks S não ganham dispatch próprio) e imprime a decisão; regras e cap de agentes simultâneos em `morph-apply` ("Análise de DAG"). Colisão de `outputs` entre fluxos → `dag` recomenda `isolation: "worktree"`, cada agente num worktree próprio, orquestrador integra por merge (`morph-apply` §3b-w). Sem colisão: working tree compartilhada, verificação única pós-batch.
|
|
363
321
|
|
|
364
322
|
O padrão de dispatch e o template de prompt para sub-agents estão detalhados em `framework/skills/core/morph-implement/SKILL.md`.
|
|
365
323
|
|
|
@@ -370,36 +328,30 @@ O padrão de dispatch e o template de prompt para sub-agents estão detalhados e
|
|
|
370
328
|
Skills são documentos de instrução que você invoca sob demanda. Eles ficam em `framework/skills/core/`.
|
|
371
329
|
Não invoque uma skill fora do momento indicado.
|
|
372
330
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
|
376
|
-
|
|
377
|
-
| morph-
|
|
378
|
-
| morph-
|
|
379
|
-
| morph-
|
|
380
|
-
| morph-
|
|
381
|
-
| morph-
|
|
382
|
-
| morph-
|
|
383
|
-
| morph-
|
|
384
|
-
| morph-
|
|
331
|
+
Path de cada skill: `framework/skills/core/{nome}/SKILL.md`.
|
|
332
|
+
|
|
333
|
+
| Skill | Quando invocar |
|
|
334
|
+
|-----------------------|---------------------------------------------------------------------------|
|
|
335
|
+
| **morph-proposal** | **Orquestrador**: brainstorming → Gate 1 → plan → Gate 2 (entry point) |
|
|
336
|
+
| **morph-apply** | **Orquestrador**: DAG-adaptive implement loop → review → Gate 3 |
|
|
337
|
+
| morph-brainstorming | Invocada pela morph-proposal — entendimento de negócio + stack-scan |
|
|
338
|
+
| morph-stack-scan | Detecta stack atual; curto-circuita em greenfield |
|
|
339
|
+
| morph-plan | Invocada pela morph-proposal — produz spec/mandate/tasks.json |
|
|
340
|
+
| morph-implement | Invocada pela morph-apply — executa cada task |
|
|
341
|
+
| morph-eval | Após concluir uma task ou fase |
|
|
342
|
+
| morph-review | Invocada pela morph-apply — produz review-report + Gate 3 |
|
|
343
|
+
| morph-hotfix | **Orquestrador**: ADW cirúrgico de hotfix (scout → fix → gate humano → ship) |
|
|
344
|
+
| morph-standards | Quando precisar localizar ou aplicar um standard específico |
|
|
385
345
|
|
|
386
346
|
**Entry points** para o usuário:
|
|
387
347
|
- `/morph-proposal {feature}` → invoca `Skill(morph-proposal)`, que orquestra brainstorming + plan
|
|
388
348
|
- `/morph-apply {feature}` → invoca `Skill(morph-apply)`, que orquestra implement + review
|
|
389
349
|
- `/morph-hotfix {feature}` → invoca `Skill(morph-hotfix)`, o pipeline cirúrgico de correção em produção
|
|
390
350
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
Cada skill contém instruções de execução passo a passo. Leia, siga, não desvie sem justificativa registrada no recap.md.
|
|
351
|
+
Slash commands são atalhos: o agente pode chamar `Skill(morph-proposal)` diretamente quando o usuário pede "use /morph-proposal".
|
|
394
352
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
Nenhuma skill deve ser invocada proativamente por um hook ou script automático. Skills são instrumentos do modelo — você decide quando a situação pede o nível de rigor que a skill fornece.
|
|
353
|
+
Cada skill contém instruções passo a passo. Leia, siga, não desvie sem justificativa no recap.md. Apenas `framework/skills/core/` é instalado. Nenhuma skill deve ser invocada proativamente por um hook ou script — skills são instrumentos do modelo, você decide quando a situação pede o rigor que a skill fornece.
|
|
398
354
|
|
|
399
355
|
---
|
|
400
356
|
|
|
401
|
-
> **Nota de autoria:**
|
|
402
|
-
> Alterações de comportamento do harness exigem atualização aqui, não em hooks ou scripts.
|
|
403
|
-
> Versão inicial criada em 2026-04-24. Próxima revisão recomendada após o ciclo completo com NLH.
|
|
404
|
-
>
|
|
405
|
-
> Para histórico de decisões sobre este documento, consulte os commits do arquivo.
|
|
357
|
+
> **Nota de autoria:** este documento é mantido pelo time de engenharia. Alterações de comportamento do harness são feitas aqui, não em hooks ou scripts. Histórico de decisões: commits do arquivo.
|