@spec-wave/cli 0.5.7 → 0.5.8
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 +390 -0
- package/bin/spec-wave.mjs +14 -0
- package/package.json +1 -1
- package/src/commands/init.mjs +1 -1
- package/src/commands/install-skill.mjs +292 -0
- package/src/templates/skill/SKILL.md +517 -0
package/README.md
ADDED
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
# @spec-wave/cli
|
|
2
|
+
|
|
3
|
+
CLI e skill para implementar um fluxo **spec-driven** completo no GitHub — do backlog ao deploy — com GitHub Projects v2, labels de gatilho e GitHub Actions com IA.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Conceito
|
|
8
|
+
|
|
9
|
+
Spec Wave é um sistema de processo de desenvolvimento baseado em especificações. Cada Feature passa por um ciclo documentado antes de ser implementada:
|
|
10
|
+
|
|
11
|
+
1. **Spec funcional** gerada por IA a partir do título e descrição da issue
|
|
12
|
+
2. **Plano técnico** gerado por IA a partir da spec e do contexto tecnológico do repositório
|
|
13
|
+
3. **Validação automática** das seções obrigatórias
|
|
14
|
+
4. **Decomposição em Stories e Tasks** gerada por IA
|
|
15
|
+
5. **Automação do board** durante o ciclo de desenvolvimento (Code Review → QA → Done)
|
|
16
|
+
|
|
17
|
+
O resultado é um board Kanban no GitHub Projects v2 que avança automaticamente conforme o trabalho progride, com toda a documentação versionada no próprio repositório.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Fluxo Kanban
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
📥 Backlog
|
|
25
|
+
→ 🎯 Priorizado
|
|
26
|
+
→ 📋 Spec ← label spec-wave:spec → Action gera spec.md
|
|
27
|
+
→ 📋 Plan ← label spec-wave:plan → Action gera plan.md
|
|
28
|
+
→ ✅ Ready ← label spec-wave:ready → Action valida ambos
|
|
29
|
+
→ 📋 Backlog Técnico
|
|
30
|
+
→ 🚧 Desenvolvimento ← comando local: spec-wave implement <n>
|
|
31
|
+
→ 👀 Code Review ← PR aberto → Action move automaticamente
|
|
32
|
+
→ 🧪 QA ← PR aprovado → Action move automaticamente
|
|
33
|
+
→ 📋 Homologação
|
|
34
|
+
→ 🚀 Deploy
|
|
35
|
+
→ 🎉 Done
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Hierarquia de Work Items
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
Initiative
|
|
44
|
+
└── Epic
|
|
45
|
+
└── Feature
|
|
46
|
+
├── Story
|
|
47
|
+
│ └── Task
|
|
48
|
+
└── Task
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Cada nível é uma GitHub Issue com prefixo no título (`[FEATURE]`, `[STORY]`, etc.) e vínculo de sub-issue nativo do GitHub.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Componentes
|
|
56
|
+
|
|
57
|
+
### CLI (`@spec-wave/cli`)
|
|
58
|
+
|
|
59
|
+
Ferramenta Node.js que configura e opera o fluxo via linha de comando.
|
|
60
|
+
|
|
61
|
+
| Comando | O que faz |
|
|
62
|
+
|---------|-----------|
|
|
63
|
+
| `init` | Cria o GitHub Project, labels, workflows e `.spec-wave.json` |
|
|
64
|
+
| `info` | Mostra o estado de configuração do repositório atual |
|
|
65
|
+
| `refresh` | Re-sincroniza o `.spec-wave.json` com o GitHub Project |
|
|
66
|
+
| `issue` | Cria qualquer work item (initiative/epic/feature/story/task/bug/spike/rfc) |
|
|
67
|
+
| `initiative` | Atalho para `issue --type initiative` |
|
|
68
|
+
| `feature` | Atalho para `issue --type feature` |
|
|
69
|
+
| `generate-spec` | Gera `spec.md` (usado pelo GitHub Action) |
|
|
70
|
+
| `generate-plan` | Gera `plan.md` (usado pelo GitHub Action) |
|
|
71
|
+
| `validate` | Valida spec.md e plan.md (usado pelo GitHub Action) |
|
|
72
|
+
| `decompose` | Decompõe Feature em Stories e Tasks (usado pelo GitHub Action) |
|
|
73
|
+
| `code-review` | Move Feature para Code Review ao abrir PR (usado pelo GitHub Action) |
|
|
74
|
+
| `qa` | Move Feature para QA ao aprovar PR (usado pelo GitHub Action) |
|
|
75
|
+
| `implement` | Aciona o spec-kit localmente para implementar uma Story ou Task |
|
|
76
|
+
| `uninstall` | Remove labels, workflows e `.spec-wave.json` |
|
|
77
|
+
|
|
78
|
+
### GitHub Actions (instalados pelo `init`)
|
|
79
|
+
|
|
80
|
+
| Workflow | Gatilho | Ação |
|
|
81
|
+
|----------|---------|------|
|
|
82
|
+
| `generate-spec.yml` | label `spec-wave:spec` | Gera `docs/features/<slug>/spec.md` via IA |
|
|
83
|
+
| `generate-plan.yml` | label `spec-wave:plan` | Gera `docs/features/<slug>/plan.md` via IA |
|
|
84
|
+
| `validate.yml` | label `spec-wave:ready` | Valida seções obrigatórias; adiciona `spec-wave:plan-approved` |
|
|
85
|
+
| `decompose.yml` | label `spec-wave:decompose` | Cria Stories e Tasks como sub-issues |
|
|
86
|
+
| `code-review.yml` | PR aberto/reaberto | Move Feature para `👀 Code Review` |
|
|
87
|
+
| `qa.yml` | PR aprovado | Move Feature para `🧪 QA` |
|
|
88
|
+
|
|
89
|
+
### Skill (`src/templates/skill/SKILL.md`)
|
|
90
|
+
|
|
91
|
+
Skill que guia o usuário pelo fluxo via comandos como `/spec-wave spec 42`, `/spec-wave plan 42`, `/spec-wave decompose 42`. A skill lê o `.spec-wave.json` local, detecta o estado atual e executa os comandos corretos sem abrir wizards interativos. Instale-a no seu agente com `install-skill` (ver abaixo).
|
|
92
|
+
|
|
93
|
+
### `.spec-wave.json`
|
|
94
|
+
|
|
95
|
+
Arquivo de configuração gerado pelo `init` na raiz do repositório. Armazena `owner/repo`, dados do GitHub Project (ID, URL, campos) e o provider de IA configurado. Todos os comandos leem este arquivo para operar sem precisar de flags adicionais.
|
|
96
|
+
|
|
97
|
+
### `tech_context.yml`
|
|
98
|
+
|
|
99
|
+
Arquivo em `.github/config/tech_context.yml` que descreve a stack tecnológica do sistema (backend, frontend, banco, infra, roles RBAC, schemas, serviços). O `generate-plan` usa este arquivo para embasar o plano técnico — sem ele, o plano fica genérico.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Pré-requisitos
|
|
104
|
+
|
|
105
|
+
- Node.js >= 20
|
|
106
|
+
- GitHub CLI (`gh`) autenticado com escopos `project`, `repo` e `workflow`:
|
|
107
|
+
```bash
|
|
108
|
+
gh auth refresh --scopes project,repo,workflow
|
|
109
|
+
```
|
|
110
|
+
- Secret no repositório: `ANTHROPIC_API_KEY` ou `OPENROUTER_API_KEY` (Settings → Secrets → Actions)
|
|
111
|
+
- Para repositórios em organizações: criar PAT com escopo `project` e adicionar como secret `GH_PROJECT_TOKEN`
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Instalação da CLI
|
|
116
|
+
|
|
117
|
+
Não é necessário instalar globalmente — use `npx`:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
npx @spec-wave/cli --help
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Para instalar globalmente:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
npm install -g @spec-wave/cli
|
|
127
|
+
spec-wave --help
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Instalação da Skill
|
|
133
|
+
|
|
134
|
+
A skill permite usar o fluxo diretamente no seu agente via `/spec-wave`.
|
|
135
|
+
|
|
136
|
+
**1. Instale a skill com o comando `install-skill`:**
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
# Autodetecta o agente em uso e instala no local/formato correto
|
|
140
|
+
npx @spec-wave/cli install-skill
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
O comando suporta Claude Code, Cursor, opencode, Cline, Kilo Code, Antigravity e o
|
|
144
|
+
padrão genérico `AGENTS.md`. Por padrão instala no escopo do projeto (versionável
|
|
145
|
+
com o time); use `--global` para o escopo do usuário. Escolha alvos com
|
|
146
|
+
`--agent <nomes>` (ex.: `--agent claude,cursor`) ou `--all` para todos os
|
|
147
|
+
detectados. Use `--dry-run` para pré-visualizar sem gravar.
|
|
148
|
+
|
|
149
|
+
**2. Adicione ao `CLAUDE.md` (ou equivalente) do projeto:**
|
|
150
|
+
|
|
151
|
+
```markdown
|
|
152
|
+
# spec-wave skill
|
|
153
|
+
Trigger `/spec-wave` to invoke the spec-wave skill.
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**3. Use no seu agente:**
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
/spec-wave setup
|
|
160
|
+
/spec-wave spec 42
|
|
161
|
+
/spec-wave plan 42
|
|
162
|
+
/spec-wave ready 42
|
|
163
|
+
/spec-wave decompose 42
|
|
164
|
+
/spec-wave implement 45
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Exemplo de uso — do início ao fim
|
|
170
|
+
|
|
171
|
+
### Contexto
|
|
172
|
+
|
|
173
|
+
Equipe quer implementar uma feature de "Checkout com PIX" em um repositório `acme/loja`.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
### 1. Configurar o repositório
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
# Verificar autenticação
|
|
181
|
+
gh auth status
|
|
182
|
+
|
|
183
|
+
# Se faltarem escopos:
|
|
184
|
+
gh auth refresh --scopes project,repo,workflow
|
|
185
|
+
|
|
186
|
+
# Configurar spec-wave (cria Project, labels e workflows)
|
|
187
|
+
npx @spec-wave/cli init --repo acme/loja --project-title "Loja — Spec Wave"
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
O `init` cria:
|
|
191
|
+
- GitHub Project v2 com 12 colunas Kanban e campos personalizados (Work Item Type, Priority, Story Points, Area)
|
|
192
|
+
- 20+ labels de tipo, prioridade e gatilho
|
|
193
|
+
- 6 GitHub Actions workflows em `.github/workflows/`
|
|
194
|
+
- `.spec-wave.json` com os IDs do Project
|
|
195
|
+
|
|
196
|
+
Adicionar o secret de IA no GitHub: **Settings → Secrets → Actions → `ANTHROPIC_API_KEY`**.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
### 2. Criar a hierarquia de issues
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
# Criar Epic
|
|
204
|
+
npx @spec-wave/cli issue \
|
|
205
|
+
--type epic \
|
|
206
|
+
--title "Checkout e Pagamentos" \
|
|
207
|
+
--priority P1 \
|
|
208
|
+
--area Backend
|
|
209
|
+
# → Issue #5 criada: [EPIC] Checkout e Pagamentos
|
|
210
|
+
|
|
211
|
+
# Criar Feature como sub-issue do Epic
|
|
212
|
+
npx @spec-wave/cli feature \
|
|
213
|
+
--title "Checkout com PIX" \
|
|
214
|
+
--parent 5 \
|
|
215
|
+
--priority P1 \
|
|
216
|
+
--area Backend
|
|
217
|
+
# → Issue #12 criada: [FEATURE] Checkout com PIX (sub-issue de #5)
|
|
218
|
+
# → Adicionada ao board em 📥 Backlog
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
### 3. Gerar a especificação funcional
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
gh issue edit 12 --add-label "spec-wave:spec"
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
O GitHub Action `generate-spec.yml` dispara, chama a IA e faz commit de:
|
|
230
|
+
```
|
|
231
|
+
docs/features/checkout-com-pix/spec.md
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
A issue #12 recebe um comentário com o link para o arquivo.
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
### 4. Gerar o plano técnico
|
|
239
|
+
|
|
240
|
+
Antes de gerar o plano, garanta que `.github/config/tech_context.yml` existe e reflete a stack real. O `init` cria um scaffold — edite-o:
|
|
241
|
+
|
|
242
|
+
```yaml
|
|
243
|
+
system_info:
|
|
244
|
+
name: "Loja ACME"
|
|
245
|
+
stack:
|
|
246
|
+
backend: "Node.js (NestJS v11)"
|
|
247
|
+
frontend: "Next.js 16"
|
|
248
|
+
database: "PostgreSQL (Prisma 5)"
|
|
249
|
+
infra: "Docker / AWS ECS"
|
|
250
|
+
security:
|
|
251
|
+
auth_protocol: "JWT"
|
|
252
|
+
rbac_roles: ["ADMIN", "CUSTOMER"]
|
|
253
|
+
database_schemas:
|
|
254
|
+
- table: "orders"
|
|
255
|
+
columns: "id, customer_id, status, total, created_at"
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
git add .github/config/tech_context.yml
|
|
260
|
+
git commit -m "chore: tech_context.yml"
|
|
261
|
+
git push
|
|
262
|
+
|
|
263
|
+
# Acionar geração do plano
|
|
264
|
+
gh issue edit 12 --add-label "spec-wave:plan"
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
O Action gera `docs/features/checkout-com-pix/plan.md` com:
|
|
268
|
+
- Estratégia Técnica e Matriz de Rastreabilidade
|
|
269
|
+
- Detalhamento da Implementação
|
|
270
|
+
- Segurança e Conformidade
|
|
271
|
+
- Estratégia de Testes
|
|
272
|
+
- Rollback e Monitoramento
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
### 5. Validar spec e plan
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
gh issue edit 12 --add-label "spec-wave:ready"
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
O Action `validate.yml` verifica se todas as seções obrigatórias estão presentes em spec.md e plan.md. Se passar:
|
|
283
|
+
- Remove a label `spec-wave:ready`
|
|
284
|
+
- Adiciona a label `spec-wave:plan-approved`
|
|
285
|
+
- Comenta "Validação aprovada ✅" na issue
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
### 6. Decompor em Stories e Tasks
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
gh issue edit 12 --add-label "spec-wave:decompose"
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
O Action `decompose.yml` usa IA para criar sub-issues da Feature #12:
|
|
296
|
+
|
|
297
|
+
```
|
|
298
|
+
#13 [STORY] Como cliente, quero selecionar PIX como forma de pagamento
|
|
299
|
+
#14 [TASK] Criar endpoint POST /orders/:id/payment/pix
|
|
300
|
+
#15 [TASK] Integrar API do banco via webhook
|
|
301
|
+
#16 [TASK] Exibir QR Code na tela de checkout
|
|
302
|
+
#17 [STORY] Como cliente, quero receber confirmação do pagamento
|
|
303
|
+
#18 [TASK] Webhook de confirmação do banco
|
|
304
|
+
#19 [TASK] Notificação por e-mail ao confirmar
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
Todas as Stories e Tasks são adicionadas ao board em **📋 Backlog Técnico** com Status `Todo`.
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
### 7. Implementar
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
# Via skill no Claude Code:
|
|
315
|
+
/spec-wave implement 13
|
|
316
|
+
|
|
317
|
+
# Ou direto:
|
|
318
|
+
npx @spec-wave/cli implement 13 --dry-run # ver contexto antes
|
|
319
|
+
npx @spec-wave/cli implement 13 # executar
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
O comando monta um arquivo de contexto com spec.md, plan.md e todas as Tasks da Story, e aciona o spec-kit configurado.
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
### 8. Code Review automático
|
|
327
|
+
|
|
328
|
+
Ao abrir um PR que referencia `Closes #14` (ou qualquer issue da hierarquia):
|
|
329
|
+
|
|
330
|
+
```markdown
|
|
331
|
+
## Descrição
|
|
332
|
+
Implementa endpoint PIX
|
|
333
|
+
|
|
334
|
+
Closes #14
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
O Action `code-review.yml` detecta a referência, sobe a hierarquia Task → Story → Feature, e move a Feature #12 para **👀 Code Review** no board.
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
### 9. QA automático
|
|
342
|
+
|
|
343
|
+
Quando um reviewer aprova o PR, o Action `qa.yml` move a Feature #12 para **🧪 QA**.
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
### 10. Estado final no board
|
|
348
|
+
|
|
349
|
+
```
|
|
350
|
+
Feature #12: [FEATURE] Checkout com PIX
|
|
351
|
+
Etapa: 🧪 QA
|
|
352
|
+
Status: Todo
|
|
353
|
+
Work Item Type: Feature
|
|
354
|
+
Priority: P1
|
|
355
|
+
Area: Backend
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
Após QA passar, mover manualmente para **📋 Homologação → 🚀 Deploy → 🎉 Done**.
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
## Atualizar repositórios existentes
|
|
363
|
+
|
|
364
|
+
Quando uma nova versão da CLI for publicada, rode em cada repositório configurado:
|
|
365
|
+
|
|
366
|
+
```bash
|
|
367
|
+
npx @spec-wave/cli@latest init --skip-project --skip-labels
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
Isso atualiza apenas os arquivos de workflow sem recriar o Project ou as labels.
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Providers de IA
|
|
375
|
+
|
|
376
|
+
| Provider | Secret | Modelo padrão |
|
|
377
|
+
|----------|--------|---------------|
|
|
378
|
+
| Anthropic | `ANTHROPIC_API_KEY` | `claude-sonnet-4-6` |
|
|
379
|
+
| OpenRouter | `OPENROUTER_API_KEY` | `anthropic/claude-3.7-sonnet` |
|
|
380
|
+
|
|
381
|
+
Configurar no `init`:
|
|
382
|
+
```bash
|
|
383
|
+
npx @spec-wave/cli init --repo owner/repo --provider openrouter --model anthropic/claude-3.7-sonnet
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
## Licença
|
|
389
|
+
|
|
390
|
+
MIT
|
package/bin/spec-wave.mjs
CHANGED
|
@@ -86,6 +86,20 @@ program
|
|
|
86
86
|
await feature(options).catch(err => { console.error(err.message); process.exit(1); });
|
|
87
87
|
});
|
|
88
88
|
|
|
89
|
+
program
|
|
90
|
+
.command('install-skill')
|
|
91
|
+
.description('Instala a skill spec-wave no(s) agente(s) detectado(s): Claude Code, Cursor, opencode, Cline, Kilo, Antigravity, AGENTS.md')
|
|
92
|
+
.option('--agent <names>', 'Agente(s) alvo, separados por vírgula (pula a detecção)')
|
|
93
|
+
.option('--all', 'Instala em todos os agentes detectados')
|
|
94
|
+
.option('--global', 'Instala no escopo do usuário (padrão: projeto)')
|
|
95
|
+
.option('--dry-run', 'Mostra o que seria instalado sem gravar')
|
|
96
|
+
.option('--force', 'Sobrescreve arquivos existentes sem confirmar')
|
|
97
|
+
.option('--yes', 'Modo não-interativo')
|
|
98
|
+
.action(async (options) => {
|
|
99
|
+
const { installSkill } = await import('../src/commands/install-skill.mjs');
|
|
100
|
+
await installSkill(options).catch(err => { console.error(err.message); process.exit(1); });
|
|
101
|
+
});
|
|
102
|
+
|
|
89
103
|
program
|
|
90
104
|
.command('uninstall')
|
|
91
105
|
.description('Remove labels, arquivos .github e o .spec-wave.json (mantém o GitHub Project)')
|
package/package.json
CHANGED
package/src/commands/init.mjs
CHANGED
|
@@ -218,6 +218,6 @@ export async function init(options) {
|
|
|
218
218
|
` 2. Configure o board view para agrupar por "Etapa"\n` +
|
|
219
219
|
` 3. Crie uma Feature com o prefixo [FEATURE] no título\n` +
|
|
220
220
|
` 4. Use a skill spec-wave para guiar o fluxo\n\n` +
|
|
221
|
-
` ${chalk.dim('Para
|
|
221
|
+
` ${chalk.dim('Para instalar a skill no seu agente: npx @spec-wave/cli install-skill')}`
|
|
222
222
|
);
|
|
223
223
|
}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import * as p from '@clack/prompts';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import yaml from 'js-yaml';
|
|
4
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { homedir } from 'node:os';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
|
|
9
|
+
const __dir = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
// Fonte única da skill, publicada via "files": ["src"] no package.json.
|
|
11
|
+
const SKILL_SOURCE = path.join(__dir, '..', 'templates', 'skill', 'SKILL.md');
|
|
12
|
+
|
|
13
|
+
// Marcadores usados para gravar/atualizar a skill de forma idempotente em
|
|
14
|
+
// arquivos compartilhados (AGENTS.md) — permite reinstalar sem duplicar.
|
|
15
|
+
const BLOCK_START = '<!-- spec-wave:start -->';
|
|
16
|
+
const BLOCK_END = '<!-- spec-wave:end -->';
|
|
17
|
+
|
|
18
|
+
// Registro de agentes suportados. Cada alvo descreve como detectá-lo no
|
|
19
|
+
// diretório-base, onde gravar (projeto vs. global) e em que formato converter
|
|
20
|
+
// o SKILL.md. Caminhos conferidos na doc oficial de cada ferramenta.
|
|
21
|
+
const TARGETS = [
|
|
22
|
+
{
|
|
23
|
+
key: 'claude',
|
|
24
|
+
name: 'Claude Code',
|
|
25
|
+
format: 'skill',
|
|
26
|
+
detect: ['.claude'],
|
|
27
|
+
project: '.claude/skills/spec-wave/SKILL.md',
|
|
28
|
+
global: '.claude/skills/spec-wave/SKILL.md',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
key: 'opencode',
|
|
32
|
+
name: 'opencode',
|
|
33
|
+
format: 'skill',
|
|
34
|
+
detect: ['.opencode'],
|
|
35
|
+
project: '.opencode/skills/spec-wave/SKILL.md',
|
|
36
|
+
global: '.config/opencode/skills/spec-wave/SKILL.md',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
key: 'cursor',
|
|
40
|
+
name: 'Cursor',
|
|
41
|
+
format: 'mdc',
|
|
42
|
+
detect: ['.cursor'],
|
|
43
|
+
project: '.cursor/rules/spec-wave.mdc',
|
|
44
|
+
global: null, // Cursor user rules não são baseadas em arquivo.
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
key: 'cline',
|
|
48
|
+
name: 'Cline',
|
|
49
|
+
format: 'rules',
|
|
50
|
+
detect: ['.clinerules'],
|
|
51
|
+
project: '.clinerules/spec-wave.md',
|
|
52
|
+
global: null,
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
key: 'kilo',
|
|
56
|
+
name: 'Kilo Code',
|
|
57
|
+
format: 'rules',
|
|
58
|
+
detect: ['.kilocode'],
|
|
59
|
+
project: '.kilocode/rules/spec-wave.md',
|
|
60
|
+
global: '.kilocode/rules/spec-wave.md',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
key: 'antigravity',
|
|
64
|
+
name: 'Antigravity',
|
|
65
|
+
format: 'rules',
|
|
66
|
+
detect: ['.agent', 'GEMINI.md'],
|
|
67
|
+
project: '.agent/rules/spec-wave.md',
|
|
68
|
+
global: '.gemini/AGENTS.md',
|
|
69
|
+
globalFormat: 'agents', // ~/.gemini/AGENTS.md é compartilhado → append.
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
key: 'agents',
|
|
73
|
+
name: 'AGENTS.md (genérico)',
|
|
74
|
+
format: 'agents',
|
|
75
|
+
detect: ['AGENTS.md'],
|
|
76
|
+
project: 'AGENTS.md',
|
|
77
|
+
global: '.config/opencode/AGENTS.md',
|
|
78
|
+
},
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
const TARGET_BY_KEY = new Map(TARGETS.map((t) => [t.key, t]));
|
|
82
|
+
|
|
83
|
+
// Separa o frontmatter YAML do corpo do SKILL.md. Retorna { meta, body }.
|
|
84
|
+
function parseSkill(raw) {
|
|
85
|
+
const match = raw.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
|
|
86
|
+
if (!match) return { meta: {}, body: raw.trim() };
|
|
87
|
+
let meta = {};
|
|
88
|
+
try {
|
|
89
|
+
meta = yaml.load(match[1]) || {};
|
|
90
|
+
} catch {
|
|
91
|
+
meta = {};
|
|
92
|
+
}
|
|
93
|
+
return { meta, body: match[2].trim() };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Converte o SKILL.md para o formato exigido por cada agente.
|
|
97
|
+
function renderContent(format, raw, parsed) {
|
|
98
|
+
const { meta, body } = parsed;
|
|
99
|
+
const description = meta.description ?? 'Skill spec-wave.';
|
|
100
|
+
switch (format) {
|
|
101
|
+
case 'skill':
|
|
102
|
+
// Claude Code / opencode consomem o SKILL.md nativo. Campos extras do
|
|
103
|
+
// frontmatter são ignorados pelo opencode — sem problema.
|
|
104
|
+
return raw.trimEnd() + '\n';
|
|
105
|
+
case 'mdc':
|
|
106
|
+
return (
|
|
107
|
+
`---\n` +
|
|
108
|
+
`description: ${JSON.stringify(description)}\n` +
|
|
109
|
+
`alwaysApply: false\n` +
|
|
110
|
+
`---\n\n` +
|
|
111
|
+
`${body}\n`
|
|
112
|
+
);
|
|
113
|
+
case 'rules':
|
|
114
|
+
return `# spec-wave\n\n${description}\n\n${body}\n`;
|
|
115
|
+
case 'agents':
|
|
116
|
+
return `${BLOCK_START}\n\n# spec-wave\n\n${description}\n\n${body}\n\n${BLOCK_END}\n`;
|
|
117
|
+
default:
|
|
118
|
+
return raw;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Insere/atualiza o bloco spec-wave num arquivo compartilhado (AGENTS.md),
|
|
123
|
+
// preservando o restante do conteúdo. Idempotente via marcadores.
|
|
124
|
+
function mergeAgentsFile(destPath, block) {
|
|
125
|
+
const existing = existsSync(destPath) ? readFileSync(destPath, 'utf-8') : '';
|
|
126
|
+
const blockRe = new RegExp(
|
|
127
|
+
`${escapeRe(BLOCK_START)}[\\s\\S]*?${escapeRe(BLOCK_END)}\\n?`,
|
|
128
|
+
);
|
|
129
|
+
if (blockRe.test(existing)) {
|
|
130
|
+
return existing.replace(blockRe, block);
|
|
131
|
+
}
|
|
132
|
+
if (existing.trim() === '') return block;
|
|
133
|
+
return `${existing.trimEnd()}\n\n${block}`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function escapeRe(s) {
|
|
137
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Resolve o alvo do agente para um destino concreto no escopo escolhido.
|
|
141
|
+
// Retorna null quando o agente não suporta o escopo global.
|
|
142
|
+
function resolveDest(target, baseDir, isGlobal) {
|
|
143
|
+
const rel = isGlobal ? target.global : target.project;
|
|
144
|
+
if (!rel) return null;
|
|
145
|
+
const format = isGlobal && target.globalFormat ? target.globalFormat : target.format;
|
|
146
|
+
return { path: path.join(baseDir, rel), format };
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Retorna true se algum dos sinais de detecção existir em baseDir.
|
|
150
|
+
function isDetected(target, baseDir) {
|
|
151
|
+
return target.detect.some((sig) => existsSync(path.join(baseDir, sig)));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export async function installSkill(options = {}) {
|
|
155
|
+
p.intro(chalk.bold('spec-wave install-skill'));
|
|
156
|
+
|
|
157
|
+
if (!existsSync(SKILL_SOURCE)) {
|
|
158
|
+
p.log.error(`SKILL.md não encontrado no pacote (${SKILL_SOURCE}).`);
|
|
159
|
+
process.exitCode = 1;
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const raw = readFileSync(SKILL_SOURCE, 'utf-8');
|
|
163
|
+
const parsed = parseSkill(raw);
|
|
164
|
+
|
|
165
|
+
const isGlobal = !!options.global;
|
|
166
|
+
const baseDir = isGlobal ? homedir() : process.cwd();
|
|
167
|
+
const scopeLabel = isGlobal ? 'global (usuário)' : 'projeto (local)';
|
|
168
|
+
|
|
169
|
+
// 1) Determinar quais agentes receberão a skill.
|
|
170
|
+
let selectedKeys;
|
|
171
|
+
if (options.agent) {
|
|
172
|
+
const requested = String(options.agent)
|
|
173
|
+
.split(',')
|
|
174
|
+
.map((s) => s.trim().toLowerCase())
|
|
175
|
+
.filter(Boolean);
|
|
176
|
+
const invalid = requested.filter((k) => !TARGET_BY_KEY.has(k));
|
|
177
|
+
if (invalid.length) {
|
|
178
|
+
p.log.error(
|
|
179
|
+
`Agente(s) inválido(s): ${invalid.join(', ')}.\n` +
|
|
180
|
+
`Válidos: ${TARGETS.map((t) => t.key).join(', ')}.`,
|
|
181
|
+
);
|
|
182
|
+
process.exitCode = 1;
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
selectedKeys = requested;
|
|
186
|
+
} else {
|
|
187
|
+
const detected = TARGETS.filter((t) => isDetected(t, baseDir)).map((t) => t.key);
|
|
188
|
+
|
|
189
|
+
if (options.all) {
|
|
190
|
+
if (!detected.length) {
|
|
191
|
+
p.log.error(
|
|
192
|
+
`Nenhum agente detectado em ${scopeLabel}. Use --agent <nome> para escolher manualmente.`,
|
|
193
|
+
);
|
|
194
|
+
process.exitCode = 1;
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
selectedKeys = detected;
|
|
198
|
+
} else if (options.yes) {
|
|
199
|
+
if (!detected.length) {
|
|
200
|
+
p.log.error(
|
|
201
|
+
`Nenhum agente detectado em ${scopeLabel}. Use --agent <nome> em modo não-interativo.`,
|
|
202
|
+
);
|
|
203
|
+
process.exitCode = 1;
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
selectedKeys = detected;
|
|
207
|
+
} else {
|
|
208
|
+
const answer = await p.multiselect({
|
|
209
|
+
message: `Onde instalar a skill? (escopo: ${scopeLabel})`,
|
|
210
|
+
options: TARGETS.map((t) => ({
|
|
211
|
+
value: t.key,
|
|
212
|
+
label: t.name,
|
|
213
|
+
hint: isDetected(t, baseDir) ? 'detectado' : undefined,
|
|
214
|
+
})),
|
|
215
|
+
initialValues: detected,
|
|
216
|
+
required: true,
|
|
217
|
+
});
|
|
218
|
+
if (p.isCancel(answer)) {
|
|
219
|
+
p.cancel('Instalação cancelada.');
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
selectedKeys = answer;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// 2) Resolver destinos, avisando sobre escopos não suportados.
|
|
227
|
+
const jobs = [];
|
|
228
|
+
for (const key of selectedKeys) {
|
|
229
|
+
const target = TARGET_BY_KEY.get(key);
|
|
230
|
+
const dest = resolveDest(target, baseDir, isGlobal);
|
|
231
|
+
if (!dest) {
|
|
232
|
+
p.log.warn(`${target.name}: escopo global não suportado — pulado.`);
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
jobs.push({ target, dest });
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (!jobs.length) {
|
|
239
|
+
p.log.warn('Nenhum destino a instalar.');
|
|
240
|
+
p.outro('Nada foi feito.');
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// 3) Dry-run: apenas listar.
|
|
245
|
+
if (options.dryRun) {
|
|
246
|
+
p.note(
|
|
247
|
+
jobs
|
|
248
|
+
.map((j) => `${chalk.dim(j.target.name.padEnd(20))} ${j.dest.path} ${chalk.dim(`(${j.dest.format})`)}`)
|
|
249
|
+
.join('\n'),
|
|
250
|
+
`Dry-run — nada será gravado (escopo: ${scopeLabel})`,
|
|
251
|
+
);
|
|
252
|
+
p.outro('Dry-run concluído.');
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// 4) Gravar cada destino.
|
|
257
|
+
const written = [];
|
|
258
|
+
for (const { target, dest } of jobs) {
|
|
259
|
+
const content =
|
|
260
|
+
dest.format === 'agents'
|
|
261
|
+
? mergeAgentsFile(dest.path, renderContent('agents', raw, parsed))
|
|
262
|
+
: renderContent(dest.format, raw, parsed);
|
|
263
|
+
|
|
264
|
+
// Confirmar sobrescrita de arquivos "próprios" (skill/rules/mdc). Para
|
|
265
|
+
// 'agents' o merge por marcadores já é seguro (não apaga conteúdo alheio).
|
|
266
|
+
if (existsSync(dest.path) && dest.format !== 'agents' && !options.force && !options.yes) {
|
|
267
|
+
const ok = await p.confirm({
|
|
268
|
+
message: `${target.name}: ${dest.path} já existe. Sobrescrever?`,
|
|
269
|
+
initialValue: true,
|
|
270
|
+
});
|
|
271
|
+
if (p.isCancel(ok) || !ok) {
|
|
272
|
+
p.log.info(`${target.name}: mantido (não sobrescrito).`);
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
mkdirSync(path.dirname(dest.path), { recursive: true });
|
|
278
|
+
writeFileSync(dest.path, content, 'utf-8');
|
|
279
|
+
written.push({ target, dest });
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (!written.length) {
|
|
283
|
+
p.outro('Nada foi gravado.');
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
p.note(
|
|
288
|
+
written.map((w) => `${chalk.green('✓')} ${chalk.bold(w.target.name)}\n ${chalk.dim(w.dest.path)}`).join('\n'),
|
|
289
|
+
`Skill instalada (escopo: ${scopeLabel})`,
|
|
290
|
+
);
|
|
291
|
+
p.outro('Reinicie/recarregue o agente para que ele detecte a skill.');
|
|
292
|
+
}
|
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-wave
|
|
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|issue|feature|spec|plan|ready|decompose|implement|uninstall|rfc|fix-pr] [target]"
|
|
5
|
+
user-invocable: true
|
|
6
|
+
allowed-tools:
|
|
7
|
+
- Bash(npx spec-wave *)
|
|
8
|
+
- Bash(gh issue *)
|
|
9
|
+
- Bash(gh project *)
|
|
10
|
+
- Bash(gh repo view *)
|
|
11
|
+
- Bash(gh auth status)
|
|
12
|
+
- Bash(gh pr *)
|
|
13
|
+
- Bash(gh api *)
|
|
14
|
+
- Bash(git add *)
|
|
15
|
+
- Bash(git commit *)
|
|
16
|
+
- Bash(git push *)
|
|
17
|
+
- Bash(git checkout *)
|
|
18
|
+
- Read
|
|
19
|
+
- Edit
|
|
20
|
+
- Write
|
|
21
|
+
- Agent
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# spec-wave Skill
|
|
25
|
+
|
|
26
|
+
Este skill guia o usuário pelo fluxo spec-driven definido no RFC-001.
|
|
27
|
+
|
|
28
|
+
> **Antes de responder a qualquer sub-comando**, leia o arquivo `rfc/rfc-integrate-spec-kit-into-kanban.md` se ele existir no diretório atual, para embasar suas respostas no processo real da equipe.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Detecção de configuração (faça isto primeiro, sempre)
|
|
33
|
+
|
|
34
|
+
Antes de qualquer sub-comando, leia o arquivo `.spec-wave.json` na raiz do repositório atual (use o tool Read). Esse arquivo é gravado pelo `npx spec-wave init` e é a fonte de estado persistente entre sessões.
|
|
35
|
+
|
|
36
|
+
- **Se existir**, o spec-wave já foi configurado. Use seus campos para contextualizar as respostas, sem perguntar de novo:
|
|
37
|
+
- `owner`/`repo` → repositório alvo dos comandos `gh`
|
|
38
|
+
- `project.url` / `project.title` → o GitHub Project a referenciar
|
|
39
|
+
- `version` → versão da CLI usada no `init` (compare com `npx spec-wave --version`; se divergir, sugira `npx spec-wave refresh --config` para atualizar o arquivo, ou re-rodar o `init` para atualizar workflows/labels)
|
|
40
|
+
- `initializedAt` → quando foi configurado
|
|
41
|
+
Não rode `/spec-wave setup` de novo a menos que o usuário peça explicitamente.
|
|
42
|
+
- **Se não existir**, o repositório provavelmente ainda não foi configurado. Sugira começar por `/spec-wave setup`.
|
|
43
|
+
|
|
44
|
+
Exemplo de `.spec-wave.json`:
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"version": "0.1.0",
|
|
48
|
+
"owner": "acme",
|
|
49
|
+
"repo": "loja",
|
|
50
|
+
"project": {
|
|
51
|
+
"title": "loja — Spec Wave",
|
|
52
|
+
"url": "https://github.com/users/acme/projects/5",
|
|
53
|
+
"id": "PVT_..."
|
|
54
|
+
},
|
|
55
|
+
"initializedAt": "2026-06-18T13:40:00.000Z"
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Regra fundamental
|
|
62
|
+
|
|
63
|
+
**Nunca gere `spec.md` ou `plan.md` diretamente.** Sempre acione a label correspondente e deixe o GitHub Action gerar o arquivo. Isso garante que o arquivo seja commitado no repositório e referenciado na issue.
|
|
64
|
+
|
|
65
|
+
Exceção: se o usuário pedir explicitamente para revisar ou melhorar um documento já gerado, use o Write tool para editar o arquivo local.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Fluxo Kanban
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
📥 Backlog → 🎯 Priorizado → 📋 Spec → 📋 Plan → ✅ Ready
|
|
73
|
+
→ 📋 Backlog Técnico → 🚧 Desenvolvimento → 👀 Code Review
|
|
74
|
+
→ 🧪 QA → 📋 Homologação → 🚀 Deploy → 🎉 Done
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Labels de gatilho:
|
|
78
|
+
- `spec-wave:spec` → dispara `generate-spec.yml` → gera `spec.md` (especificação funcional, primeiro)
|
|
79
|
+
- `spec-wave:plan` → dispara `generate-plan.yml` → gera `plan.md` (plano técnico, a partir da spec)
|
|
80
|
+
- `spec-wave:ready` → dispara `validate.yml` → valida ambos os arquivos
|
|
81
|
+
- `spec-wave:decompose` → dispara `decompose.yml` → gera Stories e Tasks
|
|
82
|
+
|
|
83
|
+
A etapa **🚧 Desenvolvimento** é coberta pelo comando **local** `spec-wave implement <número>` (não é uma label/Action): lê uma Story ou Task e aciona o spec-kit para implementar. Veja `/spec-wave implement`.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Referência da CLI (conheça os parâmetros ANTES de executar)
|
|
88
|
+
|
|
89
|
+
Esta skill é um **wrapper** da CLI `spec-wave`. Regra de ouro: **nunca rode um comando sem os parâmetros que ele aceita** esperando que ele pergunte — colete os valores com o usuário e passe via flags. Em especial, **`init` sem `--repo` abre um wizard interativo (@clack/prompts) que a skill NÃO consegue dirigir** — sempre passe `--repo`.
|
|
90
|
+
|
|
91
|
+
### `spec-wave init` — configura o repositório
|
|
92
|
+
| Flag | Tipo | Descrição |
|
|
93
|
+
|------|------|-----------|
|
|
94
|
+
| `--repo <owner/repo>` | string | Repositório alvo. **Passe SEMPRE** para evitar o wizard interativo. |
|
|
95
|
+
| `--project-title <title>` | string | Nome do GitHub Project. Padrão: `<repo> — Spec Wave`. |
|
|
96
|
+
| `--skip-project` | flag | Pula a criação do Project (use ao re-rodar se já existe). |
|
|
97
|
+
| `--skip-labels` | flag | Pula a criação das labels. |
|
|
98
|
+
| `--skip-files` | flag | Pula a criação dos workflows + issue templates. |
|
|
99
|
+
| `--dry-run` | flag | Simula a configuração sem alterar nada. |
|
|
100
|
+
|
|
101
|
+
### `spec-wave issue` — cria um work item tipado, opcionalmente como sub-issue, e adiciona ao board
|
|
102
|
+
| Flag | Tipo | Descrição |
|
|
103
|
+
|------|------|-----------|
|
|
104
|
+
| `--title <title>` | string (obrigatório) | Título, **sem** o prefixo de tipo (a CLI adiciona, ex.: `[STORY]`). |
|
|
105
|
+
| `--type <type>` | string | `initiative`, `epic`, `feature`, `story`, `task`, `bug`, `spike` ou `rfc`. Default: `feature`. |
|
|
106
|
+
| `--parent <n>` | string | Número da issue pai — cria como **sub-issue** dela (relação nativa do GitHub). |
|
|
107
|
+
| `--body <text>` | string | Descrição. |
|
|
108
|
+
| `--priority <p>` | string | `P0`, `P1`, `P2` ou `P3`. |
|
|
109
|
+
| `--area <area>` | string | `Frontend`, `Backend`, `Mobile`, `Infra`, `DevOps` ou `Data`. |
|
|
110
|
+
|
|
111
|
+
> Faz tudo: cria a issue (label de tipo + prioridade), vincula ao parent como sub-issue, adiciona ao Project e define os campos **Etapa = 📥 Backlog**, **Work Item Type**, **Priority** e **Area**. Grava `Parent: #N` no corpo. Lê o Project do `.spec-wave.json`. **Não use `gh issue create` direto** — ele não adiciona ao board nem vincula o parent.
|
|
112
|
+
|
|
113
|
+
### `spec-wave initiative` — atalho de `issue --type initiative`
|
|
114
|
+
Cria o nó raiz da hierarquia (agrupa Epics). Mesmas flags do `issue` exceto `--type` (fixo em `initiative`) e `--parent` (Initiative é raiz, não tem pai).
|
|
115
|
+
|
|
116
|
+
### `spec-wave feature` — atalho de `issue --type feature`
|
|
117
|
+
Mesmas flags do `issue` (exceto `--type`, fixo em `feature`). Mantido para o fluxo do RFC-001.
|
|
118
|
+
|
|
119
|
+
### `spec-wave uninstall` — remove a configuração (mantém o Project)
|
|
120
|
+
| Flag | Tipo | Descrição |
|
|
121
|
+
|------|------|-----------|
|
|
122
|
+
| `--repo <owner/repo>` | string | Repositório (default: lê do `.spec-wave.json`). |
|
|
123
|
+
| `--skip-labels` | flag | Não remove as labels. |
|
|
124
|
+
| `--skip-files` | flag | Não remove os arquivos `.github`. |
|
|
125
|
+
| `--keep-config` | flag | Mantém o `.spec-wave.json` local. |
|
|
126
|
+
| `--dry-run` | flag | Mostra o que seria removido sem alterar nada. |
|
|
127
|
+
| `--yes` | flag | Não pede confirmação. |
|
|
128
|
+
|
|
129
|
+
> Remove labels + arquivos `.github` + `.spec-wave.json`. **NUNCA apaga o GitHub Project** (preserva o histórico do board) — o usuário deve excluí-lo manualmente se quiser.
|
|
130
|
+
|
|
131
|
+
### `spec-wave info` — status de configuração do repo atual
|
|
132
|
+
| Flag | Tipo | Descrição |
|
|
133
|
+
|------|------|-----------|
|
|
134
|
+
| `--json` | flag | Saída JSON (`{"initialized":bool, ...}`) para parsing programático. |
|
|
135
|
+
|
|
136
|
+
### `spec-wave refresh` — atualiza o `.spec-wave.json` local
|
|
137
|
+
| Flag | Tipo | Descrição |
|
|
138
|
+
|------|------|-----------|
|
|
139
|
+
| `--config` | flag | Re-consulta o GitHub Project e reescreve o `.spec-wave.json` (IDs do campo Etapa, opções, number, versão da CLI). |
|
|
140
|
+
|
|
141
|
+
> Use quando o `.spec-wave.json` estiver desatualizado: repos inicializados por uma versão antiga (sem `etapaFieldId`/`stageOptions`), Project renomeado, ou versão da CLI divergente. Escreve no arquivo **local** — faça commit depois.
|
|
142
|
+
|
|
143
|
+
### `spec-wave generate-plan` · `generate-spec` · `validate` · `decompose`
|
|
144
|
+
| Flag | Tipo | Descrição |
|
|
145
|
+
|------|------|-----------|
|
|
146
|
+
| `--issue-number <n>` | string (obrigatório) | Número da issue no GitHub. |
|
|
147
|
+
|
|
148
|
+
> ⚠️ 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).
|
|
149
|
+
|
|
150
|
+
### `spec-wave implement` — aciona o spec-kit para uma Story ou Task (comando LOCAL)
|
|
151
|
+
| Flag/Arg | Tipo | Descrição |
|
|
152
|
+
|----------|------|-----------|
|
|
153
|
+
| `<issue>` | string (obrigatório) | Número da issue (Story ou Task), ex.: `12` ou `#12`. Argumento posicional. |
|
|
154
|
+
| `--feature-dir <path>` | string | Caminho `docs/features/<slug>` para anexar `spec.md`/`plan.md` como contexto (sobrescreve a resolução automática). |
|
|
155
|
+
| `--dry-run` | flag | Monta o contexto e imprime o comando do spec-kit **sem executar**. |
|
|
156
|
+
|
|
157
|
+
> Diferente dos quatro acima, `implement` roda **localmente** (lê `.spec-wave.json`, como `issue`), não por Action. Detecta o tipo da issue: **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 já inclui uma instrução para o agente mover a Story e as Tasks para **🚧 Desenvolvimento** (in progress) ao iniciar.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Sub-comandos
|
|
162
|
+
|
|
163
|
+
### `/spec-wave info`
|
|
164
|
+
|
|
165
|
+
Mostra se o repositório atual já foi configurado com o spec-wave.
|
|
166
|
+
|
|
167
|
+
**Passos:**
|
|
168
|
+
1. Execute: `npx spec-wave info`
|
|
169
|
+
2. **Se o repositório estiver inicializado**, o comando mostra os dados do `.spec-wave.json` (owner/repo, project, versão da CLI, data). Apresente essas informações ao usuário.
|
|
170
|
+
3. **Se NÃO estiver inicializado**, pergunte ao usuário: "Este repositório ainda não foi configurado com o spec-wave. Quer rodar o `init` agora?"
|
|
171
|
+
- Se sim → siga o fluxo de `/spec-wave setup`.
|
|
172
|
+
- Se não → encerre sem alterar nada.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
### `/spec-wave setup`
|
|
177
|
+
|
|
178
|
+
Configura o spec-wave no repositório. Você dirige o `init` com flags — **nunca rode `npx spec-wave init` sem `--repo`** (abre o wizard interativo que você não controla).
|
|
179
|
+
|
|
180
|
+
**Passos:**
|
|
181
|
+
1. **Já configurado?** Leia `.spec-wave.json` (ou rode `npx spec-wave info`). Se existir, avise (mostre `project.url` e `version`) e confirme com o usuário antes de reconfigurar.
|
|
182
|
+
2. **Descubra o repositório alvo** (parâmetro `--repo`): rode `gh repo view --json nameWithOwner -q .nameWithOwner` para obter `owner/repo` do repo atual. Confirme com o usuário; se não houver remote, pergunte o `owner/repo`.
|
|
183
|
+
3. **Pergunte o título do Project** (parâmetro `--project-title`). Ofereça o default `<repo> — Spec Wave` e aceite-o se o usuário não tiver preferência.
|
|
184
|
+
4. **Cheque o auth:** `gh auth status`. Se faltarem os escopos `project,repo,workflow`, oriente o usuário a rodar ele mesmo `gh auth refresh --scopes project,repo,workflow` (comando interativo — o usuário executa, não você).
|
|
185
|
+
5. **(Opcional) Pré-visualize** antes de aplicar: `npx spec-wave init --repo <owner/repo> --dry-run`.
|
|
186
|
+
6. **Execute com os parâmetros coletados:**
|
|
187
|
+
```bash
|
|
188
|
+
npx spec-wave init --repo <owner/repo> --project-title "<título>"
|
|
189
|
+
```
|
|
190
|
+
Use `--skip-project` / `--skip-labels` / `--skip-files` **apenas** para re-rodar uma fase específica que falhou antes.
|
|
191
|
+
7. O `init` cria o Project, as labels, os workflows, um **scaffold de `.github/config/tech_context.yml`** (só se ainda não existir) e grava `.spec-wave.json`. Oriente o usuário a fazer `git pull` para trazer os arquivos ao checkout local.
|
|
192
|
+
8. **Adapte o `tech_context.yml`**: o scaffold vem com dados de exemplo. Ofereça ajustá-lo à stack real do repo seguindo a seção **Tech Context** (perto do comando `/spec-wave plan`) — isso melhora muito a qualidade do `plan.md`.
|
|
193
|
+
9. Instrua o usuário a adicionar a chave de IA como secret no repositório (Settings → Secrets → Actions): `ANTHROPIC_API_KEY` (Anthropic) ou `OPENROUTER_API_KEY` (OpenRouter), conforme o provider escolhido no `init`.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
### `/spec-wave issue <tipo> <descrição>` · `/spec-wave initiative <descrição>` · `/spec-wave feature <descrição>`
|
|
198
|
+
|
|
199
|
+
Crie um work item tipado (Initiative/Epic/Feature/Story/Task/...) já adicionado ao board em **📥 Backlog**, opcionalmente como sub-issue de um parent.
|
|
200
|
+
|
|
201
|
+
**Hierarquia típica:** Initiative → Epic → Feature → Story → Task. A **Initiative** é o nó raiz e agrupa Epics. Use `--parent <n>` para criar como sub-issue do nível acima (ex.: um Epic filho de uma Initiative, ou uma Story filha de uma Feature). O GitHub mostra o parent na issue filha e vice-versa; a CLI ainda grava `Parent: #N` no corpo.
|
|
202
|
+
|
|
203
|
+
**Passos:**
|
|
204
|
+
1. Pergunte ao usuário: tipo (initiative/epic/feature/story/task/...), título (sem prefixo), descrição, área, prioridade, e se há uma issue **pai** (número).
|
|
205
|
+
2. Execute o comando com os parâmetros coletados:
|
|
206
|
+
```bash
|
|
207
|
+
npx spec-wave issue \
|
|
208
|
+
--type "<tipo>" \
|
|
209
|
+
--title "<título>" \
|
|
210
|
+
--body "<descrição>" \
|
|
211
|
+
--area "<área>" \
|
|
212
|
+
--priority "<prioridade>" \
|
|
213
|
+
--parent "<número-do-pai>" # opcional
|
|
214
|
+
```
|
|
215
|
+
Para Features, pode usar o atalho `npx spec-wave feature --title ...` (equivale a `--type feature`).
|
|
216
|
+
A CLI cria a issue (label de tipo + prioridade), vincula como sub-issue do parent, adiciona ao Project e define Etapa = 📥 Backlog + Work Item Type + Priority + Area. **Não use `gh issue create`** (não adiciona ao board nem vincula o parent).
|
|
217
|
+
3. Informe o número criado e o vínculo com o pai (se houver).
|
|
218
|
+
4. Para Features: "Quando quiser iniciar, mova para **📋 Spec** e use `/spec-wave spec <número>` para gerar a especificação funcional (o plano técnico vem depois)".
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
### `/spec-wave uninstall`
|
|
223
|
+
|
|
224
|
+
Remove a configuração do spec-wave do repositório (labels, arquivos `.github`, `.spec-wave.json`). **Não apaga o GitHub Project.**
|
|
225
|
+
|
|
226
|
+
**Passos:**
|
|
227
|
+
1. Confirme com o usuário que ele quer remover (a ação remove labels e faz commits removendo os workflows).
|
|
228
|
+
2. Mostre antes o que será removido com `npx spec-wave uninstall --dry-run`.
|
|
229
|
+
3. Execute `npx spec-wave uninstall` (a CLI pede confirmação; use `--yes` só se o usuário já confirmou).
|
|
230
|
+
4. Lembre o usuário de excluir o **GitHub Project** manualmente, se desejar — a CLI não o apaga de propósito.
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
### `/spec-wave spec <número-da-issue>`
|
|
235
|
+
|
|
236
|
+
Inicia a geração da **especificação funcional** para uma Feature. É o **primeiro** passo do ciclo de documentos (antes do plano técnico).
|
|
237
|
+
|
|
238
|
+
**Passos:**
|
|
239
|
+
1. Adicione a label de gatilho:
|
|
240
|
+
```bash
|
|
241
|
+
gh issue edit <número> --add-label "spec-wave:spec"
|
|
242
|
+
```
|
|
243
|
+
2. Informe: "Label `spec-wave:spec` adicionada. O GitHub Action `generate-spec.yml` irá gerar o `spec.md` automaticamente."
|
|
244
|
+
3. Após a conclusão, ofereça revisar o spec.md gerado em `docs/features/<slug>/spec.md`.
|
|
245
|
+
4. Próximo passo: gerar o plano técnico — mova para **📋 Plan** e use `/spec-wave plan <número>`.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
### `/spec-wave plan <número-da-issue>`
|
|
250
|
+
|
|
251
|
+
Inicia a geração do **plano técnico** para uma Feature, derivado da especificação. É o **segundo** passo (a spec deve existir antes).
|
|
252
|
+
|
|
253
|
+
O plano técnico segue o schema do RFC-002 §3.2: **Estratégia Técnica** (com Matriz de Rastreabilidade), **Detalhamento da Implementação**, **Segurança e Conformidade**, **Estratégia de Testes** e **Rollback e Monitoramento**. O agente usa o `tech_context` do repositório (`.github/config/tech_context.yml` + versões de pacote e migrations recentes) para embasar o plano e usar APENAS as tecnologias declaradas. Para desvios pontuais, adicione uma seção `## Tech Override` no corpo da issue (RFC-002 §4.3).
|
|
254
|
+
|
|
255
|
+
**Passos:**
|
|
256
|
+
1. Verifique se `spec.md` já existe em `docs/features/<slug>/` (o plano usa a especificação funcional como contexto). Se não existir, gere a spec primeiro com `/spec-wave spec <número>`.
|
|
257
|
+
2. **Garanta o `tech_context`** (a qualidade do plano depende disso). Verifique se `.github/config/tech_context.yml` existe no repo (use Read). **Se não existir, ajude a criar AGORA** seguindo a seção **Tech Context** abaixo (logo após este comando) — e garanta que esteja **commitado e pushado** antes de adicionar a label (o Action lê o arquivo do repositório, não do seu disco local).
|
|
258
|
+
3. Adicione a label de gatilho:
|
|
259
|
+
```bash
|
|
260
|
+
gh issue edit <número> --add-label "spec-wave:plan"
|
|
261
|
+
```
|
|
262
|
+
4. Informe: "Label `spec-wave:plan` adicionada. O GitHub Action `generate-plan.yml` irá gerar o `plan.md` automaticamente. Acompanhe em: Actions → Generate Plan."
|
|
263
|
+
5. Após a conclusão (cheque comentários na issue ou aguarde confirmação do usuário), ofereça revisar o plan.md gerado em `docs/features/<slug>/plan.md`.
|
|
264
|
+
6. Próximo passo: validar a Feature — mova para **✅ Ready** e use `/spec-wave ready <número>`.
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
### Tech Context (`.github/config/tech_context.yml`)
|
|
269
|
+
|
|
270
|
+
Fonte de verdade estática da stack do sistema (RFC-002 §4). O `generate-plan` lê este arquivo para embasar o plano técnico e usar **APENAS** as tecnologias/serviços nele declarados — sem ele, o plano fica genérico e pode inventar APIs inexistentes. O `npx spec-wave init` gera um **scaffold de exemplo** que **deve ser adaptado** à stack real. Use este fluxo quando o arquivo estiver ausente ou desatualizado.
|
|
271
|
+
|
|
272
|
+
**Como ajudar a criar (quando não existir):**
|
|
273
|
+
|
|
274
|
+
1. **Confirme a ausência:** tente `Read .github/config/tech_context.yml`. Se já existir, apenas confirme com o usuário se reflete a stack atual e pule para o fim.
|
|
275
|
+
2. **Detecte a stack** lendo os arquivos do repositório (use Read; não invente):
|
|
276
|
+
- `package.json` → backend/frontend e libs (ex.: `@nestjs/core`, `next`, `react`, `@prisma/client`, `express`).
|
|
277
|
+
- `pom.xml` / `build.gradle` (Java), `requirements.txt` / `pyproject.toml` (Python), `go.mod` (Go).
|
|
278
|
+
- `prisma/schema.prisma` ou pasta `migrations/` → tabelas e colunas para `database_schemas`.
|
|
279
|
+
- `Dockerfile` / `docker-compose.yml` / charts Helm → `infra`.
|
|
280
|
+
- Procure papéis/roles (enum de RBAC) no código para `security.rbac_roles`.
|
|
281
|
+
3. **Rascunhe** o YAML seguindo EXATAMENTE este schema (preencha só o que conseguir confirmar; deixe `# TODO` no que faltar — não invente):
|
|
282
|
+
```yaml
|
|
283
|
+
system_info:
|
|
284
|
+
name: "<nome do sistema>"
|
|
285
|
+
stack:
|
|
286
|
+
backend: "<ex.: Node.js (NestJS v11)>"
|
|
287
|
+
frontend: "<ex.: Next.js 16 (React 19)>"
|
|
288
|
+
database: "<ex.: PostgreSQL (Prisma 5)>"
|
|
289
|
+
infra: "<ex.: Docker / Kubernetes>"
|
|
290
|
+
architecture: "<ex.: Monorepo Nx / Microservices>"
|
|
291
|
+
security:
|
|
292
|
+
auth_protocol: "<ex.: JWT>"
|
|
293
|
+
rbac_roles: ["ADMIN", "..."]
|
|
294
|
+
database_schemas:
|
|
295
|
+
- table: "<tabela>"
|
|
296
|
+
columns: "<col1, col2, ...>"
|
|
297
|
+
existing_services:
|
|
298
|
+
- name: "<serviço>"
|
|
299
|
+
endpoint: "<caminho>"
|
|
300
|
+
auth: "<ex.: JWT, mTLS>"
|
|
301
|
+
internal_libraries:
|
|
302
|
+
- "<lib interna>"
|
|
303
|
+
```
|
|
304
|
+
4. **Mostre o rascunho ao usuário e peça confirmação/ajustes** antes de gravar (ele conhece serviços internos e roles que o código pode não revelar).
|
|
305
|
+
5. **Grave** com Write em `.github/config/tech_context.yml`.
|
|
306
|
+
6. **Oriente a commitar e pushar** antes de seguir (o Action lê do repo). Sugira ao usuário rodar, via prefixo `!`:
|
|
307
|
+
```bash
|
|
308
|
+
!git add .github/config/tech_context.yml && git commit -m "chore: tech_context.yml [spec-wave]" && git push
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
**Desvios pontuais:** para uma Feature específica usar algo fora do padrão (ex.: "usar DynamoDB só aqui"), oriente a adicionar uma seção `## Tech Override` no corpo da issue, com um bloco YAML que será mesclado (deep-merge) sobre o `tech_context.yml`:
|
|
312
|
+
|
|
313
|
+
````markdown
|
|
314
|
+
## Tech Override
|
|
315
|
+
```yaml
|
|
316
|
+
system_info:
|
|
317
|
+
stack:
|
|
318
|
+
database: "DynamoDB"
|
|
319
|
+
```
|
|
320
|
+
````
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
### `/spec-wave ready <número-da-issue>`
|
|
325
|
+
|
|
326
|
+
Valida que spec.md e plan.md estão completos e a Feature pode avançar.
|
|
327
|
+
|
|
328
|
+
**Passos:**
|
|
329
|
+
1. Adicione a label de validação:
|
|
330
|
+
```bash
|
|
331
|
+
gh issue edit <número> --add-label "spec-wave:ready"
|
|
332
|
+
```
|
|
333
|
+
2. Informe: "Validação iniciada. O workflow verificará se spec.md e plan.md contêm todas as seções obrigatórias."
|
|
334
|
+
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.
|
|
335
|
+
4. Se passar, oriente: "Feature validada! Mova o card para **✅ Ready** e depois para **📋 Backlog Técnico** para iniciar a decomposição."
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
### `/spec-wave decompose <número-da-issue>`
|
|
340
|
+
|
|
341
|
+
Decompõe uma Feature em Stories e Tasks automaticamente.
|
|
342
|
+
|
|
343
|
+
**Passos:**
|
|
344
|
+
1. Confirme que a Feature está em **✅ Ready** (spec.md e plan.md validados)
|
|
345
|
+
2. Adicione a label de decomposição:
|
|
346
|
+
```bash
|
|
347
|
+
gh issue edit <número> --add-label "spec-wave:decompose"
|
|
348
|
+
```
|
|
349
|
+
3. Informe: "Decomposição iniciada. O workflow gerará Stories e Tasks baseados em spec.md e plan.md."
|
|
350
|
+
4. Após a conclusão, as issues filhas aparecerão como comentário na Feature pai.
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
### `/spec-wave implement <número-da-issue>`
|
|
355
|
+
|
|
356
|
+
Aciona o spec-kit para implementar uma **Story** (todas as suas Tasks) ou uma **Task** isolada. Comando **local** (etapa 🚧 Desenvolvimento) — não usa label/Action.
|
|
357
|
+
|
|
358
|
+
**Pré-requisitos:** o repositório atual precisa estar inicializado (`.spec-wave.json` presente) e a issue deve ser do tipo Story ou Task. Para executar de fato (fora do `--dry-run`), o spec-kit precisa estar configurado via `specKit.command` no `.spec-wave.json` ou a env `SPEC_WAVE_IMPLEMENT_CMD`.
|
|
359
|
+
|
|
360
|
+
**Passos:**
|
|
361
|
+
1. Confirme que há `.spec-wave.json` no repo (senão, oriente `/spec-wave setup`).
|
|
362
|
+
2. **Sempre comece com `--dry-run`** para inspecionar o que será feito — detecção do tipo, lista de Tasks coletadas (no caso de Story) e o comando do spec-kit que seria executado:
|
|
363
|
+
```bash
|
|
364
|
+
npx spec-wave implement <número> --dry-run
|
|
365
|
+
```
|
|
366
|
+
3. Mostre ao usuário o contexto montado em `.spec-wave/implement-<número>.md` e o comando.
|
|
367
|
+
4. Se o usuário aprovar e o spec-kit estiver configurado, rode sem `--dry-run`:
|
|
368
|
+
```bash
|
|
369
|
+
npx spec-wave implement <número>
|
|
370
|
+
```
|
|
371
|
+
- 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}`).
|
|
372
|
+
- 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.
|
|
373
|
+
5. Se a issue **não** for Story nem Task (ex.: Feature, Bug), o comando recusa — oriente o usuário: Features se decompõem (`/spec-wave decompose`); implemente as Stories/Tasks resultantes.
|
|
374
|
+
6. Após implementar: oriente revisar as mudanças, abrir o PR e mover o card para **👀 Code Review**.
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
|
|
378
|
+
### `/spec-wave rfc <tópico>`
|
|
379
|
+
|
|
380
|
+
Crie um documento RFC seguindo a estrutura do RFC-001.
|
|
381
|
+
|
|
382
|
+
**Passos:**
|
|
383
|
+
1. Entreviste o usuário sobre: objetivo, problema atual, solução proposta, princípios, stakeholders afetados
|
|
384
|
+
2. Escreva o RFC em português com as seções:
|
|
385
|
+
- 1. Objetivo
|
|
386
|
+
- 2. Princípios
|
|
387
|
+
- 3. Papéis e Responsabilidades
|
|
388
|
+
- 4. Estrutura de Trabalho
|
|
389
|
+
- 5. Fluxo de Trabalho
|
|
390
|
+
- 6. Automação
|
|
391
|
+
- 7. Métricas
|
|
392
|
+
- 8. Riscos e Mitigações
|
|
393
|
+
3. Salve em `rfc/rfc-<slug-do-tópico>.md` usando o Write tool
|
|
394
|
+
4. Crie uma issue de RFC:
|
|
395
|
+
```bash
|
|
396
|
+
gh issue create --title "[RFC] <título>" --label "[RFC]"
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
### `/spec-wave fix-pr <número-do-pr>`
|
|
402
|
+
|
|
403
|
+
Audita um Pull Request e corrige automaticamente os problemas encontrados — segurança, arquitetura, infraestrutura e qualidade de código. Cada fix vira um commit separado no branch do PR. Cada review comment recebe uma resposta com o hash do commit.
|
|
404
|
+
|
|
405
|
+
**Pré-requisitos:** `.spec-wave.json` deve existir (para resolver `owner/repo`). Token com permissão de push no branch do PR.
|
|
406
|
+
|
|
407
|
+
**Passos:**
|
|
408
|
+
|
|
409
|
+
1. **Resolver contexto**
|
|
410
|
+
- Leia `.spec-wave.json` para obter `owner` e `repo`.
|
|
411
|
+
- Confirme o número do PR com o usuário se não vier como argumento.
|
|
412
|
+
|
|
413
|
+
2. **Coletar dados do PR**
|
|
414
|
+
```bash
|
|
415
|
+
gh pr view <número> --json number,title,headRefName,body,changedFiles
|
|
416
|
+
gh pr diff <número>
|
|
417
|
+
gh api repos/<owner>/<repo>/pulls/<número>/comments
|
|
418
|
+
gh api repos/<owner>/<repo>/pulls/<número>/reviews
|
|
419
|
+
```
|
|
420
|
+
- Liste todos os arquivos alterados.
|
|
421
|
+
- Colete todos os review comments (inline) e reviews gerais.
|
|
422
|
+
|
|
423
|
+
3. **Fazer checkout no branch do PR**
|
|
424
|
+
```bash
|
|
425
|
+
gh pr checkout <número>
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
4. **Varredura de problemas** — para cada categoria abaixo, leia os arquivos alterados e identifique issues:
|
|
429
|
+
|
|
430
|
+
| Categoria | O que procurar |
|
|
431
|
+
|-----------|----------------|
|
|
432
|
+
| **Segurança** | Credenciais hardcoded, secrets/API keys expostas, configs inseguras, injeção SQL/XSS |
|
|
433
|
+
| **Arquitetura** | Dependências circulares, exports faltando, wiring incompleto, violações de camada |
|
|
434
|
+
| **Infraestrutura** | OIDC mal configurado, IAM permissivo demais, Dockerfile sem usuário não-root, state remoto ausente |
|
|
435
|
+
| **Qualidade** | sync-over-async, validação ausente, operações não idempotentes, error handling ausente |
|
|
436
|
+
|
|
437
|
+
Se não houver review comments manuais, use o agente `caveman:cavecrew-reviewer` para detecção automatizada:
|
|
438
|
+
```
|
|
439
|
+
Agent(caveman:cavecrew-reviewer) → diff do PR + arquivos alterados
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
5. **Para cada problema encontrado:**
|
|
443
|
+
a. Leia o(s) arquivo(s) afetado(s) com Read
|
|
444
|
+
b. Aplique o fix com Edit
|
|
445
|
+
c. Faça commit separado:
|
|
446
|
+
```bash
|
|
447
|
+
git add <arquivo>
|
|
448
|
+
git commit -m "fix: <problema> (issue #<N>)
|
|
449
|
+
|
|
450
|
+
<causa raiz>
|
|
451
|
+
|
|
452
|
+
Solution: <descrição do fix>"
|
|
453
|
+
```
|
|
454
|
+
d. Push ao branch do PR:
|
|
455
|
+
```bash
|
|
456
|
+
git push
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
6. **Responder aos review comments** — para cada comment inline do PR:
|
|
460
|
+
```bash
|
|
461
|
+
gh api repos/<owner>/<repo>/pulls/<número>/comments/<comment-id>/replies \
|
|
462
|
+
-f body="✅ **FIXED** — commit **<HASH>**
|
|
463
|
+
|
|
464
|
+
\`\`\`<linguagem>
|
|
465
|
+
<trecho corrigido>
|
|
466
|
+
\`\`\`
|
|
467
|
+
|
|
468
|
+
<explicação do fix>"
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
7. **Comentário de sumário no PR**
|
|
472
|
+
```bash
|
|
473
|
+
gh pr comment <número> --body "<sumário>"
|
|
474
|
+
```
|
|
475
|
+
Formato do sumário:
|
|
476
|
+
```
|
|
477
|
+
## 🔍 PR Audit — Spec Wave
|
|
478
|
+
|
|
479
|
+
### Problemas encontrados e corrigidos
|
|
480
|
+
|
|
481
|
+
| # | Severidade | Categoria | Problema | Commit |
|
|
482
|
+
|---|-----------|-----------|---------|--------|
|
|
483
|
+
| 1 | 🔴 Critical | Segurança | Credencial hardcoded em config.js | abc1234 |
|
|
484
|
+
| 2 | 🟡 Medium | Qualidade | Operação não idempotente em createOrder | def5678 |
|
|
485
|
+
|
|
486
|
+
### Commits criados
|
|
487
|
+
- `abc1234` fix: credencial hardcoded removida (issue #1)
|
|
488
|
+
- `def5678` fix: idempotency key adicionada em createOrder (issue #2)
|
|
489
|
+
|
|
490
|
+
**Total:** <N> problema(s) encontrado(s) e corrigido(s).
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
**Output esperado:**
|
|
494
|
+
- Lista de issues (severidade + impacto)
|
|
495
|
+
- Lista de commits criados (hash + mensagem)
|
|
496
|
+
- Confirmação de replies postadas nos review comments
|
|
497
|
+
- Estado final do PR
|
|
498
|
+
|
|
499
|
+
**Severidade:**
|
|
500
|
+
- 🔴 Critical — segurança, dados expostos, falha em produção
|
|
501
|
+
- 🟠 High — bug que afeta usuários, arquitetura quebrada
|
|
502
|
+
- 🟡 Medium — qualidade, manutenibilidade, performance
|
|
503
|
+
- 🔵 Low — estilo, naming, comentários
|
|
504
|
+
|
|
505
|
+
---
|
|
506
|
+
|
|
507
|
+
## Estrutura de arquivos gerados
|
|
508
|
+
|
|
509
|
+
```
|
|
510
|
+
docs/
|
|
511
|
+
features/
|
|
512
|
+
<slug-da-feature>/
|
|
513
|
+
spec.md ← gerado pelo GitHub Action quando spec-wave:spec é adicionado (1º)
|
|
514
|
+
plan.md ← gerado pelo GitHub Action quando spec-wave:plan é adicionado (2º, usa a spec)
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
O slug é gerado a partir do título da issue: `[FEATURE] Cadastro de Pedidos com PIX` → `cadastro-de-pedidos-com-pix`
|