@spec-wave/cli 0.8.1 → 0.10.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 CHANGED
@@ -26,7 +26,6 @@ O resultado é um board Kanban no GitHub Projects v2 que avança automaticamente
26
26
  → 📋 Spec ← label spec-wave:spec → Action gera spec.md
27
27
  → 📋 Plan ← label spec-wave:plan → Action gera plan.md
28
28
  → ✅ Ready ← label spec-wave:ready → Action valida ambos
29
- → 📋 Backlog Técnico
30
29
  → 🚧 Desenvolvimento ← comando local: spec-wave implement <n>
31
30
  → 👀 Code Review ← PR aberto → Action move automaticamente
32
31
  → 🧪 QA ← PR aprovado → Action move automaticamente
@@ -117,7 +116,7 @@ Arquivo em `.github/config/tech_context.yml` que descreve a stack tecnológica d
117
116
  Não é necessário instalar globalmente — use `npx`:
118
117
 
119
118
  ```bash
120
- npx @spec-wave/cli --help
119
+ npx @spec-wave/cli@latest --help
121
120
  ```
122
121
 
123
122
  Para instalar globalmente:
@@ -137,7 +136,7 @@ A skill permite usar o fluxo diretamente no seu agente via `/spec-wave`.
137
136
 
138
137
  ```bash
139
138
  # Autodetecta o agente em uso e instala no local/formato correto
140
- npx @spec-wave/cli install-skill
139
+ npx @spec-wave/cli@latest install-skill
141
140
  ```
142
141
 
143
142
  O comando suporta Claude Code, Cursor, opencode, Cline, Kilo Code, Antigravity e o
@@ -184,7 +183,7 @@ gh auth status
184
183
  gh auth refresh --scopes project,repo,workflow
185
184
 
186
185
  # Configurar spec-wave (cria Project, labels e workflows)
187
- npx @spec-wave/cli init --repo acme/loja --project-title "Loja — Spec Wave"
186
+ npx @spec-wave/cli@latest init --repo acme/loja --project-title "Loja — Spec Wave"
188
187
  ```
189
188
 
190
189
  O `init` cria:
@@ -201,7 +200,7 @@ Adicionar o secret de IA no GitHub: **Settings → Secrets → Actions → `ANTH
201
200
 
202
201
  ```bash
203
202
  # Criar Epic
204
- npx @spec-wave/cli issue \
203
+ npx @spec-wave/cli@latest issue \
205
204
  --type epic \
206
205
  --title "Checkout e Pagamentos" \
207
206
  --priority P1 \
@@ -209,7 +208,7 @@ npx @spec-wave/cli issue \
209
208
  # → Issue #5 criada: [EPIC] Checkout e Pagamentos
210
209
 
211
210
  # Criar Feature como sub-issue do Epic
212
- npx @spec-wave/cli feature \
211
+ npx @spec-wave/cli@latest feature \
213
212
  --title "Checkout com PIX" \
214
213
  --parent 5 \
215
214
  --priority P1 \
@@ -304,7 +303,7 @@ O Action `decompose.yml` usa IA para criar sub-issues da Feature #12:
304
303
  #19 [TASK] Notificação por e-mail ao confirmar
305
304
  ```
306
305
 
307
- Todas as Stories e Tasks são adicionadas ao board em **📋 Backlog Técnico** com Status `Todo`.
306
+ Todas as Stories e Tasks são adicionadas ao board em **✅ Ready** com Status `Todo`.
308
307
 
309
308
  ---
310
309
 
@@ -315,8 +314,8 @@ Todas as Stories e Tasks são adicionadas ao board em **📋 Backlog Técnico**
315
314
  /spec-wave implement 13
316
315
 
317
316
  # Ou direto:
318
- npx @spec-wave/cli implement 13 --dry-run # ver contexto antes
319
- npx @spec-wave/cli implement 13 # executar
317
+ npx @spec-wave/cli@latest implement 13 --dry-run # ver contexto antes
318
+ npx @spec-wave/cli@latest implement 13 # executar
320
319
  ```
321
320
 
322
321
  O comando monta um arquivo de contexto com spec.md, plan.md e todas as Tasks da Story, e aciona o spec-kit configurado.
@@ -380,7 +379,7 @@ Isso atualiza apenas os arquivos de workflow sem recriar o Project ou as labels.
380
379
 
381
380
  Configurar no `init`:
382
381
  ```bash
383
- npx @spec-wave/cli init --repo owner/repo --provider openrouter --model anthropic/claude-3.7-sonnet
382
+ npx @spec-wave/cli@latest init --repo owner/repo --provider openrouter --model anthropic/claude-3.7-sonnet
384
383
  ```
385
384
 
386
385
  ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spec-wave/cli",
3
- "version": "0.8.1",
3
+ "version": "0.10.0",
4
4
  "description": "Setup spec-driven GitHub workflow with Projects v2, labels, issue templates, and AI-powered Actions",
5
5
  "type": "module",
6
6
  "bin": {
@@ -28,4 +28,4 @@
28
28
  "commander": "^13.1.0",
29
29
  "js-yaml": "^4.1.0"
30
30
  }
31
- }
31
+ }
@@ -265,7 +265,7 @@ async function decomposeFeature(ctx) {
265
265
  token, owner, repo, parseInt(issueNumber, 10),
266
266
  `🔀 **Decomposição concluída!**\n\n` +
267
267
  `Foram criados ${decomposition.stories.length} stories e suas tasks:\n\n${list}\n\n` +
268
- `Mova o card para **📋 Backlog Técnico** para iniciar o desenvolvimento.` +
268
+ `Tudo posicionado em **✅ Ready**. Inicie o desenvolvimento com \`npx @spec-wave/cli@latest implement ${issueNumber}\` (Stories em ordem de dependência).` +
269
269
  formatItemsLintWarning(generatedTexts)
270
270
  );
271
271
  console.log(`Decomposição concluída: ${decomposition.stories.length} stories criadas.`);
@@ -321,7 +321,7 @@ async function decomposeRFC(ctx) {
321
321
  token, owner, repo, parseInt(issueNumber, 10),
322
322
  `🔀 **Decomposição do RFC concluída!**\n\n` +
323
323
  `Foram criadas ${created.length} tasks:\n\n${list}\n\n` +
324
- `Mova o card para **📋 Backlog Técnico** para iniciar o desenvolvimento.` +
324
+ `Tudo posicionado em **✅ Ready**. Inicie o desenvolvimento com \`npx @spec-wave/cli@latest implement <task>\`.` +
325
325
  formatItemsLintWarning(generatedTexts)
326
326
  );
327
327
  console.log(`Decomposição concluída: ${created.length} tasks criadas.`);
@@ -202,7 +202,7 @@ async function checkConfig(ctx) {
202
202
  return {
203
203
  name,
204
204
  status: 'fail',
205
- detail: `${CONFIG_FILE} não encontrado em ${ctx.cwd}. Rode \`npx @spec-wave/cli init\`.`,
205
+ detail: `${CONFIG_FILE} não encontrado em ${ctx.cwd}. Rode \`npx @spec-wave/cli@latest init\`.`,
206
206
  };
207
207
  }
