vibetachyon 1.5.0 → 1.5.2

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 CHANGED
@@ -2,17 +2,17 @@
2
2
 
3
3
  > O sistema operacional que roda dentro do seu code agent.
4
4
 
5
- Transforma qualquer agente de código (Claude Code, Cursor, Windsurf, Cline...) em uma máquina especializada em desenvolvimento de produtos digitais — com **38 slash commands**, **50+ skills especializadas**, **8 personas** e **workflows estruturados** prontos para usar.
5
+ Transforma qualquer agente de código (Claude Code, Cursor, Windsurf, Cline...) em uma máquina especializada em desenvolvimento de produtos digitais — com **39 slash commands**, **50+ skills especializadas**, **8 personas** e **workflows estruturados** prontos para usar.
6
6
 
7
7
  ```bash
8
- npx vibetachyon-cli
8
+ npx vibetachyon
9
9
  ```
10
10
 
11
11
  ---
12
12
 
13
13
  ## O que você ganha
14
14
 
15
- - **38 slash commands** — `/vibe-review`, `/vibe-test`, `/vibe-explain`, `/vibe-bug`, `/vibe-pr`, `/vibe-changelog`, `/vibe-spec`, `/vibe-dev` e mais
15
+ - **39 slash commands** — `/vibe-review`, `/vibe-test`, `/vibe-explain`, `/vibe-bug`, `/vibe-pr`, `/vibe-changelog`, `/vibe-spec`, `/vibe-dev` e mais
16
16
  - **50+ skills especializadas** — busca de componentes, segurança, performance, ADR, métricas, backlog, geração de testes, code review
17
17
  - **8 personas** — Dev, QA, Architect, PM, Data, UX, DevOps, Analyst
18
18
  - **5 squads pré-configurados** — fullstack, qa-focused, minimal, design, release
@@ -27,7 +27,7 @@ npx vibetachyon-cli
27
27
  ## Instalação
28
28
 
29
29
  ```bash
30
- npx vibetachyon-cli
30
+ npx vibetachyon
31
31
  ```
32
32
 
33
33
  Selecione seu agente, cole o token VibeCodes MAX e pronto.
@@ -35,9 +35,9 @@ Selecione seu agente, cole o token VibeCodes MAX e pronto.
35
35
  ### Flags não-interativas
36
36
 
37
37
  ```bash
38
- npx vibetachyon-cli install --agent claude --token vcf_...
39
- npx vibetachyon-cli install --agent cursor --token vcf_... --dry-run
40
- npx vibetachyon-cli doctor
38
+ npx vibetachyon install --agent claude --token vcf_...
39
+ npx vibetachyon install --agent cursor --token vcf_... --dry-run
40
+ npx vibetachyon doctor
41
41
  ```
42
42
 
43
43
  **Agentes suportados:** `claude` | `cursor` | `windsurf` | `cline` | `copilot` | `gemini` | `codex`
