spec-first-copilot 0.7.0-beta.1 → 0.7.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.
Files changed (55) hide show
  1. package/README.md +252 -167
  2. package/bin/cli.js +70 -70
  3. package/lib/init.js +92 -92
  4. package/lib/update.js +132 -132
  5. package/package.json +1 -1
  6. package/templates/.ai/memory/napkin.md +68 -68
  7. package/templates/.github/CHANGELOG.md +560 -533
  8. package/templates/.github/adapters/SETUP.md +314 -314
  9. package/templates/.github/adapters/confluence.md +295 -295
  10. package/templates/.github/adapters/errors.md +234 -234
  11. package/templates/.github/adapters/filesystem.md +353 -353
  12. package/templates/.github/adapters/interface.md +301 -301
  13. package/templates/.github/adapters/naming.md +241 -241
  14. package/templates/.github/adapters/registry.md +244 -244
  15. package/templates/.github/agents/backend-coder.md +215 -215
  16. package/templates/.github/agents/db-coder.md +165 -165
  17. package/templates/.github/agents/doc-writer.md +66 -66
  18. package/templates/.github/agents/frontend-coder.md +222 -222
  19. package/templates/.github/agents/infra-coder.md +341 -341
  20. package/templates/.github/agents/reviewer.md +99 -99
  21. package/templates/.github/agents/security-reviewer.md +153 -153
  22. package/templates/.github/copilot-instructions.md +272 -272
  23. package/templates/.github/instructions/docs.instructions.md +147 -145
  24. package/templates/.github/instructions/sensitive-files.instructions.md +32 -32
  25. package/templates/.github/rules.md +229 -229
  26. package/templates/.github/scripts/bootstrap-confluence.js +289 -289
  27. package/templates/.github/skills/sf-design/SKILL.md +161 -161
  28. package/templates/.github/skills/sf-dev/SKILL.md +204 -204
  29. package/templates/.github/skills/sf-discovery/SKILL.md +415 -415
  30. package/templates/.github/skills/sf-extract/SKILL.md +225 -225
  31. package/templates/.github/skills/sf-load/SKILL.md +296 -296
  32. package/templates/.github/skills/sf-mcp/SKILL.md +386 -386
  33. package/templates/.github/skills/sf-merge-docs/SKILL.md +152 -152
  34. package/templates/.github/skills/sf-plan/SKILL.md +152 -152
  35. package/templates/.github/skills/sf-publish/SKILL.md +144 -144
  36. package/templates/.github/skills/sf-session-finish/SKILL.md +93 -93
  37. package/templates/.github/skills/sf-start/SKILL.md +192 -192
  38. package/templates/.github/templates/estrutura/apiContracts.template.md +160 -159
  39. package/templates/.github/templates/estrutura/architecture.template.md +169 -168
  40. package/templates/.github/templates/estrutura/conventions.template.md +214 -212
  41. package/templates/.github/templates/estrutura/decisions.template.md +107 -107
  42. package/templates/.github/templates/estrutura/domain.template.md +161 -160
  43. package/templates/.github/templates/feature/PRD.template.md +279 -279
  44. package/templates/.github/templates/feature/Progresso.template.md +141 -141
  45. package/templates/.github/templates/feature/TRD.template.md +358 -358
  46. package/templates/.github/templates/feature/context.template.md +89 -89
  47. package/templates/.github/templates/feature/extract-log.template.md +49 -49
  48. package/templates/.github/templates/feature/projetos.template.yaml +79 -79
  49. package/templates/.github/templates/global/progresso_global.template.md +59 -57
  50. package/templates/.github/templates/specs/brief.template.md +66 -66
  51. package/templates/.github/templates/specs/contracts.template.md +147 -147
  52. package/templates/.github/templates/specs/scenarios.template.md +125 -125
  53. package/templates/.github/templates/specs/tasks.template.md +65 -65
  54. package/templates/_gitignore +35 -35
  55. package/templates/sfw.config.yml.example +147 -147
