@spec-wave/cli 0.13.0 → 0.15.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 +17 -1
- package/package.json +1 -1
- package/src/api/github-rest.mjs +198 -2
- 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 +372 -71
- 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/pr-branch.mjs +267 -0
- 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 +158 -30
- 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
|
---
|
|
@@ -174,15 +180,24 @@ Mesmas flags do `issue` (exceto `--type`, fixo em `feature`). Mantido para o flu
|
|
|
174
180
|
|------|------|-----------|
|
|
175
181
|
| `--global` | flag | Verifica a skill no escopo do usuário (padrão: projeto). |
|
|
176
182
|
| `--skip-skill` / `--skip-config` / `--skip-repo` | flag | Pula a categoria correspondente. |
|
|
183
|
+
| `--branch [nome]` | flag/string | Envia os arquivos do repo como **Pull Request** numa branch, em **um único commit**, em vez de commitar direto na branch default. Sem valor, usa `spec-wave/update-v<versão>`. |
|
|
184
|
+
| `--config-in-pr` / `--no-config-in-pr` | flag | Força incluir/excluir o `.spec-wave.json` do PR (o default decide sozinho — veja abaixo). |
|
|
177
185
|
| `--dry-run` | flag | Mostra o que seria atualizado sem alterar nada. |
|
|
178
186
|
| `--yes` | flag | Aplica sem pedir confirmação. |
|
|
179
187
|
|
|
180
188
|
> Detecta e atualiza **somente o que divergiu** da versão atual da CLI: a **skill** instalada (por agente), o **`.spec-wave.json`** local (se versão/formato divergir) e os **workflows/labels** do repo (compara com os templates empacotados). Interativo por padrão (mostra o plano e confirma). É o atalho recomendado após atualizar a CLI.
|
|
181
189
|
|
|
190
|
+
> **`--branch` (modo Pull Request).** Sem a flag, os arquivos do repo vão em **commits diretos na branch default** — o que falha no meio da execução em repositório com proteção de branch, deixando parte aplicada, e contorna a revisão. Com a flag, todos os arquivos vão em **um commit atômico** numa branch nova e um PR é aberto: se algo falhar antes da criação da branch, **nada** é alterado no repositório. É **idempotente** — rodar duas vezes não gera um segundo commit nem um segundo PR.
|
|
191
|
+
>
|
|
192
|
+
> Duas coisas **não** entram no PR, porque não são versionáveis: as **labels** (metadado do repositório — já valem na base, com ou sem merge) e a **skill** (arquivo em máquina local). O corpo do PR diz isso explicitamente a quem revisa.
|
|
193
|
+
>
|
|
194
|
+
> ⚠️ O modo PR exige **`pull_requests: write`** além de `contents: write` (ou o escopo `repo` num PAT classic). Sem essa permissão, a branch é criada e o PR falha — a mensagem oferece a URL de `compare` para abrir à mão.
|
|
195
|
+
|
|
182
196
|
### `@spec-wave/cli generate-plan` · `generate-spec` · `validate` · `decompose`
|
|
183
197
|
| Flag | Tipo | Descrição |
|
|
184
198
|
|------|------|-----------|
|
|
185
199
|
| `--issue-number <n>` | string (obrigatório) | Número da issue no GitHub. |
|
|
200
|
+
| `--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
201
|
|
|
187
202
|
> ⚠️ 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
203
|
>
|
|
@@ -195,12 +210,12 @@ Mesmas flags do `issue` (exceto `--type`, fixo em `feature`). Mantido para o flu
|
|
|
195
210
|
|----------|------|-----------|
|
|
196
211
|
| `<issue>` | string (obrigatório) | Número da issue (Feature, Story ou Task), ex.: `12` ou `#12`. Argumento posicional. |
|
|
197
212
|
| `--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
|
|
213
|
+
| `--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
214
|
|
|
200
215
|
> 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
216
|
|
|
202
217
|
### `@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
|
|
218
|
+
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
219
|
|
|
205
220
|
> 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
221
|
|
|
@@ -227,23 +242,88 @@ Sem flags. Roda um checklist de diagnóstico no repositório atual: token GitHub
|
|
|
227
242
|
|
|
228
243
|
> 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
244
|
|
|
245
|
+
### `@spec-wave/cli move <n> <etapa>` — move QUALQUER item do board (comando LOCAL)
|
|
246
|
+
| Flag/Arg | Tipo | Descrição |
|
|
247
|
+
|----------|------|-----------|
|
|
248
|
+
| `<n>` | string (obrigatório) | Número da issue, ex.: `8` ou `#8`. |
|
|
249
|
+
| `<etapa>` | string (obrigatório) | Etapa de destino, com ou sem emoji, sem acento e em qualquer caixa: `"code review"`, `"Homologação"`, `"🎉 Done"`. |
|
|
250
|
+
| `--status <valor>` | string | Valor do campo Status no destino: `Todo`, `In Progress` ou `Done` (default: `Todo`). |
|
|
251
|
+
|
|
252
|
+
> 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.
|
|
253
|
+
>
|
|
254
|
+
> **Prefira `move` a `gh api graphql` manual.** Não existe escape hatch para retroceder — isso é a regra do fluxo, não uma limitação.
|
|
255
|
+
|
|
230
256
|
---
|
|
231
257
|
|
|
232
|
-
## Crítica adversarial,
|
|
258
|
+
## Crítica adversarial, decomposição em duas etapas e dependências
|
|
233
259
|
|
|
234
260
|
### Crítica adversarial (comentário 🔎)
|
|
235
261
|
|
|
236
|
-
|
|
262
|
+
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.
|
|
263
|
+
|
|
264
|
+
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.
|
|
265
|
+
|
|
266
|
+
**A remediação depende de ONDE a crítica reprovou — são superfícies diferentes:**
|
|
267
|
+
|
|
268
|
+
| Reprovou depois de | O que corrigir | Como retomar |
|
|
269
|
+
|--------------------|----------------|--------------|
|
|
270
|
+
| `generate-plan` | `plan.md` (ou a `spec.md` que o embasa) | corrija/regere → remova `spec-wave:critique-failed` → reaplique `spec-wave:ready` |
|
|
271
|
+
| `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) |
|
|
272
|
+
|
|
273
|
+
> ⚠️ 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.
|
|
274
|
+
|
|
275
|
+
- 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.
|
|
276
|
+
- Findings **menores** não bloqueiam — trate-os como revisão de qualidade.
|
|
277
|
+
- **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`).
|
|
278
|
+
- Uma crítica **limpa** remove a `spec-wave:critique-failed` automaticamente e zera o contador de tentativas.
|
|
279
|
+
|
|
280
|
+
### Decomposição em duas etapas (`decomposition.md`)
|
|
281
|
+
|
|
282
|
+
O `decompose` **não cria issues direto**. São dois passos, com um artefato revisável no meio:
|
|
283
|
+
|
|
284
|
+
```
|
|
285
|
+
spec-wave:decompose
|
|
286
|
+
├─ decomposition.md ausente → gera via IA → commita → critica
|
|
287
|
+
└─ decomposition.md presente → critica o arquivo COMO ESTÁ (preserva suas edições)
|
|
288
|
+
├─ grave → +critique-failed, comentário citando Story N / Task N.M, exit 1
|
|
289
|
+
└─ limpo → +decompose-ready, comentário "revise e aplique"
|
|
290
|
+
|
|
291
|
+
spec-wave:decompose-apply
|
|
292
|
+
└─ lê decomposition.md → cria Stories/Tasks → board → +decomposed
|
|
293
|
+
(sem nova crítica: aplicar a label É a aprovação humana)
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
O arquivo fica em **`docs/features/<slug>/decomposition.md`** (Feature) ou **`docs/rfcs/<slug>/decomposition.md`** (RFC). Formato:
|
|
237
297
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
298
|
+
```markdown
|
|
299
|
+
# Decomposição — [FEATURE] Cadastro de Pedidos
|
|
300
|
+
<!-- spec-wave:decomposition v1 issue=360 kind=stories -->
|
|
301
|
+
|
|
302
|
+
## Story 1 — visualizar meus pedidos
|
|
303
|
+
|
|
304
|
+
**User story:** Como cliente, quero visualizar meus pedidos, para acompanhar entregas
|
|
305
|
+
**Depende de:** —
|
|
306
|
+
|
|
307
|
+
Descrição complementar (contexto, critérios de aceite).
|
|
308
|
+
|
|
309
|
+
### Task 1.1 — criar endpoint GET /pedidos
|
|
310
|
+
|
|
311
|
+
Corpo técnico.
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
**Ao editar à mão:**
|
|
315
|
+
- a **posição** manda, não o número escrito — inserir uma Story no meio sem renumerar funciona;
|
|
316
|
+
- `**Depende de:**` usa referências **1-based** (`Story 1, Story 3`) ou `—`; apontar para si mesma ou para frente é **erro**, não filtro silencioso;
|
|
317
|
+
- o corpo aceita markdown livre (`## Backend`, cercas de código) — só `## Story N` e `### Task N.M` são estrutura;
|
|
318
|
+
- **para gerar outro rascunho do zero:** apague o arquivo e reaplique `spec-wave:decompose`.
|
|
241
319
|
|
|
242
320
|
### Guard de idempotência do decompose (`spec-wave:decomposed`)
|
|
243
321
|
|
|
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).
|
|
322
|
+
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.
|
|
323
|
+
|
|
324
|
+
A `spec-wave:decompose-ready` **não** entra nesse guard: é estado de rascunho pendente, não de decomposição feita.
|
|
245
325
|
|
|
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`.
|
|
326
|
+
**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
327
|
|
|
248
328
|
### Dependências entre Stories (`Depende de: #N`)
|
|
249
329
|
|
|
@@ -266,12 +346,37 @@ Cada ação de IA (`spec`, `plan`, `decompose`, `critique`) pode usar um modelo
|
|
|
266
346
|
"models": {
|
|
267
347
|
"plan": "claude-opus-4-1",
|
|
268
348
|
"critique": "claude-opus-4-1"
|
|
349
|
+
},
|
|
350
|
+
"escalationModel": "claude-opus-5",
|
|
351
|
+
"maxCritiqueAttempts": 3,
|
|
352
|
+
"modelAliases": {
|
|
353
|
+
"opus": "claude-opus-5",
|
|
354
|
+
"haiku": "claude-haiku-4-5"
|
|
269
355
|
}
|
|
270
356
|
}
|
|
271
357
|
}
|
|
272
358
|
```
|
|
273
359
|
|
|
274
|
-
|
|
360
|
+
- `escalationModel` → modelo usado a partir da **segunda** tentativa da crítica.
|
|
361
|
+
- `maxCritiqueAttempts` → quantas reprovas seguidas antes de exigir revisão humana (`spec-wave:needs-human`).
|
|
362
|
+
- `modelAliases` → apelidos para a label **`spec-wave:model:<apelido>`**.
|
|
363
|
+
|
|
364
|
+
**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.
|
|
365
|
+
|
|
366
|
+
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.
|
|
367
|
+
|
|
368
|
+
### Override de modelo numa execução (`spec-wave:model:<apelido>`)
|
|
369
|
+
|
|
370
|
+
Para reprocessar **uma issue difícil** num modelo mais forte sem editar a configuração do repositório inteiro:
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
# 1. Garanta o apelido em ai.modelAliases (uma vez, commitado)
|
|
374
|
+
# 2. Aplique a label na issue e redispare o gatilho
|
|
375
|
+
gh issue edit 360 --add-label "spec-wave:model:opus"
|
|
376
|
+
gh issue edit 360 --add-label "spec-wave:decompose"
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
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
380
|
|
|
276
381
|
### Teto de saída (`ai.maxTokens`) e truncamento
|
|
277
382
|
|
|
@@ -320,12 +425,16 @@ Traz tudo para a versão atual da CLI, atualizando **só o que mudou**: a skill
|
|
|
320
425
|
npx @spec-wave/cli@latest update --dry-run
|
|
321
426
|
```
|
|
322
427
|
2. Mostre ao usuário o resumo (skill / config / arquivos do repo / labels que divergiram). Se **nada** estiver desatualizado, informe que já está tudo na versão atual e encerre.
|
|
323
|
-
3.
|
|
428
|
+
3. **Pergunte como os arquivos do repo devem sair** — e prefira o Pull Request:
|
|
324
429
|
```bash
|
|
325
|
-
npx @spec-wave/cli@latest update --yes
|
|
430
|
+
npx @spec-wave/cli@latest update --yes --branch # 1 commit atômico + PR (recomendado)
|
|
431
|
+
npx @spec-wave/cli@latest update --yes # commits diretos na branch default
|
|
326
432
|
```
|
|
327
433
|
- Escopos podem ser limitados com `--skip-skill`, `--skip-config`, `--skip-repo`.
|
|
328
|
-
-
|
|
434
|
+
- **Com `--branch`:** os arquivos do repo vão em **um único commit** numa branch nova e um PR é aberto — nada é escrito na branch default. Passe o link do PR ao usuário e lembre que o merge é dele. Exige `pull_requests: write` no token.
|
|
435
|
+
- **Sem `--branch`:** cada arquivo é um commit direto na branch default. Em repositório com **proteção de branch** isso falha no meio e deixa parte aplicada — nesses casos use `--branch`.
|
|
436
|
+
- **Nos dois modos**, as **labels** são aplicadas direto na base (metadado do repositório, não versionável) e a **skill** é gravada em máquina local. Nenhuma das duas entra no PR.
|
|
437
|
+
- **`.spec-wave.json`:** com `--branch`, ele entra no PR se o repositório **já o versiona**; se não versiona, segue apenas local e o usuário precisa commitá-lo (ou use `--config-in-pr` para passar a versioná-lo). Sem `--branch`, é sempre só local.
|
|
329
438
|
4. Se a skill foi atualizada, oriente recarregar/reiniciar o agente para pegar a nova versão.
|
|
330
439
|
|
|
331
440
|
---
|
|
@@ -495,28 +604,39 @@ Valida que spec.md e plan.md estão completos e a Feature pode avançar.
|
|
|
495
604
|
```
|
|
496
605
|
2. Informe: "Validação iniciada. O workflow verificará se spec.md e plan.md contêm todas as seções obrigatórias."
|
|
497
606
|
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
|
|
607
|
+
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`).
|
|
608
|
+
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
609
|
|
|
501
610
|
---
|
|
502
611
|
|
|
503
612
|
### `/spec-wave decompose <número-da-issue>`
|
|
504
613
|
|
|
505
|
-
Decompõe
|
|
506
|
-
- **Feature** →
|
|
507
|
-
- **RFC** →
|
|
614
|
+
Decompõe em **duas etapas**, com um rascunho revisável no meio (veja *Decomposição em duas etapas*). Aplica-se a **dois tipos**:
|
|
615
|
+
- **Feature** → **Stories** (cada uma com suas **Tasks**), a partir de `spec.md` + `plan.md`.
|
|
616
|
+
- **RFC** → **Tasks diretamente** (sem Stories), a partir da descrição do RFC.
|
|
508
617
|
|
|
509
618
|
Para qualquer outro tipo (Spike, Bug, Story, Task, …) o Action **recusa** e comenta.
|
|
510
619
|
|
|
511
620
|
**Passos:**
|
|
512
621
|
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.
|
|
622
|
+
2. **Etapa 1 — gerar o rascunho:**
|
|
514
623
|
```bash
|
|
515
624
|
gh issue edit <número> --add-label "spec-wave:decompose"
|
|
516
625
|
```
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
626
|
+
Informe: "Rascunho iniciado — vai commitar `decomposition.md` e passar pela crítica. **Nenhuma issue é criada nesta etapa.**"
|
|
627
|
+
3. Quando o Action terminar, leia o comentário na issue:
|
|
628
|
+
- **`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.
|
|
629
|
+
- **`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.
|
|
630
|
+
- **`spec-wave:needs-human`** → a crítica esgotou as tentativas. Pare e envolva o usuário: as duas labels precisam sair à mão.
|
|
631
|
+
4. **Etapa 2 — aplicar o rascunho aprovado** (só depois da revisão):
|
|
632
|
+
```bash
|
|
633
|
+
gh issue edit <número> --add-label "spec-wave:decompose-apply"
|
|
634
|
+
```
|
|
635
|
+
Aplicar essa label **é** a aprovação humana — não há nova crítica.
|
|
636
|
+
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.
|
|
637
|
+
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*.
|
|
638
|
+
|
|
639
|
+
> **Nunca pule a etapa 1** aplicando `spec-wave:decompose-apply` direto: sem `decomposition.md` o Action falha pedindo o rascunho.
|
|
520
640
|
|
|
521
641
|
---
|
|
522
642
|
|
|
@@ -682,8 +802,16 @@ Audita um Pull Request e corrige automaticamente os problemas encontrados — se
|
|
|
682
802
|
docs/
|
|
683
803
|
features/
|
|
684
804
|
<slug-da-feature>/
|
|
685
|
-
spec.md
|
|
686
|
-
plan.md
|
|
805
|
+
spec.md ← gerado quando spec-wave:spec é adicionado (1º)
|
|
806
|
+
plan.md ← gerado quando spec-wave:plan é adicionado (2º, usa a spec)
|
|
807
|
+
decomposition.md ← rascunho gerado quando spec-wave:decompose é adicionado (3º).
|
|
808
|
+
REVISÁVEL e EDITÁVEL à mão; as issues só nascem com
|
|
809
|
+
spec-wave:decompose-apply
|
|
810
|
+
rfcs/
|
|
811
|
+
<slug-do-rfc>/
|
|
812
|
+
decomposition.md ← mesmo papel, com "## Task N" (RFC não usa spec/plan)
|
|
687
813
|
```
|
|
688
814
|
|
|
689
815
|
O slug é gerado a partir do título da issue: `[FEATURE] Cadastro de Pedidos com PIX` → `cadastro-de-pedidos-com-pix`
|
|
816
|
+
|
|
817
|
+
> ⚠️ 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 }}
|