@spec-wave/cli 0.26.0 → 0.28.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.
Files changed (45) hide show
  1. package/package.json +1 -1
  2. package/src/api/github-rest.mjs +52 -0
  3. package/src/cli.mjs +12 -0
  4. package/src/commands/decompose.mjs +166 -39
  5. package/src/commands/doctor.mjs +214 -3
  6. package/src/commands/generate-bug.mjs +22 -16
  7. package/src/commands/generate-plan.mjs +72 -23
  8. package/src/commands/generate-spec.mjs +19 -15
  9. package/src/commands/implement.mjs +47 -22
  10. package/src/commands/install-skill.mjs +18 -8
  11. package/src/commands/preflight.mjs +322 -0
  12. package/src/commands/run.mjs +51 -30
  13. package/src/commands/update.mjs +143 -12
  14. package/src/commands/validate.mjs +84 -17
  15. package/src/config.mjs +18 -0
  16. package/src/lib/artifact-pr.mjs +272 -0
  17. package/src/lib/artifact-publish.mjs +169 -0
  18. package/src/lib/doc-availability.mjs +23 -1
  19. package/src/lib/doc-source.mjs +162 -0
  20. package/src/lib/flow-run.mjs +9 -218
  21. package/src/lib/next-step.mjs +27 -4
  22. package/src/lib/pr-branch.mjs +106 -7
  23. package/src/lib/repo-links.mjs +8 -2
  24. package/src/plugin/.claude-plugin/plugin.json +1 -1
  25. package/src/plugin/README.md +5 -0
  26. package/src/plugin/skills/bug/SKILL.md +2 -2
  27. package/src/plugin/skills/decompose/SKILL.md +4 -4
  28. package/src/plugin/skills/plan/SKILL.md +1 -1
  29. package/src/plugin/skills/preparar-feature/SKILL.md +245 -0
  30. package/src/plugin/skills/preparar-feature/reference/critica.md +88 -0
  31. package/src/plugin/skills/preparar-specs/SKILL.md +171 -0
  32. package/src/plugin/skills/preparar-specs/reference/armadilhas.md +209 -0
  33. package/src/plugin/skills/preparar-specs/reference/revisao.md +107 -0
  34. package/src/plugin/skills/run/SKILL.md +3 -1
  35. package/src/plugin/skills/spec/SKILL.md +4 -4
  36. package/src/plugin/skills/update/SKILL.md +10 -4
  37. package/src/plugin/skills/workflow/SKILL.md +8 -3
  38. package/src/templates/skill/SKILL.md +13 -10
  39. package/src/templates/workflows/code-review.yml +13 -2
  40. package/src/templates/workflows/critique.yml +1 -1
  41. package/src/templates/workflows/decompose.yml +13 -2
  42. package/src/templates/workflows/generate-bug.yml +17 -6
  43. package/src/templates/workflows/generate-plan.yml +20 -7
  44. package/src/templates/workflows/generate-spec.yml +20 -7
  45. package/src/templates/workflows/qa.yml +13 -0
