@polymorphism-tech/morph-spec 8.19.0 → 8.21.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 +2 -1
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/CLAUDE.md +3 -11
- package/framework/MORPH.md +53 -55
- package/framework/agents.json +1 -1
- package/framework/docs/CLI.md +3 -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/telemetry-logger.js +64 -1
- package/framework/phases.json +1 -1
- 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 +6 -15
- package/framework/skills/core/morph-brainstorming/SKILL.md +3 -3
- 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 +6 -4
- package/framework/skills/core/morph-proposal/SKILL.md +10 -1
- package/framework/skills/core/morph-review/SKILL.md +4 -3
- 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 +135 -0
- package/package.json +1 -1
- package/src/commands/observability/cost.js +93 -5
- package/src/commands/project/update.js +2 -63
- package/src/commands/state/gate-check.js +10 -3
- package/src/core/templates/template-registry.js +2 -30
- 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/scripts/setup-infra.js +23 -5
|
@@ -16,12 +16,22 @@
|
|
|
16
16
|
* - Windows-safe paths via path.join
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
appendFileSync, readFileSync, mkdirSync, existsSync, statSync, renameSync,
|
|
21
|
+
} from 'fs';
|
|
20
22
|
import { join, dirname } from 'path';
|
|
21
23
|
|
|
22
24
|
const LOGS_DIR = '.morph/logs';
|
|
23
25
|
export const EVENTS_FILE = join(LOGS_DIR, 'events.jsonl');
|
|
24
26
|
|
|
27
|
+
// SessionStart (worktree-context.js) rotates events.jsonl once it crosses
|
|
28
|
+
// this size, alongside the pre-existing activity.jsonl rotation — same
|
|
29
|
+
// call site, same "between sessions" checkpoint. events.jsonl has no natural
|
|
30
|
+
// per-turn cap (prompts/commands are truncated at the write site, but the
|
|
31
|
+
// LINE COUNT itself grows unbounded across a long-lived project), so without
|
|
32
|
+
// this it grows forever the way activity.jsonl used to before R1.2.
|
|
33
|
+
export const ROTATE_THRESHOLD_BYTES = 5 * 1024 * 1024; // 5 MB
|
|
34
|
+
|
|
25
35
|
function getEventsPath(projectPath) {
|
|
26
36
|
return join(projectPath || process.cwd(), EVENTS_FILE);
|
|
27
37
|
}
|
|
@@ -73,3 +83,56 @@ export function readTelemetryEvents(projectPath) {
|
|
|
73
83
|
return [];
|
|
74
84
|
}
|
|
75
85
|
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Archive the current events.jsonl to `.morph/logs/sessions/`, mirroring
|
|
89
|
+
* activity-logger.js's `archiveSession()` — same directory, same rename-not-
|
|
90
|
+
* rewrite mechanics (O(1) even at multi-MB sizes). Named with an `events-`
|
|
91
|
+
* prefix (activity-logger's archives carry no prefix) so the two streams
|
|
92
|
+
* never collide inside the shared `sessions/` directory and stay
|
|
93
|
+
* distinguishable at a glance.
|
|
94
|
+
*
|
|
95
|
+
* Fail-silent — called only from `rotateEventsLogIfLarge` below, which has
|
|
96
|
+
* already confirmed the file exists.
|
|
97
|
+
*
|
|
98
|
+
* @param {string} [projectPath]
|
|
99
|
+
*/
|
|
100
|
+
function archiveEvents(projectPath) {
|
|
101
|
+
try {
|
|
102
|
+
const eventsPath = getEventsPath(projectPath);
|
|
103
|
+
if (!existsSync(eventsPath)) return;
|
|
104
|
+
|
|
105
|
+
const sessionsDir = join(projectPath || process.cwd(), LOGS_DIR, 'sessions');
|
|
106
|
+
mkdirSync(sessionsDir, { recursive: true });
|
|
107
|
+
|
|
108
|
+
const stamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
109
|
+
const archivePath = join(sessionsDir, `events-${stamp}.jsonl`);
|
|
110
|
+
renameSync(eventsPath, archivePath);
|
|
111
|
+
} catch {
|
|
112
|
+
// Fail-silent
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Rotate events.jsonl when it crosses `thresholdBytes`. Called from
|
|
118
|
+
* worktree-context.js on SessionStart, right next to the existing
|
|
119
|
+
* `rotateActivityLogIfLarge()` call — the only reliable "between sessions"
|
|
120
|
+
* checkpoint the harness gets. `thresholdBytes` is injectable so a test can
|
|
121
|
+
* force rotation without writing multiple megabytes.
|
|
122
|
+
*
|
|
123
|
+
* @param {string} [projectPath] - Project root (defaults to cwd)
|
|
124
|
+
* @param {number} [thresholdBytes] - Rotate once the log is at least this large
|
|
125
|
+
* @returns {boolean} true if a rotation was performed
|
|
126
|
+
*/
|
|
127
|
+
export function rotateEventsLogIfLarge(projectPath, thresholdBytes = ROTATE_THRESHOLD_BYTES) {
|
|
128
|
+
try {
|
|
129
|
+
const eventsPath = getEventsPath(projectPath);
|
|
130
|
+
if (!existsSync(eventsPath)) return false;
|
|
131
|
+
const { size } = statSync(eventsPath);
|
|
132
|
+
if (size < thresholdBytes) return false;
|
|
133
|
+
archiveEvents(projectPath);
|
|
134
|
+
return true;
|
|
135
|
+
} catch {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
}
|
package/framework/phases.json
CHANGED
|
@@ -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.21.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.21.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.21.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
|
|
|
@@ -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.21.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-brainstorming
|
|
@@ -88,7 +88,7 @@ options:
|
|
|
88
88
|
|
|
89
89
|
1. Produza `proposal.md` em `.morph/features/{feature}/0-proposal/` com:
|
|
90
90
|
- **Problema:** o que está sendo resolvido e para quem (máx. 2 parágrafos)
|
|
91
|
-
- **Escopo:** o que está incluído e o que está explicitamente excluído
|
|
91
|
+
- **Escopo:** o que está incluído e o que está explicitamente excluído — registre se a mudança cria ou altera superfície de UI (componente, página, tela, estilo, fluxo de navegação): é o fato que decide o roteamento para o ramo uiux na `morph-proposal` (critério objetivo em `MORPH.md` §2.1)
|
|
92
92
|
- **Usuários e fluxos críticos:** quem usa e qual é o caminho principal
|
|
93
93
|
- **Stack:** confirme o stack padrão ou documente desvios aprovados
|
|
94
94
|
- **Riscos e dependências:** o que pode dar errado, o que esta feature depende
|
|
@@ -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.21.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.21.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.21.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.21.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-plan
|
|
@@ -84,10 +84,10 @@ 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
91
|
- Checklist de done com critérios verificáveis por tarefa.
|
|
92
92
|
|
|
93
93
|
5. Produza `tasks.json` em `.morph/features/{feature}/2-plan/` seguindo o schema em `.morph/framework/schemas/tasks.schema.json`.
|
|
@@ -132,6 +132,8 @@ Ao iniciar a fase plan — após o `proposal.md` ser aprovado e antes de qualque
|
|
|
132
132
|
- `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.
|
|
133
133
|
- `standards`: o array `standards` dessa persona, mais qualquer standard adicional que a task especificamente exija (some, não substitua).
|
|
134
134
|
|
|
135
|
+
**Task que cria ou altera superfície de UI** (componente, página, estilo, fluxo de navegação) carimba `agent: "ui-designer"` — inclusive numa feature que não tomou o ramo uiux (MORPH.md §2.1): o critério de agente é por domínio da task, não por fase percorrida.
|
|
136
|
+
|
|
135
137
|
Uma task cujo domínio não bate com nenhuma persona registrada (ex.: task pura de config/docs) fica sem `agent` — `morph-implement` cai no fallback de Read de `agents.json` nesse caso.
|
|
136
138
|
|
|
137
139
|
**O `doneCriteria` carrega a pós-condição LITERAL.** Este é o elo que amarra a cadeia inteira: a pós-condição escrita em linguagem de negócio chega **sem tradução** ao critério que o `morph-spec verify` e o `morph-eval` cobram. Copie o texto da pós-condição, prefixado pelo seu rótulo (`"P2 — Cada veterinário traz..."`). Reescrever com outras palavras aqui é exatamente o ponto em que o requisito se perde hoje.
|
|
@@ -197,7 +199,7 @@ Ao registrar a aprovação do Gate 2, atualize o frontmatter de cada use case de
|
|
|
197
199
|
## Referências
|
|
198
200
|
|
|
199
201
|
- `.morph/framework/MORPH.md` — seções 2 (Fases), 3 (Contratos de Output), 5 (Gates), Trust Mode
|
|
200
|
-
-
|
|
202
|
+
- `morph-spec standards --find "<query>"` — para identificar standards relevantes ao mandate (o índice inteiro só como navegação exploratória; ver `morph-standards`)
|
|
201
203
|
- `.morph/framework/agents.json` — personas por domínio; lido UMA VEZ no passo 5a para carimbar `agent`/`standards` por task
|
|
202
204
|
- `.morph/framework/schemas/tasks.schema.json` — schema obrigatório de tasks.json
|
|
203
205
|
- `.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.21.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-proposal
|
|
@@ -98,6 +98,13 @@ morph-spec approve {feature} proposal --mode auto
|
|
|
98
98
|
morph-spec advance {feature}
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
+
### 3a. Roteamento uiux (após o Gate 1)
|
|
102
|
+
|
|
103
|
+
Critério objetivo em `MORPH.md` §2.1: a mudança cria ou altera superfície de UI (componente, página, tela, estilo, fluxo de navegação)?
|
|
104
|
+
|
|
105
|
+
- **Sim** → em vez do `advance {feature}` do passo 3, rode `morph-spec advance {feature} --design` (cria `1-design/`) e invoque `Skill(morph-uiux)`. Ela conduz a fase de design e, com o Gate uiux aprovado, devolve o controle aqui — siga para o passo 4.
|
|
106
|
+
- **Não** → nenhuma ação extra; o `advance {feature}` do passo 3 já criou `2-plan/` direto.
|
|
107
|
+
|
|
101
108
|
### 4. Verificar retomada antes de morph-plan
|
|
102
109
|
|
|
103
110
|
- Se `.morph/features/{feature}/2-plan/spec.md` já existe: pular para passo 6 (Gate 2).
|
|
@@ -129,6 +136,7 @@ Mesma mecânica do passo 3: a decisão já foi tomada e persistida pela `morph-p
|
|
|
129
136
|
## Output esperado
|
|
130
137
|
|
|
131
138
|
- `.morph/features/{feature}/0-proposal/proposal.md`
|
|
139
|
+
- `.morph/features/{feature}/1-design/` (se o ramo uiux — passo 3a — foi tomado)
|
|
132
140
|
- `.morph/features/{feature}/2-plan/spec.md`
|
|
133
141
|
- `.morph/features/{feature}/2-plan/mandate.md`
|
|
134
142
|
- `.morph/features/{feature}/2-plan/tasks.json`
|
|
@@ -139,6 +147,7 @@ Mesma mecânica do passo 3: a decisão já foi tomada e persistida pela `morph-p
|
|
|
139
147
|
- `.morph/framework/MORPH.md` — charter NLH completo
|
|
140
148
|
- `.morph/framework/MORPH.md` §2.1 — roteamento por tipo de trabalho (Passo 0)
|
|
141
149
|
- `framework/skills/core/morph-brainstorming/SKILL.md`
|
|
150
|
+
- `framework/skills/core/morph-uiux/SKILL.md` — invocada no passo 3a quando a feature toma o ramo uiux
|
|
142
151
|
- `framework/skills/core/morph-plan/SKILL.md`
|
|
143
152
|
- `framework/skills/core/morph-hotfix/SKILL.md` — pipeline invocado pelo branch `hotfix` do Passo 0
|
|
144
153
|
- `.morph/framework/MORPH.md` §5 — regras de pausa de gate (trust mode)
|
|
@@ -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.21.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-review
|
|
@@ -98,7 +98,8 @@ e o `recap.md` estar atualizado. Normalmente invocada pela skill orquestradora `
|
|
|
98
98
|
|
|
99
99
|
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
100
|
|
|
101
|
-
8. Apresente o Gate 3 segundo trust mode
|
|
101
|
+
8. Apresente o Gate 3 segundo trust mode — **única apresentação do gate**: `morph-apply` §5 aponta
|
|
102
|
+
para cá em vez de duplicar; ao devolver o controle a ela, o gate já está decidido.
|
|
102
103
|
|
|
103
104
|
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
105
|
|
|
@@ -109,7 +110,7 @@ e o `recap.md` estar atualizado. Normalmente invocada pela skill orquestradora `
|
|
|
109
110
|
|
|
110
111
|
Julgamento do revisor que nenhuma dessas chaves representa: use `gate-decision` direto em vez de `gate-check`.
|
|
111
112
|
|
|
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.
|
|
113
|
+
**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
114
|
|
|
114
115
|
**Se `pause === true`**, use `AskUserQuestion`:
|
|
115
116
|
|
|
@@ -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.21.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.21.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)
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: morph-uiux
|
|
3
|
+
description: Conduz a fase opcional de UI/UX — design system, mockups, componentes e fluxos — entre o Gate 1 e o plan, despachando a persona ui-designer para o trabalho visual.
|
|
4
|
+
version: core
|
|
5
|
+
when-to-invoke: ao tomar o ramo uiux (morph-spec advance --design), depois do Gate 1 e antes do morph-plan
|
|
6
|
+
user-invokable: true
|
|
7
|
+
cliVersion: "8.21.0"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# morph-uiux
|
|
11
|
+
|
|
12
|
+
## Objetivo
|
|
13
|
+
|
|
14
|
+
Produzir os artefatos de `1-design/` com qualidade de produção — boas práticas de UI/UX, usabilidade, consistência com o padrão visual do projeto, tecnologia de ponta do stack instalado — e apresentar o Gate uiux antes de entregar a feature ao `morph-plan`.
|
|
15
|
+
|
|
16
|
+
## Quando invocar
|
|
17
|
+
|
|
18
|
+
Ao tomar o ramo opcional uiux: feature/bug cuja mudança cria ou altera superfície de UI (componente, página, tela, estilo, fluxo de navegação) — critério objetivo em `MORPH.md` §2.1. Normalmente invocada pela `morph-proposal` logo após o Gate 1, via `morph-spec advance {feature} --design`. Sem essa condição a feature segue direto para `morph-plan` e esta skill nunca é chamada.
|
|
19
|
+
|
|
20
|
+
## O que fazer
|
|
21
|
+
|
|
22
|
+
1. **Garanta os insumos em contexto** — use a tool Read se não estiver:
|
|
23
|
+
- `.morph/features/{feature}/0-proposal/proposal.md` — problema, escopo, usuários e fluxos.
|
|
24
|
+
- `.morph/context/design-system.md` (se existir) — o design system **vivo** do projeto: toda decisão de token/componente parte dele, nunca do zero. Ausente → greenfield de design; use `.morph/framework/templates/context/design-system.md` como forma de partida.
|
|
25
|
+
- `.morph/config/config.json` → `project.stack` — decide a tecnologia de ponta a aplicar (`nextjs` → Tailwind + shadcn + Framer Motion; outro stack → o equivalente idiomático dele). Nunca hardcode Next.js quando o stack detectado é outro.
|
|
26
|
+
- `.morph/features/{feature}/0-proposal/stack-scan.md` (se existir) — desvios de stack já detectados.
|
|
27
|
+
|
|
28
|
+
2. **Princípios de qualidade** (decisão do produto — não são opcionais):
|
|
29
|
+
- **Usabilidade e acessibilidade:** WCAG AA, todos os estados de componente interativo cobertos (default/hover/focus/disabled/loading/error) — não só o caminho feliz.
|
|
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
|
+
- **Tecnologia de ponta condicionada ao stack real** (passo 1) — nunca a suposição de que o projeto é Next.js.
|
|
32
|
+
- **Sistemas, não telas isoladas** — mesmo critério da persona `ui-designer`: componentes reutilizáveis antes de composições de uso único.
|
|
33
|
+
|
|
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
|
+
|
|
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
|
+
|
|
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
|
+
```
|
|
40
|
+
Produzir os artefatos de UI/UX de [feature] em `.morph/features/{feature}/1-design/`.
|
|
41
|
+
|
|
42
|
+
Contexto: [problema/escopo do proposal.md] + design system atual
|
|
43
|
+
(`.morph/context/design-system.md`, tokens/componentes a reusar) + stack: [stack real do config.json]
|
|
44
|
+
|
|
45
|
+
Produza, NESTA ORDEM — design-system.md primeiro, os demais só como aplicável ao escopo:
|
|
46
|
+
1. `design-system.md` — tokens (cor, tipografia, espaço, motion) consistentes com o projeto
|
|
47
|
+
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
|
+
3. `components.md` — inventário de componentes novos/reusados, com props e os estados do
|
|
50
|
+
princípio 2 acima
|
|
51
|
+
4. `flows.md` — fluxos de navegação/interação entre as telas
|
|
52
|
+
|
|
53
|
+
Done quando: os artefatos aplicáveis existem e cada um cita os tokens/componentes do
|
|
54
|
+
design-system.md em vez de reinventar valores soltos.
|
|
55
|
+
|
|
56
|
+
Contrato do relatório final:
|
|
57
|
+
1. GRAVE um relatório por artefato produzido em
|
|
58
|
+
`1-design/reports/[artefato]-report.md` (ex.: `1-design/reports/design-system-report.md`)
|
|
59
|
+
ANTES de encerrar — é o retorno autoritativo, não a sua mensagem final (cortesia
|
|
60
|
+
best-effort, pode não chegar inteira). NÃO chame SendMessage.
|
|
61
|
+
2. Você não tem Bash — não rode `morph-spec`, build nem testes; a aprovação do Gate uiux
|
|
62
|
+
e qualquer comando CLI são do orquestrador.
|
|
63
|
+
3. NÃO toque em tasks.json, feature.json, state.json nem no board de sessão.
|
|
64
|
+
|
|
65
|
+
Cada relatório contém: (1) o que foi feito em 2-3 frases, (2) o artefato produzido,
|
|
66
|
+
(3) decisões de design e por quê (token reusado vs. novo, padrão de acessibilidade
|
|
67
|
+
aplicado), (4) auto-score 0-10 com justificativa em uma linha. Relatório ausente, oco,
|
|
68
|
+
ou sem os 4 itens, é falha de protocolo.
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
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
|
+
|
|
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): atualize `.morph/context/design-system.md` com a adição e uma entrada de changelog (data, 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
|
+
|
|
75
|
+
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
|
+
|
|
77
|
+
6. Apresente o Gate uiux.
|
|
78
|
+
|
|
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:
|
|
80
|
+
```
|
|
81
|
+
morph-spec gate-check {feature} uiux --signals '{"designSystemDivergence":true}'
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Se `pause === true`**, use `AskUserQuestion`:
|
|
85
|
+
```
|
|
86
|
+
question: "Gate uiux — Design de {feature} aprovado?{ reason ? ' Sinal: ' + reason : '' }"
|
|
87
|
+
header: "Gate uiux"
|
|
88
|
+
options:
|
|
89
|
+
- { label: "aprovado, prosseguir", description: "Aceitar design-system/mockups/components/flows e avançar para o plano" }
|
|
90
|
+
- { label: "preciso ajustar", description: "Apontar mudanças no design antes de prosseguir" }
|
|
91
|
+
- { label: "cancelar feature", description: "Abortar" }
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Aguardar resposta. Se "preciso ajustar", aplicar e reapresentar.
|
|
95
|
+
|
|
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
|
+
```
|
|
98
|
+
morph-spec approve {feature} uiux --approver <quem respondeu>
|
|
99
|
+
# ou, para já aprovar e criar 2-plan/ num passo só:
|
|
100
|
+
morph-spec advance {feature} --approver <quem respondeu>
|
|
101
|
+
```
|
|
102
|
+
(o `--approver` importa aqui: sem ele, num terminal não-interativo `advance`/`approve` resolvem `approvedBy: "auto"` — que MORPH.md §5 proíbe registrar quando quem aprovou foi um humano.)
|
|
103
|
+
|
|
104
|
+
**Se `pause === false`** (auto-aprovação, sem `AskUserQuestion`), exibir summary curto e já aprovar via CLI:
|
|
105
|
+
```
|
|
106
|
+
## Gate uiux (auto-aprovado)
|
|
107
|
+
|
|
108
|
+
**Design system:** {tokens novos, se houver} | **Mockups:** {N telas}
|
|
109
|
+
**Components:** {N novos / N reusados} | **Flows:** {N fluxos}
|
|
110
|
+
```
|
|
111
|
+
```
|
|
112
|
+
morph-spec advance {feature}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Os 4 outputs de `1-design/` (`protected: true, approvalGate: 'uiux'`) travam na aprovação — retrabalho de design depois do gate passa pelo gate de novo (revogar, ajustar, reapresentar), nunca por Edit direto no arquivo travado.
|
|
116
|
+
|
|
117
|
+
**Próximo passo (não é desta skill):** com o Gate uiux aprovado e `2-plan/` criado, devolva o controle a quem invocou (`morph-proposal`, passo 4/5) — ela invoca `Skill(morph-plan)`. Não invoque `morph-plan` diretamente daqui.
|
|
118
|
+
|
|
119
|
+
## Output esperado
|
|
120
|
+
|
|
121
|
+
- `.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
|
|
123
|
+
- `.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` atualizado (se tokens/componentes novos entraram) com entrada de changelog
|
|
125
|
+
- Gate uiux registrado aprovado em `.morph/features/{feature}/feature.json` (autoritativo)
|
|
126
|
+
|
|
127
|
+
## Referências
|
|
128
|
+
|
|
129
|
+
- `.morph/framework/MORPH.md` §2.1 — critério objetivo de entrada no ramo uiux
|
|
130
|
+
- `.morph/framework/MORPH.md` §6 — protocolo de dispatch e contrato do relatório final
|
|
131
|
+
- `.morph/framework/MORPH.md` §5 — regras de pausa de gate (trust mode)
|
|
132
|
+
- `.morph/framework/agents.json` — persona `ui-designer` (tools, MCPs, standards)
|
|
133
|
+
- `.morph/framework/templates/context/design-system.md` — forma de partida quando o projeto não tem design system vivo
|
|
134
|
+
- `framework/skills/core/morph-brainstorming/SKILL.md` — protocolo de reconciliação/changelog do design-system vivo (Parte 0), reaplicado no passo 4
|
|
135
|
+
- `framework/skills/core/morph-plan/SKILL.md` — consome os artefatos desta fase por path
|