spec-first-claude 0.6.0-beta.8 → 0.7.0-beta.1
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/bin/cli.js +13 -13
- package/lib/init.js +19 -7
- package/lib/update.js +9 -9
- package/package.json +1 -1
- package/templates/.claude/CHANGELOG.md +122 -0
- package/templates/.claude/adapters/SETUP.md +3 -3
- package/templates/.claude/adapters/filesystem.md +2 -2
- package/templates/.claude/adapters/naming.md +1 -1
- package/templates/.claude/adapters/registry.md +2 -2
- package/templates/.claude/agents/backend-coder.md +215 -215
- package/templates/.claude/agents/db-coder.md +5 -5
- package/templates/.claude/agents/doc-writer.md +32 -19
- package/templates/.claude/agents/frontend-coder.md +222 -222
- package/templates/.claude/agents/infra-coder.md +341 -341
- package/templates/.claude/agents/reviewer.md +99 -99
- package/templates/.claude/agents/security-reviewer.md +5 -5
- package/templates/.claude/commands/design.md +101 -157
- package/templates/.claude/commands/dev.md +24 -19
- package/templates/.claude/commands/extract.md +118 -143
- package/templates/.claude/commands/load.md +5 -5
- package/templates/.claude/commands/mcp.md +1 -1
- package/templates/.claude/commands/merge-docs.md +109 -58
- package/templates/.claude/commands/plan.md +80 -57
- package/templates/.claude/commands/publish.md +4 -4
- package/templates/.claude/commands/sfw-start.md +101 -55
- package/templates/.claude/scripts/bootstrap-confluence.js +101 -35
- package/templates/.claude/templates/feature/PRD.template.md +279 -286
- package/templates/.claude/templates/feature/TRD.template.md +358 -0
- package/templates/.claude/templates/feature/context.template.md +54 -13
- package/templates/.claude/templates/feature/extract-log.template.md +19 -9
- package/templates/.claude/templates/specs/brief.template.md +11 -4
- package/templates/.claude/templates/specs/contracts.template.md +11 -5
- package/templates/.claude/templates/specs/scenarios.template.md +13 -5
- package/templates/.claude/templates/specs/tasks.template.md +11 -9
- package/templates/CLAUDE.md +43 -39
- package/templates/sfw.config.yml.example +4 -4
- package/templates/.claude/templates/feature/backlog-extraido.template.md +0 -156
- package/templates/.claude/templates/feature/sdd.template.md +0 -559
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('
|
|
12
|
-
console.log(' spec-first-claude init --name=<
|
|
13
|
-
console.log(' spec-first-claude update [--target=<
|
|
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('
|
|
16
|
-
console.log(' init
|
|
17
|
-
console.log(' update
|
|
18
|
-
console.log(' (
|
|
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('
|
|
21
|
-
console.log(' --name=<
|
|
22
|
-
console.log(' --target=<path>
|
|
23
|
-
console.log(' --force
|
|
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 só 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('
|
|
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(`\
|
|
67
|
+
console.error(`\nComando desconhecido: "${command}"`);
|
|
68
68
|
}
|
|
69
69
|
process.exit(command ? 1 : 0);
|
|
70
70
|
}
|
package/lib/init.js
CHANGED
|
@@ -42,19 +42,31 @@ function init({ name, templatesDir, targetDir }) {
|
|
|
42
42
|
const dest = targetDir || path.resolve(process.cwd(), name);
|
|
43
43
|
|
|
44
44
|
const existed = fs.existsSync(dest);
|
|
45
|
-
console.log(`\n${existed ? '
|
|
45
|
+
console.log(`\n${existed ? 'Inicializando' : 'Criando'} projeto "${name}" em ${dest}\n`);
|
|
46
46
|
|
|
47
47
|
const replacements = { [PLACEHOLDER]: name };
|
|
48
48
|
copyDir(templatesDir, dest, replacements);
|
|
49
49
|
patchProjectName(dest, name);
|
|
50
50
|
|
|
51
|
-
console.log(`
|
|
52
|
-
console.log('\
|
|
51
|
+
console.log(`Pronto! Projeto "${name}" criado.`);
|
|
52
|
+
console.log('\nPróximos passos:');
|
|
53
53
|
console.log(` 1. cd ${name}`);
|
|
54
|
-
console.log(' 2.
|
|
55
|
-
console.log('
|
|
56
|
-
console.log('
|
|
57
|
-
console.log('
|
|
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).');
|
|
58
70
|
console.log('');
|
|
59
71
|
}
|
|
60
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(`
|
|
22
|
-
console.error('
|
|
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('
|
|
29
|
-
console.error('
|
|
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(`\
|
|
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(`
|
|
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(`
|
|
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('
|
|
48
|
+
console.log('Já está atualizado — nenhum arquivo novo pra adicionar.');
|
|
49
49
|
} else {
|
|
50
|
-
console.log(`\n${stats.added.length}
|
|
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
|
}
|
package/package.json
CHANGED
|
@@ -8,6 +8,128 @@
|
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
+
## 0.7.0-beta.1 (2026-04-13) — Redesign v4 (BREAKING)
|
|
12
|
+
|
|
13
|
+
Reestruturação arquitetural baseada em feedback de uso real do v3. TRD ressuscitado
|
|
14
|
+
como peer do PRD, SDD eliminado, aprovação por persona. Pipeline continua unificado
|
|
15
|
+
via `/sfw-start`.
|
|
16
|
+
|
|
17
|
+
### Breaking
|
|
18
|
+
|
|
19
|
+
- **TRD ressuscitado** — peer do PRD, aprovado pelo dev. Não é o TRD antigo
|
|
20
|
+
transiente: agora tem papel próprio (source técnica autoritativa).
|
|
21
|
+
- **SDD eliminado** — camada intermediária desnecessária quando PRD+TRD são bem
|
|
22
|
+
estruturados. `specs/{nome}/` deriva direto de PRD+TRD. `docs/` atualizado via
|
|
23
|
+
`/merge-docs` a partir de PRD+TRD.
|
|
24
|
+
- **Aprovação por persona** — PM aprova PRD (`prd_aprovado: true`), dev aprova TRD
|
|
25
|
+
(`trd_aprovado: true`). Flags no `.context.md`. Em time pequeno, user faz as 2
|
|
26
|
+
aprovações — não pula.
|
|
27
|
+
- **Discovery obrigatório** — `/discovery` deixou de ser skill opcional e virou
|
|
28
|
+
passo obrigatório dentro do `/sfw-start`. Força entendimento antes da extração.
|
|
29
|
+
- **PRD `empty` removido** — conceito obsoleto. Agora: scope puro-técnico tem
|
|
30
|
+
`prd_existe=false`; scope puro-produto tem `trd_existe=false`. Maioria tem ambos.
|
|
31
|
+
- **backlog_extraido.md eliminado** — features futuras viram itens em PRD §11
|
|
32
|
+
Fora de Escopo com sugestão de `/sfw-start <nome>` próprio.
|
|
33
|
+
- **Schema do `.context.md` mudou**: `prd_empty` → `prd_existe` + `prd_aprovado`;
|
|
34
|
+
adicionado `trd_existe` + `trd_aprovado`. Status fluxo tem novos estados:
|
|
35
|
+
`discovery_done → extract_done → prd_approved → trd_approved → design_done`.
|
|
36
|
+
|
|
37
|
+
### Templates
|
|
38
|
+
|
|
39
|
+
- `TRD.template.md` novo — 11 seções, organizado por área (§Sistema + §Área-X)
|
|
40
|
+
- `PRD.template.md` refatorado — 13 seções puro-produto, sem conteúdo técnico
|
|
41
|
+
- `sdd.template.md` deletado
|
|
42
|
+
- `backlog-extraido.template.md` deletado
|
|
43
|
+
- `context.template.md` schema v4
|
|
44
|
+
- `extract-log.template.md` sem categorização "produto/tech" (obsoleta)
|
|
45
|
+
- `specs/*.template.md` com ORIGEM atualizada: PRD+TRD em vez de SDD
|
|
46
|
+
|
|
47
|
+
### Skills
|
|
48
|
+
|
|
49
|
+
- `/sfw-start` — 2 aprovações + discovery obrigatório
|
|
50
|
+
- `/extract` — gera PRD e/ou TRD conforme conteúdo dos insumos (Reader + Produto-Analyzer + Tech-Analyzer)
|
|
51
|
+
- `/design` — consome PRD+TRD aprovados, gera docs/ (first-run) + specs/
|
|
52
|
+
- `/merge-docs` — diff semântico PRD+TRD ↔ docs/ (agente Integrator promovido pra Opus)
|
|
53
|
+
- `/plan` — entrada PRD+TRD+specs/, tasks com `Ref TRD` em vez de `Ref SDD`
|
|
54
|
+
- `/publish` — adicionado TRD à whitelist; SDD removido
|
|
55
|
+
|
|
56
|
+
### Agents
|
|
57
|
+
|
|
58
|
+
- Doc Writer reescrito: fonte muda de "SDD §Sistema" para "PRD + TRD"
|
|
59
|
+
- Coders (backend/frontend/db/infra) e Reviewers: refs de "SDD §X" → "TRD §X" ou "specs/{nome}/"
|
|
60
|
+
|
|
61
|
+
### Migração de v3 (0.6.x) pra v4
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# 1. Atualizar kit
|
|
65
|
+
npx spec-first-claude@beta update
|
|
66
|
+
|
|
67
|
+
# 2. Para cada scope em andamento: migrar .context.md
|
|
68
|
+
# - Remover `prd_empty`
|
|
69
|
+
# - Adicionar `prd_existe`, `trd_existe`, `prd_aprovado`, `trd_aprovado`
|
|
70
|
+
# - Se scope já tem SDD: extrair conteúdo técnico pra TRD.md manual
|
|
71
|
+
|
|
72
|
+
# 3. SDDs antigos em workspace/Output/{nome}/sdd.md ficam como legado
|
|
73
|
+
# (nenhum skill v4 lê eles). Deletar quando confortável.
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Versionamento
|
|
77
|
+
|
|
78
|
+
- Bump **minor** (0.6 → 0.7) pelo breaking. v3 (`0.6.0-beta.10`) permanece no npm
|
|
79
|
+
como histórico.
|
|
80
|
+
- Publicado com tag `beta`. Promoção para `latest` apenas após validação em uso real.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 0.6.0-beta.10 (2026-04-13)
|
|
85
|
+
|
|
86
|
+
### `bootstrap-confluence.js` agora é idempotente
|
|
87
|
+
|
|
88
|
+
Script agora lê `.mcp.json` existente e reusa valores da entry `atlassian` em
|
|
89
|
+
vez de perguntar tudo de novo:
|
|
90
|
+
|
|
91
|
+
- Se `CONFLUENCE_URL` já existe: mostra URL atual, pergunta "Manter? [S/n]"
|
|
92
|
+
- Se `CONFLUENCE_USERNAME` já existe: mostra email atual, pergunta "Manter? [S/n]"
|
|
93
|
+
- Se `CONFLUENCE_API_TOKEN` já existe: mostra token mascarado (`abcd…wxyz`), pergunta "Manter? [S/n]"
|
|
94
|
+
- Default ENTER = manter. Responder `n` abre o prompt completo da informação.
|
|
95
|
+
|
|
96
|
+
Se todos os 3 campos foram mantidos: detecta que nada mudou e **não reescreve**
|
|
97
|
+
`.mcp.json` (evita dirty git). Se mudou algo: reescreve preservando outras
|
|
98
|
+
entries MCP (Supabase, GitHub, etc.).
|
|
99
|
+
|
|
100
|
+
Útil pra: reexecução após novo rebuild do MCP, rotação apenas do token, debug
|
|
101
|
+
de setup sem perder credenciais já válidas.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 0.6.0-beta.9 (2026-04-13)
|
|
106
|
+
|
|
107
|
+
### CLI em pt-BR + dica de bootstrap-confluence no init
|
|
108
|
+
|
|
109
|
+
Mensagens do CLI (`init` e `update`) traduzidas para pt-BR — usuário final é o público.
|
|
110
|
+
|
|
111
|
+
Mensagem do `init` reescrita para deixar **explícito o passo opcional de pré-setup
|
|
112
|
+
do Confluence**:
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
Pronto! Projeto "X" criado.
|
|
116
|
+
|
|
117
|
+
Próximos passos:
|
|
118
|
+
1. cd X
|
|
119
|
+
2. Crie uma pasta em workspace/Input/ com os insumos do seu projeto
|
|
120
|
+
3. (Opcional) Configure o backend de input/output:
|
|
121
|
+
cp sfw.config.yml.example sfw.config.yml
|
|
122
|
+
4. (Opcional, se vai usar Confluence) Prepare o ambiente ANTES de abrir o Claude:
|
|
123
|
+
node .claude/scripts/bootstrap-confluence.js
|
|
124
|
+
5. Abra o Claude Code e rode: /sfw-start <nome-da-pasta>
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
O passo 4 era invisível antes — só aparecia inline na "Dica" do skill `/mcp`.
|
|
128
|
+
Agora aparece logo no fim do `init`, no momento exato em que o usuário vai decidir
|
|
129
|
+
se prepara o Confluence ou não.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
11
133
|
## 0.6.0-beta.8 (2026-04-13)
|
|
12
134
|
|
|
13
135
|
### Novo: `bootstrap-confluence.js` (opcional, pré-Claude)
|
|
@@ -148,7 +148,7 @@ output:
|
|
|
148
148
|
config:
|
|
149
149
|
space_key: "ST" # ← mesmo Space Key
|
|
150
150
|
parent_page_id: "294931" # ← Page ID da page Output
|
|
151
|
-
publishes: [PRD,
|
|
151
|
+
publishes: [PRD, TRD, Progresso]
|
|
152
152
|
mode: auto # ← auto | manual | off
|
|
153
153
|
conflict_detection: version
|
|
154
154
|
approval_mechanism: label
|
|
@@ -225,7 +225,7 @@ output:
|
|
|
225
225
|
adapter: filesystem
|
|
226
226
|
config:
|
|
227
227
|
root_path: "workspace/Output"
|
|
228
|
-
publishes: [PRD,
|
|
228
|
+
publishes: [PRD, TRD, Progresso]
|
|
229
229
|
mode: auto
|
|
230
230
|
conflict_detection: hash
|
|
231
231
|
approval_mechanism: none
|
|
@@ -282,7 +282,7 @@ E coloque `mode: off` nos targets de Confluence.
|
|
|
282
282
|
config:
|
|
283
283
|
space_key: "ST"
|
|
284
284
|
parent_page_id: "294931"
|
|
285
|
-
publishes: [PRD,
|
|
285
|
+
publishes: [PRD, TRD, Progresso]
|
|
286
286
|
mode: auto
|
|
287
287
|
```
|
|
288
288
|
3. Re-rode `/extract`, `/design`, `/plan` — os artefatos locais serão publicados
|
|
@@ -259,7 +259,7 @@ output:
|
|
|
259
259
|
adapter: filesystem
|
|
260
260
|
config:
|
|
261
261
|
root_path: "./workspace/Output"
|
|
262
|
-
publishes: [PRD,
|
|
262
|
+
publishes: [PRD, TRD, Progresso]
|
|
263
263
|
mode: auto
|
|
264
264
|
conflict_detection: hash
|
|
265
265
|
approval_mechanism: none
|
|
@@ -284,7 +284,7 @@ output:
|
|
|
284
284
|
adapter: filesystem
|
|
285
285
|
config:
|
|
286
286
|
root_path: "./tests/fixtures/barbearia/actual_output"
|
|
287
|
-
publishes: [PRD,
|
|
287
|
+
publishes: [PRD, TRD, Progresso]
|
|
288
288
|
mode: auto
|
|
289
289
|
```
|
|
290
290
|
|
|
@@ -56,7 +56,7 @@ O `sfw.config.yml` define 2 templates de output:
|
|
|
56
56
|
**`output_container`** é o agrupador. No Confluence vira uma page-mãe com
|
|
57
57
|
children; no filesystem vira uma pasta.
|
|
58
58
|
|
|
59
|
-
**`output_artifact`** é o item individual (PRD,
|
|
59
|
+
**`output_artifact`** é o item individual (PRD, TRD, Progresso). No
|
|
60
60
|
Confluence é title de uma child page; no filesystem é nome de arquivo
|
|
61
61
|
(adapter adiciona `.md` automaticamente).
|
|
62
62
|
|
|
@@ -178,13 +178,13 @@ output:
|
|
|
178
178
|
config:
|
|
179
179
|
space_key: ST
|
|
180
180
|
parent_page_id: "294931"
|
|
181
|
-
publishes: [PRD,
|
|
181
|
+
publishes: [PRD, TRD, Progresso]
|
|
182
182
|
mode: auto
|
|
183
183
|
- name: local-mirror
|
|
184
184
|
adapter: filesystem
|
|
185
185
|
config:
|
|
186
186
|
root_path: "./mirror"
|
|
187
|
-
publishes: [PRD,
|
|
187
|
+
publishes: [PRD, TRD, Progresso]
|
|
188
188
|
mode: auto
|
|
189
189
|
```
|
|
190
190
|
|