spec-first-copilot 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 (55) hide show
  1. package/README.md +43 -38
  2. package/bin/cli.js +13 -13
  3. package/lib/init.js +23 -20
  4. package/lib/update.js +12 -10
  5. package/package.json +1 -1
  6. package/templates/.github/CHANGELOG.md +460 -112
  7. package/templates/.github/adapters/SETUP.md +6 -6
  8. package/templates/.github/adapters/confluence.md +6 -6
  9. package/templates/.github/adapters/errors.md +6 -6
  10. package/templates/.github/adapters/filesystem.md +7 -7
  11. package/templates/.github/adapters/interface.md +8 -8
  12. package/templates/.github/adapters/naming.md +25 -25
  13. package/templates/.github/adapters/registry.md +5 -5
  14. package/templates/.github/agents/db-coder.md +165 -165
  15. package/templates/.github/agents/doc-writer.md +21 -16
  16. package/templates/.github/agents/infra-coder.md +341 -341
  17. package/templates/.github/agents/security-reviewer.md +153 -153
  18. package/templates/.github/copilot-instructions.md +262 -221
  19. package/templates/.github/instructions/docs.instructions.md +145 -123
  20. package/templates/.github/instructions/sensitive-files.instructions.md +32 -32
  21. package/templates/.github/rules.md +4 -4
  22. package/templates/.github/scripts/bootstrap-confluence.js +289 -0
  23. package/templates/.github/skills/sf-design/SKILL.md +216 -209
  24. package/templates/.github/skills/sf-dev/SKILL.md +351 -354
  25. package/templates/.github/skills/sf-discovery/SKILL.md +10 -1
  26. package/templates/.github/skills/sf-extract/SKILL.md +199 -234
  27. package/templates/.github/skills/sf-load/SKILL.md +206 -116
  28. package/templates/.github/skills/sf-mcp/SKILL.md +385 -0
  29. package/templates/.github/skills/sf-merge-docs/SKILL.md +100 -0
  30. package/templates/.github/skills/sf-plan/SKILL.md +128 -180
  31. package/templates/.github/skills/sf-publish/SKILL.md +143 -0
  32. package/templates/.github/skills/sf-start/SKILL.md +145 -0
  33. package/templates/.github/templates/estrutura/apiContracts.template.md +18 -10
  34. package/templates/.github/templates/estrutura/architecture.template.md +19 -9
  35. package/templates/.github/templates/estrutura/conventions.template.md +29 -19
  36. package/templates/.github/templates/estrutura/decisions.template.md +16 -8
  37. package/templates/.github/templates/estrutura/domain.template.md +25 -13
  38. package/templates/.github/templates/feature/PRD.template.md +286 -256
  39. package/templates/.github/templates/feature/Progresso.template.md +141 -136
  40. package/templates/.github/templates/feature/backlog-extraido.template.md +11 -9
  41. package/templates/.github/templates/feature/context.template.md +19 -13
  42. package/templates/.github/templates/feature/extract-log.template.md +3 -2
  43. package/templates/.github/templates/feature/projetos.template.yaml +29 -23
  44. package/templates/.github/templates/feature/sdd.template.md +365 -178
  45. package/templates/.github/templates/global/progresso_global.template.md +10 -10
  46. package/templates/.github/templates/specs/brief.template.md +20 -8
  47. package/templates/.github/templates/specs/contracts.template.md +92 -33
  48. package/templates/.github/templates/specs/scenarios.template.md +75 -37
  49. package/templates/.github/templates/specs/tasks.template.md +63 -61
  50. package/templates/_gitignore +35 -0
  51. package/templates/sfw.config.yml.example +20 -4
  52. package/templates/.github/skills/sf-feature/SKILL.md +0 -130
  53. package/templates/.github/skills/sf-merge-delta/SKILL.md +0 -145
  54. package/templates/.github/skills/sf-new-project/SKILL.md +0 -128
  55. package/templates/.github/templates/feature/TRD.template.md +0 -204
