spec-first-copilot 0.5.0-beta.7 → 0.5.0-beta.9

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/lib/update.js CHANGED
@@ -12,6 +12,7 @@ const FRAMEWORK_DIRS = [
12
12
  const FRAMEWORK_FILES = [
13
13
  path.join('.github', 'rules.md'),
14
14
  path.join('.github', 'copilot-instructions.md'),
15
+ path.join('.github', 'CHANGELOG.md'),
15
16
  'sfw.config.yml.example',
16
17
  ];
17
18
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spec-first-copilot",
3
- "version": "0.5.0-beta.7",
3
+ "version": "0.5.0-beta.9",
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"
@@ -0,0 +1,112 @@
1
+ # SFW Changelog — spec-first-copilot
2
+
3
+ > Este arquivo é atualizado automaticamente pelo `spec-first-copilot update`.
4
+ > O agent deve ler este arquivo quando o usuário perguntar sobre mudanças,
5
+ > funcionalidades novas, ou o que está disponível no framework.
6
+ >
7
+ > **Não editar manualmente** — será sobrescrito no próximo update.
8
+
9
+ ---
10
+
11
+ ## 0.5.0-beta.7 (2026-04-12)
12
+
13
+ ### Novo: Comando `/sf-load <nome>`
14
+ Puxa insumos do backend configurado (Confluence ou filesystem) para `workspace/Input/{nome}/`.
15
+ - Busca o scope pelo nome no backend (match exato)
16
+ - Desce recursivamente na árvore (Confluence `get_page_children` é apenas direto — `/sf-load` faz loop)
17
+ - Baixa conteúdo + attachments
18
+ - Log incremental em `.ai/sf-load-log.md` (NOVO/MODIFICADO/INALTERADO via sha256)
19
+ - Idempotente — rodar N vezes sem mudanças no backend não altera nada
20
+ - Referência: `.github/commands/sf-load.md`
21
+
22
+ ### Novo: Adapter layer (Confluence + Filesystem)
23
+ Pipeline agora é backend-agnóstico via adapters plugáveis.
24
+ - **ConfluenceAdapter** — fala com Confluence via MCP `sooperset/mcp-atlassian`
25
+ - **FilesystemAdapter** — lê/escreve direto no disco (também serve como mock pra testes)
26
+ - Configurado em `sfw.config.yml` (copiar de `sfw.config.yml.example`)
27
+ - Interface: `.github/adapters/interface.md` (7 métodos)
28
+ - Erros tipados: `.github/adapters/errors.md` (6 classes)
29
+ - Naming engine: `.github/adapters/naming.md` (placeholders `{scope}`, `{type}`)
30
+ - Registry: `.github/adapters/registry.md`
31
+ - Setup guide: `.github/adapters/SETUP.md` (passo a passo de MCP + Confluence)
32
+
33
+ ### Novo: `sfw.config.yml`
34
+ Manifesto do projeto que define de onde vêm e pra onde vão os artefatos.
35
+ - `input.adapter` — de onde puxar insumos (`confluence` ou `filesystem`)
36
+ - `output.targets[].mode` — ligar/desligar publish (`auto`, `manual`, `off`)
37
+ - `naming.output_container` — template do nome da subpasta no Output (ex: `out_{scope}`)
38
+ - `naming.output_artifact` — template do nome do artefato (ex: `{scope} - {type}`)
39
+ - Copiar `sfw.config.yml.example` e preencher. Zero segredos neste arquivo.
40
+
41
+ ### Novo: `SETUP.md` — Guia de configuração
42
+ Guia passo a passo em `.github/adapters/SETUP.md`:
43
+ - Setup Confluence: uvx, .mcp.json, token Atlassian, space key, page IDs
44
+ - Setup 100% local (filesystem, zero dependências)
45
+ - Como ligar/desligar Confluence via `mode: auto|manual|off`
46
+ - Troubleshooting: tabela com todos os gotchas conhecidos
47
+ - **IMPORTANTE**: Confluence NÃO é CLI. Acesso via MCP tools prefixadas `mcp__atlassian__confluence_*`
48
+
49
+ ### Novo: CLI `update`
50
+ ```bash
51
+ npx spec-first-copilot update # adiciona novos, atualiza framework
52
+ npx spec-first-copilot update --force # sobrescreve tudo incluindo copilot-instructions.md
53
+ ```
54
+ Atualiza projeto existente sem perder arquivos do usuário.
55
+
56
+ ### Breaking: `/sf-setup-projeto` → `/sf-new-project <nome>`
57
+ - Antes: `/sf-setup-projeto` era hardcoded pra pasta `setup_projeto`
58
+ - Agora: `/sf-new-project <nome>` recebe o nome como argumento (simétrico com `/sf-feature <nome>`)
59
+ - `/sf-new-project` gera TRD (bootstrap técnico), `/sf-feature` gera PRD (feature)
60
+ - **Não existe mais pasta mágica** — usuário nomeia livremente em `workspace/Input/`
61
+ - O antigo `setup-projeto.md` foi removido. Usar `new-project.md`
62
+
63
+ ### Breaking: `{sequence}` removido
64
+ - Antes: todo item tinha prefixo numérico `001 - ` pra unicidade no Confluence
65
+ - Agora: usuário nomeia livremente, agent segue o nome do Input
66
+ - Naming simplificado: só `{scope}` e `{type}` como placeholders
67
+ - Premissa: 1 space Confluence = 1 projeto (multi-projeto no mesmo space requer nomes únicos no Input)
68
+
69
+ ### Breaking: Output agrupado por scope
70
+ - Antes: artefatos flat no Output (ex: `001 - TRD setup_projeto`)
71
+ - Agora: subpasta por scope (ex: `out_app_barbearia/app_barbearia - TRD`)
72
+ - Container configurável via `naming.output_container` (default: `out_{scope}`)
73
+ - Artifact configurável via `naming.output_artifact` (default: `{scope} - {type}`)
74
+
75
+ ---
76
+
77
+ ## 0.5.0-beta.2 (2026-04-11)
78
+
79
+ ### Refactor: `docs/specs/` → `specs/` (top-level)
80
+ - Projeções do SDD (brief, contracts, scenarios, tasks) movidas pra raiz
81
+ - Regra: humano lê `workspace/Output/`, agent lê `specs/`
82
+
83
+ ### Refactor: 3-zone separation
84
+ - `.github/` = AI config (rules, templates, commands, agents)
85
+ - `docs/` = system knowledge (5 docs de sistema)
86
+ - `workspace/` = team content (Input/ + Output/)
87
+
88
+ ---
89
+
90
+ ## 0.4.0 (2026-04-10) — v1 stable
91
+
92
+ ### Funcionalidades base
93
+ - 9 commands: setup-projeto, feature, discovery, extract, design, plan, dev, merge-delta, session-finish
94
+ - 7 agents: backend-coder, frontend-coder, db-coder, infra-coder, doc-writer, reviewer, security-reviewer
95
+ - Templates: PRD, TRD, SDD, tasks, Progresso, context, extract-log, backlog, projetos.yaml
96
+ - Templates de estrutura: architecture, domain, conventions, apiContracts, decisions
97
+ - Pipeline: extract → design → plan → dev com checkpoints de aprovação
98
+ - Delta Specs (SDD §11) + merge-delta automático
99
+ - Security Reviewer como gate pós-dev
100
+ - Multi-repo via projetos.yaml
101
+ - Entregáveis contínuos (fases de entrega)
102
+
103
+ ---
104
+
105
+ ## Como usar este arquivo
106
+
107
+ Se o usuário perguntar:
108
+ - **"O que tem de novo?"** → ler a versão mais recente acima
109
+ - **"Como uso o /sf-load?"** → apontar pra `.github/commands/sf-load.md`
110
+ - **"Como configuro Confluence?"** → apontar pra `.github/adapters/SETUP.md`
111
+ - **"O que é adapter?"** → apontar pra `.github/adapters/interface.md`
112
+ - **"O que mudou de setup-projeto?"** → seção "Breaking" do 0.5.0-beta.7
@@ -58,38 +58,76 @@ Ler `sfw.config.yml` e extrair:
58
58
  4. Anotar scope_path
59
59
  ```
60
60
 
61
- ### 3. Trazer conteúdo recursivamente
61
+ ### 3. Trazer conteúdo — RECURSIVO ATÉ O ÚLTIMO NÍVEL, FLAT LOCAL
62
+
63
+ > **3 REGRAS INVIOLÁVEIS:**
64
+ > 1. **Descer até o último nível** — se uma page tem filhas, e as filhas têm netas, TODAS devem ser trazidas. `get_page_children` retorna só 1 nível — o agent DEVE fazer loop recursivo.
65
+ > 2. **Local é flat** — todos os arquivos ficam soltos em `workspace/Input/{nome}/`, SEM subpastas por nível. A hierarquia do Confluence NÃO é replicada localmente.
66
+ > 3. **Refletir 100% do externo** — tudo que existe no backend (pages, attachments) DEVE existir em `workspace/Input/{nome}/`. Se falta algo, o `/sf-load` está errado.
62
67
 
63
68
  **Para Confluence**:
64
69
 
65
70
  ```
66
- function loadScope(pageId, localDir):
67
- // Baixar conteúdo da page-mãe
68
- page = mcp__atlassian__confluence_get_page(page_id=pageId, convert_to_markdown=true)
69
- salvar page.content em {localDir}/_parent.md (ou {titulo_sanitizado}.md)
70
- registrar no load-log: pageId, title, version, sha256(content)
71
-
72
- // Baixar attachments (se include_attachments=true)
73
- attachments = mcp__atlassian__confluence_get_attachments(page_id=pageId)
74
- para cada attachment:
75
- bytes = mcp__atlassian__confluence_download_attachment(page_id=pageId, filename=attachment.title)
76
- salvar em {localDir}/attachments/{filename}
77
- registrar no load-log
78
-
79
- // Recursão nos filhos
71
+ function loadScope(pageId, targetDir):
72
+ // PASSO 1: Coletar TODAS as pages da árvore (recursivo)
73
+ allPages = []
74
+ collectAllPages(pageId, allPages)
75
+
76
+ // PASSO 2: Baixar conteúdo de CADA page como arquivo flat
77
+ para cada page em allPages:
78
+ content = mcp__atlassian__confluence_get_page(page_id=page.id, convert_to_markdown=true)
79
+ filename = sanitize(page.title) + ".md"
80
+ salvar content em {targetDir}/{filename} // ← FLAT, sem subpastas
81
+ registrar no load-log: page.id, page.title, page.version, sha256(content), filename
82
+
83
+ // PASSO 3: Baixar attachments de CADA page (se include_attachments=true)
84
+ para cada page em allPages:
85
+ attachments = mcp__atlassian__confluence_get_attachments(page_id=page.id)
86
+ para cada att em attachments:
87
+ bytes = mcp__atlassian__confluence_download_attachment(page_id=page.id, filename=att.title)
88
+ salvar em {targetDir}/{att.title} // ← FLAT junto com os .md
89
+ registrar no load-log
90
+
91
+ function collectAllPages(pageId, result):
92
+ // get_page_children retorna APENAS filhos diretos — por isso o loop recursivo
80
93
  children = mcp__atlassian__confluence_get_page_children(page_id=pageId)
81
- para cada child:
82
- childDir = {localDir}/{sanitize(child.title)}
83
- mkdir childDir
84
- loadScope(child.id, childDir) // recursão
94
+ para cada child em children:
95
+ result.push(child) // adiciona o filho
96
+ collectAllPages(child.id, result) // desce nos netos, bisnetos, etc.
97
+ ```
98
+
99
+ **Exemplo concreto — Confluence tem esta árvore:**
100
+ ```
101
+ app_barbearia (page raiz do scope)
102
+ ├── Requisitos funcionais
103
+ │ ├── Regras de negocio
104
+ │ │ └── Neta da pagina ← 3º nível!
105
+ │ └── Jornadas
106
+ ├── Stack tecnica
107
+ └── attachment: diagrama.png
85
108
  ```
86
109
 
110
+ **Resultado local em `workspace/Input/app_barbearia/` — TUDO FLAT:**
111
+ ```
112
+ workspace/Input/app_barbearia/
113
+ ├── app_barbearia.md ← conteúdo da page raiz
114
+ ├── requisitos_funcionais.md ← filho
115
+ ├── regras_de_negocio.md ← neto
116
+ ├── neta_da_pagina.md ← bisneto (3º nível!)
117
+ ├── jornadas.md ← filho
118
+ ├── stack_tecnica.md ← filho
119
+ └── diagrama.png ← attachment
120
+ ```
121
+
122
+ **Nenhuma subpasta.** Não importa quantos níveis a árvore do Confluence tem — local é flat.
123
+
87
124
  **Para Filesystem**:
88
125
 
89
126
  ```
90
- function loadScope(sourcePath, localDir):
91
- // Se source == localDir → no-op (input já é local)
92
- // Senão: copiar recursivamente sourcePath localDir
127
+ function loadScope(sourcePath, targetDir):
128
+ // Se source == targetDir → no-op (input já é local)
129
+ // Senão: copiar TODOS os arquivos recursivamente pra targetDir (flat)
130
+ // Subpastas do source viram arquivos flat no target
93
131
  // Calcular sha256 de cada arquivo pra load-log
94
132
  ```
95
133
 
@@ -102,9 +140,13 @@ Formato append-only:
102
140
 
103
141
  | Item ID | Title | Version | SHA256 | Local Path | Status |
104
142
  |---------|-------|---------|--------|------------|--------|
105
- | 294950 | setup_projeto | 3 | a3f5... | workspace/Input/app_barbearia/_parent.md | NOVO |
106
- | 557057 | brief fullstack | 1 | 9fc3... | workspace/Input/app_barbearia/brief_fullstack.md | NOVO |
107
- | att:diagram.png | diagram.png | | 7d2e... | workspace/Input/app_barbearia/attachments/diagram.png | NOVO |
143
+ | 294950 | app_barbearia | 3 | a3f5... | workspace/Input/app_barbearia/app_barbearia.md | NOVO |
144
+ | 491572 | Requisitos funcionais | 2 | 8b1c... | workspace/Input/app_barbearia/requisitos_funcionais.md | NOVO |
145
+ | 491573 | Regras de negocio | 1 | 4d2a... | workspace/Input/app_barbearia/regras_de_negocio.md | NOVO |
146
+ | 491574 | Neta da pagina | 1 | 7f3e... | workspace/Input/app_barbearia/neta_da_pagina.md | NOVO |
147
+ | 491575 | Jornadas | 1 | 9c5b... | workspace/Input/app_barbearia/jornadas.md | NOVO |
148
+ | 491576 | Stack tecnica | 1 | 2e8d... | workspace/Input/app_barbearia/stack_tecnica.md | NOVO |
149
+ | att:diagrama.png | diagrama.png | — | 7d2e... | workspace/Input/app_barbearia/diagrama.png | NOVO |
108
150
  ```
109
151
 
110
152
  **Se `incremental: true`** (default):
@@ -138,8 +180,10 @@ Log salvo em .ai/sf-load-log.md
138
180
  - O `/sf-load` **nunca modifica o backend** — só lê
139
181
  - O `/sf-load` **nunca deleta arquivos locais** — se algo sumiu do backend,
140
182
  marca como REMOVIDO no log mas mantém o arquivo local
141
- - Attachments são salvos em subpasta `attachments/` dentro do scope
183
+ - Attachments ficam flat junto com os .md (sem subpasta `attachments/`)
142
184
  - Nomes de arquivo são sanitizados: espaços → `_`, caracteres especiais removidos
185
+ - **Estrutura local é FLAT** — não replica hierarquia do backend. Todos os arquivos soltos na mesma pasta
186
+ - **Recursão é total** — desce até o último nível. Se `get_page_children` retornou filhos, DESCER em cada um
143
187
 
144
188
  ## Erros
145
189