@@ -0,0 +1,209 @@
1
+ # Armadilhas operacionais deste fluxo
2
+
3
+ Cada item aqui custou uma investigação real. A causa vem junto porque o sintoma, sozinho,
4
+ costuma apontar para o lugar errado.
5
+
6
+ ## Índice
7
+
8
+ 1. Token do `gh` inválido no ambiente
9
+ 2. `gh issue edit --add-label` falha com 503
10
+ 3. A API do GitHub devolve 503 intermitente
11
+ 4. Working tree compartilhado com outros agentes
12
+ 5. Label de gatilho grudada impede o retry
13
+ 6. `spec-wave:spec` sobrescreve spec revisada
14
+ 7. `spec-wave update` reescreve os workflows
15
+ 8. Runs `skipped` são normais — não são falha
16
+ 9. `conclusion` vazia não é conclusão
17
+ 10. Geração leva minutos — não rode em primeiro plano
18
+ 11. Run interrompido deixa lock órfão
19
+ 12. O documento foi gerado e o PR não nasceu
20
+
21
+ ---
22
+
23
+ ## 1. Token do `gh` inválido no ambiente
24
+
25
+ **Sintoma:** `gh` falha com erro de autenticação, ou enxerga o repositório errado.
26
+
27
+ **Causa:** a variável `GH_TOKEN` do ambiente pode estar inválida ou pertencer a uma conta
28
+ sem acesso à organização, enquanto o keyring tem a conta certa.
29
+
30
+ **Como resolver:** exporte o token da conta correta antes dos comandos:
31
+
32
+ ```bash
33
+ export GH_TOKEN=$(env -u GH_TOKEN gh auth token -u <conta-com-acesso>)
34
+ ```
35
+
36
+ O `env -u GH_TOKEN` é necessário porque o `gh auth token` também consulta a variável
37
+ inválida se ela estiver setada.
38
+
39
+ A CLI tem a saída própria dela para o mesmo problema, que não depende do shell:
40
+ `spec-wave --account <login> <comando>`, ou `"github": { "account": "<login>" }` no
41
+ `.spec-wave.json`. Fora do CI, a conta declarada vence a variável de ambiente.
42
+
43
+ ## 2. `gh issue edit --add-label` falha com 503
44
+
45
+ **Sintoma:** o comando falha repetidamente, e parece que o gatilho não existe.
46
+
47
+ **Causa:** esse subcomando passa pelo GraphQL, que pode estar degradado enquanto o REST
48
+ funciona normalmente.
49
+
50
+ **Alternativa que funciona:**
51
+
52
+ ```bash
53
+ gh api -X POST repos/<owner>/<repo>/issues/<n>/labels -f "labels[]=spec-wave:spec"
54
+ ```
55
+
56
+ ## 3. A API do GitHub devolve 503 intermitente
57
+
58
+ **Sintoma:** comandos falham de forma aleatória e passam na tentativa seguinte.
59
+
60
+ **Como lidar:** envolva as chamadas em retry (3–5 tentativas com pausa) e **verifique o
61
+ resultado real**, não o código de saída isolado. Um `gh` que devolve string vazia sem erro
62
+ é indistinguível de "não encontrei nada" se você não conferir.
63
+
64
+ ## 4. Working tree compartilhado com outros agentes
65
+
66
+ **Sintoma:** arquivos modificados que você não criou; branch diferente da esperada.
67
+
68
+ **Causa:** outros processos (dev-agents, outras sessões) usam o mesmo checkout e trocam de
69
+ branch sem aviso.
70
+
71
+ **Regra:** nunca `checkout`, `stash` ou `reset` sem antes conferir `git branch --show-current`
72
+ e `git status --short`. A geração em si não disputa o checkout — ela publica por API, sem
73
+ tocar em disco —, mas tudo que você fizer à mão disputa.
74
+
75
+ Se precisar mesmo de uma branch checada — por exemplo, para editar arquivos de um PR já
76
+ aberto — use um worktree temporário fora do repositório, e remova depois:
77
+
78
+ ```bash
79
+ git worktree add /tmp/<dir> <branch>
80
+ # ... edições, commit, push ...
81
+ git worktree remove --force /tmp/<dir> && git worktree prune
82
+ ```
83
+
84
+ ## 5. Label de gatilho grudada impede o retry
85
+
86
+ **Sintoma:** reaplicar a label não dispara nada; ou o `run` local recusa executar com
87
+ `⛔ trigger-pending`.
88
+
89
+ **Causa:** o evento `issues: [labeled]` não redispara com a label já presente, e o `run`
90
+ recusa rodar com gatilho pendente — a label significa "Action em execução", ou uma que
91
+ falhou e a deixou para trás.
92
+
93
+ **Como resolver:** remover e reaplicar. No modo local, onde nenhuma Action está rodando, a
94
+ label é resíduo: **remova-a em vez de usar `--force`**, para a issue não mentir sobre o
95
+ estado.
96
+
97
+ ```bash
98
+ gh api -X DELETE "repos/<owner>/<repo>/issues/<n>/labels/spec-wave:spec"
99
+ ```
100
+
101
+ Nem sempre a label fica: em algumas falhas a CLI a remove sozinha no início do run.
102
+ Confira issue a issue em vez de supor — o `preflight` já lista as pendentes.
103
+
104
+ ## 6. `spec-wave:spec` sobrescreve spec revisada
105
+
106
+ A label **regenera** o documento do zero. Se a spec já foi revisada, editada à mão ou
107
+ corrigida, reaplicar joga tudo fora para consertar o que muitas vezes é uma frase.
108
+
109
+ Para correção pontual em documento já gerado, a edição direta é permitida **quando o
110
+ usuário pede explicitamente** — e só nesse caso. Edite no PR: as edições são preservadas.
111
+
112
+ ## 7. `spec-wave update` reescreve os workflows
113
+
114
+ O `update` compara os workflows com os templates da CLI e sobrescreve os divergentes. Toda
115
+ customização local neles é perdida no bump, silenciosamente, e o sintoma só aparece na
116
+ próxima geração.
117
+
118
+ Se o repositório tem workflows customizados de propósito, rode `update --skip-repo`, ou
119
+ reaplique a customização antes de commitar o bump. Confirme depois:
120
+
121
+ ```bash
122
+ git show origin/main:.github/workflows/generate-spec.yml | grep <marca-da-customizacao>
123
+ ```
124
+
125
+ ## 8. Runs `skipped` são normais — não são falha
126
+
127
+ O evento `issues: [labeled]` dispara **todos** os workflows que escutam labels; cada um se
128
+ filtra pelo próprio `if:`. Ver `generate-plan` e `decompose` como `skipped` depois de
129
+ aplicar `spec-wave:spec` é o comportamento correto, não um problema.
130
+
131
+ O mesmo vale para o repositório em modo `local`: todo job carrega
132
+ `if: vars.SPEC_WAVE_EXECUTION != 'local'`, então o run aparece verde e `skipped`, sem erro
133
+ e sem documento. Se você aplicou uma label e nada aconteceu, confira o modo antes de
134
+ procurar defeito: `npx @spec-wave/cli@latest mode`.
135
+
136
+ Ao procurar o run que interessa, filtre pelo workflow **e** pelo título da issue.
137
+
138
+ ## 9. `conclusion` vazia não é conclusão
139
+
140
+ O `gh run list` devolve `conclusion` como **string vazia** — não `null` — enquanto o run
141
+ está em andamento. Um filtro `select(.conclusion != null)` deixa passar runs que ainda
142
+ estão rodando, e você conclui cedo demais que tudo terminou.
143
+
144
+ Filtre por `.status == "completed"` **e** `conclusion` não-vazia.
145
+
146
+ ## 10. Geração leva minutos — não rode em primeiro plano
147
+
148
+ Uma spec é uma chamada de modelo gerando um documento longo: leva minutos. Rodar no
149
+ primeiro plano de uma ferramenta com timeout curto faz o comando morrer no meio — e o custo
150
+ já foi pago.
151
+
152
+ Rode em background, ou com timeout generoso (10 min por Feature). Numa milestone grande em
153
+ modo local isso passa de uma hora em série; combine com o usuário antes de começar.
154
+
155
+ ## 11. Run interrompido deixa lock órfão
156
+
157
+ **Sintoma:** `Já existe um 'spec-wave run' para <n> (pid NNNN, desde ...)` e a geração é
158
+ recusada, mesmo não havendo nada rodando.
159
+
160
+ **Causa:** o `run` grava `.git/spec-wave/run-<n>.lock` para impedir duas execuções na mesma
161
+ issue. Um run morto por timeout ou Ctrl-C não tem chance de limpar o próprio lock.
162
+
163
+ **Como resolver — confirmando antes:** o lock guarda o pid, então dá para verificar se o
164
+ processo realmente morreu em vez de apagar no escuro:
165
+
166
+ ```bash
167
+ cat .git/spec-wave/run-<n>.lock # {"pid":NNNN,"startedAt":"..."}
168
+ ps -p NNNN >/dev/null && echo VIVO || echo morto
169
+ rm .git/spec-wave/run-<n>.lock # só se morto
170
+ ```
171
+
172
+ O cuidado importa quando você rodou várias Features: pode haver um lock órfão e outro de um
173
+ run **em andamento** ao lado. Apagar o lock errado põe dois `run` na mesma issue.
174
+
175
+ A boa notícia é que a interrupção em si é limpa — o documento não é publicado pela metade.
176
+ Confirme com a ausência de PR novo antes de rerodar.
177
+
178
+ ## 12. O documento foi gerado e o PR não nasceu
179
+
180
+ **Sintoma:** o passo termina, o commit existe na branch `spec-wave/<n>-<doc>` — e nenhum PR
181
+ aparece. O documento fica numa branch que ninguém está olhando, e a próxima execução, se
182
+ ninguém perceber, **regera por cima**.
183
+
184
+ **Causa:** a publicação precisa de `pull-requests: write` **e** de a organização permitir
185
+ que Actions abram PRs. A segunda parte é a traiçoeira: *"Allow GitHub Actions to create and
186
+ approve pull requests"* (Settings → Actions → General) vem desligada por padrão em muitas
187
+ organizações, e o erro não se parece com falta de permissão.
188
+
189
+ **Como resolver:** ligar a opção, ou definir um PAT no secret `GH_PR_TOKEN`. O `preflight`
190
+ e o `doctor` verificam os dois; o estado `⚠ em branch sem PR` no inventário é exatamente
191
+ este caso.
192
+
193
+ Não se aplica ao modo `local`, onde o token é o seu.
194
+
195
+ ---
196
+
197
+ ## Nota histórica: o regime anterior à 0.27.0
198
+
199
+ Até a 0.26.0 a geração publicava com `commit` + `pull --rebase` + `push` **na branch
200
+ default**, a partir do checkout. Duas armadilhas vinham daí e **não valem mais**:
201
+
202
+ - **push rejeitado com `GH013`** em repositório que exige PR — a falha vinha *depois* de o
203
+ modelo ter gerado o documento, e o conteúdo se perdia com o runner;
204
+ - **working tree sujo quebrava toda geração local**, porque qualquer arquivo modificado
205
+ travava o `pull --rebase`.
206
+
207
+ Hoje a publicação é por API, em branch própria por documento, sem tocar no checkout. Se o
208
+ `preflight` apontar uma CLI antiga fixada nos workflows, as duas voltam a valer — e a
209
+ saída é `npx @spec-wave/cli@latest update --branch`.
@@ -0,0 +1,107 @@
1
+ # Fase 3 — revisão de conteúdo
2
+
3
+ O gerador escreve cada spec isoladamente, a partir do corpo de uma issue. Ele é bom nisso:
4
+ as seções vêm completas, os requisitos rastreados, os fluxos coerentes **dentro** do
5
+ documento. O que ele estruturalmente não consegue ver é a relação entre os documentos —
6
+ porque, quando escreveu o primeiro, os outros não existiam.
7
+
8
+ É exatamente aí que moram os problemas que custam caro depois. Por isso a regra desta fase:
9
+ **leia as specs como conjunto, não uma a uma.**
10
+
11
+ ## Como ler
12
+
13
+ Leia todas na íntegra antes de julgar qualquer uma. Ao ler a quinta, você reconhece na
14
+ primeira uma contradição que era invisível quando ela era o único documento.
15
+
16
+ Vale montar, enquanto lê, um mapa mental de três coisas:
17
+
18
+ - **regras compartilhadas** — um teto, uma ordem de prioridade, uma janela de tempo que
19
+ aparece em mais de uma feature;
20
+ - **quem depende de quem** — e em que direção cada spec declara a dependência;
21
+ - **afirmações sobre o mundo** — "tal feature ainda não existe", "isso é feito por X".
22
+
23
+ As três classes de problema abaixo saem desse mapa.
24
+
25
+ ## Classe 1 — contradição entre specs
26
+
27
+ Duas features descrevem a mesma regra de formas que não fecham: contagens diferentes,
28
+ prioridades diferentes, a mesma janela de tempo medida a partir de marcos diferentes.
29
+
30
+ Isso é grave porque cada spec, sozinha, parece certa. O erro só existe no par — e vira dois
31
+ comportamentos incompatíveis em produção, descobertos na integração.
32
+
33
+ Ao encontrar, verifique qual das duas está alinhada com a fonte normativa (o corpo da issue,
34
+ o documento de requisitos) antes de propor a correção. Frequentemente uma está certa e a
35
+ outra derivou.
36
+
37
+ ## Classe 2 — dependência que não fecha
38
+
39
+ Três formatos, todos vistos de verdade:
40
+
41
+ **Aponta para algo que não existe.** A feature A declara que seu componente vive na feature
42
+ B, e a spec de B não menciona esse componente em lugar nenhum. Alguém vai descobrir isso na
43
+ implementação, quando já for caro.
44
+
45
+ **Direção invertida ou circular.** A declara depender de B enquanto B declara depender de A.
46
+ Uma spec bem gerada às vezes corrige isso sozinha e **documenta a correção** — quando vir
47
+ uma nota dessas, confira se a outra ponta concorda.
48
+
49
+ **Inversão de sequenciamento entre milestones.** A dependência bloqueante está numa
50
+ milestone que vence *depois* da que depende dela. Não é erro de spec — é erro de
51
+ planejamento que só aparece quando se olha as datas junto com as dependências. Levante
52
+ sempre, porque ninguém mais vai olhar para os dois ao mesmo tempo.
53
+
54
+ **Como verificar de forma barata:** para cada dependência declarada, confira se o
55
+ diretório/arquivo existe e se a outra ponta concorda com a direção e o escopo.
56
+
57
+ ## Classe 3 — afirmação que a própria rodada tornou falsa
58
+
59
+ Esta é sutil e específica de gerar várias specs de uma vez: a spec gerada às 10h afirma
60
+ "tal feature ainda não possui spec" e às 10h20 essa spec passa a existir — gerada pela
61
+ mesma rodada.
62
+
63
+ **Cuidado ao corrigir:** a mesma frase costuma aparecer várias vezes no documento, sobre
64
+ alvos diferentes, e só algumas ficaram obsoletas. Verifique alvo por alvo antes de editar.
65
+ Corrigir por padrão de texto transforma afirmação verdadeira em falsa.
66
+
67
+ E note *como* corrigir: quando a afirmação obsoleta era a **justificativa** de um TODO, a
68
+ pergunta não desaparece — ela muda de razão. Reescreva a justificativa apontando onde a
69
+ questão vive agora, em vez de apagar a frase e deixar o TODO sem explicação.
70
+
71
+ ## Também procure
72
+
73
+ - **Sobreposição com feature já entregue.** Se uma spec descreve algo que uma feature
74
+ fechada já faz, há risco de duplicar comportamento em produção. Confira o estado da issue
75
+ antiga — "fechada" muda a conversa de "coordenar" para "não quebrar o que existe".
76
+ - **Regra que contradiz outra regra da mesma spec.** Raro, mas acontece quando uma regra é
77
+ categórica ("nunca expor dado individual") e outra define um recorte fino o bastante para
78
+ violá-la na prática. Vale destacar: costuma ser o achado de maior severidade.
79
+ - **Parâmetro declarado como "definido previamente" que ninguém definiu.** Limiares, prazos,
80
+ número de tentativas. Individualmente parecem detalhe; juntos costumam ser uma decisão só,
81
+ sem dono.
82
+
83
+ ## Como classificar o que encontrou
84
+
85
+ **Achado material** — muda o desenho de uma feature, ou tem risco em produção. Vai como
86
+ comentário na issue correspondente, contendo: a regra que o originou (citada), por que não
87
+ se resolve no `plan`, e a decisão necessária. Se o achado tem dois lados (duas features
88
+ discordando), comente **nos dois**, apontando um para o outro — quem abrir só uma issue
89
+ precisa enxergar o quadro inteiro.
90
+
91
+ **Lacuna paramétrica** — falta um número. Não bloqueia o `plan`. Agrupe por tema no
92
+ relatório final: doze lacunas espalhadas costumam ser seis decisões, e uma lista de doze
93
+ itens soltos não é acionável.
94
+
95
+ O teste para separar as duas: *se ninguém decidir isso, o que acontece?* Se a resposta é
96
+ "implementam errado" ou "duas partes se comportam de formas incompatíveis", é material. Se
97
+ é "implementam com um valor provisório e ajustam depois", é paramétrico.
98
+
99
+ ## O que não fazer
100
+
101
+ Não reescreva a spec para consertar o que encontrou. A spec é registro do que foi gerado a
102
+ partir da fonte normativa; a correção de regra é decisão do PO, e o lugar dela é a issue.
103
+ Editar o documento direto faz a decisão parecer tomada — e ninguém consegue rastrear quem
104
+ a tomou.
105
+
106
+ A exceção é o erro factual puro (Classe 3), que não é decisão de ninguém — e, mesmo aí,
107
+ só com pedido explícito do usuário.
@@ -50,13 +50,15 @@ O comando **explica e para**, saindo com código 2. Não force sem entender:
50
50
  - **`trigger-pending`** — há label de gatilho na issue: um Action está em voo (ou falhou deixando-a). Rodar por cima duplicaria documento e comentário. `--force` fura, quando você tem certeza.