@@ -1,244 +1,244 @@
1
- # Adapter Registry
2
-
3
- > Como o SFW resolve `adapter: "confluence"` no `sfw.config.yml` pra uma
4
- > instância concreta de `SourceAdapter`.
5
- >
6
- > Este arquivo é a **especificação** do registry. A implementação real vive
7
- > no bootstrap do kit (quando for codada — §9.9.P0.2+).
8
-
9
- ---
10
-
11
- ## Conceito
12
-
13
- O usuário declara no manifest:
14
-
15
- ```yaml
16
- input:
17
- adapter: confluence
18
- config:
19
- space_key: ST
20
- parent_page_id: "360668"
21
- ```
22
-
23
- As skills **nunca** veem a string `"confluence"`. Elas recebem uma instância
24
- que implementa `SourceAdapter` — já configurada, já validada. O registry é
25
- a ponte entre os dois.
26
-
27
- ---
28
-
29
- ## Responsabilidades do registry
30
-
31
- 1. **Descobrir adapters disponíveis** (builtin + futuros plugins)
32
- 2. **Resolver** a string `adapter: X` na classe correta
33
- 3. **Instanciar** o adapter passando o objeto `config` do manifest
34
- 4. **Validar** chamando `adapter.validateConfig(config)` antes de devolver
35
- 5. **Falhar cedo e rápido** se o adapter não existe ou config está errado
36
-
37
- ---
38
-
39
- ## Adapters built-in no MVP
40
-
41
- | Chave no YAML | Classe | Arquivo de runbook | Status MVP |
42
- |---------------|--------|-------------------|------------|
43
- | `confluence` | `ConfluenceAdapter` | `.github/adapters/confluence.md` | P0.2 — reuso do validado em testes/barbearia |
44
- | `filesystem` | `FilesystemAdapter` | `.github/adapters/filesystem.md` | P0.2 — novo, trivial |
45
-
46
- **Apenas esses 2 no MVP.** Qualquer outro valor em `adapter:` → `ValidationError`
47
- no load do manifest.
48
-
49
- ---
50
-
51
- ## Fluxo de resolução
52
-
53
- ```
54
- 1. Skill começa (ex: /sf-load)
55
- 2. Carrega sfw.config.yml
56
- 3. Para cada seção que precisa de adapter (input, cada output.target):
57
- a. Lê string `adapter: X`
58
- b. Consulta registry: registry.get("X")
59
- - Se X não existe → ValidationError: "unknown adapter 'X' (available: confluence, filesystem)"
60
- c. Instancia: const a = new AdapterClass()
61
- d. Valida config: a.validateConfig(target.config)
62
- - Se inválido → ValidationError (propaga do adapter)
63
- e. Armazena a instância configurada em memória pra reuso durante a skill
64
- 4. Usa as instâncias via interface — nunca chama .name direto no hot path
65
- ```
66
-
67
- **Importante**: o registry é consultado **1 vez** por execução de skill.
68
- Instâncias são cached pela duração da skill. Skills que rodam em sequência
69
- (`/sf-extract` → `/sf-design`) podem re-instanciar — não há estado compartilhado
70
- entre execuções (não deveria haver, por contrato).
71
-
72
- ---
73
-
74
- ## Contrato textual do registry
75
-
76
- ```typescript
77
- interface AdapterRegistry {
78
- /**
79
- * Retorna a classe do adapter (não instancia).
80
- * @throws ValidationError se a chave não existir
81
- */
82
- get(key: string): AdapterClass;
83
-
84
- /**
85
- * Lista as chaves disponíveis. Usado em mensagens de erro.
86
- */
87
- available(): string[];
88
-
89
- /**
90
- * Registra um novo adapter. No MVP só é chamado internamente pros 2 builtin.
91
- * Plugin system (P2) usaria isso pra carregar adapters externos.
92
- */
93
- register(key: string, cls: AdapterClass): void;
94
- }
95
-
96
- interface AdapterClass {
97
- new(): SourceAdapter;
98
- /** Chave que o adapter usa no YAML — deve bater com o que está no registry */
99
- readonly adapterName: string;
100
- }
101
- ```
102
-
103
- ### Inicialização builtin (pseudo-código)
104
-
105
- ```typescript
106
- const registry = new AdapterRegistry();
107
- registry.register("confluence", ConfluenceAdapter);
108
- registry.register("filesystem", FilesystemAdapter);
109
-
110
- // quando o manifest é carregado:
111
- function resolveAdapter(section: { adapter: string; config: object }): SourceAdapter {
112
- const cls = registry.get(section.adapter); // throws se não existe
113
- const instance = new cls();
114
- instance.validateConfig(section.config); // throws se config errada
115
- return instance;
116
- }
117
- ```
118
-
119
- ---
120
-
121
- ## Declaração de config requerida (contrato por adapter)
122
-
123
- Cada adapter **documenta** (em `.github/adapters/{name}.md`) quais campos
124
- são obrigatórios e quais são opcionais na seção `config`. O registry não
125
- valida isso — delega pro `validateConfig` do adapter. Isso evita duplicação
126
- e mantém a responsabilidade localizada.
127
-
128
- **Exemplo — ConfluenceAdapter**:
129
- | Campo | Obrigatório | Tipo | Descrição |
130
- |-------|:---:|------|-----------|
131
- | `space_key` | ✅ | string | ex: `"ST"` |
132
- | `parent_page_id` | ✅ | string | ID numérico da page pai |
133
- | `recursive` | — | boolean | default `true` |
134
- | `include_attachments` | — | boolean | default `true` |
135
-
136
- **Exemplo — FilesystemAdapter**:
137
- | Campo | Obrigatório | Tipo | Descrição |
138
- |-------|:---:|------|-----------|
139
- | `root_path` | ✅ | string | path absoluto ou relativo ao projeto |
140
- | `glob` | — | string | default `**/*.md` |
141
- | `watch` | — | boolean | default `false` (watch mode é P2) |
142
-
143
- ---
144
-
145
- ## Ordem de validação no load do manifest
146
-
147
- Quando skill chama `loadConfig("sfw.config.yml")`:
148
-
149
- 1. **Parse YAML.** Erro de sintaxe → `ValidationError` (nem chama registry).
150
- 2. **Valida shape top-level.** Presença de `project`, `naming`, `input`, `output.targets[]`.
151
- 3. **Resolve `input.adapter`** via registry + `validateConfig` do adapter.
152
- 4. **Resolve cada `output.targets[i].adapter`** via registry + `validateConfig`.
153
- 5. **Valida `naming.*`** — templates precisam ser strings não-vazias; placeholders
154
- desconhecidos detectados agora (antecipa erro de runtime).
155
- 6. **Valida coerência inter-seções**: ex., `output.targets[i].mode: auto` exige
156
- `approval_mechanism` presente quando `publishes` contém PRD/SDD (artefatos
157
- com gate de aprovação).
158
-
159
- Tudo no load. Se qualquer passo falha, skill para antes de tocar backend.
160
-
161
- ---
162
-
163
- ## Config de exemplo resolvida
164
-
165
- Input YAML:
166
- ```yaml
167
- project:
168
- name: "Barbearia"
169
- input:
170
- adapter: confluence
171
- config:
172
- space_key: ST
173
- parent_page_id: "360668"
174
- output:
175
- targets:
176
- - name: confluence-mirror
177
- adapter: confluence
178
- config:
179
- space_key: ST
180
- parent_page_id: "294931"
181
- publishes: [PRD, TRD, Progresso]
182
- mode: auto
183
- - name: local-mirror
184
- adapter: filesystem
185
- config:
186
- root_path: "./mirror"
187
- publishes: [PRD, TRD, Progresso]
188
- mode: auto
189
- ```
190
-
191
- Após load:
192
- ```typescript
193
- const manifest = {
194
- project: { name: "Barbearia" },
195
- input: <ConfluenceAdapter instance, configured>,
196
- outputs: [
197
- { name: "confluence-mirror", adapter: <ConfluenceAdapter>, publishes: [...], mode: "auto" },
198
- { name: "local-mirror", adapter: <FilesystemAdapter>, publishes: [...], mode: "auto" },
199
- ],
200
- };
201
- ```
202
-
203
- Skill chama `manifest.input.listChildren(...)` e `manifest.outputs[0].adapter.update(...)`.
204
- A string `"confluence"` nunca aparece fora do registry.
205
-
206
- ---
207
-
208
- ## O que NÃO é responsabilidade do registry
209
-
210
- - **Credenciais.** Adapter lê `.mcp.json` / env var direto. Registry nem vê.
211
- - **Retry/backoff.** Cada adapter implementa. Registry devolve instância "crua".
212
- - **Logging.** Skills logam. Adapter/registry silenciam (exceto em erro).
213
- - **Connection pooling.** MVP é single-process single-skill. Se virar batch,
214
- registry pode cachear. Não agora.
215
-
216
- ---
217
-
218
- ## Futuro (P2) — Plugin system
219
-
220
- Quando aparecer o 3º caso real de backend não-builtin:
221
-
222
- 1. `sfw.config.yml` ganha seção `plugins:`:
223
- ```yaml
224
- plugins:
225
- - npm:@sfw/notion-adapter@1.2.0
226
- - file:./local-adapters/sharepoint.js
227
- ```
228
- 2. Bootstrap do kit carrega plugins antes do manifest.
229
- 3. Cada plugin exporta `{ key, class }` e chama `registry.register(...)`.
230
- 4. Interface do adapter fica estável (breaking change vira major version).
231
-
232
- **Decisão (2026-04-11)**: não implementar agora. Builtin resolve 95% dos casos
233
- e prova que a interface está certa. Plugin system vira prioridade quando um
234
- usuário real pedir.
235
-
236
- ---
237
-
238
- ## Referências
239
-
240
- - Interface: `.github/adapters/interface.md`
241
- - Erros: `.github/adapters/errors.md`
242
- - Naming: `.github/adapters/naming.md`
243
- - Manifest: `sfw.config.yml.example`
244
- - Roadmap: `planodetarefas.md §9.9.P0.2` (implementação dos builtins)
1
+ # Adapter Registry
2
+
3
+ > Como o SFW resolve `adapter: "confluence"` no `sfw.config.yml` pra uma
4
+ > instância concreta de `SourceAdapter`.
5
+ >
6
+ > Este arquivo é a **especificação** do registry. A implementação real vive
7
+ > no bootstrap do kit (quando for codada — §9.9.P0.2+).
8
+
9
+ ---
10
+
11
+ ## Conceito
12
+
13
+ O usuário declara no manifest:
14
+
15
+ ```yaml
16
+ input:
17
+ adapter: confluence
18
+ config:
19
+ space_key: ST
20
+ parent_page_id: "360668"
21
+ ```
22
+
23
+ As skills **nunca** veem a string `"confluence"`. Elas recebem uma instância
24
+ que implementa `SourceAdapter` — já configurada, já validada. O registry é
25
+ a ponte entre os dois.
26
+
27
+ ---
28
+
29
+ ## Responsabilidades do registry
30
+
31
+ 1. **Descobrir adapters disponíveis** (builtin + futuros plugins)
32
+ 2. **Resolver** a string `adapter: X` na classe correta
33
+ 3. **Instanciar** o adapter passando o objeto `config` do manifest
34
+ 4. **Validar** chamando `adapter.validateConfig(config)` antes de devolver
35
+ 5. **Falhar cedo e rápido** se o adapter não existe ou config está errado
36
+
37
+ ---
38
+
39
+ ## Adapters built-in no MVP
40
+
41
+ | Chave no YAML | Classe | Arquivo de runbook | Status MVP |
42
+ |---------------|--------|-------------------|------------|
43
+ | `confluence` | `ConfluenceAdapter` | `.github/adapters/confluence.md` | P0.2 — reuso do validado em testes/barbearia |
44
+ | `filesystem` | `FilesystemAdapter` | `.github/adapters/filesystem.md` | P0.2 — novo, trivial |
45
+
46
+ **Apenas esses 2 no MVP.** Qualquer outro valor em `adapter:` → `ValidationError`
47
+ no load do manifest.
48
+
49
+ ---
50
+
51
+ ## Fluxo de resolução
52
+
53
+ ```
54
+ 1. Skill começa (ex: /sf-load)
55
+ 2. Carrega sfw.config.yml
56
+ 3. Para cada seção que precisa de adapter (input, cada output.target):
57
+ a. Lê string `adapter: X`
58
+ b. Consulta registry: registry.get("X")
59
+ - Se X não existe → ValidationError: "unknown adapter 'X' (available: confluence, filesystem)"
60
+ c. Instancia: const a = new AdapterClass()
61
+ d. Valida config: a.validateConfig(target.config)
62
+ - Se inválido → ValidationError (propaga do adapter)
63
+ e. Armazena a instância configurada em memória pra reuso durante a skill
64
+ 4. Usa as instâncias via interface — nunca chama .name direto no hot path
65
+ ```
66
+
67
+ **Importante**: o registry é consultado **1 vez** por execução de skill.
68
+ Instâncias são cached pela duração da skill. Skills que rodam em sequência
69
+ (`/sf-extract` → `/sf-design`) podem re-instanciar — não há estado compartilhado
70
+ entre execuções (não deveria haver, por contrato).
71
+
72
+ ---
73
+
74
+ ## Contrato textual do registry
75
+
76
+ ```typescript
77
+ interface AdapterRegistry {
78
+ /**
79
+ * Retorna a classe do adapter (não instancia).
80
+ * @throws ValidationError se a chave não existir
81
+ */
82
+ get(key: string): AdapterClass;
83
+
84
+ /**
85
+ * Lista as chaves disponíveis. Usado em mensagens de erro.
86
+ */
87
+ available(): string[];
88
+
89
+ /**
90
+ * Registra um novo adapter. No MVP só é chamado internamente pros 2 builtin.
91
+ * Plugin system (P2) usaria isso pra carregar adapters externos.
92
+ */
93
+ register(key: string, cls: AdapterClass): void;
94
+ }
95
+
96
+ interface AdapterClass {
97
+ new(): SourceAdapter;
98
+ /** Chave que o adapter usa no YAML — deve bater com o que está no registry */
99
+ readonly adapterName: string;
100
+ }
101
+ ```
102
+
103
+ ### Inicialização builtin (pseudo-código)
104
+
105
+ ```typescript
106
+ const registry = new AdapterRegistry();
107
+ registry.register("confluence", ConfluenceAdapter);
108
+ registry.register("filesystem", FilesystemAdapter);
109
+
110
+ // quando o manifest é carregado:
111
+ function resolveAdapter(section: { adapter: string; config: object }): SourceAdapter {
112
+ const cls = registry.get(section.adapter); // throws se não existe
113
+ const instance = new cls();
114
+ instance.validateConfig(section.config); // throws se config errada
115
+ return instance;
116
+ }
117
+ ```
118
+
119
+ ---
120
+
121
+ ## Declaração de config requerida (contrato por adapter)
122
+
123
+ Cada adapter **documenta** (em `.github/adapters/{name}.md`) quais campos
124
+ são obrigatórios e quais são opcionais na seção `config`. O registry não
125
+ valida isso — delega pro `validateConfig` do adapter. Isso evita duplicação
126
+ e mantém a responsabilidade localizada.
127
+
128
+ **Exemplo — ConfluenceAdapter**:
129
+ | Campo | Obrigatório | Tipo | Descrição |
130
+ |-------|:---:|------|-----------|
131
+ | `space_key` | ✅ | string | ex: `"ST"` |
132
+ | `parent_page_id` | ✅ | string | ID numérico da page pai |
133
+ | `recursive` | — | boolean | default `true` |
134
+ | `include_attachments` | — | boolean | default `true` |
135
+
136
+ **Exemplo — FilesystemAdapter**:
137
+ | Campo | Obrigatório | Tipo | Descrição |
138
+ |-------|:---:|------|-----------|
139
+ | `root_path` | ✅ | string | path absoluto ou relativo ao projeto |
140
+ | `glob` | — | string | default `**/*.md` |
141
+ | `watch` | — | boolean | default `false` (watch mode é P2) |
142
+
143
+ ---
144
+
145
+ ## Ordem de validação no load do manifest
146
+
147
+ Quando skill chama `loadConfig("sfw.config.yml")`:
148
+
149
+ 1. **Parse YAML.** Erro de sintaxe → `ValidationError` (nem chama registry).
150
+ 2. **Valida shape top-level.** Presença de `project`, `naming`, `input`, `output.targets[]`.
151
+ 3. **Resolve `input.adapter`** via registry + `validateConfig` do adapter.
152
+ 4. **Resolve cada `output.targets[i].adapter`** via registry + `validateConfig`.
153
+ 5. **Valida `naming.*`** — templates precisam ser strings não-vazias; placeholders
154
+ desconhecidos detectados agora (antecipa erro de runtime).
155
+ 6. **Valida coerência inter-seções**: ex., `output.targets[i].mode: auto` exige
156
+ `approval_mechanism` presente quando `publishes` contém PRD/TRD (artefatos
157
+ com gate de aprovação).
158
+
159
+ Tudo no load. Se qualquer passo falha, skill para antes de tocar backend.
160
+
161
+ ---
162
+
163
+ ## Config de exemplo resolvida
164
+
165
+ Input YAML:
166
+ ```yaml
167
+ project:
168
+ name: "Barbearia"
169
+ input:
170
+ adapter: confluence
171
+ config:
172
+ space_key: ST
173
+ parent_page_id: "360668"
174
+ output:
175
+ targets:
176
+ - name: confluence-mirror
177
+ adapter: confluence
178
+ config:
179
+ space_key: ST
180
+ parent_page_id: "294931"
181
+ publishes: [PRD, TRD, Progresso]
182
+ mode: auto
183
+ - name: local-mirror
184
+ adapter: filesystem
185
+ config:
186
+ root_path: "./mirror"
187
+ publishes: [PRD, TRD, Progresso]
188
+ mode: auto
189
+ ```
190
+
191
+ Após load:
192
+ ```typescript
193
+ const manifest = {
194
+ project: { name: "Barbearia" },
195
+ input: <ConfluenceAdapter instance, configured>,
196
+ outputs: [
197
+ { name: "confluence-mirror", adapter: <ConfluenceAdapter>, publishes: [...], mode: "auto" },
198
+ { name: "local-mirror", adapter: <FilesystemAdapter>, publishes: [...], mode: "auto" },
199
+ ],
200
+ };
201
+ ```
202
+
203
+ Skill chama `manifest.input.listChildren(...)` e `manifest.outputs[0].adapter.update(...)`.
204
+ A string `"confluence"` nunca aparece fora do registry.
205
+
206
+ ---
207
+
208
+ ## O que NÃO é responsabilidade do registry
209
+
210
+ - **Credenciais.** Adapter lê `.mcp.json` / env var direto. Registry nem vê.
211
+ - **Retry/backoff.** Cada adapter implementa. Registry devolve instância "crua".
212
+ - **Logging.** Skills logam. Adapter/registry silenciam (exceto em erro).
213
+ - **Connection pooling.** MVP é single-process single-skill. Se virar batch,
214
+ registry pode cachear. Não agora.
215
+
216
+ ---
217
+
218
+ ## Futuro (P2) — Plugin system
219
+
220
+ Quando aparecer o 3º caso real de backend não-builtin:
221
+
222
+ 1. `sfw.config.yml` ganha seção `plugins:`:
223
+ ```yaml
224
+ plugins:
225
+ - npm:@sfw/notion-adapter@1.2.0
226
+ - file:./local-adapters/sharepoint.js
227
+ ```
228
+ 2. Bootstrap do kit carrega plugins antes do manifest.
229
+ 3. Cada plugin exporta `{ key, class }` e chama `registry.register(...)`.
230
+ 4. Interface do adapter fica estável (breaking change vira major version).
231
+
232
+ **Decisão (2026-04-11)**: não implementar agora. Builtin resolve 95% dos casos
233
+ e prova que a interface está certa. Plugin system vira prioridade quando um
234
+ usuário real pedir.
235
+
236
+ ---
237
+
238
+ ## Referências
239
+
240
+ - Interface: `.github/adapters/interface.md`
241
+ - Erros: `.github/adapters/errors.md`
242
+ - Naming: `.github/adapters/naming.md`
243
+ - Manifest: `sfw.config.yml.example`
244
+ - Roadmap: `planodetarefas.md §9.9.P0.2` (implementação dos builtins)