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,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.runEnrich = runEnrich;
|
|
40
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
41
|
+
const ora_1 = __importDefault(require("ora"));
|
|
42
|
+
const fs = __importStar(require("fs"));
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
async function runEnrich() {
|
|
45
|
+
console.log(chalk_1.default.hex('#2D7DD2').bold('\n Vireum Spec — Enrich\n'));
|
|
46
|
+
console.log(chalk_1.default.gray(' Gera um prompt para a IA identificar gaps no spec\n'));
|
|
47
|
+
const specDir = path.join(process.cwd(), '.spec');
|
|
48
|
+
if (!fs.existsSync(path.join(specDir, 'INDEX.md'))) {
|
|
49
|
+
console.log(chalk_1.default.red('\n❌ Spec não encontrado.'));
|
|
50
|
+
console.log(chalk_1.default.gray(' Execute primeiro: ') + chalk_1.default.white('vireum-spec retrofit') + chalk_1.default.gray(' ou ') + chalk_1.default.white('vireum-spec distill\n'));
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
const spinner = (0, ora_1.default)('Lendo spec...').start();
|
|
54
|
+
const arquivos = [
|
|
55
|
+
{ nome: 'INDEX.md', path: path.join(specDir, 'INDEX.md') },
|
|
56
|
+
{ nome: 'briefing.md', path: path.join(specDir, 'briefing.md') },
|
|
57
|
+
{ nome: 'requirements.md', path: path.join(specDir, 'requirements.md') },
|
|
58
|
+
{ nome: 'architecture.md', path: path.join(specDir, 'architecture.md') },
|
|
59
|
+
{ nome: 'users.md', path: path.join(specDir, 'users.md') },
|
|
60
|
+
{ nome: 'risks.md', path: path.join(specDir, 'risks.md') },
|
|
61
|
+
{ nome: 'rules.md', path: path.join(specDir, 'rules.md') },
|
|
62
|
+
{ nome: 'tasks/active.md', path: path.join(specDir, 'tasks', 'active.md') },
|
|
63
|
+
{ nome: 'tasks/backlog.md', path: path.join(specDir, 'tasks', 'backlog.md') },
|
|
64
|
+
];
|
|
65
|
+
const conteudos = [];
|
|
66
|
+
for (const arq of arquivos) {
|
|
67
|
+
if (fs.existsSync(arq.path)) {
|
|
68
|
+
const conteudo = fs.readFileSync(arq.path, 'utf-8');
|
|
69
|
+
conteudos.push(`### ${arq.nome}\n\`\`\`\n${conteudo}\n\`\`\``);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
spinner.succeed('Spec lido');
|
|
73
|
+
const prompt = gerarPrompt(conteudos.join('\n\n'));
|
|
74
|
+
const promptPath = path.join(specDir, 'enrich-prompt.md');
|
|
75
|
+
const s2 = (0, ora_1.default)('Gerando prompt...').start();
|
|
76
|
+
fs.writeFileSync(promptPath, prompt, 'utf-8');
|
|
77
|
+
s2.succeed('.spec/enrich-prompt.md gerado');
|
|
78
|
+
console.log(chalk_1.default.green.bold('\n✅ Prompt pronto!\n'));
|
|
79
|
+
console.log(chalk_1.default.white(' Proximos passos:\n'));
|
|
80
|
+
console.log(chalk_1.default.gray(' 1. Abra o arquivo: ') + chalk_1.default.white('.spec/enrich-prompt.md'));
|
|
81
|
+
console.log(chalk_1.default.gray(' 2. Cole o conteudo no seu agente de IA (Claude Code, Cursor, Codex)'));
|
|
82
|
+
console.log(chalk_1.default.gray(' 3. Responda as perguntas que a IA fizer'));
|
|
83
|
+
console.log(chalk_1.default.gray(' 4. Salve as respostas nos arquivos de spec relevantes\n'));
|
|
84
|
+
console.log(chalk_1.default.hex('#2D7DD2')(' Dica: use o modo 4 do protocolo Vireum para garantir que as respostas\n sejam incorporadas corretamente ao spec.\n'));
|
|
85
|
+
}
|
|
86
|
+
// ─── GERADOR DE PROMPT ────────────────────────────────────────────────────────
|
|
87
|
+
function gerarPrompt(specConteudo) {
|
|
88
|
+
return `# Vireum Spec — Enrich Prompt
|
|
89
|
+
|
|
90
|
+
> Cole este prompt inteiro no seu agente de IA (Claude Code, Cursor, Codex CLI).
|
|
91
|
+
> O agente vai analisar o spec e fazer perguntas para preencher os gaps.
|
|
92
|
+
> Responda as perguntas e salve as respostas nos arquivos de spec relevantes.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Instrucao para a IA
|
|
97
|
+
|
|
98
|
+
Voce e um especialista em desenvolvimento de software e analise de requisitos.
|
|
99
|
+
Analise o spec abaixo de um projeto em desenvolvimento e identifique:
|
|
100
|
+
|
|
101
|
+
1. **Gaps de negocio** — informacoes sobre o negocio que estao faltando ou vagas
|
|
102
|
+
2. **Gaps tecnicos** — decisoes arquiteturais nao documentadas ou ambiguas
|
|
103
|
+
3. **Riscos nao mapeados** — situacoes de risco que nao foram identificadas
|
|
104
|
+
4. **Regras de negocio implicitas** — comportamentos que provavelmente existem mas nao estao documentados
|
|
105
|
+
5. **Ambiguidades** — partes do spec que podem ser interpretadas de formas diferentes
|
|
106
|
+
|
|
107
|
+
Para cada gap identificado, faca UMA pergunta clara e direta ao dev.
|
|
108
|
+
Organize as perguntas por prioridade — comece pelas mais criticas para o desenvolvimento.
|
|
109
|
+
Limite a no maximo 15 perguntas — foque no que realmente importa.
|
|
110
|
+
|
|
111
|
+
Apos o dev responder, indique em qual arquivo de spec cada resposta deve ser salva:
|
|
112
|
+
- Regras de negocio → .spec/requirements.md
|
|
113
|
+
- Decisoes tecnicas → .spec/architecture.md
|
|
114
|
+
- Riscos → .spec/risks.md
|
|
115
|
+
- Perfis de usuario → .spec/users.md
|
|
116
|
+
- Regras do projeto → .spec/rules.md
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Spec atual do projeto
|
|
121
|
+
|
|
122
|
+
${specConteudo}
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Formato esperado da sua resposta
|
|
127
|
+
|
|
128
|
+
Comece com um resumo de 2-3 linhas do que voce entendeu sobre o projeto.
|
|
129
|
+
Depois liste as perguntas numeradas, cada uma com:
|
|
130
|
+
- A pergunta em si
|
|
131
|
+
- Por que essa informacao e importante
|
|
132
|
+
- Onde a resposta deve ser salva
|
|
133
|
+
|
|
134
|
+
Exemplo:
|
|
135
|
+
**Pergunta 1:** Como o sistema lida com usuarios inativos?
|
|
136
|
+
**Importancia:** Afeta logica de autenticacao e limpeza de dados
|
|
137
|
+
**Salvar em:** .spec/requirements.md e .spec/rules.md
|
|
138
|
+
`;
|
|
139
|
+
}
|
package/dist/commands/health.js
CHANGED
|
@@ -46,7 +46,6 @@ async function runHealth() {
|
|
|
46
46
|
const specDir = path.join(process.cwd(), '.spec');
|
|
47
47
|
const vireumDir = path.join(process.cwd(), '.vireum');
|
|
48
48
|
const spinner = (0, ora_1.default)('Verificando spec...').start();
|
|
49
|
-
await sleep(600);
|
|
50
49
|
spinner.stop();
|
|
51
50
|
const problemas = [];
|
|
52
51
|
const avisos = [];
|
|
@@ -167,6 +166,3 @@ async function runHealth() {
|
|
|
167
166
|
console.log(chalk_1.default.red(` ${problemas.length} problema(s) crítico(s) encontrado(s). Resolva antes de continuar.\n`));
|
|
168
167
|
}
|
|
169
168
|
}
|
|
170
|
-
function sleep(ms) {
|
|
171
|
-
return new Promise(r => setTimeout(r, ms));
|
|
172
|
-
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runInitAi = runInitAi;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const prompts_1 = require("@inquirer/prompts");
|
|
9
|
+
const system_1 = require("./system");
|
|
10
|
+
async function runInitAi() {
|
|
11
|
+
console.log(chalk_1.default.hex('#2D7DD2').bold('\n Vireum Spec — Briefing Interativo (IA)\n'));
|
|
12
|
+
console.log(chalk_1.default.gray(' Responda as perguntas abaixo. As respostas serão salvas em .spec/briefing.md\n'));
|
|
13
|
+
// ── 1. Informações Gerais ──────────────────────────────────────────────────
|
|
14
|
+
console.log(chalk_1.default.hex('#2D7DD2').bold('📌 1. Informações Gerais\n'));
|
|
15
|
+
const geral = {
|
|
16
|
+
projeto: await (0, prompts_1.input)({ message: 'Nome do projeto:' }),
|
|
17
|
+
cliente: await (0, prompts_1.input)({ message: 'Nome do cliente:' }),
|
|
18
|
+
responsavel: await (0, prompts_1.input)({ message: 'Responsável pelo projeto (Vireum):' }),
|
|
19
|
+
data: await (0, prompts_1.input)({ message: 'Data da reunião:', default: new Date().toLocaleDateString('pt-BR') }),
|
|
20
|
+
};
|
|
21
|
+
// ── 2. Problema e Caso de Uso ──────────────────────────────────────────────
|
|
22
|
+
console.log(chalk_1.default.hex('#2D7DD2').bold('\n🎯 2. Problema e Caso de Uso\n'));
|
|
23
|
+
const problema = {
|
|
24
|
+
tarefa: await (0, prompts_1.input)({ message: 'Qual tarefa repetitiva ou custosa a IA vai resolver?' }),
|
|
25
|
+
quem_faz: await (0, prompts_1.input)({ message: 'Quem executa essa tarefa hoje?' }),
|
|
26
|
+
tempo_atual: await (0, prompts_1.input)({ message: 'Quanto tempo leva hoje? (ex: 2h por dia, 30min por atendimento)' }),
|
|
27
|
+
caso_uso: await (0, prompts_1.select)({
|
|
28
|
+
message: 'Caso de uso mais próximo:',
|
|
29
|
+
choices: [
|
|
30
|
+
{ name: 'Chatbot de atendimento (docs / FAQ)', value: 'Chatbot de atendimento' },
|
|
31
|
+
{ name: 'Agente WhatsApp automático', value: 'Agente WhatsApp' },
|
|
32
|
+
{ name: 'Qualificação automática de leads', value: 'Qualificação de leads' },
|
|
33
|
+
{ name: 'Resumo automático de reuniões', value: 'Resumo de reuniões' },
|
|
34
|
+
{ name: 'Extração de dados de documentos', value: 'Extração de dados' },
|
|
35
|
+
{ name: 'Gerador de conteúdo / descrições', value: 'Geração de conteúdo' },
|
|
36
|
+
{ name: 'Recomendação personalizada', value: 'Recomendação' },
|
|
37
|
+
{ name: 'Outro', value: 'Outro' },
|
|
38
|
+
],
|
|
39
|
+
}),
|
|
40
|
+
caso_uso_detalhe: await (0, prompts_1.input)({ message: 'Descreva melhor o caso de uso (se "Outro" ou precisar de detalhes):' }),
|
|
41
|
+
prazo_mvp: await (0, prompts_1.input)({ message: 'Prazo esperado para o MVP:' }),
|
|
42
|
+
};
|
|
43
|
+
// ── 3. Conhecimento e Dados ────────────────────────────────────────────────
|
|
44
|
+
console.log(chalk_1.default.hex('#2D7DD2').bold('\n📚 3. Fonte de Conhecimento e Dados\n'));
|
|
45
|
+
const conhecimento = {
|
|
46
|
+
fonte: await (0, prompts_1.select)({
|
|
47
|
+
message: 'Fonte de conhecimento da IA:',
|
|
48
|
+
choices: [
|
|
49
|
+
{ name: 'Documentos internos (PDFs, Word, planilhas)', value: 'Documentos internos' },
|
|
50
|
+
{ name: 'Banco de dados da empresa', value: 'Banco de dados' },
|
|
51
|
+
{ name: 'Site / páginas web', value: 'Site / Web' },
|
|
52
|
+
{ name: 'API externa', value: 'API externa' },
|
|
53
|
+
{ name: 'Múltiplas fontes', value: 'Múltiplas fontes' },
|
|
54
|
+
{ name: 'Nenhuma (usa só o modelo base)', value: 'Modelo base' },
|
|
55
|
+
],
|
|
56
|
+
}),
|
|
57
|
+
dados_existem: await (0, prompts_1.confirm)({ message: 'Os dados já existem ou precisam ser coletados?', default: true }),
|
|
58
|
+
volume_docs: await (0, prompts_1.input)({ message: 'Volume de documentos/dados (ex: 50 PDFs, 10k registros):' }),
|
|
59
|
+
atualizacao: await (0, prompts_1.select)({
|
|
60
|
+
message: 'Frequência de atualização do conhecimento:',
|
|
61
|
+
choices: [
|
|
62
|
+
{ name: 'Estático (raramente muda)', value: 'Estático' },
|
|
63
|
+
{ name: 'Mensal', value: 'Mensal' },
|
|
64
|
+
{ name: 'Semanal', value: 'Semanal' },
|
|
65
|
+
{ name: 'Diário / tempo real', value: 'Tempo real' },
|
|
66
|
+
],
|
|
67
|
+
}),
|
|
68
|
+
};
|
|
69
|
+
// ── 4. Interface e Interação ───────────────────────────────────────────────
|
|
70
|
+
console.log(chalk_1.default.hex('#2D7DD2').bold('\n💬 4. Interface e Interação\n'));
|
|
71
|
+
const interface_ = {
|
|
72
|
+
canal: await (0, prompts_1.select)({
|
|
73
|
+
message: 'Como o usuário vai interagir?',
|
|
74
|
+
choices: [
|
|
75
|
+
{ name: 'Chat em site / app', value: 'Chat web' },
|
|
76
|
+
{ name: 'WhatsApp', value: 'WhatsApp' },
|
|
77
|
+
{ name: 'E-mail', value: 'E-mail' },
|
|
78
|
+
{ name: 'Telegram', value: 'Telegram' },
|
|
79
|
+
{ name: 'Roda em background (sem UI)', value: 'Background' },
|
|
80
|
+
{ name: 'API chamada por outro sistema', value: 'API interna' },
|
|
81
|
+
],
|
|
82
|
+
}),
|
|
83
|
+
tem_interface: await (0, prompts_1.confirm)({ message: 'Precisa de interface visual (painel admin, dashboard)?', default: false }),
|
|
84
|
+
usuarios: await (0, prompts_1.input)({ message: 'Quem vai usar / quantas pessoas interagem?' }),
|
|
85
|
+
autonomia: await (0, prompts_1.select)({
|
|
86
|
+
message: 'A IA só responde ou também executa ações?',
|
|
87
|
+
choices: [
|
|
88
|
+
{ name: 'Só responde — chatbot, Q&A, resumos', value: 'Só responde' },
|
|
89
|
+
{ name: 'Executa ações simples — envia e-mail, cria registro', value: 'Executa ações simples' },
|
|
90
|
+
{ name: 'Agente completo — usa ferramentas, toma decisões', value: 'Agente completo' },
|
|
91
|
+
],
|
|
92
|
+
}),
|
|
93
|
+
};
|
|
94
|
+
// ── 5. Modelo e Infraestrutura ─────────────────────────────────────────────
|
|
95
|
+
console.log(chalk_1.default.hex('#2D7DD2').bold('\n🤖 5. Modelo e Infraestrutura\n'));
|
|
96
|
+
const modelo = {
|
|
97
|
+
provider: await (0, prompts_1.select)({
|
|
98
|
+
message: 'Provider do modelo de IA:',
|
|
99
|
+
choices: [
|
|
100
|
+
{ name: 'OpenAI (GPT-4o, GPT-4)', value: 'OpenAI' },
|
|
101
|
+
{ name: 'Anthropic (Claude)', value: 'Anthropic' },
|
|
102
|
+
{ name: 'Google (Gemini)', value: 'Google' },
|
|
103
|
+
{ name: 'Open source (Llama, etc.)', value: 'Open source' },
|
|
104
|
+
{ name: 'A definir', value: 'A definir' },
|
|
105
|
+
],
|
|
106
|
+
}),
|
|
107
|
+
restricao_custo: await (0, prompts_1.confirm)({ message: 'Há restrição de custo por uso (ex: orçamento mensal de API)?', default: false }),
|
|
108
|
+
custo_detalhe: await (0, prompts_1.input)({ message: 'Orçamento ou limite (deixe em branco se não):' }),
|
|
109
|
+
dados_sensiveis: await (0, prompts_1.confirm)({ message: 'Haverá dados sensíveis (saúde, financeiro, pessoal) no contexto?', default: false }),
|
|
110
|
+
rodar_local: await (0, prompts_1.confirm)({ message: 'Restrição de enviar dados para API externa (precisa rodar local)?', default: false }),
|
|
111
|
+
integracao_sistema: await (0, prompts_1.input)({ message: 'Integra com algum sistema existente? (CRM, ERP, WhatsApp Business, etc. — deixe em branco se não):' }),
|
|
112
|
+
custo_operacional: await (0, prompts_1.select)({
|
|
113
|
+
message: 'Custo operacional mensal estimado (API de IA + infra):',
|
|
114
|
+
choices: [
|
|
115
|
+
{ name: 'Até R$ 200 — baixo volume, uso interno', value: 'Até R$ 200' },
|
|
116
|
+
{ name: 'R$ 200–800 — volume moderado', value: 'R$ 200–800' },
|
|
117
|
+
{ name: 'R$ 800–3k — alto volume ou modelo pesado', value: 'R$ 800–3k' },
|
|
118
|
+
{ name: 'Acima de R$ 3k — missão crítica / escala empresarial', value: 'Acima de R$ 3k' },
|
|
119
|
+
{ name: 'A definir com o cliente', value: 'A definir' },
|
|
120
|
+
],
|
|
121
|
+
}),
|
|
122
|
+
};
|
|
123
|
+
// ── 6. Qualidade e Supervisão ──────────────────────────────────────────────
|
|
124
|
+
console.log(chalk_1.default.hex('#2D7DD2').bold('\n✅ 6. Qualidade e Supervisão\n'));
|
|
125
|
+
const qualidade = {
|
|
126
|
+
criterio_sucesso: await (0, prompts_1.input)({ message: 'O que define que a IA respondeu bem? (ex: resolve dúvida sem escalada, extrai campo correto)' }),
|
|
127
|
+
supervisao: await (0, prompts_1.select)({
|
|
128
|
+
message: 'Nível de supervisão humana:',
|
|
129
|
+
choices: [
|
|
130
|
+
{ name: '100% automático — sem revisão humana', value: '100% automático' },
|
|
131
|
+
{ name: 'Supervisão ocasional — humano revisa às vezes', value: 'Supervisão ocasional' },
|
|
132
|
+
{ name: 'Human-in-the-loop — aprovação antes de agir', value: 'Human-in-the-loop' },
|
|
133
|
+
],
|
|
134
|
+
}),
|
|
135
|
+
fallback: await (0, prompts_1.confirm)({ message: 'Precisa de fallback para atendente humano quando a IA não sabe?', default: false }),
|
|
136
|
+
};
|
|
137
|
+
const briefing = gerarBriefingAi({ geral, problema, conhecimento, interface_, modelo, qualidade });
|
|
138
|
+
(0, system_1.salvarBriefing)(briefing, 'ai');
|
|
139
|
+
}
|
|
140
|
+
function gerarBriefingAi(data) {
|
|
141
|
+
const { geral, problema, conhecimento, interface_, modelo, qualidade } = data;
|
|
142
|
+
return `# Briefing — ${geral.projeto}
|
|
143
|
+
|
|
144
|
+
## 📌 1. Informações Gerais
|
|
145
|
+
- **Projeto:** ${geral.projeto}
|
|
146
|
+
- **Cliente:** ${geral.cliente}
|
|
147
|
+
- **Responsável:** ${geral.responsavel}
|
|
148
|
+
- **Data da reunião:** ${geral.data}
|
|
149
|
+
- **Tipo:** Produto / Feature de IA
|
|
150
|
+
- **Versão:** 1.0
|
|
151
|
+
|
|
152
|
+
## 🎯 2. Problema e Caso de Uso
|
|
153
|
+
- **Tarefa que a IA vai resolver:** ${problema.tarefa}
|
|
154
|
+
- **Quem executa hoje:** ${problema.quem_faz}
|
|
155
|
+
- **Tempo atual:** ${problema.tempo_atual}
|
|
156
|
+
- **Caso de uso:** ${problema.caso_uso}
|
|
157
|
+
${problema.caso_uso_detalhe ? `- **Detalhes:** ${problema.caso_uso_detalhe}` : ''}
|
|
158
|
+
- **Prazo do MVP:** ${problema.prazo_mvp}
|
|
159
|
+
|
|
160
|
+
## 📚 3. Fonte de Conhecimento e Dados
|
|
161
|
+
- **Fonte:** ${conhecimento.fonte}
|
|
162
|
+
- Dados já existem: ${conhecimento.dados_existem ? 'Sim' : 'Não — precisam ser coletados'}
|
|
163
|
+
- Volume: ${conhecimento.volume_docs || 'A definir'}
|
|
164
|
+
- Frequência de atualização: ${conhecimento.atualizacao}
|
|
165
|
+
|
|
166
|
+
## 💬 4. Interface e Interação
|
|
167
|
+
- **Canal de interação:** ${interface_.canal}
|
|
168
|
+
- **Autonomia:** ${interface_.autonomia}
|
|
169
|
+
- Interface visual (painel/dashboard): ${interface_.tem_interface ? 'Sim' : 'Não'}
|
|
170
|
+
- Usuários: ${interface_.usuarios}
|
|
171
|
+
|
|
172
|
+
## 🤖 5. Modelo e Infraestrutura
|
|
173
|
+
- **Provider:** ${modelo.provider}
|
|
174
|
+
- Restrição de custo: ${modelo.restricao_custo ? 'Sim' : 'Não'}
|
|
175
|
+
${modelo.custo_detalhe ? `- Orçamento/limite: ${modelo.custo_detalhe}` : ''}
|
|
176
|
+
- Dados sensíveis: ${modelo.dados_sensiveis ? 'Sim' : 'Não'}
|
|
177
|
+
- Restrição de API externa (rodar local): ${modelo.rodar_local ? 'Sim — deve rodar localmente' : 'Não — pode usar API externa'}
|
|
178
|
+
${modelo.integracao_sistema ? `- Integração com sistema existente: ${modelo.integracao_sistema}` : ''}
|
|
179
|
+
- Custo operacional estimado: ${modelo.custo_operacional}
|
|
180
|
+
|
|
181
|
+
## ✅ 6. Qualidade e Supervisão
|
|
182
|
+
- **Critério de sucesso:** ${qualidade.criterio_sucesso}
|
|
183
|
+
- **Supervisão humana:** ${qualidade.supervisao}
|
|
184
|
+
- Fallback para humano: ${qualidade.fallback ? 'Sim' : 'Não'}
|
|
185
|
+
`;
|
|
186
|
+
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runInitApi = runInitApi;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const prompts_1 = require("@inquirer/prompts");
|
|
9
|
+
const system_1 = require("./system");
|
|
10
|
+
async function runInitApi() {
|
|
11
|
+
console.log(chalk_1.default.hex('#2D7DD2').bold('\n Vireum Spec — Briefing Interativo (API)\n'));
|
|
12
|
+
console.log(chalk_1.default.gray(' Responda as perguntas abaixo. As respostas serão salvas em .spec/briefing.md\n'));
|
|
13
|
+
// ── 1. Informações Gerais ──────────────────────────────────────────────────
|
|
14
|
+
console.log(chalk_1.default.hex('#2D7DD2').bold('📌 1. Informações Gerais\n'));
|
|
15
|
+
const geral = {
|
|
16
|
+
projeto: await (0, prompts_1.input)({ message: 'Nome do projeto:' }),
|
|
17
|
+
cliente: await (0, prompts_1.input)({ message: 'Nome do cliente:' }),
|
|
18
|
+
responsavel: await (0, prompts_1.input)({ message: 'Responsável pelo projeto (Vireum):' }),
|
|
19
|
+
data: await (0, prompts_1.input)({ message: 'Data da reunião:', default: new Date().toLocaleDateString('pt-BR') }),
|
|
20
|
+
};
|
|
21
|
+
// ── 2. Objetivo ────────────────────────────────────────────────────────────
|
|
22
|
+
console.log(chalk_1.default.hex('#2D7DD2').bold('\n🎯 2. Objetivo da API\n'));
|
|
23
|
+
const objetivo = {
|
|
24
|
+
objetivo: await (0, prompts_1.input)({ message: 'O que esta API faz? Qual é seu propósito?' }),
|
|
25
|
+
visibilidade: await (0, prompts_1.select)({
|
|
26
|
+
message: 'A API será pública ou privada?',
|
|
27
|
+
choices: [
|
|
28
|
+
{ name: 'Privada (uso interno / frontend próprio)', value: 'Privada' },
|
|
29
|
+
{ name: 'Pública (terceiros podem consumir)', value: 'Pública' },
|
|
30
|
+
{ name: 'Ambas', value: 'Ambas' },
|
|
31
|
+
],
|
|
32
|
+
}),
|
|
33
|
+
consumidores: await (0, prompts_1.select)({
|
|
34
|
+
message: 'Quem vai consumir esta API?',
|
|
35
|
+
choices: [
|
|
36
|
+
{ name: 'Frontend próprio', value: 'Frontend próprio' },
|
|
37
|
+
{ name: 'App mobile próprio', value: 'App mobile próprio' },
|
|
38
|
+
{ name: 'Terceiros / parceiros', value: 'Terceiros / parceiros' },
|
|
39
|
+
{ name: 'Múltiplos consumidores', value: 'Múltiplos consumidores' },
|
|
40
|
+
],
|
|
41
|
+
}),
|
|
42
|
+
endpoints_principais: await (0, prompts_1.input)({ message: 'Principais recursos/endpoints (separados por vírgula, ex: /users, /orders, /products):' }),
|
|
43
|
+
prazo_mvp: await (0, prompts_1.input)({ message: 'Prazo esperado para o MVP:' }),
|
|
44
|
+
};
|
|
45
|
+
// ── 3. Autenticação e Segurança ────────────────────────────────────────────
|
|
46
|
+
console.log(chalk_1.default.hex('#2D7DD2').bold('\n🔐 3. Autenticação e Segurança\n'));
|
|
47
|
+
const seguranca = {
|
|
48
|
+
auth: await (0, prompts_1.select)({
|
|
49
|
+
message: 'Tipo de autenticação:',
|
|
50
|
+
choices: [
|
|
51
|
+
{ name: 'JWT + Refresh Token', value: 'JWT + Refresh Token' },
|
|
52
|
+
{ name: 'API Key', value: 'API Key' },
|
|
53
|
+
{ name: 'OAuth 2.0', value: 'OAuth 2.0' },
|
|
54
|
+
{ name: 'Sem autenticação', value: 'Sem autenticação' },
|
|
55
|
+
{ name: 'A definir', value: 'A definir' },
|
|
56
|
+
],
|
|
57
|
+
}),
|
|
58
|
+
multi_tenancy: await (0, prompts_1.confirm)({ message: 'Haverá multi-tenancy (múltiplos clientes isolados)?', default: false }),
|
|
59
|
+
rate_limiting: await (0, prompts_1.confirm)({ message: 'Precisa de rate limiting?', default: true }),
|
|
60
|
+
cors: await (0, prompts_1.confirm)({ message: 'Precisa configurar CORS?', default: true }),
|
|
61
|
+
dados_sensiveis: await (0, prompts_1.confirm)({ message: 'Armazenará dados sensíveis (senhas, CPF, saúde)?', default: false }),
|
|
62
|
+
lgpd: await (0, prompts_1.confirm)({ message: 'Precisa de conformidade com LGPD?', default: true }),
|
|
63
|
+
};
|
|
64
|
+
// ── 4. Banco de Dados ──────────────────────────────────────────────────────
|
|
65
|
+
console.log(chalk_1.default.hex('#2D7DD2').bold('\n🗄️ 4. Banco de Dados\n'));
|
|
66
|
+
const banco = {
|
|
67
|
+
tipo: await (0, prompts_1.select)({
|
|
68
|
+
message: 'Banco de dados:',
|
|
69
|
+
choices: [
|
|
70
|
+
{ name: 'PostgreSQL', value: 'PostgreSQL' },
|
|
71
|
+
{ name: 'Supabase', value: 'Supabase' },
|
|
72
|
+
{ name: 'MySQL', value: 'MySQL' },
|
|
73
|
+
{ name: 'MongoDB', value: 'MongoDB' },
|
|
74
|
+
{ name: 'SQLite', value: 'SQLite' },
|
|
75
|
+
{ name: 'A definir', value: 'A definir' },
|
|
76
|
+
],
|
|
77
|
+
}),
|
|
78
|
+
orm: await (0, prompts_1.select)({
|
|
79
|
+
message: 'ORM / query builder:',
|
|
80
|
+
choices: [
|
|
81
|
+
{ name: 'Prisma', value: 'Prisma' },
|
|
82
|
+
{ name: 'TypeORM', value: 'TypeORM' },
|
|
83
|
+
{ name: 'Drizzle', value: 'Drizzle' },
|
|
84
|
+
{ name: 'Knex', value: 'Knex' },
|
|
85
|
+
{ name: 'Nenhum (SQL puro)', value: 'SQL puro' },
|
|
86
|
+
],
|
|
87
|
+
}),
|
|
88
|
+
cache: await (0, prompts_1.confirm)({ message: 'Precisa de cache (Redis)?', default: false }),
|
|
89
|
+
};
|
|
90
|
+
// ── 5. Modelo de Dados ─────────────────────────────────────────────────────
|
|
91
|
+
console.log(chalk_1.default.hex('#2D7DD2').bold('\n🧩 5. Modelo de Dados\n'));
|
|
92
|
+
const modelo = {
|
|
93
|
+
entidades: await (0, prompts_1.select)({
|
|
94
|
+
message: 'Quantas entidades principais estima?',
|
|
95
|
+
choices: [
|
|
96
|
+
{ name: '1–5 (simples)', value: '1–5' },
|
|
97
|
+
{ name: '6–15 (moderado)', value: '6–15' },
|
|
98
|
+
{ name: '16+ (complexo)', value: '16+' },
|
|
99
|
+
],
|
|
100
|
+
}),
|
|
101
|
+
relacionamentos_complexos: await (0, prompts_1.confirm)({ message: 'Existem relacionamentos complexos (many-to-many, hierarquias)?', default: false }),
|
|
102
|
+
};
|
|
103
|
+
// ── 6. Documentação ────────────────────────────────────────────────────────
|
|
104
|
+
console.log(chalk_1.default.hex('#2D7DD2').bold('\n📄 6. Documentação\n'));
|
|
105
|
+
const docs = {
|
|
106
|
+
swagger: await (0, prompts_1.confirm)({ message: 'Precisa de documentação Swagger / OpenAPI?', default: false }),
|
|
107
|
+
versioning: await (0, prompts_1.confirm)({ message: 'A API terá versionamento (v1, v2)?', default: false }),
|
|
108
|
+
sdk: await (0, prompts_1.confirm)({ message: 'Será necessário gerar SDK para consumidores?', default: false }),
|
|
109
|
+
};
|
|
110
|
+
// ── 7. Deploy e Ambientes ──────────────────────────────────────────────────
|
|
111
|
+
console.log(chalk_1.default.hex('#2D7DD2').bold('\n🚀 7. Deploy e Ambientes\n'));
|
|
112
|
+
const deploy = {
|
|
113
|
+
plataforma: await (0, prompts_1.select)({
|
|
114
|
+
message: 'Plataforma de deploy:',
|
|
115
|
+
choices: [
|
|
116
|
+
{ name: 'Railway', value: 'Railway' },
|
|
117
|
+
{ name: 'Render', value: 'Render' },
|
|
118
|
+
{ name: 'AWS / GCP / Azure', value: 'Cloud (AWS/GCP/Azure)' },
|
|
119
|
+
{ name: 'VPS própria', value: 'VPS' },
|
|
120
|
+
{ name: 'Docker / K8s', value: 'Docker/K8s' },
|
|
121
|
+
{ name: 'A definir', value: 'A definir' },
|
|
122
|
+
],
|
|
123
|
+
}),
|
|
124
|
+
custo_operacional: await (0, prompts_1.select)({
|
|
125
|
+
message: 'Custo operacional mensal estimado:',
|
|
126
|
+
choices: [
|
|
127
|
+
{ name: 'Até R$ 200 — projeto leve, baixo tráfego', value: 'Até R$ 200' },
|
|
128
|
+
{ name: 'R$ 200–800 — projeto moderado', value: 'R$ 200–800' },
|
|
129
|
+
{ name: 'R$ 800–3k — projeto robusto', value: 'R$ 800–3k' },
|
|
130
|
+
{ name: 'Acima de R$ 3k — missão crítica / alta escala', value: 'Acima de R$ 3k' },
|
|
131
|
+
{ name: 'A definir com o cliente', value: 'A definir' },
|
|
132
|
+
],
|
|
133
|
+
}),
|
|
134
|
+
webhooks: await (0, prompts_1.confirm)({ message: 'Precisa de webhooks para integração com terceiros?', default: false }),
|
|
135
|
+
staging: await (0, prompts_1.confirm)({ message: 'Precisa de ambiente de staging?', default: false }),
|
|
136
|
+
cicd: await (0, prompts_1.confirm)({ message: 'Precisa de CI/CD?', default: false }),
|
|
137
|
+
monitoramento: await (0, prompts_1.confirm)({ message: 'Precisa de monitoramento / alertas de saúde?', default: false }),
|
|
138
|
+
};
|
|
139
|
+
const briefing = gerarBriefingApi({ geral, objetivo, seguranca, banco, modelo, docs, deploy });
|
|
140
|
+
(0, system_1.salvarBriefing)(briefing, 'api');
|
|
141
|
+
}
|
|
142
|
+
function gerarBriefingApi(data) {
|
|
143
|
+
const { geral, objetivo, seguranca, banco, modelo, docs, deploy } = data;
|
|
144
|
+
const endpoints = objetivo.endpoints_principais
|
|
145
|
+
.split(',').map((e) => `- ${e.trim()}`).join('\n');
|
|
146
|
+
return `# Briefing — ${geral.projeto}
|
|
147
|
+
|
|
148
|
+
## 📌 1. Informações Gerais
|
|
149
|
+
- **Projeto:** ${geral.projeto}
|
|
150
|
+
- **Cliente:** ${geral.cliente}
|
|
151
|
+
- **Responsável:** ${geral.responsavel}
|
|
152
|
+
- **Data da reunião:** ${geral.data}
|
|
153
|
+
- **Tipo:** API / Backend
|
|
154
|
+
- **Versão:** 1.0
|
|
155
|
+
|
|
156
|
+
## 🎯 2. Objetivo da API
|
|
157
|
+
- **Propósito:** ${objetivo.objetivo}
|
|
158
|
+
- **Visibilidade:** ${objetivo.visibilidade}
|
|
159
|
+
- **Consumidores:** ${objetivo.consumidores}
|
|
160
|
+
- **Prazo do MVP:** ${objetivo.prazo_mvp}
|
|
161
|
+
|
|
162
|
+
### Principais recursos
|
|
163
|
+
${endpoints}
|
|
164
|
+
|
|
165
|
+
## 🔐 3. Autenticação e Segurança
|
|
166
|
+
- **Autenticação:** ${seguranca.auth}
|
|
167
|
+
- Multi-tenancy: ${seguranca.multi_tenancy ? 'Sim' : 'Não'}
|
|
168
|
+
- Rate limiting: ${seguranca.rate_limiting ? 'Sim' : 'Não'}
|
|
169
|
+
- CORS configurado: ${seguranca.cors ? 'Sim' : 'Não'}
|
|
170
|
+
- Dados sensíveis: ${seguranca.dados_sensiveis ? 'Sim' : 'Não'}
|
|
171
|
+
- LGPD: ${seguranca.lgpd ? 'Sim' : 'Não'}
|
|
172
|
+
|
|
173
|
+
## 🗄️ 4. Banco de Dados
|
|
174
|
+
- **Banco:** ${banco.tipo}
|
|
175
|
+
- **ORM:** ${banco.orm}
|
|
176
|
+
- Cache (Redis): ${banco.cache ? 'Sim' : 'Não'}
|
|
177
|
+
|
|
178
|
+
## 🧩 5. Modelo de Dados
|
|
179
|
+
- Entidades principais: ${modelo.entidades}
|
|
180
|
+
- Relacionamentos complexos: ${modelo.relacionamentos_complexos ? 'Sim' : 'Não'}
|
|
181
|
+
|
|
182
|
+
## 📄 6. Documentação
|
|
183
|
+
- Swagger / OpenAPI: ${docs.swagger ? 'Sim' : 'Não'}
|
|
184
|
+
- Versionamento de API: ${docs.versioning ? 'Sim' : 'Não'}
|
|
185
|
+
- SDK para consumidores: ${docs.sdk ? 'Sim' : 'Não'}
|
|
186
|
+
|
|
187
|
+
## 🚀 7. Deploy e Ambientes
|
|
188
|
+
- **Plataforma:** ${deploy.plataforma}
|
|
189
|
+
- Custo operacional estimado: ${deploy.custo_operacional}
|
|
190
|
+
- Webhooks para terceiros: ${deploy.webhooks ? 'Sim' : 'Não'}
|
|
191
|
+
- Staging: ${deploy.staging ? 'Sim' : 'Não'}
|
|
192
|
+
- CI/CD: ${deploy.cicd ? 'Sim' : 'Não'}
|
|
193
|
+
- Monitoramento / alertas: ${deploy.monitoramento ? 'Sim' : 'Não'}
|
|
194
|
+
`;
|
|
195
|
+
}
|