51
51
  - **`needs-human` / `critique-failed`** — portões humanos da crítica. O caminho é corrigir o documento e remover a label; para o `critique-failed` o passo de retomada é **re-criticar**, nunca regerar.
52
52
  - **`stale-checkout`** — o documento existe no repositório e não no seu clone. `git pull` e repita; seguir sobrescreveria o que já foi publicado.
53
+ - **`pr-pending`** — o documento foi gerado e está num **Pull Request ainda não mergeado**. Revise o PR (edite ali mesmo, se precisar) e faça o merge; o passo seguinte lê o documento da branch base. Rodar por cima regeraria o arquivo, descartando a revisão e pagando a IA de novo.
54
+ - **`branch-without-pr`** — o documento foi commitado numa branch `spec-wave/*` e **nenhum PR foi aberto** para ela. Quase sempre a abertura do PR falhou: opção *"Allow GitHub Actions to create and approve pull requests"* desligada, ou secret `GH_PR_TOKEN` ausente. Rode `spec-wave doctor`, corrija e abra o PR — reaplicar o gatilho **regera** o documento.
53
55
  - **`needs-confirmation`** — o passo cria issues (`decompose-apply`) ou gasta IA repetindo a crítica de um rascunho existente. Revise antes e confirme com `--apply` / `--yes`.
