@spec-wave/cli 0.14.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/bin/spec-wave.mjs +44 -2
- 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-rest.mjs +206 -2
- package/src/commands/bug.mjs +8 -0
- package/src/commands/code-review.mjs +45 -4
- package/src/commands/decompose.mjs +11 -49
- 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 +6 -20
- package/src/commands/generate-spec.mjs +6 -22
- 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 +145 -5
- package/src/commands/triage.mjs +174 -0
- package/src/commands/update.mjs +352 -62
- 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/implement-board.mjs +12 -1
- package/src/lib/plugin-skills.mjs +122 -0
- package/src/lib/pr-branch.mjs +267 -0
- 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 +111 -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 +53 -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 +37 -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 +154 -0
- package/src/templates/skill/SKILL.md +69 -7
- 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,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "spec-wave",
|
|
3
|
+
"displayName": "Spec Wave",
|
|
4
|
+
"version": "0.16.0",
|
|
5
|
+
"description": "Fluxo spec-driven no GitHub (RFC-001): Projects v2, labels de gatilho, spec/plan gerados por Action, decomposição em duas etapas e implementação orientada a Stories/Tasks.",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "Astratech",
|
|
8
|
+
"url": "https://github.com/astratech-net-br"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/astratech-net-br/spec-wave-cli",
|
|
11
|
+
"repository": "https://github.com/astratech-net-br/spec-wave-cli",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"spec-driven",
|
|
14
|
+
"github-projects",
|
|
15
|
+
"kanban",
|
|
16
|
+
"rfc",
|
|
17
|
+
"spec-kit",
|
|
18
|
+
"workflow"
|
|
19
|
+
]
|
|
20
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Plugin spec-wave
|
|
2
|
+
|
|
3
|
+
Uma skill por comando do fluxo spec-driven (RFC-001). Em vez de um `SKILL.md`
|
|
4
|
+
monolítico que entra inteiro no contexto para qualquer pergunta, cada comando
|
|
5
|
+
carrega só a sua instrução.
|
|
6
|
+
|
|
7
|
+
## Skills
|
|
8
|
+
|
|
9
|
+
| Skill | Para quê |
|
|
10
|
+
|-------|----------|
|
|
11
|
+
| `workflow` | Mapa do processo: Kanban, labels, crítica adversarial, roteamento |
|
|
12
|
+
| `setup` | Configura o repositório (`init`) |
|
|
13
|
+
| `info` | Status de configuração |
|
|
14
|
+
| `doctor` | Preflight de auth, escopos, IA, board e workflows |
|
|
15
|
+
| `update` | Atualiza skill, `.spec-wave.json` e workflows/labels |
|
|
16
|
+
| `issue` | Cria Initiative/Epic/Feature/Bug/Spike/RFC no board |
|
|
17
|
+
| `spec` | Gera `spec.md` (1º documento) |
|
|
18
|
+
| `plan` | Gera `plan.md` (2º documento) + `tech_context.yml` |
|
|
19
|
+
| `ready` | Valida spec + plan |
|
|
20
|
+
| `decompose` | Rascunho revisável → Stories/Tasks |
|
|
21
|
+
| `order` | Ordem topológica das Stories |
|
|
22
|
+
| `implement` | Etapa 🚧 Desenvolvimento |
|
|
23
|
+
| `task` | `start` / `done` de uma Task |
|
|
24
|
+
| `story` | `review` de uma Story |
|
|
25
|
+
| `move` | Move qualquer item do board |
|
|
26
|
+
| `rfc` | Escreve um RFC e registra no board |
|
|
27
|
+
| `fix-pr` | Audita e corrige um Pull Request |
|
|
28
|
+
| `uninstall` | Remove a configuração do repositório |
|
|
29
|
+
|
|
30
|
+
## Instalação
|
|
31
|
+
|
|
32
|
+
### Claude Code
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
/plugin marketplace add astratech-net-br/spec-wave-cli
|
|
36
|
+
/plugin install spec-wave@spec-wave
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
As skills ficam namespaced: `/spec-wave:spec`, `/spec-wave:decompose`, etc.
|
|
40
|
+
|
|
41
|
+
### Codex
|
|
42
|
+
|
|
43
|
+
Codex não tem plugins — ele varre diretórios de skills. A CLI copia o mesmo
|
|
44
|
+
conteúdo para lá:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npx @spec-wave/cli@latest install-skill --agent codex # .agents/skills (projeto)
|
|
48
|
+
npx @spec-wave/cli@latest install-skill --agent codex --global # ~/.agents/skills (usuário)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Como não há namespace nesse destino, o `name:` do frontmatter é
|
|
52
|
+
`spec-wave-<comando>` — invocação: `$spec-wave-spec`.
|
|
53
|
+
|
|
54
|
+
## Estrutura de uma skill
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
skills/plan/
|
|
58
|
+
SKILL.md ← o agente LÊ (dirige a CLI)
|
|
59
|
+
model-prompt.md ← a CLI ENVIA a um modelo (id: `plan`)
|
|
60
|
+
model-prompt.critique.md ← idem (id: `plan/critique`)
|
|
61
|
+
reference/tech-context.md ← apoio, lido sob demanda
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Os `model-prompt*.md` **não** são instalados em agente nenhum: dizem o oposto do
|
|
65
|
+
`SKILL.md` ao lado. Arquivo de apoio também não entra sozinho no contexto, então
|
|
66
|
+
a cópia do marketplace fica inerte.
|
|
67
|
+
|
|
68
|
+
## Manutenção
|
|
69
|
+
|
|
70
|
+
- Edite os `SKILL.md` aqui; é a fonte única para os dois destinos.
|
|
71
|
+
- `.claude-plugin/plugin.json` deve acompanhar a versão do `package.json` —
|
|
72
|
+
há um teste que falha se divergirem.
|
|
73
|
+
- Valide com `claude plugin validate ./packages/spec-wave/src/plugin`.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-wave-bug
|
|
3
|
+
description: "Use para gerar o bug.md de um defeito do spec-wave — reprodução, causa raiz, escopo do fix e teste de regressão. Aplica a label spec-wave:bug e deixa o GitHub Action gerar e commitar o arquivo em docs/bugs/<slug>/. Gatilhos: 'gerar o bug.md da issue 42', 'documentar a causa raiz do bug', 'rodar o spec-wave:bug'. Só vale para issues do tipo Bug — Feature usa spec/plan."
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Bash(gh issue *)
|
|
6
|
+
- Bash(npx @spec-wave/cli@latest *)
|
|
7
|
+
- Read
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# spec-wave bug — o documento do defeito
|
|
11
|
+
|
|
12
|
+
> **Regra fundamental: nunca escreva o `bug.md` você mesmo.** Aplique a label e deixe o Action gerar — é isso que garante que o arquivo seja commitado e referenciado na issue. Exceção: revisar/melhorar um `bug.md` já gerado (aí sim use Edit no arquivo local).
|
|
13
|
+
|
|
14
|
+
**Contexto:** leia `.spec-wave.json` (Read). Ausente → skill **setup**.
|
|
15
|
+
|
|
16
|
+
## Por que existe
|
|
17
|
+
|
|
18
|
+
Um Bug **não** gera `spec.md` + `plan.md`. Esses documentos pedem visão geral funcional, critérios de aceite, requisitos não-funcionais e plano de rollback — peso desproporcional para um defeito.
|
|
19
|
+
|
|
20
|
+
O `bug.md` tem seis seções e uma finalidade: permitir que outra pessoa (ou o dev-agent) **reproduza, entenda e corrija** o defeito, com prova de que corrigiu.
|
|
21
|
+
|
|
22
|
+
## Passos
|
|
23
|
+
|
|
24
|
+
1. **Confirme que a issue é do tipo Bug.**
|
|
25
|
+
|
|
26
|
+
> **Apenas Bug.** Para qualquer outro tipo o Action **pula** a geração, remove a label e comenta.
|
|
27
|
+
|
|
28
|
+
2. Adicione a label de gatilho:
|
|
29
|
+
```bash
|
|
30
|
+
gh issue edit <número> --add-label "spec-wave:bug"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
3. Informe ao usuário: "Label `spec-wave:bug` adicionada. O Action `generate-bug.yml` vai gerar o `bug.md` automaticamente. Acompanhe em Actions → Generate Bug."
|
|
34
|
+
|
|
35
|
+
4. Quando concluir, ofereça revisar `docs/bugs/<slug>/bug.md`. O slug vem do título: `[BUG] Duplicidade de pedidos no PIX` → `duplicidade-de-pedidos-no-pix`.
|
|
36
|
+
|
|
37
|
+
Concentre a revisão em **duas seções**: **Causa Raiz** e **Teste de Regressão**. São elas que decidem se a correção ataca o defeito ou o sintoma — o resto do documento é contexto.
|
|
38
|
+
|
|
39
|
+
5. **Validar:** aplique `spec-wave:ready`. O Action confere as seis seções obrigatórias e aplica `spec-wave:bug-approved`.
|
|
40
|
+
|
|
41
|
+
## Quando é obrigatório
|
|
42
|
+
|
|
43
|
+
| Severidade | `bug.md` |
|
|
44
|
+
|---|---|
|
|
45
|
+
| **P0** | Opcional — o fix não espera documento. Documente depois, se valer. |
|
|
46
|
+
| **P1** | Recomendado. |
|
|
47
|
+
| **P2 / P3** | **Obrigatório** antes de o bug entrar na fila técnica (✅ Ready). |
|
|
48
|
+
|
|
49
|
+
## As seis seções
|
|
50
|
+
|
|
51
|
+
`Reprodução` · `Esperado e Obtido` · `Impacto e Severidade` · `Causa Raiz` · `Escopo do Fix` · `Teste de Regressão`
|
|
52
|
+
|
|
53
|
+
O validador procura estes títulos byte a byte — se alguém renomear uma seção ao editar o arquivo, o `spec-wave:ready` reprova.
|
|
54
|
+
|
|
55
|
+
## Se falhar
|
|
56
|
+
|
|
57
|
+
- **Comentário 🔎 de crítica com `spec-wave:critique-failed`** → a crítica adversarial achou problema grave. Os três alvos mais comuns: a causa raiz não explica todos os sintomas relatados; o escopo do fix é maior que a causa (refatoração pegando carona); o teste de regressão passaria mesmo sem o fix. Corrija o `bug.md`, commite, remova a label e reaplique `spec-wave:bug`.
|
|
58
|
+
- **`spec-wave:needs-human`** → a crítica reprovou N vezes seguidas e o fluxo está **parado**. Uma pessoa precisa revisar e remover a label.
|
|
59
|
+
- **Relato insuficiente** → o `bug.md` sai com "Causa raiz não determinada" e uma lista de hipóteses. Isso é comportamento correto, não falha: leve as perguntas a quem reportou, acrescente as respostas como comentário na issue e reaplique `spec-wave:bug` — os comentários entram no próximo payload.
|
|
60
|
+
- Para reprocessar num modelo mais forte só nesta issue, aplique também `spec-wave:model:<apelido>` (o apelido precisa existir em `ai.modelAliases`).
|
|
@@ -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,111 @@
|
|
|
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:**
|
|
42
|
+
```bash
|
|
43
|
+
gh issue edit <número> --add-label "spec-wave:decompose"
|
|
44
|
+
```
|
|
45
|
+
Informe: "Rascunho iniciado — vai commitar o `decomposition.md` e passar pela crítica. **Nenhuma issue é criada nesta etapa.**"
|
|
46
|
+
|
|
47
|
+
3. **Leia o resultado** quando o Action terminar:
|
|
48
|
+
|
|
49
|
+
| Label resultante | O que fazer |
|
|
50
|
+
|------------------|-------------|
|
|
51
|
+
| `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. |
|
|
52
|
+
| `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). |
|
|
53
|
+
| `spec-wave:needs-human` | A crítica esgotou as tentativas. **Pare** e envolva o usuário: as duas labels precisam sair à mão. |
|
|
54
|
+
|
|
55
|
+
4. **Etapa 2 — aplicar o rascunho aprovado**, só depois da revisão:
|
|
56
|
+
```bash
|
|
57
|
+
gh issue edit <número> --add-label "spec-wave:decompose-apply"
|
|
58
|
+
```
|
|
59
|
+
Aplicar essa label **é** a aprovação humana — não há nova crítica.
|
|
60
|
+
|
|
61
|
+
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.
|
|
62
|
+
|
|
63
|
+
6. A issue recebe `spec-wave:decomposed` (guard de idempotência): rodar de novo **não** duplica as issues.
|
|
64
|
+
|
|
65
|
+
> **Nunca pule a etapa 1** aplicando `spec-wave:decompose-apply` direto — sem `decomposition.md` o Action falha pedindo o rascunho.
|
|
66
|
+
|
|
67
|
+
## O arquivo `decomposition.md`
|
|
68
|
+
|
|
69
|
+
Fica em `docs/features/<slug>/decomposition.md` (Feature) ou `docs/rfcs/<slug>/decomposition.md` (RFC):
|
|
70
|
+
|
|
71
|
+
```markdown
|
|
72
|
+
# Decomposição — [FEATURE] Cadastro de Pedidos
|
|
73
|
+
<!-- spec-wave:decomposition v1 issue=360 kind=stories -->
|
|
74
|
+
|
|
75
|
+
## Story 1 — visualizar meus pedidos
|
|
76
|
+
|
|
77
|
+
**User story:** Como cliente, quero visualizar meus pedidos, para acompanhar entregas
|
|
78
|
+
**Depende de:** —
|
|
79
|
+
|
|
80
|
+
Descrição complementar (contexto, critérios de aceite).
|
|
81
|
+
|
|
82
|
+
### Task 1.1 — criar endpoint GET /pedidos
|
|
83
|
+
|
|
84
|
+
Corpo técnico.
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Ao editar à mão:**
|
|
88
|
+
|
|
89
|
+
- a **posição** manda, não o número escrito — inserir uma Story no meio sem renumerar funciona
|
|
90
|
+
- `**Depende de:**` usa referências **1-based** (`Story 1, Story 3`) ou `—`; apontar para si mesma ou para frente é **erro**, não filtro silencioso
|
|
91
|
+
- o corpo aceita markdown livre (`## Backend`, cercas de código) — só `## Story N` e `### Task N.M` são estrutura
|
|
92
|
+
- **para gerar outro rascunho do zero:** apague o arquivo e reaplique `spec-wave:decompose`
|
|
93
|
+
|
|
94
|
+
> ⚠️ 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.
|
|
95
|
+
|
|
96
|
+
## Guard de idempotência (`spec-wave:decomposed`)
|
|
97
|
+
|
|
98
|
+
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.
|
|
99
|
+
|
|
100
|
+
A `spec-wave:decompose-ready` **não** entra nesse guard — é estado de rascunho pendente, não de decomposição feita.
|
|
101
|
+
|
|
102
|
+
**Para forçar um re-decompose:**
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
gh issue edit <n> --remove-label "spec-wave:decomposed"
|
|
106
|
+
```
|
|
107
|
+
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`.
|
|
108
|
+
|
|
109
|
+
## Dependências entre Stories
|
|
110
|
+
|
|
111
|
+
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.
|