@polymorphism-tech/morph-spec 8.20.0 → 8.22.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 +31 -2
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/CLAUDE.md +2 -1
- package/framework/MORPH.md +6 -2
- package/framework/agents.json +3 -2
- package/framework/docs/CLI.md +4 -3
- package/framework/hooks/claude-code/core/enforce-phase-writes.js +23 -2
- package/framework/hooks/claude-code/core/state-sync.js +5 -0
- package/framework/hooks/claude-code/core/telemetry-log.js +34 -3
- package/framework/hooks/claude-code/core/validate-completion.js +116 -4
- package/framework/hooks/claude-code/core/worktree-context.js +9 -4
- package/framework/hooks/shared/e2e-check.js +0 -0
- package/framework/hooks/shared/telemetry-logger.js +64 -1
- package/framework/schemas/feature.schema.json +5 -3
- package/framework/schemas/tasks.schema.json +1 -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 +7 -16
- package/framework/skills/core/morph-brainstorming/SKILL.md +2 -2
- 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 +1 -1
- package/framework/skills/core/morph-plan/SKILL.md +25 -4
- package/framework/skills/core/morph-proposal/SKILL.md +1 -1
- package/framework/skills/core/morph-review/SKILL.md +35 -8
- package/framework/skills/core/morph-stack-scan/SKILL.md +1 -1
- package/framework/skills/core/morph-standards/SKILL.md +29 -15
- package/framework/skills/core/morph-uiux/SKILL.md +3 -3
- package/framework/templates/infrastructure/docker/docker-compose.template.yml +29 -5
- package/package.json +1 -1
- package/src/commands/e2e/e2e.js +318 -0
- package/src/commands/observability/cost.js +93 -5
- package/src/commands/project/update.js +2 -63
- package/src/commands/state/finish.js +38 -0
- package/src/commands/state/gate-check.js +10 -3
- package/src/commands/validation/validate-feature.js +7 -1
- package/src/commands/validation/verify.js +7 -0
- package/src/core/templates/template-registry.js +2 -30
- package/src/lib/e2e/compose-env.js +74 -0
- package/src/lib/git/default-branch.js +44 -8
- package/src/lib/installers/templates-reconcile.js +81 -0
- package/src/lib/risk-detector.js +20 -1
- package/src/lib/telemetry/telemetry-reader.js +80 -4
- package/src/lib/validators/verify-runner.js +121 -2
- package/src/scripts/setup-infra.js +23 -5
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"standards": {
|
|
40
40
|
"type": "array",
|
|
41
41
|
"items": { "type": "string", "minLength": 1 },
|
|
42
|
-
"description": "Standards pinned by morph-plan for this task, as
|
|
42
|
+
"description": "Standards pinned by morph-plan for this task, as PATHS relative to the framework root (e.g. \"standards/backend/dotnet/vsa-handler-patterns.md\"). Optional. Part of the plan contract: frozen after Gate 2. NOT the same vocabulary as agents.json's top-level `standards` field, which lists IDs (e.g. \"backend-dotnet-vsa-handler-patterns\", no slashes/extension) — same field name, different shape; do not treat one as the other."
|
|
43
43
|
}
|
|
44
44
|
},
|
|
45
45
|
"additionalProperties": false
|
|
@@ -4,7 +4,7 @@ description: Guia a criação de uma landing page nova ponta-a-ponta a partir do
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao iniciar um novo projeto de LP com o template Umbraco genérico
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.22.0"
|
|
8
8
|
stacks:
|
|
9
9
|
- umbraco
|
|
10
10
|
---
|
|
@@ -4,7 +4,7 @@ description: Migra uma landing page existente (React/Vite, Next.js estático ou
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao receber instrução "use /migrate-lp-to-umbraco {projeto}" do usuário, ou quando o usuário descrever necessidade de migrar uma LP para Umbraco
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.22.0"
|
|
8
8
|
stacks:
|
|
9
9
|
- umbraco
|
|
10
10
|
---
|
|
@@ -4,7 +4,7 @@ description: Orquestra a execução autônoma de tasks de uma feature morph-spec
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: após Gate 2 aprovado, ao receber instrução "use /morph-apply" ou "implementar feature"
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.22.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-apply
|
|
@@ -208,21 +208,12 @@ Quando `getPendingTasks(data).length === 0`:
|
|
|
208
208
|
- Invocar `Skill(morph-review)` para gerar `.morph/features/{feature}/4-review/review-report.md`.
|
|
209
209
|
- A skill morph-review chama `morph-eval` em escopo de feature inteira.
|
|
210
210
|
|
|
211
|
-
### 5. Gate 3
|
|
211
|
+
### 5. Gate 3
|
|
212
212
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
morph-spec gate-check {feature} review --signals '{"evalScore":9.2,"standardsViolations":[]}'
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
Risco que nenhuma dessas chaves representa (julgamento do avaliador que não vira `standardsViolations`): use `gate-decision` direto em vez de `gate-check`.
|
|
221
|
-
|
|
222
|
-
**Nunca edite `feature.json` à mão** (colide com o hook state-sync — erro "file modified since read"). Os caminhos acima gravam no mesmo lugar; o hook `gate-guard.js` confere depois se a ação bateu com a decisão persistida.
|
|
223
|
-
|
|
224
|
-
- Pause: `AskUserQuestion` com options `["aprovado, fechar feature", "preciso ajustar", "rollback"]`.
|
|
225
|
-
- Auto: exibir summary do review-report, aprovar via `morph-spec approve {feature} review --mode auto`, e prosseguir.
|
|
213
|
+
Apresentado e persistido por `morph-review` §8 (invocada no passo 4 acima) — gate-check, template
|
|
214
|
+
fixo nomeando a feature, aprovação registrada pós-resposta. Ao retomar o controle dela, **NÃO
|
|
215
|
+
re-apresente o gate**: siga direto para o encerramento (§6) conforme a decisão já persistida em
|
|
216
|
+
`gateDecisions.review`.
|
|
226
217
|
|
|
227
218
|
### 6. Pós Gate 3 — encerramento
|
|
228
219
|
|
|
@@ -255,7 +246,7 @@ Risco que nenhuma dessas chaves representa (julgamento do avaliador que não vir
|
|
|
255
246
|
- `framework/skills/core/morph-review/SKILL.md`
|
|
256
247
|
- `framework/skills/core/morph-plan/SKILL.md` §5a — resolve e carimba `task.agent`/`task.standards` no plano; fonte primária deste §3b
|
|
257
248
|
- `morph-spec dag {feature}` — análise de DAG e decisão sequencial vs paralelo (ponderada por effort), incluindo recomendação de isolamento (`isolation.recommended: "worktree"`)
|
|
258
|
-
- `morph-spec verify {feature} [task] --json` — cadeia determinística build+testes+validadores (código antes do juiz)
|
|
249
|
+
- `morph-spec verify {feature} [task] --json` — cadeia determinística build+testes+validadores+e2e (código antes do juiz)
|
|
259
250
|
- `morph-spec score {feature} {task} {score} [--dims a,c,q,t]` — grava taskScores no feature.json com timestamp server-side
|
|
260
251
|
- `morph-spec gate-check {feature} {gate} [--json]` — default: coleta sinais do disco, decide via `shouldPauseGate`, persiste `gateDecisions`
|
|
261
252
|
- `morph-spec gate-decision {feature} {gate} --pause {bool} [--reason ...] [--signals ...]` — escape manual: risco que o `gate-check` não vê no disco (shape em `.morph/framework/schemas/feature.schema.json`)
|
|
@@ -4,7 +4,7 @@ description: Entende o negócio, os usuários e a arquitetura antes de qualquer
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao receber um novo request de feature, antes de morph-plan
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.22.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-brainstorming
|
|
@@ -147,6 +147,6 @@ options:
|
|
|
147
147
|
|
|
148
148
|
## Referências
|
|
149
149
|
- `.morph/framework/MORPH.md` — seções 1 (Papéis), 2 (Fases), 5 (Gates), Trust Mode
|
|
150
|
-
-
|
|
150
|
+
- `morph-spec standards --find "<query>"` — para referência de standards relevantes à stack (ver `morph-standards`)
|
|
151
151
|
- `framework/skills/core/morph-stack-scan/SKILL.md` — invocada na Parte 0 (varredura), antes de qualquer pergunta
|
|
152
152
|
- `.morph/framework/MORPH.md` §5 — regras de pausa do Gate 1 (trust mode)
|
|
@@ -4,7 +4,7 @@ description: Avalia a qualidade de uma tarefa ou fase com rubricas graduadas 0-1
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao completar uma tarefa ou ao finalizar uma fase de implementação
|
|
6
6
|
user-invokable: false
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.22.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-eval
|
|
@@ -4,7 +4,7 @@ description: ADW cirúrgico de hotfix — resolve uma queda/bug crítico de prod
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao receber "/morph-hotfix {feature}", quando a morph-proposal classifica o pedido como workType hotfix (Passo 0), ou o usuário diz "produção caiu / hotfix / urgente"
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.22.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-hotfix
|
|
@@ -4,7 +4,7 @@ description: Guia a execução de cada tarefa de implementação com standard e
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao iniciar cada task de implementação listada em tasks.json
|
|
6
6
|
user-invokable: false
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.22.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-implement
|
|
@@ -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.22.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-plan
|
|
@@ -84,10 +84,31 @@ Ao iniciar a fase plan — após o `proposal.md` ser aprovado e antes de qualque
|
|
|
84
84
|
|
|
85
85
|
4. Produza `mandate.md` em `.morph/features/{feature}/2-plan/`:
|
|
86
86
|
- Stack exata do projeto (leia de `.morph/config/config.json` → `project.stack` ou do CLAUDE.md).
|
|
87
|
-
- Standards obrigatórios: liste os IDs
|
|
87
|
+
- Standards obrigatórios: descubra-os com `morph-spec standards --find "<domínio/tecnologia>"` (top 3 `id · path · digest` — o digest decide) por domínio tocado; liste os IDs escolhidos.
|
|
88
88
|
- Patterns proibidos — **copie por extenso no mandate.md** a lista canônica de `MORPH.md` § "Stack baked-in" (`Guid.NewGuid()`→`Guid.CreateVersion7()`, classes não-sealed sem justificativa, exceptions como fluxo de controle, camada de Service/Manager entre handler e dados, repository genérico `IRepository<T>`/`IUnitOfWork`, SQL cru sem justificativa) mais qualquer proibição específica da feature. Copie o texto completo — o mandate.md é lido por implementadores em contexto fresco, sem `MORPH.md` carregado, então um ponteiro sozinho não basta aqui.
|
|
89
89
|
- Política de acesso a dados (registre no mandate): `ApplicationDbContext` injetado direto no slice — para CRUD e para queries específicas (joins, projeção, paginação). Para concorrência ou SQL específico, store dedicado hand-written com justificativa em `decisions.md`.
|
|
90
|
-
- **Features com agentes de IA (MAF):** se a feature envolve um agente (Microsoft Agent Framework), **use a tool Read** nos standards relevantes de `framework/standards/ai-agents/*.md` (ex.: `setup`, `agent-session`, `middleware-patterns`, `mcp-server`, `mcp-tools`, `multi-agent-patterns`, `production`) — filtre pelo que a feature exige via
|
|
90
|
+
- **Features com agentes de IA (MAF):** se a feature envolve um agente (Microsoft Agent Framework), **use a tool Read** nos standards relevantes de `framework/standards/ai-agents/*.md` (ex.: `setup`, `agent-session`, `middleware-patterns`, `mcp-server`, `mcp-tools`, `multi-agent-patterns`, `production`) — filtre pelo que a feature exige via `morph-spec standards --find "<tema>" --category ai-agents`. Esses standards carregam as **convenções de projeto** (single-agent por padrão — Workflows só para fan-in/out real; provider, caching, observability, A2A) que uma fonte externa de docs (ex.: context7) não conhece. Padrão de divisão: **superfície da API** pode vir de docs ao vivo/context7 (mais frescas para um SDK em evolução), mas **as convenções vêm dos standards** — registre ambas no mandate. Não pule os `ai-agents/*.md` só porque o STANDARDS.json index lista que eles existem.
|
|
91
|
+
- **Verificação de runtime** — como se PROVA que a feature funciona rodando, não só compilando.
|
|
92
|
+
Compilar não é subir: um serviço injetado sem registro em `Program.cs` passa no build e derruba
|
|
93
|
+
a aplicação no startup. Registre no mandate:
|
|
94
|
+
- **Como o stack sobe:** o `docker compose` do projeto (`morph-spec e2e up {feature}`). Se o
|
|
95
|
+
projeto containeriza mas não tem compose, **isso é uma task** — sem ele o nó `e2e` do verify
|
|
96
|
+
reprova (não dispensa).
|
|
97
|
+
- **O que precisa ser exercitado:** os fluxos desta feature que o avaliador vai navegar, em
|
|
98
|
+
linguagem de comportamento — os mesmos verbos das pós-condições dos use cases.
|
|
99
|
+
- **Quais viram spec Playwright versionada:** caminho crítico e bug corrigido merecem regressão;
|
|
100
|
+
exploração pontual não. O critério vai aqui; escrever a spec é tarefa da implementação.
|
|
101
|
+
- **Base URL vinda do ambiente:** o harness dá a cada feature um bloco de portas próprio (para
|
|
102
|
+
duas worktrees não brigarem pela porta 3000), então o `playwright.config.ts` **não pode**
|
|
103
|
+
cravar a URL — leia `process.env.PLAYWRIGHT_BASE_URL ?? \`http://localhost:${process.env.PORT ?? 3000}\``
|
|
104
|
+
e faça o compose publicar `"${PORT:-3000}:3000"`. Config cravada = suíte batendo em porta
|
|
105
|
+
vazia e `ECONNREFUSED` com cara de app quebrada. Se estiver cravado, **isso é uma task**.
|
|
106
|
+
- **Setup de autenticação**, se a aplicação tem login: `e2e.auth` em `config.json`
|
|
107
|
+
(`mode: seed|storageState|bypass|none`, `seedCommand`, `storageStatePath`, `envFile`), com as
|
|
108
|
+
credenciais num `.env.e2e` **gitignored** — nunca no config commitado. **Se a app tem login e
|
|
109
|
+
isso não existe, crie a task de setup**: sem ela a navegação para na tela de login e a
|
|
110
|
+
verificação de runtime vira teatro. É gap de Gate 2, não dispensa de Gate 3.
|
|
111
|
+
- **Quando não se aplica** (biblioteca pura, chore sem runtime), registre a dispensa e o porquê.
|
|
91
112
|
- Checklist de done com critérios verificáveis por tarefa.
|
|
92
113
|
|
|
93
114
|
5. Produza `tasks.json` em `.morph/features/{feature}/2-plan/` seguindo o schema em `.morph/framework/schemas/tasks.schema.json`.
|
|
@@ -199,7 +220,7 @@ Ao registrar a aprovação do Gate 2, atualize o frontmatter de cada use case de
|
|
|
199
220
|
## Referências
|
|
200
221
|
|
|
201
222
|
- `.morph/framework/MORPH.md` — seções 2 (Fases), 3 (Contratos de Output), 5 (Gates), Trust Mode
|
|
202
|
-
-
|
|
223
|
+
- `morph-spec standards --find "<query>"` — para identificar standards relevantes ao mandate (o índice inteiro só como navegação exploratória; ver `morph-standards`)
|
|
203
224
|
- `.morph/framework/agents.json` — personas por domínio; lido UMA VEZ no passo 5a para carimbar `agent`/`standards` por task
|
|
204
225
|
- `.morph/framework/schemas/tasks.schema.json` — schema obrigatório de tasks.json
|
|
205
226
|
- `.morph/specs/usecases/` — acervo permanente de use cases do projeto (leia antes de numerar; em `bug`, é onde mora o UC a corrigir)
|
|
@@ -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.22.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.22.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-review
|
|
@@ -43,12 +43,22 @@ e o `recap.md` estar atualizado. Normalmente invocada pela skill orquestradora `
|
|
|
43
43
|
outro propósito. Falha aqui é bloqueante — quebra silenciosa em runtime, não em build.
|
|
44
44
|
|
|
45
45
|
4. **Despache o avaliador independente** — o score do Gate 3 nunca é auto-atribuído por quem implementou:
|
|
46
|
-
- Rode `morph-spec verify {feature} --json` (escopo feature) e capture o JSON — é a saída real de build+testes+validadores que você anexa ao prompt do avaliador independente (`morph-evaluator`).
|
|
46
|
+
- 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`).
|
|
47
|
+
- **Confira o nó `e2e` do verify antes de despachar.** Ele carrega o estado do stack:
|
|
48
|
+
- `pass` → a aplicação subiu e está saudável; o avaliador pode navegá-la. **Passe a URL no prompt**
|
|
49
|
+
— cada feature roda no seu bloco de portas, não em `localhost:3000`; pegue de
|
|
50
|
+
`morph-spec e2e status {feature} --json` (`baseUrl`) e não deixe o avaliador adivinhar.
|
|
51
|
+
- `fail` → **não abra o Gate 3.** Volte ao loop de correção: a app não sobe, ou as specs quebraram.
|
|
52
|
+
- `skip` → leia a razão e decida se a dispensa é legítima. "não containeriza" num projeto sem UI é
|
|
53
|
+
legítimo; "docker indisponível no ambiente" numa feature de UI **não** é — registre você mesmo
|
|
54
|
+
`morph-spec gate-decision {feature} review --pause true --reason "e2e não verificado: {razão}"`.
|
|
55
|
+
O disco não distingue dispensa legítima de verificação que faltou; esse julgamento é seu.
|
|
47
56
|
- 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).
|
|
48
|
-
- 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, sem Write/Edit), com contexto fresco:
|
|
57
|
+
- 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:
|
|
49
58
|
```
|
|
50
59
|
dispatch Agent (subagent_type: "morph-evaluator") with prompt:
|
|
51
60
|
contexto: mandate.md + spec.md + diff da implementação + saída real dos testes
|
|
61
|
+
+ nó e2e do verify (stack no ar? em qual URL?)
|
|
52
62
|
instrução: |
|
|
53
63
|
Você NÃO participou da implementação — avalie o que está no diff,
|
|
54
64
|
contra o mandate. Você tem Bash: use `morph-spec verify`, testes/build
|
|
@@ -56,6 +66,16 @@ e o `recap.md` estar atualizado. Normalmente invocada pela skill orquestradora `
|
|
|
56
66
|
foi reportado, em vez de confiar cegamente. Aplique as rubricas em
|
|
57
67
|
.morph/framework/evals/rubrics/ (architecture 30%, contracts 25%,
|
|
58
68
|
code-quality 25%, test-coverage 20%) seguindo as bandas 0-10 de cada uma.
|
|
69
|
+
Se o nó e2e subiu o stack, NAVEGUE a aplicação com Playwright e
|
|
70
|
+
percorra os fluxos desta feature como um usuário faria — ler o diff
|
|
71
|
+
prova que o código existe, usar a aplicação prova que ela funciona.
|
|
72
|
+
Confira console e network atrás de erro que teste nenhum cobriu.
|
|
73
|
+
Registre no relatório o que você navegou e o que viu. Se um fluxo que
|
|
74
|
+
você exercitou merece virar regressão, RECOMENDE a spec Playwright —
|
|
75
|
+
recomendar é seu papel, escrever a spec não é.
|
|
76
|
+
NÃO suba nem derrube o stack por conta própria (`morph-spec e2e` e o
|
|
77
|
+
nó de verify fazem isso): stack que não sobe é achado de INFRA a
|
|
78
|
+
reportar, não defeito de implementação a pontuar.
|
|
59
79
|
NÃO reescreva código. NÃO toque em tasks.json, feature.json nem no board
|
|
60
80
|
de sessão — Bash é só para verificação, nunca para mudar estado.
|
|
61
81
|
Contrato do relatório final: GRAVE seu relatório em
|
|
@@ -71,8 +91,9 @@ e o `recap.md` estar atualizado. Normalmente invocada pela skill orquestradora `
|
|
|
71
91
|
contracts×0.25 + quality×0.25 + tests×0.20) gravado TAMBÉM como a
|
|
72
92
|
linha literal `**Composite-Score:** {n.n}` (machine-readable — o
|
|
73
93
|
`morph-spec gate-check` lê o score real daí em vez do proxy de
|
|
74
|
-
taskScores),
|
|
75
|
-
qualquer dimensão < 9
|
|
94
|
+
taskScores), feedback priorizado (bloqueantes primeiro) para
|
|
95
|
+
qualquer dimensão < 9, e — quando o stack estava no ar — o que você
|
|
96
|
+
navegou e o que observou. Relatório ausente, oco, ou sem esses itens,
|
|
76
97
|
é falha de protocolo.
|
|
77
98
|
```
|
|
78
99
|
- **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).
|
|
@@ -87,6 +108,10 @@ e o `recap.md` estar atualizado. Normalmente invocada pela skill orquestradora `
|
|
|
87
108
|
uma regra de negócio, e ainda dizendo `976/976` quando eram 982).
|
|
88
109
|
- Scores por dimensão (arquitetura, contratos, qualidade, cobertura)
|
|
89
110
|
- Score composto final
|
|
111
|
+
- **Verificação de runtime** — o resultado do nó `e2e` (`pass`/`fail`/`skip` + razão), e o que o
|
|
112
|
+
avaliador navegou. Dispensa (`skip`) entra aqui **por extenso**: o valor de um gate está tanto
|
|
113
|
+
no que ele provou quanto no que ele deixou de provar, e uma dispensa silenciosa se lê como
|
|
114
|
+
aprovação. Se houver spec Playwright recomendada pelo avaliador, liste-a como melhoria.
|
|
90
115
|
- Lista de itens bloqueantes (se houver) — com descrição e critério de resolução
|
|
91
116
|
- Lista de melhorias recomendadas (não bloqueantes)
|
|
92
117
|
- Recomendação final: Aprovado / Rejeitar com condições / Reprovar
|
|
@@ -98,7 +123,8 @@ e o `recap.md` estar atualizado. Normalmente invocada pela skill orquestradora `
|
|
|
98
123
|
|
|
99
124
|
7. **NÃO finalize o trace manualmente.** O hook `trace-autogen` gera e finaliza `.morph/traces/YYYY-MM-DD-{feature}-implement.json` automaticamente (incl. `phase_summary` e `completed_at`) no último write de `tasks.json` — quando a última task sai de `pending`/`in_progress`. Se o trace parecer desatualizado, a causa é um `morph-spec score` faltante ou um recap sem o bloco da task — corrija a fonte, não o trace.
|
|
100
125
|
|
|
101
|
-
8. Apresente o Gate 3 segundo trust mode
|
|
126
|
+
8. Apresente o Gate 3 segundo trust mode — **única apresentação do gate**: `morph-apply` §5 aponta
|
|
127
|
+
para cá em vez de duplicar; ao devolver o controle a ela, o gate já está decidido.
|
|
102
128
|
|
|
103
129
|
Rode `morph-spec gate-check {feature} review [--json]` — lê `trust` de `.morph/config/config.json`, decide via `shouldPauseGate` e persiste `gateDecisions.review` com timestamp server-side, imprimindo `pause`/`reason`/`signals`. É o default — não recompute a tabela do MORPH.md §5 em linguagem natural.
|
|
104
130
|
|
|
@@ -109,7 +135,7 @@ e o `recap.md` estar atualizado. Normalmente invocada pela skill orquestradora `
|
|
|
109
135
|
|
|
110
136
|
Julgamento do revisor que nenhuma dessas chaves representa: use `gate-decision` direto em vez de `gate-check`.
|
|
111
137
|
|
|
112
|
-
**Nunca edite `feature.json` à mão** (colide com o hook state-sync). Os caminhos acima gravam no mesmo lugar; o hook `gate-guard.js` confere depois se a ação bateu com a decisão persistida.
|
|
138
|
+
**Nunca edite `feature.json` à mão** (colide com o hook state-sync — erro "file modified since read"). Os caminhos acima gravam no mesmo lugar; o hook `gate-guard.js` confere depois se a ação bateu com a decisão persistida.
|
|
113
139
|
|
|
114
140
|
**Se `pause === true`**, use `AskUserQuestion`:
|
|
115
141
|
|
|
@@ -129,6 +155,7 @@ e o `recap.md` estar atualizado. Normalmente invocada pela skill orquestradora `
|
|
|
129
155
|
|
|
130
156
|
**Composite score:** {score}/10
|
|
131
157
|
**Dimensões:** arquitetura={X} contratos={Y} qualidade={Z} cobertura={W}
|
|
158
|
+
**Runtime:** e2e={pass|skip} {razão, quando skip}
|
|
132
159
|
**Bloqueantes:** {N (zero esperado em auto-aprovação)}
|
|
133
160
|
**Recomendação:** Aprovado
|
|
134
161
|
```
|
|
@@ -146,7 +173,7 @@ e o `recap.md` estar atualizado. Normalmente invocada pela skill orquestradora `
|
|
|
146
173
|
- Gate 3 registrado aprovado em `.morph/features/{feature}/feature.json` (autoritativo), na forma canônica `{ approved, timestamp, approvedBy }` — via `morph-spec approve` em auto, ou pelo hook state-sync no caminho manual
|
|
147
174
|
|
|
148
175
|
## Referências
|
|
149
|
-
- `morph-spec verify {feature} [task] --json` — cadeia determinística build+testes+validadores anexada ao prompt do avaliador (passo 4)
|
|
176
|
+
- `morph-spec verify {feature} [task] --json` — cadeia determinística build+testes+validadores+e2e anexada ao prompt do avaliador (passo 4)
|
|
150
177
|
- `.morph/framework/MORPH.md` — seção 5 (Gate 3 + regras de pausa), seção 1 (papel Evaluator), Trust Mode
|
|
151
178
|
- `.claude/agents/morph-evaluator.md` — subagent do avaliador (gerado de `.morph/framework/agents.json`), despachado no passo 4
|
|
152
179
|
- `framework/skills/core/morph-eval/SKILL.md` — rubricas e bandas que o avaliador aplica
|
|
@@ -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.22.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-stack-scan
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: morph-standards
|
|
3
|
-
description: Localiza
|
|
3
|
+
description: Localiza um standard específico via busca server-side (morph-spec standards --find) e carrega só o necessário
|
|
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.22.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-standards
|
|
11
11
|
|
|
12
12
|
## Objetivo
|
|
13
|
-
Encontrar o standard certo para a situação atual e carregar apenas
|
|
14
|
-
Nunca
|
|
13
|
+
Encontrar o standard certo para a situação atual e carregar apenas o necessário no contexto.
|
|
14
|
+
Nunca abra o `STANDARDS.json` inteiro (65 KB) — a busca server-side já devolve o suficiente
|
|
15
|
+
para aplicar o standard na maioria dos casos.
|
|
15
16
|
|
|
16
17
|
## Quando invocar
|
|
17
18
|
Quando durante a implementação surgir uma dúvida de padrão arquitetural, de contrato, de qualidade
|
|
@@ -19,21 +20,33 @@ ou de teste — e o mandate.md não for suficiente para resolver.
|
|
|
19
20
|
|
|
20
21
|
## O que fazer
|
|
21
22
|
|
|
22
|
-
1.
|
|
23
|
+
1. Rode a busca server-side — é O caminho, não uma opção entre várias:
|
|
24
|
+
```
|
|
25
|
+
morph-spec standards --find "<domínio/tecnologia da task>" [--category <cat>] [--tags <a,b>] [--json]
|
|
26
|
+
```
|
|
27
|
+
Devolve o **top 3** como `id · path · digest` — o `digest` é o texto completo do standard;
|
|
28
|
+
na maioria dos casos ele já basta para aplicar o padrão, sem abrir o `.md`.
|
|
23
29
|
|
|
24
|
-
2.
|
|
30
|
+
2. Se dois resultados parecerem relevantes e houver conflito, adote o mais específico ao stack
|
|
31
|
+
do projeto. Registre o conflito no `decisions.md` da feature.
|
|
25
32
|
|
|
26
|
-
3.
|
|
27
|
-
|
|
33
|
+
3. Abra o arquivo `.md` do standard (campo `path`) só quando o `digest` não bastar para resolver
|
|
34
|
+
a dúvida — ex.: precisa de um exemplo de código completo ou de uma seção que o resumo não cobre.
|
|
28
35
|
|
|
29
|
-
4.
|
|
30
|
-
Registre o conflito no `decisions.md` da feature.
|
|
36
|
+
4. Aplique o standard na tarefa atual.
|
|
31
37
|
|
|
32
|
-
5.
|
|
38
|
+
5. Registre no `recap.md`: qual standard foi consultado (via `--find`, ou navegação — item abaixo)
|
|
39
|
+
e como foi aplicado.
|
|
33
40
|
|
|
34
|
-
|
|
41
|
+
## Fallback — navegação exploratória
|
|
35
42
|
|
|
36
|
-
|
|
43
|
+
`--find` exige uma query. Quando a necessidade é genuinamente exploratória (ex.: "o que existe
|
|
44
|
+
pra categoria X?", sem um termo de busca claro), nesta ordem:
|
|
45
|
+
|
|
46
|
+
1. `morph-spec standards` sem `--find` — lista categorias + contagem, custo mínimo, o suficiente
|
|
47
|
+
pra decidir qual `--category` usar num `--find` em seguida.
|
|
48
|
+
2. Só se isso não bastar, abra `framework/standards/STANDARDS.json` inteiro — último recurso,
|
|
49
|
+
nunca o primeiro passo.
|
|
37
50
|
|
|
38
51
|
## Quando não há standard adequado
|
|
39
52
|
Registre no `decisions.md` que nenhum standard cobre o caso.
|
|
@@ -41,10 +54,11 @@ Descreva o critério adotado e sinalize para revisão futura.
|
|
|
41
54
|
Não invente um standard — padrões não documentados são dívida técnica.
|
|
42
55
|
|
|
43
56
|
## Output esperado
|
|
44
|
-
- Standard identificado
|
|
57
|
+
- Standard identificado (via `--find`/digest, ou `.md` completo quando necessário) no contexto
|
|
45
58
|
- Critério de implementação claro para a tarefa atual
|
|
46
59
|
- Entrada no recap.md registrando o standard consultado
|
|
47
60
|
|
|
48
61
|
## Referências
|
|
49
|
-
- `
|
|
62
|
+
- `morph-spec standards --find "<query>" [--category] [--tags] [--json]` — busca server-side, top 3 `id · path · digest`
|
|
63
|
+
- `framework/standards/STANDARDS.json` — índice completo; abrir só como fallback exploratório (ver acima)
|
|
50
64
|
- `framework/MORPH.md` — seção 4 (Como consultar 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.22.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-uiux
|
|
@@ -33,7 +33,7 @@ Ao tomar o ramo opcional uiux: feature/bug cuja mudança cria ou altera superfí
|
|
|
33
33
|
|
|
34
34
|
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
35
|
|
|
36
|
-
**
|
|
36
|
+
**Persona universal** (`ui-designer.stack = ["*"]` em `agents.json`, mesmo mecanismo de `evaluator`/`scout`): UI/UX importa sempre que há superfície de UI, então o subagent está registrado em **todo** projeto — .NET/Blazor incluído, não só Next.js. **Fallback** (caso raro: instalação anterior a essa mudança, `.claude/agents/morph-ui-designer.md` ainda não regenerado): `general-purpose` colando o campo `persona` (Read em `.morph/framework/agents.json`) no prompt, registrando o fallback no relatório — resolvido rodando `morph-spec setup-infra --reinstall`.
|
|
37
37
|
|
|
38
38
|
Template do prompt (contrato do relatório em forma curta — copia o padrão de `morph-implement` §4, sem a cláusula de build/isolamento, que não se aplica a um agente sem Bash):
|
|
39
39
|
```
|
|
@@ -93,7 +93,7 @@ Ao tomar o ramo opcional uiux: feature/bug cuja mudança cria ou altera superfí
|
|
|
93
93
|
|
|
94
94
|
Aguardar resposta. Se "preciso ajustar", aplicar e reapresentar.
|
|
95
95
|
|
|
96
|
-
**
|
|
96
|
+
**Hook state-sync reconhece este gate, como os demais.** Igual a Gate 1/2/3, o hook `state-sync.js` (`gateFromQuestion`) reconhece o texto "Gate uiux" — uma resposta "aprovado" ao template acima grava sozinha `approvalGates.uiux = { approved: true, timestamp, approvedBy: "manual" }` no `feature.json` autoritativo, atribuído pelo nome da feature que a pergunta cita (MORPH.md §5). Sem nome na pergunta, ou fora de `AskUserQuestion` (headless/CI): aprove explicitamente:
|
|
97
97
|
```
|
|
98
98
|
morph-spec approve {feature} uiux --approver <quem respondeu>
|
|
99
99
|
# ou, para já aprovar e criar 2-plan/ num passo só:
|
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
# Docker Compose for Local Development
|
|
2
2
|
# Next.js + Neon Stack
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
#
|
|
4
|
+
# Ports come from variables with sane defaults so `morph-spec e2e up` can hand
|
|
5
|
+
# each feature worktree its own port block (see env-allocator.js). Hardcode
|
|
6
|
+
# "3000:3000" here and two features running side by side collide on the host,
|
|
7
|
+
# no matter what the harness injects — the container names would be distinct
|
|
8
|
+
# and the ports would not.
|
|
9
|
+
#
|
|
10
|
+
# Healthchecks are what make `up --wait` meaningful: without them Compose
|
|
11
|
+
# reports "started" the moment the process launches, and the e2e node would
|
|
12
|
+
# navigate an application that is not serving yet.
|
|
13
|
+
#
|
|
14
|
+
# The harness also exports PLAYWRIGHT_BASE_URL for the same allocated port, so
|
|
15
|
+
# `playwright.config.ts` must read it instead of hardcoding a URL:
|
|
16
|
+
# baseURL: process.env.PLAYWRIGHT_BASE_URL ?? `http://localhost:${process.env.PORT ?? 3000}`
|
|
5
17
|
|
|
6
18
|
services:
|
|
7
19
|
# Next.js Application
|
|
@@ -11,7 +23,7 @@ services:
|
|
|
11
23
|
dockerfile: Dockerfile.dev
|
|
12
24
|
container_name: {{kebabCase FEATURE_NAME}}-app
|
|
13
25
|
ports:
|
|
14
|
-
- "3000:3000"
|
|
26
|
+
- "${PORT:-3000}:3000"
|
|
15
27
|
environment:
|
|
16
28
|
- NODE_ENV=development
|
|
17
29
|
- DATABASE_URL=${DATABASE_URL}
|
|
@@ -20,7 +32,14 @@ services:
|
|
|
20
32
|
- /app/node_modules
|
|
21
33
|
- /app/.next
|
|
22
34
|
depends_on:
|
|
23
|
-
|
|
35
|
+
postgres:
|
|
36
|
+
condition: service_healthy
|
|
37
|
+
healthcheck:
|
|
38
|
+
test: ["CMD-SHELL", "node -e \"fetch('http://localhost:3000/').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))\""]
|
|
39
|
+
interval: 10s
|
|
40
|
+
timeout: 5s
|
|
41
|
+
retries: 12
|
|
42
|
+
start_period: 20s
|
|
24
43
|
networks:
|
|
25
44
|
- app-network
|
|
26
45
|
|
|
@@ -30,7 +49,7 @@ services:
|
|
|
30
49
|
container_name: {{kebabCase FEATURE_NAME}}-postgres
|
|
31
50
|
restart: unless-stopped
|
|
32
51
|
ports:
|
|
33
|
-
- "5432:5432"
|
|
52
|
+
- "${POSTGRES_PORT:-5432}:5432"
|
|
34
53
|
environment:
|
|
35
54
|
POSTGRES_USER: postgres
|
|
36
55
|
POSTGRES_PASSWORD: postgres
|
|
@@ -38,6 +57,11 @@ services:
|
|
|
38
57
|
volumes:
|
|
39
58
|
- postgres-data:/var/lib/postgresql/data
|
|
40
59
|
- ./migrations:/docker-entrypoint-initdb.d
|
|
60
|
+
healthcheck:
|
|
61
|
+
test: ["CMD-SHELL", "pg_isready -U postgres -d {{snakeCase FEATURE_NAME}}"]
|
|
62
|
+
interval: 5s
|
|
63
|
+
timeout: 5s
|
|
64
|
+
retries: 10
|
|
41
65
|
networks:
|
|
42
66
|
- app-network
|
|
43
67
|
|