@polymorphism-tech/morph-spec 6.0.0 → 7.0.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 +19 -18
- package/docs/CHEATSHEET.md +3 -3
- package/docs/QUICKSTART.md +4 -4
- package/framework/CLAUDE.md +13 -0
- package/framework/MORPH.md +57 -36
- package/framework/commands/morph-apply.md +4 -21
- package/framework/commands/morph-archive.md +1 -1
- package/framework/commands/morph-proposal.md +2 -0
- package/framework/hooks/claude-code/core/enforce-phase-writes.js +1 -1
- package/framework/hooks/claude-code/core/protect-spec-files.js +1 -1
- package/framework/hooks/claude-code/core/state-sync.js +212 -0
- package/framework/hooks/shared/phase-utils.js +5 -4
- package/framework/hooks/shared/state-reader.js +1 -1
- package/framework/phases.json +1 -1
- package/framework/rules/morph-workflow.md +15 -34
- package/framework/schemas/tasks.schema.json +35 -0
- package/framework/skills/core/morph-apply/SKILL.md +154 -0
- package/framework/skills/core/morph-brainstorming/SKILL.md +53 -30
- package/framework/skills/core/morph-implement/SKILL.md +25 -14
- package/framework/skills/core/morph-plan/SKILL.md +91 -23
- package/framework/skills/core/morph-proposal/SKILL.md +137 -0
- package/framework/skills/core/morph-review/SKILL.md +43 -7
- package/framework/skills/core/morph-stack-scan/SKILL.md +40 -1
- package/framework/standards/STANDARDS.json +4 -5
- package/framework/templates/docs/onboarding.md +4 -4
- package/framework/templates/tasks.template.json +17 -0
- package/package.json +1 -1
- package/src/commands/project/init.js +16 -0
- package/src/commands/validation/validate-feature.js +1 -1
- package/src/core/paths/output-schema.js +6 -6
- package/src/core/state/state-manager.js +1 -1
- package/src/lib/detectors/design-system-detector.js +1 -1
- package/src/lib/installers/memory-installer.js +138 -0
- package/src/lib/phase-chain/phase-validator.js +4 -4
- package/src/lib/risk-detector.js +80 -0
- package/src/lib/tasks/tasks-json-parser.js +185 -0
- package/src/scripts/setup-infra.js +25 -0
- package/src/utils/hooks-installer.js +59 -10
|
@@ -13,20 +13,18 @@ stacks:
|
|
|
13
13
|
|
|
14
14
|
**NEVER skip to code without a specification.** Every feature must progress through phases:
|
|
15
15
|
|
|
16
|
-
1. **Proposal** —
|
|
17
|
-
2. **Design** —
|
|
18
|
-
3. **Plan** —
|
|
19
|
-
4. **
|
|
20
|
-
5. **
|
|
21
|
-
|
|
22
|
-
UI-heavy features also include **UI/UX** phase (`1-ui/`) between Design and Tasks.
|
|
16
|
+
1. **Proposal** — Problem statement + acceptance criteria (`0-proposal/proposal.md`)
|
|
17
|
+
2. **Design** (optional, UI-heavy) — Design system + mockups + flows (`1-design/`)
|
|
18
|
+
3. **Plan** — Technical spec + mandate + tasks (`2-plan/spec.md`, `mandate.md`, `tasks.json`)
|
|
19
|
+
4. **Implement** — Code + recap (`3-implement/recap.md`)
|
|
20
|
+
5. **Review** — Review report + Gate 3 (`4-review/review-report.md`)
|
|
23
21
|
|
|
24
22
|
---
|
|
25
23
|
|
|
26
24
|
## Phase Sequence
|
|
27
25
|
|
|
28
26
|
```
|
|
29
|
-
proposal → [
|
|
27
|
+
proposal → [design] → plan → implement → review
|
|
30
28
|
```
|
|
31
29
|
|
|
32
30
|
Use `morph-spec status {feature}` to see current phase and pending approval gates.
|
|
@@ -52,25 +50,11 @@ Use `morph-spec status {feature}` to see current phase and pending approval gate
|
|
|
52
50
|
| `.morph/framework/` | **READ-ONLY** — framework files managed by morph-spec |
|
|
53
51
|
| `.morph/config/config.json` | Project configuration (editable) |
|
|
54
52
|
|
|
55
|
-
###
|
|
56
|
-
|
|
57
|
-
Use `morph-spec state mark-output <feature> <type>` with one of these exact type names:
|
|
53
|
+
### output types
|
|
58
54
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
| `schemaAnalysis` | design | `schema-analysis` |
|
|
63
|
-
| `spec` | design | — |
|
|
64
|
-
| `contracts` | design | — |
|
|
65
|
-
| `contractsVsa` | design | `contracts-vsa` |
|
|
66
|
-
| `decisions` | design | — |
|
|
67
|
-
| `plan` | plan | — |
|
|
68
|
-
| `tasks` | tasks | — |
|
|
69
|
-
| `uiDesignSystem` | uiux | `ui-design-system` |
|
|
70
|
-
| `uiMockups` | uiux | `ui-mockups` |
|
|
71
|
-
| `uiComponents` | uiux | `ui-components` |
|
|
72
|
-
| `uiFlows` | uiux | `ui-flows` |
|
|
73
|
-
| `recap` | implement | — |
|
|
55
|
+
Output types are defined in `src/core/paths/output-schema.js`. State sync is
|
|
56
|
+
handled automatically by the `state-sync.js` PostToolUse hook — the agent
|
|
57
|
+
does not need to call mark-output explicitly.
|
|
74
58
|
|
|
75
59
|
---
|
|
76
60
|
|
|
@@ -80,14 +64,11 @@ All outputs go in `.morph/features/{feature}/`:
|
|
|
80
64
|
|
|
81
65
|
| Phase | Path |
|
|
82
66
|
|-------|------|
|
|
83
|
-
| Proposal | `0-proposal/proposal.md` |
|
|
84
|
-
|
|
|
85
|
-
|
|
|
86
|
-
|
|
|
87
|
-
|
|
|
88
|
-
| Plan | `3-plan/plan.md` |
|
|
89
|
-
| Tasks | `4-tasks/tasks.md` |
|
|
90
|
-
| Recap | `5-implement/recap.md` |
|
|
67
|
+
| Proposal | `0-proposal/proposal.md`, `stack-scan.md`, `migration-plan.md` (optional) |
|
|
68
|
+
| Design (optional) | `1-design/design-system.md`, `mockups.md`, `components.md`, `flows.md` |
|
|
69
|
+
| Plan | `2-plan/spec.md`, `mandate.md`, `tasks.json`, `decisions.md` |
|
|
70
|
+
| Implement | `3-implement/recap.md` + source code |
|
|
71
|
+
| Review | `4-review/review-report.md` |
|
|
91
72
|
|
|
92
73
|
---
|
|
93
74
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "MORPH-SPEC tasks.json",
|
|
4
|
+
"description": "Structured task list for a morph-spec feature. Replaces tasks.md.",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": ["version", "feature", "tasks"],
|
|
7
|
+
"properties": {
|
|
8
|
+
"version": { "type": "string", "const": "1.0" },
|
|
9
|
+
"feature": { "type": "string", "minLength": 1 },
|
|
10
|
+
"tasks": {
|
|
11
|
+
"type": "array",
|
|
12
|
+
"items": {
|
|
13
|
+
"type": "object",
|
|
14
|
+
"required": ["id", "title", "description", "dependencies", "effort", "doneCriteria", "status"],
|
|
15
|
+
"properties": {
|
|
16
|
+
"id": { "type": "string", "pattern": "^T\\d+$" },
|
|
17
|
+
"title": { "type": "string", "minLength": 1 },
|
|
18
|
+
"description": { "type": "string", "minLength": 1 },
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"type": "array",
|
|
21
|
+
"items": { "type": "string", "pattern": "^T\\d+$" }
|
|
22
|
+
},
|
|
23
|
+
"effort": { "type": "string", "enum": ["S", "M", "L", "XL"] },
|
|
24
|
+
"doneCriteria": { "type": "string", "minLength": 1 },
|
|
25
|
+
"status": { "type": "string", "enum": ["pending", "in_progress", "done", "skipped", "blocked"] },
|
|
26
|
+
"outputs": { "type": "array", "items": { "type": "string" } },
|
|
27
|
+
"notes": { "type": "string" },
|
|
28
|
+
"group": { "type": "string", "enum": ["backend", "frontend", "tests", "infra", "docs"] }
|
|
29
|
+
},
|
|
30
|
+
"additionalProperties": false
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"additionalProperties": false
|
|
35
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: morph-apply
|
|
3
|
+
description: Orquestra a execução autônoma de tasks de uma feature morph-spec. Analisa DAG de dependências em tasks.json e decide adaptativamente entre execução sequencial (auto-advance) ou paralela (Agent dispatch). Termina com morph-review e Gate 3.
|
|
4
|
+
version: core
|
|
5
|
+
when-to-invoke: após Gate 2 aprovado, ao receber instrução "use /morph-apply" ou "implementar feature"
|
|
6
|
+
user-invokable: true
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# morph-apply
|
|
10
|
+
|
|
11
|
+
## Objetivo
|
|
12
|
+
|
|
13
|
+
Executar todas as tasks pendentes de uma feature até `done`, aplicando `morph-eval` após cada uma, e finalizar com `morph-review` + Gate 3.
|
|
14
|
+
|
|
15
|
+
## Quando invocar
|
|
16
|
+
|
|
17
|
+
- Após Gate 2 aprovado (verificar `.morph/state.json → features[X].approvalGates.plan === true`).
|
|
18
|
+
- Usuário pede "use /morph-apply {feature}" ou "implementar {feature}".
|
|
19
|
+
|
|
20
|
+
## Argumentos
|
|
21
|
+
|
|
22
|
+
- `{feature-name}` — nome da feature. Se ausente, usar a feature `in_progress` mais recente em `state.json`.
|
|
23
|
+
|
|
24
|
+
## Pré-condições
|
|
25
|
+
|
|
26
|
+
- `.morph/features/{feature}/2-plan/tasks.json` existe e é válido (schema check).
|
|
27
|
+
- `.morph/features/{feature}/2-plan/spec.md` e `mandate.md` existem.
|
|
28
|
+
- Gate 2 está marcado aprovado no state.json (ou trust:auto está ativo).
|
|
29
|
+
|
|
30
|
+
## Fluxo
|
|
31
|
+
|
|
32
|
+
### 1. Carregar contexto
|
|
33
|
+
|
|
34
|
+
- Ler `.morph/config/config.json → trust`.
|
|
35
|
+
- Parsear `tasks.json` via `src/lib/tasks/tasks-json-parser.js`:
|
|
36
|
+
```js
|
|
37
|
+
import { parseTasksJson, getReadyTasks, getPendingTasks, updateTaskStatus, writeTasksJson, groupTasks } from '../../../src/lib/tasks/tasks-json-parser.js';
|
|
38
|
+
const data = await parseTasksJson('.morph/features/{feature}/2-plan/tasks.json');
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 2. Análise de DAG — decisão sequencial vs paralelo
|
|
42
|
+
|
|
43
|
+
Construir o grafo de dependências e detectar subsets independentes.
|
|
44
|
+
|
|
45
|
+
**Regras de decisão:**
|
|
46
|
+
|
|
47
|
+
1. Se `data.tasks.length <= 3`: **sequencial** (overhead de Agent dispatch não compensa).
|
|
48
|
+
2. Identificar tasks **100% independentes** (`dependencies: []`):
|
|
49
|
+
- Se `>= 3` tasks independentes existem: dispachar essas em **paralelo**, depois cair em sequencial para o resto.
|
|
50
|
+
3. Caso contrário: **sequencial puro** com auto-advance.
|
|
51
|
+
|
|
52
|
+
Logar a decisão:
|
|
53
|
+
```
|
|
54
|
+
DAG analysis: 12 tasks, 4 independent → parallel batch (T1, T3, T7, T9) + sequential remainder
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 3a. Modo Sequencial (auto-advance)
|
|
58
|
+
|
|
59
|
+
Loop:
|
|
60
|
+
```
|
|
61
|
+
while (true):
|
|
62
|
+
ready = getReadyTasks(data)
|
|
63
|
+
if ready.length === 0:
|
|
64
|
+
break
|
|
65
|
+
|
|
66
|
+
task = ready[0]
|
|
67
|
+
updateTaskStatus(data, task.id, 'in_progress')
|
|
68
|
+
writeTasksJson(tasksPath, data)
|
|
69
|
+
|
|
70
|
+
invoke Skill(morph-implement) with task
|
|
71
|
+
|
|
72
|
+
result = invoke Skill(morph-eval) with implementation output
|
|
73
|
+
|
|
74
|
+
if result.score >= 8:
|
|
75
|
+
updateTaskStatus(data, task.id, 'done')
|
|
76
|
+
else:
|
|
77
|
+
// forçar pausa — qualidade é guardrail, trust não ignora aqui
|
|
78
|
+
AskUserQuestion: "Task {id} com score {score} — aceitar, reimplementar ou pular?"
|
|
79
|
+
options: [aceitar mesmo assim, reimplementar, pular task]
|
|
80
|
+
|
|
81
|
+
writeTasksJson(tasksPath, data)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 3b. Modo Paralelo (para o subset independente)
|
|
85
|
+
|
|
86
|
+
Para cada task independente:
|
|
87
|
+
```
|
|
88
|
+
dispatch Agent (subagent_type: "general-purpose") with prompt:
|
|
89
|
+
contexto: spec.md, mandate.md, task description completa, doneCriteria
|
|
90
|
+
instrução: |
|
|
91
|
+
Implemente esta task isoladamente. Não modifique spec.md, mandate.md.
|
|
92
|
+
Retorne:
|
|
93
|
+
- sumário das mudanças
|
|
94
|
+
- arquivos modificados (paths)
|
|
95
|
+
- auto-score 0-10 (rubric: completeness, correctness, mandate compliance)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Aguardar todos os agentes terminarem (Promise.all equivalente). Depois, sequencialmente:
|
|
99
|
+
- Para cada output retornado:
|
|
100
|
+
- Aplicar `Skill(morph-eval)`.
|
|
101
|
+
- Se score >= 8: marcar `done`.
|
|
102
|
+
- Se score < 8: marcar `pending` novamente com nota — será re-executada no modo sequencial.
|
|
103
|
+
|
|
104
|
+
Depois do batch paralelo, executar o restante em modo sequencial (passo 3a).
|
|
105
|
+
|
|
106
|
+
### 4. Conclusão de tasks
|
|
107
|
+
|
|
108
|
+
Quando `getPendingTasks(data).length === 0`:
|
|
109
|
+
|
|
110
|
+
- Invocar `Skill(morph-review)` para gerar `.morph/features/{feature}/4-review/review-report.md`.
|
|
111
|
+
- A skill morph-review chama `morph-eval` em escopo de feature inteira.
|
|
112
|
+
|
|
113
|
+
### 5. Gate 3 (trust-aware)
|
|
114
|
+
|
|
115
|
+
Sinais de risco para Gate 3:
|
|
116
|
+
|
|
117
|
+
- Score médio < 8 no review-report.
|
|
118
|
+
- Presença de erros não resolvidos.
|
|
119
|
+
- Mudanças incidentais em standards/.morph/framework/.
|
|
120
|
+
|
|
121
|
+
Mesma lógica do Gate 1/Gate 2 via `shouldPauseGate(config, signals)`:
|
|
122
|
+
|
|
123
|
+
- Pause: `AskUserQuestion` com options `["aprovado, fechar feature", "preciso ajustar", "rollback"]`.
|
|
124
|
+
- Auto: exibir summary do review-report e prosseguir.
|
|
125
|
+
|
|
126
|
+
### 6. Pós Gate 3
|
|
127
|
+
|
|
128
|
+
- Atualizar `state.features[feature].status = "completed"` via state-sync (hook detecta "aprovado" em AskUserQuestion answer).
|
|
129
|
+
- Sinalizar: "Feature {nome} concluída. Rode `/morph-archive {feature}` para arquivar."
|
|
130
|
+
- Não arquivar automaticamente.
|
|
131
|
+
|
|
132
|
+
## Anti-padrões
|
|
133
|
+
|
|
134
|
+
- Não dispachar paralelo se há deps cruzadas entre as tasks selecionadas (corrompe ordem).
|
|
135
|
+
- Não pular `morph-eval` — silêncio em score >= 8 é o sinal correto.
|
|
136
|
+
- Não reescrever spec.md/mandate.md durante implement (são read-only após Gate 2 — `protect-spec-files.js` hook bloqueia).
|
|
137
|
+
- Não dispachar mais que 4 agentes em paralelo (sobrecarga de contexto + custo).
|
|
138
|
+
|
|
139
|
+
## Output esperado
|
|
140
|
+
|
|
141
|
+
- Todas as tasks em `tasks.json` com status `done` ou `skipped`.
|
|
142
|
+
- `.morph/features/{feature}/3-implement/recap.md` produzido por morph-implement.
|
|
143
|
+
- `.morph/features/{feature}/4-review/review-report.md` produzido por morph-review.
|
|
144
|
+
- Gate 3 marcado aprovado em `.morph/state.json` (via state-sync hook ou Edit direto).
|
|
145
|
+
- `state.features[feature].status === "completed"`.
|
|
146
|
+
|
|
147
|
+
## Referências
|
|
148
|
+
|
|
149
|
+
- `.morph/framework/MORPH.md` — charter NLH
|
|
150
|
+
- `framework/skills/core/morph-implement/SKILL.md`
|
|
151
|
+
- `framework/skills/core/morph-eval/SKILL.md`
|
|
152
|
+
- `framework/skills/core/morph-review/SKILL.md`
|
|
153
|
+
- `src/lib/tasks/tasks-json-parser.js` — DAG queries (`getReadyTasks`, `getPendingTasks`)
|
|
154
|
+
- `src/lib/risk-detector.js` — `shouldPauseGate`
|
|
@@ -42,26 +42,22 @@ O harness conhece o stack por padrão. Não pergunte sobre tecnologia a menos qu
|
|
|
42
42
|
|
|
43
43
|
### Parte 2 — Detecção de contexto (greenfield vs brownfield)
|
|
44
44
|
|
|
45
|
-
2.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
3. Com base na varredura:
|
|
62
|
-
- **Se o projeto não existe ainda (greenfield):** siga direto para a Parte 3.
|
|
63
|
-
- **Se o projeto existe e segue o stack padrão:** siga para a Parte 3.
|
|
64
|
-
- **Se o projeto existe mas desvia do stack padrão:** gere um `migration-plan.md` em `.morph/features/{feature}/0-proposal/` listando o que migrar e em que ordem. Faça UMA pergunta via `AskUserQuestion`: "A migração de stack deve ser incluída nesta feature ou tratada numa feature separada?" Registre a decisão e siga para a Parte 3.
|
|
45
|
+
2. Invoque `Skill(morph-stack-scan)` para detectar contexto. A skill:
|
|
46
|
+
- Curto-circuita em projetos greenfield (sem source files) — retorna relatório vazio.
|
|
47
|
+
- Em brownfield, varre stack atual (.csproj, package.json, migrations), padrões (Guid.NewGuid vs Guid.CreateVersion7, sealed, result pattern), features existentes.
|
|
48
|
+
- Produz `.morph/features/{feature}/0-proposal/stack-scan.md`.
|
|
49
|
+
|
|
50
|
+
3. Reconciliação de design-system (se aplicável):
|
|
51
|
+
- Comparar `.morph/context/design-system.md` (se existir) com o que foi detectado no stack-scan e com bundles/mocks recentes do usuário.
|
|
52
|
+
- Se houver **divergência** (tokens diferentes, framework version mismatch, fonte aprovada distinta):
|
|
53
|
+
- Marcar `signals.designSystemDivergence = true` no contexto da feature.
|
|
54
|
+
- Perguntar ao usuário via `AskUserQuestion` qual fonte usar, listando as fontes detectadas como options.
|
|
55
|
+
- Atualizar `.morph/context/design-system.md` com a fonte escolhida + entrada de changelog (data, motivo).
|
|
56
|
+
|
|
57
|
+
4. Com base no relatório:
|
|
58
|
+
- **Greenfield:** seguir para a Parte 3.
|
|
59
|
+
- **Stack padrão:** seguir para a Parte 3.
|
|
60
|
+
- **Desvio de stack:** gerar `migration-plan.md` em `.morph/features/{feature}/0-proposal/`. Perguntar via `AskUserQuestion`: "A migração de stack deve ser incluída nesta feature ou tratada numa feature separada?" Registrar decisão e seguir.
|
|
65
61
|
|
|
66
62
|
### Parte 3 — Produção do proposal.md
|
|
67
63
|
|
|
@@ -76,21 +72,46 @@ O harness conhece o stack por padrão. Não pergunte sobre tecnologia a menos qu
|
|
|
76
72
|
|
|
77
73
|
Um bom proposal.md tem no máximo 2 páginas. Se está crescendo além disso, o escopo precisa ser cortado.
|
|
78
74
|
|
|
79
|
-
5. Apresente o Gate 1
|
|
75
|
+
5. Apresente o Gate 1 segundo trust mode.
|
|
76
|
+
|
|
77
|
+
Ler `.morph/config/config.json → trust` (default `"auto"`). Calcular sinais de risco via `src/lib/risk-detector.js`:
|
|
78
|
+
|
|
79
|
+
```js
|
|
80
|
+
import { shouldPauseGate, getRiskSignals } from '../../../src/lib/risk-detector.js';
|
|
81
|
+
const signals = {
|
|
82
|
+
designSystemDivergence: /* from passo 3 */,
|
|
83
|
+
standardsViolations: /* lista de violações detectadas */,
|
|
84
|
+
};
|
|
85
|
+
const { pause, reason } = shouldPauseGate(config, signals);
|
|
86
|
+
const riskList = getRiskSignals(signals);
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Se `pause === true`** (manual mode OU risco detectado em auto), use `AskUserQuestion`:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
question: "Gate 1 — Proposta de {nome} aprovada?{ reason ? ' Sinal de risco: ' + reason : '' }"
|
|
93
|
+
header: "Gate 1"
|
|
94
|
+
options:
|
|
95
|
+
- { label: "aprovado, prosseguir", description: "Aceitar a proposta e avançar para o planejamento" }
|
|
96
|
+
- { label: "preciso ajustar", description: "Apontar mudanças necessárias antes de prosseguir" }
|
|
97
|
+
- { label: "cancelar feature", description: "Abortar — feature não vai avançar" }
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Aguardar resposta. Se "preciso ajustar", aplique e reapresente.
|
|
101
|
+
|
|
102
|
+
**Se `pause === false`** (auto-aprovação), exibir summary curto e prosseguir sem aguardar:
|
|
80
103
|
|
|
81
104
|
```
|
|
82
|
-
## Gate 1
|
|
105
|
+
## Gate 1 (auto-aprovado)
|
|
83
106
|
|
|
84
107
|
**Feature:** {nome}
|
|
85
108
|
**Problema:** {1 frase}
|
|
86
|
-
**Escopo:** {incluído} | Excluído: {exclusões
|
|
87
|
-
**Stack:** {
|
|
88
|
-
**Riscos:** {principal
|
|
89
|
-
|
|
90
|
-
Aprovado? Responda "aprovado" para avançar para o planejamento.
|
|
109
|
+
**Escopo:** {incluído} | Excluído: {exclusões}
|
|
110
|
+
**Stack:** {compliance}
|
|
111
|
+
**Riscos:** {principal} (sinais detectados: nenhum)
|
|
91
112
|
```
|
|
92
113
|
|
|
93
|
-
|
|
114
|
+
O hook state-sync.js detecta a aprovação automaticamente. Em modo auto sem AskUserQuestion, a skill atualiza `.morph/state.json` via Edit direto (allowlist permite — ver settings.local.json).
|
|
94
115
|
|
|
95
116
|
## Output esperado
|
|
96
117
|
- `.morph/features/{feature}/0-proposal/proposal.md` — proposta aprovada
|
|
@@ -98,5 +119,7 @@ O harness conhece o stack por padrão. Não pergunte sobre tecnologia a menos qu
|
|
|
98
119
|
- Gate 1 apresentado e aprovado
|
|
99
120
|
|
|
100
121
|
## Referências
|
|
101
|
-
-
|
|
102
|
-
-
|
|
122
|
+
- `.morph/framework/MORPH.md` — seções 1 (Papéis), 2 (Fases), 5 (Gates), Trust Mode
|
|
123
|
+
- `.morph/framework/standards/STANDARDS.json` — para referência de standards relevantes à stack
|
|
124
|
+
- `framework/skills/core/morph-stack-scan/SKILL.md` — invocada na Parte 2
|
|
125
|
+
- `src/lib/risk-detector.js` — `shouldPauseGate(config, signals)` para Gate 1
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: morph-implement
|
|
3
3
|
description: Guia a execução de cada tarefa de implementação com standard e persona adequados
|
|
4
4
|
version: core
|
|
5
|
-
when-to-invoke: ao iniciar cada
|
|
5
|
+
when-to-invoke: ao iniciar cada task de implementação listada em tasks.json
|
|
6
6
|
user-invokable: false
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -13,7 +13,7 @@ Garantir que cada tarefa seja executada com o standard correto, a persona de age
|
|
|
13
13
|
e que o resultado seja registrado no recap.md ao final.
|
|
14
14
|
|
|
15
15
|
## Quando invocar
|
|
16
|
-
Ao iniciar cada
|
|
16
|
+
Ao iniciar cada task de `tasks.json` — antes de escrever qualquer código. Normalmente invocada pela skill orquestradora `morph-apply`, que passa o objeto da task atual.
|
|
17
17
|
|
|
18
18
|
## O que fazer
|
|
19
19
|
|
|
@@ -29,21 +29,21 @@ Ao iniciar cada tarefa do tasks.md — antes de escrever qualquer código.
|
|
|
29
29
|
- Consulte `framework/agents.json` — encontre o agente cujo `domains` cobre o domínio da tarefa.
|
|
30
30
|
- Leia o campo `persona` do agente e adote esse ponto de vista durante a implementação.
|
|
31
31
|
|
|
32
|
-
4. Avalie se a
|
|
33
|
-
- Duração estimada > 5 minutos
|
|
32
|
+
4. Avalie se a task se qualifica para sub-agent dispatch (ver critérios em `.morph/framework/MORPH.md` seção 6):
|
|
33
|
+
- Duração estimada > 5 minutos (effort L ou XL)
|
|
34
34
|
- Mais de 3 tentativas de correção falharam no mesmo problema
|
|
35
35
|
- Análise de arquivo com > 500 linhas
|
|
36
|
-
-
|
|
36
|
+
- Task repetitiva com > 3 instâncias do mesmo padrão
|
|
37
37
|
- Risco de contaminar o contexto principal com detalhes de baixo nível irrelevantes para o fluxo
|
|
38
38
|
|
|
39
39
|
**Se sim — despache sub-agent com este template:**
|
|
40
40
|
```
|
|
41
|
-
Implementar [ID
|
|
41
|
+
Implementar [ID]: [title da task]
|
|
42
42
|
|
|
43
|
-
Spec: [
|
|
43
|
+
Spec: [description completa do tasks.json]
|
|
44
44
|
Standard: [path do .md do standard identificado no passo 2]
|
|
45
|
-
Arquivos relevantes: [lista de paths
|
|
46
|
-
Done quando: [
|
|
45
|
+
Arquivos relevantes: [lista de paths]
|
|
46
|
+
Done quando: [doneCriteria do tasks.json]
|
|
47
47
|
|
|
48
48
|
Retorne APENAS: (1) o que foi feito em 2-3 frases, (2) arquivos modificados,
|
|
49
49
|
(3) problemas encontrados e como foram resolvidos, (4) auto-score 0-10.
|
|
@@ -69,15 +69,26 @@ Ao iniciar cada tarefa do tasks.md — antes de escrever qualquer código.
|
|
|
69
69
|
- Deixe `eval_score` e `eval_dimensions` como `null` — serão preenchidos pelo morph-eval
|
|
70
70
|
- Se esta for a última tarefa da fase, preencha `completed_at`
|
|
71
71
|
|
|
72
|
-
8.
|
|
72
|
+
8. Atualizar `tasks.json` marcando a task como `done` via `updateTaskStatus`:
|
|
73
|
+
|
|
74
|
+
```js
|
|
75
|
+
import { parseTasksJson, updateTaskStatus, writeTasksJson, getReadyTasks } from '../../../src/lib/tasks/tasks-json-parser.js';
|
|
76
|
+
const data = await parseTasksJson(tasksPath);
|
|
77
|
+
updateTaskStatus(data, task.id, 'done');
|
|
78
|
+
await writeTasksJson(tasksPath, data);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
9. Quando invocada por `morph-apply`, retornar o controle à skill orquestradora — ela decide qual task vem em seguida via `getReadyTasks(data)`. Quando invocada manualmente, verificar se há próxima task ready e iniciá-la imediatamente aplicando esta skill desde o passo 1 (auto-advance). Pause apenas se encontrar ambiguidade bloqueante não coberta pelo mandate.
|
|
73
82
|
|
|
74
83
|
## Output esperado
|
|
75
84
|
- Código implementado conforme o standard consultado (direto ou via sub-agent)
|
|
76
|
-
- `.morph/features/{feature}/3-implement/recap.md` atualizado com entrada da
|
|
85
|
+
- `.morph/features/{feature}/3-implement/recap.md` atualizado com entrada da task concluída
|
|
86
|
+
- `.morph/features/{feature}/2-plan/tasks.json` com status da task atualizado para `done`
|
|
77
87
|
- `.morph/features/{feature}/2-plan/decisions.md` atualizado se houver decisão não trivial
|
|
78
88
|
|
|
79
89
|
## Referências
|
|
80
|
-
-
|
|
81
|
-
-
|
|
82
|
-
-
|
|
90
|
+
- `.morph/framework/standards/STANDARDS.json` — índice de standards (não carregue todos — filtre por task)
|
|
91
|
+
- `.morph/framework/agents.json` — personas dos agentes por domínio
|
|
92
|
+
- `.morph/framework/MORPH.md` seção 6 — critérios de dispatch e contrato de retorno do sub-agent
|
|
83
93
|
- `.morph/features/{feature}/2-plan/mandate.md` — contrato da feature
|
|
94
|
+
- `src/lib/tasks/tasks-json-parser.js` — `parseTasksJson`, `updateTaskStatus`, `writeTasksJson`
|
|
@@ -1,64 +1,132 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: morph-plan
|
|
3
|
-
description: Guia a produção dos três artefatos de planejamento de uma feature
|
|
3
|
+
description: Guia a produção dos três artefatos de planejamento de uma feature (spec.md, mandate.md, tasks.json) e apresenta o Gate 2 trust-aware.
|
|
4
4
|
version: core
|
|
5
|
-
when-to-invoke: ao iniciar a fase plan de uma feature, após o
|
|
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
7
|
---
|
|
8
8
|
|
|
9
9
|
# morph-plan
|
|
10
10
|
|
|
11
11
|
## Objetivo
|
|
12
|
-
|
|
12
|
+
|
|
13
|
+
Produzir `spec.md`, `mandate.md` e `tasks.json` com qualidade suficiente para abrir o Gate 2.
|
|
13
14
|
Os três artefatos juntos definem o quê, o como e o quanto da feature.
|
|
14
15
|
|
|
15
16
|
## Quando invocar
|
|
16
|
-
|
|
17
|
+
|
|
18
|
+
Ao iniciar a fase plan — após o `proposal.md` ser aprovado e antes de qualquer implementação. Normalmente invocada pela skill orquestradora `morph-proposal`.
|
|
17
19
|
|
|
18
20
|
## O que fazer
|
|
19
21
|
|
|
20
22
|
1. Leia o `proposal.md` em `.morph/features/{feature}/0-proposal/` para entender escopo e critérios de aceite.
|
|
23
|
+
|
|
21
24
|
2. Produza `spec.md` em `.morph/features/{feature}/2-plan/`:
|
|
22
25
|
- Arquitetura da solução: quais componentes, como se conectam, fluxos de dados principais.
|
|
23
26
|
- Edge cases identificados e como serão tratados.
|
|
24
27
|
- Integrações externas e contratos esperados.
|
|
28
|
+
|
|
25
29
|
3. Produza `mandate.md` em `.morph/features/{feature}/2-plan/`:
|
|
26
|
-
- Stack exata do projeto (leia
|
|
27
|
-
- Standards obrigatórios: liste os IDs relevantes de
|
|
30
|
+
- Stack exata do projeto (leia de `.morph/config/config.json` → `project.stack` ou do CLAUDE.md).
|
|
31
|
+
- Standards obrigatórios: liste os IDs relevantes de `.morph/framework/standards/STANDARDS.json`.
|
|
28
32
|
- Patterns proibidos — inclua sempre os defaults abaixo mais qualquer específico da feature:
|
|
29
33
|
- `Guid.NewGuid()` → usar `Guid.CreateVersion7()`
|
|
30
34
|
- Classes não-sealed sem justificativa documentada
|
|
31
35
|
- Exceptions como fluxo de controle → usar result pattern com `result.Match()`
|
|
32
36
|
- Repository pattern / `IRepository<T>` → handlers VSA acessam DbContext diretamente
|
|
33
37
|
- Checklist de done com critérios verificáveis por tarefa.
|
|
34
|
-
4. Produza `tasks.md` em `.morph/features/{feature}/2-plan/`:
|
|
35
|
-
- Liste cada tarefa com ID único (T1, T2...).
|
|
36
|
-
- Para cada tarefa: descrição, dependências, estimativa de esforço, critério de done.
|
|
37
|
-
- Ordene por dependências — tarefas sem dependências primeiro.
|
|
38
|
-
5. Apresente o Gate 2 ao usuário usando exatamente este formato:
|
|
39
38
|
|
|
39
|
+
4. Produza `tasks.json` em `.morph/features/{feature}/2-plan/` seguindo o schema em `.morph/framework/schemas/tasks.schema.json`.
|
|
40
|
+
|
|
41
|
+
**Formato obrigatório** (validado pelo parser em `src/lib/tasks/tasks-json-parser.js`):
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"version": "1.0",
|
|
46
|
+
"feature": "{feature-name}",
|
|
47
|
+
"tasks": [
|
|
48
|
+
{
|
|
49
|
+
"id": "T1",
|
|
50
|
+
"title": "Título curto",
|
|
51
|
+
"description": "Detalhes — o que esta task realiza e por quê",
|
|
52
|
+
"dependencies": [],
|
|
53
|
+
"effort": "S",
|
|
54
|
+
"doneCriteria": "Critério verificável em 1 frase",
|
|
55
|
+
"status": "pending",
|
|
56
|
+
"outputs": [],
|
|
57
|
+
"group": "backend"
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
}
|
|
40
61
|
```
|
|
41
|
-
## Gate 2 — Plano pronto para revisão
|
|
42
62
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
63
|
+
Regras:
|
|
64
|
+
- `id` segue padrão `T\d+` (T1, T2, T10...).
|
|
65
|
+
- `dependencies` lista outros IDs Tn. Tasks sem deps tem `[]`.
|
|
66
|
+
- `effort`: S (≤30min), M (≤1h), L (≤2h), XL (>2h).
|
|
67
|
+
- `status` inicia sempre como `pending`.
|
|
68
|
+
- `group` (opcional): backend, frontend, tests, infra, docs. Default backend.
|
|
69
|
+
- `outputs` (opcional): array de paths que serão criados/modificados.
|
|
46
70
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
{
|
|
71
|
+
Antes de retornar, validar com:
|
|
72
|
+
```js
|
|
73
|
+
import { validateTasksJson, writeTasksJson } from '../../../src/lib/tasks/tasks-json-parser.js';
|
|
74
|
+
const { valid, errors } = validateTasksJson(data);
|
|
75
|
+
if (!valid) throw new Error(errors.join('\n'));
|
|
76
|
+
await writeTasksJson(tasksPath, data);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
5. Apresente o Gate 2 segundo trust mode.
|
|
80
|
+
|
|
81
|
+
Ler `.morph/config/config.json → trust` (default `"auto"`). Calcular sinais de risco:
|
|
50
82
|
|
|
51
|
-
|
|
83
|
+
```js
|
|
84
|
+
import { shouldPauseGate, getRiskSignals } from '../../../src/lib/risk-detector.js';
|
|
85
|
+
const signals = {
|
|
86
|
+
taskCount: data.tasks.length,
|
|
87
|
+
designSystemDivergence: /* herdado do brainstorming */,
|
|
88
|
+
standardsViolations: /* detectado em mandate */,
|
|
89
|
+
};
|
|
90
|
+
const { pause, reason } = shouldPauseGate(config, signals);
|
|
52
91
|
```
|
|
53
92
|
|
|
54
|
-
|
|
93
|
+
**Se `pause === true`**, use `AskUserQuestion`:
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
question: "Gate 2 — Plano de {feature} aprovado?{ reason ? ' Sinal: ' + reason : '' }"
|
|
97
|
+
header: "Gate 2"
|
|
98
|
+
options:
|
|
99
|
+
- { label: "aprovado, prosseguir", description: "Aceitar spec/mandate/tasks e habilitar /morph-apply" }
|
|
100
|
+
- { label: "preciso ajustar", description: "Apontar mudanças no plano antes de prosseguir" }
|
|
101
|
+
- { label: "cancelar feature", description: "Abortar" }
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Aguardar resposta. Se "preciso ajustar", aplicar e reapresentar.
|
|
105
|
+
|
|
106
|
+
**Se `pause === false`** (auto-aprovação), exibir summary curto:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
## Gate 2 (auto-aprovado)
|
|
110
|
+
|
|
111
|
+
**Spec:** {1 frase} → {1 frase da solução}
|
|
112
|
+
**Mandate:** Stack: {stack} | Standards: {N obrigatórios} | Proibido: {N padrões}
|
|
113
|
+
**Tasks:** {N} | Esforço total: {soma} | Caminho crítico: {IDs sem deps paralelas}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
O hook state-sync registra a aprovação automaticamente em answers de AskUserQuestion. Em auto sem AskUserQuestion, a skill edita `state.json` diretamente.
|
|
55
117
|
|
|
56
118
|
## Output esperado
|
|
119
|
+
|
|
57
120
|
- `.morph/features/{feature}/2-plan/spec.md` — especificação técnica completa
|
|
58
121
|
- `.morph/features/{feature}/2-plan/mandate.md` — contrato de implementação
|
|
59
|
-
- `.morph/features/{feature}/2-plan/tasks.
|
|
122
|
+
- `.morph/features/{feature}/2-plan/tasks.json` — task list estruturada válida contra schema
|
|
123
|
+
- Gate 2 marcado aprovado em `state.json`
|
|
60
124
|
|
|
61
125
|
## Referências
|
|
62
|
-
|
|
63
|
-
-
|
|
126
|
+
|
|
127
|
+
- `.morph/framework/MORPH.md` — seções 2 (Fases), 3 (Contratos de Output), 5 (Gates), Trust Mode
|
|
128
|
+
- `.morph/framework/standards/STANDARDS.json` — para identificar standards relevantes ao mandate
|
|
129
|
+
- `.morph/framework/schemas/tasks.schema.json` — schema obrigatório de tasks.json
|
|
64
130
|
- `.morph/features/{feature}/0-proposal/proposal.md` — escopo da feature
|
|
131
|
+
- `src/lib/tasks/tasks-json-parser.js` — `validateTasksJson`, `writeTasksJson`
|
|
132
|
+
- `src/lib/risk-detector.js` — `shouldPauseGate`, `getRiskSignals`
|