54
56
  - **`inconsistent-state`** — as labels afirmam um documento que não existe. Quase sempre o título da issue mudou depois de gerar (o slug vira outro diretório).
55
57
 
56
58
  ## Regras que o `run` respeita — e você também
57
59
 
58
60
  - **Nunca aplique label de gatilho no modo local.** Ela dispararia o Action e o passo aconteceria duas vezes. O `run` não aplica nenhuma.
59
- - **Um passo por invocação.** `--max-steps <n>` encadeia, mas cada passo de IA custa dinheiro — encadeie só quando o usuário pedir.
61
+ - **Um passo por invocação.** `--max-steps <n>` encadeia, mas cada passo de IA custa dinheiro — encadeie só quando o usuário pedir. Na prática o encadeamento agora para sozinho: cada documento vai para um Pull Request, e o passo seguinte depende do merge.
60
62
  - A **Regra fundamental** continua valendo: nunca escreva `spec.md`/`plan.md`/`decomposition.md` à mão. Quem gera é a CLI, aqui como no Action.
61
63
 
62
64
  ## `mode` — o interruptor
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: spec-wave-spec
3
- description: "Use para iniciar a geração da especificação funcional (spec.md) de uma Feature do spec-wave — o PRIMEIRO documento do ciclo, antes do plano técnico. Aplica a label spec-wave:spec e deixa o GitHub Action gerar e commitar o arquivo. Gatilhos: 'gerar a spec da feature 12', 'criar especificação funcional', 'rodar o spec-wave:spec'. Só vale para Features — Spike, RFC e Bug não usam spec."
3
+ description: "Use para iniciar a geração da especificação funcional (spec.md) de uma Feature do spec-wave — o PRIMEIRO documento do ciclo, antes do plano técnico. Aplica a label spec-wave:spec e deixa o GitHub Action gerar o arquivo e abrir um Pull Request. Gatilhos: 'gerar a spec da feature 12', 'criar especificação funcional', 'rodar o spec-wave:spec'. Só vale para Features — Spike, RFC e Bug não usam spec."
4
4
  allowed-tools:
5
5
  - Bash(gh issue *)
6
6
  - Bash(npx @spec-wave/cli@latest *)
@@ -9,7 +9,7 @@ allowed-tools:
9
9
 
10
10
  # spec-wave spec — especificação funcional (1º documento)
11
11
 
12
- > **Regra fundamental: nunca escreva o `spec.md` à mão.** Quem gera é o spec-wave — pelo Action ou pela CLI local. É isso que garante que o arquivo seja commitado e referenciado na issue. Exceção: revisar/melhorar um `spec.md` já gerado (aí sim use Edit).
12
+ > **Regra fundamental: nunca escreva o `spec.md` à mão.** Quem gera é o spec-wave — pelo Action ou pela CLI local. É isso que garante que o arquivo chegue à main por Pull Request e seja referenciado na issue. Exceção: revisar/melhorar um `spec.md` já gerado (aí sim use Edit).
13
13
 
14
14
  ## Dois modos, mesmo resultado
15
15
 
@@ -18,7 +18,7 @@ allowed-tools:
18
18
  | **Action** | aplicar a label `spec-wave:spec` | fluxo assíncrono; roda no CI, você acompanha pela issue |
19
19
  | **Local** | `npx @spec-wave/cli@latest generate-spec --issue-number <n>` | você quer o documento **agora**, nesta sessão, e iterar em cima dele |
