@spec-wave/cli 0.15.0 → 0.16.1
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 +1 -0
- package/bin/spec-wave.mjs +44 -5
- package/package.json +8 -2
- package/src/agent/anthropic-agent.mjs +337 -0
- package/src/agent/errors.mjs +33 -0
- package/src/agent/index.mjs +108 -0
- package/src/agent/openrouter-agent.mjs +378 -0
- package/src/agent/run-types.mjs +59 -0
- package/src/agent/telemetry.mjs +54 -0
- package/src/agent/tools.mjs +452 -0
- package/src/agent/tracing.mjs +106 -0
- package/src/api/github-graphql.mjs +23 -1
- package/src/api/github-rest.mjs +8 -0
- package/src/commands/bug.mjs +8 -0
- package/src/commands/code-review.mjs +45 -4
- package/src/commands/decompose.mjs +22 -72
- package/src/commands/dev-agent.mjs +3 -3
- package/src/commands/doctor.mjs +77 -6
- package/src/commands/generate-bug.mjs +195 -0
- package/src/commands/generate-plan.mjs +19 -44
- package/src/commands/generate-spec.mjs +18 -46
- package/src/commands/implement.mjs +105 -2
- package/src/commands/init.mjs +3 -3
- package/src/commands/install-skill.mjs +72 -16
- package/src/commands/issue.mjs +9 -7
- package/src/commands/move.mjs +11 -1
- package/src/commands/qa.mjs +23 -2
- package/src/commands/refresh.mjs +171 -5
- package/src/commands/triage.mjs +174 -0
- package/src/commands/update.mjs +16 -3
- package/src/commands/validate.mjs +82 -10
- package/src/config.mjs +159 -1
- package/src/lib/bug-context.mjs +160 -0
- package/src/lib/bug-doc.mjs +51 -0
- package/src/lib/bug-triage.mjs +81 -0
- package/src/lib/claude.mjs +71 -254
- package/src/lib/critique.mjs +43 -30
- package/src/lib/flow-run.mjs +145 -0
- package/src/lib/implement-board.mjs +12 -1
- package/src/lib/plugin-skills.mjs +122 -0
- package/src/lib/project-root.mjs +9 -2
- package/src/lib/prompt-loader.mjs +257 -0
- package/src/lib/skill-file.mjs +35 -0
- package/src/plugin/.claude-plugin/plugin.json +20 -0
- package/src/plugin/README.md +73 -0
- package/src/plugin/skills/bug/SKILL.md +60 -0
- package/src/plugin/skills/bug/model-prompt.critique.md +48 -0
- package/src/plugin/skills/bug/model-prompt.md +74 -0
- package/src/plugin/skills/decompose/SKILL.md +117 -0
- package/src/plugin/skills/decompose/model-prompt.critique.md +46 -0
- package/src/plugin/skills/decompose/model-prompt.feature.md +69 -0
- package/src/plugin/skills/decompose/model-prompt.rfc.md +52 -0
- package/src/plugin/skills/doctor/SKILL.md +51 -0
- package/src/plugin/skills/fix-pr/SKILL.md +130 -0
- package/src/plugin/skills/implement/SKILL.md +102 -0
- package/src/plugin/skills/info/SKILL.md +40 -0
- package/src/plugin/skills/issue/SKILL.md +63 -0
- package/src/plugin/skills/move/SKILL.md +52 -0
- package/src/plugin/skills/order/SKILL.md +36 -0
- package/src/plugin/skills/plan/SKILL.md +58 -0
- package/src/plugin/skills/plan/model-prompt.critique.md +44 -0
- package/src/plugin/skills/plan/model-prompt.md +59 -0
- package/src/plugin/skills/plan/reference/tech-context.md +56 -0
- package/src/plugin/skills/ready/SKILL.md +44 -0
- package/src/plugin/skills/rfc/SKILL.md +47 -0
- package/src/plugin/skills/setup/SKILL.md +67 -0
- package/src/plugin/skills/spec/SKILL.md +55 -0
- package/src/plugin/skills/spec/model-prompt.md +61 -0
- package/src/plugin/skills/story/SKILL.md +49 -0
- package/src/plugin/skills/task/SKILL.md +41 -0
- package/src/plugin/skills/triage/SKILL.md +52 -0
- package/src/plugin/skills/uninstall/SKILL.md +43 -0
- package/src/plugin/skills/update/SKILL.md +51 -0
- package/src/plugin/skills/workflow/SKILL.md +158 -0
- package/src/templates/skill/SKILL.md +54 -4
- package/src/templates/workflows/generate-bug.yml +36 -0
- package/src/templates/workflows/validate.yml +2 -1
- package/src/ui/wizard.mjs +5 -2
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: critique-bug
|
|
3
|
+
action: critique
|
|
4
|
+
description: Critério da crítica adversarial do bug.md contra o relato original — causa raiz, escopo do fix e teste de regressão.
|
|
5
|
+
tools: [Read, Glob, Grep]
|
|
6
|
+
maxTurns: 20
|
|
7
|
+
verifiers: 3
|
|
8
|
+
lenses:
|
|
9
|
+
- "explicação — a causa raiz proposta explica TODOS os sintomas relatados, ou só o mais visível?"
|
|
10
|
+
- "escopo — o fix cobre a causa raiz e apenas ela, sem refatoração oportunista nem correção de sintoma?"
|
|
11
|
+
- "prova — o teste de regressão descrito falharia mesmo sem o fix, ou passaria de qualquer jeito?"
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Crítica adversarial do bug.md
|
|
15
|
+
|
|
16
|
+
Você é um engenheiro cético revisando a investigação de um defeito **antes** de alguém gastar tempo corrigindo. Sua função não é melhorar o texto: é encontrar onde ele levaria à correção errada.
|
|
17
|
+
|
|
18
|
+
Você recebe o **relato original** (issue e comentários) e o **bug.md** proposto. O relato é a verdade sobre o comportamento observado; o bug.md é a hipótese.
|
|
19
|
+
|
|
20
|
+
## O que auditar
|
|
21
|
+
|
|
22
|
+
**1. A causa raiz explica os sintomas?**
|
|
23
|
+
Compare cada sintoma do relato com a causa proposta. Um sintoma relatado que a causa não explica significa uma de duas coisas: a causa está errada, ou há um segundo defeito. As duas são **graves**.
|
|
24
|
+
|
|
25
|
+
**2. É causa ou sintoma?**
|
|
26
|
+
"O campo chega nulo" descreve o sintoma. Por que chega nulo é a causa. Uma correção que trata o sintoma reaparece na próxima entrada — **grave**.
|
|
27
|
+
|
|
28
|
+
**3. O escopo bate com a causa?**
|
|
29
|
+
- Escopo **menor** que a causa: o fix não resolve. Grave.
|
|
30
|
+
- Escopo **maior** que a causa: há refatoração pegando carona. Grave — aumenta o risco de uma correção que deveria ser cirúrgica.
|
|
31
|
+
- Escopo que não diz o que **não** muda: menor.
|
|
32
|
+
|
|
33
|
+
**4. O teste de regressão prova alguma coisa?**
|
|
34
|
+
A pergunta é única: **esse teste falharia sem o fix?** Um teste que passa nos dois cenários não é regressão, é decoração — **grave**. Um teste descrito vagamente demais para responder a essa pergunta é **menor**.
|
|
35
|
+
|
|
36
|
+
**5. A reprodução é executável?**
|
|
37
|
+
Passos que dependem de estado não descrito ("com o usuário na situação X") não reproduzem. Menor — a menos que tornem impossível verificar o fix, aí grave.
|
|
38
|
+
|
|
39
|
+
**6. Severidade coerente com o impacto?**
|
|
40
|
+
Um P3 cujo impacto descrito é "nenhum usuário consegue finalizar a compra" está classificado errado. Menor.
|
|
41
|
+
|
|
42
|
+
## O que NÃO é achado
|
|
43
|
+
|
|
44
|
+
- Preferência de redação, formatação ou ordem das seções.
|
|
45
|
+
- Ausência de código — o `bug.md` **não deve** propor implementação.
|
|
46
|
+
- "Causa raiz não determinada" **acompanhada de hipóteses testáveis**: isso é honestidade, e é o comportamento correto quando a investigação não conclui. Já uma causa afirmada sem evidência é grave.
|
|
47
|
+
|
|
48
|
+
Prefira o silêncio ao achado inventado: um comentário cheio de observações menores treina o time a ignorar o portão.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bug
|
|
3
|
+
action: bug
|
|
4
|
+
description: Gera o bug.md — reprodução, causa raiz, escopo do fix e teste de regressão — a partir do relato na issue.
|
|
5
|
+
tools: [Read, Glob, Grep]
|
|
6
|
+
maxTurns: 30
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Geração de bug.md
|
|
10
|
+
|
|
11
|
+
Você é um engenheiro sênior investigando um defeito relatado. Produza o `bug.md`: o documento que outra pessoa (ou um agente) vai usar para **reproduzir, entender e corrigir** o defeito.
|
|
12
|
+
|
|
13
|
+
Este documento é **leve por decisão**. Um defeito não gera especificação funcional nem plano técnico — gera o mínimo que torna a correção possível e verificável.
|
|
14
|
+
|
|
15
|
+
## Entrada
|
|
16
|
+
|
|
17
|
+
Você recebe um payload JSON com:
|
|
18
|
+
|
|
19
|
+
- `metadata.bug_title` — título da issue
|
|
20
|
+
- `metadata.labels` — labels aplicadas (a prioridade `P0`–`P3` é a **severidade**)
|
|
21
|
+
- `metadata.required_sections` — os títulos exatos que o documento precisa ter
|
|
22
|
+
- `report.raw` — o relato: corpo da issue **e** os comentários humanos, em ordem
|
|
23
|
+
|
|
24
|
+
Trate o relato como a única fonte sobre o comportamento observado. Ele costuma ser incompleto — dizer o que falta é parte do trabalho, inventar não é.
|
|
25
|
+
|
|
26
|
+
<!-- requires-tools -->
|
|
27
|
+
## Investigação antes de escrever
|
|
28
|
+
|
|
29
|
+
Você tem `Read`, `Glob` e `Grep` no repositório. Use-os para transformar sintoma em causa:
|
|
30
|
+
|
|
31
|
+
1. Localize o código do caminho descrito no relato (comece pela mensagem de erro, nome de tela, endpoint ou função citada).
|
|
32
|
+
2. Leia o trecho e os arredores — a causa quase nunca está na linha que estourou.
|
|
33
|
+
3. Procure o teste que deveria ter pego isto. A ausência dele é um achado, e vira a seção **Teste de Regressão**.
|
|
34
|
+
|
|
35
|
+
Cite arquivo e função nas seções **Causa Raiz** e **Escopo do Fix**. Um `bug.md` sem referência a código é um relato reescrito, não uma investigação.
|
|
36
|
+
<!-- /requires-tools -->
|
|
37
|
+
|
|
38
|
+
## Estrutura obrigatória
|
|
39
|
+
|
|
40
|
+
Use **exatamente** estes títulos, nesta ordem, como headings de nível 2:
|
|
41
|
+
|
|
42
|
+
```markdown
|
|
43
|
+
# Bug: <título sem o prefixo [BUG]>
|
|
44
|
+
|
|
45
|
+
## Reprodução
|
|
46
|
+
## Esperado e Obtido
|
|
47
|
+
## Impacto e Severidade
|
|
48
|
+
## Causa Raiz
|
|
49
|
+
## Escopo do Fix
|
|
50
|
+
## Teste de Regressão
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
O validador procura estes títulos byte a byte. Não os traduza, abrevie nem reordene.
|
|
54
|
+
|
|
55
|
+
## O que cada seção precisa conter
|
|
56
|
+
|
|
57
|
+
**Reprodução** — passos numerados e determinísticos. Ambiente, dados de entrada e pré-condições. Se o relato não permite reproduzir, escreva os passos até onde dá e liste explicitamente, em "Informação faltante", o que precisa ser perguntado a quem reportou.
|
|
58
|
+
|
|
59
|
+
**Esperado e Obtido** — duas afirmações curtas e contrastantes. O que o sistema deveria fazer × o que ele faz. Sem narrativa.
|
|
60
|
+
|
|
61
|
+
**Impacto e Severidade** — quem é afetado, com que frequência, e o que fica impossível de fazer. Justifique a severidade (`P0`–`P3`) com base nisso; se discordar da que veio nas labels, diga e explique.
|
|
62
|
+
|
|
63
|
+
**Causa Raiz** — a origem, não o sintoma. Cite arquivo e função. Se a investigação não permitir concluir, escreva **"Causa raiz não determinada"** e liste as hipóteses em ordem de probabilidade, cada uma com o que a confirmaria ou descartaria. Uma causa inventada é pior que uma ausente: ela produz correção errada com aparência de fundamentada.
|
|
64
|
+
|
|
65
|
+
**Escopo do Fix** — o que muda, e — igualmente importante — **o que deliberadamente não muda**. Um bug é o convite mais comum para refatoração oportunista; delimitar aqui é o que impede isso.
|
|
66
|
+
|
|
67
|
+
**Teste de Regressão** — o teste que **falha sem o fix e passa com ele**. Nomeie o arquivo, descreva o caso e os dados. Se não houver como testar automaticamente, diga por quê e descreva a verificação manual.
|
|
68
|
+
|
|
69
|
+
## Regras
|
|
70
|
+
|
|
71
|
+
- Escreva em **português (pt-BR)**.
|
|
72
|
+
- Seja específico: "a validação de CPF aceita string vazia em `validators.ts:checkCpf`" vale mais que "há um problema na validação".
|
|
73
|
+
- **Não proponha código.** O documento descreve o defeito e delimita a correção; implementar é outra etapa.
|
|
74
|
+
- Distinga o que você **observou** do que você **supõe**. Marque suposição como suposição.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-wave-decompose
|
|
3
|
+
description: "Use para quebrar uma Feature em Stories+Tasks, ou um RFC em Tasks, no spec-wave. São DUAS etapas com um rascunho revisável no meio: spec-wave:decompose gera/critica o decomposition.md sem criar nada, e spec-wave:decompose-apply cria as issues a partir do rascunho aprovado. Gatilhos: 'decompor a feature 12', 'gerar as stories', 'quebrar em tasks', 'aplicar a decomposição', 'o decompose falhou na crítica'. Também cobre re-decompose e o guard de idempotência."
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Bash(gh issue *)
|
|
6
|
+
- Bash(npx @spec-wave/cli@latest *)
|
|
7
|
+
- Read
|
|
8
|
+
- Edit
|
|
9
|
+
- Write
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# spec-wave decompose — decomposição em duas etapas
|
|
13
|
+
|
|
14
|
+
Aplica-se a **dois tipos**:
|
|
15
|
+
|
|
16
|
+
- **Feature** → **Stories** (cada uma com suas **Tasks**), a partir de `spec.md` + `plan.md`
|
|
17
|
+
- **RFC** → **Tasks diretamente** (sem Stories), a partir da descrição
|
|
18
|
+
|
|
19
|
+
Para qualquer outro tipo (Spike, Bug, Story, Task…) o Action **recusa** e comenta.
|
|
20
|
+
|
|
21
|
+
**Contexto:** leia `.spec-wave.json` (Read). Ausente → skill **setup**.
|
|
22
|
+
|
|
23
|
+
## O modelo mental
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
spec-wave:decompose
|
|
27
|
+
├─ decomposition.md ausente → gera via IA → commita → critica
|
|
28
|
+
└─ decomposition.md presente → critica o arquivo COMO ESTÁ (preserva suas edições)
|
|
29
|
+
├─ grave → +critique-failed, comentário citando Story N / Task N.M, exit 1
|
|
30
|
+
└─ limpo → +decompose-ready, comentário "revise e aplique"
|
|
31
|
+
|
|
32
|
+
spec-wave:decompose-apply
|
|
33
|
+
└─ lê decomposition.md → cria Stories/Tasks → board → +decomposed
|
|
34
|
+
(sem nova crítica: aplicar a label É a aprovação humana)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Passos
|
|
38
|
+
|
|
39
|
+
1. **Pré-requisito.** Feature: confirme que está em **✅ Ready** (spec e plan validados — skill **ready**). RFC: basta a descrição estar completa.
|
|
40
|
+
|
|
41
|
+
2. **Etapa 1 — gerar o rascunho**, no modo que preferir (mesmo resultado; o modo é detectado pelo ambiente):
|
|
42
|
+
```bash
|
|
43
|
+
# local — resultado nesta sessão
|
|
44
|
+
npx @spec-wave/cli@latest decompose --issue-number <número>
|
|
45
|
+
# ou Action — assíncrono
|
|
46
|
+
gh issue edit <número> --add-label "spec-wave:decompose"
|
|
47
|
+
```
|
|
48
|
+
Informe: "Rascunho iniciado — vai commitar o `decomposition.md` e passar pela crítica. **Nenhuma issue é criada nesta etapa.**"
|
|
49
|
+
|
|
50
|
+
3. **Leia o resultado** quando o Action terminar:
|
|
51
|
+
|
|
52
|
+
| Label resultante | O que fazer |
|
|
53
|
+
|------------------|-------------|
|
|
54
|
+
| `spec-wave:decompose-ready` | Passou na crítica. **Leia o `decomposition.md`** e mostre ao usuário o que será criado (Stories, Tasks, dependências). Ofereça editar antes de aplicar. |
|
|
55
|
+
| `spec-wave:critique-failed` | O Action **falhou (exit 1)** e nada foi criado. Os achados citam `Story N` / `Task N.M`. **Corrija o `decomposition.md`** — não o `plan.md` — commite e reaplique `spec-wave:decompose` (o arquivo é criticado como está, sem ser regerado). |
|
|
56
|
+
| `spec-wave:needs-human` | A crítica esgotou as tentativas. **Pare** e envolva o usuário: as duas labels precisam sair à mão. |
|
|
57
|
+
|
|
58
|
+
4. **Etapa 2 — aplicar o rascunho aprovado**, só depois da revisão:
|
|
59
|
+
```bash
|
|
60
|
+
# local
|
|
61
|
+
npx @spec-wave/cli@latest decompose --issue-number <número> --apply
|
|
62
|
+
# ou Action
|
|
63
|
+
gh issue edit <número> --add-label "spec-wave:decompose-apply"
|
|
64
|
+
```
|
|
65
|
+
Aplicar essa label **é** a aprovação humana — não há nova crítica.
|
|
66
|
+
|
|
67
|
+
5. Após a aplicação, as issues filhas aparecem como comentário na issue pai. Pai e filhas entram no board em **✅ Ready** (Status Todo; a Etapa nunca retrocede — itens já adiante não são tocados). As Stories trazem `Depende de: #N` — use a skill **order** para ver a ordem de execução.
|
|
68
|
+
|
|
69
|
+
6. A issue recebe `spec-wave:decomposed` (guard de idempotência): rodar de novo **não** duplica as issues.
|
|
70
|
+
|
|
71
|
+
> **Nunca pule a etapa 1** aplicando `spec-wave:decompose-apply` direto — sem `decomposition.md` o Action falha pedindo o rascunho.
|
|
72
|
+
|
|
73
|
+
## O arquivo `decomposition.md`
|
|
74
|
+
|
|
75
|
+
Fica em `docs/features/<slug>/decomposition.md` (Feature) ou `docs/rfcs/<slug>/decomposition.md` (RFC):
|
|
76
|
+
|
|
77
|
+
```markdown
|
|
78
|
+
# Decomposição — [FEATURE] Cadastro de Pedidos
|
|
79
|
+
<!-- spec-wave:decomposition v1 issue=360 kind=stories -->
|
|
80
|
+
|
|
81
|
+
## Story 1 — visualizar meus pedidos
|
|
82
|
+
|
|
83
|
+
**User story:** Como cliente, quero visualizar meus pedidos, para acompanhar entregas
|
|
84
|
+
**Depende de:** —
|
|
85
|
+
|
|
86
|
+
Descrição complementar (contexto, critérios de aceite).
|
|
87
|
+
|
|
88
|
+
### Task 1.1 — criar endpoint GET /pedidos
|
|
89
|
+
|
|
90
|
+
Corpo técnico.
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Ao editar à mão:**
|
|
94
|
+
|
|
95
|
+
- a **posição** manda, não o número escrito — inserir uma Story no meio sem renumerar funciona
|
|
96
|
+
- `**Depende de:**` usa referências **1-based** (`Story 1, Story 3`) ou `—`; apontar para si mesma ou para frente é **erro**, não filtro silencioso
|
|
97
|
+
- o corpo aceita markdown livre (`## Backend`, cercas de código) — só `## Story N` e `### Task N.M` são estrutura
|
|
98
|
+
- **para gerar outro rascunho do zero:** apague o arquivo e reaplique `spec-wave:decompose`
|
|
99
|
+
|
|
100
|
+
> ⚠️ O slug vem do **título**. Renomear a Feature entre o rascunho e o apply muda o diretório e órfã o `decomposition.md` — o apply reclama que não achou o rascunho.
|
|
101
|
+
|
|
102
|
+
## Guard de idempotência (`spec-wave:decomposed`)
|
|
103
|
+
|
|
104
|
+
O evento `labeled` pode redisparar (re-add da label, retry de runner). Para não duplicar issues, o `decompose` **pula** quando a issue já tem `spec-wave:decomposed` **ou** já tem sub-issues do tipo-alvo (`[STORY]` para Feature, `[TASK]` para RFC). A label é gravada ao **aplicar**. Os workflows ainda usam `concurrency` por issue.
|
|
105
|
+
|
|
106
|
+
A `spec-wave:decompose-ready` **não** entra nesse guard — é estado de rascunho pendente, não de decomposição feita.
|
|
107
|
+
|
|
108
|
+
**Para forçar um re-decompose:**
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
gh issue edit <n> --remove-label "spec-wave:decomposed"
|
|
112
|
+
```
|
|
113
|
+
Depois **apague/feche as sub-issues antigas** (senão a detecção por sub-issues pula de novo), apague o `decomposition.md` se quiser um rascunho novo, e re-adicione `spec-wave:decompose`.
|
|
114
|
+
|
|
115
|
+
## Dependências entre Stories
|
|
116
|
+
|
|
117
|
+
O `decompose` grava `Depende de: #N, #M` no corpo das Stories e cria a relação nativa *blocked by*. Isso alimenta as skills **order** e **implement**. **Não apague essa linha** ao editar o corpo de uma Story; para mudar dependências, edite a linha (e/ou a relação *blocked by*).
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: critique-stories
|
|
3
|
+
action: critique
|
|
4
|
+
description: Critério da crítica adversarial das Stories propostas contra o spec.md e o plan.md, antes de virarem issues.
|
|
5
|
+
tools: [Read, Glob, Grep]
|
|
6
|
+
maxTurns: 20
|
|
7
|
+
verifiers: 3
|
|
8
|
+
lenses:
|
|
9
|
+
- "contradição — alguma story contradiz, inverte ou ignora um requisito da spec ou uma decisão do plan?"
|
|
10
|
+
- "critérios de aceite — os critérios embutidos nas stories são compatíveis com as regras de negócio da spec?"
|
|
11
|
+
- "cobertura e ordem — as stories cobrem a Feature inteira, e a ordem/dependências declaradas são executáveis?"
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Crítica adversarial das Stories
|
|
15
|
+
|
|
16
|
+
Você audita as Stories propostas (JSON) contra o `spec.md` e o `plan.md` fornecidos. Seu papel é encontrar problemas, não elogiar.
|
|
17
|
+
|
|
18
|
+
Procure stories que contradizem, invertem ou ignoram requisitos da spec ou decisões do plan, e critérios de aceite incompatíveis com as regras de negócio.
|
|
19
|
+
|
|
20
|
+
Esta auditoria roda **antes de qualquer issue ser criada**. É a última chance de impedir que trabalho errado vire backlog.
|
|
21
|
+
|
|
22
|
+
## O que caracteriza um achado
|
|
23
|
+
|
|
24
|
+
- **Contradições diretas** entre as stories e a spec/plan.
|
|
25
|
+
- **Inversões de requisito** — ex.: a spec exige consentimento ANTES de persistir e a story persiste antes de pedir consentimento.
|
|
26
|
+
- **Violações de restrição explícita** — minimização de dados (LGPD), limites de retenção, campos proibidos.
|
|
27
|
+
- **Critérios de aceite incompatíveis** com as regras de negócio da spec.
|
|
28
|
+
- **Lacuna de cobertura** — um Critério de Aceite da spec que nenhuma story endereça.
|
|
29
|
+
- **Dependência impossível** — `dependsOn` que aponta para uma story que entrega depois, ou ordem que exige o que ainda não existe.
|
|
30
|
+
|
|
31
|
+
<!-- requires-tools -->
|
|
32
|
+
## Como verificar
|
|
33
|
+
|
|
34
|
+
Você tem `Read`, `Glob` e `Grep`. Confira as stories contra os arquivos reais, não contra o que elas afirmam sobre eles.
|
|
35
|
+
<!-- /requires-tools -->
|
|
36
|
+
## Barra de rigor
|
|
37
|
+
|
|
38
|
+
NÃO invente problemas. Se as stories estiverem consistentes com spec e plan, diga isso — uma decomposição limpa é um resultado legítimo e frequente.
|
|
39
|
+
|
|
40
|
+
O inverso também vale: "não consegui confirmar" é uma refutação, não uma aprovação.
|
|
41
|
+
|
|
42
|
+
## Consequência
|
|
43
|
+
|
|
44
|
+
Um achado marcado como **grave** **aborta** a decomposição: nenhuma story ou task é criada, a label `spec-wave:critique-failed` é aplicada e o trigger `spec-wave:decompose` é removido. Um achado **menor** é comentado na issue, e a decomposição segue.
|
|
45
|
+
|
|
46
|
+
Ou seja: um achado grave seu cancela a criação de dezenas de issues. Reserve-o para contradição real, não para preferência de estilo.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: decompose-feature
|
|
3
|
+
action: decompose
|
|
4
|
+
description: Decompõe uma Feature em Stories ordenadas, cada uma com suas Tasks técnicas.
|
|
5
|
+
tools: [Read, Glob, Grep]
|
|
6
|
+
maxTurns: 30
|
|
7
|
+
json:
|
|
8
|
+
shape: '{"stories": [{"title": "...", "userStory": "...", "body": "...", "dependsOn": [0], "tasks": [{"title": "...", "body": "..."}]}]}'
|
|
9
|
+
retries: 1
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Decomposição de Feature em Stories
|
|
13
|
+
|
|
14
|
+
Você é um Tech Lead experiente em decomposição de trabalho ágil. A partir da Feature fornecida (com spec.md e plan.md), gere uma lista de Stories e Tasks.
|
|
15
|
+
|
|
16
|
+
## Entrada
|
|
17
|
+
|
|
18
|
+
- Título e número da issue da Feature
|
|
19
|
+
- O conteúdo de `spec.md` — critérios de aceite em Gherkin, fluxos, regras de negócio
|
|
20
|
+
- O conteúdo de `plan.md` — estratégia técnica, matriz de rastreabilidade, detalhamento por camada
|
|
21
|
+
|
|
22
|
+
Quando um dos dois documentos não existir, a entrada diz isso explicitamente. Decomponha com o que houver, mas não invente o que faltou.
|
|
23
|
+
|
|
24
|
+
<!-- requires-tools -->
|
|
25
|
+
## Exploração antes de decompor
|
|
26
|
+
|
|
27
|
+
Você tem `Read`, `Glob` e `Grep` no repositório. Use-os para dimensionar as tasks contra o código que existe de verdade: uma task "criar endpoint X" é diferente conforme o controller já exista ou não. Ancore os títulos técnicos nos caminhos e nomes reais que encontrar.
|
|
28
|
+
<!-- /requires-tools -->
|
|
29
|
+
|
|
30
|
+
## Contrato de saída
|
|
31
|
+
|
|
32
|
+
Responda APENAS com JSON válido neste formato:
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"stories": [
|
|
37
|
+
{
|
|
38
|
+
"title": "Título curto da story (apenas a parte 'quero', sem prefixo)",
|
|
39
|
+
"userStory": "Como <perfil>, quero <objetivo>, para <benefício>",
|
|
40
|
+
"body": "Descrição complementar da story com contexto e critérios de aceite relevantes",
|
|
41
|
+
"dependsOn": [0],
|
|
42
|
+
"tasks": [
|
|
43
|
+
{
|
|
44
|
+
"title": "Título técnico curto da task (sem prefixo)",
|
|
45
|
+
"body": "Descrição técnica detalhada"
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Regras
|
|
54
|
+
|
|
55
|
+
- `title` deve ser CURTO (máx. ~60 caracteres): apenas a parte "quero" da user story, sem o "Como" nem o "para", e sem prefixo. Ex.: "visualizar meus repositórios em layout responsivo"
|
|
56
|
+
- `userStory` deve trazer a user story completa no formato "Como <perfil>, quero <objetivo>, para <benefício>"
|
|
57
|
+
- `body` é texto complementar (contexto, critérios de aceite); não repita o título
|
|
58
|
+
- Cada Story deve ter 2–5 Tasks associadas
|
|
59
|
+
- Tasks devem ser atividades técnicas concretas, com `title` curto e `body` detalhado
|
|
60
|
+
- Gere entre 3 e 7 Stories por Feature
|
|
61
|
+
- Ordene as stories na sequência de implementação — a ORDEM da lista importa
|
|
62
|
+
- `dependsOn` (opcional): índices 0-based das stories ANTERIORES na lista das quais esta story depende. Referencie apenas índices menores que o da própria story. Use `[]` quando a story puder ser feita em paralelo (sem dependências); se omitido, assume-se dependência da story anterior (sequencial)
|
|
63
|
+
- Escreva títulos e corpos em português (pt-BR). Não use caracteres de outros alfabetos (CJK, cirílico, árabe, tailandês).
|
|
64
|
+
|
|
65
|
+
## O que acontece com a sua saída
|
|
66
|
+
|
|
67
|
+
Cada story vira uma issue `[STORY]` e cada task uma issue `[TASK]` vinculada como sub-issue, posicionadas na etapa **✅ Ready** do board. As dependências viram a relação nativa `blocked_by` do GitHub e uma linha "Depende de: #N" no corpo. Ou seja: a ordem e o `dependsOn` que você devolver determinam a ordem real de execução do time.
|
|
68
|
+
|
|
69
|
+
Antes disso, uma crítica adversarial audita as stories contra a spec e o plan (ver a skill `critique-stories`). Achados graves cancelam a criação — nenhuma issue é aberta.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: decompose-rfc
|
|
3
|
+
action: decompose
|
|
4
|
+
description: Decompõe um RFC diretamente em Tasks técnicas, sem camada de Stories.
|
|
5
|
+
tools: [Read, Glob, Grep]
|
|
6
|
+
maxTurns: 30
|
|
7
|
+
json:
|
|
8
|
+
shape: '{"tasks": [{"title": "...", "body": "..."}]}'
|
|
9
|
+
retries: 1
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Decomposição de RFC em Tasks
|
|
13
|
+
|
|
14
|
+
Você é um Tech Lead experiente. A partir do RFC fornecido (proposta técnica/de processo), gere a lista de Tasks técnicas concretas necessárias para implementá-lo.
|
|
15
|
+
|
|
16
|
+
Um RFC não passa por spec/plan — ele é a proposta em si. Por isso não há camada de Stories aqui: as tasks penduram direto no RFC.
|
|
17
|
+
|
|
18
|
+
## Entrada
|
|
19
|
+
|
|
20
|
+
- Título e número da issue do RFC
|
|
21
|
+
- O corpo da issue, que é o texto da proposta
|
|
22
|
+
|
|
23
|
+
<!-- requires-tools -->
|
|
24
|
+
## Exploração antes de decompor
|
|
25
|
+
|
|
26
|
+
Você tem `Read`, `Glob` e `Grep` no repositório. Um RFC quase sempre descreve mudança em algo que já existe — localize esse algo antes de listar tasks, e nomeie na `body` os arquivos e áreas que cada task vai tocar.
|
|
27
|
+
<!-- /requires-tools -->
|
|
28
|
+
## Contrato de saída
|
|
29
|
+
|
|
30
|
+
Responda APENAS com JSON válido neste formato:
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"tasks": [
|
|
35
|
+
{
|
|
36
|
+
"title": "Título técnico curto da task (sem prefixo)",
|
|
37
|
+
"body": "Descrição técnica detalhada (o que fazer, áreas/arquivos afetados, critério de pronto)"
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Regras
|
|
44
|
+
|
|
45
|
+
- `title` CURTO (máx. ~60 caracteres), sem prefixo.
|
|
46
|
+
- `body` detalhado e acionável.
|
|
47
|
+
- Gere entre 3 e 10 Tasks concretas que, juntas, cubram o RFC.
|
|
48
|
+
- Escreva títulos e corpos em português (pt-BR). Não use caracteres de outros alfabetos (CJK, cirílico, árabe, tailandês).
|
|
49
|
+
|
|
50
|
+
## O que acontece com a sua saída
|
|
51
|
+
|
|
52
|
+
Cada task vira uma issue `[TASK]` vinculada como sub-issue do RFC e posicionada na etapa **✅ Ready** do board.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-wave-doctor
|
|
3
|
+
description: "Use como PRIMEIRO passo de troubleshooting do spec-wave: erro 404 ao criar issues, comando falhando sem motivo claro, board com colunas estranhas, Action que não roda, dúvida sobre token/escopos ou sobre qual modelo de IA está configurado. Também no início de uma sessão de trabalho. Gatilhos: 'spec-wave está com erro', 'não consigo criar issue', 'diagnosticar spec-wave', 'rodar o doctor'. Prefira esta skill a depurar gh api na mão."
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Bash(npx @spec-wave/cli@latest *)
|
|
6
|
+
- Bash(gh auth status)
|
|
7
|
+
- Read
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# spec-wave doctor — preflight de auth e configuração
|
|
11
|
+
|
|
12
|
+
Comando **local**, sem flags:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npx @spec-wave/cli@latest doctor
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## O que ele checa
|
|
19
|
+
|
|
20
|
+
- **Token GitHub** e a fonte dele; **escopos** (`repo`, `project`, `workflow`), com degradação para checks funcionais em fine-grained PATs
|
|
21
|
+
- **Conta ativa do `gh`** vs. o owner do repositório
|
|
22
|
+
- **`.spec-wave.json`**: campos presentes e sincronia com o Project real
|
|
23
|
+
- **Acesso ao repositório**
|
|
24
|
+
- **Configuração de IA**: provider, modelo, `ai.models`, escalada da crítica, apelidos de modelo, teto de saída e os secrets do Actions
|
|
25
|
+
- **Higiene do board e das labels**: colunas fora do fluxo canônico, labels `spec-wave:*` descontinuadas ou ausentes
|
|
26
|
+
- **spec-kit**: `specKit.command` / env `SPEC_WAVE_IMPLEMENT_CMD` — se ausente, sugere exemplos por agente (Claude Code, opencode, Codex, Copilot CLI, Kiro CLI, Qwen Code)
|
|
27
|
+
- **Workflows**: presença + **versão da CLI fixada** (não `@latest`)
|
|
28
|
+
|
|
29
|
+
## Como ler a saída
|
|
30
|
+
|
|
31
|
+
| Símbolo | Significado |
|
|
32
|
+
|---------|-------------|
|
|
33
|
+
| `✓` | ok |
|
|
34
|
+
| `✗` | problema confirmado |
|
|
35
|
+
| `!` | não verificável (best-effort — falha de rede nunca derruba o doctor) |
|
|
36
|
+
|
|
37
|
+
**Exit 1** se houver algum `✗`.
|
|
38
|
+
|
|
39
|
+
## Passos
|
|
40
|
+
|
|
41
|
+
1. Rode o comando.
|
|
42
|
+
2. Para cada `✗`, explique a causa ao usuário e proponha a correção concreta:
|
|
43
|
+
- escopo faltando → o usuário roda `!gh auth refresh --scopes project,repo,workflow` (interativo, ele executa)
|
|
44
|
+
- `.spec-wave.json` dessincronizado → `npx @spec-wave/cli@latest refresh --config`
|
|
45
|
+
- workflows/labels divergentes → skill **update**
|
|
46
|
+
- secret de IA ausente → Settings → Secrets → Actions (`ANTHROPIC_API_KEY` ou `OPENROUTER_API_KEY`)
|
|
47
|
+
- `specKit.command` ausente → configure antes de usar a skill **implement**
|
|
48
|
+
3. Trate `!` como "não deu para verificar", não como falha.
|
|
49
|
+
4. Se tudo passar e o problema original persistir, aí sim investigue a superfície específica (Action, issue, board).
|
|
50
|
+
|
|
51
|
+
> **404 ao criar issues** é o caso clássico: quase sempre token sem acesso ao repo/org — e o doctor aponta exatamente isso.
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-wave-fix-pr
|
|
3
|
+
description: "Use para auditar um Pull Request e corrigir os problemas encontrados — segurança, arquitetura, infraestrutura e qualidade — gerando um commit separado por fix, respondendo cada review comment com o hash do commit e postando um sumário no PR. Gatilhos: 'auditar o PR 42', 'corrigir os comentários de review', 'fix-pr 42', 'resolver os apontamentos do PR'."
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Bash(gh pr *)
|
|
6
|
+
- Bash(gh api *)
|
|
7
|
+
- Bash(git add *)
|
|
8
|
+
- Bash(git commit *)
|
|
9
|
+
- Bash(git push *)
|
|
10
|
+
- Bash(git checkout *)
|
|
11
|
+
- Read
|
|
12
|
+
- Edit
|
|
13
|
+
- Glob
|
|
14
|
+
- Grep
|
|
15
|
+
- Agent
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# spec-wave fix-pr — auditoria e correção de PR
|
|
19
|
+
|
|
20
|
+
Cada fix vira um **commit separado** no branch do PR. Cada review comment recebe uma **resposta com o hash do commit**.
|
|
21
|
+
|
|
22
|
+
**Pré-requisitos:** `.spec-wave.json` deve existir (para resolver `owner/repo`). Token com permissão de push no branch do PR.
|
|
23
|
+
|
|
24
|
+
## Passos
|
|
25
|
+
|
|
26
|
+
### 1. Resolver contexto
|
|
27
|
+
|
|
28
|
+
Leia `.spec-wave.json` para obter `owner` e `repo`. Confirme o número do PR com o usuário se não vier como argumento.
|
|
29
|
+
|
|
30
|
+
### 2. Coletar dados do PR
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
gh pr view <número> --json number,title,headRefName,body,changedFiles
|
|
34
|
+
gh pr diff <número>
|
|
35
|
+
gh api repos/<owner>/<repo>/pulls/<número>/comments
|
|
36
|
+
gh api repos/<owner>/<repo>/pulls/<número>/reviews
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Liste todos os arquivos alterados e colete os review comments (inline) e reviews gerais.
|
|
40
|
+
|
|
41
|
+
### 3. Checkout do branch
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
gh pr checkout <número>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 4. Varredura de problemas
|
|
48
|
+
|
|
49
|
+
Para cada categoria, leia os arquivos alterados e identifique issues:
|
|
50
|
+
|
|
51
|
+
| Categoria | O que procurar |
|
|
52
|
+
|-----------|----------------|
|
|
53
|
+
| **Segurança** | Credenciais hardcoded, secrets/API keys expostas, configs inseguras, injeção SQL/XSS |
|
|
54
|
+
| **Arquitetura** | Dependências circulares, exports faltando, wiring incompleto, violações de camada |
|
|
55
|
+
| **Infraestrutura** | OIDC mal configurado, IAM permissivo demais, Dockerfile sem usuário não-root, state remoto ausente |
|
|
56
|
+
| **Qualidade** | sync-over-async, validação ausente, operações não idempotentes, error handling ausente |
|
|
57
|
+
|
|
58
|
+
Se não houver review comments manuais, use um agente de review para detecção automatizada sobre o diff + arquivos alterados.
|
|
59
|
+
|
|
60
|
+
### 5. Corrigir, um commit por problema
|
|
61
|
+
|
|
62
|
+
Para cada problema: leia o arquivo (Read), aplique o fix (Edit), e commite isoladamente:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
git add <arquivo>
|
|
66
|
+
git commit -m "fix: <problema> (issue #<N>)
|
|
67
|
+
|
|
68
|
+
<causa raiz>
|
|
69
|
+
|
|
70
|
+
Solution: <descrição do fix>"
|
|
71
|
+
git push
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 6. Responder aos review comments
|
|
75
|
+
|
|
76
|
+
Para cada comment inline:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
gh api repos/<owner>/<repo>/pulls/<número>/comments/<comment-id>/replies \
|
|
80
|
+
-f body="✅ **FIXED** — commit **<HASH>**
|
|
81
|
+
|
|
82
|
+
\`\`\`<linguagem>
|
|
83
|
+
<trecho corrigido>
|
|
84
|
+
\`\`\`
|
|
85
|
+
|
|
86
|
+
<explicação do fix>"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 7. Sumário no PR
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
gh pr comment <número> --body "<sumário>"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Formato:
|
|
96
|
+
|
|
97
|
+
```markdown
|
|
98
|
+
## 🔍 PR Audit — Spec Wave
|
|
99
|
+
|
|
100
|
+
### Problemas encontrados e corrigidos
|
|
101
|
+
|
|
102
|
+
| # | Severidade | Categoria | Problema | Commit |
|
|
103
|
+
|---|-----------|-----------|---------|--------|
|
|
104
|
+
| 1 | 🔴 Critical | Segurança | Credencial hardcoded em config.js | abc1234 |
|
|
105
|
+
| 2 | 🟡 Medium | Qualidade | Operação não idempotente em createOrder | def5678 |
|
|
106
|
+
|
|
107
|
+
### Commits criados
|
|
108
|
+
- `abc1234` fix: credencial hardcoded removida (issue #1)
|
|
109
|
+
- `def5678` fix: idempotency key adicionada em createOrder (issue #2)
|
|
110
|
+
|
|
111
|
+
**Total:** <N> problema(s) encontrado(s) e corrigido(s).
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Severidade
|
|
115
|
+
|
|
116
|
+
| Nível | Critério |
|
|
117
|
+
|-------|----------|
|
|
118
|
+
| 🔴 Critical | Segurança, dados expostos, falha em produção |
|
|
119
|
+
| 🟠 High | Bug que afeta usuários, arquitetura quebrada |
|
|
120
|
+
| 🟡 Medium | Qualidade, manutenibilidade, performance |
|
|
121
|
+
| 🔵 Low | Estilo, naming, comentários |
|
|
122
|
+
|
|
123
|
+
## Output esperado
|
|
124
|
+
|
|
125
|
+
- Lista de issues (severidade + impacto)
|
|
126
|
+
- Lista de commits criados (hash + mensagem)
|
|
127
|
+
- Confirmação das replies postadas nos review comments
|
|
128
|
+
- Estado final do PR
|
|
129
|
+
|
|
130
|
+
> Reporte fielmente: se um problema foi encontrado mas **não** corrigido (fora de escopo, exige decisão do usuário), diga isso explicitamente no sumário em vez de omitir.
|