@spec-wave/cli 0.24.0 → 0.25.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 +84 -0
- package/bin/spec-wave.mjs +35 -2
- package/package.json +1 -1
- package/src/api/github-rest.mjs +63 -1
- package/src/commands/decompose.mjs +3 -10
- package/src/commands/doctor.mjs +32 -0
- package/src/commands/generate-bug.mjs +8 -14
- package/src/commands/generate-plan.mjs +2 -1
- package/src/commands/generate-spec.mjs +2 -1
- package/src/commands/mode.mjs +169 -0
- package/src/commands/run.mjs +396 -0
- package/src/commands/validate.mjs +22 -6
- package/src/config.mjs +4 -1
- package/src/lib/config-file.mjs +62 -0
- package/src/lib/doc-paths.mjs +51 -0
- package/src/lib/execution-mode.mjs +110 -0
- package/src/lib/next-step.mjs +356 -0
- package/src/lib/pr-step.mjs +102 -0
- package/src/lib/repo-links.mjs +84 -0
- package/src/plugin/.claude-plugin/plugin.json +1 -1
- package/src/plugin/skills/doctor/SKILL.md +1 -0
- package/src/plugin/skills/run/SKILL.md +76 -0
- package/src/plugin/skills/spec/SKILL.md +1 -1
- package/src/templates/skill/SKILL.md +24 -1
- package/src/templates/workflows/code-review.yml +5 -1
- package/src/templates/workflows/critique.yml +4 -0
- package/src/templates/workflows/decompose.yml +4 -0
- package/src/templates/workflows/generate-bug.yml +4 -0
- package/src/templates/workflows/generate-plan.yml +4 -0
- package/src/templates/workflows/generate-spec.yml +4 -0
- package/src/templates/workflows/qa.yml +6 -1
- package/src/templates/workflows/validate.yml +4 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-wave-run
|
|
3
|
+
description: "Use para conduzir o fluxo do spec-wave LOCALMENTE, sem gastar minutos de GitHub Actions: `spec-wave run <issue>` executa nesta máquina o passo que a label dispararia (spec, plan, crítica, validate, decompose, apply) e `spec-wave mode local|actions` alterna entre os dois mundos. Gatilhos: 'rodar o spec-wave local', 'qual o próximo passo da issue 12', 'sem gastar Actions', 'desligar os workflows', 'trocar para execução local'."
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Bash(npx @spec-wave/cli@latest *)
|
|
6
|
+
- Bash(gh issue view *)
|
|
7
|
+
- Read
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# spec-wave run — o fluxo inteiro na sua máquina
|
|
11
|
+
|
|
12
|
+
Os workflows do spec-wave nunca fizeram o trabalho: eles instalam a CLI e chamam um comando. O `run` é o mesmo comando, disparado **daqui** — e o `mode` desarma os workflows para o gatilho não acontecer duas vezes.
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npx @spec-wave/cli@latest mode local # desarma os workflows (0 minutos de Actions)
|
|
16
|
+
npx @spec-wave/cli@latest run <issue> # executa o próximo passo pendente
|
|
17
|
+
npx @spec-wave/cli@latest mode actions # volta tudo para o CI
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Contexto:** leia `.spec-wave.json` (Read). Ausente → skill **setup**. O campo `execution.mode` diz em qual mundo o repositório está.
|
|
21
|
+
|
|
22
|
+
## Como decidir o que fazer
|
|
23
|
+
|
|
24
|
+
1. **Sempre comece pelo `--dry-run`.** Ele consulta a issue, olha os documentos e explica o passo sem executar nada nem chamar IA:
|
|
25
|
+
```bash
|
|
26
|
+
npx @spec-wave/cli@latest run <issue> --dry-run
|
|
27
|
+
```
|
|
28
|
+
2. Mostre ao usuário o passo, o motivo e o comando que rodaria. **Só então** execute sem a flag.
|
|
29
|
+
3. `--json` devolve a mesma decisão em JSON, quando você precisar ramificar programaticamente.
|
|
30
|
+
|
|
31
|
+
## O que o `run` decide sozinho
|
|
32
|
+
|
|
33
|
+
| Estado da issue | Passo |
|
|
34
|
+
|---|---|
|
|
35
|
+
| Feature sem `spec.md` | `generate-spec` |
|
|
36
|
+
| spec pronta, sem `plan.md` | `generate-plan` (a crítica roda embutida) |
|
|
37
|
+
| spec+plan sem `spec-wave:plan-approved` | `validate` |
|
|
38
|
+
| validada, sem `decomposition.md` | `decompose` (rascunho) |
|
|
39
|
+
| `spec-wave:decompose-ready` | `decompose-apply` — **exige `--apply`** |
|
|
40
|
+
| `spec-wave:decomposed` | nada: sugere a skill **implement** |
|
|
41
|
+
| Bug sem `bug.md` → com `bug.md` → validado | `generate-bug` → `validate` → `triage` (humano) |
|
|
42
|
+
| RFC | `decompose` → `decompose-apply` |
|
|
43
|
+
|
|
44
|
+
Para PRs: `run --pr <n>` roda `code-review` e, se houver review aprovada, também `qa` — a mesma coisa que os workflows fariam nos eventos do PR.
|
|
45
|
+
|
|
46
|
+
## Portões (quando ele se recusa a rodar)
|
|
47
|
+
|
|
48
|
+
O comando **explica e para**, saindo com código 2. Não force sem entender:
|
|
49
|
+
|
|
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
|
+
- **`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
|
+
- **`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
|
+
- **`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
|
+
- **`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
|
+
|
|
56
|
+
## Regras que o `run` respeita — e você também
|
|
57
|
+
|
|
58
|
+
- **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.
|
|
60
|
+
- A **Regra fundamental** continua valendo: nunca escreva `spec.md`/`plan.md`/`decomposition.md` à mão. Quem gera é a CLI, aqui como no Action.
|
|
61
|
+
|
|
62
|
+
## `mode` — o interruptor
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npx @spec-wave/cli@latest mode # estado atual
|
|
66
|
+
npx @spec-wave/cli@latest mode local # config + variável SPEC_WAVE_EXECUTION
|
|
67
|
+
npx @spec-wave/cli@latest mode actions # remove a variável
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Ele escreve os **dois** lados: o `.spec-wave.json` (que a CLI e as skills leem) e a variável de repositório que o `if:` de cada job avalia. Com ela setada, o run do workflow aparece como *skipped* — job que não roda não é faturado.
|
|
71
|
+
|
|
72
|
+
- A variável exige **admin** no repositório. Sem permissão o comando grava o config, avisa e aponta Settings → Secrets and variables → Actions → Variables.
|
|
73
|
+
- **Commite o `.spec-wave.json`**: quem clona o repo (inclusive o dev-agent) lê a versão versionada.
|
|
74
|
+
- Se os workflows instalados forem anteriores à guarda, o comando avisa e o conserto é a skill **update**.
|
|
75
|
+
|
|
76
|
+
O `doctor` tem um check dedicado: config e variável em desacordo é problema, não detalhe — é o usuário achando que desligou o CI e continuando a pagar por ele.
|
|
@@ -20,7 +20,7 @@ allowed-tools:
|
|
|
20
20
|
|
|
21
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).
|
|
22
22
|
|
|
23
|
-
> Local exige a
|
|
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
|
|
|
25
25
|
**Contexto:** leia `.spec-wave.json` (Read). Ausente → skill **setup**.
|
|
26
26
|
|
|
@@ -61,9 +61,32 @@ Exemplo de `.spec-wave.json`:
|
|
|
61
61
|
|
|
62
62
|
---
|
|
63
63
|
|
|
64
|
+
## Modo de execução (Actions × local)
|
|
65
|
+
|
|
66
|
+
Leia `execution.mode` no `.spec-wave.json` **antes** de acionar qualquer passo do fluxo:
|
|
67
|
+
|
|
68
|
+
| `execution.mode` | Como acionar um passo | Custo |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| `actions` (default) | aplicar a label de gatilho (`spec-wave:spec`, `:plan`, …) | minutos de GitHub Actions |
|
|
71
|
+
| `local` | `npx @spec-wave/cli@latest run <issue>` | nenhum — roda nesta máquina |
|
|
72
|
+
|
|
73
|
+
**No modo `local`, NÃO aplique label de gatilho.** Os workflows estão desarmados por uma variável de repositório, mas a label continua sendo o contrato do outro modo — aplicá-la só polui a issue (e, se alguém religar o CI, dispara tarde).
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
npx @spec-wave/cli@latest mode # estado atual dos dois lados do interruptor
|
|
77
|
+
npx @spec-wave/cli@latest mode local # desarma os workflows
|
|
78
|
+
npx @spec-wave/cli@latest run <issue> --dry-run # explica o próximo passo sem executar
|
|
79
|
+
npx @spec-wave/cli@latest run <issue> # executa
|
|
80
|
+
npx @spec-wave/cli@latest run --pr <n> # code-review (+ qa, se houver aprovação)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
O `run` decide o passo pelo estado da issue (documentos existentes + labels), respeita os portões humanos (`needs-human`, `critique-failed`), recusa rodar com uma label de gatilho pendente e **exige `--apply`** para o `decompose-apply`, que cria issues. Sempre mostre o `--dry-run` ao usuário antes de executar.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
64
87
|
## Regra fundamental
|
|
65
88
|
|
|
66
|
-
**Nunca gere `spec.md` ou `plan.md` diretamente.**
|
|
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.
|
|
67
90
|
|
|
68
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.
|
|
69
92
|
|
|
@@ -15,6 +15,10 @@ jobs:
|
|
|
15
15
|
# de concurrency ao job seguinte: `concurrency` de workflow é avaliada no
|
|
16
16
|
# trigger, quando ainda não se sabe qual issue o PR implementa.
|
|
17
17
|
resolve:
|
|
18
|
+
# Modo de execução: `spec-wave mode local` cria a variável de repositório
|
|
19
|
+
# SPEC_WAVE_EXECUTION=local e este job passa a ser PULADO — run aparece como
|
|
20
|
+
# skipped e job que não roda não é faturado. `mode actions` remove a variável.
|
|
21
|
+
if: vars.SPEC_WAVE_EXECUTION != 'local'
|
|
18
22
|
runs-on: ubuntu-latest
|
|
19
23
|
permissions:
|
|
20
24
|
issues: read
|
|
@@ -40,7 +44,7 @@ jobs:
|
|
|
40
44
|
move:
|
|
41
45
|
needs: resolve
|
|
42
46
|
# PR sem vínculo explícito não resolve Feature nenhuma — e não move nada.
|
|
43
|
-
if: needs.resolve.outputs.feature != ''
|
|
47
|
+
if: vars.SPEC_WAVE_EXECUTION != 'local' && needs.resolve.outputs.feature != ''
|
|
44
48
|
runs-on: ubuntu-latest
|
|
45
49
|
# MESMO namespace do decompose.yml: um `decompose-apply` em curso na Feature
|
|
46
50
|
# segura este job na fila em vez de disputar a subárvore com ele. Foi essa
|
|
@@ -24,7 +24,11 @@ concurrency:
|
|
|
24
24
|
|
|
25
25
|
jobs:
|
|
26
26
|
critique:
|
|
27
|
+
# Modo de execução: `spec-wave mode local` cria a variável de repositório
|
|
28
|
+
# SPEC_WAVE_EXECUTION=local e este job passa a ser PULADO — run aparece como
|
|
29
|
+
# skipped e job que não roda não é faturado. `mode actions` remove a variável.
|
|
27
30
|
if: >
|
|
31
|
+
vars.SPEC_WAVE_EXECUTION != 'local' &&
|
|
28
32
|
github.event.label.name == 'spec-wave:critique' &&
|
|
29
33
|
contains(github.event.issue.title, '[FEATURE]')
|
|
30
34
|
runs-on: ubuntu-latest
|
|
@@ -44,7 +44,11 @@ jobs:
|
|
|
44
44
|
# • spec-wave:decompose-apply → cria as Stories/Tasks a partir do rascunho
|
|
45
45
|
# O `[RFC]` no título também dispara: o caminho RFC → Tasks existe na CLI
|
|
46
46
|
# desde sempre, mas era inalcançável porque o filtro exigia `[FEATURE]`.
|
|
47
|
+
# Modo de execução: `spec-wave mode local` cria a variável de repositório
|
|
48
|
+
# SPEC_WAVE_EXECUTION=local e este job passa a ser PULADO — run aparece como
|
|
49
|
+
# skipped e job que não roda não é faturado. `mode actions` remove a variável.
|
|
47
50
|
if: >
|
|
51
|
+
vars.SPEC_WAVE_EXECUTION != 'local' &&
|
|
48
52
|
(github.event.label.name == 'spec-wave:decompose' ||
|
|
49
53
|
github.event.label.name == 'spec-wave:decompose-apply') &&
|
|
50
54
|
(contains(github.event.issue.title, '[FEATURE]') ||
|
|
@@ -31,7 +31,11 @@ concurrency:
|
|
|
31
31
|
|
|
32
32
|
jobs:
|
|
33
33
|
generate-bug:
|
|
34
|
+
# Modo de execução: `spec-wave mode local` cria a variável de repositório
|
|
35
|
+
# SPEC_WAVE_EXECUTION=local e este job passa a ser PULADO — run aparece como
|
|
36
|
+
# skipped e job que não roda não é faturado. `mode actions` remove a variável.
|
|
34
37
|
if: >
|
|
38
|
+
vars.SPEC_WAVE_EXECUTION != 'local' &&
|
|
35
39
|
github.event.label.name == 'spec-wave:bug' &&
|
|
36
40
|
contains(github.event.issue.title, '[BUG]')
|
|
37
41
|
runs-on: ubuntu-latest
|
|
@@ -39,7 +39,11 @@ concurrency:
|
|
|
39
39
|
|
|
40
40
|
jobs:
|
|
41
41
|
generate-plan:
|
|
42
|
+
# Modo de execução: `spec-wave mode local` cria a variável de repositório
|
|
43
|
+
# SPEC_WAVE_EXECUTION=local e este job passa a ser PULADO — run aparece como
|
|
44
|
+
# skipped e job que não roda não é faturado. `mode actions` remove a variável.
|
|
42
45
|
if: >
|
|
46
|
+
vars.SPEC_WAVE_EXECUTION != 'local' &&
|
|
43
47
|
github.event.label.name == 'spec-wave:plan' &&
|
|
44
48
|
contains(github.event.issue.title, '[FEATURE]')
|
|
45
49
|
runs-on: ubuntu-latest
|
|
@@ -39,7 +39,11 @@ concurrency:
|
|
|
39
39
|
|
|
40
40
|
jobs:
|
|
41
41
|
generate-spec:
|
|
42
|
+
# Modo de execução: `spec-wave mode local` cria a variável de repositório
|
|
43
|
+
# SPEC_WAVE_EXECUTION=local e este job passa a ser PULADO — run aparece como
|
|
44
|
+
# skipped e job que não roda não é faturado. `mode actions` remove a variável.
|
|
42
45
|
if: >
|
|
46
|
+
vars.SPEC_WAVE_EXECUTION != 'local' &&
|
|
43
47
|
github.event.label.name == 'spec-wave:spec' &&
|
|
44
48
|
contains(github.event.issue.title, '[FEATURE]')
|
|
45
49
|
runs-on: ubuntu-latest
|
|
@@ -10,7 +10,12 @@ concurrency:
|
|
|
10
10
|
|
|
11
11
|
jobs:
|
|
12
12
|
qa:
|
|
13
|
-
|
|
13
|
+
# Modo de execução: `spec-wave mode local` cria a variável de repositório
|
|
14
|
+
# SPEC_WAVE_EXECUTION=local e este job passa a ser PULADO — run aparece como
|
|
15
|
+
# skipped e job que não roda não é faturado. `mode actions` remove a variável.
|
|
16
|
+
if: >
|
|
17
|
+
vars.SPEC_WAVE_EXECUTION != 'local' &&
|
|
18
|
+
github.event.review.state == 'approved'
|
|
14
19
|
runs-on: ubuntu-latest
|
|
15
20
|
permissions:
|
|
16
21
|
issues: write
|
|
@@ -24,7 +24,11 @@ concurrency:
|
|
|
24
24
|
|
|
25
25
|
jobs:
|
|
26
26
|
validate:
|
|
27
|
+
# Modo de execução: `spec-wave mode local` cria a variável de repositório
|
|
28
|
+
# SPEC_WAVE_EXECUTION=local e este job passa a ser PULADO — run aparece como
|
|
29
|
+
# skipped e job que não roda não é faturado. `mode actions` remove a variável.
|
|
27
30
|
if: >
|
|
31
|
+
vars.SPEC_WAVE_EXECUTION != 'local' &&
|
|
28
32
|
github.event.label.name == 'spec-wave:ready' &&
|
|
29
33
|
(contains(github.event.issue.title, '[FEATURE]') ||
|
|
30
34
|
contains(github.event.issue.title, '[BUG]'))
|