vireum-spec-cli 0.4.2 → 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.
- package/README.md +259 -0
- package/dist/commands/brief.js +0 -4
- package/dist/commands/distill.js +64 -301
- package/dist/commands/enrich.js +139 -0
- package/dist/commands/health.js +0 -4
- package/dist/commands/init/ai.js +186 -0
- package/dist/commands/init/api.js +195 -0
- package/dist/commands/init/automation.js +166 -0
- package/dist/commands/init/mobile.js +155 -0
- package/dist/commands/init/system.js +307 -0
- package/dist/commands/init/web.js +165 -0
- package/dist/commands/init.js +21 -253
- package/dist/commands/prioritize.js +82 -34
- package/dist/commands/retrofit.js +14 -400
- package/dist/commands/setup.js +56 -488
- package/dist/commands/skills.js +0 -6
- package/dist/commands/verify-mcps.js +0 -4
- package/dist/index.js +44 -2
- package/dist/lib/analyzer.js +194 -0
- package/dist/lib/generators-retrofit.js +259 -0
- package/dist/lib/generators-retrofit.test.js +112 -0
- package/dist/lib/generators-setup.js +764 -0
- package/dist/lib/generators-setup.test.js +118 -0
- package/dist/lib/generators.js +593 -0
- package/dist/lib/parsers/ai.js +54 -0
- package/dist/lib/parsers/api.js +63 -0
- package/dist/lib/parsers/automation.js +52 -0
- package/dist/lib/parsers/mobile.js +60 -0
- package/dist/lib/parsers/system.js +66 -0
- package/dist/lib/parsers/web.js +70 -0
- package/dist/lib/types.js +2 -0
- package/docs/COMO_USAR.md +322 -0
- package/docs/DOCUMENTACAO_FRAMEWORK.md +568 -0
- package/package.json +9 -3
|
@@ -0,0 +1,593 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.gerarRequirements = gerarRequirements;
|
|
4
|
+
exports.gerarArchitecture = gerarArchitecture;
|
|
5
|
+
exports.gerarUsers = gerarUsers;
|
|
6
|
+
exports.gerarRisks = gerarRisks;
|
|
7
|
+
exports.gerarRules = gerarRules;
|
|
8
|
+
exports.gerarIndex = gerarIndex;
|
|
9
|
+
exports.gerarChangelog = gerarChangelog;
|
|
10
|
+
exports.gerarTasksActive = gerarTasksActive;
|
|
11
|
+
exports.gerarTasksBacklog = gerarTasksBacklog;
|
|
12
|
+
exports.gerarTasksDone = gerarTasksDone;
|
|
13
|
+
// ─── REQUIREMENTS ─────────────────────────────────────────────────────────────
|
|
14
|
+
function gerarRequirements(d) {
|
|
15
|
+
switch (d.tipo) {
|
|
16
|
+
case 'web': return gerarRequirementsWeb(d);
|
|
17
|
+
case 'api': return gerarRequirementsApi(d);
|
|
18
|
+
case 'mobile': return gerarRequirementsMobile(d);
|
|
19
|
+
case 'automation': return gerarRequirementsAutomation(d);
|
|
20
|
+
case 'ai': return gerarRequirementsAi(d);
|
|
21
|
+
default: return gerarRequirementsSystem(d);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function gerarRequirementsSystem(d) {
|
|
25
|
+
const features = d.features.length
|
|
26
|
+
? d.features.map((f, i) => `- [ ] R-${String(i + 1).padStart(3, '0')} ${f}`).join('\n')
|
|
27
|
+
: '- [ ] R-001 (a definir)';
|
|
28
|
+
const fase2 = d.featuresDesejaveis.length
|
|
29
|
+
? d.featuresDesejaveis.map((f, i) => `- [ ] F2-${String(i + 1).padStart(3, '0')} ${f}`).join('\n')
|
|
30
|
+
: '> Preencher após vireum-spec prioritize';
|
|
31
|
+
const e = d.extra;
|
|
32
|
+
return `# Requirements — ${d.projeto}
|
|
33
|
+
|
|
34
|
+
> Gerado automaticamente a partir do briefing em ${d.data}
|
|
35
|
+
> Fonte: .spec/briefing.md
|
|
36
|
+
|
|
37
|
+
## Objetivo
|
|
38
|
+
${d.objetivo}
|
|
39
|
+
|
|
40
|
+
**Problema:** ${d.problema}
|
|
41
|
+
|
|
42
|
+
**Prioridade do cliente:** ${d.prioridade}
|
|
43
|
+
|
|
44
|
+
## Funcionalidades — MVP
|
|
45
|
+
${features}
|
|
46
|
+
|
|
47
|
+
## Funcionalidades — Fase 2
|
|
48
|
+
${fase2}
|
|
49
|
+
|
|
50
|
+
## Regras de Negócio
|
|
51
|
+
${d.regras || '> A extrair do briefing'}
|
|
52
|
+
|
|
53
|
+
## Integrações
|
|
54
|
+
${e.integracoes || 'Nenhuma identificada'}
|
|
55
|
+
|
|
56
|
+
## Financeiro
|
|
57
|
+
${e.pagamento ? `- Integração com pagamento: Sim\n- Modelo: ${e.cobranca}` : '- Sem integração financeira'}
|
|
58
|
+
|
|
59
|
+
## Métricas
|
|
60
|
+
- KPIs: ${e.kpis || 'A definir'}
|
|
61
|
+
- Dashboard: ${e.dashboard ? 'Sim' : 'Não'}
|
|
62
|
+
`;
|
|
63
|
+
}
|
|
64
|
+
function gerarRequirementsWeb(d) {
|
|
65
|
+
const e = d.extra;
|
|
66
|
+
const secoes = (e.secoes || '').split(',').map((s) => `- ${s.trim()}`).join('\n');
|
|
67
|
+
return `# Requirements — ${d.projeto}
|
|
68
|
+
|
|
69
|
+
> Gerado automaticamente a partir do briefing em ${d.data}
|
|
70
|
+
> Tipo: Web — ${e.subtipo_label || e.subtipo}
|
|
71
|
+
|
|
72
|
+
## Objetivo
|
|
73
|
+
${d.objetivo}
|
|
74
|
+
|
|
75
|
+
**CTA principal:** ${e.cta_principal || 'A definir'}
|
|
76
|
+
|
|
77
|
+
**Público-alvo:** ${e.publico || 'A definir'}
|
|
78
|
+
|
|
79
|
+
## Seções da Página
|
|
80
|
+
${secoes || '> A definir'}
|
|
81
|
+
|
|
82
|
+
## Formulário
|
|
83
|
+
- Formulário de contato/captura: ${e.formulario ? 'Sim' : 'Não'}
|
|
84
|
+
${e.campos_form ? `- Campos: ${e.campos_form}` : ''}
|
|
85
|
+
${e.blog_categorias ? `- Categorias do blog: ${e.blog_categorias}` : ''}
|
|
86
|
+
|
|
87
|
+
## Integrações
|
|
88
|
+
- Analytics: ${e.analytics ? 'Sim' : 'Não'}
|
|
89
|
+
- Chat ao vivo: ${e.chat ? 'Sim' : 'Não'}
|
|
90
|
+
- CRM / E-mail marketing: ${e.crm || 'Não'}
|
|
91
|
+
- Pixel de rastreamento: ${e.pixel ? 'Sim' : 'Não'}
|
|
92
|
+
|
|
93
|
+
## Deploy e SEO
|
|
94
|
+
- Plataforma: ${e.deploy_plataforma || 'A definir'}
|
|
95
|
+
- SEO (meta tags, sitemap, OG): ${e.seo ? 'Obrigatório' : 'Não'}
|
|
96
|
+
- Performance / Core Web Vitals: ${e.performance ? 'Crítico' : 'Normal'}
|
|
97
|
+
`;
|
|
98
|
+
}
|
|
99
|
+
function gerarRequirementsApi(d) {
|
|
100
|
+
const e = d.extra;
|
|
101
|
+
const endpoints = (e.endpoints || '').split(',').map((ep) => `- ${ep.trim()}`).join('\n');
|
|
102
|
+
return `# Requirements — ${d.projeto}
|
|
103
|
+
|
|
104
|
+
> Gerado automaticamente a partir do briefing em ${d.data}
|
|
105
|
+
> Tipo: API / Backend
|
|
106
|
+
|
|
107
|
+
## Objetivo
|
|
108
|
+
${d.objetivo}
|
|
109
|
+
|
|
110
|
+
**Consumidores:** ${e.consumidores || 'A definir'}
|
|
111
|
+
|
|
112
|
+
## Endpoints Principais
|
|
113
|
+
${endpoints || '> A definir'}
|
|
114
|
+
|
|
115
|
+
## Autenticação e Segurança
|
|
116
|
+
- Autenticação: ${e.auth || 'A definir'}
|
|
117
|
+
- Rate limiting: ${e.rate_limiting ? 'Sim' : 'Não'}
|
|
118
|
+
- CORS: ${e.cors ? 'Sim' : 'Não'}
|
|
119
|
+
- Dados sensíveis: ${e.dados_sensiveis ? 'Sim' : 'Não'}
|
|
120
|
+
- LGPD: ${e.lgpd ? 'Sim' : 'Não'}
|
|
121
|
+
|
|
122
|
+
## Banco de Dados
|
|
123
|
+
- Banco: ${e.banco || 'A definir'}
|
|
124
|
+
- ORM: ${e.orm || 'A definir'}
|
|
125
|
+
- Cache (Redis): ${e.cache ? 'Sim' : 'Não'}
|
|
126
|
+
|
|
127
|
+
## Documentação
|
|
128
|
+
- Swagger / OpenAPI: ${e.swagger ? 'Sim' : 'Não'}
|
|
129
|
+
- Versionamento: ${e.versioning ? 'Sim' : 'Não'}
|
|
130
|
+
- SDK para consumidores: ${e.sdk ? 'Sim' : 'Não'}
|
|
131
|
+
`;
|
|
132
|
+
}
|
|
133
|
+
function gerarRequirementsMobile(d) {
|
|
134
|
+
const e = d.extra;
|
|
135
|
+
const features = d.features.map((f, i) => `- [ ] R-${String(i + 1).padStart(3, '0')} ${f}`).join('\n');
|
|
136
|
+
const permissoes = [
|
|
137
|
+
e.camera && '- Câmera / Galeria',
|
|
138
|
+
e.localizacao && '- Localização / GPS',
|
|
139
|
+
e.push && '- Notificações push',
|
|
140
|
+
e.biometria && '- Biometria (Face ID / Touch ID)',
|
|
141
|
+
].filter(Boolean).join('\n') || '- Nenhuma adicional';
|
|
142
|
+
return `# Requirements — ${d.projeto}
|
|
143
|
+
|
|
144
|
+
> Gerado automaticamente a partir do briefing em ${d.data}
|
|
145
|
+
> Tipo: Mobile — ${e.framework || 'React Native'}
|
|
146
|
+
|
|
147
|
+
## Objetivo
|
|
148
|
+
${d.objetivo}
|
|
149
|
+
|
|
150
|
+
**Problema resolvido:** ${d.problema}
|
|
151
|
+
|
|
152
|
+
**Plataformas:** ${e.plataformas || 'iOS e Android'}
|
|
153
|
+
|
|
154
|
+
## Funcionalidades — MVP
|
|
155
|
+
${features || '> A definir'}
|
|
156
|
+
|
|
157
|
+
## Permissões de Dispositivo
|
|
158
|
+
${permissoes}
|
|
159
|
+
|
|
160
|
+
- Funcionamento offline: ${e.offline ? 'Sim' : 'Não'}
|
|
161
|
+
|
|
162
|
+
## Backend e Autenticação
|
|
163
|
+
- Conecta a API: ${e.tem_api ? 'Sim' : 'Não'}
|
|
164
|
+
- API própria (Vireum): ${e.api_propria ? 'Sim' : 'Não'}
|
|
165
|
+
- Autenticação: ${e.auth_mobile || 'A definir'}
|
|
166
|
+
|
|
167
|
+
## Publicação nas Lojas
|
|
168
|
+
- Publicar nas lojas: ${e.publicar ? 'Sim' : 'Não'}
|
|
169
|
+
- Deep linking: ${e.deep_linking ? 'Sim' : 'Não'}
|
|
170
|
+
- Atualizações OTA: ${e.updates_ota ? 'Sim' : 'Não'}
|
|
171
|
+
`;
|
|
172
|
+
}
|
|
173
|
+
function gerarRequirementsAutomation(d) {
|
|
174
|
+
const e = d.extra;
|
|
175
|
+
return `# Requirements — ${d.projeto}
|
|
176
|
+
|
|
177
|
+
> Gerado automaticamente a partir do briefing em ${d.data}
|
|
178
|
+
> Tipo: Automação
|
|
179
|
+
|
|
180
|
+
## O que Faz
|
|
181
|
+
${d.objetivo}
|
|
182
|
+
|
|
183
|
+
**Processo atual (manual):** ${d.problema}
|
|
184
|
+
|
|
185
|
+
## Trigger e Frequência
|
|
186
|
+
- Trigger: ${e.trigger || 'A definir'}
|
|
187
|
+
- Frequência: ${e.frequencia || 'A definir'}
|
|
188
|
+
- Volume por execução: ${e.volume || 'A definir'}
|
|
189
|
+
|
|
190
|
+
## Fluxo de Dados
|
|
191
|
+
- Fonte: ${e.fonte || 'A definir'} — ${e.fonte_detalhe || ''}
|
|
192
|
+
- Transformação: ${e.transformacao || 'A definir'}
|
|
193
|
+
- Destino: ${e.destino || 'A definir'} — ${e.destino_detalhe || ''}
|
|
194
|
+
|
|
195
|
+
## Confiabilidade
|
|
196
|
+
- Retry em falha: ${e.retry ? 'Sim' : 'Não'}
|
|
197
|
+
- Alerta de falha: ${e.alerta ? 'Sim' : 'Não'}
|
|
198
|
+
${e.alerta_canal ? `- Canal: ${e.alerta_canal}` : ''}
|
|
199
|
+
- Idempotente: ${e.idempotente ? 'Sim' : 'Não (cuidado com duplicatas)'}
|
|
200
|
+
|
|
201
|
+
## Monitoramento
|
|
202
|
+
- Logs de execução: ${e.logs ? 'Sim' : 'Não'}
|
|
203
|
+
- Dashboard: ${e.dashboard_mon ? 'Sim' : 'Não'}
|
|
204
|
+
`;
|
|
205
|
+
}
|
|
206
|
+
function gerarRequirementsAi(d) {
|
|
207
|
+
const e = d.extra;
|
|
208
|
+
return `# Requirements — ${d.projeto}
|
|
209
|
+
|
|
210
|
+
> Gerado automaticamente a partir do briefing em ${d.data}
|
|
211
|
+
> Tipo: Produto / Feature de IA
|
|
212
|
+
|
|
213
|
+
## Problema
|
|
214
|
+
${d.objetivo}
|
|
215
|
+
|
|
216
|
+
**Quem executa hoje:** ${e.quem_faz || 'A definir'}
|
|
217
|
+
**Tempo atual:** ${e.tempo_atual || 'A definir'}
|
|
218
|
+
**Caso de uso:** ${e.caso_uso || 'A definir'}
|
|
219
|
+
${e.caso_uso_detalhe ? `**Detalhe:** ${e.caso_uso_detalhe}` : ''}
|
|
220
|
+
|
|
221
|
+
## Fonte de Conhecimento
|
|
222
|
+
- Fonte: ${e.conhecimento_fonte || 'A definir'}
|
|
223
|
+
- Dados já existem: ${e.dados_existem ? 'Sim' : 'Não — precisam ser coletados'}
|
|
224
|
+
- Volume: ${e.volume_docs || 'A definir'}
|
|
225
|
+
- Atualização: ${e.atualizacao || 'A definir'}
|
|
226
|
+
|
|
227
|
+
## Interação
|
|
228
|
+
- Canal: ${e.canal || 'A definir'}
|
|
229
|
+
- Interface visual: ${e.tem_interface ? 'Sim' : 'Não'}
|
|
230
|
+
- Usuários: ${e.usuarios_ai || 'A definir'}
|
|
231
|
+
|
|
232
|
+
## Modelo
|
|
233
|
+
- Provider: ${e.provider || 'A definir'}
|
|
234
|
+
- Restrição de custo: ${e.restricao_custo ? 'Sim' : 'Não'}
|
|
235
|
+
${e.custo_detalhe ? `- Limite: ${e.custo_detalhe}` : ''}
|
|
236
|
+
- Dados sensíveis: ${e.dados_sensiveis ? 'Sim' : 'Não'}
|
|
237
|
+
- Rodar local: ${e.rodar_local ? 'Sim' : 'Não'}
|
|
238
|
+
|
|
239
|
+
## Qualidade e Supervisão
|
|
240
|
+
- Critério de sucesso: ${e.criterio_sucesso || 'A definir'}
|
|
241
|
+
- Supervisão humana: ${e.supervisao || 'A definir'}
|
|
242
|
+
- Fallback para humano: ${e.fallback ? 'Sim' : 'Não'}
|
|
243
|
+
`;
|
|
244
|
+
}
|
|
245
|
+
// ─── ARCHITECTURE ─────────────────────────────────────────────────────────────
|
|
246
|
+
function gerarArchitecture(d) {
|
|
247
|
+
switch (d.tipo) {
|
|
248
|
+
case 'web': return gerarArchitectureWeb(d);
|
|
249
|
+
case 'api': return gerarArchitectureApi(d);
|
|
250
|
+
case 'mobile': return gerarArchitectureMobile(d);
|
|
251
|
+
case 'automation': return gerarArchitectureAutomation(d);
|
|
252
|
+
case 'ai': return gerarArchitectureAi(d);
|
|
253
|
+
default: return gerarArchitectureSystem(d);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function gerarArchitectureSystem(d) {
|
|
257
|
+
const e = d.extra;
|
|
258
|
+
return `# Architecture — ${d.projeto}
|
|
259
|
+
|
|
260
|
+
> Gerado automaticamente a partir do briefing em ${d.data}
|
|
261
|
+
> Completar com vireum-spec setup
|
|
262
|
+
|
|
263
|
+
## Stack
|
|
264
|
+
> A definir em vireum-spec setup
|
|
265
|
+
|
|
266
|
+
- Frontend:
|
|
267
|
+
- Backend:
|
|
268
|
+
- Banco de dados:
|
|
269
|
+
- Cache:
|
|
270
|
+
- Auth:
|
|
271
|
+
|
|
272
|
+
## Infraestrutura
|
|
273
|
+
- Plataforma: ${e.plataforma || 'A definir'}
|
|
274
|
+
- Hospedagem: ${e.hospedagem || 'A definir'}
|
|
275
|
+
- CI/CD: ${e.cicd ? 'Sim' : 'Não definido'}
|
|
276
|
+
- Staging: ${e.staging ? 'Sim' : 'Não'}
|
|
277
|
+
|
|
278
|
+
## Decisões Arquiteturais
|
|
279
|
+
> A IA deve registrar aqui cada decisão técnica com justificativa
|
|
280
|
+
|
|
281
|
+
| Data | Decisão | Alternativas descartadas | Motivo |
|
|
282
|
+
|------|---------|--------------------------|--------|
|
|
283
|
+
| | | | |
|
|
284
|
+
|
|
285
|
+
## MCPs Ativos
|
|
286
|
+
> A configurar em vireum-spec setup
|
|
287
|
+
`;
|
|
288
|
+
}
|
|
289
|
+
function gerarArchitectureWeb(d) {
|
|
290
|
+
const e = d.extra;
|
|
291
|
+
return `# Architecture — ${d.projeto}
|
|
292
|
+
|
|
293
|
+
> Gerado automaticamente a partir do briefing em ${d.data}
|
|
294
|
+
> Tipo: Web — ${e.subtipo_label || e.subtipo}
|
|
295
|
+
|
|
296
|
+
## Stack
|
|
297
|
+
- UI Framework: ${e.design_system || 'A definir'}
|
|
298
|
+
- Deploy: ${e.deploy_plataforma || 'A definir'}
|
|
299
|
+
- Domínio: ${e.dominio ? 'Configurado' : 'A configurar'}
|
|
300
|
+
|
|
301
|
+
## Decisões Arquiteturais
|
|
302
|
+
| Data | Decisão | Alternativas descartadas | Motivo |
|
|
303
|
+
|------|---------|--------------------------|--------|
|
|
304
|
+
| | | | |
|
|
305
|
+
|
|
306
|
+
## MCPs Ativos
|
|
307
|
+
> A configurar em vireum-spec setup
|
|
308
|
+
`;
|
|
309
|
+
}
|
|
310
|
+
function gerarArchitectureApi(d) {
|
|
311
|
+
const e = d.extra;
|
|
312
|
+
return `# Architecture — ${d.projeto}
|
|
313
|
+
|
|
314
|
+
> Gerado automaticamente a partir do briefing em ${d.data}
|
|
315
|
+
> Tipo: API / Backend
|
|
316
|
+
|
|
317
|
+
## Stack
|
|
318
|
+
- Backend: A definir em vireum-spec setup
|
|
319
|
+
- Banco de dados: ${e.banco || 'A definir'}
|
|
320
|
+
- ORM: ${e.orm || 'A definir'}
|
|
321
|
+
- Autenticação: ${e.auth || 'A definir'}
|
|
322
|
+
- Cache: ${e.cache ? 'Redis' : 'Não definido'}
|
|
323
|
+
- Deploy: ${e.deploy_plataforma || 'A definir'}
|
|
324
|
+
|
|
325
|
+
## Decisões Arquiteturais
|
|
326
|
+
| Data | Decisão | Alternativas descartadas | Motivo |
|
|
327
|
+
|------|---------|--------------------------|--------|
|
|
328
|
+
| | | | |
|
|
329
|
+
|
|
330
|
+
## MCPs Ativos
|
|
331
|
+
> A configurar em vireum-spec setup
|
|
332
|
+
`;
|
|
333
|
+
}
|
|
334
|
+
function gerarArchitectureMobile(d) {
|
|
335
|
+
const e = d.extra;
|
|
336
|
+
return `# Architecture — ${d.projeto}
|
|
337
|
+
|
|
338
|
+
> Gerado automaticamente a partir do briefing em ${d.data}
|
|
339
|
+
> Tipo: Mobile
|
|
340
|
+
|
|
341
|
+
## Stack
|
|
342
|
+
- Framework: ${e.framework || 'A definir'}
|
|
343
|
+
- Plataformas: ${e.plataformas || 'iOS e Android'}
|
|
344
|
+
- Autenticação: ${e.auth_mobile || 'A definir'}
|
|
345
|
+
- Backend: ${e.api_propria ? 'API própria (Vireum)' : 'API externa'}
|
|
346
|
+
|
|
347
|
+
## Decisões Arquiteturais
|
|
348
|
+
| Data | Decisão | Alternativas descartadas | Motivo |
|
|
349
|
+
|------|---------|--------------------------|--------|
|
|
350
|
+
| | | | |
|
|
351
|
+
|
|
352
|
+
## MCPs Ativos
|
|
353
|
+
> A configurar em vireum-spec setup
|
|
354
|
+
`;
|
|
355
|
+
}
|
|
356
|
+
function gerarArchitectureAutomation(d) {
|
|
357
|
+
const e = d.extra;
|
|
358
|
+
return `# Architecture — ${d.projeto}
|
|
359
|
+
|
|
360
|
+
> Gerado automaticamente a partir do briefing em ${d.data}
|
|
361
|
+
> Tipo: Automação
|
|
362
|
+
|
|
363
|
+
## Stack
|
|
364
|
+
- Linguagem: ${e.linguagem || 'A definir'}
|
|
365
|
+
- Trigger: ${e.trigger || 'A definir'}
|
|
366
|
+
- Deploy: ${e.deploy_auto || 'A definir'}
|
|
367
|
+
|
|
368
|
+
## Fluxo
|
|
369
|
+
- Fonte → Transformação → Destino
|
|
370
|
+
- ${e.fonte || '?'} → ${e.transformacao || '?'} → ${e.destino || '?'}
|
|
371
|
+
|
|
372
|
+
## Decisões Arquiteturais
|
|
373
|
+
| Data | Decisão | Alternativas descartadas | Motivo |
|
|
374
|
+
|------|---------|--------------------------|--------|
|
|
375
|
+
| | | | |
|
|
376
|
+
`;
|
|
377
|
+
}
|
|
378
|
+
function gerarArchitectureAi(d) {
|
|
379
|
+
const e = d.extra;
|
|
380
|
+
return `# Architecture — ${d.projeto}
|
|
381
|
+
|
|
382
|
+
> Gerado automaticamente a partir do briefing em ${d.data}
|
|
383
|
+
> Tipo: Produto / Feature de IA
|
|
384
|
+
|
|
385
|
+
## Stack
|
|
386
|
+
- Provider: ${e.provider || 'A definir'}
|
|
387
|
+
- Canal de interação: ${e.canal || 'A definir'}
|
|
388
|
+
- Fonte de conhecimento: ${e.conhecimento_fonte || 'A definir'}
|
|
389
|
+
- Interface visual: ${e.tem_interface ? 'Sim' : 'Não'}
|
|
390
|
+
|
|
391
|
+
## Decisões Arquiteturais
|
|
392
|
+
| Data | Decisão | Alternativas descartadas | Motivo |
|
|
393
|
+
|------|---------|--------------------------|--------|
|
|
394
|
+
| | | | |
|
|
395
|
+
`;
|
|
396
|
+
}
|
|
397
|
+
// ─── USERS ────────────────────────────────────────────────────────────────────
|
|
398
|
+
function gerarUsers(d) {
|
|
399
|
+
const e = d.extra;
|
|
400
|
+
const publicoPrincipal = e.usuarios || e.publico || e.usuarios_ai || 'A definir';
|
|
401
|
+
const tiposUsuario = d.tipo === 'system'
|
|
402
|
+
? (e.multiUsuario ? '> Definir perfis após vireum-spec setup' : '- Usuário único (sem diferenciação de perfis)')
|
|
403
|
+
: d.tipo === 'api'
|
|
404
|
+
? `- Consumidores: ${e.consumidores || 'A definir'}`
|
|
405
|
+
: d.tipo === 'ai'
|
|
406
|
+
? `- Interage via: ${e.canal || 'A definir'}`
|
|
407
|
+
: '> A detalhar';
|
|
408
|
+
return `# Users — ${d.projeto}
|
|
409
|
+
|
|
410
|
+
> Gerado automaticamente a partir do briefing em ${d.data}
|
|
411
|
+
|
|
412
|
+
## Público Principal
|
|
413
|
+
${publicoPrincipal}
|
|
414
|
+
|
|
415
|
+
## Tipos de Usuário / Consumidores
|
|
416
|
+
${tiposUsuario}
|
|
417
|
+
|
|
418
|
+
## Níveis de Acesso
|
|
419
|
+
${d.tipo === 'system' && e.niveisAcesso ? '> Detalhar níveis em vireum-spec setup' : '- A definir'}
|
|
420
|
+
|
|
421
|
+
## Jornadas Principais
|
|
422
|
+
> A detalhar durante o desenvolvimento — referenciar requirements.md
|
|
423
|
+
`;
|
|
424
|
+
}
|
|
425
|
+
// ─── RISKS ────────────────────────────────────────────────────────────────────
|
|
426
|
+
function gerarRisks(d) {
|
|
427
|
+
const e = d.extra;
|
|
428
|
+
const riscosEspecificos = gerarRiscosEspecificos(d);
|
|
429
|
+
return `# Risks — ${d.projeto}
|
|
430
|
+
|
|
431
|
+
> Gerado automaticamente a partir do briefing em ${d.data}
|
|
432
|
+
|
|
433
|
+
## Riscos Identificados no Briefing
|
|
434
|
+
|
|
435
|
+
### Técnico
|
|
436
|
+
${d.riscos.tecnico || riscosEspecificos.tecnico || 'Nenhum identificado'}
|
|
437
|
+
|
|
438
|
+
### Jurídico
|
|
439
|
+
${d.riscos.juridico || riscosEspecificos.juridico || 'Nenhum identificado'}
|
|
440
|
+
${e.lgpd ? '\n> ⚠️ LGPD requerida — atenção ao tratamento de dados pessoais' : ''}
|
|
441
|
+
|
|
442
|
+
### Operacional
|
|
443
|
+
${d.riscos.operacional || riscosEspecificos.operacional || 'Nenhum identificado'}
|
|
444
|
+
|
|
445
|
+
## Riscos Identificados Durante o Desenvolvimento
|
|
446
|
+
> A IA deve adicionar entradas aqui ao identificar novos riscos
|
|
447
|
+
|
|
448
|
+
| Data | Risco | Impacto | Mitigação |
|
|
449
|
+
|------|-------|---------|-----------|
|
|
450
|
+
| | | | |
|
|
451
|
+
`;
|
|
452
|
+
}
|
|
453
|
+
function gerarRiscosEspecificos(d) {
|
|
454
|
+
const e = d.extra;
|
|
455
|
+
switch (d.tipo) {
|
|
456
|
+
case 'api':
|
|
457
|
+
return {
|
|
458
|
+
tecnico: e.dados_sensiveis ? 'Dados sensíveis expostos via API' : '',
|
|
459
|
+
juridico: e.lgpd ? 'LGPD — verificar armazenamento e consentimento' : '',
|
|
460
|
+
operacional: e.rate_limiting ? '' : 'Sem rate limiting — risco de abuso',
|
|
461
|
+
};
|
|
462
|
+
case 'mobile':
|
|
463
|
+
return {
|
|
464
|
+
tecnico: 'Aprovação nas lojas pode demorar 1-3 dias úteis',
|
|
465
|
+
juridico: '',
|
|
466
|
+
operacional: e.offline ? 'Sincronização offline pode gerar conflitos de dados' : '',
|
|
467
|
+
};
|
|
468
|
+
case 'automation':
|
|
469
|
+
return {
|
|
470
|
+
tecnico: e.idempotente ? '' : 'Automação não idempotente — risco de duplicar dados em retry',
|
|
471
|
+
juridico: '',
|
|
472
|
+
operacional: e.retry ? '' : 'Sem retry — falhas silenciosas podem passar despercebidas',
|
|
473
|
+
};
|
|
474
|
+
case 'ai':
|
|
475
|
+
return {
|
|
476
|
+
tecnico: e.rodar_local ? 'Modelo local pode ter performance inferior a APIs externas' : 'Custo de API pode escalar com volume',
|
|
477
|
+
juridico: e.dados_sensiveis ? 'Dados sensíveis enviados para API externa — verificar termos do provider' : '',
|
|
478
|
+
operacional: e.supervisao === '100% automático' ? 'Sem supervisão humana — respostas incorretas passam sem revisão' : '',
|
|
479
|
+
};
|
|
480
|
+
default:
|
|
481
|
+
return { tecnico: '', juridico: '', operacional: '' };
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
// ─── RULES ────────────────────────────────────────────────────────────────────
|
|
485
|
+
function gerarRules(d) {
|
|
486
|
+
const e = d.extra;
|
|
487
|
+
const extras = [];
|
|
488
|
+
if (e.lgpd || e.lgpd === true)
|
|
489
|
+
extras.push('- Nunca armazenar dados pessoais sem consentimento explícito (LGPD)');
|
|
490
|
+
if (e.dados_sensiveis)
|
|
491
|
+
extras.push('- Dados sensíveis devem ser encriptados em repouso e em trânsito');
|
|
492
|
+
if (e.pagamento)
|
|
493
|
+
extras.push('- Nunca logar dados de pagamento (cartão, CVV, etc.)');
|
|
494
|
+
if (e.niveisAcesso)
|
|
495
|
+
extras.push('- Toda rota deve validar o nível de acesso do usuário');
|
|
496
|
+
if (d.tipo === 'automation' && !e.idempotente)
|
|
497
|
+
extras.push('- Automação não é idempotente — implementar deduplicação antes de salvar');
|
|
498
|
+
if (d.tipo === 'ai' && e.dados_sensiveis)
|
|
499
|
+
extras.push('- Nunca enviar dados sensíveis sem mascaramento para APIs externas');
|
|
500
|
+
return `# Rules — ${d.projeto}
|
|
501
|
+
|
|
502
|
+
> Regras específicas deste projeto geradas a partir do briefing.
|
|
503
|
+
> Estas regras complementam as regras globais em .vireum/rules.md
|
|
504
|
+
> Em caso de conflito, as regras globais prevalecem.
|
|
505
|
+
|
|
506
|
+
## Regras do Projeto
|
|
507
|
+
${extras.length ? extras.join('\n') : '- Nenhuma regra específica identificada no briefing'}
|
|
508
|
+
|
|
509
|
+
## Regras a Definir
|
|
510
|
+
> Completar após vireum-spec setup com decisões técnicas do projeto
|
|
511
|
+
`;
|
|
512
|
+
}
|
|
513
|
+
// ─── INDEX ────────────────────────────────────────────────────────────────────
|
|
514
|
+
function gerarIndex(d) {
|
|
515
|
+
return `# INDEX — ${d.projeto}
|
|
516
|
+
|
|
517
|
+
> Arquivo de entrada. Sempre carregado pela IA no início de cada sessão.
|
|
518
|
+
> Arquivos pesados são carregados por referência — apenas quando a tarefa exigir.
|
|
519
|
+
|
|
520
|
+
## Projeto
|
|
521
|
+
- **Cliente:** ${d.cliente}
|
|
522
|
+
- **Responsável:** ${d.responsavel}
|
|
523
|
+
- **Fase atual:** MVP
|
|
524
|
+
- **Iniciado em:** ${d.data}
|
|
525
|
+
|
|
526
|
+
## Estado do MVP
|
|
527
|
+
> Atualizar conforme o desenvolvimento avança
|
|
528
|
+
|
|
529
|
+
- [ ] Nenhuma task concluída ainda
|
|
530
|
+
|
|
531
|
+
## Arquivos de contexto disponíveis
|
|
532
|
+
Não carregue esses arquivos automaticamente.
|
|
533
|
+
Carregue apenas quando a tarefa exigir:
|
|
534
|
+
|
|
535
|
+
- Escopo e features → leia \`.spec/requirements.md\`
|
|
536
|
+
- Decisões técnicas → leia \`.spec/architecture.md\`
|
|
537
|
+
- Perfis e permissões → leia \`.spec/users.md\`
|
|
538
|
+
- Riscos → leia \`.spec/risks.md\`
|
|
539
|
+
- Tarefas ativas → leia \`.spec/tasks/active.md\`
|
|
540
|
+
- Histórico de decisões → leia \`.spec/changelog.md\`
|
|
541
|
+
|
|
542
|
+
## Resumo do Objetivo
|
|
543
|
+
${d.objetivo}
|
|
544
|
+
`;
|
|
545
|
+
}
|
|
546
|
+
// ─── CHANGELOG ────────────────────────────────────────────────────────────────
|
|
547
|
+
function gerarChangelog(d) {
|
|
548
|
+
return `# Changelog — ${d.projeto}
|
|
549
|
+
|
|
550
|
+
> Registro de decisões, mudanças e causa raiz de bugs.
|
|
551
|
+
> A IA deve adicionar entradas aqui ao tomar decisões relevantes ou resolver bugs.
|
|
552
|
+
> Formato: data, tipo, descrição.
|
|
553
|
+
|
|
554
|
+
## ${d.data} — Projeto iniciado
|
|
555
|
+
- Briefing realizado com ${d.cliente}
|
|
556
|
+
- Spec gerado via vireum-spec distill
|
|
557
|
+
`;
|
|
558
|
+
}
|
|
559
|
+
// ─── TASKS ────────────────────────────────────────────────────────────────────
|
|
560
|
+
function gerarTasksActive(_d) {
|
|
561
|
+
return `# Tasks — Active
|
|
562
|
+
|
|
563
|
+
> Tarefas do MVP prontas para desenvolvimento.
|
|
564
|
+
> A IA só implementa tasks desta lista.
|
|
565
|
+
> Ao concluir uma task: marcar status, mover para done.md, atualizar INDEX.md
|
|
566
|
+
|
|
567
|
+
---
|
|
568
|
+
|
|
569
|
+
> Nenhuma task ativa ainda.
|
|
570
|
+
> Execute vireum-spec prioritize para gerar as tasks do MVP.
|
|
571
|
+
`;
|
|
572
|
+
}
|
|
573
|
+
function gerarTasksBacklog(d) {
|
|
574
|
+
const items = d.features.length
|
|
575
|
+
? d.features.map((f, i) => `- [ ] [FEATURE-T${String(i + 1).padStart(3, '0')}] ${f} [PENDING: aguarda prioritize]`).join('\n')
|
|
576
|
+
: '- [ ] (nenhuma feature mapeada ainda)';
|
|
577
|
+
return `# Tasks — Backlog
|
|
578
|
+
|
|
579
|
+
> Features mapeadas aguardando priorização.
|
|
580
|
+
> Execute vireum-spec prioritize para classificar em MVP ou Fase 2.
|
|
581
|
+
|
|
582
|
+
${items}
|
|
583
|
+
`;
|
|
584
|
+
}
|
|
585
|
+
function gerarTasksDone(d) {
|
|
586
|
+
return `# Tasks — Done
|
|
587
|
+
|
|
588
|
+
> Tasks concluídas. Arquivo de referência — raramente entra no contexto ativo.
|
|
589
|
+
|
|
590
|
+
## ${d.data}
|
|
591
|
+
- Projeto iniciado — spec gerado via vireum-spec distill
|
|
592
|
+
`;
|
|
593
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseBriefingAi = parseBriefingAi;
|
|
4
|
+
function parseBriefingAi(briefing) {
|
|
5
|
+
const tarefa = extrairCampo(briefing, 'Tarefa que a IA vai resolver');
|
|
6
|
+
return {
|
|
7
|
+
tipo: 'ai',
|
|
8
|
+
projeto: extrairCampo(briefing, 'Projeto'),
|
|
9
|
+
cliente: extrairCampo(briefing, 'Cliente'),
|
|
10
|
+
responsavel: extrairCampo(briefing, 'Responsável'),
|
|
11
|
+
data: extrairCampo(briefing, 'Data da reunião') || new Date().toLocaleDateString('pt-BR'),
|
|
12
|
+
objetivo: tarefa,
|
|
13
|
+
problema: extrairCampo(briefing, 'Quem executa hoje'),
|
|
14
|
+
prioridade: '',
|
|
15
|
+
features: tarefa ? [tarefa] : [],
|
|
16
|
+
featuresDesejaveis: [],
|
|
17
|
+
regras: '',
|
|
18
|
+
riscos: { tecnico: '', juridico: '', operacional: '' },
|
|
19
|
+
extra: {
|
|
20
|
+
quem_faz: extrairCampo(briefing, 'Quem executa hoje'),
|
|
21
|
+
tempo_atual: extrairCampo(briefing, 'Tempo atual'),
|
|
22
|
+
caso_uso: extrairCampo(briefing, 'Caso de uso'),
|
|
23
|
+
caso_uso_detalhe: extrairCampo(briefing, 'Detalhes'),
|
|
24
|
+
conhecimento_fonte: extrairCampo(briefing, 'Fonte'),
|
|
25
|
+
dados_existem: briefing.includes('Dados já existem: Sim'),
|
|
26
|
+
volume_docs: extrairCampo(briefing, 'Volume'),
|
|
27
|
+
atualizacao: extrairCampo(briefing, 'Frequência de atualização'),
|
|
28
|
+
canal: extrairCampo(briefing, 'Canal de interação'),
|
|
29
|
+
tem_interface: briefing.includes('Interface visual (painel/dashboard): Sim'),
|
|
30
|
+
usuarios_ai: extrairCampo(briefing, 'Usuários'),
|
|
31
|
+
provider: extrairCampo(briefing, 'Provider'),
|
|
32
|
+
restricao_custo: briefing.includes('Restrição de custo: Sim'),
|
|
33
|
+
custo_detalhe: extrairCampo(briefing, 'Orçamento/limite'),
|
|
34
|
+
dados_sensiveis: briefing.includes('Dados sensíveis: Sim'),
|
|
35
|
+
rodar_local: briefing.includes('Restrição de API externa (rodar local): Sim'),
|
|
36
|
+
criterio_sucesso: extrairCampo(briefing, 'Critério de sucesso'),
|
|
37
|
+
supervisao: extrairCampo(briefing, 'Supervisão humana'),
|
|
38
|
+
fallback: briefing.includes('Fallback para humano: Sim'),
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function extrairCampo(briefing, campo) {
|
|
43
|
+
const r1 = new RegExp(`\\*\\*${campo}:\\*\\*\\s*(.+)`, 'i');
|
|
44
|
+
const m1 = briefing.match(r1);
|
|
45
|
+
if (m1)
|
|
46
|
+
return m1[1].trim();
|
|
47
|
+
const r2 = new RegExp(`- \\*\\*${campo}:\\*\\*\\s*(.+)`, 'i');
|
|
48
|
+
const m2 = briefing.match(r2);
|
|
49
|
+
if (m2)
|
|
50
|
+
return m2[1].trim();
|
|
51
|
+
const r3 = new RegExp(`- ${campo}:\\s*(.+)`, 'i');
|
|
52
|
+
const m3 = briefing.match(r3);
|
|
53
|
+
return m3 ? m3[1].trim() : '';
|
|
54
|
+
}
|