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