trackfw 1.0.2 → 1.0.4

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.
@@ -0,0 +1,643 @@
1
+ 'use strict'
2
+
3
+ const fs = require('fs')
4
+ const path = require('path')
5
+ const os = require('os')
6
+
7
+ const GOV_DIRS = [
8
+ 'docs/adr',
9
+ 'docs/req',
10
+ 'docs/roadmaps/backlog',
11
+ 'docs/roadmaps/wip',
12
+ 'docs/roadmaps/blocked',
13
+ 'docs/roadmaps/done',
14
+ 'docs/roadmaps/abandoned',
15
+ ]
16
+
17
+ /**
18
+ * scaffold(cfg) — cria diretórios de governança e gera arquivos de configuração.
19
+ * cfg = { projectName, projectType, frontend, backend, pkgManager, hooks, ci }
20
+ */
21
+ async function scaffold(cfg) {
22
+ for (const dir of GOV_DIRS) {
23
+ fs.mkdirSync(dir, { recursive: true })
24
+ console.log(` ✓ ${dir}`)
25
+ }
26
+
27
+ writeTrackfwConfig(cfg)
28
+ generateValidateScript(cfg)
29
+ generateCIWorkflow(cfg)
30
+ generateGitHooks(cfg)
31
+ generateClaudeMD(cfg)
32
+ generateClaudeCommands()
33
+ }
34
+
35
+ // ---------------------------------------------------------------------------
36
+ // trackfw.yaml
37
+ // ---------------------------------------------------------------------------
38
+
39
+ function writeTrackfwConfig(cfg) {
40
+ const today = new Date().toISOString().slice(0, 10)
41
+ const content = `# trackfw configuration
42
+ # generated: ${today}
43
+
44
+ frontend: ${cfg.frontend || ''}
45
+ backend: ${cfg.backend || ''}
46
+ pkg_manager: ${cfg.pkgManager || ''}
47
+ hooks: ${cfg.hooks || ''}
48
+ ci: ${cfg.ci || ''}
49
+ `
50
+ fs.writeFileSync('trackfw.yaml', content, 'utf8')
51
+ console.log(' ✓ trackfw.yaml')
52
+ }
53
+
54
+ // ---------------------------------------------------------------------------
55
+ // scripts/trackfw-validate.sh
56
+ // ---------------------------------------------------------------------------
57
+
58
+ function generateValidateScript(cfg) {
59
+ fs.mkdirSync('scripts', { recursive: true })
60
+
61
+ const script = buildValidateScript(cfg)
62
+ const scriptPath = path.join('scripts', 'trackfw-validate.sh')
63
+ fs.writeFileSync(scriptPath, script, { encoding: 'utf8', mode: 0o755 })
64
+ console.log(` ✓ ${scriptPath}`)
65
+ }
66
+
67
+ function buildValidateScript(cfg) {
68
+ let base = `#!/usr/bin/env sh
69
+ # trackfw governance gate — generated by trackfw init
70
+ set -e
71
+
72
+ echo "→ trackfw: validating governance..."
73
+ trackfw validate
74
+
75
+ `
76
+
77
+ switch (cfg.backend) {
78
+ case 'go':
79
+ base += 'echo "→ build check (go)..."\ngo build ./...\n'
80
+ break
81
+ case 'java':
82
+ base += 'echo "→ build check (maven)..."\nmvn compile -q\n'
83
+ break
84
+ case 'node': {
85
+ const pm = cfg.pkgManager || 'npm'
86
+ base += `echo "→ build check (node)..."\n${pm} run build\n`
87
+ break
88
+ }
89
+ case 'python':
90
+ base += "echo \"→ build check (python)...\"\npython -m py_compile $(find . -name '*.py' -not -path './.venv/*' -not -path './venv/*')\n"
91
+ break
92
+ }
93
+
94
+ if (['react', 'vue', 'angular'].includes(cfg.frontend)) {
95
+ const pm = cfg.pkgManager && cfg.pkgManager !== 'none' ? cfg.pkgManager : 'npm'
96
+ base += `echo "→ frontend build check..."\n${pm} run build\n`
97
+ }
98
+
99
+ base += '\necho "✓ all checks passed."\n'
100
+ return base
101
+ }
102
+
103
+ // ---------------------------------------------------------------------------
104
+ // CI workflows
105
+ // ---------------------------------------------------------------------------
106
+
107
+ function generateCIWorkflow(cfg) {
108
+ switch (cfg.ci) {
109
+ case 'github-actions':
110
+ generateGitHubActionsWorkflow()
111
+ break
112
+ case 'gitlab-ci':
113
+ generateGitLabCIWorkflow()
114
+ break
115
+ }
116
+ }
117
+
118
+ function generateGitHubActionsWorkflow() {
119
+ fs.mkdirSync('.github/workflows', { recursive: true })
120
+
121
+ const content = `name: trackfw-gate
122
+ on:
123
+ pull_request:
124
+ branches: [main]
125
+
126
+ jobs:
127
+ governance:
128
+ runs-on: ubuntu-latest
129
+ steps:
130
+ - uses: actions/checkout@v4
131
+
132
+ - name: Install trackfw
133
+ run: |
134
+ curl -sSfL https://github.com/kgsaran/trackfw/releases/latest/download/install.sh | sh
135
+
136
+ - name: Governance gate
137
+ run: trackfw validate
138
+ `
139
+
140
+ const filePath = '.github/workflows/trackfw-gate.yml'
141
+ fs.writeFileSync(filePath, content, 'utf8')
142
+ console.log(` ✓ ${filePath}`)
143
+ }
144
+
145
+ function generateGitLabCIWorkflow() {
146
+ const content = `# trackfw governance gate
147
+ trackfw-gate:
148
+ stage: test
149
+ image: alpine:latest
150
+ before_script:
151
+ - apk add --no-cache curl
152
+ - curl -sSfL https://github.com/kgsaran/trackfw/releases/latest/download/install.sh | sh
153
+ script:
154
+ - trackfw validate
155
+ only:
156
+ - merge_requests
157
+ `
158
+
159
+ fs.writeFileSync('.gitlab-ci-trackfw.yml', content, 'utf8')
160
+ console.log(' ✓ .gitlab-ci-trackfw.yml')
161
+ }
162
+
163
+ // ---------------------------------------------------------------------------
164
+ // Git hooks
165
+ // ---------------------------------------------------------------------------
166
+
167
+ function generateGitHooks(cfg) {
168
+ switch (cfg.hooks) {
169
+ case 'husky':
170
+ generateHuskyHook()
171
+ break
172
+ case 'lefthook':
173
+ generateLefthookHook()
174
+ break
175
+ }
176
+ }
177
+
178
+ function generateHuskyHook() {
179
+ fs.mkdirSync('.husky', { recursive: true })
180
+ const content = '#!/usr/bin/env sh\n. "$(dirname -- "$0")/_/husky.sh"\n\ntrackfw validate\n'
181
+ const filePath = '.husky/pre-commit'
182
+ fs.writeFileSync(filePath, content, { encoding: 'utf8', mode: 0o755 })
183
+ console.log(` ✓ ${filePath}`)
184
+ }
185
+
186
+ function generateLefthookHook() {
187
+ const content = `pre-commit:
188
+ commands:
189
+ trackfw-validate:
190
+ run: trackfw validate
191
+ `
192
+ fs.writeFileSync('lefthook.yml', content, 'utf8')
193
+ console.log(' ✓ lefthook.yml')
194
+ }
195
+
196
+ // ---------------------------------------------------------------------------
197
+ // CLAUDE.md
198
+ // ---------------------------------------------------------------------------
199
+
200
+ function generateClaudeMD(cfg) {
201
+ const today = new Date().toISOString().slice(0, 10)
202
+ const projectName = cfg.projectName || 'my-project'
203
+
204
+ let content = `# ${projectName} — Claude Code Instructions\n\n`
205
+ content += `> Generated by trackfw on ${today}. Update this file as the project evolves.\n\n`
206
+
207
+ content += '## Project overview\n\n'
208
+ content += '<!-- Describe what this project does in 2-3 sentences. -->\n\n'
209
+
210
+ content += '## Governance chain\n\n'
211
+ content += '```\nADR → REQ → ROADMAP → backlog / wip / blocked / done / abandoned\n```\n\n'
212
+
213
+ content += '## Agent rules (mandatory)\n\n'
214
+ content += 'These rules apply to every agent or AI assistant working in this project:\n\n'
215
+ content += '1. **Never start coding without a REQ and a ROADMAP.** If none exists, create them first.\n'
216
+ content += '2. **Use `/trackfw:implement <req-slug>` to start any implementation.** This skill orchestrates the full flow automatically: finds or generates the roadmap, moves it to `wip/`, executes each ML, updates the roadmap, and moves to `done/`.\n'
217
+ content += '3. **Only one roadmap in `wip/` at a time.** Before starting a new one, complete or move to `blocked/` the current one.\n'
218
+ content += '4. **Update the roadmap after every ML.** Mark completed MLs as `✅ Concluído` in the roadmap file before moving to the next.\n'
219
+ content += '5. **Run `trackfw validate` before every commit.** Zero violations required.\n'
220
+ content += '6. **ADRs before decisions.** Any architectural or technical decision must have an ADR (`/trackfw:adr`).\n\n'
221
+
222
+ content += '## Slash commands (Claude Code)\n\n'
223
+ content += '| Command | When to use |\n'
224
+ content += '|---|---|\n'
225
+ content += '| `/trackfw:implement <req>` | **Start here** — orchestrates full implementation flow |\n'
226
+ content += '| `/trackfw:adr <title>` | Before any architectural decision |\n'
227
+ content += '| `/trackfw:req <title>` | Before any implementation work |\n'
228
+ content += '| `/trackfw:roadmap <req>` | Generate AI roadmap from a REQ |\n'
229
+ content += '| `/trackfw:move <name> <state>` | Move roadmap between states manually |\n'
230
+ content += '| `/trackfw:validate` | Run governance validation |\n'
231
+ content += '| `/trackfw:status` | Check what is in flight |\n\n'
232
+
233
+ content += '## CLI commands (terminal / CI)\n\n'
234
+ content += '| Command | When to use |\n'
235
+ content += '|---|---|\n'
236
+ content += '| `trackfw adr new "title"` | Create ADR |\n'
237
+ content += '| `trackfw req new "title"` | Create REQ |\n'
238
+ content += '| `trackfw roadmap new` | Create empty roadmap linked to a REQ |\n'
239
+ content += '| `trackfw roadmap move <name> <state>` | Move roadmap state |\n'
240
+ content += '| `trackfw validate` | Governance validation gate |\n'
241
+ content += '| `trackfw status` | Show governance status |\n\n'
242
+
243
+ // Frontend section
244
+ if (cfg.frontend && cfg.frontend !== 'none' && cfg.frontend !== '') {
245
+ const pm = (cfg.pkgManager && cfg.pkgManager !== 'none') ? cfg.pkgManager : 'npm'
246
+ content += '## Frontend\n\n'
247
+ content += `Stack: ${cfg.frontend}\n`
248
+ content += `Package manager: ${pm}\n\n`
249
+ content += 'Build commands:\n'
250
+ content += ` ${pm} run build # build\n`
251
+ content += ` ${pm} run dev # dev server\n`
252
+ content += ` ${pm} run test # tests\n\n`
253
+ content += 'Rules:\n'
254
+ content += `- Build must pass (\`${pm} run build\`) before marking any ML as done\n`
255
+ content += '- Run `trackfw validate` before committing frontend changes\n\n'
256
+ }
257
+
258
+ // Backend section
259
+ if (cfg.backend && cfg.backend !== 'none' && cfg.backend !== '') {
260
+ const [buildCmd, testCmd, lintCmd] = backendCommands(cfg)
261
+ content += '## Backend\n\n'
262
+ content += `Stack: ${cfg.backend}\n\n`
263
+ content += 'Build commands:\n'
264
+ content += ` ${buildCmd} # build / compile check\n`
265
+ content += ` ${testCmd} # tests\n`
266
+ content += ` ${lintCmd} # lint / vet\n\n`
267
+ content += 'Rules:\n'
268
+ content += '- Build must pass before marking any ML as done\n'
269
+ content += '- Run `trackfw validate` before committing backend changes\n\n'
270
+ }
271
+
272
+ // Pre-commit checklist
273
+ content += '## Pre-commit checklist\n\n'
274
+ content += 'Before every commit:\n'
275
+ content += '- [ ] `trackfw validate` passes with zero violations\n'
276
+ if (cfg.backend && cfg.backend !== 'none' && cfg.backend !== '') {
277
+ const [buildCmd] = backendCommands(cfg)
278
+ content += `- [ ] \`${buildCmd}\` passes\n`
279
+ }
280
+ if (cfg.frontend && cfg.frontend !== 'none' && cfg.frontend !== '') {
281
+ const pm = (cfg.pkgManager && cfg.pkgManager !== 'none') ? cfg.pkgManager : 'npm'
282
+ content += `- [ ] \`${pm} run build\` passes\n`
283
+ }
284
+ content += '\n'
285
+
286
+ // Git hooks section
287
+ content += '## Git hooks\n\n'
288
+ switch (cfg.hooks) {
289
+ case 'husky':
290
+ content += 'Git hook configured in `.husky/pre-commit` — runs `trackfw validate` automatically.\n\n'
291
+ break
292
+ case 'lefthook':
293
+ content += 'Git hook configured in `lefthook.yml` — runs `trackfw validate` automatically.\n\n'
294
+ break
295
+ default:
296
+ content += 'No git hook configured. Run `trackfw validate` manually before every commit.\n\n'
297
+ }
298
+
299
+ // CI gate section
300
+ content += '## CI gate\n\n'
301
+ switch (cfg.ci) {
302
+ case 'github-actions':
303
+ content += '`.github/workflows/trackfw-gate.yml` runs `trackfw validate` on every pull request to main.\n'
304
+ break
305
+ case 'gitlab-ci':
306
+ content += '`.gitlab-ci-trackfw.yml` runs `trackfw validate` on every merge request.\n'
307
+ break
308
+ default:
309
+ content += 'No CI gate configured.\n'
310
+ }
311
+
312
+ fs.writeFileSync('CLAUDE.md', content, 'utf8')
313
+ console.log(' ✓ CLAUDE.md')
314
+ }
315
+
316
+ /**
317
+ * Retorna [buildCmd, testCmd, lintCmd] para o backend configurado.
318
+ */
319
+ function backendCommands(cfg) {
320
+ const pm = (cfg.pkgManager && cfg.pkgManager !== 'none') ? cfg.pkgManager : 'npm'
321
+ switch (cfg.backend) {
322
+ case 'go':
323
+ return ['go build ./...', 'go test ./...', 'go vet ./...']
324
+ case 'java':
325
+ return ['mvn package -q', 'mvn test', 'mvn compile -q']
326
+ case 'node':
327
+ return [`${pm} run build`, `${pm} test`, `${pm} run lint`]
328
+ case 'python':
329
+ return [
330
+ "python -m py_compile $(find . -name '*.py' -not -path './.venv/*' -not -path './venv/*')",
331
+ 'python -m pytest',
332
+ 'ruff check .',
333
+ ]
334
+ default:
335
+ return ['', '', '']
336
+ }
337
+ }
338
+
339
+ // ---------------------------------------------------------------------------
340
+ // .claude/commands/trackfw/ — 7 slash commands
341
+ // ---------------------------------------------------------------------------
342
+
343
+ function generateClaudeCommands() {
344
+ const dir = '.claude/commands/trackfw'
345
+ fs.mkdirSync(dir, { recursive: true })
346
+
347
+ const commands = {
348
+ 'adr.md': `Execute o seguinte comando bash: \`trackfw adr new "$ARGUMENTS"\`
349
+
350
+ Se o comando falhar com \`trackfw: command not found\` ou similar, informe ao usuário:
351
+
352
+ \`\`\`
353
+ trackfw não está instalado. Instale com uma das opções:
354
+
355
+ curl -sSfL https://github.com/kgsaran/trackfw/releases/latest/download/install.sh | sh
356
+ npm install -g trackfw
357
+ pip install trackfw
358
+ \`\`\``,
359
+
360
+ 'req.md': `Execute o seguinte comando bash: \`trackfw req new "$ARGUMENTS"\`
361
+
362
+ Se o comando falhar com \`trackfw: command not found\` ou similar, informe ao usuário:
363
+
364
+ \`\`\`
365
+ trackfw não está instalado. Instale com uma das opções:
366
+
367
+ curl -sSfL https://github.com/kgsaran/trackfw/releases/latest/download/install.sh | sh
368
+ npm install -g trackfw
369
+ pip install trackfw
370
+ \`\`\``,
371
+
372
+ 'validate.md': `Execute o seguinte comando bash: \`trackfw validate\`
373
+
374
+ Se o comando falhar com \`trackfw: command not found\` ou similar, informe ao usuário:
375
+
376
+ \`\`\`
377
+ trackfw não está instalado. Instale com uma das opções:
378
+
379
+ curl -sSfL https://github.com/kgsaran/trackfw/releases/latest/download/install.sh | sh
380
+ npm install -g trackfw
381
+ pip install trackfw
382
+ \`\`\``,
383
+
384
+ 'status.md': `Execute o seguinte comando bash: \`trackfw status\`
385
+
386
+ Se o comando falhar com \`trackfw: command not found\` ou similar, informe ao usuário:
387
+
388
+ \`\`\`
389
+ trackfw não está instalado. Instale com uma das opções:
390
+
391
+ curl -sSfL https://github.com/kgsaran/trackfw/releases/latest/download/install.sh | sh
392
+ npm install -g trackfw
393
+ pip install trackfw
394
+ \`\`\``,
395
+
396
+ 'move.md': `Execute o seguinte comando bash: \`trackfw roadmap move $ARGUMENTS\`
397
+
398
+ O formato esperado é: \`<nome-do-roadmap> <estado>\`
399
+
400
+ Estados válidos: \`backlog\`, \`wip\`, \`blocked\`, \`done\`, \`abandoned\`
401
+
402
+ Exemplo: \`/trackfw:move meu-roadmap wip\`
403
+
404
+ Se o comando falhar com \`trackfw: command not found\` ou similar, informe ao usuário:
405
+ trackfw não está instalado. Instale com:
406
+ curl -sSfL https://github.com/kgsaran/trackfw/releases/latest/download/install.sh | sh
407
+ npm install -g trackfw
408
+ pip install trackfw`,
409
+
410
+ 'roadmap.md': `Gere um roadmap de implementação em microlotes para uma REQ do projeto.
411
+
412
+ ## Passos
413
+
414
+ 1. **Listar REQs disponíveis**
415
+ Use Glob para listar \`docs/req/*.md\`. Se nenhum arquivo encontrado, informe:
416
+ > Nenhuma REQ encontrada em \`docs/req/\`. Crie uma primeiro com \`/trackfw:req\`.
417
+
418
+ 2. **Selecionar a REQ**
419
+ - Se \`$ARGUMENTS\` foi fornecido: use como filtro (substring case-insensitive) para encontrar o arquivo
420
+ - Se não foi fornecido ou o filtro não encontrar exatamente um: liste os arquivos disponíveis e pergunte ao usuário qual usar
421
+ - Leia o conteúdo completo do arquivo REQ selecionado
422
+
423
+ 3. **Gerar o roadmap**
424
+ Com base no conteúdo da REQ, gere um roadmap seguindo **estritamente** este formato:
425
+
426
+ \`\`\`markdown
427
+ # Roadmap: <título derivado da REQ>
428
+
429
+ > Criado em: <YYYY-MM-DD> | Status: ⬜ Backlog
430
+
431
+ ## Diagnóstico / Contexto
432
+ <resumo do problema, motivação e escopo extraídos da REQ>
433
+
434
+ ## Wave 1 — <nome descritivo> (<N> MLs em paralelo)
435
+ > Dependências: Independente
436
+
437
+ ### ML-1A — <título>
438
+ **Status:** ⬜ Pendente
439
+ **Arquivos afetados:**
440
+ - \`caminho/exato/do/arquivo\`
441
+ **Ações:**
442
+ - Descrição detalhada da ação com valores, chaves e comandos exatos
443
+ **Critérios de aceite:**
444
+ - [ ] build sem erros
445
+ - [ ] testes verdes
446
+ **Comandos de validação:** \`<comando de build e teste do projeto>\`
447
+ \`\`\`
448
+
449
+ **Princípios obrigatórios:**
450
+ - MLs dentro da mesma Wave são **independentes** (arquivos distintos, sem conflito)
451
+ - Cada ML deve ser detalhado o suficiente para execução por um agente sem contexto extra
452
+ - Maximizar paralelismo: agrupe em paralelo tudo que não compartilhar arquivos
453
+ - Waves sequenciais apenas quando há dependência real de resultado
454
+ - Critérios de aceite mensuráveis em cada ML
455
+
456
+ 4. **Salvar o arquivo**
457
+ - Calcule o slug: título em lowercase, espaços → hifens, remova caracteres especiais
458
+ - Crie o arquivo em \`docs/roadmaps/backlog/ROADMAP-<YYYY-MM-DD>-<slug>.md\`
459
+ - Use a data de hoje
460
+
461
+ 5. **Confirmar**
462
+ Informe o caminho do arquivo criado e um resumo das Waves e total de MLs gerados.`,
463
+
464
+ 'implement.md': `Você é o orquestrador de implementação do trackfw. Siga o fluxo abaixo **sem pular etapas**.
465
+
466
+ ## Argumento
467
+
468
+ \`$ARGUMENTS\` é opcional. Se fornecido, é usado como filtro (substring case-insensitive) sobre os nomes de arquivo das REQs.
469
+
470
+ ---
471
+
472
+ ## Passo 1 — Selecionar a REQ
473
+
474
+ Use Glob para listar \`docs/req/*.md\`.
475
+
476
+ - Se **nenhum arquivo encontrado**: informe que não há REQs disponíveis e sugira criar com \`/trackfw:req\`.
477
+ - Se **\`$ARGUMENTS\` foi fornecido** e filtra para exatamente uma REQ: use-a diretamente.
478
+ - Em **todos os outros casos** (sem argumento, ou argumento ambíguo): apresente a lista de REQs disponíveis e pergunte ao usuário qual deseja implementar.
479
+
480
+ Leia o conteúdo completo da REQ selecionada.
481
+
482
+ ---
483
+
484
+ ## Passo 2 — Encontrar ou gerar o Roadmap
485
+
486
+ Verifique se existe um roadmap vinculado à REQ buscando em \`docs/roadmaps/\` (backlog, wip, blocked, done, abandoned) por arquivo cujo nome contenha o slug da REQ.
487
+
488
+ **Se o roadmap ainda não existe:**
489
+ - Informe o usuário: "Nenhum roadmap encontrado para esta REQ. Gerando agora..."
490
+ - Execute o fluxo completo de geração do \`/trackfw:roadmap\` (leia o arquivo \`.claude/commands/trackfw/roadmap.md\` para seguir as instruções exatas), passando a REQ já selecionada — não pergunte novamente.
491
+ - Salve o roadmap gerado em \`docs/roadmaps/backlog/ROADMAP-<YYYY-MM-DD>-<slug>.md\`.
492
+
493
+ **Se o roadmap existe e já está em \`done/\` ou \`abandoned/\`:**
494
+ - Informe o usuário e pergunte se deseja criar um novo roadmap ou encerrar.
495
+
496
+ **Se o roadmap existe em \`backlog/\` ou \`blocked/\`:**
497
+ - Prossiga para o Passo 3.
498
+
499
+ **Se já está em \`wip/\`:**
500
+ - Prossiga diretamente para o Passo 4 (já está em execução).
501
+
502
+ ---
503
+
504
+ ## Passo 3 — Mover roadmap para WIP
505
+
506
+ Execute:
507
+ \`\`\`bash
508
+ trackfw roadmap move <nome-do-roadmap> wip
509
+ \`\`\`
510
+
511
+ Confirme que o arquivo foi movido para \`docs/roadmaps/wip/\`.
512
+
513
+ ---
514
+
515
+ ## Passo 4 — Ler e apresentar o plano
516
+
517
+ Leia o roadmap (agora em \`wip/\`). Apresente ao usuário:
518
+ - Título do roadmap
519
+ - Total de Waves e MLs
520
+ - Lista resumida dos MLs por Wave
521
+
522
+ Confirme: "Iniciando implementação. Vou executar cada ML em ordem e atualizar o roadmap a cada conclusão."
523
+
524
+ ---
525
+
526
+ ## Passo 5 — Executar cada ML em ordem
527
+
528
+ Para cada Wave (em sequência), execute os MLs da Wave:
529
+
530
+ ### Para cada ML:
531
+
532
+ **5a. Anunciar:** informe qual ML está sendo executado (ex: "Executando ML-1A — Criar client.go").
533
+
534
+ **5b. Implementar:** execute as ações descritas no ML usando suas ferramentas (Read, Write, Edit, Bash). Siga exatamente os arquivos afetados, ações e critérios de aceite listados no roadmap.
535
+
536
+ **5c. Validar:** execute os comandos de validação do ML. Se falhar, corrija antes de avançar.
537
+
538
+ **5d. Atualizar o roadmap:** edite o arquivo de roadmap em \`docs/roadmaps/wip/\` substituindo o status do ML:
539
+ - \`**Status:** ⬜ Pendente\` → \`**Status:** ✅ Concluído\`
540
+
541
+ **5e. Commitar:**
542
+ \`\`\`bash
543
+ git add -A
544
+ git commit -m "feat(<escopo>): <descrição do ML>"
545
+ \`\`\`
546
+
547
+ Só avance para a próxima Wave após todos os MLs da Wave atual estarem ✅.
548
+
549
+ ---
550
+
551
+ ## Passo 6 — Finalizar
552
+
553
+ Quando todos os MLs estiverem ✅:
554
+
555
+ **6a.** Execute \`trackfw validate\` — deve passar com zero violations.
556
+
557
+ **6b.** Mova o roadmap para done:
558
+ \`\`\`bash
559
+ trackfw roadmap move <nome-do-roadmap> done
560
+ \`\`\`
561
+
562
+ **6c.** Faça o commit final:
563
+ \`\`\`bash
564
+ git add docs/roadmaps/
565
+ git commit -m "docs(trackfw): roadmap <nome> → done"
566
+ \`\`\`
567
+
568
+ **6d.** Informe o usuário:
569
+ \`\`\`
570
+ ✅ Implementação concluída.
571
+ Roadmap: docs/roadmaps/done/<nome>.md
572
+ Próximo passo: abrir PR com gh pr create
573
+ \`\`\``,
574
+ }
575
+
576
+ let created = 0
577
+ let skipped = 0
578
+ for (const [filename, content] of Object.entries(commands)) {
579
+ const filePath = path.join(dir, filename)
580
+ if (fs.existsSync(filePath)) {
581
+ skipped++
582
+ continue
583
+ }
584
+ fs.writeFileSync(filePath, content, 'utf8')
585
+ created++
586
+ }
587
+
588
+ if (skipped > 0) {
589
+ console.log(` ✓ ${dir} (${created} slash commands criados, ${skipped} já existiam — não sobrescritos)`)
590
+ } else {
591
+ console.log(` ✓ ${dir} (${created} slash commands)`)
592
+ }
593
+ }
594
+
595
+ // ---------------------------------------------------------------------------
596
+ // AI tool installers
597
+ // ---------------------------------------------------------------------------
598
+
599
+ /**
600
+ * installAgents — instala agentes Claude Code em ~/.claude/agents/
601
+ * O pacote npm não embute os templates binários do Go, por isso informa
602
+ * ao usuário que esta operação requer o binário Go instalado.
603
+ */
604
+ async function installAgents() {
605
+ console.log(' ✓ claude (agentes — execute `trackfw install agents` com o binário Go para instalar os templates)')
606
+ }
607
+
608
+ async function installGemini() {
609
+ console.log(' ✓ gemini (sem templates disponíveis no pacote npm — instale o binário Go para acesso completo)')
610
+ }
611
+
612
+ async function installCursor() {
613
+ console.log(' ✓ cursor (sem templates disponíveis no pacote npm — instale o binário Go para acesso completo)')
614
+ }
615
+
616
+ async function installCopilot() {
617
+ console.log(' ✓ copilot (sem templates disponíveis no pacote npm — instale o binário Go para acesso completo)')
618
+ }
619
+
620
+ async function installWindsurf() {
621
+ console.log(' ✓ windsurf (sem templates disponíveis no pacote npm — instale o binário Go para acesso completo)')
622
+ }
623
+
624
+ async function installAmazonQ() {
625
+ console.log(' ✓ amazonq (sem templates disponíveis no pacote npm — instale o binário Go para acesso completo)')
626
+ }
627
+
628
+ module.exports = {
629
+ GOV_DIRS,
630
+ scaffold,
631
+ writeTrackfwConfig,
632
+ generateValidateScript,
633
+ generateCIWorkflow,
634
+ generateGitHooks,
635
+ generateClaudeMD,
636
+ generateClaudeCommands,
637
+ installAgents,
638
+ installGemini,
639
+ installCursor,
640
+ installCopilot,
641
+ installWindsurf,
642
+ installAmazonQ,
643
+ }