vireum-spec-cli 0.5.0 → 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 ADDED
@@ -0,0 +1,259 @@
1
+ # Vireum Spec — Spec Driven Development Framework
2
+
3
+ > **Versão:** 0.7.0
4
+ > **Framework** para documentação estruturada de projetos de software
5
+ > **By:** Vireum Desenvolvimento
6
+
7
+ [![npm version](https://img.shields.io/npm/v/vireum-spec-cli.svg)](https://www.npmjs.com/package/vireum-spec-cli)
8
+ [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC)
9
+
10
+ ---
11
+
12
+ ## 🎯 O que é?
13
+
14
+ **Vireum Spec** é um framework CLI que ajuda você a documentar projetos de software de forma estruturada, alinhando requisitos, arquitetura e desenvolvimento com o cliente.
15
+
16
+ Bridging the gap between:
17
+ - 💡 **Ideias** — O que o cliente quer
18
+ - 📋 **Planejamento** — Como você vai construir
19
+ - 💻 **Execução** — Código que funciona
20
+ - 📚 **Manutenção** — Por que foi feito
21
+
22
+ ---
23
+
24
+ ## ✨ Problemas que Resolve
25
+
26
+ ✅ **Falta de clareza** — Requisitos confusos e mal documentados
27
+ ✅ **Desalinhamento** — Cliente e dev querem coisas diferentes
28
+ ✅ **Specs desatualizadas** — Documentação não reflete realidade
29
+ ✅ **Difícil onboarding** — Novos devs entendem pouco
30
+ ✅ **Sem rastreabilidade** — Quem decidiu o quê? Por quê?
31
+ ✅ **IA sem contexto** — Claude Code funciona muito melhor com briefing estruturado
32
+
33
+ ---
34
+
35
+ ## 🚀 Quick Start
36
+
37
+ ### Instalação
38
+ ```bash
39
+ npm install -g vireum-spec-cli
40
+ ```
41
+
42
+ ### Novo Projeto
43
+ ```bash
44
+ vireum-spec init --type <tipo>
45
+ vireum-spec distill
46
+ vireum-spec setup
47
+ ```
48
+
49
+ **Tipos:** `system`, `web`, `api`, `mobile`, `automation`, `ai`
50
+
51
+ ### Projeto Existente
52
+ ```bash
53
+ vireum-spec retrofit
54
+ vireum-spec distill
55
+ vireum-spec setup
56
+ ```
57
+
58
+ ---
59
+
60
+ ## 📚 Documentação Completa
61
+
62
+ - **[Guia de Uso](./docs/COMO_USAR.md)** — Step-by-step para novos e existentes
63
+ - **[Documentação Técnica](./docs/DOCUMENTACAO_FRAMEWORK.md)** — Deep dive no framework
64
+
65
+ ---
66
+
67
+ ## 🎨 O que Gera
68
+
69
+ ### 3 Principais Artefatos
70
+
71
+ 1. **`.spec/`** — Documentação estruturada
72
+ - `briefing.md` — Suas respostas originais
73
+ - `requirements.md` — Funcionalidades
74
+ - `users.md` — Personas
75
+ - `architecture.md` — Design técnico
76
+ - `risks.md` — Riscos identificados
77
+ - `rules.md` — Regras de negócio
78
+ - E mais...
79
+
80
+ 2. **`.vireum/`** — Configuração técnica
81
+ - `stack.json` — Stack escolhida
82
+ - `protocol.md` — Protocolo da IA
83
+
84
+ 3. **`.cursor/rules/`** — Integração Claude Code
85
+ - Regras estruturadas para IA trabalhar melhor
86
+
87
+ ---
88
+
89
+ ## 🛠️ 10 Comandos Principais
90
+
91
+ | Comando | Purpose |
92
+ |---------|---------|
93
+ | `init` | Briefing interativo |
94
+ | `distill` | Gera spec do briefing |
95
+ | `setup` | Configura stack & IA |
96
+ | `retrofit` | Auto-analisa projeto |
97
+ | `prioritize` | MVP / Fase 2 / Fora scope |
98
+ | `health` | Verifica consistências |
99
+ | `brief` | Resumo executivo |
100
+ | `verify-mcps` | Diagnóstico |
101
+ | `skills` | Instala no Claude Code |
102
+ | `enrich` | Encontra gaps |
103
+
104
+ ---
105
+
106
+ ## 🎓 Exemplo: Projeto de IA
107
+
108
+ ```bash
109
+ # 1. Iniciar
110
+ vireum-spec init --type ai
111
+
112
+ # Responde perguntas (6 seções):
113
+ # - Projeto: "Chatbot de Suporte"
114
+ # - Problema: "Suporte responde 200 tickets/dia, 2-3h cada"
115
+ # - Provider: "Anthropic Claude"
116
+ # - Fonte: "PDFs internos"
117
+ # - Supervisão: "Human-in-the-loop"
118
+
119
+ # 2. Gerar spec
120
+ vireum-spec distill
121
+
122
+ # 3. Configurar
123
+ vireum-spec setup
124
+ # → Next.js, Node.js + Express, PostgreSQL, Prisma, JWT, RAG
125
+
126
+ # 4. Instalar skills
127
+ vireum-spec skills
128
+
129
+ # Resultado:
130
+ # ✓ Spec completo em .spec/
131
+ # ✓ Stack definido
132
+ # ✓ Protocol de IA pronto
133
+ # ✓ Tasks para dev
134
+ # ✓ Claude Code otimizado
135
+ ```
136
+
137
+ ---
138
+
139
+ ## 🎯 Tipos de Projeto Suportados
140
+
141
+ | Tipo | Para |
142
+ |------|------|
143
+ | **system** | Sistemas completos/multi-módulo (padrão) |
144
+ | **web** | Landing pages, sites, plataformas web |
145
+ | **api** | REST APIs, GraphQL, backends |
146
+ | **mobile** | Apps iOS/Android |
147
+ | **automation** | RPA, workflows, automação |
148
+ | **ai** | Chatbots, agentes, extração de dados |
149
+
150
+ ---
151
+
152
+ ## 💡 Melhores Práticas
153
+
154
+ ### ✅ Faça:
155
+ - Responda o briefing com detalhe
156
+ - Revise spec gerado manualmente
157
+ - Use `.spec/INDEX.md` como ponto de partida
158
+ - Mantenha atualizado conforme aprende
159
+ - Rode `health` regularmente
160
+
161
+ ### ❌ Evite:
162
+ - Deixar campos em branco
163
+ - Não revisar spec auto-gerado
164
+ - Esquecer de rodar `setup`
165
+ - Ignorar avisos do `health`
166
+ - Spec preso em git sem usar
167
+
168
+ ---
169
+
170
+ ## 🤖 Para Claude Code
171
+
172
+ Rode `vireum-spec skills` para instalar skills que fazem Claude Code:
173
+ - Entender melhor seu projeto
174
+ - Seguir padrões específicos
175
+ - Usar suas regras de negócio
176
+ - Tomar decisões alinhadas
177
+ - Ser mais eficiente
178
+
179
+ ---
180
+
181
+ ## 📊 Workflow Recomendado
182
+
183
+ ```
184
+ Plan → vireum-spec init + distill
185
+ Design → vireum-spec setup + health
186
+ Dev → Tasks em spec como guia
187
+ Review → Use spec como checklist
188
+ Retro → Update changelog
189
+ Maintain → Regular health checks
190
+ ```
191
+
192
+ ---
193
+
194
+ ## 🛠️ Stack Técnico
195
+
196
+ **Dependências:**
197
+ - Node.js 18+
198
+ - Commander (CLI)
199
+ - Chalk (colors)
200
+ - Inquirer (prompts)
201
+ - Ora (spinners)
202
+
203
+ **Peso:** ~10MB instalado
204
+
205
+ ---
206
+
207
+ ## 📦 Para Publicar no NPM
208
+
209
+ O pacote está configurado para publicar com:
210
+ ```json
211
+ {
212
+ "files": ["dist/", "src/skills/", "README.md", "docs/"]
213
+ }
214
+ ```
215
+
216
+ Incluindo:
217
+ - ✓ CLI compilado (`dist/`)
218
+ - ✓ Skills (`src/skills/`)
219
+ - ✓ README.md (esse)
220
+ - ✓ Documentação completa (`docs/`)
221
+
222
+ ---
223
+
224
+ ## 🗺️ Roadmap
225
+
226
+ **Planejado:**
227
+ - UI web para gerenciar spec
228
+ - Integração Linear/Jira
229
+ - Geração de código a partir de spec
230
+ - Multi-language support (EN, ES, FR)
231
+ - API pública para tooling
232
+
233
+ ---
234
+
235
+ ## 📝 Licença
236
+
237
+ **ISC** — Use em projetos comerciais e pessoais
238
+
239
+ ---
240
+
241
+ ## 🤝 Suporte
242
+
243
+ - **Issues:** GitHub do projeto
244
+ - **Comunidade:** Discord Vireum
245
+ - **Consulting:** vireum@dev.com
246
+
247
+ ---
248
+
249
+ ## 📖 Comece Agora
250
+
251
+ 1. **Instale:** `npm install -g vireum-spec-cli`
252
+ 2. **Leia:** [Guia de Uso](./docs/COMO_USAR.md)
253
+ 3. **Inicie:** `vireum-spec init --type <tipo>`
254
+ 4. **Gere:** `vireum-spec distill`
255
+ 5. **Configure:** `vireum-spec setup`
256
+
257
+ ---
258
+
259
+ Made with ❤️ by **[Vireum Desenvolvimento](https://vireum.com.br)**
@@ -45,7 +45,6 @@ async function runBrief() {
45
45
  console.log(chalk_1.default.hex('#2D7DD2').bold('\n Vireum Spec — Brief\n'));
46
46
  const specDir = path.join(process.cwd(), '.spec');
47
47
  const spinner = (0, ora_1.default)('Lendo spec...').start();
48
- await sleep(600);
49
48
  spinner.stop();
50
49
  if (!fs.existsSync(path.join(specDir, 'INDEX.md'))) {
51
50
  console.log(chalk_1.default.red('\n❌ Spec não encontrado.'));
@@ -145,6 +144,3 @@ function gerarBarra(pct) {
145
144
  const cor = pct >= 80 ? chalk_1.default.green : pct >= 40 ? chalk_1.default.yellow : chalk_1.default.gray;
146
145
  return cor('█'.repeat(preench)) + chalk_1.default.gray('░'.repeat(vazio));
147
146
  }
148
- function sleep(ms) {
149
- return new Promise(r => setTimeout(r, ms));
150
- }
@@ -41,6 +41,13 @@ const chalk_1 = __importDefault(require("chalk"));
41
41
  const ora_1 = __importDefault(require("ora"));
42
42
  const fs = __importStar(require("fs"));
43
43
  const path = __importStar(require("path"));
44
+ const system_1 = require("../lib/parsers/system");
45
+ const web_1 = require("../lib/parsers/web");
46
+ const api_1 = require("../lib/parsers/api");
47
+ const mobile_1 = require("../lib/parsers/mobile");
48
+ const automation_1 = require("../lib/parsers/automation");
49
+ const ai_1 = require("../lib/parsers/ai");
50
+ const generators_1 = require("../lib/generators");
44
51
  async function runDistill() {
45
52
  console.log(chalk_1.default.hex('#2D7DD2').bold('\n Vireum Spec — Distill\n'));
46
53
  const specDir = path.join(process.cwd(), '.spec');
@@ -52,321 +59,77 @@ async function runDistill() {
52
59
  }
53
60
  const spinner = (0, ora_1.default)('Lendo briefing...').start();
54
61
  const briefing = fs.readFileSync(briefingPath, 'utf-8');
55
- await sleep(600);
56
62
  spinner.succeed('Briefing lido');
57
- const dados = parseBriefing(briefing);
63
+ // ── Detectar tipo e parsear ────────────────────────────────────────────────
64
+ const tipo = detectarTipo(briefing, specDir);
65
+ const dados = parsearBriefing(briefing, tipo);
66
+ if (tipo !== 'system') {
67
+ console.log(chalk_1.default.gray(` Tipo detectado: `) + chalk_1.default.white(tipo));
68
+ }
69
+ // ── Gerar arquivos .spec/ ──────────────────────────────────────────────────
58
70
  const arquivos = [
59
- { nome: 'requirements.md', conteudo: gerarRequirements(dados), msg: 'Gerando requirements.md...' },
60
- { nome: 'users.md', conteudo: gerarUsers(dados), msg: 'Gerando users.md...' },
61
- { nome: 'risks.md', conteudo: gerarRisks(dados), msg: 'Gerando risks.md...' },
62
- { nome: 'architecture.md', conteudo: gerarArchitecture(dados), msg: 'Gerando architecture.md...' },
63
- { nome: 'INDEX.md', conteudo: gerarIndex(dados), msg: 'Gerando INDEX.md...' },
64
- { nome: 'changelog.md', conteudo: gerarChangelog(dados), msg: 'Gerando changelog.md...' },
65
- { nome: 'rules.md', conteudo: gerarRules(dados), msg: 'Gerando rules.md...' },
71
+ { nome: 'requirements.md', conteudo: (0, generators_1.gerarRequirements)(dados), msg: 'Gerando requirements.md...' },
72
+ { nome: 'users.md', conteudo: (0, generators_1.gerarUsers)(dados), msg: 'Gerando users.md...' },
73
+ { nome: 'risks.md', conteudo: (0, generators_1.gerarRisks)(dados), msg: 'Gerando risks.md...' },
74
+ { nome: 'architecture.md', conteudo: (0, generators_1.gerarArchitecture)(dados), msg: 'Gerando architecture.md...' },
75
+ { nome: 'INDEX.md', conteudo: (0, generators_1.gerarIndex)(dados), msg: 'Gerando INDEX.md...' },
76
+ { nome: 'changelog.md', conteudo: (0, generators_1.gerarChangelog)(dados), msg: 'Gerando changelog.md...' },
77
+ { nome: 'rules.md', conteudo: (0, generators_1.gerarRules)(dados), msg: 'Gerando rules.md...' },
66
78
  ];
67
79
  for (const arq of arquivos) {
68
80
  const s = (0, ora_1.default)(arq.msg).start();
69
- await sleep(400);
70
81
  fs.writeFileSync(path.join(specDir, arq.nome), arq.conteudo, 'utf-8');
71
82
  s.succeed(arq.nome + ' gerado');
72
83
  }
73
- // tasks
84
+ // ── Tasks ──────────────────────────────────────────────────────────────────
74
85
  const tasksDir = path.join(specDir, 'tasks');
75
86
  if (!fs.existsSync(tasksDir))
76
87
  fs.mkdirSync(tasksDir, { recursive: true });
77
- const sActive = (0, ora_1.default)('Gerando tasks/active.md...').start();
78
- await sleep(400);
79
- fs.writeFileSync(path.join(tasksDir, 'active.md'), gerarTasksActive(dados), 'utf-8');
80
- fs.writeFileSync(path.join(tasksDir, 'backlog.md'), gerarTasksBacklog(dados), 'utf-8');
81
- fs.writeFileSync(path.join(tasksDir, 'done.md'), gerarTasksDone(dados), 'utf-8');
88
+ const sActive = (0, ora_1.default)('Gerando tasks/...').start();
89
+ fs.writeFileSync(path.join(tasksDir, 'active.md'), (0, generators_1.gerarTasksActive)(dados), 'utf-8');
90
+ fs.writeFileSync(path.join(tasksDir, 'backlog.md'), (0, generators_1.gerarTasksBacklog)(dados), 'utf-8');
91
+ fs.writeFileSync(path.join(tasksDir, 'done.md'), (0, generators_1.gerarTasksDone)(dados), 'utf-8');
82
92
  sActive.succeed('tasks/ gerado');
83
93
  console.log(chalk_1.default.green.bold('\n✅ Spec gerado com sucesso!\n'));
84
94
  console.log(chalk_1.default.gray(' Arquivos criados em ') + chalk_1.default.white('.spec/\n'));
85
95
  console.log(chalk_1.default.gray(' Próximo passo: ') + chalk_1.default.white('vireum-spec setup') + chalk_1.default.gray(' para configurar stack e protocolo\n'));
86
96
  }
87
- // ─── PARSER ───────────────────────────────────────────────────────────────────
88
- function extrairSecao(briefing, titulo) {
89
- const regex = new RegExp(`## [^#]*${titulo}[\\s\\S]*?(?=\n## |$)`, 'i');
90
- const match = briefing.match(regex);
91
- return match ? match[0].trim() : '';
92
- }
93
- function extrairCampo(briefing, campo) {
94
- const regex = new RegExp(`\\*\\*${campo}:\\*\\*\\s*(.+)`, 'i');
95
- const match = briefing.match(regex);
96
- if (match)
97
- return match[1].trim();
98
- const regex2 = new RegExp(`- \\*\\*${campo}:\\*\\*\\s*(.+)`, 'i');
99
- const match2 = briefing.match(regex2);
100
- return match2 ? match2[1].trim() : '';
101
- }
102
- function extrairLista(secao, prefixo) {
103
- const linhas = secao.split('\n').filter(l => l.includes('- [ ]') || (prefixo && l.startsWith(prefixo)));
104
- return linhas.map(l => l.replace('- [ ]', '').replace(prefixo, '').trim()).filter(Boolean);
105
- }
106
- function parseBriefing(briefing) {
107
- const secaoGeral = extrairSecao(briefing, 'Informações Gerais');
108
- const secaoObjetivo = extrairSecao(briefing, 'Objetivo');
109
- const secaoEscopo = extrairSecao(briefing, 'Escopo Funcional');
110
- const secaoRegras = extrairSecao(briefing, 'Regras de Negócio');
111
- const secaoPlat = extrairSecao(briefing, 'Plataforma');
112
- const secaoSeg = extrairSecao(briefing, 'Segurança');
113
- const secaoEscala = extrairSecao(briefing, 'Escala');
114
- const secaoRiscos = extrairSecao(briefing, 'Riscos');
115
- const secaoFinan = extrairSecao(briefing, 'Financeiro');
116
- const secaoMetricas = extrairSecao(briefing, 'Métricas');
117
- const featuresObrig = extrairLista(secaoEscopo, '- [ ]');
118
- const featuresDesej = extrairLista(secaoEscopo, '- [ ]');
119
- return {
120
- projeto: extrairCampo(secaoGeral, 'Projeto'),
121
- cliente: extrairCampo(secaoGeral, 'Cliente'),
122
- responsavel: extrairCampo(secaoGeral, 'Responsável'),
123
- data: extrairCampo(secaoGeral, 'Data da reunião'),
124
- objetivo: extrairCampo(secaoObjetivo, 'Objetivo principal') || extrairSecao(briefing, 'Objetivo').split('\n')[1] || '',
125
- problema: extrairCampo(secaoObjetivo, 'Problema que o sistema resolve'),
126
- prioridade: extrairCampo(secaoObjetivo, 'Prioridade do cliente'),
127
- usuarios: extrairCampo(secaoEscopo, 'Quem usará') || '',
128
- multiUsuario: secaoEscopo.includes('Diferentes tipos de usuários: Sim'),
129
- niveisAcesso: secaoEscopo.includes('Níveis de acesso: Sim'),
130
- integracoes: extrairCampo(secaoEscopo, 'Integrações Externas') || '',
131
- features: featuresObrig,
132
- regras: secaoRegras,
133
- plataforma: extrairCampo(secaoPlat, 'Tipo'),
134
- hospedagem: extrairCampo(secaoPlat, 'Hospedagem'),
135
- cicd: secaoPlat.includes('CI/CD desde o início: Sim'),
136
- staging: secaoPlat.includes('Ambiente de staging: Sim'),
137
- lgpd: secaoSeg.includes('LGPD: Sim'),
138
- dadosSensiveis: secaoSeg.includes('Dados sensíveis: Sim'),
139
- pagamento: secaoFinan.includes('Integração com pagamento: Sim'),
140
- cobranca: extrairCampo(secaoFinan, 'Modelo de cobrança'),
141
- dashboard: secaoMetricas.includes('Dashboard administrativo: Sim'),
142
- kpis: extrairCampo(secaoMetricas, 'KPIs'),
143
- usuariosLanc: extrairCampo(secaoEscala, 'Usuários no lançamento'),
144
- riscTecnico: extrairCampo(secaoRiscos, 'Risco técnico'),
145
- riscJuridico: extrairCampo(secaoRiscos, 'Risco jurídico'),
146
- riscOperacional: extrairCampo(secaoRiscos, 'Risco operacional'),
147
- };
148
- }
149
- // ─── GERADORES ────────────────────────────────────────────────────────────────
150
- function gerarRequirements(d) {
151
- const features = d.features.length
152
- ? d.features.map((f, i) => `- [ ] R-${String(i + 1).padStart(3, '0')} ${f}`).join('\n')
153
- : '- [ ] R-001 (a definir)';
154
- return `# Requirements — ${d.projeto}
155
-
156
- > Gerado automaticamente a partir do briefing em ${d.data}
157
- > Fonte: .spec/briefing.md
158
-
159
- ## Objetivo
160
- ${d.objetivo}
161
-
162
- **Problema:** ${d.problema}
163
-
164
- **Prioridade do cliente:** ${d.prioridade}
165
-
166
- ## Funcionalidades — MVP
167
-
168
- ${features}
169
-
170
- ## Funcionalidades — Fase 2
171
- > Preencher após vireum-spec prioritize
172
-
173
- ## Regras de Negócio
174
- ${d.regras || '> A extrair do briefing'}
175
-
176
- ## Integrações
177
- ${d.integracoes || 'Nenhuma identificada'}
178
-
179
- ## Financeiro
180
- ${d.pagamento ? `- Integração com pagamento: Sim\n- Modelo: ${d.cobranca}` : '- Sem integração financeira'}
181
-
182
- ## Métricas
183
- - KPIs: ${d.kpis || 'A definir'}
184
- - Dashboard: ${d.dashboard ? 'Sim' : 'Não'}
185
- `;
186
- }
187
- function gerarUsers(d) {
188
- return `# Users — ${d.projeto}
189
-
190
- > Gerado automaticamente a partir do briefing em ${d.data}
191
-
192
- ## Público Principal
193
- ${d.usuarios || 'A definir'}
194
-
195
- ## Tipos de Usuário
196
- ${d.multiUsuario ? '> Definir perfis após vireum-spec setup' : '- Usuário único (sem diferenciação de perfis)'}
197
-
198
- ## Níveis de Acesso
199
- ${d.niveisAcesso ? '> Detalhar níveis em vireum-spec setup' : '- Acesso único (sem controle de permissões diferenciado)'}
200
-
201
- ## Jornadas Principais
202
- > A detalhar durante o desenvolvimento — referenciar requirements.md
203
- `;
204
- }
205
- function gerarRisks(d) {
206
- return `# Risks — ${d.projeto}
207
-
208
- > Gerado automaticamente a partir do briefing em ${d.data}
209
-
210
- ## Riscos Identificados no Briefing
211
-
212
- ### Técnico
213
- ${d.riscTecnico || 'Nenhum identificado'}
214
-
215
- ### Jurídico
216
- ${d.riscJuridico || 'Nenhum identificado'}
217
- ${d.lgpd ? '\n> ⚠️ LGPD requerida — atenção ao tratamento de dados pessoais' : ''}
218
-
219
- ### Operacional
220
- ${d.riscOperacional || 'Nenhum identificado'}
221
-
222
- ## Riscos Identificados Durante o Desenvolvimento
223
- > A IA deve adicionar entradas aqui ao identificar novos riscos
224
-
225
- | Data | Risco | Impacto | Mitigação |
226
- |------|-------|---------|-----------|
227
- | | | | |
228
- `;
229
- }
230
- function gerarArchitecture(d) {
231
- return `# Architecture — ${d.projeto}
232
-
233
- > Gerado automaticamente a partir do briefing em ${d.data}
234
- > Completar com vireum-spec setup
235
-
236
- ## Stack
237
- > A definir em vireum-spec setup
238
-
239
- - Frontend:
240
- - Backend:
241
- - Banco de dados:
242
- - Cache:
243
- - Auth:
244
-
245
- ## Infraestrutura
246
- - Plataforma: ${d.plataforma || 'A definir'}
247
- - Hospedagem: ${d.hospedagem || 'A definir'}
248
- - CI/CD: ${d.cicd ? 'Sim' : 'Não definido'}
249
- - Staging: ${d.staging ? 'Sim' : 'Não'}
250
-
251
- ## Decisões Arquiteturais
252
- > A IA deve registrar aqui cada decisão técnica relevante
253
-
254
- | Data | Decisão | Alternativas descartadas | Motivo |
255
- |------|---------|--------------------------|--------|
256
- | | | | |
257
-
258
- ## MCPs Ativos
259
- > A configurar em vireum-spec setup
260
- `;
261
- }
262
- function gerarIndex(d) {
263
- return `# INDEX — ${d.projeto}
264
-
265
- > Arquivo de entrada. Sempre carregado pela IA no início de cada sessão.
266
- > Arquivos pesados são carregados por referência — apenas quando a tarefa exigir.
267
-
268
- ## Projeto
269
- - **Cliente:** ${d.cliente}
270
- - **Responsável:** ${d.responsavel}
271
- - **Fase atual:** MVP
272
- - **Iniciado em:** ${d.data}
273
-
274
- ## Estado do MVP
275
- > Atualizar conforme o desenvolvimento avança
276
-
277
- - [ ] Nenhuma task concluída ainda
278
-
279
- ## Arquivos de contexto disponíveis
280
- Não carregue esses arquivos automaticamente.
281
- Carregue apenas quando a tarefa exigir:
282
-
283
- - Escopo e features → leia \`.spec/requirements.md\`
284
- - Decisões técnicas → leia \`.spec/architecture.md\`
285
- - Perfis e permissões → leia \`.spec/users.md\`
286
- - Riscos → leia \`.spec/risks.md\`
287
- - Tarefas ativas → leia \`.spec/tasks/active.md\`
288
- - Histórico de decisões → leia \`.spec/changelog.md\`
289
-
290
- ## Resumo do Objetivo
291
- ${d.objetivo}
292
- `;
293
- }
294
- function gerarChangelog(d) {
295
- return `# Changelog — ${d.projeto}
296
-
297
- > Registro de decisões, mudanças e causa raiz de bugs.
298
- > A IA deve adicionar entradas aqui ao tomar decisões relevantes ou resolver bugs.
299
- > Formato: data, tipo, descrição.
300
-
301
- ## ${d.data} — Projeto iniciado
302
- - Briefing realizado com ${d.cliente}
303
- - Spec gerado via vireum-spec distill
304
- `;
305
- }
306
- function gerarRules(d) {
307
- const extras = [];
308
- if (d.lgpd)
309
- extras.push('- Nunca armazenar dados pessoais sem consentimento explícito (LGPD)');
310
- if (d.dadosSensiveis)
311
- extras.push('- Dados sensíveis devem ser encriptados em repouso e em trânsito');
312
- if (d.pagamento)
313
- extras.push('- Nunca logar dados de pagamento (cartão, CVV, etc.)');
314
- if (d.niveisAcesso)
315
- extras.push('- Toda rota deve validar o nível de acesso do usuário');
316
- return `# Rules — ${d.projeto}
317
-
318
- > Regras específicas deste projeto geradas a partir do briefing.
319
- > Estas regras complementam as regras globais em .vireum/rules.md
320
- > Em caso de conflito, as regras globais prevalecem.
321
-
322
- ## Regras do Projeto
323
- ${extras.length ? extras.join('\n') : '- Nenhuma regra específica identificada no briefing'}
324
-
325
- ## Regras a Definir
326
- > Completar após vireum-spec setup com decisões técnicas do projeto
327
- `;
328
- }
329
- function gerarTasksActive(d) {
330
- return `# Tasks — Active
331
-
332
- > Tarefas em desenvolvimento ativo.
333
- > Formato: [FEATURE-TIPO_NUMERO] Descrição
334
- > A IA só implementa tasks desta lista.
335
- > Ao concluir, mover para done.md
336
-
337
- ## Como usar
338
- - [FEATURE-T001] Descrição da task
339
- - Origem: requirements.md → R-001
340
- - Critérios: o que deve passar para considerar done
341
- - Camada: Backend | Frontend | Integração
342
-
343
- ---
344
-
345
- > Nenhuma task ativa ainda.
346
- > Execute vireum-spec prioritize para gerar as tasks do MVP.
347
- `;
348
- }
349
- function gerarTasksBacklog(d) {
350
- const items = d.features.length
351
- ? d.features.map((f, i) => `- [ ] [FEATURE-T${String(i + 1).padStart(3, '0')}] ${f} [PENDING: aguarda prioritize]`).join('\n')
352
- : '- [ ] (nenhuma feature mapeada ainda)';
353
- return `# Tasks — Backlog
354
-
355
- > Features mapeadas aguardando priorização.
356
- > Execute vireum-spec prioritize para classificar em MVP ou Fase 2.
357
-
358
- ${items}
359
- `;
360
- }
361
- function gerarTasksDone(d) {
362
- return `# Tasks — Done
363
-
364
- > Tasks concluídas. Arquivo de referência — raramente entra no contexto ativo.
365
-
366
- ## ${d.data}
367
- - Projeto iniciado — spec gerado via vireum-spec distill
368
- `;
369
- }
370
- function sleep(ms) {
371
- return new Promise(r => setTimeout(r, ms));
97
+ // ─── DETECÇÃO DE TIPO ─────────────────────────────────────────────────────────
98
+ function detectarTipo(briefing, specDir) {
99
+ // Preferir .spec/meta.json fonte canonica gravada pelo init
100
+ const metaPath = path.join(specDir, 'meta.json');
101
+ if (fs.existsSync(metaPath)) {
102
+ try {
103
+ const meta = JSON.parse(fs.readFileSync(metaPath, 'utf-8'));
104
+ if (meta.tipo)
105
+ return meta.tipo;
106
+ }
107
+ catch { /* fallback abaixo */ }
108
+ }
109
+ // Fallback: heuristica antiga para briefings pre-meta.json
110
+ const match = briefing.match(/- \*\*Tipo:\*\*\s*(.+)/i);
111
+ if (!match)
112
+ return 'system';
113
+ const tipo = match[1].toLowerCase();
114
+ if (tipo.includes('web'))
115
+ return 'web';
116
+ if (tipo.includes('api') || tipo.includes('backend'))
117
+ return 'api';
118
+ if (tipo.includes('mobile'))
119
+ return 'mobile';
120
+ if (tipo.includes('automa'))
121
+ return 'automation';
122
+ if (tipo.includes('ia') || tipo.includes('feature de ia'))
123
+ return 'ai';
124
+ return 'system';
125
+ }
126
+ function parsearBriefing(briefing, tipo) {
127
+ switch (tipo) {
128
+ case 'web': return (0, web_1.parseBriefingWeb)(briefing);
129
+ case 'api': return (0, api_1.parseBriefingApi)(briefing);
130
+ case 'mobile': return (0, mobile_1.parseBriefingMobile)(briefing);
131
+ case 'automation': return (0, automation_1.parseBriefingAutomation)(briefing);
132
+ case 'ai': return (0, ai_1.parseBriefingAi)(briefing);
133
+ default: return (0, system_1.parseBriefingSystem)(briefing);
134
+ }
372
135
  }