208
208
  if (ctx.cfgError) {
@@ -219,7 +219,7 @@ async function checkConfig(ctx) {
219
219
  status: 'warn',
220
220
  detail:
221
221
  notes.join('\n') +
222
- `\nproject.fields sem ${missingFields.map((f) => `"${f}"`).join(' e ')} — rode \`npx @spec-wave/cli refresh\`.`,
222
+ `\nproject.fields sem ${missingFields.map((f) => `"${f}"`).join(' e ')} — rode \`npx @spec-wave/cli@latest refresh\`.`,
223
223
  };
224
224
  }
225
225
 
@@ -240,7 +240,7 @@ async function checkConfig(ctx) {
240
240
  status: 'warn',
241
241
  detail:
242
242
  notes.join('\n') +
243
- `\nOpções de Etapa do config ausentes no project real: ${diverged.join(', ')} — rode \`npx @spec-wave/cli refresh\`.`,
243
+ `\nOpções de Etapa do config ausentes no project real: ${diverged.join(', ')} — rode \`npx @spec-wave/cli@latest refresh\`.`,
244
244
  };
245
245
  }
246
246
  notes.push(`Project "${snapshot.title}" verificado — campos Etapa/Status em sincronia.`);
@@ -371,7 +371,7 @@ async function checkWorkflows(ctx) {
371
371
  return {
372
372
  name,
373
373
  status: 'warn',
374
- detail: '.github/workflows/ não encontrado — rode `npx @spec-wave/cli init` (ou `update`) para instalar os workflows.',
374
+ detail: '.github/workflows/ não encontrado — rode `npx @spec-wave/cli@latest init` (ou `update`) para instalar os workflows.',
375
375
  };
376
376
  }
377
377
  const present = readdirSync(dir);
@@ -380,7 +380,7 @@ async function checkWorkflows(ctx) {
380
380
  return {
381
381
  name,
382
382
  status: 'warn',
383
- detail: `Workflows faltando em .github/workflows/: ${missing.join(', ')} — rode \`npx @spec-wave/cli update\`.`,
383
+ detail: `Workflows faltando em .github/workflows/: ${missing.join(', ')} — rode \`npx @spec-wave/cli@latest update\`.`,
384
384
  };
385
385
  }
386
386
  return { name, status: 'ok', detail: `Os ${WORKFLOW_FILES.length} workflows do spec-wave estão presentes.` };
@@ -14,6 +14,7 @@ import { detectIssueType } from '../lib/issue-type.mjs';
14
14
  import { slugify } from '../lib/slugify.mjs';
15
15
  import { parseDependencies, orderStories, formatDependencyLine } from '../lib/dependencies.mjs';
16
16
  import { loadProjectConfig, resolveField } from '../lib/board.mjs';
17
+ import { planBoardMoves, applyBoardMoves } from '../lib/implement-board.mjs';
17
18
  import { extractPathsFromPlan, buildCodeDigest } from '../lib/code-digest.mjs';
18
19
 
19
20
  // Diretório onde montamos o arquivo de contexto entregue ao spec-kit.