20
20
 
21
- O modo é detectado pelo ambiente — fora do Actions, a CLI roda em modo local automaticamente. Os dois geram o arquivo, commitam, dão push, comentam na issue e removem a label de gatilho. **Pergunte ao usuário qual ele quer** se não estiver claro; na dúvida numa sessão interativa, prefira o local (o resultado aparece em segundos, em vez de exigir acompanhar o Action).
21
+ O modo é detectado pelo ambiente — fora do Actions, a CLI roda em modo local automaticamente. Os dois geram o arquivo, abrem um **Pull Request** com ele, comentam na issue e removem a label de gatilho. **Pergunte ao usuário qual ele quer** se não estiver claro; na dúvida numa sessão interativa, prefira o local (o resultado aparece em segundos, em vez de exigir acompanhar o Action).
22
22
 
23
23
  > Local exige a credencial de IA no seu ambiente (`OPENROUTER_API_KEY`, `ANTHROPIC_API_KEY` ou o login do Claude Code, se o provider for `claude-oauth`) e um `.spec-wave.json` no repositório. Para conduzir o fluxo inteiro sem gastar minutos de Actions, veja a skill **run**.
24
24
 
@@ -36,7 +36,7 @@ O modo é detectado pelo ambiente — fora do Actions, a CLI roda em modo local
36
36
  ```bash
37
37
  npx @spec-wave/cli@latest generate-spec --issue-number <número>
38
38
  ```
39
- O comando imprime `Modo de execução: local`, gera, commita e faz push.
39
+ O comando imprime `Modo de execução: local`, gera e abre o Pull Request. Nada é gravado no seu clone — o documento vive no PR até o merge.
40
40
 
41
41
  **Action** — assíncrono:
42
42
  ```bash
@@ -16,6 +16,9 @@ Atualiza **somente o que divergiu** da versão da CLI: a **skill** instalada (po
16
16
  | `--skip-skill` | Não verifica/atualiza a skill instalada. |
17
17
  | `--skip-config` | Não verifica/atualiza o `.spec-wave.json`. |
18
18
  | `--skip-repo` | Não verifica/atualiza workflows e labels do repo. |
19
+ | `--branch [nome]` | Envia os arquivos do repo como **Pull Request** numa branch, em um único commit (sem valor: `spec-wave/update-v<versão>`). |
20
+ | `--config-in-pr` / `--no-config-in-pr` | Força incluir/excluir o `.spec-wave.json` do PR. |
21
+ | `--skill-in-pr` / `--no-skill-in-pr` | Força incluir/excluir a skill dos agentes do PR. |
19
22
  | `--dry-run` | Mostra o que seria atualizado sem alterar nada. |
20
23
  | `--yes` | Aplica sem pedir confirmação. |
21
24
 
@@ -28,15 +31,18 @@ Atualiza **somente o que divergiu** da versão da CLI: a **skill** instalada (po
28
31
 
29
32
  2. Mostre ao usuário o resumo por categoria (skill / config / arquivos do repo / labels). Se **nada** divergiu, informe que já está tudo na versão atual e encerre.
30
33
 
31
- 3. Com a aprovação, aplique:
34
+ 3. Com a aprovação, aplique — e **prefira o Pull Request**:
32
35
  ```bash
33
- npx @spec-wave/cli@latest update --yes
36
+ npx @spec-wave/cli@latest update --yes --branch # 1 commit atômico + PR (recomendado)
37
+ npx @spec-wave/cli@latest update --yes # commits diretos na branch default
34
38
  ```
35
39
  Limite o escopo com `--skip-skill`, `--skip-config` ou `--skip-repo` se o usuário só quiser parte.
36
40
 
37
41
  4. **Onde cada coisa aterrissa:**
38
- - **arquivos do repo** (workflows, labels) commitados no remoto pelo comando
39
- - **`.spec-wave.json`**arquivo **local**; lembre o usuário de commitá-lo
42
+ - **workflows e templates de issue** → no PR (com `--branch`) ou commitados direto na branch default
43
+ - **labels**sempre direto na base: são metadado do repositório, não há como versioná-las
44
+ - **`.spec-wave.json` e a skill** → o comando **consulta a base** e vai pelo mesmo caminho do arquivo: se o repositório já versiona aquele caminho, a atualização entra no PR; se não versiona, fica só local e o usuário precisa commitá-la. Force com `--config-in-pr` / `--skill-in-pr` se o projeto quiser passar a versionar.
45
+ - a skill é gravada em disco nos dois casos — é a cópia que o agente carrega
40
46
 
41
47
  5. Se a skill foi atualizada, oriente a **recarregar/reiniciar o agente** para pegar a nova versão.
42
48
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: spec-wave-workflow
3
- description: "Use quando a pergunta for sobre o fluxo spec-wave como um todo — qual é a próxima etapa de uma issue, o que cada coluna do Kanban significa, quais labels disparam quais Actions, como funciona a crítica adversarial, ou quando o usuário pedir spec-wave sem dizer qual comando. É o mapa do processo RFC-001; para executar uma ação específica, use a skill do comando correspondente (setup, issue, spec, plan, ready, decompose, implement, order, task, story, move, doctor, update, info, uninstall, rfc, fix-pr)."
3
+ description: "Use quando a pergunta for sobre o fluxo spec-wave como um todo — qual é a próxima etapa de uma issue, o que cada coluna do Kanban significa, quais labels disparam quais Actions, como funciona a crítica adversarial, ou quando o usuário pedir spec-wave sem dizer qual comando. É o mapa do processo RFC-001; para executar uma ação específica, use a skill do comando correspondente (setup, issue, spec, plan, ready, decompose, run, bug, triage, implement, order, task, story, move, doctor, update, info, uninstall, rfc, fix-pr); para conduzir um trecho inteiro do fluxo de uma vez, preparar-feature (uma Feature até Ready) ou preparar-specs (as specs de uma milestone)."
4
4
  allowed-tools:
5
5
  - Bash(npx @spec-wave/cli@latest *)
6
6
  - Bash(gh issue *)
@@ -31,7 +31,7 @@ Toda a CLI é invocada como `npx @spec-wave/cli@latest <comando>`.
31
31
  - **Action:** aplique a label de gatilho (`spec-wave:spec`, `spec-wave:plan`, `spec-wave:decompose`);
32
32
  - **Local:** `npx @spec-wave/cli@latest generate-spec|generate-plan|decompose --issue-number <n>` na sua sessão.
33
33
 
34
- O modo é detectado pelo ambiente (`GITHUB_ACTIONS`), sem flag. Os dois geram, commitam, fazem push, comentam na issue e sincronizam o board — o board é a fonte de verdade independentemente de onde rodou. Local exige a chave de IA no seu ambiente e um `.spec-wave.json`. Exceção à regra: revisar/melhorar um documento já gerado.
34
+ O modo é detectado pelo ambiente (`GITHUB_ACTIONS`), sem flag. Os dois geram, abrem um **Pull Request** com o documento, comentam na issue e sincronizam o board — o board é a fonte de verdade independentemente de onde rodou. Local exige a chave de IA no seu ambiente e um `.spec-wave.json`. Exceção à regra: revisar/melhorar um documento já gerado.
35
35
  2. **Nunca crie Story ou Task avulsa.** Elas nascem do `decompose`, já em **✅ Ready** e vinculadas ao pai. Criadas à mão caem em 📥 Backlog e **não aparecem em tela nenhuma** da UI (o inbox do PM lista Features, a tela do Dev lê 🚧 Desenvolvimento, a fila do TL lê ✅ Ready).
36
36
  3. **Nunca use `gh issue create`** para work items — não adiciona ao Project, a issue fica sem Etapa e some das telas. Use `npx @spec-wave/cli@latest issue`.
37
37
  4. **A Etapa só avança, nunca retrocede.** O campo **Status** (Todo / In Progress / Done) mede o progresso *dentro* da Etapa e reinicia a cada avanço. Prefira `move`, `task start|done` e `story review` a mutações GraphQL manuais — os comandos embutem essas regras.
@@ -88,7 +88,7 @@ Depois do `generate-plan` e **antes** de qualquer issue nascer no `decompose`, u
88
88
  | Reprovou depois de | O que corrigir | Como retomar |
89
89
  |--------------------|----------------|--------------|
90
90
  | `generate-plan` | `plan.md` (ou a `spec.md` que o embasa) | corrija/regere → remova `critique-failed` → reaplique `spec-wave:ready` |
91
- | `decompose` | **`decomposition.md`** — os achados citam `Story N` / `Task N.M`, títulos **desse arquivo** | edite e commite → remova `critique-failed` → reaplique `spec-wave:decompose` (critica o arquivo como está, sem regerar) |
91
+ | `decompose` | **`decomposition.md`** — os achados citam `Story N` / `Task N.M`, títulos **desse arquivo** | edite no Pull Request → remova `critique-failed` → reaplique `spec-wave:decompose` (critica o arquivo como está, sem regerar) |
92
92
 
93
93
  > ⚠️ No `decompose` os achados são sobre as **Stories propostas**, não sobre o `plan.md`. Corrigir o plan não muda o rascunho já gravado.
94
94
 
@@ -148,6 +148,11 @@ O slug vem do **título**: `[FEATURE] Cadastro de Pedidos com PIX` → `cadastro
148
148
  | gerar o plano técnico | `plan` |
