@spec-wave/cli 0.27.0 → 0.29.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/package.json +1 -1
- package/src/api/github-graphql.mjs +37 -0
- package/src/api/github-rest.mjs +48 -0
- package/src/cli.mjs +51 -2
- package/src/commands/audit.mjs +280 -0
- package/src/commands/doctor.mjs +40 -16
- package/src/commands/implement.mjs +19 -2
- package/src/commands/install-skill.mjs +18 -8
- package/src/commands/merge.mjs +292 -0
- package/src/commands/move.mjs +26 -11
- package/src/commands/order.mjs +42 -0
- package/src/commands/preflight.mjs +322 -0
- package/src/commands/run.mjs +4 -3
- package/src/commands/update.mjs +143 -12
- package/src/lib/board.mjs +18 -2
- package/src/lib/critique.mjs +64 -8
- package/src/lib/pr-branch.mjs +96 -7
- package/src/lib/pr-step.mjs +12 -7
- package/src/lib/spec-audit.mjs +372 -0
- package/src/lib/tech-context.mjs +20 -14
- package/src/plugin/.claude-plugin/plugin.json +1 -1
- package/src/plugin/README.md +5 -0
- package/src/plugin/skills/audit/SKILL.md +34 -0
- package/src/plugin/skills/audit/model-prompt.critique.md +34 -0
- package/src/plugin/skills/merge/SKILL.md +34 -0
- package/src/plugin/skills/order/SKILL.md +1 -0
- package/src/plugin/skills/plan/model-prompt.md +1 -0
- package/src/plugin/skills/plan/reference/tech-context.md +6 -0
- package/src/plugin/skills/preparar-feature/SKILL.md +247 -0
- package/src/plugin/skills/preparar-feature/reference/critica.md +88 -0
- package/src/plugin/skills/preparar-specs/SKILL.md +191 -0
- package/src/plugin/skills/preparar-specs/reference/armadilhas.md +209 -0
- package/src/plugin/skills/preparar-specs/reference/revisao.md +110 -0
- package/src/plugin/skills/update/SKILL.md +10 -4
- package/src/plugin/skills/workflow/SKILL.md +6 -1
- package/src/templates/config/tech_context.yml +13 -0
- package/src/templates/skill/SKILL.md +36 -7
- package/src/templates/workflows/qa.yml +9 -1
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# Armadilhas operacionais deste fluxo
|
|
2
|
+
|
|
3
|
+
Cada item aqui custou uma investigação real. A causa vem junto porque o sintoma, sozinho,
|
|
4
|
+
costuma apontar para o lugar errado.
|
|
5
|
+
|
|
6
|
+
## Índice
|
|
7
|
+
|
|
8
|
+
1. Token do `gh` inválido no ambiente
|
|
9
|
+
2. `gh issue edit --add-label` falha com 503
|
|
10
|
+
3. A API do GitHub devolve 503 intermitente
|
|
11
|
+
4. Working tree compartilhado com outros agentes
|
|
12
|
+
5. Label de gatilho grudada impede o retry
|
|
13
|
+
6. `spec-wave:spec` sobrescreve spec revisada
|
|
14
|
+
7. `spec-wave update` reescreve os workflows
|
|
15
|
+
8. Runs `skipped` são normais — não são falha
|
|
16
|
+
9. `conclusion` vazia não é conclusão
|
|
17
|
+
10. Geração leva minutos — não rode em primeiro plano
|
|
18
|
+
11. Run interrompido deixa lock órfão
|
|
19
|
+
12. O documento foi gerado e o PR não nasceu
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 1. Token do `gh` inválido no ambiente
|
|
24
|
+
|
|
25
|
+
**Sintoma:** `gh` falha com erro de autenticação, ou enxerga o repositório errado.
|
|
26
|
+
|
|
27
|
+
**Causa:** a variável `GH_TOKEN` do ambiente pode estar inválida ou pertencer a uma conta
|
|
28
|
+
sem acesso à organização, enquanto o keyring tem a conta certa.
|
|
29
|
+
|
|
30
|
+
**Como resolver:** exporte o token da conta correta antes dos comandos:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
export GH_TOKEN=$(env -u GH_TOKEN gh auth token -u <conta-com-acesso>)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
O `env -u GH_TOKEN` é necessário porque o `gh auth token` também consulta a variável
|
|
37
|
+
inválida se ela estiver setada.
|
|
38
|
+
|
|
39
|
+
A CLI tem a saída própria dela para o mesmo problema, que não depende do shell:
|
|
40
|
+
`spec-wave --account <login> <comando>`, ou `"github": { "account": "<login>" }` no
|
|
41
|
+
`.spec-wave.json`. Fora do CI, a conta declarada vence a variável de ambiente.
|
|
42
|
+
|
|
43
|
+
## 2. `gh issue edit --add-label` falha com 503
|
|
44
|
+
|
|
45
|
+
**Sintoma:** o comando falha repetidamente, e parece que o gatilho não existe.
|
|
46
|
+
|
|
47
|
+
**Causa:** esse subcomando passa pelo GraphQL, que pode estar degradado enquanto o REST
|
|
48
|
+
funciona normalmente.
|
|
49
|
+
|
|
50
|
+
**Alternativa que funciona:**
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
gh api -X POST repos/<owner>/<repo>/issues/<n>/labels -f "labels[]=spec-wave:spec"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 3. A API do GitHub devolve 503 intermitente
|
|
57
|
+
|
|
58
|
+
**Sintoma:** comandos falham de forma aleatória e passam na tentativa seguinte.
|
|
59
|
+
|
|
60
|
+
**Como lidar:** envolva as chamadas em retry (3–5 tentativas com pausa) e **verifique o
|
|
61
|
+
resultado real**, não o código de saída isolado. Um `gh` que devolve string vazia sem erro
|
|
62
|
+
é indistinguível de "não encontrei nada" se você não conferir.
|
|
63
|
+
|
|
64
|
+
## 4. Working tree compartilhado com outros agentes
|
|
65
|
+
|
|
66
|
+
**Sintoma:** arquivos modificados que você não criou; branch diferente da esperada.
|
|
67
|
+
|
|
68
|
+
**Causa:** outros processos (dev-agents, outras sessões) usam o mesmo checkout e trocam de
|
|
69
|
+
branch sem aviso.
|
|
70
|
+
|
|
71
|
+
**Regra:** nunca `checkout`, `stash` ou `reset` sem antes conferir `git branch --show-current`
|
|
72
|
+
e `git status --short`. A geração em si não disputa o checkout — ela publica por API, sem
|
|
73
|
+
tocar em disco —, mas tudo que você fizer à mão disputa.
|
|
74
|
+
|
|
75
|
+
Se precisar mesmo de uma branch checada — por exemplo, para editar arquivos de um PR já
|
|
76
|
+
aberto — use um worktree temporário fora do repositório, e remova depois:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
git worktree add /tmp/<dir> <branch>
|
|
80
|
+
# ... edições, commit, push ...
|
|
81
|
+
git worktree remove --force /tmp/<dir> && git worktree prune
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## 5. Label de gatilho grudada impede o retry
|
|
85
|
+
|
|
86
|
+
**Sintoma:** reaplicar a label não dispara nada; ou o `run` local recusa executar com
|
|
87
|
+
`⛔ trigger-pending`.
|
|
88
|
+
|
|
89
|
+
**Causa:** o evento `issues: [labeled]` não redispara com a label já presente, e o `run`
|
|
90
|
+
recusa rodar com gatilho pendente — a label significa "Action em execução", ou uma que
|
|
91
|
+
falhou e a deixou para trás.
|
|
92
|
+
|
|
93
|
+
**Como resolver:** remover e reaplicar. No modo local, onde nenhuma Action está rodando, a
|
|
94
|
+
label é resíduo: **remova-a em vez de usar `--force`**, para a issue não mentir sobre o
|
|
95
|
+
estado.
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
gh api -X DELETE "repos/<owner>/<repo>/issues/<n>/labels/spec-wave:spec"
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Nem sempre a label fica: em algumas falhas a CLI a remove sozinha no início do run.
|
|
102
|
+
Confira issue a issue em vez de supor — o `preflight` já lista as pendentes.
|
|
103
|
+
|
|
104
|
+
## 6. `spec-wave:spec` sobrescreve spec revisada
|
|
105
|
+
|
|
106
|
+
A label **regenera** o documento do zero. Se a spec já foi revisada, editada à mão ou
|
|
107
|
+
corrigida, reaplicar joga tudo fora para consertar o que muitas vezes é uma frase.
|
|
108
|
+
|
|
109
|
+
Para correção pontual em documento já gerado, a edição direta é permitida **quando o
|
|
110
|
+
usuário pede explicitamente** — e só nesse caso. Edite no PR: as edições são preservadas.
|
|
111
|
+
|
|
112
|
+
## 7. `spec-wave update` reescreve os workflows
|
|
113
|
+
|
|
114
|
+
O `update` compara os workflows com os templates da CLI e sobrescreve os divergentes. Toda
|
|
115
|
+
customização local neles é perdida no bump, silenciosamente, e o sintoma só aparece na
|
|
116
|
+
próxima geração.
|
|
117
|
+
|
|
118
|
+
Se o repositório tem workflows customizados de propósito, rode `update --skip-repo`, ou
|
|
119
|
+
reaplique a customização antes de commitar o bump. Confirme depois:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
git show origin/main:.github/workflows/generate-spec.yml | grep <marca-da-customizacao>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## 8. Runs `skipped` são normais — não são falha
|
|
126
|
+
|
|
127
|
+
O evento `issues: [labeled]` dispara **todos** os workflows que escutam labels; cada um se
|
|
128
|
+
filtra pelo próprio `if:`. Ver `generate-plan` e `decompose` como `skipped` depois de
|
|
129
|
+
aplicar `spec-wave:spec` é o comportamento correto, não um problema.
|
|
130
|
+
|
|
131
|
+
O mesmo vale para o repositório em modo `local`: todo job carrega
|
|
132
|
+
`if: vars.SPEC_WAVE_EXECUTION != 'local'`, então o run aparece verde e `skipped`, sem erro
|
|
133
|
+
e sem documento. Se você aplicou uma label e nada aconteceu, confira o modo antes de
|
|
134
|
+
procurar defeito: `npx @spec-wave/cli@latest mode`.
|
|
135
|
+
|
|
136
|
+
Ao procurar o run que interessa, filtre pelo workflow **e** pelo título da issue.
|
|
137
|
+
|
|
138
|
+
## 9. `conclusion` vazia não é conclusão
|
|
139
|
+
|
|
140
|
+
O `gh run list` devolve `conclusion` como **string vazia** — não `null` — enquanto o run
|
|
141
|
+
está em andamento. Um filtro `select(.conclusion != null)` deixa passar runs que ainda
|
|
142
|
+
estão rodando, e você conclui cedo demais que tudo terminou.
|
|
143
|
+
|
|
144
|
+
Filtre por `.status == "completed"` **e** `conclusion` não-vazia.
|
|
145
|
+
|
|
146
|
+
## 10. Geração leva minutos — não rode em primeiro plano
|
|
147
|
+
|
|
148
|
+
Uma spec é uma chamada de modelo gerando um documento longo: leva minutos. Rodar no
|
|
149
|
+
primeiro plano de uma ferramenta com timeout curto faz o comando morrer no meio — e o custo
|
|
150
|
+
já foi pago.
|
|
151
|
+
|
|
152
|
+
Rode em background, ou com timeout generoso (10 min por Feature). Numa milestone grande em
|
|
153
|
+
modo local isso passa de uma hora em série; combine com o usuário antes de começar.
|
|
154
|
+
|
|
155
|
+
## 11. Run interrompido deixa lock órfão
|
|
156
|
+
|
|
157
|
+
**Sintoma:** `Já existe um 'spec-wave run' para <n> (pid NNNN, desde ...)` e a geração é
|
|
158
|
+
recusada, mesmo não havendo nada rodando.
|
|
159
|
+
|
|
160
|
+
**Causa:** o `run` grava `.git/spec-wave/run-<n>.lock` para impedir duas execuções na mesma
|
|
161
|
+
issue. Um run morto por timeout ou Ctrl-C não tem chance de limpar o próprio lock.
|
|
162
|
+
|
|
163
|
+
**Como resolver — confirmando antes:** o lock guarda o pid, então dá para verificar se o
|
|
164
|
+
processo realmente morreu em vez de apagar no escuro:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
cat .git/spec-wave/run-<n>.lock # {"pid":NNNN,"startedAt":"..."}
|
|
168
|
+
ps -p NNNN >/dev/null && echo VIVO || echo morto
|
|
169
|
+
rm .git/spec-wave/run-<n>.lock # só se morto
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
O cuidado importa quando você rodou várias Features: pode haver um lock órfão e outro de um
|
|
173
|
+
run **em andamento** ao lado. Apagar o lock errado põe dois `run` na mesma issue.
|
|
174
|
+
|
|
175
|
+
A boa notícia é que a interrupção em si é limpa — o documento não é publicado pela metade.
|
|
176
|
+
Confirme com a ausência de PR novo antes de rerodar.
|
|
177
|
+
|
|
178
|
+
## 12. O documento foi gerado e o PR não nasceu
|
|
179
|
+
|
|
180
|
+
**Sintoma:** o passo termina, o commit existe na branch `spec-wave/<n>-<doc>` — e nenhum PR
|
|
181
|
+
aparece. O documento fica numa branch que ninguém está olhando, e a próxima execução, se
|
|
182
|
+
ninguém perceber, **regera por cima**.
|
|
183
|
+
|
|
184
|
+
**Causa:** a publicação precisa de `pull-requests: write` **e** de a organização permitir
|
|
185
|
+
que Actions abram PRs. A segunda parte é a traiçoeira: *"Allow GitHub Actions to create and
|
|
186
|
+
approve pull requests"* (Settings → Actions → General) vem desligada por padrão em muitas
|
|
187
|
+
organizações, e o erro não se parece com falta de permissão.
|
|
188
|
+
|
|
189
|
+
**Como resolver:** ligar a opção, ou definir um PAT no secret `GH_PR_TOKEN`. O `preflight`
|
|
190
|
+
e o `doctor` verificam os dois; o estado `⚠ em branch sem PR` no inventário é exatamente
|
|
191
|
+
este caso.
|
|
192
|
+
|
|
193
|
+
Não se aplica ao modo `local`, onde o token é o seu.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Nota histórica: o regime anterior à 0.27.0
|
|
198
|
+
|
|
199
|
+
Até a 0.26.0 a geração publicava com `commit` + `pull --rebase` + `push` **na branch
|
|
200
|
+
default**, a partir do checkout. Duas armadilhas vinham daí e **não valem mais**:
|
|
201
|
+
|
|
202
|
+
- **push rejeitado com `GH013`** em repositório que exige PR — a falha vinha *depois* de o
|
|
203
|
+
modelo ter gerado o documento, e o conteúdo se perdia com o runner;
|
|
204
|
+
- **working tree sujo quebrava toda geração local**, porque qualquer arquivo modificado
|
|
205
|
+
travava o `pull --rebase`.
|
|
206
|
+
|
|
207
|
+
Hoje a publicação é por API, em branch própria por documento, sem tocar no checkout. Se o
|
|
208
|
+
`preflight` apontar uma CLI antiga fixada nos workflows, as duas voltam a valer — e a
|
|
209
|
+
saída é `npx @spec-wave/cli@latest update --branch`.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Fase 3 — revisão de conteúdo
|
|
2
|
+
|
|
3
|
+
O gerador escreve cada spec isoladamente, a partir do corpo de uma issue. Ele é bom nisso:
|
|
4
|
+
as seções vêm completas, os requisitos rastreados, os fluxos coerentes **dentro** do
|
|
5
|
+
documento. O que ele estruturalmente não consegue ver é a relação entre os documentos —
|
|
6
|
+
porque, quando escreveu o primeiro, os outros não existiam.
|
|
7
|
+
|
|
8
|
+
É exatamente aí que moram os problemas que custam caro depois. Por isso a regra desta fase:
|
|
9
|
+
**leia as specs como conjunto, não uma a uma.**
|
|
10
|
+
|
|
11
|
+
## Como ler
|
|
12
|
+
|
|
13
|
+
Leia todas na íntegra antes de julgar qualquer uma. Ao ler a quinta, você reconhece na
|
|
14
|
+
primeira uma contradição que era invisível quando ela era o único documento.
|
|
15
|
+
|
|
16
|
+
Vale montar, enquanto lê, um mapa mental de três coisas:
|
|
17
|
+
|
|
18
|
+
- **regras compartilhadas** — um teto, uma ordem de prioridade, uma janela de tempo que
|
|
19
|
+
aparece em mais de uma feature;
|
|
20
|
+
- **quem depende de quem** — e em que direção cada spec declara a dependência;
|
|
21
|
+
- **afirmações sobre o mundo** — "tal feature ainda não existe", "isso é feito por X".
|
|
22
|
+
|
|
23
|
+
As três classes de problema abaixo saem desse mapa.
|
|
24
|
+
|
|
25
|
+
## Classe 1 — contradição entre specs
|
|
26
|
+
|
|
27
|
+
Duas features descrevem a mesma regra de formas que não fecham: contagens diferentes,
|
|
28
|
+
prioridades diferentes, a mesma janela de tempo medida a partir de marcos diferentes.
|
|
29
|
+
|
|
30
|
+
Isso é grave porque cada spec, sozinha, parece certa. O erro só existe no par — e vira dois
|
|
31
|
+
comportamentos incompatíveis em produção, descobertos na integração.
|
|
32
|
+
|
|
33
|
+
Ao encontrar, verifique qual das duas está alinhada com a fonte normativa (o corpo da issue,
|
|
34
|
+
o documento de requisitos) antes de propor a correção. Frequentemente uma está certa e a
|
|
35
|
+
outra derivou.
|
|
36
|
+
|
|
37
|
+
## Classe 2 — dependência que não fecha
|
|
38
|
+
|
|
39
|
+
Três formatos, todos vistos de verdade:
|
|
40
|
+
|
|
41
|
+
**Aponta para algo que não existe.** A feature A declara que seu componente vive na feature
|
|
42
|
+
B, e a spec de B não menciona esse componente em lugar nenhum. Alguém vai descobrir isso na
|
|
43
|
+
implementação, quando já for caro.
|
|
44
|
+
|
|
45
|
+
**Direção invertida ou circular.** A declara depender de B enquanto B declara depender de A.
|
|
46
|
+
Uma spec bem gerada às vezes corrige isso sozinha e **documenta a correção** — quando vir
|
|
47
|
+
uma nota dessas, confira se a outra ponta concorda.
|
|
48
|
+
|
|
49
|
+
**Inversão de sequenciamento entre milestones.** A dependência bloqueante está numa
|
|
50
|
+
milestone que vence *depois* da que depende dela. Não é erro de spec — é erro de
|
|
51
|
+
planejamento que só aparece quando se olha as datas junto com as dependências. Levante
|
|
52
|
+
sempre, porque ninguém mais vai olhar para os dois ao mesmo tempo.
|
|
53
|
+
|
|
54
|
+
**Como verificar de forma barata:** `spec-wave audit --milestone <nome>` cruza as
|
|
55
|
+
seções de Dependências de todas as specs e acusa ciclo, inversão de milestone,
|
|
56
|
+
referência sem alvo e sobreposição com código (Fase 3.5 da skill). O que sobra
|
|
57
|
+
para o olho é a parte semântica: a outra ponta concorda com a direção e o
|
|
58
|
+
escopo do que foi declarado?
|
|
59
|
+
|
|
60
|
+
## Classe 3 — afirmação que a própria rodada tornou falsa
|
|
61
|
+
|
|
62
|
+
Esta é sutil e específica de gerar várias specs de uma vez: a spec gerada às 10h afirma
|
|
63
|
+
"tal feature ainda não possui spec" e às 10h20 essa spec passa a existir — gerada pela
|
|
64
|
+
mesma rodada.
|
|
65
|
+
|
|
66
|
+
**Cuidado ao corrigir:** a mesma frase costuma aparecer várias vezes no documento, sobre
|
|
67
|
+
alvos diferentes, e só algumas ficaram obsoletas. Verifique alvo por alvo antes de editar.
|
|
68
|
+
Corrigir por padrão de texto transforma afirmação verdadeira em falsa.
|
|
69
|
+
|
|
70
|
+
E note *como* corrigir: quando a afirmação obsoleta era a **justificativa** de um TODO, a
|
|
71
|
+
pergunta não desaparece — ela muda de razão. Reescreva a justificativa apontando onde a
|
|
72
|
+
questão vive agora, em vez de apagar a frase e deixar o TODO sem explicação.
|
|
73
|
+
|
|
74
|
+
## Também procure
|
|
75
|
+
|
|
76
|
+
- **Sobreposição com feature já entregue.** Se uma spec descreve algo que uma feature
|
|
77
|
+
fechada já faz, há risco de duplicar comportamento em produção. Confira o estado da issue
|
|
78
|
+
antiga — "fechada" muda a conversa de "coordenar" para "não quebrar o que existe".
|
|
79
|
+
- **Regra que contradiz outra regra da mesma spec.** Raro, mas acontece quando uma regra é
|
|
80
|
+
categórica ("nunca expor dado individual") e outra define um recorte fino o bastante para
|
|
81
|
+
violá-la na prática. Vale destacar: costuma ser o achado de maior severidade.
|
|
82
|
+
- **Parâmetro declarado como "definido previamente" que ninguém definiu.** Limiares, prazos,
|
|
83
|
+
número de tentativas. Individualmente parecem detalhe; juntos costumam ser uma decisão só,
|
|
84
|
+
sem dono.
|
|
85
|
+
|
|
86
|
+
## Como classificar o que encontrou
|
|
87
|
+
|
|
88
|
+
**Achado material** — muda o desenho de uma feature, ou tem risco em produção. Vai como
|
|
89
|
+
comentário na issue correspondente, contendo: a regra que o originou (citada), por que não
|
|
90
|
+
se resolve no `plan`, e a decisão necessária. Se o achado tem dois lados (duas features
|
|
91
|
+
discordando), comente **nos dois**, apontando um para o outro — quem abrir só uma issue
|
|
92
|
+
precisa enxergar o quadro inteiro.
|
|
93
|
+
|
|
94
|
+
**Lacuna paramétrica** — falta um número. Não bloqueia o `plan`. Agrupe por tema no
|
|
95
|
+
relatório final: doze lacunas espalhadas costumam ser seis decisões, e uma lista de doze
|
|
96
|
+
itens soltos não é acionável.
|
|
97
|
+
|
|
98
|
+
O teste para separar as duas: *se ninguém decidir isso, o que acontece?* Se a resposta é
|
|
99
|
+
"implementam errado" ou "duas partes se comportam de formas incompatíveis", é material. Se
|
|
100
|
+
é "implementam com um valor provisório e ajustam depois", é paramétrico.
|
|
101
|
+
|
|
102
|
+
## O que não fazer
|
|
103
|
+
|
|
104
|
+
Não reescreva a spec para consertar o que encontrou. A spec é registro do que foi gerado a
|
|
105
|
+
partir da fonte normativa; a correção de regra é decisão do PO, e o lugar dela é a issue.
|
|
106
|
+
Editar o documento direto faz a decisão parecer tomada — e ninguém consegue rastrear quem
|
|
107
|
+
a tomou.
|
|
108
|
+
|
|
109
|
+
A exceção é o erro factual puro (Classe 3), que não é decisão de ninguém — e, mesmo aí,
|
|
110
|
+
só com pedido explícito do usuário.
|
|
@@ -16,6 +16,9 @@ Atualiza **somente o que divergiu** da versão da CLI: a **skill** instalada (po
|
|
|
16
16
|
| `--skip-skill` | Não verifica/atualiza a skill instalada. |
|
|
17
17
|
| `--skip-config` | Não verifica/atualiza o `.spec-wave.json`. |
|
|
18
18
|
| `--skip-repo` | Não verifica/atualiza workflows e labels do repo. |
|
|
19
|
+
| `--branch [nome]` | Envia os arquivos do repo como **Pull Request** numa branch, em um único commit (sem valor: `spec-wave/update-v<versão>`). |
|
|
20
|
+
| `--config-in-pr` / `--no-config-in-pr` | Força incluir/excluir o `.spec-wave.json` do PR. |
|
|
21
|
+
| `--skill-in-pr` / `--no-skill-in-pr` | Força incluir/excluir a skill dos agentes do PR. |
|
|
19
22
|
| `--dry-run` | Mostra o que seria atualizado sem alterar nada. |
|
|
20
23
|
| `--yes` | Aplica sem pedir confirmação. |
|
|
21
24
|
|
|
@@ -28,15 +31,18 @@ Atualiza **somente o que divergiu** da versão da CLI: a **skill** instalada (po
|
|
|
28
31
|
|
|
29
32
|
2. Mostre ao usuário o resumo por categoria (skill / config / arquivos do repo / labels). Se **nada** divergiu, informe que já está tudo na versão atual e encerre.
|
|
30
33
|
|
|
31
|
-
3. Com a aprovação, aplique
|
|
34
|
+
3. Com a aprovação, aplique — e **prefira o Pull Request**:
|
|
32
35
|
```bash
|
|
33
|
-
npx @spec-wave/cli@latest update --yes
|
|
36
|
+
npx @spec-wave/cli@latest update --yes --branch # 1 commit atômico + PR (recomendado)
|
|
37
|
+
npx @spec-wave/cli@latest update --yes # commits diretos na branch default
|
|
34
38
|
```
|
|
35
39
|
Limite o escopo com `--skip-skill`, `--skip-config` ou `--skip-repo` se o usuário só quiser parte.
|
|
36
40
|
|
|
37
41
|
4. **Onde cada coisa aterrissa:**
|
|
38
|
-
- **
|
|
39
|
-
-
|
|
42
|
+
- **workflows e templates de issue** → no PR (com `--branch`) ou commitados direto na branch default
|
|
43
|
+
- **labels** → sempre direto na base: são metadado do repositório, não há como versioná-las
|
|
44
|
+
- **`.spec-wave.json` e a skill** → o comando **consulta a base** e vai pelo mesmo caminho do arquivo: se o repositório já versiona aquele caminho, a atualização entra no PR; se não versiona, fica só local e o usuário precisa commitá-la. Force com `--config-in-pr` / `--skill-in-pr` se o projeto quiser passar a versionar.
|
|
45
|
+
- a skill é gravada em disco nos dois casos — é a cópia que o agente carrega
|
|
40
46
|
|
|
41
47
|
5. Se a skill foi atualizada, oriente a **recarregar/reiniciar o agente** para pegar a nova versão.
|
|
42
48
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: spec-wave-workflow
|
|
3
|
-
description: "Use quando a pergunta for sobre o fluxo spec-wave como um todo — qual é a próxima etapa de uma issue, o que cada coluna do Kanban significa, quais labels disparam quais Actions, como funciona a crítica adversarial, ou quando o usuário pedir spec-wave sem dizer qual comando. É o mapa do processo RFC-001; para executar uma ação específica, use a skill do comando correspondente (setup, issue, spec, plan, ready, decompose, implement, order, task, story, move, doctor, update, info, uninstall, rfc, fix-pr)."
|
|
3
|
+
description: "Use quando a pergunta for sobre o fluxo spec-wave como um todo — qual é a próxima etapa de uma issue, o que cada coluna do Kanban significa, quais labels disparam quais Actions, como funciona a crítica adversarial, ou quando o usuário pedir spec-wave sem dizer qual comando. É o mapa do processo RFC-001; para executar uma ação específica, use a skill do comando correspondente (setup, issue, spec, plan, ready, decompose, run, bug, triage, implement, order, task, story, move, doctor, update, info, uninstall, rfc, fix-pr); para conduzir um trecho inteiro do fluxo de uma vez, preparar-feature (uma Feature até Ready) ou preparar-specs (as specs de uma milestone)."
|
|
4
4
|
allowed-tools:
|
|
5
5
|
- Bash(npx @spec-wave/cli@latest *)
|
|
6
6
|
- Bash(gh issue *)
|
|
@@ -148,6 +148,11 @@ O slug vem do **título**: `[FEATURE] Cadastro de Pedidos com PIX` → `cadastro
|
|
|
148
148
|
| gerar o plano técnico | `plan` |
|
|
149
149
|
| validar spec+plan | `ready` |
|
|
150
150
|
| quebrar em Stories/Tasks | `decompose` |
|
|
151
|
+
| levar uma Feature da spec até ✅ Ready, de ponta a ponta | `preparar-feature` |
|
|
152
|
+
| gerar as specs de uma milestone inteira | `preparar-specs` |
|
|
153
|
+
| rodar o fluxo localmente / desarmar os workflows | `run` |
|
|
154
|
+
| registrar ou corrigir um Bug | `bug` |
|
|
155
|
+
| triar um Bug | `triage` |
|
|
151
156
|
| implementar | `implement` |
|
|
152
157
|
| ver ordem das Stories | `order` |
|
|
153
158
|
| mover Task | `task` |
|
|
@@ -40,3 +40,16 @@ existing_services:
|
|
|
40
40
|
internal_libraries:
|
|
41
41
|
- "shared-logger"
|
|
42
42
|
- "db-client (TypeORM)"
|
|
43
|
+
|
|
44
|
+
# Decisões de modelagem de recursos COMPARTILHADOS entre features (opcional).
|
|
45
|
+
#
|
|
46
|
+
# `criada_por:` é obrigatório em cada entrada: a Feature que cria o recurso
|
|
47
|
+
# (ex.: "FT-01.7" ou "#42"), ou o literal SEM DONO enquanto ninguém o criar.
|
|
48
|
+
# "Não existe feature para editar esses valores" escrito em prosa fica meses
|
|
49
|
+
# sem ninguém agir; SEM DONO aparece no `spec-wave audit` como pendência de
|
|
50
|
+
# checklist antes de planejar a milestone.
|
|
51
|
+
#
|
|
52
|
+
# decisoes_de_modelagem:
|
|
53
|
+
# - recurso: "custo_canal"
|
|
54
|
+
# decisao: "Tabela própria; valores editados por ADMIN, consumidos por 4 features"
|
|
55
|
+
# criada_por: "SEM DONO"
|
|
@@ -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|move|uninstall|rfc|bug|triage|fix-pr] [target]"
|
|
4
|
+
argument-hint: "[info|setup|update|doctor|preflight|audit|issue|feature|spec|plan|ready|decompose|order|implement|merge|task|story|move|uninstall|rfc|bug|triage|fix-pr] [target]"
|
|
5
5
|
user-invocable: true
|
|
6
6
|
allowed-tools:
|
|
7
7
|
- Bash(npx @spec-wave/cli@latest *)
|
|
@@ -77,7 +77,7 @@ npx @spec-wave/cli@latest mode # estado atual dos dois lados do
|
|
|
77
77
|
npx @spec-wave/cli@latest mode local # desarma os workflows
|
|
78
78
|
npx @spec-wave/cli@latest run <issue> --dry-run # explica o próximo passo sem executar
|
|
79
79
|
npx @spec-wave/cli@latest run <issue> # executa
|
|
80
|
-
npx @spec-wave/cli@latest run --pr <n> # code-review (+ qa, se
|
|
80
|
+
npx @spec-wave/cli@latest run --pr <n> # code-review (+ qa, se aprovado OU mergeado)
|
|
81
81
|
```
|
|
82
82
|
|
|
83
83
|
O `run` decide o passo pelo estado da issue (documentos existentes + labels), respeita os portões humanos (`needs-human`, `critique-failed`), recusa rodar com uma label de gatilho pendente e **exige `--apply`** para o `decompose-apply`, que cria issues. Sempre mostre o `--dry-run` ao usuário antes de executar.
|
|
@@ -208,6 +208,7 @@ Mesmas flags do `issue` (exceto `--type`, fixo em `feature`). Mantido para o flu
|
|
|
208
208
|
| `--skip-skill` / `--skip-config` / `--skip-repo` | flag | Pula a categoria correspondente. |
|
|
209
209
|
| `--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>`. |
|
|
210
210
|
| `--config-in-pr` / `--no-config-in-pr` | flag | Força incluir/excluir o `.spec-wave.json` do PR (o default decide sozinho — veja abaixo). |
|
|
211
|
+
| `--skill-in-pr` / `--no-skill-in-pr` | flag | Força incluir/excluir a **skill dos agentes** do PR (o default decide sozinho — veja abaixo). |
|
|
211
212
|
| `--dry-run` | flag | Mostra o que seria atualizado sem alterar nada. |
|
|
212
213
|
| `--yes` | flag | Aplica sem pedir confirmação. |
|
|
213
214
|
|
|
@@ -215,7 +216,9 @@ Mesmas flags do `issue` (exceto `--type`, fixo em `feature`). Mantido para o flu
|
|
|
215
216
|
|
|
216
217
|
> **`--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.
|
|
217
218
|
>
|
|
218
|
-
>
|
|
219
|
+
> As **labels** nunca entram no PR: são metadado do repositório, não há como versioná-las — já valem na base, com ou sem o merge. O corpo do PR diz isso a quem revisa.
|
|
220
|
+
>
|
|
221
|
+
> A **skill** e o **`.spec-wave.json`** seguem a mesma regra, e ela é **verificada, não presumida**: o comando pergunta à base se aquele arquivo já é versionado. Se for (repos que commitam `.claude/skills/spec-wave/SKILL.md`, `.agents/skills/`, `AGENTS.md`, `.cursor/rules/…`), a atualização entra no PR junto com os workflows; se não for, fica só na máquina local. Passar a versionar (ou deixar de versionar) é decisão do projeto — use `--skill-in-pr` / `--no-skill-in-pr` para forçar.
|
|
219
222
|
>
|
|
220
223
|
> ⚠️ 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.
|
|
221
224
|
|
|
@@ -250,7 +253,33 @@ Sem flags. Roda um checklist de diagnóstico no repositório atual: token GitHub
|
|
|
250
253
|
|----------|------|-----------|
|
|
251
254
|
| `<feature>` | string (obrigatório) | Número da issue da **Feature**, ex.: `12` ou `#12`. Argumento posicional. |
|
|
252
255
|
|
|
253
|
-
> **Sem argumento**, monta o mapa de TODAS as Features abertas fora de 🎉 Done num grafo só (conjunto vindo do board), com a Feature de cada Story ao lado — nesse escopo a dependência entre Features entra na ordenação. Com `<feature>`, lista as Stories da Feature em **ordem topológica** pelas dependências (linha `Depende de: #N` no corpo + relação nativa *blocked by*, mescladas), com a Etapa atual de cada uma no board. Dependências para **fora da Feature** não entram na ordenação (não há como saber onde a Story de outra Feature entra nesta sequência), mas aparecem em **"Bloqueadas por fora desta Feature"**, com o estado de cada bloqueadora. Avisa sobre **ciclos de dependência** (essas Stories ficam fora da ordem — corrija as linhas `Depende de`)
|
|
256
|
+
> **Sem argumento**, monta o mapa de TODAS as Features abertas fora de 🎉 Done num grafo só (conjunto vindo do board), com a Feature de cada Story ao lado — nesse escopo a dependência entre Features entra na ordenação. Com `<feature>`, lista as Stories da Feature em **ordem topológica** pelas dependências (linha `Depende de: #N` no corpo + relação nativa *blocked by*, mescladas), com a Etapa atual de cada uma no board. Dependências para **fora da Feature** não entram na ordenação (não há como saber onde a Story de outra Feature entra nesta sequência), mas aparecem em **"Bloqueadas por fora desta Feature"**, com o estado de cada bloqueadora. Avisa sobre **ciclos de dependência** (essas Stories ficam fora da ordem — corrija as linhas `Depende de`), sobre **dependências fora de ordem** (Story já em Desenvolvimento+ dependendo de outra que não está Done) e sobre **milestone divergente** (Story sem milestone ou em milestone diferente do da Feature — órfã de toda visão de release; sem milestone na Feature, nada é comparado). Use antes de escolher qual Story implementar, e logo após o `decompose --apply` como detector do pós-apply.
|
|
257
|
+
|
|
258
|
+
### `@spec-wave/cli preflight --milestone <nome>` — confere tudo ANTES de gerar as specs (comando LOCAL)
|
|
259
|
+
| Flag/Arg | Tipo | Descrição |
|
|
260
|
+
|----------|------|-----------|
|
|
261
|
+
| `--milestone <nome>` | string (obrigatório) | Título da milestone a inventariar. |
|
|
262
|
+
| `--json` | boolean | O relatório em JSON, para ramificar. |
|
|
263
|
+
|
|
264
|
+
> Um comando reporta: token utilizável, modo de execução (config × variável do repositório), publicação por PR, e as Features da milestone com o **estado do `spec.md` de cada uma** (na base, no disco, em PR aberto, em branch sem PR, a gerar). Existe porque **cada geração paga um modelo**: um erro de configuração descoberto na sétima Feature custa sete gerações — e regenerar um documento que já vive num PR descarta a revisão em curso. Sai com código 1 quando há bloqueio. Rode SEMPRE antes de uma rodada de specs por milestone.
|
|
265
|
+
|
|
266
|
+
### `@spec-wave/cli audit --milestone <nome>` — cruza as specs da milestone como CONJUNTO (comando LOCAL)
|
|
267
|
+
| Flag/Arg | Tipo | Descrição |
|
|
268
|
+
|----------|------|-----------|
|
|
269
|
+
| `--milestone <nome>` | string (obrigatório) | Título da milestone a auditar. |
|
|
270
|
+
| `--critique` | boolean | Roda também a **crítica adversarial de conjunto** — UMA chamada de modelo sobre todas as specs juntas, procurando contradição ENTRE documentos. |
|
|
271
|
+
| `--json` | boolean | O relatório em JSON (com `critica.markdown` pronto para comentar nas issues). |
|
|
272
|
+
|
|
273
|
+
> A crítica normal audita cada documento contra os insumos da **mesma** Feature; este comando olha o que só existe **no par**: dependência circular entre Features, bloqueante em milestone **posterior** à de quem depende dela, referência a issue inexistente (materiais — exit 1), dependência que nenhuma Feature cria ("recurso sem dono"), sobreposição do slug com código existente e decisão de modelagem com `criada_por: SEM DONO` no `tech_context.yml` (avisos heurísticos — **confira antes de reportar**). Rode depois que as specs existirem (PR aberto também conta), antes de gerar os planos. Achado material é decisão de PO: comente nas issues **dos dois lados**.
|
|
274
|
+
|
|
275
|
+
### `@spec-wave/cli merge <feature>` — mergeia os PRs empilhados das Stories (comando LOCAL)
|
|
276
|
+
| Flag/Arg | Tipo | Descrição |
|
|
277
|
+
|----------|------|-----------|
|
|
278
|
+
| `<feature>` | string (obrigatório) | Número da issue da **Feature**, ex.: `12` ou `#12`. |
|
|
279
|
+
| `--yes` | boolean | Executa os merges. **Sem ela, só mostra o plano** (fila na ordem, retargets, avisos). |
|
|
280
|
+
| `--keep-branches` | boolean | Não apaga as branches das Stories após o merge. |
|
|
281
|
+
|
|
282
|
+
> O `implement` empilha os PRs (cada um baseado no anterior) e o merge da pilha é **ordem-dependente**: `--delete-branch` no primeiro PR fecha o segundo. Este comando encapsula a sequência segura — para cada PR na ordem topológica das Stories: reaponta a base para a default, mergeia com **merge commit**, atualiza o board (**merge move até 🧪 QA**) e **só no fim** apaga as branches. **PR em rascunho bloqueia o plano inteiro** (marcar pronto é a revisão humana — o comando não pula isso). Rodar de novo **retoma**: PR mergeado sai do plano. Use após a revisão, em vez de mergear à mão com `gh`.
|
|
254
283
|
|
|
255
284
|
### `@spec-wave/cli task <start|done> <n>` — transições de Task no board (comando LOCAL)
|
|
256
285
|
| Flag/Arg | Tipo | Descrição |
|
|
@@ -459,8 +488,8 @@ Traz tudo para a versão atual da CLI, atualizando **só o que mudou**: a skill
|
|
|
459
488
|
- Escopos podem ser limitados com `--skip-skill`, `--skip-config`, `--skip-repo`.
|
|
460
489
|
- **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.
|
|
461
490
|
- **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`.
|
|
462
|
-
- **Nos dois modos**, as **labels** são aplicadas direto na base (metadado do repositório, não versionável) e
|
|
463
|
-
- **`.spec-wave.json
|
|
491
|
+
- **Nos dois modos**, as **labels** são aplicadas direto na base (metadado do repositório, não versionável) e nunca entram no PR.
|
|
492
|
+
- **`.spec-wave.json` e skill:** com `--branch`, cada um entra no PR se o repositório **já o versiona** (o comando consulta a base, arquivo a arquivo); se não versiona, segue apenas local e o usuário precisa commitá-lo — ou use `--config-in-pr` / `--skill-in-pr` para passar a versioná-lo. Sem `--branch`, os dois são sempre só locais. A skill é gravada em disco de qualquer forma, para o agente já pegar a versão nova.
|
|
464
493
|
4. Se a skill foi atualizada, oriente recarregar/reiniciar o agente para pegar a nova versão.
|
|
465
494
|
|
|
466
495
|
---
|
|
@@ -689,7 +718,7 @@ Aciona o spec-kit para implementar uma **Feature** (todas as Stories pendentes,
|
|
|
689
718
|
- Se o spec-kit **não** estiver configurado, o comando só monta o contexto e mostra como configurar (`specKit.command` / `SPEC_WAVE_IMPLEMENT_CMD`). Ajude o usuário a definir o template (placeholders: `{tasksFile} {specFile} {planFile} {issue} {type} {title}`).
|
|
690
719
|
- Use `--feature-dir docs/features/<slug>` se a resolução automática da Feature falhar (a skill avisa com warning) e você quiser anexar `spec.md`/`plan.md` como contexto.
|
|
691
720
|
6. **No modo Feature**, siga o contexto Story a Story, na ordem listada: para cada Story pendente, implemente as Tasks com `task start`/`task done`, depois commit + PR + `npx @spec-wave/cli@latest story review <n>`; só então passe à próxima Story. **Bug** tem modo próprio (RFC-004): sem tasks e sem spec/plan, com quatro fases — reproduzir → causa raiz → fix mínimo → teste de regressão — e o `bug.md` entrando como hipótese a confirmar. Se a issue não for Feature, Story, Task nem Bug (ex.: Spike, Epic), o comando recusa. Feature **sem Stories** → rode `/spec-wave decompose` primeiro. **Ciclo de dependências** → corrija as linhas `Depende de:` (veja `spec-wave order`).
|
|
692
|
-
7. Ao final (Tasks em **🎉 Done**, Story em **👀 Code Review**; a Feature só vai para Code Review quando a última Story concluir — no modo Feature, isso acontece dentro da mesma execução): confirme o resultado com o usuário e oriente a revisão dos PRs.
|
|
721
|
+
7. Ao final (Tasks em **🎉 Done**, Story em **👀 Code Review**; a Feature só vai para Code Review quando a última Story concluir — no modo Feature, isso acontece dentro da mesma execução): confirme o resultado com o usuário e oriente a revisão dos PRs. **Avise que os PRs estão empilhados** e que o merge é ordem-dependente: depois da revisão (PRs marcados prontos), o caminho é `npx @spec-wave/cli@latest merge <feature>` — nunca `gh pr merge --delete-branch` à mão em PR de pilha.
|
|
693
722
|
|
|
694
723
|
---
|
|
695
724
|
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
name: QA
|
|
2
2
|
|
|
3
|
+
# Dois gatilhos, um destino: aprovação formal OU merge movem a Feature para
|
|
4
|
+
# 🧪 QA. O de merge existe porque o autor não consegue aprovar o próprio PR —
|
|
5
|
+
# num fluxo solo, QA por aprovação nunca aconteceria — e porque homologação de
|
|
6
|
+
# verdade começa com o código integrado. Espelha o `run --pr` do modo local.
|
|
3
7
|
on:
|
|
4
8
|
pull_request_review:
|
|
5
9
|
types: [submitted]
|
|
10
|
+
pull_request:
|
|
11
|
+
types: [closed]
|
|
6
12
|
|
|
7
13
|
concurrency:
|
|
8
14
|
group: spec-wave-qa-${{ github.event.pull_request.number }}
|
|
@@ -25,10 +31,12 @@ jobs:
|
|
|
25
31
|
# Aqui a guarda é INDISPENSÁVEL, não defensiva: `pull_request_review`
|
|
26
32
|
# dispara por uma aprovação HUMANA, independentemente de quem abriu o
|
|
27
33
|
# PR. Aprovar o PR da spec moveria a Feature para 🧪 QA.
|
|
34
|
+
# A última linha aceita os dois eventos: review aprovada (pull_request_review)
|
|
35
|
+
# ou PR fechado COM merge (pull_request closed — fechado sem merge não conta).
|
|
28
36
|
if: >
|
|
29
37
|
vars.SPEC_WAVE_EXECUTION != 'local' &&
|
|
30
38
|
!startsWith(github.event.pull_request.head.ref, 'spec-wave/') &&
|
|
31
|
-
github.event.review.state == 'approved'
|
|
39
|
+
(github.event.review.state == 'approved' || github.event.pull_request.merged == true)
|
|
32
40
|
runs-on: ubuntu-latest
|
|
33
41
|
permissions:
|
|
34
42
|
issues: write
|