@@ -281,7 +281,7 @@ Activate the Vibe Dev persona for focused implementation work.
281
281
  1. Call \`vibe_persona_activate\` with persona="dev" and the current task as context
282
282
  2. Review the task requirements and acceptance criteria
283
283
  3. Use \`vibe_scan_local_architecture\` to understand the codebase context before writing any code
284
- 4. Use \`vibe_search_snippets\` if the task involves UI components
284
+ 4. **OBRIGATÓRIO para qualquer elemento visual:** Use \`vibe_search_snippets\` ANTES de escrever qualquer componente, botão, card, seção ou layout. Nunca invente UI do zero quando a biblioteca tem 4800+ componentes prontos.
285
285
  5. Implement with these non-negotiable rules:
286
286
  - Zero TypeScript errors before committing
287
287
  - Use \`vibe_self_heal_typescript\` if type errors occur
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AGENT_BIN_MAP = void 0;
6
7
  exports.getActivePersonaPath = getActivePersonaPath;
7
8
  exports.listPersonas = listPersonas;
8
9
  exports.isPersonaId = isPersonaId;
@@ -11,10 +12,23 @@ exports.saveActivePersona = saveActivePersona;
11
12
  exports.loadActivePersona = loadActivePersona;
12
13
  const fs_1 = __importDefault(require("fs"));
13
14
  const path_1 = __importDefault(require("path"));
15
+ // Agent name → persona id map (for CLI bin detection)
16
+ exports.AGENT_BIN_MAP = {
17
+ quasar: 'architect',
18
+ lumen: 'frontend',
19
+ axiom: 'backend',
20
+ cipher: 'security',
21
+ flux: 'performance',
22
+ prism: 'reviewer',
23
+ zenith: 'growth',
24
+ };
14
25
  const PERSONAS = {
15
26
  architect: {
16
27
  id: 'architect',
17
28
  label: 'Architect',
29
+ agentName: 'QUASAR',
30
+ agentColor: '\x1b[38;5;220m',
31
+ agentTagline: 'Projeta sistemas que escalam infinitamente.',
18
32
  description: 'Prioritizes structure, long-term shape, dependency boundaries, and execution sequencing.',
19
33
  defaultChecks: ['context', 'spec', 'gate'],
20
34
  riskTolerance: 'low',
@@ -24,6 +38,9 @@ const PERSONAS = {
24
38
  frontend: {
25
39
  id: 'frontend',
26
40
  label: 'Frontend',
41
+ agentName: 'LUMEN',
42
+ agentColor: '\x1b[38;5;231m',
43
+ agentTagline: 'Interfaces que iluminam a experiência do usuário.',
27
44
  description: 'Prioritizes UI quality, framework fit, and user-facing implementation details.',
28
45
  defaultChecks: ['context', 'frontend', 'gate'],
29
46
  riskTolerance: 'medium',
@@ -33,6 +50,9 @@ const PERSONAS = {
33
50
  backend: {
34
51
  id: 'backend',
35
52
  label: 'Backend',
53
+ agentName: 'AXIOM',
54
+ agentColor: '\x1b[38;5;39m',
55
+ agentTagline: 'A verdade por trás de toda API e banco de dados.',
36
56
  description: 'Prioritizes API contracts, services, persistence, and execution safety on the server side.',
37
57
  defaultChecks: ['context', 'gate'],
38
58
  riskTolerance: 'medium',
@@ -42,6 +62,9 @@ const PERSONAS = {
42
62
  security: {
43
63
  id: 'security',
44
64
  label: 'Security',
65
+ agentName: 'CIPHER',
66
+ agentColor: '\x1b[38;5;46m',
67
+ agentTagline: 'Nenhuma vulnerabilidade escapa do Cipher.',
45
68
  description: 'Prioritizes auth, access scope, unsafe patterns, secrets, and exploit surfaces.',
46
69
  defaultChecks: ['context', 'gate', 'release-evidence'],
47
70
  riskTolerance: 'low',
@@ -51,6 +74,9 @@ const PERSONAS = {
51
74
  performance: {
52
75
  id: 'performance',
53
76
  label: 'Performance',
77
+ agentName: 'FLUX',
78
+ agentColor: '\x1b[38;5;51m',
79
+ agentTagline: 'Velocidade sem resistência.',
54
80
  description: 'Prioritizes Lighthouse budgets, runtime weight, latency, and delivery efficiency.',
55
81
  defaultChecks: ['context', 'frontend', 'perf'],
56
82
  riskTolerance: 'medium',
@@ -60,6 +86,9 @@ const PERSONAS = {
60
86
  reviewer: {
61
87
  id: 'reviewer',
62
88
  label: 'Reviewer',
89
+ agentName: 'PRISM',
90
+ agentColor: '\x1b[38;5;135m',
91
+ agentTagline: 'Enxerga seu código de todos os ângulos.',
63
92
  description: 'Prioritizes findings, regressions, and missing validation before approval.',
64
93
  defaultChecks: ['context', 'gate', 'release-evidence'],
65
94
  riskTolerance: 'low',
@@ -69,6 +98,9 @@ const PERSONAS = {
69
98
  growth: {
70
99
  id: 'growth',
71
100
  label: 'Growth',
101
+ agentName: 'ZENITH',
102
+ agentColor: '\x1b[38;5;208m',
103
+ agentTagline: 'Leva seu SaaS ao ponto mais alto.',
72
104
  description: 'Prioritizes funnels, conversion, tracking, offers, and experiment surfaces.',
73
105
  defaultChecks: ['context', 'frontend', 'gate'],
74
106
  riskTolerance: 'high',
@@ -0,0 +1,322 @@
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.runCipherAudit = runCipherAudit;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ // Padrões de secrets hardcoded
10
+ const SECRET_PATTERNS = [
11
+ { pattern: /sk_live_[a-zA-Z0-9]{20,}/g, label: 'Stripe secret key (live)' },
12
+ { pattern: /sk_test_[a-zA-Z0-9]{20,}/g, label: 'Stripe secret key (test)' },
13
+ { pattern: /rk_live_[a-zA-Z0-9]{20,}/g, label: 'Stripe restricted key (live)' },
14
+ { pattern: /AKIA[0-9A-Z]{16}/g, label: 'AWS Access Key ID' },
15
+ { pattern: /ghp_[a-zA-Z0-9]{36}/g, label: 'GitHub Personal Access Token' },
16
+ { pattern: /xoxb-[0-9]{11}-[0-9]{11}-[a-zA-Z0-9]{24}/g, label: 'Slack Bot Token' },
17
+ { pattern: /AIza[0-9A-Za-z\-_]{35}/g, label: 'Google API Key' },
18
+ { pattern: /eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g, label: 'JWT Token hardcoded' },
19
+ { pattern: /password\s*[:=]\s*["'][^"']{6,}["']/gi, label: 'Hardcoded password' },
20
+ { pattern: /secret\s*[:=]\s*["'][^"']{8,}["']/gi, label: 'Hardcoded secret' },
21
+ { pattern: /api[_-]?key\s*[:=]\s*["'][^"']{8,}["']/gi, label: 'Hardcoded API key' },
22
+ ];
23
+ const SKIP_DIRS = new Set([
24
+ 'node_modules', '.git', '.next', 'dist', 'build', '.turbo',
25
+ 'coverage', '.cache', '__pycache__', 'vendor',
26
+ ]);
27
+ const SCAN_EXTENSIONS = new Set([
28
+ '.ts', '.tsx', '.js', '.jsx', '.env', '.json', '.yaml', '.yml',
29
+ '.py', '.rb', '.go', '.php', '.java', '.cs', '.sh', '.bash',
30
+ ]);
31
+ function walkFiles(dir, maxFiles = 2000) {
32
+ const results = [];
33
+ function recurse(current, depth) {
34
+ if (depth > 8 || results.length >= maxFiles)
35
+ return;
36
+ let entries;
37
+ try {
38
+ entries = fs_1.default.readdirSync(current, { withFileTypes: true });
39
+ }
40
+ catch {
41
+ return;
42
+ }
43
+ for (const entry of entries) {
44
+ if (SKIP_DIRS.has(entry.name))
45
+ continue;
46
+ const full = path_1.default.join(current, entry.name);
47
+ if (entry.isDirectory()) {
48
+ recurse(full, depth + 1);
49
+ }
50
+ else if (entry.isFile()) {
51
+ const ext = path_1.default.extname(entry.name).toLowerCase();
52
+ if (SCAN_EXTENSIONS.has(ext) || entry.name.startsWith('.env')) {
53
+ results.push(full);
54
+ }
55
+ }
56
+ }
57
+ }
58
+ recurse(dir, 0);
59
+ return results;
60
+ }
61
+ function checkSecrets(files, projectRoot) {
62
+ const findings = [];
63
+ for (const file of files) {
64
+ // Pula arquivos de lock e binários
65
+ if (file.endsWith('.lock') || file.endsWith('.min.js'))
66
+ continue;
67
+ let content;
68
+ try {
69
+ content = fs_1.default.readFileSync(file, 'utf8');
70
+ }
71
+ catch {
72
+ continue;
73
+ }
74
+ const lines = content.split('\n');
75
+ for (const { pattern, label } of SECRET_PATTERNS) {
76
+ pattern.lastIndex = 0;
77
+ for (let i = 0; i < lines.length; i++) {
78
+ const line = lines[i];
79
+ if (pattern.test(line)) {
80
+ // Pula se estiver em comentário ou exemplo óbvio
81
+ if (/\/\/.*example|\/\/.*sample|#.*example/i.test(line))
82
+ continue;
83
+ if (/your[_-]?key|placeholder|xxx|abc123/i.test(line))
84
+ continue;
85
+ findings.push({
86
+ severity: 'critical',
87
+ category: 'Secret Exposure',
88
+ message: `${label} encontrado hardcoded`,
89
+ file: path_1.default.relative(projectRoot, file),
90
+ line: i + 1,
91
+ snippet: line.trim().slice(0, 80),
92
+ });
93
+ pattern.lastIndex = 0;
94
+ break; // um finding por arquivo por padrão
95
+ }
96
+ pattern.lastIndex = 0;
97
+ }
98
+ }
99
+ }
100
+ return findings;
101
+ }
102
+ function checkEnvFiles(projectRoot) {
103
+ const findings = [];
104
+ const gitignorePath = path_1.default.join(projectRoot, '.gitignore');
105
+ const envPath = path_1.default.join(projectRoot, '.env');
106
+ const envLocalPath = path_1.default.join(projectRoot, '.env.local');
107
+ let gitignoreContent = '';
108
+ if (fs_1.default.existsSync(gitignorePath)) {
109
+ gitignoreContent = fs_1.default.readFileSync(gitignorePath, 'utf8');
110
+ }
111
+ else {
112
+ findings.push({
113
+ severity: 'warning',
114
+ category: 'Git Security',
115
+ message: '.gitignore não encontrado — secrets podem ser commitados acidentalmente',
116
+ });
117
+ }
118
+ if (fs_1.default.existsSync(envPath)) {
119
+ if (!gitignoreContent.includes('.env')) {
120
+ findings.push({
121
+ severity: 'critical',
122
+ category: 'Git Security',
123
+ message: '.env existe mas NÃO está no .gitignore — risco de exposição de secrets',
124
+ file: '.env',
125
+ });
126
+ }
127
+ else {
128
+ findings.push({
129
+ severity: 'info',
130
+ category: 'Git Security',
131
+ message: '.env presente e protegido pelo .gitignore',
132
+ file: '.env',
133
+ });
134
+ }
135
+ }
136
+ if (fs_1.default.existsSync(envLocalPath) && !gitignoreContent.includes('.env.local')) {
137
+ findings.push({
138
+ severity: 'warning',
139
+ category: 'Git Security',
140
+ message: '.env.local existe mas pode não estar no .gitignore',
141
+ file: '.env.local',
142
+ });
143
+ }
144
+ return findings;
145
+ }
146
+ function checkDependencies(projectRoot) {
147
+ const findings = [];
148
+ const pkgPath = path_1.default.join(projectRoot, 'package.json');
149
+ if (!fs_1.default.existsSync(pkgPath))
150
+ return findings;
151
+ let pkg;
152
+ try {
153
+ pkg = JSON.parse(fs_1.default.readFileSync(pkgPath, 'utf8'));
154
+ }
155
+ catch {
156
+ return findings;
157
+ }
158
+ const allDeps = {
159
+ ...pkg.dependencies,
160
+ ...pkg.devDependencies,
161
+ };
162
+ // Pacotes conhecidamente problemáticos ou abandonados
163
+ const flagged = {
164
+ 'event-stream': 'Pacote comprometido em supply chain attack (2018)',
165
+ 'flatmap-stream': 'Pacote malicioso injetado via event-stream',
166
+ 'node-uuid': 'Deprecated — use "uuid" em vez disso',
167
+ 'request': 'Deprecated e não mantido desde 2020',
168
+ 'lodash': 'Versões < 4.17.21 têm vulnerabilidade de prototype pollution',
169
+ };
170
+ for (const [dep, reason] of Object.entries(flagged)) {
171
+ if (allDeps[dep]) {
172
+ findings.push({
173
+ severity: dep === 'event-stream' || dep === 'flatmap-stream' ? 'critical' : 'warning',
174
+ category: 'Dependencies',
175
+ message: `${dep}@${allDeps[dep]}: ${reason}`,
176
+ });
177
+ }
178
+ }
179
+ // Verifica se tem npm audit disponível
180
+ findings.push({
181
+ severity: 'info',
182
+ category: 'Dependencies',
183
+ message: `${Object.keys(allDeps).length} dependências encontradas. Rode "npm audit" para verificação completa.`,
184
+ });
185
+ return findings;
186
+ }
187
+ function checkAuthPatterns(files, projectRoot) {
188
+ const findings = [];
189
+ // Rotas sem middleware de auth em Next.js/Express
190
+ const routeFiles = files.filter(f => (f.includes('/api/') || f.includes('/routes/')) &&
191
+ (f.endsWith('.ts') || f.endsWith('.js')));
192
+ let unprotectedRoutes = 0;
193
+ for (const file of routeFiles) {
194
+ let content;
195
+ try {
196
+ content = fs_1.default.readFileSync(file, 'utf8');
197
+ }
198
+ catch {
199
+ continue;
200
+ }
201
+ const hasAuth = content.includes('getSession') ||
202
+ content.includes('getServerSession') ||
203
+ content.includes('auth()') ||
204
+ content.includes('requireAuth') ||
205
+ content.includes('verifyToken') ||
206
+ content.includes('middleware') ||
207
+ content.includes('authenticate') ||
208
+ content.includes('authorize') ||
209
+ content.includes('clerkClient') ||
210
+ content.includes('currentUser');
211
+ const isPublicRoute = file.includes('/auth/') ||
212
+ file.includes('/public/') ||
213
+ file.includes('webhook') ||
214
+ file.includes('health') ||
215
+ file.includes('callback');
216
+ if (!hasAuth && !isPublicRoute) {
217
+ unprotectedRoutes++;
218
+ if (unprotectedRoutes <= 3) {
219
+ findings.push({
220
+ severity: 'warning',
221
+ category: 'Authentication',
222
+ message: 'Rota sem verificação de autenticação detectada',
223
+ file: path_1.default.relative(projectRoot, file),
224
+ });
225
+ }
226
+ }
227
+ }
228
+ if (unprotectedRoutes > 3) {
229
+ findings.push({
230
+ severity: 'warning',
231
+ category: 'Authentication',
232
+ message: `${unprotectedRoutes - 3} outras rotas sem autenticação detectadas`,
233
+ });
234
+ }
235
+ return findings;
236
+ }
237
+ function calculateScore(findings) {
238
+ let score = 100;
239
+ for (const f of findings) {
240
+ if (f.severity === 'critical')
241
+ score -= 20;
242
+ else if (f.severity === 'warning')
243
+ score -= 5;
244
+ }
245
+ return Math.max(0, score);
246
+ }
247
+ function saveReport(result, projectRoot) {
248
+ const dir = path_1.default.join(projectRoot, '.vibetachyon');
249
+ if (!fs_1.default.existsSync(dir))
250
+ fs_1.default.mkdirSync(dir, { recursive: true });
251
+ const reportPath = path_1.default.join(dir, 'cipher-audit.md');
252
+ const scoreEmoji = result.summary.score >= 80 ? '🟢' : result.summary.score >= 50 ? '🟡' : '🔴';
253
+ const lines = [
254
+ `# CIPHER — Security Audit Report`,
255
+ ``,
256
+ `**Projeto:** \`${result.projectRoot}\``,
257
+ `**Data:** ${new Date(result.timestamp).toLocaleString('pt-BR')}`,
258
+ `**Score de Segurança:** ${scoreEmoji} ${result.summary.score}/100`,
259
+ ``,
260
+ `## Resumo`,
261
+ ``,
262
+ `| Severidade | Total |`,
263
+ `|------------|-------|`,
264
+ `| 🔴 Critical | ${result.summary.critical} |`,
265
+ `| 🟡 Warning | ${result.summary.warning} |`,
266
+ `| 🔵 Info | ${result.summary.info} |`,
267
+ ``,
268
+ `## Findings`,
269
+ ``,
270
+ ];
271
+ const criticals = result.findings.filter(f => f.severity === 'critical');
272
+ const warnings = result.findings.filter(f => f.severity === 'warning');
273
+ const infos = result.findings.filter(f => f.severity === 'info');
274
+ for (const group of [
275
+ { label: '🔴 Critical', items: criticals },
276
+ { label: '🟡 Warning', items: warnings },
277
+ { label: '🔵 Info', items: infos },
278
+ ]) {
279
+ if (group.items.length === 0)
280
+ continue;
281
+ lines.push(`### ${group.label}`);
282
+ lines.push('');
283
+ for (const f of group.items) {
284
+ lines.push(`- **[${f.category}]** ${f.message}`);
285
+ if (f.file)
286
+ lines.push(` - Arquivo: \`${f.file}\`${f.line ? ` (linha ${f.line})` : ''}`);
287
+ if (f.snippet)
288
+ lines.push(` - \`${f.snippet}\``);
289
+ }
290
+ lines.push('');
291
+ }
292
+ lines.push(`---`);
293
+ lines.push(`*Gerado pelo CIPHER — VibeTachyon Security Agent*`);
294
+ fs_1.default.writeFileSync(reportPath, lines.join('\n'), 'utf8');
295
+ return reportPath;
296
+ }
297
+ async function runCipherAudit(projectRoot) {
298
+ const files = walkFiles(projectRoot);
299
+ const findings = [
300
+ ...checkSecrets(files, projectRoot),
301
+ ...checkEnvFiles(projectRoot),
302
+ ...checkDependencies(projectRoot),
303
+ ...checkAuthPatterns(files, projectRoot),
304
+ ];
305
+ const critical = findings.filter(f => f.severity === 'critical').length;
306
+ const warning = findings.filter(f => f.severity === 'warning').length;
307
+ const info = findings.filter(f => f.severity === 'info').length;
308
+ const result = {
309
+ projectRoot,
310
+ timestamp: new Date().toISOString(),
311
+ findings,
312
+ summary: {
313
+ critical,
314
+ warning,
315
+ info,
316
+ total: findings.length,
317
+ score: calculateScore(findings),
318
+ },
319
+ };
320
+ saveReport(result, projectRoot);
321
+ return result;
322
+ }
package/dist/index.js CHANGED
@@ -50,6 +50,7 @@ const update_js_1 = require("./core/spec/update.js");
50
50
  const validate_js_1 = require("./core/spec/validate.js");