@@ -160,6 +161,13 @@ function buildContext({
160
161
  lines.push('');
161
162
  lines.push(boardFieldsExplainer());
162
163
  lines.push('');
164
+ lines.push(
165
+ '> **O board é atualizado automaticamente pelo spec-wave**: no início, ' +
166
+ 'Feature/Story vão para Desenvolvimento (In Progress); na conclusão, ' +
167
+ 'Tasks vão para Done e a Story para Code Review. As instruções de board ' +
168
+ 'abaixo descrevem o modelo — você NÃO precisa mover cards manualmente.'
169
+ );
170
+ lines.push('');
163
171
  if (type === 'Story') {
164
172
  lines.push(
165
173
  `Nesta fase, a Story #${issue.number} e suas Tasks estão na Etapa **${STAGE_DEVELOPMENT}**. ` +
@@ -365,6 +373,11 @@ async function implementFeature({ token, owner, repo, config, feature, featureDi
365
373
  }
366
374
  p.log.info(`Feature com ${stories.length} story(ies): ${stories.map(s => `#${s.number}`).join(', ')}`);
367
375
 
376
+ // F1-board. Feature → Desenvolvimento (In Progress) já no início.
377
+ await applyBoardMoves({ token, moves: planBoardMoves('start', {
378
+ feature: { nodeId: feature.node_id, number: feature.number },
379
+ }) });
380
+
368
381
  // F2. Dependências de cada Story: linha "Depende de:" do body ∪ blocked_by nativo.
369
382
  const enriched = await Promise.all(stories.map(async (s) => {
370
383
  let body = s.body;
@@ -425,7 +438,7 @@ async function implementFeature({ token, owner, repo, config, feature, featureDi
425
438
  const storySubs = await listSubIssues(token, s.nodeId).catch(() => []);
426
439
  s.tasks = storySubs
427
440
  .filter(t => detectIssueType({ title: t.title, labels: t.labels }) === 'Task')
428
- .map(t => ({ number: t.number, title: t.title, body: t.body || '' }));
441
+ .map(t => ({ number: t.number, title: t.title, body: t.body || '', nodeId: t.nodeId }));
429
442
  if (s.tasks.length === 0) noTasks.push(s.number);
430
443
  }
431
444
  if (noTasks.length > 0) {
@@ -509,7 +522,7 @@ async function implementFeature({ token, owner, repo, config, feature, featureDi
509
522
  codeDigest,
510
523
  blockedByWarnings,
511
524
  });
512
- writeContextAndRunSpecKit({
525
+ await writeContextAndRunSpecKit({
513
526
  config,
514
527
  issueNumber: feature.number,
515
528
  type: 'Feature',
@@ -521,6 +534,16 @@ async function implementFeature({ token, owner, repo, config, feature, featureDi
521
534
  `${chalk.green('✓')} Implementação acionada para a Feature #${feature.number} ` +
522
535
  `(${pending.length} story(ies) pendente(s)).\n` +
523
536
  ` Próximo: acompanhe os PRs de cada Story; a Feature avança para ${STAGE_CODE_REVIEW} após a última.`,
537
+ onSuccess: async () => {
538
+ // Execução única para todas as pendentes: no sucesso, Tasks → Done e
539
+ // Stories → Code Review (a Feature fica com a Action de PR/code-review).
540
+ for (const s of pending) {
541
+ await applyBoardMoves({ token, moves: planBoardMoves('success', {
542
+ story: { nodeId: s.nodeId, number: s.number },
543
+ tasks: s.tasks || [],
544
+ }) });
545
+ }
546
+ },
524
547
  });
525
548
  }
526
549
 
@@ -588,7 +611,7 @@ export async function implement({ issue: issueArg, featureDir: featureDirOpt, dr
588
611
  }
589
612
  p.log.info(`Story com ${tasks.length} task(s): ${tasks.map(t => `#${t.number}`).join(', ')}`);
590
613
  } else if (type === 'Task') {
591
- tasks = [{ number: issue.number, title: issue.title, body: issue.body || '' }];
614
+ tasks = [{ number: issue.number, title: issue.title, body: issue.body || '', nodeId: issue.node_id }];
592
615
  p.log.info(`Task única #${issueNumber}.`);
593
616
  } else if (type === 'Feature') {
594
617
  // Modo Feature: Stories pendentes em ordem de dependência, contexto único.
@@ -618,6 +641,16 @@ export async function implement({ issue: issueArg, featureDir: featureDirOpt, dr
618
641
  p.log.warn('Não foi possível resolver a Feature; seguindo só com as tasks (use --feature-dir).');
619
642
  }
620
643
 
644
+ // 4a-board. Board determinístico: Feature/Story → Desenvolvimento (In
645
+ // Progress) já no início — a UI mostra o desenvolvimento em andamento sem
646
+ // depender de o LLM mover cards. Best-effort: falha vira warn.
647
+ await applyBoardMoves({ token, moves: planBoardMoves('start', {
648
+ feature: feature ? { nodeId: feature.nodeId, number: feature.number } : null,
649
+ story: type === 'Story' ? { nodeId: issue.node_id, number: issue.number } : null,
650
+ tasks: tasks.map(t => ({ nodeId: t.nodeId, number: t.number })),
651
+ tasksStartStatus: type === 'Task' ? PROGRESS_IN_PROGRESS : PROGRESS_TODO,
652
+ }) });
653
+
621
654
  // 4b. Stories irmãs da Feature — a Feature só avança para Code Review quando
622
655
  // TODAS as suas Stories estiverem implementadas. Lista as outras para o agente
623
656
  // verificar antes de mover a Feature.
@@ -690,17 +723,21 @@ export async function implement({ issue: issueArg, featureDir: featureDirOpt, dr
690
723
  type, issue, tasks, feature, siblingStories, ...specPlan,
691
724
  comments, codeDigest, blockedByWarnings,
692
725
  });
693
- writeContextAndRunSpecKit({
726
+ await writeContextAndRunSpecKit({
694
727
  config, issueNumber, type, title: issue.title, specPlan, context, dryRun,
695
728
  outroSuccess:
696
729
  `${chalk.green('✓')} Implementação acionada para ${type} #${issueNumber}.\n` +
697
- ' Próximo: revise as mudanças, abra o PR e mova o card para 👀 Code Review.',
730
+ ' Próximo: revise as mudanças e abra o PR o board foi atualizado.',
731
+ onSuccess: () => applyBoardMoves({ token, moves: planBoardMoves('success', {
732
+ story: type === 'Story' ? { nodeId: issue.node_id, number: issue.number } : null,
733
+ tasks: tasks.map(t => ({ nodeId: t.nodeId, number: t.number })),
734
+ }) }),
698
735
  });
699
736
  }
700
737
 
701
738
  // Grava o arquivo de contexto e aciona o spec-kit (comando configurável) —
702
739
  // fecho comum dos modos Feature e Story/Task.
703
- function writeContextAndRunSpecKit({ config, issueNumber, type, title, specPlan, context, dryRun, outroSuccess }) {
740
+ async function writeContextAndRunSpecKit({ config, issueNumber, type, title, specPlan, context, dryRun, outroSuccess, onSuccess }) {
704
741
  mkdirSync(WORK_DIR, { recursive: true });
705
742
  const tasksFile = path.join(WORK_DIR, `implement-${issueNumber}.md`);
706
743
  writeFileSync(tasksFile, context);
@@ -746,5 +783,6 @@ function writeContextAndRunSpecKit({ config, issueNumber, type, title, specPlan,
746
783
  return;
747
784
  }
748
785
 
786
+ if (onSuccess) await onSuccess();
749
787
  p.outro(outroSuccess);
750
788
  }
@@ -23,7 +23,7 @@ function reportSkill(status) {
23
23
  if (status.agentsDetected.length === 0) {
24
24
  p.log.warn(
25
25
  'Nenhum agente de código detectado neste diretório — a skill spec-wave ' +
26
- 'não parece instalada. Rode `npx @spec-wave/cli install-skill`.'
26
+ 'não parece instalada. Rode `npx @spec-wave/cli@latest install-skill`.'
27
27
  );
28
28
  return;
29
29
  }
@@ -34,7 +34,7 @@ function reportSkill(status) {
34
34
  p.log.warn(
35
35
  'Skill pendente de instalação/atualização:\n' +
36
36
  status.pending.map(s => ` ${chalk.yellow('↻')} ${s.agent} (${s.reason}) — ${chalk.dim(s.path)}`).join('\n') +
37
- '\nRode `npx @spec-wave/cli install-skill` (ou `npx @spec-wave/cli update`).'
37
+ '\nRode `npx @spec-wave/cli@latest install-skill` (ou `npx @spec-wave/cli@latest update`).'
38
38
  );
39
39
  }
40
40
 
@@ -55,7 +55,7 @@ export async function info(options = {}) {
55
55
  p.log.warn(`Este repositório ${chalk.bold('não foi inicializado')} (sem ${CONFIG_FILE}).`);
56
56
  reportSkill(skill);
57
57
  p.log.info(`🌐 Acesse o Portal Web da ferramenta em ${chalk.cyan(PORTAL_URL)}`);
58
- p.outro('Execute `npx @spec-wave/cli init` para configurar.');
58
+ p.outro('Execute `npx @spec-wave/cli@latest init` para configurar.');
59
59
  return;
60
60
  }
61
61
 
@@ -223,7 +223,7 @@ export async function init(options) {
223
223
  ` ${configWritten ? '3' : '2'}. Configure o board view para agrupar por "Etapa"\n` +
224
224
  ` ${configWritten ? '4' : '3'}. Crie uma Feature com o prefixo [FEATURE] no título\n` +
225
225
  ` ${configWritten ? '5' : '4'}. Use a skill spec-wave para guiar o fluxo\n\n` +
226
- ` ${chalk.dim('Para instalar a skill no seu agente: npx @spec-wave/cli install-skill')}\n\n` +
226
+ ` ${chalk.dim('Para instalar a skill no seu agente: npx @spec-wave/cli@latest install-skill')}\n\n` +
227
227
  ` 🌐 Acesse o Portal Web da ferramenta em ${chalk.cyan(PORTAL_URL)}`
228
228
  );
229
229
  }
@@ -100,13 +100,13 @@ export function parseSkill(raw) {
100
100
  }
101
101
 
102
102
  // Banner de versão inserido no topo do corpo da skill instalada. O agente lê
103
- // esta linha e, se `npx @spec-wave/cli --version` for maior, orienta reinstalar.
103
+ // esta linha e, se `npx @spec-wave/cli@latest --version` for maior, orienta reinstalar.
104
104
  function versionBanner(version) {
105
105
  return (
106
106
  `> ⚙️ **spec-wave skill v${version}** — esta skill é uma cópia estática. ` +
107
- 'Se `npx @spec-wave/cli --version` indicar uma versão maior, ela está ' +
108
- 'desatualizada: rode `npx @spec-wave/cli update` (atualiza só o que mudou) ' +
109
- 'ou `npx @spec-wave/cli install-skill --force` (só a skill).'
107
+ 'Se `npx @spec-wave/cli@latest --version` indicar uma versão maior, ela está ' +
108
+ 'desatualizada: rode `npx @spec-wave/cli@latest update` (atualiza só o que mudou) ' +
109
+ 'ou `npx @spec-wave/cli@latest install-skill --force` (só a skill).'
110
110
  );
111
111
  }
112
112
 
@@ -210,7 +210,7 @@ export async function update(options = {}) {
210
210
  // Config (.spec-wave.json) — reconsulta o Project e reescreve local.
211
211
  if (configStale) {
212
212
  if (!configStale.canApply) {
213
- p.log.warn(`${CONFIG_FILE}: sem project.id — pulei. Rode \`npx @spec-wave/cli init\` (sem --skip-project).`);
213
+ p.log.warn(`${CONFIG_FILE}: sem project.id — pulei. Rode \`npx @spec-wave/cli@latest init\` (sem --skip-project).`);
214
214
  } else {
215
215
  const tk = await getToken();
216
216
  if (!tk) {
package/src/config.mjs CHANGED
@@ -52,7 +52,6 @@ export const STATUS_OPTIONS = [
52
52
  { name: '📋 Spec', color: 'YELLOW' },
53
53
  { name: '📋 Plan', color: 'YELLOW' },
54
54
  { name: '✅ Ready', color: 'GREEN' },
55
- { name: '📋 Backlog Técnico', color: 'BLUE' },
56
55
  { name: '🚧 Desenvolvimento', color: 'ORANGE' },
57
56
  { name: '👀 Code Review', color: 'PURPLE' },
58
57
  { name: '🧪 QA', color: 'PINK' },
@@ -0,0 +1,104 @@
1
+ // Movimentos de board do `implement` — decisão pura + executor não-fatal.
2
+ //
3
+ // O implement passa a mover os cards DETERMINISTICAMENTE (em código, não em
4
+ // prosa para o LLM seguir): no início a Feature/Story vão para Desenvolvimento
5
+ // (In Progress) e, no sucesso do spec-kit, as Tasks vão para Done e a Story
6
+ // para Code Review — mesma semântica de `task start`/`task done`/`story review`
7
+ // e do que o contexto em prosa sempre pediu. Falha de board NUNCA derruba a
8
+ // implementação (warn e segue).
9
+
10
+ import * as p from '@clack/prompts';
11
+ import { loadProjectConfig, resolveField, advanceToStage, setItemStatus } from './board.mjs';
12
+ import {
13
+ STAGE_DEVELOPMENT, STAGE_CODE_REVIEW, STAGE_DONE,
14
+ PROGRESS_TODO, PROGRESS_IN_PROGRESS, PROGRESS_DONE,
15
+ } from '../config.mjs';
16
+
17
+ /**
18
+ * Decide os movimentos de board de uma fase do implement. Pura, sem I/O.
19
+ *
20
+ * @param {'start'|'success'} phase
21
+ * @param {{ feature?: {nodeId:string,number:number}|null,
22
+ * story?: {nodeId:string,number:number}|null,
23
+ * tasks?: Array<{nodeId?:string,number:number}> }} refs
24
+ * @returns {Array<{nodeId:string, label:string, stage:string, status:string,
25
+ * statusFallback:boolean}>}
26
+ * statusFallback: se a Etapa já estiver adiante (advanceToStage devolve
27
+ * false), ainda assim alinhar o Status — usado nos movimentos de início
28
+ * (ex.: Feature já em Desenvolvimento volta a mostrar In Progress).
29
+ */
30
+ export function planBoardMoves(phase, {
31
+ feature = null, story = null, tasks = [],
32
+ // Status das Tasks na fase start: Todo quando enfileiradas atrás de uma
33
+ // Story; In Progress quando a própria Task é o item sendo implementado.
34
+ tasksStartStatus = PROGRESS_TODO,
35
+ } = {}) {
36
+ const moves = [];
37
+ if (phase === 'start') {
38
+ if (feature?.nodeId) {
39
+ moves.push({ nodeId: feature.nodeId, label: `Feature #${feature.number}`,
40
+ stage: STAGE_DEVELOPMENT, status: PROGRESS_IN_PROGRESS, statusFallback: true });
41
+ }
42
+ if (story?.nodeId) {
43
+ moves.push({ nodeId: story.nodeId, label: `Story #${story.number}`,
44
+ stage: STAGE_DEVELOPMENT, status: PROGRESS_IN_PROGRESS, statusFallback: true });
45
+ }
46
+ for (const t of tasks) {
47
+ if (!t?.nodeId) continue;
48
+ moves.push({ nodeId: t.nodeId, label: `Task #${t.number}`,
49
+ stage: STAGE_DEVELOPMENT, status: tasksStartStatus,
50
+ statusFallback: tasksStartStatus === PROGRESS_IN_PROGRESS });
51
+ }
52
+ } else if (phase === 'success') {
53
+ for (const t of tasks) {
54
+ if (!t?.nodeId) continue;
55
+ moves.push({ nodeId: t.nodeId, label: `Task #${t.number}`,
56
+ stage: STAGE_DONE, status: PROGRESS_DONE, statusFallback: false });
57
+ }
58
+ if (story?.nodeId) {
59
+ moves.push({ nodeId: story.nodeId, label: `Story #${story.number}`,
60
+ stage: STAGE_CODE_REVIEW, status: PROGRESS_TODO, statusFallback: false });
61
+ }
62
+ }
63
+ return moves;
64
+ }
65
+
66
+ /**
67
+ * Executa os movimentos no Projects v2. Best-effort: qualquer falha vira
68
+ * warn e a implementação continua. Usa PROJECT_TOKEN quando definido (PAT
69
+ * com scope de Project em org — mesmo padrão do code-review/qa).
70
+ */
71
+ export async function applyBoardMoves({ token, moves, cwd = process.cwd(), log = p.log }) {
72
+ if (!moves || moves.length === 0) return;
73
+ try {
74
+ const { project, error } = loadProjectConfig({ cwd });
75
+ if (error) {
76
+ log.warn(`board: ${error} — Etapas não atualizadas.`);
77
+ return;
78
+ }
79
+ const projectToken = process.env.PROJECT_TOKEN || token;
80
+ const etapaField = await resolveField(projectToken, project, 'Etapa').catch(() => null);
81
+ const statusField = await resolveField(projectToken, project, 'Status').catch(() => null);
82
+ if (!etapaField?.id) {
83
+ log.warn('board: campo Etapa não resolvido — Etapas não atualizadas.');
84
+ return;
85
+ }
86
+ for (const m of moves) {
87
+ try {
88
+ const advanced = await advanceToStage(
89
+ projectToken, project, etapaField, statusField, m.nodeId, m.stage, m.status);
90
+ if (advanced) {
91
+ log.info(`board: ${m.label} → ${m.stage} (${m.status})`);
92
+ } else if (m.statusFallback && statusField?.id) {
93
+ // Etapa já está nessa fase ou adiante: ao menos alinha o Status.
94
+ await setItemStatus(projectToken, project, statusField, m.nodeId, m.status);
95
+ log.info(`board: ${m.label} já em ${m.stage}+ — Status → ${m.status}`);
96
+ }
97
+ } catch (err) {
98
+ log.warn(`board: falha ao mover ${m.label}: ${err.message}`);
99
+ }
100
+ }
101
+ } catch (err) {
102
+ log.warn(`board: indisponível (${err.message}) — implementação segue.`);
103
+ }
104
+ }
@@ -4,6 +4,7 @@ description: "Use when the user wants to set up a spec-driven GitHub workflow, c
4
4
  argument-hint: "[info|setup|update|doctor|issue|feature|spec|plan|ready|decompose|order|implement|task|story|uninstall|rfc|fix-pr] [target]"
5
5
  user-invocable: true
6
6
  allowed-tools:
7
+ - Bash(npx @spec-wave/cli@latest *)
7
8
  - Bash(npx @spec-wave/cli *)
8
9
  - Bash(gh issue *)
9
10
  - Bash(gh project *)
@@ -27,18 +28,18 @@ Este skill guia o usuário pelo fluxo spec-driven definido no RFC-001.
27
28
 
28
29
  > **Antes de responder a qualquer sub-comando**, leia o arquivo `rfc/rfc-integrate-spec-kit-into-kanban.md` se ele existir no diretório atual, para embasar suas respostas no processo real da equipe.
29
30
 
30
- > **Verifique se esta skill está atualizada:** logo no topo deste arquivo há um banner `spec-wave skill vX.Y.Z` (inserido na instalação). Compare com `npx @spec-wave/cli --version`. Se a CLI for **mais recente** (ou o banner estiver ausente = instalada por versão antiga), esta skill está desatualizada — avise o usuário e sugira `npx @spec-wave/cli update` (detecta e atualiza só o que mudou: skill, `.spec-wave.json` e workflows/labels do repo) ou, para atualizar só a skill, `npx @spec-wave/cli install-skill --force`. A skill é uma cópia estática e **não** acompanha o `npx` sozinha.
31
+ > **Verifique se esta skill está atualizada:** logo no topo deste arquivo há um banner `spec-wave skill vX.Y.Z` (inserido na instalação). Compare com `npx @spec-wave/cli@latest --version`. Se a CLI for **mais recente** (ou o banner estiver ausente = instalada por versão antiga), esta skill está desatualizada — avise o usuário e sugira `npx @spec-wave/cli@latest update` (detecta e atualiza só o que mudou: skill, `.spec-wave.json` e workflows/labels do repo) ou, para atualizar só a skill, `npx @spec-wave/cli@latest install-skill --force`. A skill é uma cópia estática e **não** acompanha o `npx` sozinha.
31
32
 
32
33
  ---
33
34
 
34
35
  ## Detecção de configuração (faça isto primeiro, sempre)
35
36
 
36
- Antes de qualquer sub-comando, leia o arquivo `.spec-wave.json` na raiz do repositório atual (use o tool Read). Esse arquivo é gravado pelo `npx @spec-wave/cli init` e é a fonte de estado persistente entre sessões.
37
+ Antes de qualquer sub-comando, leia o arquivo `.spec-wave.json` na raiz do repositório atual (use o tool Read). Esse arquivo é gravado pelo `npx @spec-wave/cli@latest init` e é a fonte de estado persistente entre sessões.
37
38
 
38
39
  - **Se existir**, o spec-wave já foi configurado. Use seus campos para contextualizar as respostas, sem perguntar de novo:
39
40
  - `owner`/`repo` → repositório alvo dos comandos `gh`
40
41
  - `project.url` / `project.title` → o GitHub Project a referenciar
41
- - `version` → versão da CLI usada no `init` (compare com `npx @spec-wave/cli --version`; se divergir, sugira `npx @spec-wave/cli refresh --config` para atualizar o arquivo, ou re-rodar o `init` para atualizar workflows/labels)
42
+ - `version` → versão da CLI usada no `init` (compare com `npx @spec-wave/cli@latest --version`; se divergir, sugira `npx @spec-wave/cli@latest refresh --config` para atualizar o arquivo, ou re-rodar o `init` para atualizar workflows/labels)
42
43
  - `initializedAt` → quando foi configurado
43
44
  Não rode `/spec-wave setup` de novo a menos que o usuário peça explicitamente.
44
45
  - **Se não existir**, o repositório provavelmente ainda não foi configurado. Sugira começar por `/spec-wave setup`.
@@ -72,7 +73,7 @@ Exceção: se o usuário pedir explicitamente para revisar ou melhorar um docume
72
73
 
73
74
  ```
74
75
  📥 Backlog → 🎯 Priorizado → 📋 Spec → 📋 Plan → ✅ Ready
75
- 📋 Backlog Técnico → 🚧 Desenvolvimento → 👀 Code Review
76
+ → 🚧 Desenvolvimento → 👀 Code Review
76
77
  → 🧪 QA → 📋 Homologação → 🚀 Deploy → 🎉 Done
77
78
  ```
78
79
 
@@ -86,13 +87,13 @@ Labels de **estado** (gravadas pelas automações — **não** são gatilhos, n
86
87
  - `spec-wave:critique-failed` → a crítica adversarial apontou contradições **graves** nos documentos; **bloqueia** o `spec-wave:ready` até ser removida (veja *Crítica adversarial* abaixo)
87
88
  - `spec-wave:decomposed` → a Feature/RFC já foi decomposta; o `decompose` pula silenciosamente enquanto ela existir (veja *Guard de idempotência* abaixo)
88
89
 
89
- A etapa **🚧 Desenvolvimento** é coberta pelo comando **local** `npx @spec-wave/cli implement <número>` (não é uma label/Action): lê uma **Feature** (todas as Stories pendentes, em ordem de dependência), uma Story ou uma Task e aciona o spec-kit para implementar. Veja `/spec-wave implement`.
90
+ A etapa **🚧 Desenvolvimento** é coberta pelo comando **local** `npx @spec-wave/cli@latest implement <número>` (não é uma label/Action): lê uma **Feature** (todas as Stories pendentes, em ordem de dependência), uma Story ou uma Task e aciona o spec-kit para implementar. Veja `/spec-wave implement`.
90
91
 
91
92
  ---
92
93
 
93
94
  ## Referência da CLI (conheça os parâmetros ANTES de executar)
94
95
 
95
- Esta skill é um **wrapper** da CLI `@spec-wave/cli`, sempre invocada como `npx @spec-wave/cli <comando>`. Regra de ouro: **nunca rode um comando sem os parâmetros que ele aceita** esperando que ele pergunte — colete os valores com o usuário e passe via flags. Em especial, **`init` sem `--repo` abre um wizard interativo (@clack/prompts) que a skill NÃO consegue dirigir** — sempre passe `--repo`.
96
+ Esta skill é um **wrapper** da CLI `@spec-wave/cli`, sempre invocada como `npx @spec-wave/cli@latest <comando>`. Regra de ouro: **nunca rode um comando sem os parâmetros que ele aceita** esperando que ele pergunte — colete os valores com o usuário e passe via flags. Em especial, **`init` sem `--repo` abre um wizard interativo (@clack/prompts) que a skill NÃO consegue dirigir** — sempre passe `--repo`.
96
97
 
97
98
  ### `@spec-wave/cli init` — configura o repositório
98
99
  | Flag | Tipo | Descrição |
@@ -261,12 +262,12 @@ Edite o bloco `ai` no `.spec-wave.json` (e commite) — o `doctor` mostra o prov
261
262
  Mostra se o repositório atual já foi configurado com o spec-wave.
262
263
 
263
264
  **Passos:**
264
- 1. Execute: `npx @spec-wave/cli info`
265
+ 1. Execute: `npx @spec-wave/cli@latest info`
265
266
  2. **Se o repositório estiver inicializado**, o comando mostra os dados do `.spec-wave.json` (owner/repo, project, versão da CLI, data). Apresente essas informações ao usuário.
266
267
  3. **Se NÃO estiver inicializado**, pergunte ao usuário: "Este repositório ainda não foi configurado com o spec-wave. Quer rodar o `init` agora?"
267
268
  - Se sim → siga o fluxo de `/spec-wave setup`.
268
269
  - Se não → encerre sem alterar nada.
269
- 4. **Se a saída indicar skill pendente** (aviso "Skill pendente de instalação/atualização" ou, no `--json`, `skill.installNeeded: true`), pergunte ao usuário se quer instalar/atualizar agora: skill `ausente` → `npx @spec-wave/cli install-skill`; skill `desatualizada` → `npx @spec-wave/cli update` (atualiza tudo que ficou para trás). Lembre-o de recarregar o agente depois.
270
+ 4. **Se a saída indicar skill pendente** (aviso "Skill pendente de instalação/atualização" ou, no `--json`, `skill.installNeeded: true`), pergunte ao usuário se quer instalar/atualizar agora: skill `ausente` → `npx @spec-wave/cli@latest install-skill`; skill `desatualizada` → `npx @spec-wave/cli@latest update` (atualiza tudo que ficou para trás). Lembre-o de recarregar o agente depois.
270
271
 
271
272
  ---
272
273
 
@@ -277,12 +278,12 @@ Traz tudo para a versão atual da CLI, atualizando **só o que mudou**: a skill
277
278
  **Passos:**
278
279
  1. **Sempre comece com `--dry-run`** para inspecionar o que está desatualizado sem alterar nada:
279
280
  ```bash
280
- npx @spec-wave/cli update --dry-run
281
+ npx @spec-wave/cli@latest update --dry-run
281
282
  ```
282
283
  2. Mostre ao usuário o resumo (skill / config / arquivos do repo / labels que divergiram). Se **nada** estiver desatualizado, informe que já está tudo na versão atual e encerre.
283
284
  3. Se o usuário aprovar, aplique:
284
285
  ```bash
285
- npx @spec-wave/cli update --yes
286
+ npx @spec-wave/cli@latest update --yes
286
287
  ```
287
288
  - Escopos podem ser limitados com `--skip-skill`, `--skip-config`, `--skip-repo`.
288
289
  - Atualizações de **arquivos do repo** são commitadas no remoto; o **`.spec-wave.json`** é local (lembre o usuário de commitá-lo).
@@ -292,17 +293,17 @@ Traz tudo para a versão atual da CLI, atualizando **só o que mudou**: a skill
292
293
 
293
294
  ### `/spec-wave setup`
294
295
 
295
- Configura o spec-wave no repositório. Você dirige o `init` com flags — **nunca rode `npx @spec-wave/cli init` sem `--repo`** (abre o wizard interativo que você não controla).
296
+ Configura o spec-wave no repositório. Você dirige o `init` com flags — **nunca rode `npx @spec-wave/cli@latest init` sem `--repo`** (abre o wizard interativo que você não controla).
296
297
 
297
298
  **Passos:**
298
- 1. **Já configurado?** Leia `.spec-wave.json` (ou rode `npx @spec-wave/cli info`). Se existir, avise (mostre `project.url` e `version`) e confirme com o usuário antes de reconfigurar.
299
+ 1. **Já configurado?** Leia `.spec-wave.json` (ou rode `npx @spec-wave/cli@latest info`). Se existir, avise (mostre `project.url` e `version`) e confirme com o usuário antes de reconfigurar.
299
300
  2. **Descubra o repositório alvo** (parâmetro `--repo`): rode `gh repo view --json nameWithOwner -q .nameWithOwner` para obter `owner/repo` do repo atual. Confirme com o usuário; se não houver remote, pergunte o `owner/repo`.
300
301
  3. **Pergunte o título do Project** (parâmetro `--project-title`). Ofereça o default `<repo> — Spec Wave` e aceite-o se o usuário não tiver preferência.
301
302
  4. **Cheque o auth:** `gh auth status`. Se faltarem os escopos `project,repo,workflow`, oriente o usuário a rodar ele mesmo `gh auth refresh --scopes project,repo,workflow` (comando interativo — o usuário executa, não você).
302
- 5. **(Opcional) Pré-visualize** antes de aplicar: `npx @spec-wave/cli init --repo <owner/repo> --dry-run`.
303
+ 5. **(Opcional) Pré-visualize** antes de aplicar: `npx @spec-wave/cli@latest init --repo <owner/repo> --dry-run`.
303
304
  6. **Execute com os parâmetros coletados:**
304
305
  ```bash
305
- npx @spec-wave/cli init --repo <owner/repo> --project-title "<título>"
306
+ npx @spec-wave/cli@latest init --repo <owner/repo> --project-title "<título>"
306
307
  ```
307
308
  Use `--skip-project` / `--skip-labels` / `--skip-files` **apenas** para re-rodar uma fase específica que falhou antes.
308
309
  7. O `init` cria o Project, as labels, os workflows, um **scaffold de `.github/config/tech_context.yml`** (só se ainda não existir) e grava `.spec-wave.json`. Oriente o usuário a fazer `git pull` para trazer os arquivos ao checkout local.
@@ -323,7 +324,7 @@ Crie um work item tipado (Initiative/Epic/Feature/Story/Task/...) já adicionado
323
324
  1. Pergunte ao usuário: tipo (initiative/epic/feature/story/task/...), título (sem prefixo), descrição e se há uma issue **pai** (número). **Prioridade e área são opcionais**: só as inclua se o usuário pedir explicitamente. **Nunca atribua uma prioridade por conta própria** — se o usuário não informou, **omita `--priority`** e a prioridade fica `null` (sem prioridade) no board.
324
325
  2. Execute o comando com os parâmetros coletados (inclua **apenas** as flags que o usuário forneceu):
325
326
  ```bash
326
- npx @spec-wave/cli issue \
327
+ npx @spec-wave/cli@latest issue \
327
328
  --type "<tipo>" \
328
329
  --title "<título>" \
329
330
  --body "<descrição>" \
@@ -331,7 +332,7 @@ Crie um work item tipado (Initiative/Epic/Feature/Story/Task/...) já adicionado
331
332
  --priority "<prioridade>" \ # opcional — só se o usuário pediu; caso contrário OMITA (prioridade fica null)
332
333
  --parent "<número-do-pai>" # opcional
333
334
  ```
334
- Para Features, pode usar o atalho `npx @spec-wave/cli feature --title ...` (equivale a `--type feature`).
335
+ Para Features, pode usar o atalho `npx @spec-wave/cli@latest feature --title ...` (equivale a `--type feature`).
335
336
  A CLI cria a issue (label de tipo — e de prioridade **apenas se `--priority` for informado**), vincula como sub-issue do parent, adiciona ao Project e define Etapa = 📥 Backlog + Work Item Type + Area (+ Priority só se informada). **Não use `gh issue create`** (não adiciona ao board nem vincula o parent).
336
337
  3. Informe o número criado e o vínculo com o pai (se houver).
337
338
  4. Para Features: "Quando quiser iniciar, mova para **📋 Spec** e use `/spec-wave spec <número>` para gerar a especificação funcional (o plano técnico vem depois)".
@@ -344,8 +345,8 @@ Remove a configuração do spec-wave do repositório (labels, arquivos `.github`
344
345
 
345
346
  **Passos:**
346
347
  1. Confirme com o usuário que ele quer remover (a ação remove labels e faz commits removendo os workflows).
347
- 2. Mostre antes o que será removido com `npx @spec-wave/cli uninstall --dry-run`.
348
- 3. Execute `npx @spec-wave/cli uninstall` (a CLI pede confirmação; use `--yes` só se o usuário já confirmou).
348
+ 2. Mostre antes o que será removido com `npx @spec-wave/cli@latest uninstall --dry-run`.
349
+ 3. Execute `npx @spec-wave/cli@latest uninstall` (a CLI pede confirmação; use `--yes` só se o usuário já confirmou).
349
350
  4. Lembre o usuário de excluir o **GitHub Project** manualmente, se desejar — a CLI não o apaga de propósito.
350
351
 
351
352
  ---
@@ -389,7 +390,7 @@ O plano técnico segue o schema do RFC-002 §3.2: **Estratégia Técnica** (com
389
390
 
390
391
  ### Tech Context (`.github/config/tech_context.yml`)
391
392
 
392
- Fonte de verdade estática da stack do sistema (RFC-002 §4). O `generate-plan` lê este arquivo para embasar o plano técnico e usar **APENAS** as tecnologias/serviços nele declarados — sem ele, o plano fica genérico e pode inventar APIs inexistentes. O `npx @spec-wave/cli init` gera um **scaffold de exemplo** que **deve ser adaptado** à stack real. Use este fluxo quando o arquivo estiver ausente ou desatualizado.
393
+ Fonte de verdade estática da stack do sistema (RFC-002 §4). O `generate-plan` lê este arquivo para embasar o plano técnico e usar **APENAS** as tecnologias/serviços nele declarados — sem ele, o plano fica genérico e pode inventar APIs inexistentes. O `npx @spec-wave/cli@latest init` gera um **scaffold de exemplo** que **deve ser adaptado** à stack real. Use este fluxo quando o arquivo estiver ausente ou desatualizado.
393
394
 
394
395
  **Como ajudar a criar (quando não existir):**
395
396
 
@@ -455,7 +456,7 @@ Valida que spec.md e plan.md estão completos e a Feature pode avançar.
455
456
  2. Informe: "Validação iniciada. O workflow verificará se spec.md e plan.md contêm todas as seções obrigatórias."
456
457
  3. Se a validação falhar, o workflow comentará os problemas na issue e adicionará automaticamente `spec-wave:spec`. Informe o usuário para corrigir e tentar novamente.
457
458
  4. **Se a issue tiver a label `spec-wave:critique-failed`**, a validação falha de imediato: a crítica adversarial apontou contradições graves (comentário 🔎 na issue). Siga o fluxo de resolução da seção *Crítica adversarial*: corrigir os documentos → remover a label → re-aplicar `spec-wave:ready`.
458
- 5. Se passar, oriente: "Feature validada! Mova o card para **✅ Ready** e depois para **📋 Backlog Técnico** para iniciar a decomposição."
459
+ 5. Se passar, oriente: "Feature validada! Mova o card para **✅ Ready** e use `/spec-wave decompose <número>` para gerar as Stories."
459
460
 
460
461
  ---
461
462
 
@@ -474,7 +475,7 @@ Para qualquer outro tipo (Spike, Bug, Story, Task, …) o Action **recusa** e co
474
475
  gh issue edit <número> --add-label "spec-wave:decompose"
475
476
  ```
476
477
  3. Informe: "Decomposição iniciada — Feature gera Stories+Tasks; RFC gera Tasks."
477
- 4. Após a conclusão, as issues filhas aparecerão como comentário na issue pai, junto com o comentário 🔎 da crítica adversarial. A issue pai e as Stories/Tasks criadas entram no board na Etapa **✅ Ready** (Status Todo; a Etapa nunca retrocede — itens já adiante não são tocados). As Stories geradas trazem a linha `Depende de: #N` (+ relação *blocked by*) — use `npx @spec-wave/cli order <número>` para ver a ordem de execução.
478
+ 4. Após a conclusão, as issues filhas aparecerão como comentário na issue pai, junto com o comentário 🔎 da crítica adversarial. A issue pai e as Stories/Tasks criadas entram no board na Etapa **✅ Ready** (Status Todo; a Etapa nunca retrocede — itens já adiante não são tocados). As Stories geradas trazem a linha `Depende de: #N` (+ relação *blocked by*) — use `npx @spec-wave/cli@latest order <número>` para ver a ordem de execução.
478
479
  5. A issue recebe a label `spec-wave:decomposed` (guard de idempotência): rodar de novo **não** duplica as issues. Para forçar um re-decompose, siga a seção *Guard de idempotência*.
479
480
 
480
481
  ---
@@ -485,23 +486,23 @@ Aciona o spec-kit para implementar uma **Feature** (todas as Stories pendentes,
485
486
 
486
487
  **Pré-requisitos:** o repositório atual precisa estar inicializado (`.spec-wave.json` presente) e a issue deve ser do tipo Feature, Story ou Task. Para executar de fato (fora do `--dry-run`), o spec-kit precisa estar configurado via `specKit.command` no `.spec-wave.json` ou a env `SPEC_WAVE_IMPLEMENT_CMD`.
487
488
 
488
- **Modo Feature:** o comando avalia as Stories da Feature — ordena topologicamente pelas dependências (`Depende de:` + *blocked by*), consulta a Etapa de cada uma no board e **pula as já implementadas** (👀 Code Review ou além). O contexto único (`.spec-wave/implement-<feature>.md`) traz as pendentes em ordem, cada uma com suas Tasks. **Ciclo de dependências entre Stories pendentes → o comando aborta** (corrija as linhas `Depende de:`; use `npx @spec-wave/cli order <feature>` para visualizar). Story pendente sem Tasks → aborta pedindo decomposição. Todas implementadas → encerra sem acionar o spec-kit.
489
+ **Modo Feature:** o comando avalia as Stories da Feature — ordena topologicamente pelas dependências (`Depende de:` + *blocked by*), consulta a Etapa de cada uma no board e **pula as já implementadas** (👀 Code Review ou além). O contexto único (`.spec-wave/implement-<feature>.md`) traz as pendentes em ordem, cada uma com suas Tasks. **Ciclo de dependências entre Stories pendentes → o comando aborta** (corrija as linhas `Depende de:`; use `npx @spec-wave/cli@latest order <feature>` para visualizar). Story pendente sem Tasks → aborta pedindo decomposição. Todas implementadas → encerra sem acionar o spec-kit.
489
490
 
490
491
  **Passos:**
491
492
  1. Confirme que há `.spec-wave.json` no repo (senão, oriente `/spec-wave setup`).
492
493
  2. **Sempre comece com `--dry-run`** para inspecionar o que será feito — detecção do tipo, lista de Tasks coletadas (Story) ou a ordem/puladas/ciclos das Stories (Feature) e o comando do spec-kit que seria executado:
493
494
  ```bash
494
- npx @spec-wave/cli implement <número> --dry-run
495
+ npx @spec-wave/cli@latest implement <número> --dry-run
495
496
  ```
496
497
  3. Mostre ao usuário o contexto montado em `.spec-wave/implement-<número>.md` e o comando. Esse arquivo contém as **instruções de execução sequencial**: implemente as Tasks **uma por vez** — mova a task para **🚧 Desenvolvimento** só ao iniciá-la e para **🎉 Done** ao concluí-la, antes de passar para a próxima. **Nunca** coloque várias tasks em "in progress" ao mesmo tempo.
497
- 4. **Se você (agente) for implementar diretamente** (sem `specKit.command`): siga o contexto task por task. Para cada task: `npx @spec-wave/cli task start <n>` ao iniciar (Etapa 🚧 Desenvolvimento + Status In Progress) e `npx @spec-wave/cli task done <n>` ao concluir (Etapa 🎉 Done + Status Done) — **prefira esses comandos a mutações GraphQL/`gh` manuais**: eles embutem as regras do board (Etapa nunca retrocede; uma task In Progress por vez). Se o contexto trouxer **aviso de dependência pendente** (a issue depende de outra não concluída), confirme com o usuário antes de seguir. **Ao concluir toda a Story**: faça o commit, abra o PR e mova a Story com `npx @spec-wave/cli story review <n>` (Etapa 👀 Code Review, Status → Todo) — as Tasks já estão em 🎉 Done. A **Feature só avança** quando **TODAS as suas Stories** já estiverem em Code Review — se houver Story pendente, deixe a Feature em 🚧 Desenvolvimento. Lembre: Etapa só avança (nunca volta); Status é o progresso dentro da etapa.
498
+ 4. **Se você (agente) for implementar diretamente** (sem `specKit.command`): siga o contexto task por task. Para cada task: `npx @spec-wave/cli@latest task start <n>` ao iniciar (Etapa 🚧 Desenvolvimento + Status In Progress) e `npx @spec-wave/cli@latest task done <n>` ao concluir (Etapa 🎉 Done + Status Done) — **prefira esses comandos a mutações GraphQL/`gh` manuais**: eles embutem as regras do board (Etapa nunca retrocede; uma task In Progress por vez). Se o contexto trouxer **aviso de dependência pendente** (a issue depende de outra não concluída), confirme com o usuário antes de seguir. **Ao concluir toda a Story**: faça o commit, abra o PR e mova a Story com `npx @spec-wave/cli@latest story review <n>` (Etapa 👀 Code Review, Status → Todo) — as Tasks já estão em 🎉 Done. A **Feature só avança** quando **TODAS as suas Stories** já estiverem em Code Review — se houver Story pendente, deixe a Feature em 🚧 Desenvolvimento. Lembre: Etapa só avança (nunca volta); Status é o progresso dentro da etapa.
498
499
  5. Se o usuário aprovar e o spec-kit estiver configurado, rode sem `--dry-run`:
499
500
  ```bash
500
- npx @spec-wave/cli implement <número>
501
+ npx @spec-wave/cli@latest implement <número>
501
502
  ```
502
503
  - Se o spec-kit **não** estiver configurado, o comando só monta o contexto e mostra como configurar (`specKit.command` / `SPEC_WAVE_IMPLEMENT_CMD`). Ajude o usuário a definir o template (placeholders: `{tasksFile} {specFile} {planFile} {issue} {type} {title}`).
503
504
  - Use `--feature-dir docs/features/<slug>` se a resolução automática da Feature falhar (a skill avisa com warning) e você quiser anexar `spec.md`/`plan.md` como contexto.
504
- 6. **No modo Feature**, siga o contexto Story a Story, na ordem listada: para cada Story pendente, implemente as Tasks com `task start`/`task done`, depois commit + PR + `npx @spec-wave/cli story review <n>`; só então passe à próxima Story. Se a issue **não** for Feature, Story nem Task (ex.: Bug, Spike, Epic), o comando recusa. Feature **sem Stories** → rode `/spec-wave decompose` primeiro. **Ciclo de dependências** → corrija as linhas `Depende de:` (veja `spec-wave order`).
505
+ 6. **No modo Feature**, siga o contexto Story a Story, na ordem listada: para cada Story pendente, implemente as Tasks com `task start`/`task done`, depois commit + PR + `npx @spec-wave/cli@latest story review <n>`; só então passe à próxima Story. Se a issue **não** for Feature, Story nem Task (ex.: Bug, Spike, Epic), o comando recusa. Feature **sem Stories** → rode `/spec-wave decompose` primeiro. **Ciclo de dependências** → corrija as linhas `Depende de:` (veja `spec-wave order`).
505
506
  7. Ao final (Tasks em **🎉 Done**, Story em **👀 Code Review**; a Feature só vai para Code Review quando a última Story concluir — no modo Feature, isso acontece dentro da mesma execução): confirme o resultado com o usuário e oriente a revisão dos PRs.
506
507
 
507
508
  ---
@@ -24,7 +24,7 @@ jobs:
24
24
  node-version: '24'
25
25
 
26
26
  - name: Move Feature to Code Review
27
- run: npx @spec-wave/cli code-review --pr-number ${{ github.event.pull_request.number }}
27
+ run: npx @spec-wave/cli@latest code-review --pr-number ${{ github.event.pull_request.number }}
28
28
  env:
29
29
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30
30
  PROJECT_TOKEN: ${{ secrets.GH_PROJECT_TOKEN }}
@@ -29,7 +29,7 @@ jobs:
29
29
  node-version: '24'
30
30
 
31
31
  - name: Decompose into Stories and Tasks
32
- run: npx @spec-wave/cli decompose --issue-number ${{ github.event.issue.number }}
32
+ run: npx @spec-wave/cli@latest decompose --issue-number ${{ github.event.issue.number }}
33
33
  env:
34
34
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
35
35
  PROJECT_TOKEN: ${{ secrets.GH_PROJECT_TOKEN }}
@@ -28,7 +28,7 @@ jobs:
28
28
  node-version: '24'
29
29
 
30
30
  - name: Generate plan.md
31
- run: npx @spec-wave/cli generate-plan --issue-number ${{ github.event.issue.number }}
31
+ run: npx @spec-wave/cli@latest generate-plan --issue-number ${{ github.event.issue.number }}
32
32
  env:
33
33
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
34
34
  ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
@@ -28,7 +28,7 @@ jobs:
28
28
  node-version: '24'
29
29
 
30
30
  - name: Generate spec.md
31
- run: npx @spec-wave/cli generate-spec --issue-number ${{ github.event.issue.number }}
31
+ run: npx @spec-wave/cli@latest generate-spec --issue-number ${{ github.event.issue.number }}
32
32
  env:
33
33
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
34
34
  ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
@@ -25,7 +25,7 @@ jobs:
25
25
  node-version: '24'
26
26
 
27
27
  - name: Move Feature to QA
28
- run: npx @spec-wave/cli qa --pr-number ${{ github.event.pull_request.number }}
28
+ run: npx @spec-wave/cli@latest qa --pr-number ${{ github.event.pull_request.number }}
29
29
  env:
30
30
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31
31
  PROJECT_TOKEN: ${{ secrets.GH_PROJECT_TOKEN }}
@@ -26,7 +26,7 @@ jobs:
26
26
  node-version: '24'
27
27
 
28
28
  - name: Validate spec and plan
29
- run: npx @spec-wave/cli validate --issue-number ${{ github.event.issue.number }}
29
+ run: npx @spec-wave/cli@latest validate --issue-number ${{ github.event.issue.number }}
30
30
  env:
31
31
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
32
32
  GITHUB_REPOSITORY: ${{ github.repository }}