@polymorphism-tech/morph-spec 8.37.1 → 8.38.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/CLAUDE.md +19 -6
- package/README.md +2 -2
- package/bin/morph-spec.js +16 -7
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/CLAUDE.md +3 -3
- package/framework/MORPH.md +25 -22
- package/framework/agents.json +76 -27
- package/framework/docs/CLI.md +54 -17
- package/framework/evals/rubrics/code-quality.md +5 -0
- package/framework/evals/rubrics/condensed.md +6 -2
- package/framework/evals/rubrics/contracts.md +20 -0
- package/framework/evals/rubrics/test-coverage.md +17 -6
- package/framework/hooks/README.md +9 -3
- package/framework/hooks/claude-code/core/graph-refresh-kick.js +52 -0
- package/framework/hooks/claude-code/core/telemetry-log.js +172 -87
- package/framework/hooks/claude-code/core/validate-completion.js +16 -90
- package/framework/hooks/claude-code/core/worktree-context.js +10 -0
- package/framework/hooks/shared/command-tokens.js +96 -0
- package/framework/hooks/shared/git-exclude.js +44 -0
- package/framework/hooks/shared/git-paths.js +52 -0
- package/framework/hooks/shared/graph-freshness.js +380 -0
- package/framework/hooks/shared/graph-refresh.js +416 -0
- package/framework/hooks/shared/morph-cli.js +17 -5
- package/framework/hooks/shared/redact-secrets.js +55 -0
- package/framework/hooks/shared/telemetry-logger.js +25 -2
- package/framework/hooks/shared/transcript-usage.js +80 -0
- package/framework/rubrics/backend.json +2 -2
- package/framework/rubrics/default.json +2 -2
- package/framework/rubrics/frontend.json +2 -2
- package/framework/rules/csharp-standards.md +1 -0
- package/framework/rules/morph-workflow.md +1 -0
- package/framework/rules/nextjs-standards.md +1 -0
- package/framework/schemas/config.schema.json +41 -1
- package/framework/schemas/feature.schema.json +5 -1
- package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
- package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +1 -1
- package/framework/skills/core/morph-apply/SKILL.md +36 -11
- package/framework/skills/core/morph-brainstorming/SKILL.md +16 -7
- package/framework/skills/core/morph-eval/SKILL.md +1 -1
- package/framework/skills/core/morph-hotfix/SKILL.md +1 -1
- package/framework/skills/core/morph-implement/SKILL.md +39 -10
- package/framework/skills/core/morph-media/SKILL.md +1 -1
- package/framework/skills/core/morph-plan/SKILL.md +72 -15
- package/framework/skills/core/morph-proposal/SKILL.md +1 -1
- package/framework/skills/core/morph-review/SKILL.md +51 -13
- package/framework/skills/core/morph-stack-scan/SKILL.md +1 -1
- package/framework/skills/core/morph-standards/SKILL.md +1 -1
- package/framework/skills/core/morph-uiux/SKILL.md +34 -9
- package/framework/standards/STANDARDS.json +187 -12
- package/framework/standards/ai-agents/testing-ai.md +2 -1
- package/framework/standards/architecture/code-comments.md +64 -0
- package/framework/standards/backend/dotnet/testing.md +22 -0
- package/framework/standards/frontend/admin-app/data-table.md +562 -0
- package/framework/standards/frontend/admin-app/feedback.md +236 -0
- package/framework/standards/frontend/admin-app/forms.md +232 -0
- package/framework/standards/frontend/admin-app/page-structure.md +203 -0
- package/framework/standards/frontend/nextjs/components.md +37 -58
- package/framework/standards/frontend/nextjs/data-fetching.md +1 -0
- package/framework/standards/frontend/nextjs/forms.md +31 -30
- package/framework/standards/frontend/nextjs/state-management.md +2 -1
- package/framework/standards/frontend/nextjs/testing.md +18 -0
- package/framework/templates/context/design-system.md +3 -3
- package/framework/templates/docs/proposal.md +11 -0
- package/framework/templates/docs/spec.md +15 -0
- package/framework/templates/docs/ui-mockups.md +115 -98
- package/framework/templates/feature/decisions.md +124 -122
- package/package.json +1 -1
- package/src/commands/graph/affected.js +4 -3
- package/src/commands/graph/build.js +109 -18
- package/src/commands/graph/explain.js +8 -5
- package/src/commands/graph/status.js +14 -8
- package/src/commands/observability/cost.js +148 -18
- package/src/commands/project/doctor.js +82 -10
- package/src/commands/project/update.js +25 -0
- package/src/commands/project/worktree.js +73 -90
- package/src/commands/state/advance.js +18 -0
- package/src/commands/state/approve.js +15 -0
- package/src/commands/state/archive.js +62 -9
- package/src/commands/state/finish.js +62 -14
- package/src/commands/state/gate-check.js +8 -1
- package/src/commands/state/gate-decision.js +8 -4
- package/src/commands/state/report-check.js +90 -9
- package/src/commands/state/usecase.js +66 -0
- package/src/commands/tasks/dag.js +17 -2
- package/src/commands/validation/validate-feature.js +6 -1
- package/src/commands/validation/verify.js +20 -1
- package/src/dashboard/scanner/agents-scanner.js +5 -1
- package/src/dashboard/scanner/hooks-scanner.js +8 -1
- package/src/dashboard/scanner/standards-scanner.js +2 -1
- package/src/lib/ai/comment-stripper.js +101 -4
- package/src/lib/evaluator-report.js +25 -0
- package/src/lib/generators/handoff-generator.js +4 -18
- package/src/lib/git/default-branch.js +52 -0
- package/src/lib/git/tree-fingerprint.js +58 -0
- package/src/lib/git/tree-state.js +167 -0
- package/src/lib/graph/god-nodes.js +12 -3
- package/src/lib/graph/graph-health.js +48 -2
- package/src/lib/graph/graph-loader.js +99 -25
- package/src/lib/graph/graphifyignore.js +145 -28
- package/src/lib/graph/sanitize.js +117 -11
- package/src/lib/risk-detector.js +90 -0
- package/src/lib/specs/acervo-format.js +70 -0
- package/src/lib/specs/acervo-lifecycle.js +264 -0
- package/src/lib/specs/adr-index.js +169 -0
- package/src/lib/specs/revocations.js +156 -0
- package/src/lib/specs/screen-checklist.js +357 -0
- package/src/lib/specs/usecase-check.js +20 -16
- package/src/lib/specs/usecase-promoter.js +103 -38
- package/src/lib/specs/usecase-registry.js +7 -7
- package/src/lib/tasks/tasks-json-parser.js +2 -3
- package/src/lib/telemetry/metrics.js +386 -0
- package/src/lib/telemetry/telemetry-reader.js +161 -51
- package/src/lib/telemetry/verify-event.js +79 -0
- package/src/lib/validators/code-budget/code-budget-validator.js +172 -0
- package/src/lib/validators/code-budget/comment-scanner.js +75 -0
- package/src/lib/validators/code-budget/index.js +9 -0
- package/src/lib/validators/reuse/reuse-validator.js +4 -2
- package/src/lib/validators/reuse/symbol-scanner.js +27 -22
- package/src/lib/validators/validation-runner.js +21 -5
- package/src/lib/validators/verify-runner.js +11 -0
- package/src/lib/worktree/finish-backup.js +739 -0
- package/src/lib/worktree/ignored-triage.js +15 -8
- package/src/lib/worktree/worktree-audit.js +5 -0
- package/src/scripts/setup-infra.js +29 -18
- package/src/utils/agents-installer.js +281 -12
- package/src/utils/hooks-installer.js +75 -15
|
@@ -4,7 +4,7 @@ description: Guia a produção dos artefatos de planejamento de uma feature (use
|
|
|
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.38.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-plan
|
|
@@ -46,26 +46,42 @@ Ao iniciar a fase plan — após o `proposal.md` ser aprovado e antes de qualque
|
|
|
46
46
|
1c. **Mapa de reuso — o que desta feature JÁ EXISTE no codebase.** Antes de destilar os use cases, responda por conceito: *isto já está implementado?* É o passo que falta hoje e cujo efeito é medido — 17 duplicações intra-feature no ProspectPRO, `SimpleBuilding` redefinido em cinco arquivos da MESMA pasta, um deles já sem um campo. Sem este passo, quem implementa não tem como saber, e o framework nunca pergunta.
|
|
47
47
|
|
|
48
48
|
**Insumos, nesta ordem:**
|
|
49
|
-
|
|
49
|
+
0. **O estado do grafo** — `morph-spec graph status --json`. Stale com `refresh.running: true`: espere o refresh terminar (ele roda em background, só na raiz) ou trate cada "não existe" como possivelmente velho; stale sem refresh em andamento — e sempre numa worktree (`refresh.auto: false`), cujo grafo é o semeado da raiz e não anda sozinho: `morph-spec graph refresh`. O resultado vai para a linha de método do mapa.
|
|
50
|
+
1. **O grafo** — para cada conceito central (entidade, DTO, componente, hook, serviço, helper — e o dublê ou a fixture de teste, que também estão no grafo, com `test: true`) que a feature vai introduzir: `morph-spec graph explain <nome-candidato> --json` (existe? onde?) e `morph-spec graph affected <conceito> --uses-only --json` (quem usa de verdade, sem contar quem só implementa). **O mapa nasce dessa saída**, não de memória nem de grep por conta própria.
|
|
50
51
|
2. **O inventário do projeto** — `.morph/context/README.md` (gerado por `morph-spec context refresh`): entidades, endpoints com método e rota, páginas e **componentes com path**. É a granularidade de *conceito* que o grafo, que casa por símbolo, não dá. **Este passo é o consumidor declarado desse arquivo** — se ele não existir, rode `morph-spec context refresh` ou siga sem ele.
|
|
51
|
-
3. **Sem grafo** (`no-graph`, projeto sem Python) — **caia para `grep -rn "<nome-candidato>"` no diretório de código e siga**; a ausência de grafo nunca bloqueia o plano (ADR-002). Registre a queda no `decisions.md`.
|
|
52
|
+
3. **Sem grafo** (`no-graph`, projeto sem Python), ou o grafo não respondeu (`not-found` num grafo stale, `ambiguous` sem opção que sirva) — **caia para `grep -rn "<nome-candidato>"` no diretório de código e siga**; a ausência de grafo nunca bloqueia o plano (ADR-002). Registre a queda no `decisions.md`.
|
|
52
53
|
|
|
53
|
-
**Produza `.morph/features/{feature}/2-plan/reuse-map.md`** — artefato, não prosa solta
|
|
54
|
+
**Produza `.morph/features/{feature}/2-plan/reuse-map.md`** — artefato, não prosa solta, com a saída do grafo **citada**:
|
|
54
55
|
|
|
55
56
|
```markdown
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
|
59
|
-
|
|
60
|
-
|
|
|
57
|
+
Método: `morph-spec graph status --json` → fresh, built_at_commit 1a2b3c4d = HEAD
|
|
58
|
+
|
|
59
|
+
| Conceito | Já existe? | Onde | Fonte | Decisão |
|
|
60
|
+
|---|---|---|---|---|
|
|
61
|
+
| SimpleBuilding | SIM (5×) | features/roulette/types/roulette.types.ts:L12 | `graph explain SimpleBuilding` → ambiguous, 5 opções | REUSAR |
|
|
62
|
+
| FilterValues | SIM (ambíguo) | dashboard + leads + store | `graph affected FilterValues --uses-only` → 7 consumidores | ESTENDER o de dashboard |
|
|
63
|
+
| RouletteScore | NÃO | — | `graph explain RouletteScore` → not-found; `grep -rn RouletteScore` → 0 | CRIAR — nenhum tipo cobre pontuação por sorteio |
|
|
61
64
|
```
|
|
62
65
|
|
|
66
|
+
**A coluna Fonte cita o comando e o que ele devolveu** (`ok` com `arquivo:linha`, `not-found`, `ambiguous` com as opções) — ou o `grep` da queda, com a contagem. Sem grafo, a linha de método diz isso (`sem grafo — grep`). Uma linha sem Fonte não vale, pela mesma razão que um CRIAR sem justificativa: quem lê o mapa no Gate 2 precisa saber se o "não existe" veio de uma consulta ou de uma suposição.
|
|
67
|
+
|
|
63
68
|
**`CRIAR` exige justificativa em uma linha, na própria célula** — a mesma forma que `morph-uiux` §"Consistência" já impõe para token de design (*"um token novo precisa de justificativa: o existente não cobre o caso"*). Sem a justificativa, o veredito não vale.
|
|
64
69
|
|
|
65
70
|
**Distinga "extrair para shared" de "importar de outra feature".** Reuso não é desculpa para acoplar slices: se o conceito é de duas features, o alvo é um módulo comum, não um import cruzado — a rubrica `architecture` penaliza dependência cross-feature e continua valendo.
|
|
66
71
|
|
|
67
72
|
O veredito viaja para o implementador pelo campo `reuse` de cada task (passo 5). Quem cobra o resultado é o `morph-spec verify`: o validador `reuse` acusa símbolo novo cujo nome já existe no grafo, na mesma linguagem — **intra-feature reprova**, cross-feature avisa, e um `CRIAR` declarado no plano rebaixa o achado a aviso.
|
|
68
73
|
|
|
74
|
+
1d. **O que esta feature supera no acervo.** Insumos: a seção `Conflitos com o acervo` do `proposal.md`, o acervo `.morph/specs/usecases/` e o índice de ADRs ativos `.morph/specs/adrs/` (um arquivo por ADR). UC com `status: superseded` não é o comportamento vigente — o `superseded_by` é, e `scope` diz onde o antigo ainda vale; decisão vigente é a do índice, e os `decisions.md` arquivados são história, não instrução.
|
|
75
|
+
|
|
76
|
+
Cada conflito com UC ou ADR decidido pelo pedido novo vira duas coisas: uma linha na seção de revogação do `spec.md` (passo 3) e um ADR no `decisions.md` (conflito com `.morph/context/*.md` vira a reescrita do corpo daquele documento no encerramento — `morph-apply` §6). ADR cuja regra vale **além desta feature** leva `**Alcance:** projeto` — é por essa linha que o `finish` o copia para o índice (o resto fica só no `decisions.md` da feature):
|
|
77
|
+
|
|
78
|
+
```markdown
|
|
79
|
+
## ADR-{nnn}: {a regra que vale no projeto}
|
|
80
|
+
|
|
81
|
+
**Status:** Accepted
|
|
82
|
+
**Alcance:** projeto
|
|
83
|
+
```
|
|
84
|
+
|
|
69
85
|
2. **Destile os use cases — ANTES de escrever `spec.md` e `tasks.json`.**
|
|
70
86
|
|
|
71
87
|
Um arquivo por use case em `.morph/features/{feature}/2-plan/usecases/UC-{nn}-{slug}.md`:
|
|
@@ -130,11 +146,11 @@ Ao iniciar a fase plan — após o `proposal.md` ser aprovado e antes de qualque
|
|
|
130
146
|
| Tipo | Use case |
|
|
131
147
|
|---|---|
|
|
132
148
|
| `feature` | Obrigatório quando há comportamento observável. Feature puramente técnica (refactor, infra, migração) dispensa — **registre a dispensa em `decisions.md`**. |
|
|
133
|
-
| `bug` | Não cria novo, não reserva número novo: **copie** o `UC-{nn}-*.md` do acervo para `2-plan/usecases/` **mantendo o nome do arquivo publicado** (mesmo slug) e **corrija ou adicione a pós-condição** lá — o bug é a pós-condição que faltava, não a identidade do UC. É esse mesmo nome, inalterado, que faz o `finish` reconhecer a correção como o MESMO UC (abaixo) em vez de uma colisão. |
|
|
149
|
+
| `bug` | Não cria novo, não reserva número novo: **copie** o `UC-{nn}-*.md` do acervo para `2-plan/usecases/` **mantendo o nome do arquivo publicado** (mesmo slug) e **corrija ou adicione a pós-condição** lá — o bug é a pós-condição que faltava, não a identidade do UC. É esse mesmo nome, inalterado, que faz o `finish` reconhecer a correção como o MESMO UC (abaixo) em vez de uma colisão. UC `superseded` com `scope`: a correção vale só para a parte que ainda vale, e a cópia leva `status`/`superseded_by`/`scope` como estão — a promoção os preserva. |
|
|
134
150
|
| `chore` | Nenhum (já pula a fase plan por política). |
|
|
135
151
|
| `hotfix` | Não bloqueia. Referencia se existir; o pós-mortem pode virar pós-condição numa feature posterior. |
|
|
136
152
|
|
|
137
|
-
**Nunca edite `.morph/specs/usecases/` à mão.** A única via de escrita no acervo é a promoção do `finish`, que lê **só** de `2-plan/usecases/`: é ela que carimba `status: implemented`, sobrescreve por ID (mesmo com slug novo) e leva o arquivo no commit de arquivamento. Editar o acervo direto pula os três e cria uma segunda verdade fora do mecanismo. Mudar um UC existente = copiar para o `2-plan/usecases/` da feature, corrigir lá, e deixar o `finish` sobrescrever.
|
|
153
|
+
**Nunca edite `.morph/specs/usecases/` à mão.** A única via de escrita no acervo é a promoção do `finish`, que lê **só** de `2-plan/usecases/`: é ela que carimba `status: implemented`, sobrescreve por ID (mesmo com slug novo) e leva o arquivo no commit de arquivamento. Editar o acervo direto pula os três e cria uma segunda verdade fora do mecanismo. Mudar um UC existente = copiar para o `2-plan/usecases/` da feature, corrigir lá, e deixar o `finish` sobrescrever. Aposentar um UC (todo ou em parte) também não é edição à mão: é a seção de revogação do `spec.md` (passo 3), que o `finish` aplica.
|
|
138
154
|
|
|
139
155
|
**Backstop de colisão na promoção.** Se, apesar da reserva, duas features chegarem à promoção com o MESMO `UC-{nn}` e slugs diferentes — registro de reserva aponta para uma feature diferente da que já está no acervo —, o `finish`/`archive` **recusa promover esse UC específico** (nunca recusa fechar a feature: fail-open, só aquele use case fica de fora) e imprime onde o arquivo ficou e como recuperar. Se acontecer: renumere com `usecase reserve` e promova manualmente, ou — se for mesmo o caso `bug` — confira se o slug bate com o publicado.
|
|
140
156
|
|
|
@@ -144,6 +160,18 @@ Ao iniciar a fase plan — após o `proposal.md` ser aprovado e antes de qualque
|
|
|
144
160
|
- Arquitetura da solução: quais componentes, como se conectam, fluxos de dados principais.
|
|
145
161
|
- Edge cases **técnicos** e como serão tratados (os de comportamento estão nos fluxos alternativos dos use cases).
|
|
146
162
|
- Integrações externas e contratos esperados.
|
|
163
|
+
- **UCs e ADRs que esta feature altera ou revoga** — seção obrigatória, com este título: `Nenhum.` quando nada muda; senão, a tabela (colunas posicionais — o cabeçalho é livre):
|
|
164
|
+
|
|
165
|
+
```markdown
|
|
166
|
+
## UCs e ADRs que esta feature altera ou revoga
|
|
167
|
+
|
|
168
|
+
| Id | Mudança | Substituto | Escopo em que o antigo ainda vale |
|
|
169
|
+
|---|---|---|---|
|
|
170
|
+
| UC-{nn} | parcial | UC-{nn} | {onde o antigo ainda vale} |
|
|
171
|
+
| {feature}/ADR-{nnn} | total | — | — |
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Troque os placeholders pelos ids reais (ex.: `UC-133` superado em parte por `UC-589`, ainda valendo na vitrine) — um placeholder esquecido não é id, e o `usecase check` o aponta. `Id` é `UC-{nn}` ou `{feature}/ADR-{nnn}` — o número de ADR recomeça em cada feature. UC revogado exige `Substituto` (`UC-{nn}`, que vira o `superseded_by`) que exista no acervo depois da promoção; `parcial` exige `Escopo`, e `total` não tem; id repetido em duas linhas não aplica nenhuma delas. No `finish`, dentro do commit de arquivamento, o UC ganha `status: superseded` + `superseded_by` (+ `scope`) e o ADR sai do índice (total) ou fica com o escopo (parcial); linha malformada, alvo fora do acervo ou substituto inexistente não é aplicada e volta em `revocationProblems`. **Rode `morph-spec usecase check {feature}` logo depois de escrever a seção**: o `spec.md` congela no Gate 2, e uma linha errada descoberta no `finish` já não tem conserto no plano.
|
|
147
175
|
|
|
148
176
|
O `spec.md` responde **como** os use cases do passo 2 serão realizados. Não repita o comportamento aqui.
|
|
149
177
|
|
|
@@ -188,6 +216,13 @@ Ao iniciar a fase plan — após o `proposal.md` ser aprovado e antes de qualque
|
|
|
188
216
|
`.morph/framework/CLI.md`, seção "Suítes de teste".
|
|
189
217
|
- **Quando não se aplica** (biblioteca pura, chore sem runtime), registre a dispensa e o porquê.
|
|
190
218
|
- Checklist de done com critérios verificáveis por tarefa.
|
|
219
|
+
- **Orçamento de teste e comentário — copie no mandate**, pelo mesmo motivo dos patterns
|
|
220
|
+
proibidos: o orçamento por task do passo 5 (um teste por pós-condição + um de regressão por
|
|
221
|
+
bug, justificativa acima disso, tabela antes de cópia, nenhum teste que só fixa texto);
|
|
222
|
+
fixture compartilhada antes de helper novo; TDD onde paga (bug: regressão primeiro; lógica
|
|
223
|
+
pura), teste depois aceito em UI e integração; comentário só com o porquê que o código não
|
|
224
|
+
mostra, nunca história de task/UC/ADR. Nos standards obrigatórios, liste
|
|
225
|
+
`architecture-code-comments` e o standard de teste do stack (seção *Test budget*).
|
|
191
226
|
- **Baseline é um COMANDO, nunca um número.** O mandate congela no Gate 2 e é lido por
|
|
192
227
|
implementadores durante dias — todo número cravado nele (`Suíte: 2366 passando`, cobertura,
|
|
193
228
|
contagem de arquivos) está errado a partir da primeira task, e um agente que confia nele
|
|
@@ -243,7 +278,7 @@ Ao iniciar a fase plan — após o `proposal.md` ser aprovado e antes de qualque
|
|
|
243
278
|
|
|
244
279
|
**5a. Carimbe `agent` e `standards` — uma leitura de `agents.json`, N tasks.** Antes de fechar o array `tasks`, **use a tool Read UMA VEZ** em `.morph/framework/agents.json` (não releia por task — é essa releitura repetida por task, hoje feita em `morph-implement`/`morph-apply` a cada dispatch, que este passo existe para eliminar). Para cada task do plano, resolva:
|
|
245
280
|
- `agent`: o `id` da persona (chave do objeto `agents`, sem prefixo `morph-`) cujo `domains` cobre o `group`/domínio da task — o mesmo casamento que `morph-implement` §3 e `morph-apply` §3b fariam manualmente a cada dispatch; aqui você faz uma vez, no plano.
|
|
246
|
-
- `standards`: o array `standards` dessa persona, mais qualquer standard adicional que a task especificamente exija (some, não substitua).
|
|
281
|
+
- `standards`: o array `standards` dessa persona, mais qualquer standard adicional que a task especificamente exija (some, não substitua). **Persona com `surfaces`** (a `ui-designer`): some também a lista da superfície da tela que a task entrega — a que o checklist de tela do `1-design/mockups.md` declara em `Superfície` —, nunca a de outra superfície; sem mockup, escolha pela tela e registre a escolha em `decisions.md`.
|
|
247
282
|
|
|
248
283
|
**5b. Carimbe `reuse` — do `reuse-map.md` para a task que realiza o conceito.** Para cada linha do mapa produzido no passo 1c, encontre a task que vai escrever aquele conceito e copie o veredito para `reuse` (`concept` + `verdict` + `target`). Um conceito sem task é sinal de plano incompleto — ou o mapa listou o que a feature não vai tocar, ou falta task. Resolva antes do Gate 2.
|
|
249
284
|
|
|
@@ -255,8 +290,21 @@ Ao iniciar a fase plan — após o `proposal.md` ser aprovado e antes de qualque
|
|
|
255
290
|
|
|
256
291
|
**`morph-spec dag {feature}` cobra o encanamento.** Ele lê os use cases junto com o `tasks.json` e reporta: referência a um `UC-{nn}` inexistente (**erro** — trava), pós-condição que nenhuma task cita (aviso) e task que referencia um UC mas parafraseou em vez de copiar (aviso). A comparação normaliza caixa e espaço, então prefixar o rótulo não quebra o casamento — mas a redação e os acentos precisam bater. E um quarto achado, léxico e também só aviso: `doneCriteria` com vocabulário de artefato (`grep`, "contém a string", "o binário", "nenhum arquivo", "arquivo/pasta/diretório em", glob `**/`) sem `Por que artefato:` (passo 2). O `dag` aponta o vocabulário; se a pós-condição é observável em teste continua sendo seu no Gate 2 e do evaluator.
|
|
257
292
|
|
|
293
|
+
**Ciclo de vida do acervo — também só aviso.** O `dag` (e o `morph-spec usecase check {feature}`, que roda sem `tasks.json`) aponta task cujo `usecase` está `superseded` — no acervo, na cópia da feature ou revogado pelo próprio `spec.md` —, frontmatter de supersessão malformado e linha de revogação que o `finish` não conseguiria aplicar. Task sobre UC superado em parte é legítima quando realiza a parte que ainda vale; senão, cite o substituto.
|
|
294
|
+
|
|
258
295
|
Cada pós-condição de cada use case deve estar coberta por **pelo menos uma** task. Antes de fechar o `tasks.json`, percorra os `UC-*.md` e confira: sobrou pós-condição sem task? Ou o plano está incompleto, ou a pós-condição não era necessária — resolva antes do Gate 2, não depois.
|
|
259
296
|
|
|
297
|
+
**Orçamento de teste por task.** Cada pós-condição que a task realiza compra **um** teste, e
|
|
298
|
+
cada bug corrigido compra **um** de regressão. Acima disso, a task justifica em uma linha da
|
|
299
|
+
`description` (é ela que chega ao sub-agente). O orçamento conta comportamentos, não cenários:
|
|
300
|
+
os cenários do mesmo comportamento são linhas de uma tabela (`[Theory]`/`it.each`), não N
|
|
301
|
+
testes. **Nenhum teste que só fixa texto** (copy de UI, config de tenant, prosa): a checagem
|
|
302
|
+
vira analyzer, lint ou validação no publish e fica fora da contagem da suíte. A regra de
|
|
303
|
+
critério sobre saída de LLM, abaixo, é o caso de prompt desta. A prova de mutação do Gate 3
|
|
304
|
+
continua no caminho crítico: mutante sobrevivente se mata apertando uma asserção ou somando uma
|
|
305
|
+
linha de tabela, nunca com um teste novo por mutante. O `morph-spec verify` avisa quando as
|
|
306
|
+
linhas de teste adicionadas passam de 1,5× as de produção (validador `code-budget`).
|
|
307
|
+
|
|
260
308
|
**Preencha `outputs` (paths planejados) em cada task** — o `morph-spec dag` usa os outputs para detectar colisão de arquivos entre fluxos paralelos e recomendar `isolation: "worktree"`. Task sem `outputs` entra como footprint desconhecido (não força isolamento, mas o dag não consegue protegê-la de colisão).
|
|
261
309
|
|
|
262
310
|
**Critério sobre saída de LLM vira eval de runtime — nunca "suíte estrutural".** Duas etapas,
|
|
@@ -288,6 +336,13 @@ Ao iniciar a fase plan — após o `proposal.md` ser aprovado e antes de qualque
|
|
|
288
336
|
viraram trabalho descoberto na fase implement, quando o escopo já estava aprovado no Gate 2.
|
|
289
337
|
Sem hits, ou sem `1-design/`, o passo é um no-op silencioso.
|
|
290
338
|
|
|
339
|
+
**5d. O checklist de tela vira critério.** Cada `## Tela:` do `1-design/mockups.md` traz o
|
|
340
|
+
`### Checklist de tela` (volume, paginação, ordenação, filtro, os três estados, mobile, abas).
|
|
341
|
+
A task que entrega a tela carrega essas decisões no `doneCriteria`, citando a seção do mockup
|
|
342
|
+
por path (`1-design/mockups.md#tela-…`) — "lista pagina no servidor, 25 por página" é critério;
|
|
343
|
+
"conforme o mockup" sozinho não é. É o que o implementador entrega e o que o avaliador confere
|
|
344
|
+
no Gate 3 (`morph-review` §4). Item marcado "não se aplica" não vira critério.
|
|
345
|
+
|
|
291
346
|
Antes de retornar, valide rodando `morph-spec dag {feature}` — o comando parseia e valida o schema do tasks.json (ids únicos `T\d+`, enums de `status`/`effort`, `dependencies` válidas) e já imprime a análise de DAG que a `/morph-apply` vai usar. Erros de schema abortam com a lista do que corrigir.
|
|
292
347
|
|
|
293
348
|
6. Apresente o Gate 2 segundo trust mode.
|
|
@@ -333,13 +388,13 @@ Ao iniciar a fase plan — após o `proposal.md` ser aprovado e antes de qualque
|
|
|
333
388
|
## Output esperado
|
|
334
389
|
|
|
335
390
|
- `.morph/features/{feature}/2-plan/usecases/UC-{nn}-{slug}.md` — um arquivo por use case, com pós-condições testáveis
|
|
336
|
-
- `.morph/features/{feature}/2-plan/spec.md` — especificação técnica completa
|
|
391
|
+
- `.morph/features/{feature}/2-plan/spec.md` — especificação técnica completa, com a seção `UCs e ADRs que esta feature altera ou revoga` (passo 3)
|
|
337
392
|
- `.morph/features/{feature}/2-plan/mandate.md` — contrato de implementação
|
|
338
393
|
- `.morph/features/{feature}/2-plan/reuse-map.md` — veredito REUSAR/ESTENDER/CRIAR por conceito, com justificativa de uma linha em cada CRIAR (passo 1c)
|
|
339
394
|
- `.morph/features/{feature}/2-plan/tasks.json` — task list estruturada válida contra schema, com o `doneCriteria` carregando a pós-condição literal e, por task, `agent`/`standards` carimbados a partir de `agents.json` (passo 5a) e, nas tasks de critério sobre saída de LLM, o path de `3-implement/evidencias/{taskId}.md` em `outputs` (passo 5)
|
|
340
395
|
- Gate 2 registrado aprovado em `.morph/features/{feature}/feature.json` (autoritativo)
|
|
341
396
|
|
|
342
|
-
Ao registrar a aprovação do Gate 2, atualize o frontmatter de cada use case de `status: draft` para `status: approved`. O ciclo fecha na integração: `morph-spec finish` promove os use cases para o acervo permanente `.morph/specs/usecases/` já com `status: implemented`. O status é **descritivo** — quem trava fase é o gate, não este campo.
|
|
397
|
+
Ao registrar a aprovação do Gate 2, atualize o frontmatter de cada use case de `status: draft` para `status: approved`. O ciclo fecha na integração: `morph-spec finish` promove os use cases para o acervo permanente `.morph/specs/usecases/` já com `status: implemented` — até que uma feature posterior o revogue (passo 3) e ele passe a `status: superseded`, com `superseded_by` e, se parcial, `scope`. O status é **descritivo** — quem trava fase é o gate, não este campo.
|
|
343
398
|
|
|
344
399
|
## Referências
|
|
345
400
|
|
|
@@ -349,7 +404,9 @@ Ao registrar a aprovação do Gate 2, atualize o frontmatter de cada use case de
|
|
|
349
404
|
- `.morph/framework/schemas/tasks.schema.json` — schema obrigatório de tasks.json
|
|
350
405
|
- `morph-spec graph explain|affected --uses-only` — "isto já existe?" e "quem usa de verdade" (passo 1c); **sem grafo, o fallback é `grep -rn`**
|
|
351
406
|
- `.morph/context/README.md` — inventário do projeto (entidades, endpoints, componentes com path); insumo declarado do passo 1c, atualizado por `morph-spec context refresh`
|
|
352
|
-
- `.morph/specs/usecases/` — acervo permanente de use cases do projeto (`usecase reserve` já lê antes de numerar; em `bug`, é onde mora o UC a corrigir)
|
|
407
|
+
- `.morph/specs/usecases/` — acervo permanente de use cases do projeto (`usecase reserve` já lê antes de numerar; em `bug`, é onde mora o UC a corrigir; `status: superseded` não é comportamento vigente)
|
|
408
|
+
- `.morph/specs/adrs/` — índice dos ADRs que valem no projeto, um arquivo por ADR, mantido pelo `finish` (passo 1d); os `decisions.md` arquivados são história
|
|
409
|
+
- `morph-spec usecase check {feature}` — o ciclo de vida do acervo contra esta feature (revogações do `spec.md`, task sobre UC `superseded`), antes do Gate 2
|
|
353
410
|
- `.morph/features/{feature}/1-design/` — artefatos da fase uiux, insumo do passo 1 e do cross-check do passo 5c (ausente não é erro)
|
|
354
411
|
- `.morph/features/{feature}/0-proposal/proposal.md` — escopo da feature
|
|
355
412
|
- `.morph/features/{feature}/0-proposal/stack-scan.md` — contexto técnico detectado
|
|
@@ -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.38.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.38.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-review
|
|
@@ -57,9 +57,13 @@ e o `recap.md` estar atualizado. Normalmente invocada pela skill orquestradora `
|
|
|
57
57
|
review-report a partir dele). Re-despachar aqui joga fora um veredito de Gate 3 já válido.
|
|
58
58
|
- **Se ausente, oco, ou sem scores por dimensão:** este é exatamente o caso de falha de protocolo
|
|
59
59
|
que este passo trata — prossiga com o dispatch abaixo.
|
|
60
|
+
- **Se `PARCIAL` na 1ª linha** (`evaluator.partial: true` no `report-check`): o avaliador anterior
|
|
61
|
+
parou no limite de turnos — não é ausente nem oco. Antes de um dispatch frio, siga o bullet
|
|
62
|
+
`PARCIAL` do "Leia primeiro" abaixo: continuar quem já provou metade custa menos que refazer a
|
|
63
|
+
rodada.
|
|
60
64
|
|
|
61
65
|
**Despache o avaliador independente** — o score do Gate 3 nunca é auto-atribuído por quem implementou:
|
|
62
|
-
- Rode `morph-spec verify {feature} --json` (escopo feature) e capture o JSON — é a saída real de build+testes+validadores+e2e que você anexa ao prompt do avaliador independente (`morph-evaluator`). **Sem `--filter`, sempre:** o `--filter` é do loop por task, onde o relógio de uma task não paga a suíte inteira; a prova que o avaliador lê tem de cobrir **todos** os nós de `nodes.tests.runs[]` (uma suíte filtrada aparece como `skip` nomeando o filtro — Gate 3 aberto sobre isso é verde sobre código não testado). Se a suíte inteira não couber numa chamada, rode-a em background; não a encolha com `--filter`. `verify {feature}` (sem task) **nunca recorta** — o recorte automático é só do escopo de task —, e um `verify {feature} --filter …` nem persiste o stamp (`persisted: false`, `reason: 'filtered'`) — o mesmo vale para `--skip-tests`/`--skip-build` no escopo de feature. Rode-o **depois** da última task: o `gate-check {feature} review` pausa quando o último stamp `verification` é de escopo `task:{id}`, porque aquela rodada cobriu só a task.
|
|
66
|
+
- Rode `morph-spec verify {feature} --json` (escopo feature) e capture o JSON — é a saída real de build+testes+validadores+e2e que você anexa ao prompt do avaliador independente (`morph-evaluator`). **Sem `--filter`, sempre:** o `--filter` é do loop por task, onde o relógio de uma task não paga a suíte inteira; a prova que o avaliador lê tem de cobrir **todos** os nós de `nodes.tests.runs[]` (uma suíte filtrada aparece como `skip` nomeando o filtro — Gate 3 aberto sobre isso é verde sobre código não testado). Se a suíte inteira não couber numa chamada, rode-a em background; não a encolha com `--filter`. `verify {feature}` (sem task) **nunca recorta** — o recorte automático é só do escopo de task —, e um `verify {feature} --filter …` nem persiste o stamp (`persisted: false`, `reason: 'filtered'`) — o mesmo vale para `--skip-tests`/`--skip-build` no escopo de feature. Rode-o **depois** da última task: o `gate-check {feature} review` pausa quando o último stamp `verification` é de escopo `task:{id}`, porque aquela rodada cobriu só a task. Uma rodada por árvore: se o JSON vier com `repeatOf`, nada mudou fora de `.morph/` desde o verify de feature anterior — use aquele resultado em vez de rodar de novo; depois de uma correção a árvore mudou, e a nova rodada é a prova.
|
|
63
67
|
- **Confira o nó `e2e` do verify antes de despachar.** Ele carrega o estado do stack:
|
|
64
68
|
- `pass` → a aplicação subiu e está saudável; o avaliador pode navegá-la. **Passe a URL no prompt**
|
|
65
69
|
— cada feature roda no seu bloco de portas, não em `localhost:3000`; pegue de
|
|
@@ -88,13 +92,15 @@ e o `recap.md` estar atualizado. Normalmente invocada pela skill orquestradora `
|
|
|
88
92
|
gravaram rodando o eval (`morph-plan` §5); não confunda com `3-implement/reports/`, que diz o
|
|
89
93
|
que o sub-agente fez.
|
|
90
94
|
- Gere o **diff da implementação** (`git diff` do range da feature, ou a lista de arquivos do recap.md com seus conteúdos atuais).
|
|
91
|
-
- **Blast radius dos símbolos do diff (se houver grafo).** Para cada símbolo público que o diff tocou, rode `morph-spec graph affected <símbolo> --prod --json` e inclua o resultado no contexto do avaliador. É o que permite perguntar *"o que esta mudança pode ter quebrado FORA do diff"* sem que o avaliador leia o repositório inteiro. **Fallback:** `no-graph`, `not-found` ou `ambiguous` — siga sem o blast radius e **registre a ausência na seção de método do review-report**; o gate não depende disso. **Trate o resultado como possivelmente stale:** o
|
|
95
|
+
- **Blast radius dos símbolos do diff (se houver grafo).** Para cada símbolo público que o diff tocou, rode `morph-spec graph affected <símbolo> --prod --json` e inclua o resultado no contexto do avaliador. É o que permite perguntar *"o que esta mudança pode ter quebrado FORA do diff"* sem que o avaliador leia o repositório inteiro. **Fallback:** `no-graph`, `not-found` ou `ambiguous` — siga sem o blast radius e **registre a ausência na seção de método do review-report**; o gate não depende disso. **Trate o resultado como possivelmente stale:** o refresh automático só cobre a raiz. Numa worktree o grafo é o semeado da raiz e não vê o que o diff trouxe — com `graph status --json` stale e `refresh.auto: false`, rode `morph-spec graph refresh` antes do blast radius; na raiz, enquanto o refresh em background corre (`refresh.running`), o grafo ainda é o anterior. E lembre que em frontend ele responde "quem importa", não "quem chama".
|
|
96
|
+
- **Tire a foto da árvore imediatamente antes do dispatch:** `morph-spec report-check {feature} --before-eval --json`, depois do verify e de qualquer correção sua. É contra ela que a higiene abaixo prova que o avaliador reverteu o que mutou.
|
|
92
97
|
- Despache o subagent registrado `morph-evaluator` (gerado de `agents.json` — a persona do avaliador é o system prompt dele, com Read/Glob/Grep + Bash somente para verificação + Playwright para navegar, sem Write/Edit), com contexto fresco:
|
|
93
98
|
```
|
|
94
99
|
dispatch Agent (subagent_type: "morph-evaluator") with prompt:
|
|
95
100
|
contexto: mandate.md + spec.md + reuse-map.md + diff da implementação
|
|
96
101
|
+ saída real dos testes + nó e2e do verify (stack no ar? em qual URL?)
|
|
97
102
|
+ 3-implement/evidencias/*.md (quando existir)
|
|
103
|
+
+ 1-design/mockups.md (quando existir — o checklist de tela a conferir)
|
|
98
104
|
instrução: |
|
|
99
105
|
Você NÃO participou da implementação — avalie o que está no diff,
|
|
100
106
|
contra o mandate. NÃO leia `4-review/evaluator-report.md` neste
|
|
@@ -201,6 +207,21 @@ e o `recap.md` estar atualizado. Normalmente invocada pela skill orquestradora `
|
|
|
201
207
|
`morph-spec gate-check` PAUSA o Gate 3. Feature que NÃO gera mídia
|
|
202
208
|
não declara a seção nem a chave — a isenção é automática, e
|
|
203
209
|
escrever a seção "por precaução" é cerimônia vazia.
|
|
210
|
+
CHECKLIST DE TELA — CONDICIONAL, aplique SÓ se
|
|
211
|
+
`.morph/features/{feature}/1-design/mockups.md` existe com telas
|
|
212
|
+
`## Tela:`. Para cada tela, confira cada item decidido do seu
|
|
213
|
+
`### Checklist de tela` (volume, paginação, ordenação, filtro, os
|
|
214
|
+
três estados, mobile, abas) contra a tela ENTREGUE — navegando
|
|
215
|
+
quando o stack subiu, lendo o código quando não (a query pagina e
|
|
216
|
+
ordena no servidor? o estado vazio existe?). Grave a seção
|
|
217
|
+
`## Checklist de tela`, uma linha por item decidido de cada tela:
|
|
218
|
+
| Tela | Item | Mockup (planejado) | Entregue (observado) | Veredito |
|
|
219
|
+
com o nome da tela como está no mockup e veredito cumpre / diverge
|
|
220
|
+
/ não verificável (com o motivo). Itens "não se aplica" e a
|
|
221
|
+
Superfície não precisam de linha. Divergência pesa em CONTRATOS
|
|
222
|
+
(.morph/framework/evals/rubrics/contracts.md, "Contrato de tela").
|
|
223
|
+
Sem a seção, ou com item decidido sem linha, o `morph-spec
|
|
224
|
+
gate-check` PAUSA o Gate 3.
|
|
204
225
|
Grave também a linha literal, machine-readable:
|
|
205
226
|
`**Proof-Scores:** mutation={n} verde={n} fiacao={n} guard={n} eval={n}`
|
|
206
227
|
— os cinco 0-10, na ordem das rubricas acima. O MENOR deles
|
|
@@ -223,6 +244,10 @@ e o `recap.md` estar atualizado. Normalmente invocada pela skill orquestradora `
|
|
|
223
244
|
um idle_notification, sem texto). Ainda assim NÃO chame SendMessage:
|
|
224
245
|
ele gera um evento a mais além da notificação de término, custando
|
|
225
246
|
um turno inútil ao orquestrador.
|
|
247
|
+
Limite de turnos: se chegar a ~70% dele sem terminar, grave o
|
|
248
|
+
relatório com `PARCIAL` na 1ª linha e SEM `**Composite-Score:**`
|
|
249
|
+
(o que já provou, o que falta) — o gate-check leria o token como
|
|
250
|
+
final. Ao concluir, o relatório final substitui o parcial.
|
|
226
251
|
Seu relatório (no arquivo, e na mensagem final quando ela chega)
|
|
227
252
|
deve conter: score 0-10 por dimensão, score composto (arch×0.30 +
|
|
228
253
|
contracts×0.25 + quality×0.25 + tests×0.20) gravado TAMBÉM como a
|
|
@@ -234,14 +259,21 @@ e o `recap.md` estar atualizado. Normalmente invocada pela skill orquestradora `
|
|
|
234
259
|
é falha de protocolo.
|
|
235
260
|
```
|
|
236
261
|
- **Fallback (tipo não registrado):** se `morph-evaluator` não estiver na sua lista de subagent types, despache `general-purpose` colando o campo `persona` do agente `evaluator` (Read em `.morph/framework/agents.json`) no topo do prompt — e **registre o fallback no review-report** (seção de método).
|
|
237
|
-
- **Ao retomar o controle, HIGIENE DA ÁRVORE antes de qualquer leitura de score.**
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
262
|
+
- **Ao retomar o controle, HIGIENE DA ÁRVORE antes de qualquer leitura de score.** ANTES de
|
|
263
|
+
abrir o relatório, rode `morph-spec report-check {feature} --json`. A foto que o
|
|
264
|
+
`--before-eval` gravou antes do dispatch fica em `4-review/`, e é contra ela que o bloco `tree`
|
|
265
|
+
compara, em qualquer sessão — inclusive a que retoma depois de o avaliador morrer no meio:
|
|
266
|
+
- `tree.sinceBeforeEval.changed` vazio = o conteúdo de todo arquivo fora de `.morph/` é o de
|
|
267
|
+
antes do dispatch, e o avaliador reverteu o que mutou. Com arquivos listados, a mutação
|
|
268
|
+
ficou no disco (ou foi commitada) nesses arquivos;
|
|
269
|
+
- `tree.markers` vazio = nenhum marcador `MUTACAO` esquecido;
|
|
270
|
+
- `tree.sinceBeforeEval` `null` = não há foto (dispatch anterior a ela): confira cada arquivo
|
|
271
|
+
da seção `## Mutações` contra o md5 "antes" registrado; `tree` `null` = o git não respondeu,
|
|
272
|
+
e nada foi conferido.
|
|
273
|
+
|
|
274
|
+
Não tire a foto de novo antes desta higiene passar: a foto nova apagaria a prova da anterior.
|
|
275
|
+
|
|
276
|
+
**Por que antes:** o avaliador
|
|
245
277
|
muta código de produção de propósito, e um avaliador que morreu no meio da rodada deixa a
|
|
246
278
|
mutação NO DISCO. Ler o score primeiro e só depois descobrir a árvore suja significa ter
|
|
247
279
|
avaliado — e possivelmente aprovado — um estado que ninguém quis. E **não rode build/teste
|
|
@@ -262,6 +294,7 @@ e o `recap.md` estar atualizado. Normalmente invocada pela skill orquestradora `
|
|
|
262
294
|
> diff antes). É a mesma proibição que o prompt do passo 4 já dá ao avaliador: aqui ela vale
|
|
263
295
|
> para VOCÊ.
|
|
264
296
|
- **Leia primeiro** `.morph/features/{feature}/4-review/evaluator-report.md` — é o valor de retorno autoritativo, não a mensagem de texto do dispatch (que é cortesia, útil só quando chega inteira). Os scores por dimensão e o composto do review-report vêm **desse arquivo**, não da sua auto-avaliação. Se o arquivo vier ausente, oco, ou sem os scores por dimensão, registre a falha de protocolo na seção de método do review-report e re-despache.
|
|
297
|
+
- **`PARCIAL` na 1ª linha = o avaliador parou antes do fim** (limite de turnos; o `report-check` devolve `evaluator.partial: true`). Não leia score dele — o parcial não tem `**Composite-Score:**`, e o `gate-check` pausaria de qualquer jeito — e não re-despache frio: um avaliador novo refaz a rodada inteira (probes, mutações, navegação). Retome o MESMO avaliador por `SendMessage`, como no passo 6, colando `tree.dirty` e `tree.commits` do `report-check` no recado; ele completa o relatório, e o final substitui o parcial. Só se o id não retomar, despache um novo pelo caminho normal — o parcial no disco é resíduo, não insumo, como o prompt já diz. Antes de qualquer das duas, a higiene da árvore acima continua valendo: um avaliador cortado no meio pode ter deixado mutação no disco.
|
|
265
298
|
|
|
266
299
|
5. Produza `review-report.md` em `.morph/features/{feature}/4-review/` com:
|
|
267
300
|
- **`**Reviewed-SHA:** {git rev-parse HEAD}`** — o commit que você revisou, **obrigatório**.
|
|
@@ -294,6 +327,10 @@ e o `recap.md` estar atualizado. Normalmente invocada pela skill orquestradora `
|
|
|
294
327
|
Feature sem código de produção declara a seção com `não aplicável — feature sem código de
|
|
295
328
|
produção`. **Sem a seção, o `gate-check review` PAUSA** — a regra vive em código
|
|
296
329
|
(`risk-detector.js`), não na boa vontade do prompt.
|
|
330
|
+
- **Checklist de tela** (feature com `1-design/mockups.md`) — a seção `## Checklist de tela` do
|
|
331
|
+
`evaluator-report.md` em resumo: quantas telas e itens conferidos, e cada `diverge` por extenso
|
|
332
|
+
(tela, item, planejado × entregue). Sem ela, havendo item decidido a conferir, o `gate-check review` **pausa** — o design decidiu
|
|
333
|
+
como a tela pagina, ordena e falha, e o Gate 3 registra se a tela entregue cumpre.
|
|
297
334
|
- Lista de itens bloqueantes (se houver) — com descrição e critério de resolução
|
|
298
335
|
- Lista de melhorias recomendadas (não bloqueantes)
|
|
299
336
|
- Recomendação final: Aprovado / Rejeitar com condições / Reprovar
|
|
@@ -304,8 +341,8 @@ e o `recap.md` estar atualizado. Normalmente invocada pela skill orquestradora `
|
|
|
304
341
|
inteira é um bloqueante crítico que o loop de correção deveria ter pego.)
|
|
305
342
|
|
|
306
343
|
**Para CONFIRMAR uma correção, retome o MESMO avaliador — não despache um frio.** Use
|
|
307
|
-
`SendMessage` com o id do agente que já avaliou, colando no recado
|
|
308
|
-
`
|
|
344
|
+
`SendMessage` com o id do agente que já avaliou, colando no recado `tree.dirty` e `tree.commits`
|
|
345
|
+
do `report-check {feature} --json` — o que mudou desde o relatório dele. Antes do recado, tire a foto de novo (`--before-eval`): suas correções mudaram a árvore, e a próxima higiene compara com a árvore que ele vai receber. Ele já tem em contexto o que apontou e
|
|
309
346
|
os probes que rodou; um avaliador novo re-descobre o produto inteiro para checar um item, e
|
|
310
347
|
re-executa do zero os probes da rodada anterior.
|
|
311
348
|
|
|
@@ -389,3 +426,4 @@ e o `recap.md` estar atualizado. Normalmente invocada pela skill orquestradora `
|
|
|
389
426
|
- `.morph/features/{feature}/2-plan/spec.md` — arquitetura e contratos
|
|
390
427
|
- `.morph/features/{feature}/2-plan/decisions.md` — ADRs registrados (se existir)
|
|
391
428
|
- `.morph/features/{feature}/3-implement/recap.md` — registro de execução
|
|
429
|
+
- `.morph/features/{feature}/1-design/mockups.md` — o checklist de tela que o avaliador confere no passo 4 (quando a feature tomou o ramo uiux)
|
|
@@ -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.38.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-stack-scan
|
|
@@ -4,7 +4,7 @@ description: Localiza um standard específico via busca server-side (morph-spec
|
|
|
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.38.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-standards
|
|
@@ -4,7 +4,7 @@ description: Conduz a fase opcional de UI/UX — design system, mockups, compone
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao tomar o ramo uiux (morph-spec advance --design), depois do Gate 1 e antes do morph-plan
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.38.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-uiux
|
|
@@ -30,6 +30,7 @@ Ao tomar o ramo opcional uiux: feature/bug cuja mudança cria ou altera superfí
|
|
|
30
30
|
- **Consistência:** reusa tokens/componentes existentes de `.morph/context/design-system.md` antes de criar novos; um token novo precisa de justificativa (o existente não cobre o caso).
|
|
31
31
|
- **Tecnologia de ponta condicionada ao stack real** (passo 1) — nunca a suposição de que o projeto é Next.js.
|
|
32
32
|
- **Sistemas, não telas isoladas** — mesmo critério da persona `ui-designer`: componentes reutilizáveis antes de composições de uso único.
|
|
33
|
+
- **Toda tela sai com o checklist de tela preenchido** (template no passo 3) — a superfície, o volume esperado de dados, paginação, ordenação, filtro, os três estados (vazio, carregando, erro), o comportamento no mobile e abas × página longa. "Não se aplica" vale, **desde que escrito**. É o checklist que faz a lista de 2 000 linhas paginar: o que o design não decide não vira `doneCriteria` (`morph-plan` §5d), e o que não é critério ninguém entrega. Tela de dados segue os standards de `admin-app` (lista/tabela, formulário, feedback, estrutura de página), que a persona cita na superfície `admin-app`.
|
|
33
34
|
|
|
34
35
|
3. **Despache `morph-ui-designer`** para o trabalho visual — dispatch é o default aqui (domínio diferente do Orchestrator, MORPH.md §6). `morph-ui-designer` tem `Read/Write/Edit/Glob/Grep` + MCPs `stitch`/`gemini-image`/`playwright`/`context7`, mas **não tem Bash** — não peça build, testes nem `morph-spec` a ele; isso é do orquestrador.
|
|
35
36
|
|
|
@@ -45,13 +46,36 @@ Ao tomar o ramo opcional uiux: feature/bug cuja mudança cria ou altera superfí
|
|
|
45
46
|
Produza, NESTA ORDEM — design-system.md primeiro, os demais só como aplicável ao escopo:
|
|
46
47
|
1. `design-system.md` — tokens (cor, tipografia, espaço, motion) consistentes com o projeto
|
|
47
48
|
2. `mockups.md` — descrição estruturada de cada tela nova/alterada (+ imagem via MCP
|
|
48
|
-
gemini-image/stitch quando disponível; fallback: descrição textual detalhada)
|
|
49
|
+
gemini-image/stitch quando disponível; fallback: descrição textual detalhada).
|
|
50
|
+
Cada tela é um `## Tela: <nome>` e traz, dentro dela, o checklist abaixo, com cada `…`
|
|
51
|
+
trocado pela decisão — "não se aplica" vale se escrito; `…`, vazio ou "a definir" não.
|
|
52
|
+
O que cada item decide: Superfície (admin-app | marketing-site — ela escolhe que
|
|
53
|
+
standards você lê para ESSA tela, seção "Standards by surface" da sua persona),
|
|
54
|
+
Volume esperado (registros hoje e em 1 ano), Paginação (servidor, N por página — ou
|
|
55
|
+
por que não pagina), Ordenação (colunas + padrão, no servidor), Filtro (filtros e
|
|
56
|
+
busca, no servidor), Estado vazio (sem registros × sem resultado para o filtro),
|
|
57
|
+
Estado carregando, Estado de erro (mensagem + como tentar de novo), Mobile (o que a
|
|
58
|
+
tela vira abaixo de md), Abas (abas × página longa × wizard, e por quê).
|
|
59
|
+
### Checklist de tela
|
|
60
|
+
| Item | Decisão |
|
|
61
|
+
|---|---|
|
|
62
|
+
| Superfície | … |
|
|
63
|
+
| Volume esperado | … |
|
|
64
|
+
| Paginação | … |
|
|
65
|
+
| Ordenação | … |
|
|
66
|
+
| Filtro | … |
|
|
67
|
+
| Estado vazio | … |
|
|
68
|
+
| Estado carregando | … |
|
|
69
|
+
| Estado de erro | … |
|
|
70
|
+
| Mobile | … |
|
|
71
|
+
| Abas | … |
|
|
49
72
|
3. `components.md` — inventário de componentes novos/reusados, com props e os estados do
|
|
50
73
|
princípio 2 acima
|
|
51
74
|
4. `flows.md` — fluxos de navegação/interação entre as telas
|
|
52
75
|
|
|
53
|
-
Done quando: os artefatos aplicáveis existem
|
|
54
|
-
design-system.md em vez de reinventar valores soltos.
|
|
76
|
+
Done quando: os artefatos aplicáveis existem, cada um cita os tokens/componentes do
|
|
77
|
+
design-system.md em vez de reinventar valores soltos, e toda `## Tela:` do mockups.md
|
|
78
|
+
tem o checklist completo.
|
|
55
79
|
|
|
56
80
|
Contrato do relatório final:
|
|
57
81
|
1. GRAVE um relatório por artefato produzido em
|
|
@@ -70,13 +94,13 @@ Ao tomar o ramo opcional uiux: feature/bug cuja mudança cria ou altera superfí
|
|
|
70
94
|
|
|
71
95
|
Após o retorno: **leia primeiro** `1-design/reports/*-report.md` — valor de retorno autoritativo, a mensagem de texto é atalho best-effort quando chega inteira. `design-system.md` é o único output obrigatório (`phases.json → uiux.requiredOutputs`); sem ele em disco, `morph-spec advance` recusa avançar — confirme que existe antes de rodar `advance` no passo 6.
|
|
72
96
|
|
|
73
|
-
4. **Atualize o design system vivo do projeto** — se a Parte 3 introduziu tokens/componentes novos, aplique o mesmo protocolo do `morph-brainstorming` (Parte 0):
|
|
97
|
+
4. **Atualize o design system vivo do projeto** — se a Parte 3 introduziu tokens/componentes novos, aplique o mesmo protocolo do `morph-brainstorming` (Parte 0): **reescreva o corpo** de `.morph/context/design-system.md` com a adição — o token ou a regra que mudou é substituído na própria seção, nunca empilhado ao lado do antigo — e registre no changelog só data e motivo. `1-design/design-system.md` é o artefato **da feature** (o que ela usa/introduz); `.morph/context/design-system.md` é o acervo vivo do **projeto** — não confunda os dois.
|
|
74
98
|
|
|
75
99
|
5. **Os artefatos alimentam o `morph-plan` seguinte.** Use cases e tasks de UI referenciam `1-design/mockups.md`/`components.md` **por path** (ex.: doneCriteria citando a seção do mockup) — não redigite conteúdo visual em `spec.md`.
|
|
76
100
|
|
|
77
101
|
6. Apresente o Gate uiux.
|
|
78
102
|
|
|
79
|
-
Rode `morph-spec gate-check {feature} uiux [--json]` — mesma mecânica de `morph-plan`/`morph-review`: lê `trust`, decide via `shouldPauseGate` e persiste `gateDecisions.uiux` com timestamp server-side. Divergência de design-system detectada aqui (fonte do projeto vs. o que a feature precisa) é uma das poucas chaves que `--signals` aceita sobrescrever:
|
|
103
|
+
Rode `morph-spec gate-check {feature} uiux [--json]` — mesma mecânica de `morph-plan`/`morph-review`: lê `trust`, decide via `shouldPauseGate` e persiste `gateDecisions.uiux` com timestamp server-side. **O checklist de tela é cobrado aqui, por código:** com `1-design/mockups.md` presente, tela sem o bloco, item ausente, resposta vazia ou "a definir" — ou nenhuma `## Tela:` — **pausa** o gate nomeando tela e item (`signals.screenChecklist`), e o `approve`/`advance` com assinatura `auto` recusam encerrar a fase pela mesma regra (só o mockup no formato antigo, telas `## S001:`, é isento — e o sinal diz isso). Complete o mockup antes de apresentar o gate: não peça ao humano que aprove um design que ainda não decidiu se a lista pagina. Divergência de design-system detectada aqui (fonte do projeto vs. o que a feature precisa) é uma das poucas chaves que `--signals` aceita sobrescrever:
|
|
80
104
|
```
|
|
81
105
|
morph-spec gate-check {feature} uiux --signals '{"designSystemDivergence":true}'
|
|
82
106
|
```
|
|
@@ -119,9 +143,9 @@ Ao tomar o ramo opcional uiux: feature/bug cuja mudança cria ou altera superfí
|
|
|
119
143
|
## Output esperado
|
|
120
144
|
|
|
121
145
|
- `.morph/features/{feature}/1-design/design-system.md` — obrigatório
|
|
122
|
-
- `.morph/features/{feature}/1-design/mockups.md`, `components.md`, `flows.md` — conforme o escopo exigir
|
|
146
|
+
- `.morph/features/{feature}/1-design/mockups.md`, `components.md`, `flows.md` — conforme o escopo exigir; no `mockups.md`, toda `## Tela:` com o `### Checklist de tela` completo (cobrado pelo `gate-check uiux` e pelo `approve`/`advance` com assinatura `auto`)
|
|
123
147
|
- `.morph/features/{feature}/1-design/reports/*-report.md` — relatório(s) bruto(s) do `morph-ui-designer` despachado no passo 3
|
|
124
|
-
- `.morph/context/design-system.md`
|
|
148
|
+
- `.morph/context/design-system.md` com o corpo reescrito (se tokens/componentes novos entraram) e uma entrada de changelog (data, motivo)
|
|
125
149
|
- Gate uiux registrado aprovado em `.morph/features/{feature}/feature.json` (autoritativo)
|
|
126
150
|
|
|
127
151
|
## Referências
|
|
@@ -129,7 +153,8 @@ Ao tomar o ramo opcional uiux: feature/bug cuja mudança cria ou altera superfí
|
|
|
129
153
|
- `.morph/framework/MORPH.md` §2.1 — critério objetivo de entrada no ramo uiux
|
|
130
154
|
- `.morph/framework/MORPH.md` §6 — protocolo de dispatch e contrato do relatório final
|
|
131
155
|
- `.morph/framework/MORPH.md` §5 — regras de pausa de gate (trust mode)
|
|
132
|
-
- `.morph/framework/agents.json` — persona `ui-designer` (tools, MCPs, standards)
|
|
156
|
+
- `.morph/framework/agents.json` — persona `ui-designer` (tools, MCPs, standards; `surfaces` separa os de `marketing-site` e os de `admin-app`)
|
|
157
|
+
- `.morph/framework/standards/frontend/admin-app/` — lista e tabela, formulário, confirmação e toast, abas × página longa × wizard: o que o checklist de tela decide numa tela de dados
|
|
133
158
|
- `.morph/framework/templates/context/design-system.md` — forma de partida quando o projeto não tem design system vivo
|
|
134
159
|
- `.claude/skills/morph-brainstorming/SKILL.md` — protocolo de reconciliação/changelog do design-system vivo (Parte 0), reaplicado no passo 4
|
|
135
160
|
- `.claude/skills/morph-plan/SKILL.md` — consome os artefatos desta fase por path
|