149
149
  | validar spec+plan | `ready` |
150
150
  | quebrar em Stories/Tasks | `decompose` |
151
+ | levar uma Feature da spec até ✅ Ready, de ponta a ponta | `preparar-feature` |
152
+ | gerar as specs de uma milestone inteira | `preparar-specs` |
153
+ | rodar o fluxo localmente / desarmar os workflows | `run` |
154
+ | registrar ou corrigir um Bug | `bug` |
155
+ | triar um Bug | `triage` |
151
156
  | implementar | `implement` |
152
157
  | ver ordem das Stories | `order` |
153
158
  | mover Task | `task` |
@@ -86,7 +86,7 @@ O `run` decide o passo pelo estado da issue (documentos existentes + labels), re
86
86
 
87
87
  ## Regra fundamental
88
88
 
89
- **Nunca gere `spec.md` ou `plan.md` diretamente.** Acione o passo — a label (modo actions) ou o `run` (modo local) — e deixe o spec-wave gerar o arquivo. Isso garante que o arquivo seja commitado no repositório e referenciado na issue.
89
+ **Nunca gere `spec.md` ou `plan.md` diretamente.** Acione o passo — a label (modo actions) ou o `run` (modo local) — e deixe o spec-wave gerar o arquivo. Isso garante que o arquivo chegue à main por **Pull Request** e seja referenciado na issue.
90
90
 
91
91
  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.
92
92
 
@@ -208,6 +208,7 @@ Mesmas flags do `issue` (exceto `--type`, fixo em `feature`). Mantido para o flu
208
208
  | `--skip-skill` / `--skip-config` / `--skip-repo` | flag | Pula a categoria correspondente. |
209
209
  | `--branch [nome]` | flag/string | Envia os arquivos do repo como **Pull Request** numa branch, em **um único commit**, em vez de commitar direto na branch default. Sem valor, usa `spec-wave/update-v<versão>`. |
210
210
  | `--config-in-pr` / `--no-config-in-pr` | flag | Força incluir/excluir o `.spec-wave.json` do PR (o default decide sozinho — veja abaixo). |
211
+ | `--skill-in-pr` / `--no-skill-in-pr` | flag | Força incluir/excluir a **skill dos agentes** do PR (o default decide sozinho — veja abaixo). |
211
212
  | `--dry-run` | flag | Mostra o que seria atualizado sem alterar nada. |
212
213
  | `--yes` | flag | Aplica sem pedir confirmação. |
213
214
 
@@ -215,7 +216,9 @@ Mesmas flags do `issue` (exceto `--type`, fixo em `feature`). Mantido para o flu
215
216
 
216
217
  > **`--branch` (modo Pull Request).** Sem a flag, os arquivos do repo vão em **commits diretos na branch default** — o que falha no meio da execução em repositório com proteção de branch, deixando parte aplicada, e contorna a revisão. Com a flag, todos os arquivos vão em **um commit atômico** numa branch nova e um PR é aberto: se algo falhar antes da criação da branch, **nada** é alterado no repositório. É **idempotente** — rodar duas vezes não gera um segundo commit nem um segundo PR.
217
218
  >
218
- > Duas coisas **não** entram no PR, porque não são versionáveis: as **labels** (metadado do repositório — já valem na base, com ou sem merge) e a **skill** (arquivo em máquina local). O corpo do PR diz isso explicitamente a quem revisa.
219
+ > As **labels** nunca entram no PR: são metadado do repositório, não como versioná-las — já valem na base, com ou sem o merge. O corpo do PR diz isso a quem revisa.
220
+ >
221
+ > A **skill** e o **`.spec-wave.json`** seguem a mesma regra, e ela é **verificada, não presumida**: o comando pergunta à base se aquele arquivo já é versionado. Se for (repos que commitam `.claude/skills/spec-wave/SKILL.md`, `.agents/skills/`, `AGENTS.md`, `.cursor/rules/…`), a atualização entra no PR junto com os workflows; se não for, fica só na máquina local. Passar a versionar (ou deixar de versionar) é decisão do projeto — use `--skill-in-pr` / `--no-skill-in-pr` para forçar.
219
222
  >