51
51
  const personas_js_1 = require("./core/orchestrator/personas.js");
52
52
  const config_js_3 = require("./core/persona/config.js");
53
+ const cipher_audit_js_1 = require("./core/security/cipher-audit.js");
53
54
  const contract_js_1 = require("./core/persona/contract.js");
54
55
  const inspect_js_1 = require("./core/persona/inspect.js");
55
56
  const recommend_js_1 = require("./core/persona/recommend.js");
@@ -119,6 +120,70 @@ function printBanner() {
119
120
  `;
120
121
  console.log(banner);
121
122
  }
123
+ const AGENT_ASCII = {
124
+ QUASAR: `
125
+ ██████╗ ██╗ ██╗ █████╗ ███████╗ █████╗ ██████╗
126
+ ██╔═══██╗██║ ██║██╔══██╗██╔════╝██╔══██╗██╔══██╗
127
+ ██║ ██║██║ ██║███████║███████╗███████║██████╔╝
128
+ ██║▄▄ ██║██║ ██║██╔══██║╚════██║██╔══██║██╔══██╗
129
+ ╚██████╔╝╚██████╔╝██║ ██║███████║██║ ██║██║ ██║
130
+ ╚══▀▀═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝`,
131
+ LUMEN: `
132
+ ██╗ ██╗ ██╗███╗ ███╗███████╗███╗ ██╗
133
+ ██║ ██║ ██║████╗ ████║██╔════╝████╗ ██║
134
+ ██║ ██║ ██║██╔████╔██║█████╗ ██╔██╗ ██║
135
+ ██║ ██║ ██║██║╚██╔╝██║██╔══╝ ██║╚██╗██║
136
+ ███████╗╚██████╔╝██║ ╚═╝ ██║███████╗██║ ╚████║
137
+ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝`,
138
+ AXIOM: `
139
+ █████╗ ██╗ ██╗██╗ ██████╗ ███╗ ███╗
140
+ ██╔══██╗╚██╗██╔╝██║██╔═══██╗████╗ ████║
141
+ ███████║ ╚███╔╝ ██║██║ ██║██╔████╔██║
142
+ ██╔══██║ ██╔██╗ ██║██║ ██║██║╚██╔╝██║
143
+ ██║ ██║██╔╝ ██╗██║╚██████╔╝██║ ╚═╝ ██║
144
+ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═╝ ╚═╝`,
145
+ CIPHER: `
146
+ ██████╗██╗██████╗ ██╗ ██╗███████╗██████╗
147
+ ██╔════╝██║██╔══██╗██║ ██║██╔════╝██╔══██╗
148
+ ██║ ██║██████╔╝███████║█████╗ ██████╔╝
149
+ ██║ ██║██╔═══╝ ██╔══██║██╔══╝ ██╔══██╗
150
+ ╚██████╗██║██║ ██║ ██║███████╗██║ ██║
151
+ ╚═════╝╚═╝╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝`,
152
+ FLUX: `
153
+ ███████╗██╗ ██╗ ██╗██╗ ██╗
154
+ ██╔════╝██║ ██║ ██║╚██╗██╔╝
155
+ █████╗ ██║ ██║ ██║ ╚███╔╝
156
+ ██╔══╝ ██║ ██║ ██║ ██╔██╗
157
+ ██║ ███████╗╚██████╔╝██╔╝ ██╗
158
+ ╚═╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝`,
159
+ PRISM: `
160
+ ██████╗ ██████╗ ██╗███████╗███╗ ███╗
161
+ ██╔══██╗██╔══██╗██║██╔════╝████╗ ████║
162
+ ██████╔╝██████╔╝██║███████╗██╔████╔██║
163
+ ██╔═══╝ ██╔══██╗██║╚════██║██║╚██╔╝██║
164
+ ██║ ██║ ██║██║███████║██║ ╚═╝ ██║
165
+ ╚═╝ ╚═╝ ╚═╝╚═╝╚══════╝╚═╝ ╚═╝`,
166
+ ZENITH: `
167
+ ███████╗███████╗███╗ ██╗██╗████████╗██╗ ██╗
168
+ ╚══███╔╝██╔════╝████╗ ██║██║╚══██╔══╝██║ ██║
169
+ ███╔╝ █████╗ ██╔██╗ ██║██║ ██║ ███████║
170
+ ███╔╝ ██╔══╝ ██║╚██╗██║██║ ██║ ██╔══██║
171
+ ███████╗███████╗██║ ╚████║██║ ██║ ██║ ██║
172
+ ╚══════╝╚══════╝╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═╝ ╚═╝`,
173
+ };
174
+ function printAgentBanner(personaId) {
175
+ const persona = (0, config_js_3.getPersona)(personaId);
176
+ const ascii = AGENT_ASCII[persona.agentName] ?? '';
177
+ console.log(`${persona.agentColor}${ascii}\x1b[0m`);
178
+ console.log(`${persona.agentColor} ⚡ ${persona.agentName} — ${persona.label} Agent\x1b[0m`);
179
+ console.log(`\x1b[90m ${persona.agentTagline}\x1b[0m`);
180
+ console.log('');
181
+ }
182
+ // Detecta se foi invocado por nome de agente (ex: `cipher audit`)
183
+ function detectAgentBin() {
184
+ const binName = path_1.default.basename(process.argv[1] ?? '').replace(/\.js$/, '').toLowerCase();
185
+ return config_js_3.AGENT_BIN_MAP[binName] ?? null;
186
+ }
122
187
  async function runInteractiveMode() {
123
188
  printBanner();
124
189
  (0, prompts_1.intro)(picocolors_1.default.yellow(`⚡ Orchestrating VibeTachyon CLI v${CLI_VERSION}...`));
@@ -5138,8 +5203,76 @@ async function main() {
5138
5203
  console.log(result.message);
5139
5204
  (0, session_state_js_1.recordSessionEvent)('mcp migrate', 'success', options.dryRun ? 'dry-run' : 'written');
5140
5205
  });
5206
+ // Detecta se foi invocado por nome de agente (ex: `cipher audit`)
5207
+ const agentPersonaId = detectAgentBin();
5208
+ if (agentPersonaId) {
5209
+ printAgentBanner(agentPersonaId);
5210
+ // Auto-ativa a persona correspondente
5211
+ const projectRoot = process.cwd();
5212
+ (0, config_js_3.saveActivePersona)(projectRoot, agentPersonaId);
5213
+ }
5141
5214
  if (process.argv.length <= 2) {
5142
- await runInteractiveMode();
5215
+ if (!agentPersonaId) {
5216
+ await runInteractiveMode();
5217
+ }
5218
+ else {
5219
+ const projectRoot = process.cwd();
5220
+ if (agentPersonaId === 'security') {
5221
+ const steps = [
5222
+ ' Mapeando estrutura do projeto...',
5223
+ ' Escaneando arquivos em busca de secrets...',
5224
+ ' Verificando configurações de segurança...',
5225
+ ' Analisando dependências...',
5226
+ ' Verificando rotas e autenticação...',
5227
+ ' Gerando relatório...',
5228
+ ];
5229
+ const spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
5230
+ let frameIdx = 0;
5231
+ let stepIdx = 0;
5232
+ const interval = setInterval(() => {
5233
+ const frame = spinnerFrames[frameIdx % spinnerFrames.length];
5234
+ const step = steps[Math.min(stepIdx, steps.length - 1)];
5235
+ process.stdout.write(`\r\x1b[38;5;46m ${frame}\x1b[0m\x1b[90m${step}\x1b[0m\x1b[K`);
5236
+ frameIdx++;
5237
+ if (frameIdx % 8 === 0 && stepIdx < steps.length - 1)
5238
+ stepIdx++;
5239
+ }, 80);
5240
+ const result = await (0, cipher_audit_js_1.runCipherAudit)(projectRoot);
5241
+ clearInterval(interval);
5242
+ process.stdout.write(`\r\x1b[K`);
5243
+ console.log(`\x1b[38;5;46m ✓ Auditoria concluída\x1b[0m\n`);
5244
+ const { summary } = result;
5245
+ const scoreColor = summary.score >= 80 ? '\x1b[38;5;46m' : summary.score >= 50 ? '\x1b[38;5;220m' : '\x1b[38;5;196m';
5246
+ console.log(`${scoreColor} Score de Segurança: ${summary.score}/100\x1b[0m`);
5247
+ console.log(`\x1b[38;5;196m 🔴 Critical: ${summary.critical}\x1b[0m`);
5248
+ console.log(`\x1b[38;5;220m 🟡 Warning: ${summary.warning}\x1b[0m`);
5249
+ console.log(`\x1b[38;5;39m 🔵 Info: ${summary.info}\x1b[0m`);
5250
+ console.log('');
5251
+ if (summary.critical > 0 || summary.warning > 0) {
5252
+ const criticals = result.findings.filter(f => f.severity === 'critical').slice(0, 3);
5253
+ const warnings = result.findings.filter(f => f.severity === 'warning').slice(0, 3);
5254
+ for (const f of criticals) {
5255
+ console.log(`\x1b[38;5;196m ❌ [${f.category}] ${f.message}\x1b[0m`);
5256
+ if (f.file)
5257
+ console.log(`\x1b[90m → ${f.file}${f.line ? `:${f.line}` : ''}\x1b[0m`);
5258
+ }
5259
+ for (const f of warnings) {
5260
+ console.log(`\x1b[38;5;220m ⚠️ [${f.category}] ${f.message}\x1b[0m`);
5261
+ if (f.file)
5262
+ console.log(`\x1b[90m → ${f.file}\x1b[0m`);
5263
+ }
5264
+ console.log('');
5265
+ }
5266
+ else {
5267
+ console.log(`\x1b[38;5;46m ✅ Nenhum problema crítico encontrado.\x1b[0m\n`);
5268
+ }
5269
+ console.log(`\x1b[90m Relatório completo salvo em .vibetachyon/cipher-audit.md\x1b[0m\n`);
5270
+ }
5271
+ else {
5272
+ const persona = (0, config_js_3.getPersona)(agentPersonaId);
5273
+ console.log(`\x1b[90m Persona ${persona.agentName} ativada. Use os comandos do VibeTachyon normalmente.\x1b[0m\n`);
5274
+ }
5275
+ }
5143
5276
  return;
5144
5277
  }
5145
5278
  await program.parseAsync(process.argv);
package/dist/installer.js CHANGED
@@ -242,8 +242,8 @@ async function runInstallFlow(options = {}) {
242
242
  throw new Error(verification.error || 'Authentication failed');
243
243
  }
244
244
  if (useSpinner) {
245
- s.message(picocolors_1.default.green(`✅ Authenticated as ${verification.name}. [SHIELD ACTIVATED]`));
246
- s.message(picocolors_1.default.cyan(`Injecting VibeTachyon Shield into ${agent}...`));
245
+ s.message(picocolors_1.default.green(`✅ Authenticated as ${verification.name}. [CODEAGENT OS ACTIVATED]`));
246
+ s.message(picocolors_1.default.cyan(`Connecting VibeTachyon CodeAgent OS to ${agent}...`));
247
247
  }
248
248
  }
249
249
  else if (useSpinner) {
@@ -276,7 +276,7 @@ async function runInstallFlow(options = {}) {
276
276
  (0, prompts_1.outro)(picocolors_1.default.yellow('🧪 Dry-run mode complete. Re-run without --dry-run to persist.'));
277
277
  }
278
278
  else {
279
- (0, prompts_1.outro)(picocolors_1.default.green('🚀 VibeTachyon SHIELD is active! Your agent is now protected and connected to VibeCodes.'));
279
+ (0, prompts_1.outro)(picocolors_1.default.green('🚀 VibeTachyon CodeAgent OS is active! Your agent is now supercharged with 39 commands and 50+ skills.'));
280
280
  }
281
281
  }
282
282
  return {
@@ -29,7 +29,7 @@ if (proxyUrl) {
29
29
  const supabase = (0, supabase_js_1.createClient)(supabaseUrl, supabaseKey, supabaseOptions);
30
30
  // --- VibeTachyon Shield: Local Privacy & Sanity Traps ---
31
31
  const LOCAL_CACHE_DIR = path_1.default.join(process.env.HOME || process.env.USERPROFILE || '', '.vibetachyon', 'cache');
32
- const CALL_LIMIT_PER_SESSION = 50; // Sanity Trap to prevent agent infinite loops
32
+ const CALL_LIMIT_PER_SESSION = 150; // Sanity Trap to prevent agent infinite loops
33
33
  let sessionCallCount = 0;
34
34
  async function checkSanity() {
35
35
  sessionCallCount++;
@@ -144,10 +144,37 @@ function minifySnippet(code) {
144
144
  // Collapse excess newlines but keep some structure for the LLM
145
145
  return minified.replace(/\n\s*\n/g, '\n').trim();
146
146
  }
147
+ async function validateTokenAtStartup() {
148
+ const token = process.env.VIBECODES_TOKEN;
149
+ if (!token) {
150
+ console.error('[VibeTachyon] ERRO: VIBECODES_TOKEN não encontrado. Execute: npx vibetachyon para configurar.');
151
+ process.exit(1);
152
+ }
153
+ const apiUrl = process.env.VIBETACHYON_API_URL || 'https://vibecodings.com.br/api/vibecodes/mcp/verify';
154
+ try {
155
+ const res = await fetch(apiUrl, {
156
+ method: 'POST',
157
+ headers: { 'Content-Type': 'application/json' },
158
+ body: JSON.stringify({ token }),
159
+ signal: AbortSignal.timeout(8000)
160
+ });
161
+ const data = await res.json();
162
+ if (!data.success) {
163
+ console.error(`[VibeTachyon] Token inválido: ${data.error || 'Acesso negado'}. Reconfigure com: npx vibetachyon`);
164
+ process.exit(1);
165
+ }
166
+ console.error(`[VibeTachyon] Autenticado como ${data.name || 'VibeCodes MAX User'}. CodeAgent OS ativo.`);
167
+ }
168
+ catch {
169
+ // Network error — allow graceful degradation (offline mode)
170
+ console.error('[VibeTachyon] Aviso: Não foi possível verificar o token (modo offline). Continuando...');
171
+ }
172
+ }
147
173
  async function startMcpServer() {
174
+ await validateTokenAtStartup();
148
175
  const server = new mcp_js_1.McpServer({
149
176
  name: "VibeTachyon MCP",
150
- version: "1.4.0"
177
+ version: "1.5.0"
151
178
  });
152
179
  /**
153
180
  * SYSTEM_PROMPT INJECTION:
@@ -2474,14 +2501,14 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
2474
2501
  }
2475
2502
  // Performance
2476
2503
  if (/\.forEach\(/.test(content) && /await/.test(content)) {
2477
- issues.push(`[WARNING] ${currentFile}:${lineNum}\n await dentro de forEach nao funciona como esperado — use Promise.all() com .map() para operacoes async paralelas.`);
2504
+ issues.push(`[WARNING] ${currentFile}:${lineNum}\n await dentro de forEach não funciona como esperado — use Promise.all() com .map() para operacoes async paralelas.`);
2478
2505
  }
2479
2506
  // Style / maintainability
2480
2507
  if (/: any\b/.test(content) || /as any\b/.test(content)) {
2481
- issues.push(`[SUGGESTION] ${currentFile}:${lineNum}\n Uso de 'any' detectado — definir tipo especifico melhora a seguranca em tempo de compilacao.`);
2508
+ issues.push(`[SUGGESTION] ${currentFile}:${lineNum}\n Uso de 'any' detectado — definir tipo específico melhora a seguranca em tempo de compilacao.`);
2482
2509
  }
2483
2510
  if (/\/\/ TODO|\/\/ FIXME|\/\/ HACK/.test(content)) {
2484
- issues.push(`[SUGGESTION] ${currentFile}:${lineNum}\n ${content.trim()} — registrar no backlog com vibe_backlog_manage se nao for resolver agora.`);
2511
+ issues.push(`[SUGGESTION] ${currentFile}:${lineNum}\n ${content.trim()} — registrar no backlog com vibe_backlog_manage se não for resolver agora.`);
2485
2512
  }
2486
2513
  }
2487
2514
  else if (!line.startsWith('-') && !line.startsWith('---') && !line.startsWith('diff') && !line.startsWith('index')) {
@@ -2497,7 +2524,7 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
2497
2524
  ? '🔴 BLOQUEADO — corrija os itens CRITICAL antes de commitar'
2498
2525
  : warnings.length > 0
2499
2526
  ? '🟡 REVISAO RECOMENDADA — warnings encontrados'
2500
- : '🟢 APROVADO — nenhum problema critico detectado';
2527
+ : '🟢 APROVADO — nenhum problema crítico detectado';
2501
2528
  const sections = [
2502
2529
  `[VIBE CODE REVIEW]\nMudancas analisadas: +${addedLines} adicoes, -${removedLines} remocoes\n`,
2503
2530
  `Veredicto: ${verdict}\n`,
@@ -2509,7 +2536,7 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
2509
2536
  if (suggestions.length > 0)
2510
2537
  sections.push(`## SUGGESTION (${suggestions.length})\n${suggestions.join('\n\n')}\n`);
2511
2538
  if (issues.length === 0)
2512
- sections.push('Nenhum problema automatico detectado. Considere tambem uma revisao manual do fluxo de negocio.\n');
2539
+ sections.push('Nenhum problema automático detectado. Considere também uma revisao manual do fluxo de negocio.\n');
2513
2540
  return { content: [{ type: "text", text: sections.join('\n') }] };
2514
2541
  }
2515
2542
  catch (err) {
@@ -2525,7 +2552,7 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
2525
2552
  try {
2526
2553
  const absolutePath = path_1.default.isAbsolute(file_path) ? file_path : path_1.default.join(process.cwd(), file_path);
2527
2554
  if (!(await fs_extra_1.default.pathExists(absolutePath))) {
2528
- return { content: [{ type: "text", text: `[VIBE TEST] Arquivo nao encontrado: ${absolutePath}` }] };
2555
+ return { content: [{ type: "text", text: `[VIBE TEST] Arquivo não encontrado: ${absolutePath}` }] };
2529
2556
  }
2530
2557
  const fileContent = await fs_extra_1.default.readFile(absolutePath, 'utf8');
2531
2558
  const fileName = path_1.default.basename(absolutePath);
@@ -2579,7 +2606,7 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
2579
2606
  expect(container).toMatchSnapshot();
2580
2607
  });
2581
2608
 
2582
- // TODO: adicionar testes especificos para as props e interacoes do componente
2609
+ // TODO: adicionar testes específicos para as props e interacoes do componente
2583
2610
  });`;
2584
2611
  }
2585
2612
  else if (isNextRoute) {
@@ -2646,7 +2673,7 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
2646
2673
  ? `describe('${fileName}', () => {\n${fnTests}\n});`
2647
2674
  : `describe('${fileName}', () => {
2648
2675
  it('deve ser importado sem erros', () => {
2649
- expect(true).toBe(true); // placeholder — adicionar testes especificos
2676
+ expect(true).toBe(true); // placeholder — adicionar testes específicos
2650
2677
  });
2651
2678
  });`;
2652
2679
  }
@@ -2671,7 +2698,7 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
2671
2698
  try {
2672
2699
  const absolutePath = path_1.default.isAbsolute(file_path) ? file_path : path_1.default.join(process.cwd(), file_path);
2673
2700
  if (!(await fs_extra_1.default.pathExists(absolutePath))) {
2674
- return { content: [{ type: "text", text: `[VIBE EXPLAIN] Arquivo nao encontrado: ${absolutePath}` }] };
2701
+ return { content: [{ type: "text", text: `[VIBE EXPLAIN] Arquivo não encontrado: ${absolutePath}` }] };
2675
2702
  }
2676
2703
  const content = await fs_extra_1.default.readFile(absolutePath, 'utf8');
2677
2704
  const fileName = path_1.default.basename(absolutePath);
@@ -2692,7 +2719,7 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
2692
2719
  : isReact ? 'Componente React'
2693
2720
  : fileName.includes('types') || fileName.endsWith('.d.ts') ? 'Arquivo de tipos TypeScript'
2694
2721
  : fileName.includes('utils') || fileName.includes('lib') || fileName.includes('helpers') ? 'Utilitario / Biblioteca'
2695
- : fileName.includes('config') ? 'Arquivo de configuracao'
2722
+ : fileName.includes('config') ? 'Arquivo de configuração'
2696
2723
  : 'Modulo TypeScript';
2697
2724
  const audienceNote = audience === 'beginner'
2698
2725
  ? '\n(Explicacao voltada para iniciantes — conceitos basicos incluidos)'
@@ -2738,7 +2765,7 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
2738
2765
  const quickFixes = [];
2739
2766
  if (/auth|login|session|token|cookie/.test(desc)) {
2740
2767
  hypotheses.push('Token JWT expirado ou invalido (alta probabilidade)');
2741
- hypotheses.push('Cookie nao persistido corretamente (httpOnly, secure, sameSite)');
2768
+ hypotheses.push('Cookie não persistido corretamente (httpOnly, secure, sameSite)');
2742
2769
  hypotheses.push('Middleware de autenticacao bloqueando a rota');
2743
2770
  checklist.push('Verificar expiracao do token no DevTools (Application > Local Storage)');
2744
2771
  checklist.push('Inspecionar cookies em Application > Cookies');
@@ -2748,8 +2775,8 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
2748
2775
  }
2749
2776
  else if (/null|undefined|cannot read|is not a function/.test(desc)) {
2750
2777
  hypotheses.push('Objeto acessado antes de ser inicializado (undefined)');
2751
- hypotheses.push('Async operation nao aguardada (await faltando)');
2752
- hypotheses.push('Prop nao passada para o componente filho');
2778
+ hypotheses.push('Async operation não aguardada (await faltando)');
2779
+ hypotheses.push('Prop não passada para o componente filho');
2753
2780
  checklist.push('Adicionar optional chaining (?.) no acesso ao objeto suspeito');
2754
2781
  checklist.push('Verificar se todas as chamadas async tem await');
2755
2782
  checklist.push('Checar se o dado chega corretamente via props ou API');
@@ -2758,9 +2785,9 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
2758
2785
  }
2759
2786
  else if (/api|500|400|fetch|request|response/.test(desc)) {
2760
2787
  hypotheses.push('Corpo da requisicao em formato incorreto (JSON malformado)');
2761
- hypotheses.push('Endpoint nao existe ou URL incorreta');
2788
+ hypotheses.push('Endpoint não existe ou URL incorreta');
2762
2789
  hypotheses.push('Erro de validacao do schema no servidor');
2763
- hypotheses.push('Variavel de ambiente da API nao configurada');
2790
+ hypotheses.push('Variavel de ambiente da API não configurada');
2764
2791
  checklist.push('Verificar a URL da requisicao no Network tab do DevTools');
2765
2792
  checklist.push('Inspecionar o body da resposta de erro no Network tab');
2766
2793
  checklist.push('Checar se todas as env vars da API estao definidas');
@@ -2778,14 +2805,14 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
2778
2805
  quickFixes.push('Verificar se o componente recebe as props corretas com React DevTools');
2779
2806
  }
2780
2807
  else {
2781
- hypotheses.push('Logica de negocio incorreta na funcao principal');
2808
+ hypotheses.push('Logica de negocio incorreta na função principal');
2782
2809
  hypotheses.push('Estado inconsistente entre cliente e servidor');
2783
2810
  hypotheses.push('Race condition em operacoes assincronas');
2784
- checklist.push('Adicionar console.log nos pontos de entrada e saida da funcao');
2811
+ checklist.push('Adicionar console.log nos pontos de entrada e saida da função');
2785
2812
  checklist.push('Verificar os valores das variaveis no momento do erro');
2786
- checklist.push('Testar a funcao isoladamente com um caso simples');
2813
+ checklist.push('Testar a função isoladamente com um caso simples');
2787
2814
  quickFixes.push('Adicionar try/catch e logar o erro completo (err.stack)');
2788
- quickFixes.push('Verificar se o bug ocorre em desenvolvimento mas nao em producao (ou vice-versa)');
2815
+ quickFixes.push('Verificar se o bug ocorre em desenvolvimento mas não em producao (ou vice-versa)');
2789
2816
  }
2790
2817
  const result = [
2791
2818
  `[VIBE DEBUG FLOW]`,
@@ -2855,7 +2882,7 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
2855
2882
  hasApiChanges && '- [ ] Endpoints retornam erro correto com dados invalidos',
2856
2883
  hasAuthChanges && '- [ ] Fluxo de autenticacao funciona end-to-end',
2857
2884
  hasDBChanges && '- [ ] Migration aplicada sem erros em ambiente de teste',
2858
- hasDBChanges && '- [ ] Dados existentes nao foram corrompidos',
2885
+ hasDBChanges && '- [ ] Dados existentes não foram corrompidos',
2859
2886
  '- [ ] Testado manualmente no ambiente local',
2860
2887
  '- [ ] Sem erros no console do browser',
2861
2888
  '- [ ] TypeScript: zero erros (tsc --noEmit)',
@@ -3024,15 +3051,15 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
3024
3051
  else {
3025
3052
  sections.push(`\nArquivo de exemplo: ${exampleFile} (${exampleKeys.length} variaveis documentadas)`);
3026
3053
  }
3027
- sections.push(`Arquivo .env: ${actualKeys.length > 0 ? `${actualKeys.length} variaveis encontradas` : 'nao encontrado'}`);
3054
+ sections.push(`Arquivo .env: ${actualKeys.length > 0 ? `${actualKeys.length} variaveis encontradas` : 'não encontrado'}`);
3028
3055
  if (missing.length > 0) {
3029
- sections.push(`\n## ⚠️ VARS FALTANDO (no ${exampleFile} mas nao no .env)\n${missing.map(k => ` ⚠️ ${k}`).join('\n')}`);
3056
+ sections.push(`\n## ⚠️ VARS FALTANDO (no ${exampleFile} mas não no .env)\n${missing.map(k => ` ⚠️ ${k}`).join('\n')}`);
3030
3057
  }
3031
3058
  else if (exampleFile) {
3032
3059
  sections.push('\n## Vars requeridas: OK (todas presentes no .env)');
3033
3060
  }
3034
3061
  if (undocumented.length > 0) {
3035
- sections.push(`\n## 📝 VARS NAO DOCUMENTADAS (no .env mas nao no ${exampleFile})\n${undocumented.map(k => ` 📝 ${k}`).join('\n')}\n → Adicionar ao ${exampleFile} para documentar`);
3062
+ sections.push(`\n## 📝 VARS NAO DOCUMENTADAS (no .env mas não no ${exampleFile})\n${undocumented.map(k => ` 📝 ${k}`).join('\n')}\n → Adicionar ao ${exampleFile} para documentar`);
3036
3063
  }
3037
3064
  if (usedInCode.length > 0) {
3038
3065
  sections.push(`\n## 🔍 USADAS NO CODIGO MAS NAO DECLARADAS\n${usedInCode.map(k => ` 🔍 ${k}`).join('\n')}\n → Adicionar ao .env e ao ${exampleFile || '.env.example'}`);
@@ -3054,7 +3081,7 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
3054
3081
  try {
3055
3082
  const pkgPath = path_1.default.join(cwd, 'package.json');
3056
3083
  if (!(await fs_extra_1.default.pathExists(pkgPath))) {
3057
- return { content: [{ type: "text", text: `[VIBE DEPS] package.json nao encontrado em: ${cwd}` }] };
3084
+ return { content: [{ type: "text", text: `[VIBE DEPS] package.json não encontrado em: ${cwd}` }] };
3058
3085
  }
3059
3086
  const pkg = await fs_extra_1.default.readJson(pkgPath);
3060
3087
  const deps = Object.keys(pkg.dependencies || {});
@@ -3165,7 +3192,7 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
3165
3192
  ['Ja tem conta? Fazer login.', 'Link action direto'],
3166
3193
  ['Email em uso.', 'Ultra minimal'],
3167
3194
  ],
3168
- }[t] || [['Copy nao disponivel para esse padrao', 'N/A']]),
3195
+ }[t] || [['Copy não disponivel para esse padrão', 'N/A']]),
3169
3196
  },
3170
3197
  {
3171
3198
  pattern: /cta|botao|button|upgrade|assinar|plano|premium/,
@@ -3173,12 +3200,12 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
3173
3200
  friendly: [
3174
3201
  ['Comecar agora — e gratis!', 'Remove barreira com enfase no gratis'],
3175
3202
  ['Quero experimentar', 'Baixo compromisso, alta conversao'],
3176
- ['Dar o proximo passo', 'Progressivo, nao agressivo'],
3203
+ ['Dar o proximo passo', 'Progressivo, não agressivo'],
3177
3204
  ],
3178
3205
  professional: [
3179
3206
  ['Iniciar periodo de avaliacao', 'Claro e corporativo'],
3180
3207
  ['Fazer upgrade agora', 'Acao direta'],
3181
- ['Contratar plano Premium', 'Especifico e formal'],
3208
+ ['Contratar plano Premium', 'Específico e formal'],
3182
3209
  ],
3183
3210
  bold: [
3184
3211
  ['Quero isso agora!', 'Urgencia e desejo'],
@@ -3190,7 +3217,7 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
3190
3217
  ['Upgrade', 'Uma palavra'],
3191
3218
  ['Assinar', 'Objetivo'],
3192
3219
  ],
3193
- }[t] || [['Copy nao disponivel', 'N/A']]),
3220
+ }[t] || [['Copy não disponivel', 'N/A']]),
3194
3221
  },
3195
3222
  {
3196
3223
  pattern: /empty state|lista vazia|sem item|nenhum resultado/,
@@ -3215,7 +3242,7 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
3215
3242
  ['Vazio', 'Minimalista'],
3216
3243
  ['Nada ainda', 'Simples e honesto'],
3217
3244
  ],
3218
- }[t] || [['Copy nao disponivel', 'N/A']]),
3245
+ }[t] || [['Copy não disponivel', 'N/A']]),
3219
3246
  },
3220
3247
  ];
3221
3248
  // Find matching pattern
@@ -3257,7 +3284,7 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
3257
3284
  try {
3258
3285
  const absolutePath = path_1.default.isAbsolute(file_path) ? file_path : path_1.default.join(process.cwd(), file_path);
3259
3286
  if (!(await fs_extra_1.default.pathExists(absolutePath))) {
3260
- return { content: [{ type: "text", text: `[VIBE REFACTOR] Arquivo nao encontrado: ${absolutePath}` }] };
3287
+ return { content: [{ type: "text", text: `[VIBE REFACTOR] Arquivo não encontrado: ${absolutePath}` }] };
3261
3288
  }
3262
3289
  const content = await fs_extra_1.default.readFile(absolutePath, 'utf8');
3263
3290
  const fileName = path_1.default.basename(absolutePath);
@@ -3291,9 +3318,9 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
3291
3318
  suggestions.push({
3292
3319
  priority: '🔴 ALTA',
3293
3320
  title: `Funcao muito longa: ${longestFn.name}()`,
3294
- problem: `A funcao ${longestFn.name} tem aproximadamente ${longestFn.lines} linhas. Funcoes longas sao dificeis de testar e entender.`,
3321
+ problem: `A função ${longestFn.name} tem aproximadamente ${longestFn.lines} linhas. Funcoes longas sao dificeis de testar e entender.`,
3295
3322
  solution: `Quebre ${longestFn.name} em funcoes menores com nomes descritivos:\n Antes: ${longestFn.name}() com toda a logica\n Depois: validateInput() + processData() + formatOutput()`,
3296
- impact: 'Cada funcao menor pode ser testada isoladamente'
3323
+ impact: 'Cada função menor pode ser testada isoladamente'
3297
3324
  });
3298
3325
  }
3299
3326
  // 3. Repeated patterns (duplicate code blocks)
@@ -3310,8 +3337,8 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
3310
3337
  suggestions.push({
3311
3338
  priority: '🟠 MEDIA',
3312
3339
  title: 'Codigo duplicado detectado',
3313
- problem: `${repeated.length} padrao(oes) de codigo aparece(m) 3+ vezes:\n${repeated.map(([line, count]) => ` "${line.slice(0, 60)}..." (${count}x)`).join('\n')}`,
3314
- solution: 'Extraia o padrao repetido para uma funcao ou constante compartilhada:\n Antes: mesmo bloco em 3 lugares\n Depois: const handleX = (params) => { /* logica unica */ }',
3340
+ problem: `${repeated.length} padrão(oes) de codigo aparece(m) 3+ vezes:\n${repeated.map(([line, count]) => ` "${line.slice(0, 60)}..." (${count}x)`).join('\n')}`,
3341
+ solution: 'Extraia o padrão repetido para uma função ou constante compartilhada:\n Antes: mesmo bloco em 3 lugares\n Depois: const handleX = (params) => { /* logica unica */ }',
3315
3342
  impact: 'DRY — qualquer bug so precisa ser corrigido em um lugar'
3316
3343
  });
3317
3344
  }
@@ -3321,9 +3348,9 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
3321
3348
  suggestions.push({
3322
3349
  priority: '🟡 BAIXA',
3323
3350
  title: `${anyUsages} uso(s) de 'any' detectado(s)`,
3324
- problem: `O tipo 'any' desliga a verificacao de tipos do TypeScript, criando buracos de seguranca silenciosos.`,
3325
- solution: 'Substitua any por tipos especificos ou genericos:\n Antes: function process(data: any)\n Depois: function process<T extends Record<string, unknown>>(data: T)',
3326
- impact: 'Erros de tipo sao capturados em compile-time, nao em runtime'
3351
+ problem: `O tipo 'any' desliga a verificação de tipos do TypeScript, criando buracos de seguranca silenciosos.`,
3352
+ solution: 'Substitua any por tipos específicos ou genericos:\n Antes: function process(data: any)\n Depois: function process<T extends Record<string, unknown>>(data: T)',
3353
+ impact: 'Erros de tipo sao capturados em compile-time, não em runtime'
3327
3354
  });
3328
3355
  }
3329
3356
  // 5. Naming issues (single letter vars outside loops)
@@ -3343,7 +3370,7 @@ ${consequences.length > 0 ? consequences.map(c => `- ${c}`).join('\n') : '- (non
3343
3370
  return {
3344
3371
  content: [{
3345
3372
  type: "text",
3346
- text: `[VIBE REFACTOR] ${fileName} (${lineCount} linhas)\n\n✅ Nenhum problema critico de refatoracao detectado automaticamente.\n\nVerifique manualmente:\n- Acoplamento entre modulos\n- Abstrações faltando no domínio de negocio\n- Funcoes com muitos parametros (>4)`
3373
+ text: `[VIBE REFACTOR] ${fileName} (${lineCount} linhas)\n\n✅ Nenhum problema crítico de refatoracao detectado automaticamente.\n\nVerifique manualmente:\n- Acoplamento entre modulos\n- Abstrações faltando no domínio de negocio\n- Funcoes com muitos parametros (>4)`
3347
3374
  }]
3348
3375
  };
3349
3376
  }
package/package.json CHANGED
@@ -1,10 +1,18 @@
1
1
  {
2
2
  "name": "vibetachyon",
3
- "version": "1.5.0",
3
+ "version": "1.5.2",
4
4
  "description": "VibeCodes MCP CLI Installer and Server",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
7
- "vibetachyon": "dist/index.js"
7
+ "vibetachyon": "dist/index.js",
8
+ "quasar": "dist/index.js",
9
+ "lumen": "dist/index.js",
10
+ "axiom": "dist/index.js",
11
+ "cipher": "dist/index.js",
12
+ "flux": "dist/index.js",
13
+ "prism": "dist/index.js",
14
+ "zenith": "dist/index.js",
15
+ "nexus": "dist/index.js"
8
16
  },
9
17
  "scripts": {
10
18
  "build": "tsc",