vireum-spec-cli 0.1.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.
@@ -0,0 +1,148 @@
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.runVerifyMcps = runVerifyMcps;
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
+ const os = __importStar(require("os"));
45
+ async function runVerifyMcps() {
46
+ console.log(chalk_1.default.hex('#2D7DD2').bold('\n Vireum Spec — Verify MCPs\n'));
47
+ const specDir = path.join(process.cwd(), '.spec');
48
+ const archPath = path.join(specDir, 'architecture.md');
49
+ if (!fs.existsSync(archPath)) {
50
+ console.log(chalk_1.default.red('\n❌ architecture.md não encontrado.'));
51
+ console.log(chalk_1.default.gray(' Execute primeiro: ') + chalk_1.default.white('vireum-spec setup\n'));
52
+ process.exit(1);
53
+ }
54
+ const spinner = (0, ora_1.default)('Lendo MCPs do projeto...').start();
55
+ await sleep(400);
56
+ const arch = fs.readFileSync(archPath, 'utf-8');
57
+ const mcpsProjeto = extrairMcpsProjeto(arch);
58
+ spinner.stop();
59
+ if (mcpsProjeto.length === 0) {
60
+ console.log(chalk_1.default.yellow('\n⚠️ Nenhum MCP configurado neste projeto.\n'));
61
+ console.log(chalk_1.default.gray(' Execute: ') + chalk_1.default.white('vireum-spec setup\n'));
62
+ process.exit(0);
63
+ }
64
+ console.log(chalk_1.default.gray(` MCPs necessários: ${mcpsProjeto.join(', ')}\n`));
65
+ // ── Detectar configs dos clientes ─────────────────────────────────────────
66
+ const home = os.homedir();
67
+ const clientes = [
68
+ {
69
+ nome: 'Claude Code',
70
+ paths: [
71
+ path.join(home, '.claude', 'settings.json'),
72
+ path.join(home, '.claude.json'),
73
+ ],
74
+ },
75
+ {
76
+ nome: 'Cursor',
77
+ paths: [
78
+ path.join(home, '.cursor', 'mcp.json'),
79
+ path.join(home, 'AppData', 'Roaming', 'Cursor', 'User', 'globalStorage', 'mcp.json'),
80
+ ],
81
+ },
82
+ {
83
+ nome: 'Codex CLI',
84
+ paths: [
85
+ path.join(home, '.codex', 'config.json'),
86
+ path.join(home, '.config', 'codex', 'config.json'),
87
+ ],
88
+ },
89
+ ];
90
+ // ── Checar cada cliente ────────────────────────────────────────────────────
91
+ for (const cliente of clientes) {
92
+ console.log(chalk_1.default.white.bold(` ${cliente.nome}`));
93
+ const configPath = cliente.paths.find(p => fs.existsSync(p));
94
+ if (!configPath) {
95
+ console.log(chalk_1.default.gray(` Config não encontrada — cliente pode não estar instalado\n`));
96
+ continue;
97
+ }
98
+ let config = {};
99
+ try {
100
+ config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
101
+ }
102
+ catch {
103
+ console.log(chalk_1.default.yellow(` ⚠ Erro ao ler config em ${configPath}\n`));
104
+ continue;
105
+ }
106
+ const mcpsInstalados = extrairMcpsInstalados(config);
107
+ for (const mcp of mcpsProjeto) {
108
+ const instalado = mcpsInstalados.some(m => m.toLowerCase().includes(mcp.toLowerCase()));
109
+ if (instalado) {
110
+ console.log(chalk_1.default.green(` ✓ ${mcp}`));
111
+ }
112
+ else {
113
+ console.log(chalk_1.default.red(` ✗ ${mcp} — não encontrado`));
114
+ }
115
+ }
116
+ console.log('');
117
+ }
118
+ // ── Instruções ─────────────────────────────────────────────────────────────
119
+ console.log(chalk_1.default.gray(' Para instalar MCPs faltantes consulte: ') + chalk_1.default.white('.spec/mcp-setup.md\n'));
120
+ }
121
+ // ─── HELPERS ──────────────────────────────────────────────────────────────────
122
+ function extrairMcpsProjeto(arch) {
123
+ const idx = arch.indexOf('## MCPs Ativos');
124
+ if (idx === -1)
125
+ return [];
126
+ const secao = arch.slice(idx + '## MCPs Ativos'.length);
127
+ const linhas = secao.split('\n').filter(l => l.startsWith('- '));
128
+ return linhas.map(l => l.replace('- ', '').trim()).filter(Boolean);
129
+ }
130
+ function extrairMcpsInstalados(config) {
131
+ const nomes = [];
132
+ // Claude Code formato: { mcpServers: { "nome": {...} } }
133
+ if (config.mcpServers) {
134
+ nomes.push(...Object.keys(config.mcpServers));
135
+ }
136
+ // Cursor formato: { mcpServers: { "nome": {...} } }
137
+ if (config.mcp?.servers) {
138
+ nomes.push(...Object.keys(config.mcp.servers));
139
+ }
140
+ // Codex formato: { tools: [...] }
141
+ if (config.tools && Array.isArray(config.tools)) {
142
+ nomes.push(...config.tools.map((t) => t.name || t));
143
+ }
144
+ return nomes;
145
+ }
146
+ function sleep(ms) {
147
+ return new Promise(r => setTimeout(r, ms));
148
+ }
package/dist/index.js ADDED
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const commander_1 = require("commander");
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const init_1 = require("./commands/init");
10
+ const distill_1 = require("./commands/distill");
11
+ const setup_1 = require("./commands/setup");
12
+ const prioritize_1 = require("./commands/prioritize");
13
+ const health_1 = require("./commands/health");
14
+ const brief_1 = require("./commands/brief");
15
+ const verify_mcps_1 = require("./commands/verify-mcps");
16
+ const skills_1 = require("./commands/skills");
17
+ const program = new commander_1.Command();
18
+ program
19
+ .name('vireum-spec')
20
+ .description('Spec Driven Development framework by Vireum Desenvolvimento')
21
+ .version('0.1.0');
22
+ program
23
+ .command('init')
24
+ .description('Inicia um novo projeto com briefing interativo')
25
+ .action(async () => { await (0, init_1.runInit)(); });
26
+ program
27
+ .command('distill')
28
+ .description('Gera os arquivos de spec a partir do briefing')
29
+ .action(async () => { await (0, distill_1.runDistill)(); });
30
+ program
31
+ .command('setup')
32
+ .description('Configura stack, infra, MCPs e protocolo da IA')
33
+ .action(async () => { await (0, setup_1.runSetup)(); });
34
+ program
35
+ .command('prioritize')
36
+ .description('Classifica features em MVP, Fase 2 ou fora do escopo')
37
+ .action(async () => { await (0, prioritize_1.runPrioritize)(); });
38
+ program
39
+ .command('health')
40
+ .description('Verifica inconsistencias nos arquivos de spec')
41
+ .action(async () => { await (0, health_1.runHealth)(); });
42
+ program
43
+ .command('brief')
44
+ .description('Gera resumo do estado atual do projeto')
45
+ .action(async () => { await (0, brief_1.runBrief)(); });
46
+ program
47
+ .command('verify-mcps')
48
+ .description('Verifica se os MCPs do projeto estao instalados')
49
+ .action(async () => { await (0, verify_mcps_1.runVerifyMcps)(); });
50
+ program
51
+ .command('skills')
52
+ .description('Instala as skills do framework no cliente de IA')
53
+ .action(async () => { await (0, skills_1.runSkills)(); });
54
+ console.log(chalk_1.default.hex('#2D7DD2').bold('\n Vireum Spec Framework\n'));
55
+ program.parse(process.argv);
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "vireum-spec-cli",
3
+ "version": "0.1.0",
4
+ "description": "Spec Driven Development framework by Vireum Desenvolvimento",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "vireum-spec": "dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "dev": "ts-node src/index.ts",
12
+ "start": "node dist/index.js",
13
+ "prepublishOnly": "npm run build"
14
+ },
15
+ "files": [
16
+ "dist/",
17
+ "src/skills/"
18
+ ],
19
+ "keywords": [
20
+ "spec",
21
+ "cli",
22
+ "development",
23
+ "spec-driven",
24
+ "vireum"
25
+ ],
26
+ "author": "Vireum Desenvolvimento",
27
+ "license": "ISC",
28
+ "dependencies": {
29
+ "@inquirer/prompts": "^7.0.0",
30
+ "chalk": "^5.3.0",
31
+ "commander": "^12.0.0",
32
+ "ora": "^8.0.0"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^20.0.0",
36
+ "ts-node": "^10.9.0",
37
+ "typescript": "^5.0.0"
38
+ }
39
+ }
@@ -0,0 +1,14 @@
1
+ # Skill — Corrigir Bug
2
+
3
+ Quando o dev reportar um erro ou bug:
4
+
5
+ 1. Crie um hotfix em `.spec/tasks/active.md`:
6
+ - Formato: `## [FEATURE-H001] Fix: descrição do bug`
7
+ - Tag: [H] — prioridade crítica
8
+ - Origem: bug reportado em data atual
9
+ 2. Identifique a causa raiz antes de corrigir
10
+ 3. Corrija o bug
11
+ 4. Registre em `.spec/changelog.md`:
12
+ - Data, descrição do bug, causa raiz, solução aplicada
13
+ 5. Verifique se o bug afeta outras tasks em active.md
14
+ 6. Marque o hotfix como done e mova para tasks/done.md
@@ -0,0 +1,21 @@
1
+ # Skill — Contrato de Interface
2
+
3
+ Antes de implementar qualquer feature que envolva frontend E backend:
4
+
5
+ 1. Defina o contrato da API primeiro:
6
+ - Método e rota: `POST /auth/login`
7
+ - Request body com tipos
8
+ - Response de sucesso com tipos
9
+ - Responses de erro possíveis
10
+ 2. Registre o contrato em `.spec/architecture.md`
11
+ 3. Só depois implemente backend e frontend
12
+ 4. Frontend e backend podem rodar em paralelo após contrato definido
13
+
14
+ ## Formato do contrato
15
+ ```
16
+ ### [FEATURE] Nome da feature
17
+ - Rota: METHOD /path
18
+ - Body: { campo: tipo }
19
+ - Response 200: { campo: tipo }
20
+ - Response 4xx: { error: string }
21
+ ```
@@ -0,0 +1,14 @@
1
+ # Skill — Nova Demanda do Cliente
2
+
3
+ Quando o dev mencionar que o cliente pediu algo novo:
4
+
5
+ 1. Verifique se já existe em `.spec/requirements.md`
6
+ 2. Se não existir:
7
+ - Crie task com tag [PENDING] em `.spec/tasks/backlog.md`
8
+ - Formato: `- [ ] [FEATURE-TXXX] nome — [PENDING: aguarda priorização]`
9
+ - Estime o impacto: quais tasks existentes são afetadas?
10
+ 3. Informe o dev:
11
+ - O que foi criado no backlog
12
+ - Quais tasks existentes são impactadas
13
+ - Aguarde decisão antes de implementar
14
+ 4. NUNCA implemente demanda nova sem aprovação explícita do dev
@@ -0,0 +1,21 @@
1
+ # Skill — Verificar Escopo
2
+
3
+ Antes de implementar qualquer coisa, verificar:
4
+
5
+ 1. A solicitação está em `.spec/requirements.md`?
6
+ - Sim → prosseguir normalmente
7
+ - Não → PARAR e avisar o dev (escopo creep)
8
+
9
+ 2. A solicitação está em `.spec/tasks/active.md`?
10
+ - Sim → prosseguir
11
+ - Não → verificar se está no backlog ou é demanda nova
12
+
13
+ 3. Se escopo creep identificado, informar:
14
+ - O que foi solicitado
15
+ - Por que está fora do escopo atual
16
+ - Sugerir criar task [PENDING] no backlog
17
+
18
+ ## Nunca
19
+ - Implementar silenciosamente algo fora do spec
20
+ - Assumir que o dev "já sabe" que é escopo extra
21
+ - Deixar para avisar depois de implementar
@@ -0,0 +1,30 @@
1
+ # Skill — Atualizar Spec
2
+
3
+ Quando e como atualizar cada arquivo de spec:
4
+
5
+ ## INDEX.md
6
+ - Atualizar após cada task concluída
7
+ - Atualizar estado do MVP (checkboxes)
8
+ - Manter enxuto — máximo 50 linhas
9
+
10
+ ## tasks/active.md
11
+ - Marcar task como [x] ao concluir
12
+ - Adicionar hotfixes [H] quando bug identificado
13
+ - Mover tasks concluídas para done.md
14
+
15
+ ## tasks/backlog.md
16
+ - Adicionar [PENDING] quando nova demanda chega
17
+ - Nunca mover para active sem aprovação humana
18
+
19
+ ## architecture.md
20
+ - Registrar TODA decisão técnica relevante
21
+ - Formato: Data | Decisão | Alternativas | Motivo
22
+ - Nunca só registrar o quê — sempre o porquê
23
+
24
+ ## risks.md
25
+ - Adicionar risco novo antes de continuar implementação
26
+ - Formato: Data | Risco | Impacto | Mitigação
27
+
28
+ ## changelog.md
29
+ - Registrar: decisões importantes, causa raiz de bugs, mudanças de escopo
30
+ - Formato: ## DATA — Descrição
@@ -0,0 +1,14 @@
1
+ # Skill — Implementar Task
2
+
3
+ Quando o dev pedir para implementar uma task:
4
+
5
+ 1. Leia `.spec/tasks/active.md` e identifique a task solicitada
6
+ 2. Leia `.spec/requirements.md` para contexto da feature
7
+ 3. Leia `.spec/architecture.md` para decisões técnicas já tomadas
8
+ 4. Verifique os critérios de aceitação da task antes de começar
9
+ 5. Implemente seguindo a camada definida (Backend / Frontend / Integração)
10
+ 6. Ao concluir:
11
+ - Marque o status como [x] em active.md
12
+ - Mova a task para tasks/done.md
13
+ - Atualize o INDEX.md
14
+ - Se tomou decisão arquitetural, registre em architecture.md