220
223
  > ⚠️ O modo PR exige **`pull_requests: write`** além de `contents: write` (ou o escopo `repo` num PAT classic). Sem essa permissão, a branch é criada e o PR falha — a mensagem oferece a URL de `compare` para abrir à mão.
221
224
 
@@ -294,7 +297,7 @@ A saída da crítica é **estruturada e validada por schema**: `severity` só ac
294
297
  | Reprovou depois de | O que corrigir | Como retomar |
295
298
  |--------------------|----------------|--------------|
296
299
  | `generate-plan` | `plan.md` (ou a `spec.md` que o embasa) | corrija → remova `spec-wave:critique-failed` → reaplique **`spec-wave:critique`** (re-critica o arquivo como está). `spec-wave:ready` apenas valida, **não** re-critica; e `spec-wave:plan` **regera** o plano, descartando a correção. |
297
- | `decompose` (rascunho) | **`decomposition.md`** — os achados citam **`Story N`** e **`Task N.M`**, que são os títulos desse arquivo | edite o arquivo e commite → remova `spec-wave:critique-failed` → reaplique `spec-wave:decompose` (ele **critica o arquivo como está**, sem regerar) |
300
+ | `decompose` (rascunho) | **`decomposition.md`** — os achados citam **`Story N`** e **`Task N.M`**, que são os títulos desse arquivo | edite o arquivo **no Pull Request** → remova `spec-wave:critique-failed` → reaplique `spec-wave:decompose` (ele **critica o arquivo como está**, sem regerar) |
298
301
 
299
302
  > ⚠️ No contexto do `decompose`, os achados são sobre as **Stories propostas**, não sobre o `plan.md`. Corrigir o plan não influencia o rascunho já gravado — edite o `decomposition.md` diretamente. Foi exatamente essa confusão que fazia o ciclo não convergir.
300
303
 
@@ -309,7 +312,7 @@ O `decompose` **não cria issues direto**. São dois passos, com um artefato rev
309
312
 
310
313
  ```
311
314
  spec-wave:decompose
312
- ├─ decomposition.md ausente → gera via IA → commita → critica
315
+ ├─ decomposition.md ausente → gera via IA → abre Pull Request → critica
313
316
  └─ decomposition.md presente → critica o arquivo COMO ESTÁ (preserva suas edições)
314
317
  ├─ grave → +critique-failed, comentário citando Story N / Task N.M, exit 1
315
318
  └─ limpo → +decompose-ready, comentário "revise e aplique"
@@ -341,7 +344,7 @@ Corpo técnico.
341
344
  - a **posição** manda, não o número escrito — inserir uma Story no meio sem renumerar funciona;
342
345
  - `**Depende de:**` aceita **irmãs** (`Story 1, Story 3`, 1-based, só para trás — apontar para si mesma ou para frente é **erro**, não filtro silencioso) e **issues de outras Features** (`#412`, que precisam JÁ existir); as duas formas convivem na mesma linha (`Story 1, #412`), e `—` significa nenhuma;
343
346
  - o corpo aceita markdown livre (`## Backend`, cercas de código) — só `## Story N` e `### Task N.M` são estrutura;
344
- - **para gerar outro rascunho do zero:** apague o arquivo e reaplique `spec-wave:decompose`.
347
+ - **para gerar outro rascunho do zero:** feche o Pull Request e apague a branch `spec-wave/<n>-decompose` (ou apague o arquivo, se já mergeado) e reaplique `spec-wave:decompose`.
345
348
 
346
349
  ### Guard de idempotência do decompose (`spec-wave:decomposed`)
347
350
 
@@ -459,8 +462,8 @@ Traz tudo para a versão atual da CLI, atualizando **só o que mudou**: a skill
459
462
  - Escopos podem ser limitados com `--skip-skill`, `--skip-config`, `--skip-repo`.
460
463
  - **Com `--branch`:** os arquivos do repo vão em **um único commit** numa branch nova e um PR é aberto — nada é escrito na branch default. Passe o link do PR ao usuário e lembre que o merge é dele. Exige `pull_requests: write` no token.
461
464
  - **Sem `--branch`:** cada arquivo é um commit direto na branch default. Em repositório com **proteção de branch** isso falha no meio e deixa parte aplicada — nesses casos use `--branch`.
462
- - **Nos dois modos**, as **labels** são aplicadas direto na base (metadado do repositório, não versionável) e a **skill** é gravada em máquina local. Nenhuma das duas entra no PR.
463
- - **`.spec-wave.json`:** com `--branch`, ele entra no PR se o repositório **já o versiona**; se não versiona, segue apenas local e o usuário precisa commitá-lo (ou use `--config-in-pr` para passar a versioná-lo). Sem `--branch`, é sempre só local.
465
+ - **Nos dois modos**, as **labels** são aplicadas direto na base (metadado do repositório, não versionável) e nunca entram no PR.
466
+ - **`.spec-wave.json` e skill:** com `--branch`, cada um entra no PR se o repositório **já o versiona** (o comando consulta a base, arquivo a arquivo); se não versiona, segue apenas local e o usuário precisa commitá-lo ou use `--config-in-pr` / `--skill-in-pr` para passar a versioná-lo. Sem `--branch`, os dois são sempre só locais. A skill é gravada em disco de qualquer forma, para o agente já pegar a versão nova.
464
467
  4. Se a skill foi atualizada, oriente recarregar/reiniciar o agente para pegar a nova versão.
465
468
 
466
469
  ---
@@ -649,10 +652,10 @@ Para qualquer outro tipo (Spike, Bug, Story, Task, …) o Action **recusa** e co
649
652
  ```bash
650
653
  gh issue edit <número> --add-label "spec-wave:decompose"
651
654
  ```
652
- Informe: "Rascunho iniciado — vai commitar `decomposition.md` e passar pela crítica. **Nenhuma issue é criada nesta etapa.**"
655
+ Informe: "Rascunho iniciado — vai abrir um Pull Request com o `decomposition.md` e passar pela crítica. **Nenhuma issue é criada nesta etapa.**"
653
656
  3. Quando o Action terminar, leia o comentário na issue:
