spec-first-claude 0.5.0-beta.9 → 0.6.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +44 -36
  2. package/bin/cli.js +13 -13
  3. package/lib/init.js +23 -20
  4. package/lib/update.js +11 -10
  5. package/package.json +1 -1
  6. package/templates/.claude/CHANGELOG.md +338 -0
  7. package/templates/.claude/adapters/SETUP.md +4 -4
  8. package/templates/.claude/adapters/confluence.md +2 -2
  9. package/templates/.claude/adapters/errors.md +2 -2
  10. package/templates/.claude/adapters/filesystem.md +4 -4
  11. package/templates/.claude/adapters/interface.md +3 -3
  12. package/templates/.claude/adapters/naming.md +15 -15
  13. package/templates/.claude/adapters/registry.md +3 -3
  14. package/templates/.claude/agents/db-coder.md +165 -165
  15. package/templates/.claude/agents/doc-writer.md +21 -16
  16. package/templates/.claude/agents/security-reviewer.md +153 -153
  17. package/templates/.claude/commands/design.md +216 -123
  18. package/templates/.claude/commands/dev.md +189 -189
  19. package/templates/.claude/commands/discovery.md +10 -1
  20. package/templates/.claude/commands/extract.md +183 -71
  21. package/templates/.claude/commands/load.md +206 -116
  22. package/templates/.claude/commands/mcp.md +385 -0
  23. package/templates/.claude/commands/merge-docs.md +100 -0
  24. package/templates/.claude/commands/plan.md +128 -94
  25. package/templates/.claude/commands/publish.md +143 -0
  26. package/templates/.claude/commands/sfw-start.md +145 -0
  27. package/templates/.claude/rules.md +1 -1
  28. package/templates/.claude/scripts/bootstrap-confluence.js +289 -0
  29. package/templates/.claude/templates/estrutura/apiContracts.template.md +18 -10
  30. package/templates/.claude/templates/estrutura/architecture.template.md +19 -9
  31. package/templates/.claude/templates/estrutura/conventions.template.md +29 -19
  32. package/templates/.claude/templates/estrutura/decisions.template.md +16 -8
  33. package/templates/.claude/templates/estrutura/domain.template.md +25 -13
  34. package/templates/.claude/templates/feature/PRD.template.md +48 -18
  35. package/templates/.claude/templates/feature/Progresso.template.md +141 -136
  36. package/templates/.claude/templates/feature/backlog-extraido.template.md +8 -6
  37. package/templates/.claude/templates/feature/context.template.md +17 -11
  38. package/templates/.claude/templates/feature/extract-log.template.md +2 -1
  39. package/templates/.claude/templates/feature/projetos.template.yaml +29 -23
  40. package/templates/.claude/templates/feature/sdd.template.md +365 -178
  41. package/templates/.claude/templates/global/progresso_global.template.md +4 -4
  42. package/templates/.claude/templates/specs/brief.template.md +22 -10
  43. package/templates/.claude/templates/specs/contracts.template.md +94 -35
  44. package/templates/.claude/templates/specs/scenarios.template.md +75 -37
  45. package/templates/.claude/templates/specs/tasks.template.md +63 -61
  46. package/templates/CLAUDE.md +268 -242
  47. package/templates/_gitignore +35 -0
  48. package/templates/sfw.config.yml.example +20 -4
  49. package/templates/.claude/commands/feature.md +0 -60
  50. package/templates/.claude/commands/merge-delta.md +0 -71
  51. package/templates/.claude/commands/new-project.md +0 -72
  52. package/templates/.claude/templates/feature/TRD.template.md +0 -204