package/README.md CHANGED
@@ -6,7 +6,7 @@ Kit completo para desenvolvimento **spec-first** com [GitHub Copilot](https://gi
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
@@ -49,20 +49,25 @@ MeuProjeto/
49
49
  ├── .github/ <- AI OPERATIONAL CONFIG
50
50
  │ ├── copilot-instructions.md <- Regras globais pro agente
51
51
  │ ├── rules.md <- Regras de desenvolvimento
52
+ │ ├── CHANGELOG.md <- Historico do framework
52
53
  │ ├── instructions/ <- Regras por contexto
53
- │ ├── templates/ <- 15 templates do workflow
54
- │ │ ├── feature/ <- PRD, TRD, SDD, tasks, etc.
55
- │ │ ├── estrutura/ <- 5 templates de estado do sistema
54
+ │ ├── templates/ <- Templates do workflow
55
+ │ │ ├── feature/ <- PRD, SDD, context, extract-log, Progresso, backlog, projetos.yaml
56
+ │ │ ├── specs/ <- brief, contracts, scenarios, tasks (projecoes pro agent)
57
+ │ │ ├── estrutura/ <- 5 templates de sintese cross-feature
56
58
  │ │ └── global/ <- Progresso global
57
- │ ├── skills/ <- 9 skills do workflow
58
- ├── sf-setup-projeto/
59
- │ │ ├── sf-feature/
59
+ │ ├── adapters/ <- SourceAdapter + ConfluenceAdapter + FilesystemAdapter
60
+ │ ├── skills/ <- 11 skills do workflow
61
+ │ │ ├── sf-mcp/
62
+ │ │ ├── sf-load/
63
+ │ │ ├── sf-publish/
64
+ │ │ ├── sf-start/ <- entrada unica (substitui sf-new-project + sf-feature)
60
65
  │ │ ├── sf-discovery/
61
66
  │ │ ├── sf-extract/
62
67
  │ │ ├── sf-design/
63
68
  │ │ ├── sf-plan/
64
69
  │ │ ├── sf-dev/
65
- │ │ ├── sf-merge-delta/
70
+ │ │ ├── sf-merge-docs/ <- renomeado de sf-merge-delta
66
71
  │ │ └── sf-session-finish/
67
72
  │ └── agents/ <- 7 agentes especializados
68
73
  │ ├── backend-coder.md <- .NET 8 / C#
@@ -72,22 +77,23 @@ MeuProjeto/
72
77
  │ ├── doc-writer.md <- Documentacao
73
78
  │ ├── reviewer.md <- Code review
74
79
  │ └── security-reviewer.md <- Auditoria de seguranca
75
- ├── docs/ <- SYSTEM KNOWLEDGE (gerado pelo /sf-design)
80
+ ├── docs/ <- SINTESE CROSS-FEATURE (atualizada pelo /sf-merge-docs)
76
81
  │ ├── architecture.md <- Containers, stack, ambientes, deploy
77
82
  │ ├── domain.md <- Visao de negocio + modelo de dados
78
83
  │ ├── conventions.md <- Auth, authz, LGPD, env vars, monitoramento
79
84
  │ ├── apiContracts.md <- Rotas, paginacao, erros, catalogo de endpoints
80
- ├── decisions.md <- ADRs
81
- │ └── specs/ <- Especs por feature (projecoes do SDD, pro agent)
82
- └── {nome}/
83
- ├── brief.md <- Problema/Solucao
84
- ├── contracts.md <- Dados/API/Integracoes
85
- ├── scenarios.md <- Fluxos/UI/CAs
86
- └── tasks.md <- Tabela unica com coluna Area
87
- ├── workspace/ <- TEAM CONTENT (futuro wiki)
88
- │ ├── Input/ <- Jogue seus insumos aqui
89
- │ │ └── setup_projeto/ <- Insumos do bootstrap
90
- │ └── Output/ <- Docs narrativos pro humano (PRD, TRD, SDD, Progresso)
85
+ └── decisions.md <- ADRs (append-only)
86
+ ├── specs/ <- AGENT CONTRACTS (projecoes do SDD pro coder)
87
+ └── {nome}/
88
+ ├── brief.md <- Problema/Solucao (SDD §1+§2+§10)
89
+ ├── contracts.md <- Sistema + Áreas tocadas (SDD §3-§7)
90
+ ├── scenarios.md <- Fluxos/UI/CAs (SDD §5.2+§8+§9)
91
+ └── tasks.md <- Tabela unica com coluna Area
92
+ ├── workspace/ <- TEAM CONTENT
93
+ │ ├── Input/ <- Jogue seus insumos aqui (nome livre)
94
+ │ │ └── {nome}/ <- ex: app_barbearia, feat_login
95
+ │ └── Output/ <- Docs narrativos pro humano (PRD, SDD, Progresso)
96
+ ├── sfw.config.yml.example <- Manifesto de adapters (input/output)
91
97
  └── .gitignore
92
98
  ```
93
99
 
@@ -99,7 +105,8 @@ MeuProjeto/
99
105
  cd MeuProjeto
100
106
  ```
101
107
 
102
- 2. Jogue seus insumos em `workspace/Input/setup_projeto/` — qualquer formato:
108
+ 2. Jogue seus insumos em `workspace/Input/<nome>/` — qualquer formato.
109
+ `<nome>` e livre: `app_barbearia`, `bootstrap`, `feat_login`, `bug_checkout`, etc.
103
110
  - `.md`, `.txt` (descricoes, requisitos, decisoes)
104
111
  - `.sql` (modelagem de banco)
105
112
  - `.csv`, `.xml`, `.html` (dados, configs)
@@ -107,40 +114,38 @@ MeuProjeto/
107
114
 
108
115
  3. Abra o VS Code com Copilot Chat e rode:
109
116
  ```
110
- /sf-setup-projeto
117
+ /sf-start <nome>
111
118
  ```
112
119
 
113
- 4. O pipeline comeca. A IA vai:
114
- - Extrair um TRD dos seus insumos
115
- - Parar e pedir sua aprovacao
120
+ 4. O pipeline comeca. A IA detecta automaticamente se e first-run (docs/ ausente)
121
+ ou feature (docs/ ja existe). Nao ha skills diferentes pra setup vs feature.
122
+
123
+ - Extrai PRD dos seus insumos (pode ser empty em scopes puro-tecnicos)
124
+ - Para e pede sua aprovacao
116
125
  - Depois voce roda `/sf-design`, `/sf-plan`, `/sf-dev` na sequencia
117
126
 
118
127
  ## Pipeline completo
119
128
 
120
129
  ```
121
- workspace/Input/ (seus arquivos)
130
+ workspace/Input/<nome>/ (seus arquivos)
122
131
  |
123
132
  v
124
- /sf-setup-projeto --> /sf-extract --> TRD (voce revisa e aprova)
125
- |
126
- v
127
- /sf-design --> SDD + docs/ (5 arquivos)
133
+ /sf-start <nome> --> /sf-extract --> PRD (voce revisa e aprova)
134
+ |
135
+ v
136
+ /sf-design --> SDD + docs/ (first-run: cria 5 arquivos)
137
+ (feature: gera só §Área-X + §11 delta)
128
138
  |
129
139
  v
130
140
  /sf-plan --> tasks + Progresso.md
131
141
  |
132
142
  v
133
143
  /sf-dev --> codigo nos repos
134
- |
135
- v
136
- (merge-delta automatico)
144
+ + /sf-merge-docs automatico
145
+ (aplica §11 em docs/)
137
146
  ```
138
147
 
139
- Para features (apos o setup):
140
-
141
- ```
142
- /sf-feature nome --> /sf-extract --> PRD --> /sf-design --> /sf-plan --> /sf-dev (inclui merge-delta)
143
- ```
148
+ Mesmo comando pra bootstrap e feature — `first_run` e derivado da ausencia/presenca de `docs/`.
144
149
 
145
150
  ## Opcoes do CLI
146
151
 
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-copilot init --name=<project-name> [--target=<path>]');
13
- console.log(' spec-first-copilot update [--target=<path>] [--force]');
11
+ console.log('Uso:');
12
+ console.log(' spec-first-copilot init --name=<nome-do-projeto> [--target=<caminho>]');
13
+ console.log(' spec-first-copilot 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 skills/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 skills/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 /sf-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 VS Code:');
62
+ console.log(' node .github/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 Copilot → faltar dep → reiniciar VS Code".');
65
+ console.log('');
66
+ console.log(' 5. Abra o VS Code com Copilot Chat e rode:');
67
+ console.log(' /sf-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
@@ -20,37 +20,38 @@ function update({ templatesDir, targetDir, force }) {
20
20
  const dest = targetDir || process.cwd();
21
21
 
22
22
  if (!fs.existsSync(dest)) {
23
- console.error(`Error: directory "${dest}" does not exist.`);
24
- console.error('Run "spec-first-copilot init --name=<name>" first to create a project.');
23
+ console.error(`Erro: diretório "${dest}" não existe.`);
24
+ console.error('Rode "spec-first-copilot init --name=<nome>" primeiro pra criar o projeto.');
25
25
  process.exit(1);
26
26
  }
27
27
 
28
28
  const githubDir = path.join(dest, '.github');
29
29
  if (!fs.existsSync(githubDir)) {
30
- console.error('Error: not a spec-first project (missing .github/ directory).');
31
- console.error('Run "spec-first-copilot init --name=<name>" first.');
30
+ console.error('Erro: não é um projeto spec-first (pasta .github/ não encontrada).');
31
+ console.error('Rode "spec-first-copilot init --name=<nome>" primeiro.');
32
32
  process.exit(1);
33
33
  }
34
34
 
35
- console.log(`\nUpdating project in ${dest}\n`);
35
+ console.log(`\nAtualizando projeto em ${dest}\n`);
36
36
 
37
37
  const stats = { added: [], updated: [], skipped: 0 };
38
38
  syncDir(templatesDir, dest, force, stats, dest);
39
39
 
40
40
  console.log('');
41
41
  if (stats.added.length > 0) {
42
- console.log(`Added (${stats.added.length}):`);
42
+ console.log(`Adicionados (${stats.added.length}):`);
43
43
  for (const f of stats.added) console.log(` + ${f}`);
44
44
  }
45
45
  if (stats.updated.length > 0) {
46
- console.log(`Updated (${stats.updated.length}):`);
46
+ console.log(`Atualizados (${stats.updated.length}):`);
47
47
  for (const f of stats.updated) console.log(` ~ ${f}`);
48
48
  }
49
49
  if (stats.added.length === 0 && stats.updated.length === 0) {
50
- console.log('Already up to date no new files to add.');
50
+ console.log(' está atualizadonenhum arquivo novo pra adicionar.');
51
51
  } else {
52
- console.log(`\n${stats.added.length} added, ${stats.updated.length} updated, ${stats.skipped} unchanged`);
52
+ console.log(`\n${stats.added.length} adicionado(s), ${stats.updated.length} atualizado(s), ${stats.skipped} inalterado(s)`);
53
53
  }
54
+
54
55
  console.log('');
55
56
  }
56
57
 
@@ -58,7 +59,8 @@ function syncDir(src, dest, force, stats, root) {
58
59
  fs.mkdirSync(dest, { recursive: true });
59
60
  for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
60
61
  const srcPath = path.join(src, entry.name);
61
- const destPath = path.join(dest, entry.name);
62
+ const destName = entry.name === '_gitignore' ? '.gitignore' : entry.name;
63
+ const destPath = path.join(dest, destName);
62
64
  if (entry.isDirectory()) {
63
65
  syncDir(srcPath, destPath, force, stats, root);
64
66
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spec-first-copilot",
3
- "version": "0.5.0-beta.9",
3
+ "version": "0.6.0-beta.10",
4
4
  "description": "Spec-first workflow kit for GitHub Copilot — AI-driven development with specs, not guesswork",
5
5
  "bin": {
6
6
  "spec-first-copilot": "bin/cli.js"