654
657
  - **`spec-wave:decompose-ready`** → o rascunho passou pela crítica. **Leia o `decomposition.md`** e mostre ao usuário o que será criado (Stories, Tasks, dependências). Ofereça editar o arquivo antes de aplicar.
655
- - **`spec-wave:critique-failed`** → o Action **falhou (exit 1)** e nada foi criado. Os achados citam `Story N` / `Task N.M` do `decomposition.md`. **Corrija esse arquivo** (não o `plan.md`), commite e reaplique `spec-wave:decompose` — o arquivo é criticado como está, sem ser regerado.
658
+ - **`spec-wave:critique-failed`** → o Action **falhou (exit 1)** e nada foi criado. Os achados citam `Story N` / `Task N.M` do `decomposition.md`. **Corrija esse arquivo** (não o `plan.md`) no Pull Request e reaplique `spec-wave:decompose` — o arquivo é criticado como está, sem ser regerado.
656
659
  - **`spec-wave:needs-human`** → a crítica esgotou as tentativas. Pare e envolva o usuário: as duas labels precisam sair à mão.
657
660
  4. **Etapa 2 — aplicar o rascunho aprovado** (só depois da revisão):
658
661
  ```bash
@@ -728,7 +731,7 @@ Gera o **`bug.md`** de um defeito: `docs/bugs/<slug>/bug.md`, com reprodução,
728
731
 
729
732
  1. Confirme que a issue é do tipo **Bug** (para outros tipos o Action pula, remove a label e comenta).
730
733
  2. `gh issue edit <n> --add-label "spec-wave:bug"`
731
- 3. Avise: o Action `generate-bug.yml` gera e commita o arquivo.
734
+ 3. Avise: o Action `generate-bug.yml` gera o arquivo e abre um Pull Request com ele.
732
735
  4. Ofereça revisar **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.
733
736
  5. Validar: `spec-wave:ready` → confere as seis seções e aplica `spec-wave:bug-approved`.
734
737
 
@@ -18,7 +18,15 @@ jobs:
18
18
  # Modo de execução: `spec-wave mode local` cria a variável de repositório
19
19
  # SPEC_WAVE_EXECUTION=local e este job passa a ser PULADO — run aparece como
20
20
  # skipped e job que não roda não é faturado. `mode actions` remove a variável.
21
- if: vars.SPEC_WAVE_EXECUTION != 'local'
21
+ # PR de DOCUMENTO não é PR de implementação. O fluxo publica spec.md,
22
+ # plan.md, bug.md e decomposition.md em branches `spec-wave/*`, e deixar este
23
+ # workflow rodar em cima delas move o board por um PR que não implementa
24
+ # nada. Nos Actions um PR aberto pelo GITHUB_TOKEN não dispara workflow, mas
25
+ # um aberto no modo local (ou via GH_PR_TOKEN) dispara.
26
+ #
27
+ # A guarda cobre também `spec-wave/update-v*`, do `update --branch` — que
28
+ # tampouco implementa uma Story.
29
+ if: vars.SPEC_WAVE_EXECUTION != 'local' && !startsWith(github.event.pull_request.head.ref, 'spec-wave/')
22
30
  runs-on: ubuntu-latest
23
31
  permissions:
24
32
  issues: read
@@ -44,7 +52,10 @@ jobs:
44
52
  move:
45
53
  needs: resolve
46
54
  # PR sem vínculo explícito não resolve Feature nenhuma — e não move nada.
47
- if: vars.SPEC_WAVE_EXECUTION != 'local' && needs.resolve.outputs.feature != ''
55
+ if: >
56
+ vars.SPEC_WAVE_EXECUTION != 'local' &&
57
+ !startsWith(github.event.pull_request.head.ref, 'spec-wave/') &&
58
+ needs.resolve.outputs.feature != ''
48
59
  runs-on: ubuntu-latest
49
60
  # MESMO namespace do decompose.yml: um `decompose-apply` em curso na Feature
50
61
  # segura este job na fila em vez de disputar a subárvore com ele. Foi essa
@@ -35,7 +35,7 @@ jobs:
35
35
  permissions:
36
36
  issues: write
37
37
  # read: a crítica LÊ o plan.md do checkout e não escreve arquivo nenhum —
38
- # ao contrário do generate-plan, que commita o documento gerado.
38
+ # ao contrário do generate-plan, que publica o documento gerado.
39
39
  contents: read
40
40
 
41
41
  steps:
@@ -16,7 +16,7 @@ on:
16
16
  # proteção.
17
17
  #
18
18
  # generate-spec, generate-plan e generate-bug usam o MESMO namespace por outro
19
- # motivo: os quatro commitam e empurram na branch default, e este aqui ainda lê
19
+ # motivo: os quatro publicam documentos em branch própria + Pull Request, e este aqui ainda lê
20
20
  # o spec.md/plan.md do checkout — que uma geração concorrente estaria trocando
21
21
  # debaixo dele.
22
22
  concurrency:
@@ -56,8 +56,18 @@ jobs:
56
56
  runs-on: ubuntu-latest
57
57
  permissions:
58
58
  issues: write
59
- # A etapa de rascunho commita docs/**/decomposition.md no branch default.
60
59
  contents: write
60
+ # `contents: write` continua necessário: o commit vai por Git Data API
61
+ # (createTree/createCommit/createRef), que é autorizada por ele. O que
62
+ # mudou foi o DESTINO — branch própria do documento, nunca a default.
63
+ #
64
+ # `pull-requests: write` é a permissão NOVA deste fluxo. Sem ela o commit
65
+ # é criado e o PR não, e o documento fica numa branch que ninguém vê.
66
+ #
67
+ # Atenção: o GITHUB_TOKEN só abre PR se "Allow GitHub Actions to create and
68
+ # approve pull requests" estiver ligado (Settings → Actions → General) —
69
+ # desligado por padrão em muitas organizações. `GH_PR_TOKEN` é a saída.
70
+ pull-requests: write
61
71
 
62
72
  steps:
63
73
  - uses: actions/checkout@v4
@@ -78,6 +88,7 @@ jobs:
78
88
  ${{ github.event.label.name == 'spec-wave:decompose-apply' && '--apply' || '' }}
79
89
  env:
80
90
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
91
+ GH_PR_TOKEN: ${{ secrets.GH_PR_TOKEN }}
81
92
  PROJECT_TOKEN: ${{ secrets.GH_PROJECT_TOKEN }}
82
93
  ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
83
94
  CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}