package/README.md CHANGED
@@ -6,7 +6,7 @@ Kit completo para desenvolvimento **spec-first** com [Claude Code](https://claud
6
6
 
7
7
  Em vez de pedir pra IA "cria um CRUD de usuarios", voce fornece insumos brutos (docs, SQLs, rascunhos) e a IA:
8
8
 
9
- 1. **Extrai** requisitos estruturados (PRD/TRD)
9
+ 1. **Extrai** requisitos estruturados (PRD)
10
10
  2. **Espera sua aprovacao** (checkpoint humano)
11
11
  3. **Gera design tecnico** (SDD) — fonte unica de verdade
12
12
  4. **Planeja tasks** com dependencias e fases
@@ -48,19 +48,24 @@ MeuProjeto/
48
48
  ├── .ai/memory/napkin.md <- Memoria persistente do projeto
49
49
  ├── .claude/ <- AI OPERATIONAL CONFIG
50
50
  │ ├── rules.md <- Regras de desenvolvimento
51
- │ ├── templates/ <- 15 templates do workflow
52
- ├── feature/ <- PRD, TRD, SDD, tasks, etc.
53
- │ │ ├── estrutura/ <- 5 templates de estado do sistema
51
+ │ ├── CHANGELOG.md <- Historico do framework
52
+ │ ├── templates/ <- Templates do workflow
53
+ │ │ ├── feature/ <- PRD, SDD, context, extract-log, Progresso, backlog, projetos.yaml
54
+ │ │ ├── specs/ <- brief, contracts, scenarios, tasks (projecoes pro agent)
55
+ │ │ ├── estrutura/ <- 5 templates de sintese cross-feature
54
56
  │ │ └── global/ <- Progresso global
55
- │ ├── commands/ <- 9 commands do workflow
56
- ├── setup-projeto.md
57
- │ │ ├── feature.md
57
+ │ ├── adapters/ <- SourceAdapter + ConfluenceAdapter + FilesystemAdapter
58
+ │ ├── commands/ <- 11 commands do workflow
59
+ │ │ ├── mcp.md
60
+ │ │ ├── load.md
61
+ │ │ ├── publish.md
62
+ │ │ ├── sfw-start.md <- entrada unica (substitui setup-projeto + feature)
58
63
  │ │ ├── discovery.md
59
64
  │ │ ├── extract.md
60
65
  │ │ ├── design.md
61
66
  │ │ ├── plan.md
62
67
  │ │ ├── dev.md
63
- │ │ ├── merge-delta.md
68
+ │ │ ├── merge-docs.md <- renomeado de merge-delta
64
69
  │ │ └── session-finish.md
65
70
  │ └── agents/ <- 7 agentes especializados
66
71
  │ ├── backend-coder.md <- .NET 8 / C#
@@ -70,22 +75,23 @@ MeuProjeto/
70
75
  │ ├── doc-writer.md <- Documentacao
71
76
  │ ├── reviewer.md <- Code review
72
77
  │ └── security-reviewer.md <- Auditoria de seguranca
73
- ├── docs/ <- SYSTEM KNOWLEDGE (gerado pelo /design)
78
+ ├── docs/ <- SINTESE CROSS-FEATURE (atualizada pelo /merge-docs)
74
79
  │ ├── architecture.md <- Containers, stack, ambientes, deploy
75
80
  │ ├── domain.md <- Visao de negocio + modelo de dados
76
81
  │ ├── conventions.md <- Auth, authz, LGPD, env vars, monitoramento
77
82
  │ ├── apiContracts.md <- Rotas, paginacao, erros, catalogo de endpoints
78
- ├── decisions.md <- ADRs
79
- │ └── specs/ <- Especs por feature (projecoes do SDD, pro agent)
80
- └── {nome}/
81
- ├── brief.md <- Problema/Solucao
82
- ├── contracts.md <- Dados/API/Integracoes
83
- ├── scenarios.md <- Fluxos/UI/CAs
84
- └── tasks.md <- Tabela unica com coluna Area
85
- ├── workspace/ <- TEAM CONTENT (futuro wiki)
86
- │ ├── Input/ <- Jogue seus insumos aqui
87
- │ │ └── setup_projeto/ <- Insumos do bootstrap
88
- │ └── Output/ <- Docs narrativos pro humano (PRD, TRD, SDD, Progresso)
83
+ └── decisions.md <- ADRs (append-only)
84
+ ├── specs/ <- AGENT CONTRACTS (projecoes do SDD pro coder)
85
+ └── {nome}/
86
+ ├── brief.md <- Problema/Solucao (SDD §1+§2+§10)
87
+ ├── contracts.md <- Sistema + Áreas tocadas (SDD §3-§7)
88
+ ├── scenarios.md <- Fluxos/UI/CAs (SDD §5.2+§8+§9)
89
+ └── tasks.md <- Tabela unica com coluna Area
90
+ ├── workspace/ <- TEAM CONTENT
91
+ │ ├── Input/ <- Jogue seus insumos aqui (nome livre)
92
+ │ │ └── {nome}/ <- ex: app_barbearia, feat_login
93
+ │ └── Output/ <- Docs narrativos pro humano (PRD, SDD, Progresso)
94
+ ├── sfw.config.yml.example <- Manifesto de adapters (input/output)
89
95
  ├── CLAUDE.md <- Regras globais pro agente
90
96
  └── .gitignore
91
97
  ```
@@ -98,7 +104,8 @@ MeuProjeto/
98
104
  cd MeuProjeto
99
105
  ```
100
106
 
101
- 2. Jogue seus insumos em `workspace/Input/setup_projeto/` — qualquer formato:
107
+ 2. Jogue seus insumos em `workspace/Input/<nome>/` — qualquer formato.
108
+ `<nome>` é livre: `app_barbearia`, `bootstrap`, `feat_login`, `bug_checkout`, etc.
102
109
  - `.md`, `.txt` (descricoes, requisitos, decisoes)
103
110
  - `.sql` (modelagem de banco)
104
111
  - `.csv`, `.xml`, `.html` (dados, configs)
@@ -106,37 +113,38 @@ MeuProjeto/
106
113
 
107
114
  3. Abra o Claude Code e rode:
108
115
  ```
109
- /setup-projeto
116
+ /sfw-start <nome>
110
117
  ```
111
118
 
112
- 4. O pipeline comeca. A IA vai:
113
- - Extrair um TRD dos seus insumos
114
- - Parar e pedir sua aprovacao
119
+ 4. O pipeline comeca. A IA detecta automaticamente se e first-run (docs/ ausente)
120
+ ou feature (docs/ ja existe). Nao ha comandos diferentes pra setup vs feature.
121
+
122
+ - Extrai PRD dos seus insumos (pode ser empty em scopes puro-tecnicos)
123
+ - Para e pede sua aprovacao
115
124
  - Depois voce roda `/design`, `/plan`, `/dev` na sequencia
116
125
 
117
126
  ## Pipeline completo
118
127
 
119
128
  ```
120
- workspace/Input/ (seus arquivos)
129
+ workspace/Input/<nome>/ (seus arquivos)
121
130
  |
122
131
  v
123
- /setup-projeto --> /extract --> TRD (voce revisa e aprova)
124
- |
125
- v
126
- /design --> SDD + docs/ (5 arquivos)
132
+ /sfw-start <nome> --> /extract --> PRD (voce revisa e aprova)
133
+ |
134
+ v
135
+ /design --> SDD + docs/ (first-run: cria 5 arquivos)
136
+ (feature: gera só §Área-X + §11 delta)
127
137
  |
128
138
  v
129
139
  /plan --> tasks + Progresso.md
130
140
  |
131
141
  v
132
- /dev --> codigo nos repos + merge-delta automatico
142
+ /dev --> codigo nos repos
143
+ + /merge-docs automatico
144
+ (aplica §11 em docs/)
133
145
  ```
134
146
 
135
- Para features (apos o setup):
136
-
137
- ```
138
- /feature nome_da_feature --> /extract --> PRD --> /design --> /plan --> /dev (inclui merge-delta)
139
- ```
147
+ Mesmo comando pra bootstrap e feature — `first_run` e derivado da ausencia/presenca de `docs/`.
140
148
 
141
149
  ## Opcoes do CLI
142
150
 
package/bin/cli.js CHANGED
@@ -8,19 +8,19 @@ const args = process.argv.slice(2);
8
8
  const command = args[0];
9
9
 
10
10
  function printUsage() {
11
- console.log('Usage:');
12
- console.log(' spec-first-claude init --name=<project-name> [--target=<path>]');
13
- console.log(' spec-first-claude update [--target=<path>] [--force]');
11
+ console.log('Uso:');
12
+ console.log(' spec-first-claude init --name=<nome-do-projeto> [--target=<caminho>]');
13
+ console.log(' spec-first-claude update [--target=<caminho>] [--force]');
14
14
  console.log('');
15
- console.log('Commands:');
16
- console.log(' init Create a new spec-first project');
17
- console.log(' update Update an existing project with new framework files');
18
- console.log(' (adds missing files, updates framework files like commands/adapters/agents)');
15
+ console.log('Comandos:');
16
+ console.log(' init Cria um novo projeto spec-first');
17
+ console.log(' update Atualiza projeto existente com arquivos novos do framework');
18
+ console.log(' (adiciona faltantes, atualiza commands/adapters/agents/templates)');
19
19
  console.log('');
20
- console.log('Options:');
21
- console.log(' --name=<name> Project name (required for init)');
22
- console.log(' --target=<path> Target directory (defaults to ./<name> for init, cwd for update)');
23
- console.log(' --force Force update all files, not just framework files (use with caution)');
20
+ console.log('Opções:');
21
+ console.log(' --name=<nome> Nome do projeto (obrigatório no init)');
22
+ console.log(' --target=<path> Diretório destino (default: ./<nome> no init, cwd no update)');
23
+ console.log(' --force Força atualizar TODOS arquivos, não os do framework (cuidado)');
24
24
  }
25
25
 
26
26
  function parseArgs(args) {
@@ -40,7 +40,7 @@ if (command === 'init') {
40
40
  const opts = parseArgs(args.slice(1));
41
41
 
42
42
  if (!opts.name) {
43
- console.error('Error: --name is required.\n');
43
+ console.error('Erro: --name é obrigatório.\n');
44
44
  printUsage();
45
45
  process.exit(1);
46
46
  }
@@ -64,7 +64,7 @@ if (command === 'init') {
64
64
  } else {
65
65
  printUsage();
66
66
  if (command) {
67
- console.error(`\nUnknown command: "${command}"`);
67
+ console.error(`\nComando desconhecido: "${command}"`);
68
68
  }
69
69
  process.exit(command ? 1 : 0);
70
70
  }
package/lib/init.js CHANGED
@@ -1,6 +1,5 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
- const { execSync } = require('child_process');
4
3
 
5
4
  const PLACEHOLDER = '{{PROJECT_NAME}}';
6
5
 
@@ -8,7 +7,9 @@ function copyDir(src, dest, replacements) {
8
7
  fs.mkdirSync(dest, { recursive: true });
9
8
  for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
10
9
  const srcPath = path.join(src, entry.name);
11
- const destPath = path.join(dest, entry.name);
10
+ // Rename _gitignore .gitignore (npm strips .gitignore from packages)
11
+ const destName = entry.name === '_gitignore' ? '.gitignore' : entry.name;
12
+ const destPath = path.join(dest, destName);
12
13
  if (entry.isDirectory()) {
13
14
  copyDir(srcPath, destPath, replacements);
14
15
  } else {
@@ -24,7 +25,7 @@ function copyFile(src, dest, replacements) {
24
25
  const textExtensions = ['.md', '.yaml', '.yml', '.json', '.js', '.ts', '.gitignore', '.gitkeep', ''];
25
26
  const ext = path.extname(src).toLowerCase();
26
27
  const basename = path.basename(src);
27
- const isText = textExtensions.includes(ext) || basename.startsWith('.');
28
+ const isText = textExtensions.includes(ext) || basename.startsWith('.') || basename === '_gitignore';
28
29
 
29
30
  if (isText) {
30
31
  let content = fs.readFileSync(src, 'utf-8');
@@ -41,29 +42,31 @@ function init({ name, templatesDir, targetDir }) {
41
42
  const dest = targetDir || path.resolve(process.cwd(), name);
42
43
 
43
44
  const existed = fs.existsSync(dest);
44
- console.log(`\n${existed ? 'Initializing' : 'Creating'} project "${name}" in ${dest}\n`);
45
+ console.log(`\n${existed ? 'Inicializando' : 'Criando'} projeto "${name}" em ${dest}\n`);
45
46
 
46
47
  const replacements = { [PLACEHOLDER]: name };
47
48
  copyDir(templatesDir, dest, replacements);
48
49
  patchProjectName(dest, name);
49
50
 
50
- try {
51
- execSync('git init', { cwd: dest, stdio: 'pipe' });
52
- execSync('git add -A', { cwd: dest, stdio: 'pipe' });
53
- execSync(`git commit -m "chore: init project ${name} via spec-first-workflow"`, {
54
- cwd: dest,
55
- stdio: 'pipe',
56
- });
57
- console.log('Git initialized with initial commit.');
58
- } catch {
59
- console.log('Git init skipped (git not available or error).');
60
- }
61
-
62
- console.log(`\nDone! Project "${name}" is ready.`);
63
- console.log('\nNext steps:');
51
+ console.log(`Pronto! Projeto "${name}" criado.`);
52
+ console.log('\nPróximos passos:');
64
53
  console.log(` 1. cd ${name}`);
65
- console.log(' 2. Create a folder in workspace/Input/ with your project files (e.g. workspace/Input/my_app/)');
66
- console.log(' 3. Run /new-project <folder-name> to start the pipeline');
54
+ console.log(' 2. Crie uma pasta em workspace/Input/ com os insumos do seu projeto');
55
+ console.log(' (ex: workspace/Input/meu_app/requisitos.md)');
56
+ console.log('');
57
+ console.log(' 3. (Opcional) Configure o backend de input/output:');
58
+ console.log(' cp sfw.config.yml.example sfw.config.yml');
59
+ console.log(' Sem isso, o framework roda 100% local (sem Confluence/etc.)');
60
+ console.log('');
61
+ console.log(' 4. (Opcional, se vai usar Confluence) Prepare o ambiente ANTES de abrir o Claude:');
62
+ console.log(' node .claude/scripts/bootstrap-confluence.js');
63
+ console.log(' Valida uvx, coleta credenciais, gera .mcp.json e pré-cacheia o MCP.');
64
+ console.log(' Evita o ciclo "abrir Claude → faltar dep → reiniciar".');
65
+ console.log('');
66
+ console.log(' 5. Abra o Claude Code no diretório do projeto e rode:');
67
+ console.log(' /sfw-start <nome-da-pasta-em-Input>');
68
+ console.log(' O framework detecta first-run automaticamente (cria docs/) vs feature');
69
+ console.log(' (atualiza docs/ via merge).');
67
70
  console.log('');
68
71
  }
69
72
 
package/lib/update.js CHANGED
@@ -18,36 +18,36 @@ function update({ templatesDir, targetDir, force }) {
18
18
  const dest = targetDir || process.cwd();
19
19
 
20
20
  if (!fs.existsSync(dest)) {
21
- console.error(`Error: directory "${dest}" does not exist.`);
22
- console.error('Run "spec-first-claude init --name=<name>" first to create a project.');
21
+ console.error(`Erro: diretório "${dest}" não existe.`);
22
+ console.error('Rode "spec-first-claude init --name=<nome>" primeiro pra criar o projeto.');
23
23
  process.exit(1);
24
24
  }
25
25
 
26
26
  const claudeDir = path.join(dest, '.claude');
27
27
  if (!fs.existsSync(claudeDir)) {
28
- console.error('Error: not a spec-first project (missing .claude/ directory).');
29
- console.error('Run "spec-first-claude init --name=<name>" first.');
28
+ console.error('Erro: não é um projeto spec-first (pasta .claude/ não encontrada).');
29
+ console.error('Rode "spec-first-claude init --name=<nome>" primeiro.');
30
30
  process.exit(1);
31
31
  }
32
32
 
33
- console.log(`\nUpdating project in ${dest}\n`);
33
+ console.log(`\nAtualizando projeto em ${dest}\n`);
34
34
 
35
35
  const stats = { added: [], updated: [], skipped: 0 };
36
36
  syncDir(templatesDir, dest, force, stats, dest);
37
37
 
38
38
  console.log('');
39
39
  if (stats.added.length > 0) {
40
- console.log(`Added (${stats.added.length}):`);
40
+ console.log(`Adicionados (${stats.added.length}):`);
41
41
  for (const f of stats.added) console.log(` + ${f}`);
42
42
  }
43
43
  if (stats.updated.length > 0) {
44
- console.log(`Updated (${stats.updated.length}):`);
44
+ console.log(`Atualizados (${stats.updated.length}):`);
45
45
  for (const f of stats.updated) console.log(` ~ ${f}`);
46
46
  }
47
47
  if (stats.added.length === 0 && stats.updated.length === 0) {
48
- console.log('Already up to date no new files to add.');
48
+ console.log(' está atualizadonenhum arquivo novo pra adicionar.');
49
49
  } else {
50
- console.log(`\n${stats.added.length} added, ${stats.updated.length} updated, ${stats.skipped} unchanged`);
50
+ console.log(`\n${stats.added.length} adicionado(s), ${stats.updated.length} atualizado(s), ${stats.skipped} inalterado(s)`);
51
51
  }
52
52
  console.log('');
53
53
  }
@@ -56,7 +56,8 @@ function syncDir(src, dest, force, stats, root) {
56
56
  fs.mkdirSync(dest, { recursive: true });
57
57
  for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
58
58
  const srcPath = path.join(src, entry.name);
59
- const destPath = path.join(dest, entry.name);
59
+ const destName = entry.name === '_gitignore' ? '.gitignore' : entry.name;
60
+ const destPath = path.join(dest, destName);
60
61
  if (entry.isDirectory()) {
61
62
  syncDir(srcPath, destPath, force, stats, root);
62
63
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spec-first-claude",
3
- "version": "0.5.0-beta.9",
3
+ "version": "0.6.0-beta.10",
4
4
  "description": "Spec-first workflow kit for Claude Code — AI-driven development with specs, not guesswork",
5
5
  "bin": {
6
6
  "spec-first-claude": "bin/cli.js"