@spec-wave/cli 0.13.0 → 0.14.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 +39 -6
- package/bin/spec-wave.mjs +14 -1
- package/package.json +1 -1
- package/src/commands/code-review.mjs +5 -8
- package/src/commands/decompose.mjs +412 -130
- package/src/commands/dev-agent.mjs +3 -2
- package/src/commands/doctor.mjs +239 -9
- package/src/commands/generate-plan.mjs +105 -30
- package/src/commands/generate-spec.mjs +17 -5
- package/src/commands/implement.mjs +39 -15
- package/src/commands/info.mjs +4 -3
- package/src/commands/issue.mjs +4 -4
- package/src/commands/move.mjs +162 -0
- package/src/commands/order.mjs +1 -12
- package/src/commands/qa.mjs +5 -8
- package/src/commands/refresh.mjs +4 -3
- package/src/commands/story.mjs +1 -12
- package/src/commands/task.mjs +1 -11
- package/src/commands/update.mjs +43 -19
- package/src/commands/validate.mjs +37 -22
- package/src/config.mjs +40 -1
- package/src/lib/board.mjs +88 -26
- package/src/lib/claude.mjs +315 -70
- package/src/lib/critique.mjs +391 -91
- package/src/lib/decomposition-doc.mjs +451 -0
- package/src/lib/implement-board.mjs +14 -1
- package/src/lib/project-root.mjs +93 -0
- package/src/lib/templates.mjs +53 -0
- package/src/setup/files.mjs +3 -10
- package/src/templates/skill/SKILL.md +143 -27
- package/src/templates/workflows/code-review.yml +1 -1
- package/src/templates/workflows/decompose.yml +20 -6
- package/src/templates/workflows/generate-plan.yml +1 -1
- package/src/templates/workflows/generate-spec.yml +1 -1
- package/src/templates/workflows/qa.yml +1 -1
- package/src/templates/workflows/validate.yml +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: spec-wave
|
|
3
3
|
description: "Use when the user wants to set up a spec-driven GitHub workflow, create a Feature issue, generate spec.md or plan.md, decompose a Feature into Stories/Tasks, write RFC documentation, or audit and fix a Pull Request. Implements the RFC-001 workflow with GitHub Projects v2, labels, and AI-powered GitHub Actions."
|
|
4
|
-
argument-hint: "[info|setup|update|doctor|issue|feature|spec|plan|ready|decompose|order|implement|task|story|uninstall|rfc|fix-pr] [target]"
|
|
4
|
+
argument-hint: "[info|setup|update|doctor|issue|feature|spec|plan|ready|decompose|order|implement|task|story|move|uninstall|rfc|fix-pr] [target]"
|
|
5
5
|
user-invocable: true
|
|
6
6
|
allowed-tools:
|
|
7
7
|
- Bash(npx @spec-wave/cli@latest *)
|
|
@@ -87,24 +87,30 @@ Essa é a sequência completa, mas **cada tipo de artefato percorre só um trech
|
|
|
87
87
|
|----------|----------|----------|-------------|
|
|
88
88
|
| **Initiative / Epic** | 📥 Backlog | — | Agrupadores. Não têm fluxo próprio; acompanham os filhos. |
|
|
89
89
|
| **Feature** | 📥 Backlog | 🎯 Priorizado → 📋 Spec → 📋 Plan → ✅ Ready → 🚧 Desenvolvimento → 👀 Code Review → 🧪 QA → 📋 Homologação → 🚀 Deploy → 🎉 Done | Fica parada em **✅ Ready** esperando um dev assumir — é ali que ela aparece na fila do TL. Só avança para 👀 Code Review quando **TODAS** as suas Stories já estiverem lá. |
|
|
90
|
-
| **Story** | **✅ Ready** (criada pelo `decompose`) | 🚧 Desenvolvimento → 👀 Code Review → 🧪 QA → 📋 Homologação → 🎉 Done | **Nunca nasce em 📥 Backlog.** |
|
|
91
|
-
| **Task** | **✅ Ready** (criada pelo `decompose`) | 🚧 Desenvolvimento → 🎉 Done | **Não** passa por Code Review, QA nem Homologação — só `task start` e `task done`. |
|
|
90
|
+
| **Story** | **✅ Ready** (criada pelo `decompose-apply`) | 🚧 Desenvolvimento → 👀 Code Review → 🧪 QA → 📋 Homologação → 🎉 Done | **Nunca nasce em 📥 Backlog.** |
|
|
91
|
+
| **Task** | **✅ Ready** (criada pelo `decompose-apply`) | 🚧 Desenvolvimento → 🎉 Done | **Não** passa por Code Review, QA nem Homologação — só `task start` e `task done`. |
|
|
92
92
|
| **RFC** | 📥 Backlog | decompõe direto em **Tasks** (que nascem em ✅ Ready) | Não usa spec/plan. |
|
|
93
93
|
| **Bug** | 📥 Backlog | 🚧 Desenvolvimento → 🎉 Done | Ao aprovar, vai direto para Done (não passa por Homologação). |
|
|
94
94
|
| **Spike** | 📥 Backlog | **movido só à mão pelo usuário** | Nunca avance a Etapa de um Spike por conta própria. |
|
|
95
95
|
|
|
96
|
-
**Regra da Etapa:** a Etapa **só avança, nunca retrocede**. O campo **Status** (Todo / In Progress / Done) mede o progresso *dentro* da Etapa e reinicia a cada avanço. Prefira sempre os comandos da CLI (`task start|done`, `story review`) a mutações manuais no board — eles embutem essas regras.
|
|
96
|
+
**Regra da Etapa:** a Etapa **só avança, nunca retrocede**. O campo **Status** (Todo / In Progress / Done) mede o progresso *dentro* da Etapa e reinicia a cada avanço. Prefira sempre os comandos da CLI (`move`, `task start|done`, `story review`) a mutações manuais no board — eles embutem essas regras.
|
|
97
97
|
|
|
98
98
|
Labels de gatilho:
|
|
99
99
|
- `spec-wave:spec` → dispara `generate-spec.yml` → gera `spec.md` (especificação funcional, primeiro)
|
|
100
100
|
- `spec-wave:plan` → dispara `generate-plan.yml` → gera `plan.md` (plano técnico, a partir da spec)
|
|
101
101
|
- `spec-wave:ready` → dispara `validate.yml` → valida ambos os arquivos
|
|
102
|
-
- `spec-wave:decompose` → dispara `decompose.yml` → gera
|
|
102
|
+
- `spec-wave:decompose` → dispara `decompose.yml` → gera (ou **re-critica**) o **rascunho** em `decomposition.md`. **Não cria issue nenhuma.**
|
|
103
|
+
- `spec-wave:decompose-apply` → dispara o mesmo workflow em modo aplicação → cria as Stories e Tasks **a partir do rascunho revisado**
|
|
103
104
|
|
|
104
105
|
Labels de **estado** (gravadas pelas automações — **não** são gatilhos, não as adicione por conta própria):
|
|
105
|
-
- `spec-wave:
|
|
106
|
+
- `spec-wave:decompose-ready` → o rascunho da decomposição passou pela crítica e espera **revisão humana**; aplique `spec-wave:decompose-apply` para criar as issues
|
|
107
|
+
- `spec-wave:critique-failed` → a crítica adversarial apontou contradições **graves**; **bloqueia** o `spec-wave:ready` até ser removida (veja *Crítica adversarial* abaixo)
|
|
108
|
+
- `spec-wave:needs-human` → a crítica reprovou N vezes seguidas (default 3); **para o fluxo** até uma pessoa revisar e remover a label
|
|
106
109
|
- `spec-wave:decomposed` → a Feature/RFC já foi decomposta; o `decompose` pula silenciosamente enquanto ela existir (veja *Guard de idempotência* abaixo)
|
|
107
110
|
|
|
111
|
+
Label **modificadora** (esta você pode aplicar):
|
|
112
|
+
- `spec-wave:model:<apelido>` → força um modelo específico **naquela execução**, resolvido por `ai.modelAliases` no `.spec-wave.json`. Serve para reprocessar um caso difícil num modelo mais forte sem editar a configuração do repositório inteiro. Duas dessas labels na mesma issue = ambíguo, nenhuma vale.
|
|
113
|
+
|
|
108
114
|
A etapa **🚧 Desenvolvimento** é coberta pelo comando **local** `npx @spec-wave/cli@latest implement <número>` (não é uma label/Action): lê uma **Feature** (todas as Stories pendentes, em ordem de dependência), uma Story ou uma Task e aciona o spec-kit para implementar. Veja `/spec-wave implement`.
|
|
109
115
|
|
|
110
116
|
---
|
|
@@ -183,6 +189,7 @@ Mesmas flags do `issue` (exceto `--type`, fixo em `feature`). Mantido para o flu
|
|
|
183
189
|
| Flag | Tipo | Descrição |
|
|
184
190
|
|------|------|-----------|
|
|
185
191
|
| `--issue-number <n>` | string (obrigatório) | Número da issue no GitHub. |
|
|
192
|
+
| `--apply` | flag (só `decompose`) | Cria as issues a partir do `decomposition.md` revisado. **Sem** a flag, o `decompose` apenas gera/critica o rascunho e não cria nada. |
|
|
186
193
|
|
|
187
194
|
> ⚠️ Esses quatro comandos são executados pelos **GitHub Actions** (disparados por labels), **não** pela skill diretamente. Veja a *Regra fundamental*: para gerar plan/spec/decompor, adicione a **label** correspondente — não rode o comando à mão (a não ser para debug local).
|
|
188
195
|
>
|
|
@@ -195,12 +202,12 @@ Mesmas flags do `issue` (exceto `--type`, fixo em `feature`). Mantido para o flu
|
|
|
195
202
|
|----------|------|-----------|
|
|
196
203
|
| `<issue>` | string (obrigatório) | Número da issue (Feature, Story ou Task), ex.: `12` ou `#12`. Argumento posicional. |
|
|
197
204
|
| `--feature-dir <path>` | string | Caminho `docs/features/<slug>` para anexar `spec.md`/`plan.md` como contexto (sobrescreve a resolução automática). |
|
|
198
|
-
| `--dry-run` | flag | Monta o contexto e imprime o comando do spec-kit **sem executar
|
|
205
|
+
| `--dry-run` | flag | Monta o contexto e imprime o comando do spec-kit **sem executar** e **sem escrever nada no GitHub** (não move cards, não adiciona itens ao Project). |
|
|
199
206
|
|
|
200
207
|
> Diferente dos quatro acima, `implement` roda **localmente** (lê `.spec-wave.json`, como `issue`), não por Action. Detecta o tipo da issue: **Feature** → lista as Stories (sub-issues), **ordena topologicamente pelas dependências** (`Depende de:` + *blocked by*), **pula** as já em 👀 Code Review+ (listadas no contexto como "não tocar") e monta **um único** contexto com todas as pendentes (cada uma com suas Tasks), acionando o spec-kit **uma vez** com `{issue}/{type}/{title}` da Feature — **ciclo de dependências entre Stories pendentes aborta o comando (exit 1)**; **Story** → coleta todas as Tasks (sub-issues) e aciona o spec-kit uma única vez; **Task** → só aquela task. Monta o contexto em `.spec-wave/implement-<n>.md` e chama o comando configurado em `specKit.command` (no `.spec-wave.json`) ou na env `SPEC_WAVE_IMPLEMENT_CMD`. Placeholders disponíveis no template: `{tasksFile} {specFile} {planFile} {issue} {type} {title}`. Se nada estiver configurado, ele apenas monta o contexto e mostra como configurar (não executa). O contexto inclui os **comentários da issue**, um **digest do código recente** e um **aviso de dependências pendentes** quando a issue depende (linha `Depende de: #N` ou relação nativa *blocked by*) de outra que ainda não foi concluída — nesse caso, confirme com o usuário antes de seguir. Inclui também instruções para o agente implementar as Tasks **sequencialmente, uma por vez** (nunca duas com Status "In Progress" ao mesmo tempo): cada Task usa o **Status** (In Progress) *dentro* da Etapa 🚧 Desenvolvimento e, **ao concluir, avança para a Etapa 🎉 Done com Status Done**. **Ao concluir toda a Story**: fazer o commit, abrir o PR e **avançar a Etapa da Story para 👀 Code Review** (Status → Todo) — as Tasks já estão em 🎉 Done. A **Feature só avança** para Code Review quando **TODAS as suas Stories** já estiverem em Code Review — enquanto houver Story pendente, a Feature fica em 🚧 Desenvolvimento. Etapa só avança (nunca volta); Status mede o progresso dentro da etapa.
|
|
201
208
|
|
|
202
209
|
### `@spec-wave/cli doctor` — preflight de auth e configuração (comando LOCAL)
|
|
203
|
-
Sem flags. Roda um checklist de diagnóstico no repositório atual: token GitHub (e a fonte dele), escopos (`repo`, `project`, `workflow` — com degradação para checks funcionais em fine-grained PATs), conta ativa do `gh` vs. owner, `.spec-wave.json` (campos e sincronia com o Project real), acesso ao repositório, configuração de IA (provider/modelo/`ai.models`/teto de saída + secrets do Actions), **spec-kit** (`specKit.command` / env `SPEC_WAVE_IMPLEMENT_CMD` — se ausente, avisa e sugere exemplos por agente: Claude Code, opencode, Codex, Copilot CLI, Kiro CLI, Qwen Code) e presença
|
|
210
|
+
Sem flags. Roda um checklist de diagnóstico no repositório atual: token GitHub (e a fonte dele), escopos (`repo`, `project`, `workflow` — com degradação para checks funcionais em fine-grained PATs), conta ativa do `gh` vs. owner, `.spec-wave.json` (campos e sincronia com o Project real), acesso ao repositório, configuração de IA (provider/modelo/`ai.models`/escalada da crítica/apelidos de modelo/teto de saída + secrets do Actions), **higiene do board e das labels** (colunas fora do fluxo canônico, labels `spec-wave:*` descontinuadas ou ausentes), **spec-kit** (`specKit.command` / env `SPEC_WAVE_IMPLEMENT_CMD` — se ausente, avisa e sugere exemplos por agente: Claude Code, opencode, Codex, Copilot CLI, Kiro CLI, Qwen Code) e os workflows (presença + **versão da CLI fixada**, não `@latest`).
|
|
204
211
|
|
|
205
212
|
> Saída: `✓` ok, `✗` problema confirmado, `!` não verificável (best-effort — falha de rede nunca derruba o doctor). **Exit 1** se houver algum `✗`. **Quando rodar:** no início de uma sessão de trabalho, ou sempre que aparecer um erro estranho (ex.: **404 ao criar issues** — causa típica: token sem acesso ao repo/org, que o doctor aponta). É o primeiro passo de troubleshooting — prefira-o a depurar `gh api` na mão.
|
|
206
213
|
|
|
@@ -227,23 +234,88 @@ Sem flags. Roda um checklist de diagnóstico no repositório atual: token GitHub
|
|
|
227
234
|
|
|
228
235
|
> Avança a Story para a Etapa **👀 Code Review** com Status **Todo** (o Status reinicia ao trocar de etapa). Mesma regra do `task`: a **Etapa nunca retrocede** — se a Story já estiver em Code Review ou adiante, o comando apenas informa a Etapa atual. Use no fim do `implement` de uma Story, em vez de mutações GraphQL manuais.
|
|
229
236
|
|
|
237
|
+
### `@spec-wave/cli move <n> <etapa>` — move QUALQUER item do board (comando LOCAL)
|
|
238
|
+
| Flag/Arg | Tipo | Descrição |
|
|
239
|
+
|----------|------|-----------|
|
|
240
|
+
| `<n>` | string (obrigatório) | Número da issue, ex.: `8` ou `#8`. |
|
|
241
|
+
| `<etapa>` | string (obrigatório) | Etapa de destino, com ou sem emoji, sem acento e em qualquer caixa: `"code review"`, `"Homologação"`, `"🎉 Done"`. |
|
|
242
|
+
| `--status <valor>` | string | Valor do campo Status no destino: `Todo`, `In Progress` ou `Done` (default: `Todo`). |
|
|
243
|
+
|
|
244
|
+
> Serve para **Feature, Story, Task, Bug e RFC** — é o comando a usar quando `story review` e `task start|done` não cobrem o movimento desejado (ex.: mover uma **Feature** para Homologação). Embute as mesmas guardas: a **Etapa nunca retrocede** (se o item já estiver adiante, o comando informa a Etapa atual e não faz nada) e **Spike** é recusado (sua Etapa é movida à mão). Um nome de etapa ambíguo (`"p"` casa com Priorizado e Plan) é recusado listando as candidatas.
|
|
245
|
+
>
|
|
246
|
+
> **Prefira `move` a `gh api graphql` manual.** Não existe escape hatch para retroceder — isso é a regra do fluxo, não uma limitação.
|
|
247
|
+
|
|
230
248
|
---
|
|
231
249
|
|
|
232
|
-
## Crítica adversarial,
|
|
250
|
+
## Crítica adversarial, decomposição em duas etapas e dependências
|
|
233
251
|
|
|
234
252
|
### Crítica adversarial (comentário 🔎)
|
|
235
253
|
|
|
236
|
-
|
|
254
|
+
Depois do `generate-plan` e **antes** de qualquer issue ser criada no `decompose`, um segundo agente de IA audita o artefato procurando contradições com a spec, o plan e o `tech_context`. O resultado vira um comentário **🔎 Crítica adversarial (spec-wave)** na issue, com cabeçalho informando a **tentativa** e o **modelo** usados.
|
|
255
|
+
|
|
256
|
+
A saída da crítica é **estruturada e validada por schema**: `severity` só aceita `grave` ou `menor`, e um payload fora do contrato **falha alto** em vez de virar um finding menor com JSON cru dentro. Se a crítica não conclui, ela **não** é registrada como aprovada.
|
|
257
|
+
|
|
258
|
+
**A remediação depende de ONDE a crítica reprovou — são superfícies diferentes:**
|
|
259
|
+
|
|
260
|
+
| Reprovou depois de | O que corrigir | Como retomar |
|
|
261
|
+
|--------------------|----------------|--------------|
|
|
262
|
+
| `generate-plan` | `plan.md` (ou a `spec.md` que o embasa) | corrija/regere → remova `spec-wave:critique-failed` → reaplique `spec-wave:ready` |
|
|
263
|
+
| `decompose` (rascunho) | **`decomposition.md`** — os achados citam **`Story N`** e **`Task N.M`**, que são os títulos desse arquivo | edite o arquivo e commite → remova `spec-wave:critique-failed` → reaplique `spec-wave:decompose` (ele **critica o arquivo como está**, sem regerar) |
|
|
264
|
+
|
|
265
|
+
> ⚠️ No contexto do `decompose`, os achados são sobre as **Stories propostas**, não sobre o `plan.md`. Corrigir o plan não influencia o rascunho já gravado — edite o `decomposition.md` diretamente. Foi exatamente essa confusão que fazia o ciclo não convergir.
|
|
266
|
+
|
|
267
|
+
- Findings **graves** no `decompose` → **nenhuma Story/Task é criada** e o Action **falha (exit 1)**, com a label `spec-wave:critique-failed`. Um pipeline bloqueado nunca fica verde.
|
|
268
|
+
- Findings **menores** não bloqueiam — trate-os como revisão de qualidade.
|
|
269
|
+
- **Escalada:** na tentativa 2 a crítica roda em `ai.escalationModel` (se configurado). Ao atingir `ai.maxCritiqueAttempts` (default 3), o fluxo aplica **`spec-wave:needs-human`**, comenta e **para** — sem chamar a IA de novo. Para retomar: corrija os documentos e remova **as duas** labels (`spec-wave:needs-human` e `spec-wave:critique-failed`).
|
|
270
|
+
- Uma crítica **limpa** remove a `spec-wave:critique-failed` automaticamente e zera o contador de tentativas.
|
|
271
|
+
|
|
272
|
+
### Decomposição em duas etapas (`decomposition.md`)
|
|
273
|
+
|
|
274
|
+
O `decompose` **não cria issues direto**. São dois passos, com um artefato revisável no meio:
|
|
275
|
+
|
|
276
|
+
```
|
|
277
|
+
spec-wave:decompose
|
|
278
|
+
├─ decomposition.md ausente → gera via IA → commita → critica
|
|
279
|
+
└─ decomposition.md presente → critica o arquivo COMO ESTÁ (preserva suas edições)
|
|
280
|
+
├─ grave → +critique-failed, comentário citando Story N / Task N.M, exit 1
|
|
281
|
+
└─ limpo → +decompose-ready, comentário "revise e aplique"
|
|
282
|
+
|
|
283
|
+
spec-wave:decompose-apply
|
|
284
|
+
└─ lê decomposition.md → cria Stories/Tasks → board → +decomposed
|
|
285
|
+
(sem nova crítica: aplicar a label É a aprovação humana)
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
O arquivo fica em **`docs/features/<slug>/decomposition.md`** (Feature) ou **`docs/rfcs/<slug>/decomposition.md`** (RFC). Formato:
|
|
289
|
+
|
|
290
|
+
```markdown
|
|
291
|
+
# Decomposição — [FEATURE] Cadastro de Pedidos
|
|
292
|
+
<!-- spec-wave:decomposition v1 issue=360 kind=stories -->
|
|
237
293
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
294
|
+
## Story 1 — visualizar meus pedidos
|
|
295
|
+
|
|
296
|
+
**User story:** Como cliente, quero visualizar meus pedidos, para acompanhar entregas
|
|
297
|
+
**Depende de:** —
|
|
298
|
+
|
|
299
|
+
Descrição complementar (contexto, critérios de aceite).
|
|
300
|
+
|
|
301
|
+
### Task 1.1 — criar endpoint GET /pedidos
|
|
302
|
+
|
|
303
|
+
Corpo técnico.
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
**Ao editar à mão:**
|
|
307
|
+
- a **posição** manda, não o número escrito — inserir uma Story no meio sem renumerar funciona;
|
|
308
|
+
- `**Depende de:**` usa referências **1-based** (`Story 1, Story 3`) ou `—`; apontar para si mesma ou para frente é **erro**, não filtro silencioso;
|
|
309
|
+
- o corpo aceita markdown livre (`## Backend`, cercas de código) — só `## Story N` e `### Task N.M` são estrutura;
|
|
310
|
+
- **para gerar outro rascunho do zero:** apague o arquivo e reaplique `spec-wave:decompose`.
|
|
241
311
|
|
|
242
312
|
### Guard de idempotência do decompose (`spec-wave:decomposed`)
|
|
243
313
|
|
|
244
|
-
O evento `labeled` pode redisparar (re-add da label, retry de runner). Para não duplicar Stories/Tasks, o `decompose` **pula** quando a issue já tem a label **`spec-wave:decomposed`** ou já tem sub-issues do tipo-alvo (`[STORY]` para Feature, `[TASK]` para RFC).
|
|
314
|
+
O evento `labeled` pode redisparar (re-add da label, retry de runner). Para não duplicar Stories/Tasks, o `decompose` **pula** quando a issue já tem a label **`spec-wave:decomposed`** ou já tem sub-issues do tipo-alvo (`[STORY]` para Feature, `[TASK]` para RFC). O Action grava a label ao **aplicar** a decomposição. Os workflows ainda usam `concurrency` por issue para serializar runs simultâneos.
|
|
315
|
+
|
|
316
|
+
A `spec-wave:decompose-ready` **não** entra nesse guard: é estado de rascunho pendente, não de decomposição feita.
|
|
245
317
|
|
|
246
|
-
**Para forçar um re-decompose:** remova a label (`gh issue edit <n> --remove-label "spec-wave:decomposed"`), **apague/feche as sub-issues antigas** (senão a detecção por sub-issues pula de novo) e re-adicione `spec-wave:decompose`.
|
|
318
|
+
**Para forçar um re-decompose:** remova a label (`gh issue edit <n> --remove-label "spec-wave:decomposed"`), **apague/feche as sub-issues antigas** (senão a detecção por sub-issues pula de novo), apague o `decomposition.md` se quiser um rascunho novo, e re-adicione `spec-wave:decompose`.
|
|
247
319
|
|
|
248
320
|
### Dependências entre Stories (`Depende de: #N`)
|
|
249
321
|
|
|
@@ -266,12 +338,37 @@ Cada ação de IA (`spec`, `plan`, `decompose`, `critique`) pode usar um modelo
|
|
|
266
338
|
"models": {
|
|
267
339
|
"plan": "claude-opus-4-1",
|
|
268
340
|
"critique": "claude-opus-4-1"
|
|
341
|
+
},
|
|
342
|
+
"escalationModel": "claude-opus-5",
|
|
343
|
+
"maxCritiqueAttempts": 3,
|
|
344
|
+
"modelAliases": {
|
|
345
|
+
"opus": "claude-opus-5",
|
|
346
|
+
"haiku": "claude-haiku-4-5"
|
|
269
347
|
}
|
|
270
348
|
}
|
|
271
349
|
}
|
|
272
350
|
```
|
|
273
351
|
|
|
274
|
-
|
|
352
|
+
- `escalationModel` → modelo usado a partir da **segunda** tentativa da crítica.
|
|
353
|
+
- `maxCritiqueAttempts` → quantas reprovas seguidas antes de exigir revisão humana (`spec-wave:needs-human`).
|
|
354
|
+
- `modelAliases` → apelidos para a label **`spec-wave:model:<apelido>`**.
|
|
355
|
+
|
|
356
|
+
**Precedência do modelo:** `SPEC_WAVE_MODEL` (env) → label `spec-wave:model:<apelido>` → escalada automática da crítica → `ai.models[ação]` → `ai.model` → default do provider.
|
|
357
|
+
|
|
358
|
+
Edite o bloco `ai` no `.spec-wave.json` (e commite) — o `doctor` mostra o provider, o modelo, os apelidos, a escalada e os overrides resolvidos.
|
|
359
|
+
|
|
360
|
+
### Override de modelo numa execução (`spec-wave:model:<apelido>`)
|
|
361
|
+
|
|
362
|
+
Para reprocessar **uma issue difícil** num modelo mais forte sem editar a configuração do repositório inteiro:
|
|
363
|
+
|
|
364
|
+
```bash
|
|
365
|
+
# 1. Garanta o apelido em ai.modelAliases (uma vez, commitado)
|
|
366
|
+
# 2. Aplique a label na issue e redispare o gatilho
|
|
367
|
+
gh issue edit 360 --add-label "spec-wave:model:opus"
|
|
368
|
+
gh issue edit 360 --add-label "spec-wave:decompose"
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
A label vale só para as execuções daquela issue e **vence a escalada automática** (é decisão humana explícita). Apelido desconhecido é ignorado com aviso; duas labels dessas na mesma issue = ambíguo, nenhuma vale.
|
|
275
372
|
|
|
276
373
|
### Teto de saída (`ai.maxTokens`) e truncamento
|
|
277
374
|
|
|
@@ -495,28 +592,39 @@ Valida que spec.md e plan.md estão completos e a Feature pode avançar.
|
|
|
495
592
|
```
|
|
496
593
|
2. Informe: "Validação iniciada. O workflow verificará se spec.md e plan.md contêm todas as seções obrigatórias."
|
|
497
594
|
3. Se a validação falhar, o workflow comentará os problemas na issue e adicionará automaticamente `spec-wave:spec`. Informe o usuário para corrigir e tentar novamente.
|
|
498
|
-
4. **Se a issue tiver
|
|
499
|
-
5. Se passar, oriente: "Feature validada! Mova o card para **✅ Ready** e use `/spec-wave decompose <número>` para gerar
|
|
595
|
+
4. **Se a issue tiver `spec-wave:critique-failed` ou `spec-wave:needs-human`**, a validação falha de imediato — são portões humanos: a crítica apontou contradições graves (comentário 🔎 na issue) ou esgotou as tentativas. Nesses casos a Feature **não** é devolvida para a etapa de spec; siga o fluxo da seção *Crítica adversarial* (corrigir a superfície certa → remover a label → re-aplicar `spec-wave:ready`).
|
|
596
|
+
5. Se passar, oriente: "Feature validada! Mova o card para **✅ Ready** e use `/spec-wave decompose <número>` para gerar o **rascunho** das Stories (nada é criado ainda)."
|
|
500
597
|
|
|
501
598
|
---
|
|
502
599
|
|
|
503
600
|
### `/spec-wave decompose <número-da-issue>`
|
|
504
601
|
|
|
505
|
-
Decompõe
|
|
506
|
-
- **Feature** →
|
|
507
|
-
- **RFC** →
|
|
602
|
+
Decompõe em **duas etapas**, com um rascunho revisável no meio (veja *Decomposição em duas etapas*). Aplica-se a **dois tipos**:
|
|
603
|
+
- **Feature** → **Stories** (cada uma com suas **Tasks**), a partir de `spec.md` + `plan.md`.
|
|
604
|
+
- **RFC** → **Tasks diretamente** (sem Stories), a partir da descrição do RFC.
|
|
508
605
|
|
|
509
606
|
Para qualquer outro tipo (Spike, Bug, Story, Task, …) o Action **recusa** e comenta.
|
|
510
607
|
|
|
511
608
|
**Passos:**
|
|
512
609
|
1. Para **Feature**: confirme que está em **✅ Ready** (spec.md e plan.md validados). Para **RFC**: basta a descrição estar completa (RFC não usa spec/plan).
|
|
513
|
-
2.
|
|
610
|
+
2. **Etapa 1 — gerar o rascunho:**
|
|
514
611
|
```bash
|
|
515
612
|
gh issue edit <número> --add-label "spec-wave:decompose"
|
|
516
613
|
```
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
614
|
+
Informe: "Rascunho iniciado — vai commitar `decomposition.md` e passar pela crítica. **Nenhuma issue é criada nesta etapa.**"
|
|
615
|
+
3. Quando o Action terminar, leia o comentário na issue:
|
|
616
|
+
- **`spec-wave:decompose-ready`** → o rascunho passou pela crítica. **Leia o `decomposition.md`** e mostre ao usuário o que será criado (Stories, Tasks, dependências). Ofereça editar o arquivo antes de aplicar.
|
|
617
|
+
- **`spec-wave:critique-failed`** → o Action **falhou (exit 1)** e nada foi criado. Os achados citam `Story N` / `Task N.M` do `decomposition.md`. **Corrija esse arquivo** (não o `plan.md`), commite e reaplique `spec-wave:decompose` — o arquivo é criticado como está, sem ser regerado.
|
|
618
|
+
- **`spec-wave:needs-human`** → a crítica esgotou as tentativas. Pare e envolva o usuário: as duas labels precisam sair à mão.
|
|
619
|
+
4. **Etapa 2 — aplicar o rascunho aprovado** (só depois da revisão):
|
|
620
|
+
```bash
|
|
621
|
+
gh issue edit <número> --add-label "spec-wave:decompose-apply"
|
|
622
|
+
```
|
|
623
|
+
Aplicar essa label **é** a aprovação humana — não há nova crítica.
|
|
624
|
+
5. Após a aplicação, as issues filhas aparecem como comentário na issue pai. A issue pai e as Stories/Tasks criadas entram no board na Etapa **✅ Ready** (Status Todo; a Etapa nunca retrocede — itens já adiante não são tocados). As Stories trazem a linha `Depende de: #N` (+ relação *blocked by*) — use `npx @spec-wave/cli@latest order <número>` para ver a ordem de execução.
|
|
625
|
+
6. A issue recebe a label `spec-wave:decomposed` (guard de idempotência): rodar de novo **não** duplica as issues. Para forçar um re-decompose, siga a seção *Guard de idempotência*.
|
|
626
|
+
|
|
627
|
+
> **Nunca pule a etapa 1** aplicando `spec-wave:decompose-apply` direto: sem `decomposition.md` o Action falha pedindo o rascunho.
|
|
520
628
|
|
|
521
629
|
---
|
|
522
630
|
|
|
@@ -682,8 +790,16 @@ Audita um Pull Request e corrige automaticamente os problemas encontrados — se
|
|
|
682
790
|
docs/
|
|
683
791
|
features/
|
|
684
792
|
<slug-da-feature>/
|
|
685
|
-
spec.md
|
|
686
|
-
plan.md
|
|
793
|
+
spec.md ← gerado quando spec-wave:spec é adicionado (1º)
|
|
794
|
+
plan.md ← gerado quando spec-wave:plan é adicionado (2º, usa a spec)
|
|
795
|
+
decomposition.md ← rascunho gerado quando spec-wave:decompose é adicionado (3º).
|
|
796
|
+
REVISÁVEL e EDITÁVEL à mão; as issues só nascem com
|
|
797
|
+
spec-wave:decompose-apply
|
|
798
|
+
rfcs/
|
|
799
|
+
<slug-do-rfc>/
|
|
800
|
+
decomposition.md ← mesmo papel, com "## Task N" (RFC não usa spec/plan)
|
|
687
801
|
```
|
|
688
802
|
|
|
689
803
|
O slug é gerado a partir do título da issue: `[FEATURE] Cadastro de Pedidos com PIX` → `cadastro-de-pedidos-com-pix`
|
|
804
|
+
|
|
805
|
+
> ⚠️ O slug vem do **título**. Renomear a Feature entre o rascunho e o apply muda o diretório e o `decomposition.md` antigo fica órfão — o apply reclama que não encontrou o rascunho.
|
|
@@ -24,7 +24,7 @@ jobs:
|
|
|
24
24
|
node-version: '24'
|
|
25
25
|
|
|
26
26
|
- name: Move Feature to Code Review
|
|
27
|
-
run: npx @spec-wave/cli@
|
|
27
|
+
run: npx @spec-wave/cli@{{CLI_VERSION}} code-review --pr-number ${{ github.event.pull_request.number }}
|
|
28
28
|
env:
|
|
29
29
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
30
30
|
PROJECT_TOKEN: ${{ secrets.GH_PROJECT_TOKEN }}
|
|
@@ -4,8 +4,9 @@ on:
|
|
|
4
4
|
issues:
|
|
5
5
|
types: [labeled]
|
|
6
6
|
|
|
7
|
-
# O evento `labeled` pode redisparar (re-add da label, retry de runner)
|
|
8
|
-
#
|
|
7
|
+
# O evento `labeled` pode redisparar (re-add da label, retry de runner). O
|
|
8
|
+
# concurrency serializa runs da mesma issue — inclusive um `decompose-apply`
|
|
9
|
+
# enfileirado atrás de um `decompose` — e o guard de idempotência
|
|
9
10
|
# (label spec-wave:decomposed) descarta o run enfileirado.
|
|
10
11
|
concurrency:
|
|
11
12
|
group: spec-wave-decompose-${{ github.event.issue.number }}
|
|
@@ -13,23 +14,36 @@ concurrency:
|
|
|
13
14
|
|
|
14
15
|
jobs:
|
|
15
16
|
decompose:
|
|
17
|
+
# Duas etapas, duas labels:
|
|
18
|
+
# • spec-wave:decompose → grava/re-critica docs/**/decomposition.md
|
|
19
|
+
# • spec-wave:decompose-apply → cria as Stories/Tasks a partir do rascunho
|
|
20
|
+
# O `[RFC]` no título também dispara: o caminho RFC → Tasks existe na CLI
|
|
21
|
+
# desde sempre, mas era inalcançável porque o filtro exigia `[FEATURE]`.
|
|
16
22
|
if: >
|
|
17
|
-
github.event.label.name == 'spec-wave:decompose'
|
|
18
|
-
|
|
23
|
+
(github.event.label.name == 'spec-wave:decompose' ||
|
|
24
|
+
github.event.label.name == 'spec-wave:decompose-apply') &&
|
|
25
|
+
(contains(github.event.issue.title, '[FEATURE]') ||
|
|
26
|
+
contains(github.event.issue.title, '[RFC]'))
|
|
19
27
|
runs-on: ubuntu-latest
|
|
20
28
|
permissions:
|
|
21
29
|
issues: write
|
|
22
|
-
|
|
30
|
+
# A etapa de rascunho commita docs/**/decomposition.md no branch default.
|
|
31
|
+
contents: write
|
|
23
32
|
|
|
24
33
|
steps:
|
|
25
34
|
- uses: actions/checkout@v4
|
|
35
|
+
with:
|
|
36
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
26
37
|
|
|
27
38
|
- uses: actions/setup-node@v4
|
|
28
39
|
with:
|
|
29
40
|
node-version: '24'
|
|
30
41
|
|
|
31
42
|
- name: Decompose into Stories and Tasks
|
|
32
|
-
run:
|
|
43
|
+
run: >
|
|
44
|
+
npx @spec-wave/cli@{{CLI_VERSION}} decompose
|
|
45
|
+
--issue-number ${{ github.event.issue.number }}
|
|
46
|
+
${{ github.event.label.name == 'spec-wave:decompose-apply' && '--apply' || '' }}
|
|
33
47
|
env:
|
|
34
48
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
35
49
|
PROJECT_TOKEN: ${{ secrets.GH_PROJECT_TOKEN }}
|
|
@@ -28,7 +28,7 @@ jobs:
|
|
|
28
28
|
node-version: '24'
|
|
29
29
|
|
|
30
30
|
- name: Generate plan.md
|
|
31
|
-
run: npx @spec-wave/cli@
|
|
31
|
+
run: npx @spec-wave/cli@{{CLI_VERSION}} generate-plan --issue-number ${{ github.event.issue.number }}
|
|
32
32
|
env:
|
|
33
33
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
34
34
|
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
@@ -28,7 +28,7 @@ jobs:
|
|
|
28
28
|
node-version: '24'
|
|
29
29
|
|
|
30
30
|
- name: Generate spec.md
|
|
31
|
-
run: npx @spec-wave/cli@
|
|
31
|
+
run: npx @spec-wave/cli@{{CLI_VERSION}} generate-spec --issue-number ${{ github.event.issue.number }}
|
|
32
32
|
env:
|
|
33
33
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
34
34
|
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
@@ -25,7 +25,7 @@ jobs:
|
|
|
25
25
|
node-version: '24'
|
|
26
26
|
|
|
27
27
|
- name: Move Feature to QA
|
|
28
|
-
run: npx @spec-wave/cli@
|
|
28
|
+
run: npx @spec-wave/cli@{{CLI_VERSION}} qa --pr-number ${{ github.event.pull_request.number }}
|
|
29
29
|
env:
|
|
30
30
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
31
31
|
PROJECT_TOKEN: ${{ secrets.GH_PROJECT_TOKEN }}
|
|
@@ -26,7 +26,7 @@ jobs:
|
|
|
26
26
|
node-version: '24'
|
|
27
27
|
|
|
28
28
|
- name: Validate spec and plan
|
|
29
|
-
run: npx @spec-wave/cli@
|
|
29
|
+
run: npx @spec-wave/cli@{{CLI_VERSION}} validate --issue-number ${{ github.event.issue.number }}
|
|
30
30
|
env:
|
|
31
31
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
32
32
|
GITHUB_REPOSITORY: ${{ github.repository }}
|