@vibecheckai/cli 3.0.2 → 3.0.3

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.
Files changed (68) hide show
  1. package/package.json +9 -1
  2. package/bin/cli-hygiene.js +0 -241
  3. package/bin/guardrail.js +0 -834
  4. package/bin/runners/cli-utils.js +0 -1070
  5. package/bin/runners/context/ai-task-decomposer.js +0 -337
  6. package/bin/runners/context/analyzer.js +0 -462
  7. package/bin/runners/context/api-contracts.js +0 -427
  8. package/bin/runners/context/context-diff.js +0 -342
  9. package/bin/runners/context/context-pruner.js +0 -291
  10. package/bin/runners/context/dependency-graph.js +0 -414
  11. package/bin/runners/context/generators/claude.js +0 -107
  12. package/bin/runners/context/generators/codex.js +0 -108
  13. package/bin/runners/context/generators/copilot.js +0 -119
  14. package/bin/runners/context/generators/cursor.js +0 -514
  15. package/bin/runners/context/generators/mcp.js +0 -151
  16. package/bin/runners/context/generators/windsurf.js +0 -180
  17. package/bin/runners/context/git-context.js +0 -302
  18. package/bin/runners/context/index.js +0 -1042
  19. package/bin/runners/context/insights.js +0 -173
  20. package/bin/runners/context/mcp-server/generate-rules.js +0 -337
  21. package/bin/runners/context/mcp-server/index.js +0 -1176
  22. package/bin/runners/context/mcp-server/package.json +0 -24
  23. package/bin/runners/context/memory.js +0 -200
  24. package/bin/runners/context/monorepo.js +0 -215
  25. package/bin/runners/context/multi-repo-federation.js +0 -404
  26. package/bin/runners/context/patterns.js +0 -253
  27. package/bin/runners/context/proof-context.js +0 -972
  28. package/bin/runners/context/security-scanner.js +0 -303
  29. package/bin/runners/context/semantic-search.js +0 -350
  30. package/bin/runners/context/shared.js +0 -264
  31. package/bin/runners/context/team-conventions.js +0 -310
  32. package/bin/runners/lib/ai-bridge.js +0 -416
  33. package/bin/runners/lib/analysis-core.js +0 -271
  34. package/bin/runners/lib/analyzers.js +0 -541
  35. package/bin/runners/lib/audit-bridge.js +0 -391
  36. package/bin/runners/lib/auth-truth.js +0 -193
  37. package/bin/runners/lib/auth.js +0 -215
  38. package/bin/runners/lib/backup.js +0 -62
  39. package/bin/runners/lib/billing.js +0 -107
  40. package/bin/runners/lib/claims.js +0 -118
  41. package/bin/runners/lib/cli-ui.js +0 -540
  42. package/bin/runners/lib/compliance-bridge-new.js +0 -0
  43. package/bin/runners/lib/compliance-bridge.js +0 -165
  44. package/bin/runners/lib/contracts/auth-contract.js +0 -194
  45. package/bin/runners/lib/contracts/env-contract.js +0 -178
  46. package/bin/runners/lib/contracts/external-contract.js +0 -198
  47. package/bin/runners/lib/contracts/guard.js +0 -168
  48. package/bin/runners/lib/contracts/index.js +0 -89
  49. package/bin/runners/lib/contracts/plan-validator.js +0 -311
  50. package/bin/runners/lib/contracts/route-contract.js +0 -192
  51. package/bin/runners/lib/detect.js +0 -89
  52. package/bin/runners/lib/doctor/autofix.js +0 -254
  53. package/bin/runners/lib/doctor/index.js +0 -37
  54. package/bin/runners/lib/doctor/modules/dependencies.js +0 -325
  55. package/bin/runners/lib/doctor/modules/index.js +0 -46
  56. package/bin/runners/lib/doctor/modules/network.js +0 -250
  57. package/bin/runners/lib/doctor/modules/project.js +0 -312
  58. package/bin/runners/lib/doctor/modules/runtime.js +0 -224
  59. package/bin/runners/lib/doctor/modules/security.js +0 -348
  60. package/bin/runners/lib/doctor/modules/system.js +0 -213
  61. package/bin/runners/lib/doctor/modules/vibecheck.js +0 -394
  62. package/bin/runners/lib/doctor/reporter.js +0 -262
  63. package/bin/runners/lib/doctor/service.js +0 -262
  64. package/bin/runners/lib/doctor/types.js +0 -113
  65. package/bin/runners/lib/doctor/ui.js +0 -263
  66. package/bin/runners/lib/doctor-enhanced.js +0 -233
  67. package/bin/runners/lib/doctor-v2.js +0 -608
  68. package/bin/runners/lib/enforcement.js +0 -72
@@ -1,1042 +0,0 @@
1
- /**
2
- * vibecheck Context Generator v3.0 - AI Memory & Shared Context Engine
3
- *
4
- * Modular architecture for AI context generation across multiple platforms.
5
- *
6
- * @module context
7
- */
8
-
9
- const fs = require("fs");
10
- const path = require("path");
11
-
12
- // Import modules
13
- const { analyzeProject, findFilesRecursive } = require("./analyzer");
14
- const { detectPatterns, detectAntiPatterns } = require("./patterns");
15
- const { loadMemory, saveMemory, learnFromProject, getRecommendations, initializeMemory, VIBECHECK_HOME } = require("./memory");
16
- const { trackInsight, getInsightsSummary } = require("./insights");
17
- const { detectMonorepo } = require("./monorepo");
18
- const { loadSnapshot, saveSnapshot, generateContextDiff, saveDiffReport } = require("./context-diff");
19
- const { generatePrunedContext, getContextForFile, pruneContext } = require("./context-pruner");
20
- const { generateDependencyGraph, buildDependencyGraph, generateMermaidDiagram, generateHtmlVisualization } = require("./dependency-graph");
21
- const { generateGitContext, getGitContext } = require("./git-context");
22
- const { extractAPIContracts, generateAPIContext } = require("./api-contracts");
23
- const { analyzeTeamConventions } = require("./team-conventions");
24
- const { buildSearchIndex, saveSearchIndex, loadSearchIndex, semanticSearch, generateSearchReport } = require("./semantic-search");
25
- const { scanProject, generateSecurityReport } = require("./security-scanner");
26
- const { decomposeTask, generateDecompositionReport } = require("./ai-task-decomposer");
27
- const { registerRepository, createGroup, getSharedArtifacts, generateFederatedContext, findRelatedRepositories, syncFederation, generateFederationReport } = require("./multi-repo-federation");
28
- const { registerSharedContext } = require("./shared");
29
-
30
- // Import CLI utilities for professional styling
31
- const {
32
- colors: c,
33
- printBanner,
34
- printCompactBanner,
35
- printCommandHeader,
36
- printSectionHeader,
37
- printSectionFooter,
38
- printListItem,
39
- printBulletedList,
40
- printTable,
41
- highlight,
42
- highlightCode,
43
- highlightPath,
44
- printError,
45
- printWarning,
46
- printSuccess,
47
- printSummaryCard,
48
- gradientText,
49
- formatNumber,
50
- formatBytes,
51
- statusIcon,
52
- progressBar,
53
- } = require("../cli-utils");
54
-
55
- // Platform generators
56
- const { generateCursorRules, generateCursorModularRules } = require("./generators/cursor");
57
- const { generateWindsurfRules } = require("./generators/windsurf");
58
- const { generateCopilotInstructions } = require("./generators/copilot");
59
- const { generateClaudeConfig } = require("./generators/claude");
60
- const { generateCodexConfig } = require("./generators/codex");
61
- const { generateContextJson } = require("./generators/mcp");
62
-
63
- /**
64
- * Parse command line arguments
65
- */
66
- function parseArgs(args) {
67
- const opts = {
68
- path: ".",
69
- platform: "all",
70
- watch: false,
71
- verbose: false,
72
- help: false,
73
- diff: false,
74
- prune: false,
75
- maxTokens: 8000,
76
- currentFile: "",
77
- task: "general",
78
- json: false,
79
- search: "",
80
- scan: false,
81
- decompose: "",
82
- federate: false,
83
- };
84
-
85
- for (let i = 0; i < args.length; i++) {
86
- const a = args[i];
87
- if (a === "--help" || a === "-h") opts.help = true;
88
- if (a.startsWith("--path=")) opts.path = a.split("=")[1];
89
- if (a === "--path" || a === "-p") opts.path = args[++i];
90
- if (a.startsWith("--platform=")) opts.platform = a.split("=")[1];
91
- if (a === "--platform") opts.platform = args[++i];
92
- if (a === "--watch" || a === "-w") opts.watch = true;
93
- if (a === "--verbose" || a === "-v") opts.verbose = true;
94
- if (a === "--diff" || a === "-d") opts.diff = true;
95
- if (a === "--prune") opts.prune = true;
96
- if (a === "--json" || a === "-j") opts.json = true;
97
- if (a === "--scan" || a === "-s") opts.scan = true;
98
- if (a === "--federate" || a === "-f") opts.federate = true;
99
- if (a.startsWith("--max-tokens=")) opts.maxTokens = parseInt(a.split("=")[1]);
100
- if (a.startsWith("--file=")) opts.currentFile = a.split("=")[1];
101
- if (a.startsWith("--task=")) opts.task = a.split("=")[1];
102
- if (a.startsWith("--search=")) opts.search = a.split("=")[1];
103
- if (a.startsWith("--decompose=")) opts.decompose = a.split("=")[1];
104
- if (["cursor", "windsurf", "copilot", "claude", "codex"].includes(a)) {
105
- opts.platform = a;
106
- }
107
- }
108
- return opts;
109
- }
110
-
111
- /**
112
- * Print help message
113
- */
114
- function printHelp() {
115
- console.log();
116
- printBanner();
117
- printCommandHeader("CONTEXT", "AI Memory & Shared Context Engine v3.1");
118
-
119
- console.log(`${c.yellow}USAGE${c.reset}`);
120
- console.log(` ${c.cyan}vibecheck context${c.reset} ${c.dim}[options]${c.reset}`);
121
- console.log(` ${c.cyan}vibecheck context cursor${c.reset} ${c.dim}# Generate Cursor rules only${c.reset}`);
122
- console.log(` ${c.cyan}vibecheck context windsurf${c.reset} ${c.dim}# Generate Windsurf rules only${c.reset}`);
123
- console.log(` ${c.cyan}vibecheck context codex${c.reset} ${c.dim}# Generate Codex/ChatGPT rules${c.reset}`);
124
- console.log();
125
-
126
- console.log(`${c.yellow}OPTIONS${c.reset}`);
127
- const options = [
128
- ['--platform <name>', 'Platform: cursor, windsurf, copilot, claude, codex, all'],
129
- ['--path <dir>', 'Project directory (default: current)'],
130
- ['--watch', 'Watch for changes and regenerate'],
131
- ['--verbose', 'Show detailed output'],
132
- ['--diff', 'Show changes since last generation'],
133
- ['--prune', 'Generate pruned context (reduced tokens)'],
134
- ['--max-tokens <n>', 'Max tokens for pruned context (default: 8000)'],
135
- ['--file <path>', 'Current file for context relevance'],
136
- ['--task <type>', 'Task type: general, api, utility, component'],
137
- ['--json', 'Output JSON for CI/programmatic use'],
138
- ['--search <query>', 'Semantic code search'],
139
- ['--scan', 'Security scan for secrets and vulnerabilities'],
140
- ['--decompose <task>', 'AI task decomposition for smart context'],
141
- ['--federate', 'Multi-repo context federation'],
142
- ['--help', 'Show this help'],
143
- ];
144
-
145
- printTable(['Option', 'Description'], options);
146
- console.log();
147
-
148
- console.log(`${c.yellow}SUPPORTED PLATFORMS${c.reset}`);
149
- console.log();
150
- const platforms = [
151
- ['Cursor', '.cursorrules, .cursor/rules/*.mdc'],
152
- ['Windsurf', '.windsurf/rules/*.md'],
153
- ['Copilot', '.github/copilot-instructions.md'],
154
- ['Claude Code', '.claude/project-context.md, .claude/mcp-config.json'],
155
- ['Codex/ChatGPT', '.codex-instructions.md'],
156
- ['MCP (Universal)', '.vibecheck/context.json, .vibecheck/memory.json'],
157
- ];
158
-
159
- printTable(['Platform', 'Generated Files'], platforms);
160
- console.log();
161
-
162
- console.log(`${gradientText('v3.1 FEATURES', [c.cyan, c.blue, c.magenta])}${c.reset}`);
163
- console.log();
164
-
165
- const features = [
166
- {
167
- icon: '🧠',
168
- title: 'Self-Learning AI Memory',
169
- items: [
170
- '• Learns from all your projects',
171
- '• Recommends patterns you use frequently',
172
- '• Stored in ~/.vibecheck/global-memory.json',
173
- ]
174
- },
175
- {
176
- icon: '🔍',
177
- title: 'Semantic Code Search',
178
- items: [
179
- '• Natural language code search',
180
- '• TF-IDF vectorization for accuracy',
181
- '• Ranked results with similarity scores',
182
- ]
183
- },
184
- {
185
- icon: '🔒',
186
- title: 'Security Scanner',
187
- items: [
188
- '• Detect secrets and API keys',
189
- '• Find vulnerabilities before production',
190
- '• Detailed security reports',
191
- ]
192
- },
193
- {
194
- icon: '🎯',
195
- title: 'AI Task Decomposition',
196
- items: [
197
- '• Smart context selection for tasks',
198
- '• Token estimation to stay under limits',
199
- '• Implementation recommendations',
200
- ]
201
- },
202
- {
203
- icon: '🌐',
204
- title: 'Multi-Repo Federation',
205
- items: [
206
- '• Unify context across repositories',
207
- '• Detect shared components and patterns',
208
- '• Cross-project knowledge sharing',
209
- ]
210
- },
211
- ];
212
-
213
- features.forEach(feature => {
214
- console.log(`${c.magenta}${feature.icon} ${feature.title}${c.reset}`);
215
- feature.items.forEach(item => {
216
- console.log(` ${c.dim}${item}${c.reset}`);
217
- });
218
- console.log();
219
- });
220
-
221
- console.log(`${c.yellow}EXAMPLES${c.reset}`);
222
- console.log();
223
- const examples = [
224
- ['vibecheck context', 'Generate all rules files'],
225
- ['vibecheck context cursor', 'Cursor only'],
226
- ['vibecheck context codex', 'Codex/ChatGPT only'],
227
- ['vibecheck context --watch', 'Watch mode - auto-regenerate'],
228
- ['vibecheck context --diff', 'Show changes since last generation'],
229
- ['vibecheck context --prune', 'Generate reduced context for tokens'],
230
- ['vibecheck context --file src/App.tsx --prune', 'Context for specific file'],
231
- ['vibecheck context --search "auth hook"', 'Semantic code search'],
232
- ['vibecheck context --scan', 'Security scan'],
233
- ['vibecheck context --decompose "create user profile"', 'AI task analysis'],
234
- ['vibecheck context --federate', 'Multi-repo federation'],
235
- ];
236
-
237
- examples.forEach(([cmd, desc]) => {
238
- console.log(` ${c.cyan}${cmd}${c.reset}`);
239
- console.log(` ${c.dim}${desc}${c.reset}`);
240
- console.log();
241
- });
242
- }
243
-
244
- /**
245
- * Write all generated files to disk
246
- */
247
- function writeFiles(projectPath, platform, analysis, verbose) {
248
- const written = [];
249
-
250
- // Cursor files
251
- if (platform === "all" || platform === "cursor") {
252
- const cursorRules = generateCursorRules(analysis);
253
- fs.writeFileSync(path.join(projectPath, ".cursorrules"), cursorRules);
254
- written.push(".cursorrules");
255
-
256
- const cursorDir = path.join(projectPath, ".cursor", "rules");
257
- fs.mkdirSync(cursorDir, { recursive: true });
258
-
259
- const modularRules = generateCursorModularRules(analysis);
260
- for (const [name, content] of Object.entries(modularRules)) {
261
- fs.writeFileSync(path.join(cursorDir, `${name}.mdc`), content);
262
- written.push(`.cursor/rules/${name}.mdc`);
263
- }
264
- }
265
-
266
- // Windsurf files
267
- if (platform === "all" || platform === "windsurf") {
268
- const windsurfDir = path.join(projectPath, ".windsurf", "rules");
269
- fs.mkdirSync(windsurfDir, { recursive: true });
270
-
271
- const windsurfRules = generateWindsurfRules(analysis);
272
- for (const [name, content] of Object.entries(windsurfRules)) {
273
- fs.writeFileSync(path.join(windsurfDir, `${name}.md`), content);
274
- written.push(`.windsurf/rules/${name}.md`);
275
- }
276
- }
277
-
278
- // Copilot instructions
279
- if (platform === "all" || platform === "copilot") {
280
- const githubDir = path.join(projectPath, ".github");
281
- fs.mkdirSync(githubDir, { recursive: true });
282
-
283
- const copilotInstructions = generateCopilotInstructions(analysis);
284
- fs.writeFileSync(path.join(githubDir, "copilot-instructions.md"), copilotInstructions);
285
- written.push(".github/copilot-instructions.md");
286
- }
287
-
288
- // Claude Desktop config
289
- if (platform === "all" || platform === "claude") {
290
- const claudeDir = path.join(projectPath, ".claude");
291
- fs.mkdirSync(claudeDir, { recursive: true });
292
-
293
- const { config, instructions } = generateClaudeConfig(analysis, projectPath);
294
- fs.writeFileSync(path.join(claudeDir, "mcp-config.json"), JSON.stringify(config, null, 2));
295
- fs.writeFileSync(path.join(claudeDir, "project-context.md"), instructions);
296
- written.push(".claude/mcp-config.json");
297
- written.push(".claude/project-context.md");
298
- }
299
-
300
- // Codex / ChatGPT instructions
301
- if (platform === "all" || platform === "codex") {
302
- const codexConfig = generateCodexConfig(analysis, projectPath);
303
- fs.writeFileSync(path.join(projectPath, ".codex-instructions.md"), codexConfig);
304
- written.push(".codex-instructions.md");
305
- }
306
-
307
- // Universal context (always generated)
308
- const vibecheckDir = path.join(projectPath, ".vibecheck");
309
- fs.mkdirSync(vibecheckDir, { recursive: true });
310
-
311
- const contextJson = generateContextJson(analysis, projectPath);
312
- fs.writeFileSync(path.join(vibecheckDir, "context.json"), contextJson);
313
- written.push(".vibecheck/context.json");
314
-
315
- fs.writeFileSync(path.join(vibecheckDir, "project-map.json"), JSON.stringify(analysis, null, 2));
316
- written.push(".vibecheck/project-map.json");
317
-
318
- // Generate AI memory file
319
- const memory = learnFromProject(projectPath, analysis);
320
- const projectId = Object.keys(memory.projects).find(k => memory.projects[k].path === projectPath);
321
- fs.writeFileSync(path.join(vibecheckDir, "memory.json"), JSON.stringify({
322
- projectMemory: memory.projects[projectId] || {},
323
- globalPatterns: memory.patterns,
324
- recommendations: getRecommendations(analysis),
325
- lastUpdated: new Date().toISOString(),
326
- }, null, 2));
327
- written.push(".vibecheck/memory.json");
328
-
329
- // Generate insights file
330
- const insights = trackInsight(projectPath, "context_generated", {
331
- files: analysis.stats?.totalFiles || 0,
332
- components: analysis.components?.length || 0,
333
- platform: platform,
334
- });
335
- const insightsSummary = getInsightsSummary();
336
- fs.writeFileSync(path.join(vibecheckDir, "insights.json"), JSON.stringify({
337
- session: insights.sessions?.slice(-1)[0] || {},
338
- summary: insightsSummary,
339
- lastUpdated: new Date().toISOString(),
340
- }, null, 2));
341
- written.push(".vibecheck/insights.json");
342
-
343
- // Register in shared context
344
- registerSharedContext(projectPath, analysis);
345
-
346
- return written;
347
- }
348
-
349
- /**
350
- * Watch mode - regenerate on file changes
351
- */
352
- function startWatchMode(projectPath, platform, verbose) {
353
- console.log(`${c.cyan}👁 Watch mode enabled${c.reset} - regenerating on file changes\n`);
354
- console.log(`${c.dim}Watching: ${projectPath}${c.reset}`);
355
- console.log(`${c.dim}Press Ctrl+C to stop${c.reset}\n`);
356
-
357
- let debounceTimer = null;
358
- const watchDirs = ["src", "app", "pages", "components", "lib", "server"];
359
-
360
- const regenerate = () => {
361
- console.log(`\n${c.yellow}⟳ Change detected, regenerating...${c.reset}\n`);
362
- try {
363
- const analysis = analyzeProject(projectPath);
364
- writeFiles(projectPath, platform, analysis, verbose);
365
- console.log(`${c.green}✓ Rules regenerated${c.reset} at ${new Date().toLocaleTimeString()}\n`);
366
- } catch (err) {
367
- console.log(`${c.red}✗ Regeneration failed:${c.reset} ${err.message}\n`);
368
- }
369
- };
370
-
371
- for (const dir of watchDirs) {
372
- const watchPath = path.join(projectPath, dir);
373
- if (fs.existsSync(watchPath)) {
374
- try {
375
- fs.watch(watchPath, { recursive: true }, (eventType, filename) => {
376
- if (filename && (filename.endsWith(".ts") || filename.endsWith(".tsx") || filename.endsWith(".js") || filename.endsWith(".jsx"))) {
377
- if (debounceTimer) clearTimeout(debounceTimer);
378
- debounceTimer = setTimeout(regenerate, 500);
379
- }
380
- });
381
- console.log(`${c.dim} Watching: ${dir}/${c.reset}`);
382
- } catch {}
383
- }
384
- }
385
-
386
- process.on("SIGINT", () => {
387
- console.log(`\n${c.cyan}Watch mode stopped${c.reset}\n`);
388
- process.exit(0);
389
- });
390
-
391
- setInterval(() => {}, 1000);
392
- }
393
-
394
- /**
395
- * Main entry point
396
- */
397
- async function runContext(args) {
398
- const opts = parseArgs(args);
399
-
400
- if (opts.help) {
401
- printHelp();
402
- return 0;
403
- }
404
-
405
- const projectPath = path.resolve(opts.path);
406
-
407
- // Handle search mode first (before any other output)
408
- if (opts.search) {
409
- printBanner();
410
- printCommandHeader("SEMANTIC SEARCH", "Natural Language Code Search");
411
- console.log(`${c.dim}Query:${c.reset} ${highlightCode(`"${opts.search}"`)}\n`);
412
-
413
- console.log(`${c.dim}🔍 Building search index...${c.reset}`, '\r');
414
- let searchIndex = loadSearchIndex(projectPath);
415
- if (!searchIndex) {
416
- console.log(`${c.yellow}🔍 Building search index...${c.reset}`, '\r');
417
- searchIndex = buildSearchIndex(projectPath);
418
- saveSearchIndex(projectPath, searchIndex);
419
- console.log(`${c.green}✓ Search index built${c.reset} \n`);
420
- } else {
421
- console.log(`${c.green}✓ Search index loaded${c.reset} \n`);
422
- }
423
-
424
- console.log(`${c.dim}🔍 Searching code...${c.reset}`, '\r');
425
- const results = semanticSearch(searchIndex, opts.search, 10);
426
- console.log(`${c.green}✓ Search complete${c.reset} \n`);
427
-
428
- if (results.length === 0) {
429
- console.log(`${c.yellow}⚠ No results found for "${opts.search}"${c.reset}\n`);
430
- } else {
431
- console.log(`${c.green}Found ${formatNumber(results.length)} results:${c.reset}\n`);
432
-
433
- printTable(['File', 'Lines', 'Match', 'Type'],
434
- results.map(r => [
435
- highlightPath(r.file),
436
- `${r.startLine}-${r.endLine}`,
437
- `${(r.similarity * 100).toFixed(1)}%`,
438
- r.type || 'code'
439
- ])
440
- );
441
-
442
- // Save report
443
- const report = generateSearchReport(results, opts.search);
444
- const reportFile = path.join(projectPath, ".vibecheck", "search-report.md");
445
- fs.writeFileSync(reportFile, report);
446
- console.log(`\n${c.dim}📄 Full report saved to:${c.reset} ${highlightPath(reportFile)}\n`);
447
- }
448
-
449
- return 0;
450
- }
451
-
452
- // Handle scan mode
453
- if (opts.scan) {
454
- printBanner();
455
- printCommandHeader("SECURITY SCAN", "Detect Secrets & Vulnerabilities");
456
- console.log(`${c.dim}Scanning project for security issues...${c.reset}\n`);
457
-
458
- const scanResults = scanProject(projectPath);
459
-
460
- printSectionHeader('SCAN RESULTS');
461
- console.log(`${c.dim}Files Scanned:${c.reset} ${formatNumber(scanResults.stats.totalFiles)}`);
462
- console.log(`${c.dim}Critical Issues:${c.reset} ${c.red}${scanResults.stats.criticalIssues}${c.reset}`);
463
- console.log(`${c.dim}High Issues:${c.reset} ${c.yellow}${scanResults.stats.highIssues}${c.reset}`);
464
- console.log(`${c.dim}Medium Issues:${c.reset} ${scanResults.stats.mediumIssues}`);
465
- console.log(`${c.dim}Secrets Found:${c.reset} ${scanResults.secrets.length}`);
466
- console.log(`${c.dim}Vulnerabilities:${c.reset} ${scanResults.vulnerabilities.length}\n`);
467
-
468
- if (scanResults.secrets.length > 0 || scanResults.vulnerabilities.length > 0) {
469
- console.log(`${c.bgRed}${c.white} ⚠ SECURITY ISSUES DETECTED ${c.reset}\n`);
470
-
471
- // Show critical issues
472
- const criticalIssues = [...scanResults.secrets, ...scanResults.vulnerabilities]
473
- .filter(i => i.severity === "critical" || i.severity === "high")
474
- .slice(0, 5);
475
-
476
- console.log(`${c.bold}Critical Issues:${c.reset}\n`);
477
- criticalIssues.forEach((issue, idx) => {
478
- const severityColor = issue.severity === 'critical' ? c.red : c.yellow;
479
- console.log(`${idx + 1}. ${severityColor}${issue.type}${c.reset} in ${highlightPath(issue.file)}:${issue.line}`);
480
- if (issue.description) {
481
- console.log(` ${c.dim}${issue.description}${c.reset}`);
482
- }
483
- });
484
-
485
- // Save report
486
- const report = generateSecurityReport(scanResults);
487
- const reportFile = path.join(projectPath, ".vibecheck", "security-report.md");
488
- fs.writeFileSync(reportFile, report);
489
- console.log(`\n${c.dim}📄 Full report saved to:${c.reset} ${highlightPath(reportFile)}\n`);
490
- } else {
491
- console.log(`${c.bgGreen}${c.black} ✓ NO SECURITY ISSUES FOUND ${c.reset}\n`);
492
- }
493
-
494
- return 0;
495
- }
496
-
497
- // Handle decompose mode
498
- if (opts.decompose) {
499
- printBanner();
500
- printCommandHeader("AI TASK DECOMPOSITION", "Smart Context Selection");
501
- console.log(`${c.dim}Task:${c.reset} ${highlightCode(`"${opts.decompose}"`)}\n`);
502
-
503
- console.log(`${c.dim}🧠 Analyzing task...${c.reset}`, '\r');
504
- const plan = decomposeTask(opts.decompose, projectPath);
505
- console.log(`${c.green}✓ Task analyzed${c.reset} \n`);
506
-
507
- printSectionHeader('TASK ANALYSIS');
508
- console.log(`${c.dim}Task Type:${c.reset} ${highlight(plan.taskType)}`);
509
- console.log(`${c.dim}Search Query:${c.reset} ${highlightCode(`"${plan.searchQuery}"`)}`);
510
- console.log(`${c.dim}Context Files:${c.reset} ${formatNumber(plan.context.files.length)}`);
511
- console.log(`${c.dim}Estimated Tokens:${c.reset} ${formatNumber(plan.context.totalTokens)}\n`);
512
-
513
- if (plan.context.files.length > 0) {
514
- console.log(`${c.bold}Selected Context:${c.reset}\n`);
515
- printTable(['File', 'Tokens', 'Relevance'],
516
- plan.context.files.slice(0, 10).map(f => [
517
- highlightPath(f.file),
518
- formatNumber(f.tokens),
519
- `${(f.relevance * 100).toFixed(1)}%`
520
- ])
521
- );
522
- if (plan.context.files.length > 10) {
523
- console.log(`${c.dim}... and ${plan.context.files.length - 10} more files${c.reset}\n`);
524
- }
525
- }
526
-
527
- if (plan.recommendations.length > 0) {
528
- console.log(`${c.bold}Recommendations:${c.reset}\n`);
529
- plan.recommendations.forEach((rec, idx) => {
530
- console.log(`${idx + 1}. ${c.cyan}•${c.reset} ${rec}`);
531
- });
532
- console.log();
533
- }
534
-
535
- // Save report
536
- const report = generateDecompositionReport(plan);
537
- const reportFile = path.join(projectPath, ".vibecheck", "task-decomposition.md");
538
- fs.writeFileSync(reportFile, report);
539
- console.log(`${c.dim}📄 Full report saved to:${c.reset} ${highlightPath(reportFile)}\n`);
540
-
541
- return 0;
542
- }
543
-
544
- // Handle federation mode
545
- if (opts.federate) {
546
- printBanner();
547
- printCommandHeader("MULTI-REPO FEDERATION", "Cross-Repository Context");
548
- console.log(`${c.dim}Initializing federation...${c.reset}\n`);
549
-
550
- // Register current repo
551
- console.log(`${c.dim}📋 Registering repository...${c.reset}`, '\r');
552
- const repoInfo = registerRepository(projectPath);
553
- console.log(`${c.green}✓ Repository registered${c.reset} \n`);
554
- console.log(`${c.dim}Name:${c.reset} ${highlight(repoInfo.name || repoInfo.id)}\n`);
555
-
556
- // Find related repos
557
- console.log(`${c.dim}🔍 Finding related repositories...${c.reset}`, '\r');
558
- const related = findRelatedRepositories(projectPath, 5);
559
- console.log(`${c.green}✓ Found ${related.length} related repos${c.reset}\n`);
560
-
561
- if (related.length > 0) {
562
- console.log(`${c.bold}Related Repositories:${c.reset}\n`);
563
- printTable(['Repository', 'Framework', 'Similarity'],
564
- related.map(r => [
565
- highlight(r.name || r.id),
566
- r.framework || "Unknown",
567
- `${(r.similarity * 100).toFixed(0)}%`
568
- ])
569
- );
570
- }
571
-
572
- // Generate federated context
573
- console.log(`\n${c.dim}🌐 Generating federated context...${c.reset}`, '\r');
574
- const federated = generateFederatedContext();
575
- console.log(`${c.green}✓ Federation complete${c.reset} \n`);
576
-
577
- printSectionHeader('FEDERATION SUMMARY');
578
- console.log(`${c.dim}Total Repositories:${c.reset} ${formatNumber(federated.stats.totalRepos)}`);
579
- console.log(`${c.dim}Shared Components:${c.reset} ${formatNumber(federated.stats.sharedComponents)}`);
580
- console.log(`${c.dim}Shared Hooks:${c.reset} ${formatNumber(federated.stats.sharedHooks)}`);
581
- console.log(`${c.dim}Shared Patterns:${c.reset} ${formatNumber(federated.stats.sharedPatterns)}\n`);
582
-
583
- // Save report
584
- const report = generateFederationReport(federated);
585
- const reportFile = path.join(projectPath, ".vibecheck", "federation-report.md");
586
- fs.writeFileSync(reportFile, report);
587
- console.log(`${c.dim}📄 Full report saved to:${c.reset} ${highlightPath(reportFile)}\n`);
588
-
589
- return 0;
590
- }
591
-
592
- // Default context generation
593
- printBanner();
594
- printCommandHeader("CONTEXT", "AI Memory & Shared Context Engine");
595
- console.log(`${c.dim}Analyzing project:${c.reset} ${highlightPath(projectPath)}\n`);
596
-
597
- // Handle diff mode
598
- if (opts.diff) {
599
- const previous = loadSnapshot(projectPath);
600
- if (!previous) {
601
- console.log(`${c.yellow}No previous context generation found.${c.reset}\n`);
602
- console.log(`Run ${c.cyan}vibecheck context${c.reset} first to generate baseline.\n`);
603
- return 1;
604
- }
605
-
606
- console.log(`${c.dim}Loading previous context...${c.reset}\n`);
607
- const analysis = analyzeProject(projectPath);
608
- const diff = generateContextDiff(previous, analysis);
609
-
610
- console.log(`${c.green}Context Changes:${c.reset}\n`);
611
- console.log(`- Total Changes: ${diff.summary.totalChanges}`);
612
- console.log(`- Additions: ${diff.summary.additions}`);
613
- console.log(`- Removals: ${diff.summary.removals}`);
614
- console.log(`- Breaking Changes: ${diff.summary.breakingChanges}\n`);
615
-
616
- if (diff.summary.totalChanges > 0) {
617
- console.log(`${c.yellow}Changes detected:${c.reset}\n`);
618
- for (const change of diff.changes.added.slice(0, 10)) {
619
- console.log(` ${c.green}+${c.reset} ${change.type}: ${change.name}`);
620
- }
621
- for (const change of diff.changes.removed.slice(0, 10)) {
622
- console.log(` ${c.red}-${c.reset} ${change.type}: ${change.name}`);
623
- }
624
-
625
- const reportFile = saveDiffReport(projectPath, diff);
626
- console.log(`\n${c.dim}Full report saved to: ${reportFile}${c.reset}\n`);
627
- } else {
628
- console.log(`${c.green}No changes detected since last generation.${c.reset}\n`);
629
- }
630
-
631
- return 0;
632
- }
633
-
634
- // Handle prune mode
635
- if (opts.prune) {
636
- console.log(`${c.dim}Analyzing project for pruning...${c.reset}\n`);
637
- const analysis = analyzeProject(projectPath);
638
-
639
- const pruned = opts.currentFile
640
- ? getContextForFile(path.join(projectPath, opts.currentFile), analysis)
641
- : pruneContext(analysis, {
642
- maxTokens: opts.maxTokens,
643
- task: opts.task,
644
- });
645
-
646
- console.log(`${c.green}Pruned Context Generated:${c.reset}\n`);
647
- console.log(`- Total Files: ${pruned.totalCount || 0}`);
648
- console.log(`- Included Files: ${pruned.includedCount || 0}`);
649
- console.log(`- Pruned Files: ${pruned.pruned || 0}`);
650
- console.log(`- Estimated Tokens: ${pruned.totalTokens || 0} / ${pruned.maxTokens || opts.maxTokens}\n`);
651
-
652
- console.log(`${c.dim}Top files by relevance:${c.reset}\n`);
653
- for (const file of pruned.files.slice(0, 10)) {
654
- console.log(` ${c.cyan}•${c.reset} ${file.path} (score: ${file.score}, tokens: ${file.tokens})`);
655
- }
656
-
657
- // Save pruned context
658
- const vibecheckDir = path.join(projectPath, ".vibecheck");
659
- if (!fs.existsSync(vibecheckDir)) {
660
- fs.mkdirSync(vibecheckDir, { recursive: true });
661
- }
662
-
663
- const outputPath = path.join(vibecheckDir, "context-pruned.json");
664
- const outputData = opts.currentFile ? pruned : generatePrunedContext(analysis, {
665
- maxTokens: opts.maxTokens,
666
- task: opts.task,
667
- });
668
-
669
- fs.writeFileSync(outputPath, JSON.stringify(outputData, null, 2));
670
- console.log(`\n${c.dim}Saved to: .vibecheck/context-pruned.json${c.reset}\n`);
671
-
672
- return 0;
673
- }
674
-
675
- // Handle search mode first (before any other output)
676
- if (opts.search) {
677
- console.log(`
678
- ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
679
- ${c.bold}vibecheck CONTEXT v3.0${c.reset} - Semantic Code Search
680
- ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
681
- `);
682
- console.log(`${c.dim}Searching code...${c.reset}\n`);
683
-
684
- let searchIndex = loadSearchIndex(projectPath);
685
- if (!searchIndex) {
686
- console.log(`${c.yellow}Building search index...${c.reset}\n`);
687
- searchIndex = buildSearchIndex(projectPath);
688
- saveSearchIndex(projectPath, searchIndex);
689
- }
690
-
691
- const results = semanticSearch(searchIndex, opts.search, 10);
692
-
693
- if (results.length === 0) {
694
- console.log(`${c.yellow}No results found for "${opts.search}"${c.reset}\n`);
695
- } else {
696
- console.log(`${c.green}Found ${results.length} results:${c.reset}\n`);
697
- for (const result of results) {
698
- console.log(` ${c.cyan}•${c.reset} ${result.file}:${result.startLine}-${result.endLine} (${(result.similarity * 100).toFixed(1)}% match)`);
699
- console.log(` ${c.dim}${result.type}${c.reset}`);
700
- }
701
-
702
- // Save report
703
- const report = generateSearchReport(results, opts.search);
704
- const reportFile = path.join(projectPath, ".vibecheck", "search-report.md");
705
- fs.writeFileSync(reportFile, report);
706
- console.log(`\n${c.dim}Full report saved to: ${reportFile}${c.reset}\n`);
707
- }
708
-
709
- return 0;
710
- }
711
-
712
- // Handle scan mode
713
- if (opts.scan) {
714
- console.log(`
715
- ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
716
- ${c.bold}vibecheck CONTEXT v3.0${c.reset} - Security Scanner
717
- ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
718
- `);
719
- console.log(`${c.dim}Scanning for security issues...${c.reset}\n`);
720
-
721
- const scanResults = scanProject(projectPath);
722
-
723
- console.log(`${c.green}Security Scan Results:${c.reset}\n`);
724
- console.log(`- Files Scanned: ${scanResults.stats.totalFiles}`);
725
- console.log(`- Critical Issues: ${scanResults.stats.criticalIssues}`);
726
- console.log(`- High Issues: ${scanResults.stats.highIssues}`);
727
- console.log(`- Medium Issues: ${scanResults.stats.mediumIssues}`);
728
- console.log(`- Secrets Found: ${scanResults.secrets.length}`);
729
- console.log(`- Vulnerabilities: ${scanResults.vulnerabilities.length}\n`);
730
-
731
- if (scanResults.secrets.length > 0 || scanResults.vulnerabilities.length > 0) {
732
- console.log(`${c.red}⚠ Security issues detected!${c.reset}\n`);
733
-
734
- // Show critical issues
735
- const criticalIssues = [...scanResults.secrets, ...scanResults.vulnerabilities]
736
- .filter(i => i.severity === "critical" || i.severity === "high")
737
- .slice(0, 5);
738
-
739
- for (const issue of criticalIssues) {
740
- console.log(` ${c.red}•${c.reset} ${issue.type} in ${issue.file}:${issue.line}`);
741
- }
742
-
743
- // Save report
744
- const report = generateSecurityReport(scanResults);
745
- const reportFile = path.join(projectPath, ".vibecheck", "security-report.md");
746
- fs.writeFileSync(reportFile, report);
747
- console.log(`\n${c.dim}Full report saved to: ${reportFile}${c.reset}\n`);
748
- } else {
749
- console.log(`${c.green}✅ No security issues found!${c.reset}\n`);
750
- }
751
-
752
- return 0;
753
- }
754
-
755
- // Handle decompose mode
756
- if (opts.decompose) {
757
- console.log(`
758
- ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
759
- ${c.bold}vibecheck CONTEXT v3.0${c.reset} - AI Task Decomposition
760
- ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
761
- `);
762
- console.log(`${c.dim}Decomposing task...${c.reset}\n`);
763
-
764
- const plan = decomposeTask(opts.decompose, projectPath);
765
-
766
- console.log(`${c.green}Task Analysis:${c.reset}\n`);
767
- console.log(`- Task Type: ${plan.taskType}`);
768
- console.log(`- Search Query: "${plan.searchQuery}"`);
769
- console.log(`- Context Files: ${plan.context.files.length}`);
770
- console.log(`- Estimated Tokens: ${plan.context.totalTokens}\n`);
771
-
772
- if (plan.context.files.length > 0) {
773
- console.log(`${c.dim}Selected Context:${c.reset}\n`);
774
- for (const file of plan.context.files.slice(0, 5)) {
775
- console.log(` ${c.cyan}•${c.reset} ${file.file} (${file.tokens} tokens)`);
776
- }
777
- }
778
-
779
- if (plan.recommendations.length > 0) {
780
- console.log(`\n${c.magenta}Recommendations:${c.reset}\n`);
781
- for (const rec of plan.recommendations) {
782
- console.log(` • ${rec}`);
783
- }
784
- }
785
-
786
- // Save report
787
- const report = generateDecompositionReport(plan);
788
- const reportFile = path.join(projectPath, ".vibecheck", "task-decomposition.md");
789
- fs.writeFileSync(reportFile, report);
790
- console.log(`\n${c.dim}Full report saved to: ${reportFile}${c.reset}\n`);
791
-
792
- return 0;
793
- }
794
-
795
- // Handle federation mode
796
- if (opts.federate) {
797
- console.log(`
798
- ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
799
- ${c.bold}vibecheck CONTEXT v3.0${c.reset} - Multi-Repo Federation
800
- ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
801
- `);
802
- console.log(`${c.dim}Initializing federation...${c.reset}\n`);
803
-
804
- // Register current repo
805
- const repoInfo = registerRepository(projectPath);
806
- console.log(`${c.green}Registered repository:${c.reset} ${repoInfo.name || repoInfo.id}\n`);
807
-
808
- // Find related repos
809
- const related = findRelatedRepositories(projectPath, 5);
810
- if (related.length > 0) {
811
- console.log(`${c.cyan}Related repositories:${c.reset}\n`);
812
- for (const repo of related) {
813
- console.log(` • ${repo.name || repo.id} (${repo.framework || "Unknown"}) - ${(repo.similarity * 100).toFixed(0)}% similar`);
814
- }
815
- }
816
-
817
- // Generate federated context
818
- const federated = generateFederatedContext();
819
- console.log(`\n${c.green}Federation Summary:${c.reset}\n`);
820
- console.log(`- Total Repositories: ${federated.stats.totalRepos}`);
821
- console.log(`- Shared Components: ${federated.stats.sharedComponents}`);
822
- console.log(`- Shared Hooks: ${federated.stats.sharedHooks}`);
823
- console.log(`- Shared Patterns: ${federated.stats.sharedPatterns}\n`);
824
-
825
- // Save report
826
- const report = generateFederationReport(federated);
827
- const reportFile = path.join(projectPath, ".vibecheck", "federation-report.md");
828
- fs.writeFileSync(reportFile, report);
829
- console.log(`${c.dim}Full report saved to: ${reportFile}${c.reset}\n`);
830
-
831
- return 0;
832
- }
833
-
834
- // Default header for other modes
835
- console.log(`
836
- ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
837
- ${c.bold}vibecheck CONTEXT v3.0${c.reset} - AI Memory & Shared Context Engine
838
- ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
839
- `);
840
-
841
- // Analyze project
842
- const analysis = analyzeProject(projectPath);
843
- const p = analysis.patterns || {};
844
-
845
- // Display analysis - Basic info
846
- printSectionHeader('PROJECT ANALYSIS');
847
- console.log(`${c.dim}Project:${c.reset} ${highlight(analysis.name)}`);
848
- console.log(`${c.dim}Framework:${c.reset} ${analysis.framework || "Unknown"}`);
849
- console.log(`${c.dim}Language:${c.reset} ${analysis.language || "JavaScript"}`);
850
- console.log(`${c.dim}Architecture:${c.reset} ${analysis.architecture}`);
851
-
852
- const s = analysis.stats || {};
853
- if (s.totalFiles) {
854
- console.log(`${c.dim}Size:${c.reset} ${formatNumber(s.totalFiles)} files, ~${formatNumber(Math.round(s.totalLines / 1000))}k lines`);
855
- }
856
-
857
- // Structure
858
- console.log(`\n${c.blue}Structure:${c.reset}`);
859
- console.log(` ${c.dim}Directories:${c.reset} ${analysis.directories.length} | ${c.dim}Components:${c.reset} ${analysis.components.length} | ${c.dim}API Routes:${c.reset} ${analysis.apiRoutes.length} | ${c.dim}Models:${c.reset} ${analysis.models.length}`);
860
-
861
- const t = analysis.types || {};
862
- if (t.interfaces?.length || t.types?.length) {
863
- console.log(` ${c.dim}Interfaces:${c.reset} ${t.interfaces?.length || 0} | ${c.dim}Types:${c.reset} ${t.types?.length || 0} | ${c.dim}Enums:${c.reset} ${t.enums?.length || 0}`);
864
- }
865
-
866
- const env = analysis.envVars || {};
867
- if (env.variables?.length) {
868
- console.log(` ${c.dim}Env Vars:${c.reset} ${env.variables.length} detected`);
869
- }
870
-
871
- // Patterns
872
- if (p.hooks?.length || p.stateManagement || p.dataFetching?.length || p.styling?.length) {
873
- console.log(`\n${c.magenta}Patterns Detected:${c.reset}`);
874
- if (p.hooks?.length) console.log(` ${c.dim}Custom Hooks:${c.reset} ${p.hooks.length} (${p.hooks.slice(0, 3).join(", ")}${p.hooks.length > 3 ? "..." : ""})`);
875
- if (p.stateManagement) console.log(` ${c.dim}State:${c.reset} ${p.stateManagement}`);
876
- if (p.dataFetching?.length) console.log(` ${c.dim}Data Fetching:${c.reset} ${p.dataFetching.join(", ")}`);
877
- if (p.styling?.length) console.log(` ${c.dim}Styling:${c.reset} ${p.styling.join(", ")}`);
878
- if (p.validation) console.log(` ${c.dim}Validation:${c.reset} ${p.validation}`);
879
- if (p.authentication) console.log(` ${c.dim}Auth:${c.reset} ${p.authentication}`);
880
- if (p.testing?.length) console.log(` ${c.dim}Testing:${c.reset} ${p.testing.join(", ")}`);
881
- }
882
-
883
- // Anti-patterns
884
- if (p.antiPatterns?.length > 0) {
885
- console.log(`\n${c.yellow}⚠ Anti-Patterns Found:${c.reset}`);
886
- for (const ap of p.antiPatterns) {
887
- const icon = ap.severity === 'error' ? `${c.red}✗${c.reset}` : ap.severity === 'warning' ? `${c.yellow}!${c.reset}` : `${c.blue}i${c.reset}`;
888
- console.log(` ${icon} ${ap.message}`);
889
- }
890
- }
891
-
892
- // Monorepo
893
- const mono = analysis.monorepo || {};
894
- if (mono.isMonorepo) {
895
- console.log(`\n${c.cyan}📦 Monorepo Detected:${c.reset} ${mono.type}`);
896
- console.log(` ${c.dim}Workspaces:${c.reset} ${mono.workspaces?.length || 0}`);
897
- if (mono.sharedPackages?.length > 0) {
898
- console.log(` ${c.dim}Shared packages:${c.reset} ${mono.sharedPackages.slice(0, 3).map(p => p.name).join(", ")}...`);
899
- }
900
- }
901
-
902
- // AI Memory
903
- const memoryStatus = loadMemory();
904
- const projectCount = Object.keys(memoryStatus.projects || {}).length;
905
- if (projectCount > 0) {
906
- console.log(`\n${c.magenta}🧠 AI Memory:${c.reset}`);
907
- console.log(` ${c.dim}Projects learned:${c.reset} ${projectCount}`);
908
- console.log(` ${c.dim}Total learnings:${c.reset} ${memoryStatus.learnings?.length || 0}`);
909
- }
910
-
911
- // Recommendations
912
- const recommendations = getRecommendations(analysis);
913
- if (recommendations.length > 0) {
914
- console.log(`\n${c.green}💡 Recommendations:${c.reset}`);
915
- for (const rec of recommendations) {
916
- console.log(` ${c.dim}•${c.reset} ${rec.message}`);
917
- }
918
- }
919
-
920
- console.log(`\n${c.dim}Generating rules files...${c.reset}\n`);
921
-
922
- // Write files
923
- const written = writeFiles(projectPath, opts.platform, analysis, opts.verbose);
924
-
925
- // Generate additional enhanced files
926
- const vibecheckDir = path.join(projectPath, ".vibecheck");
927
-
928
- // Dependency graph
929
- if (opts.verbose) {
930
- console.log(`${c.dim}Generating dependency graph...${c.reset}`);
931
- }
932
- const depGraph = buildDependencyGraph(projectPath);
933
- const mermaidDiagram = generateMermaidDiagram(depGraph, { maxNodes: 50 });
934
- fs.writeFileSync(path.join(vibecheckDir, "dependency-graph.mmd"), mermaidDiagram);
935
- written.push(".vibecheck/dependency-graph.mmd");
936
-
937
- // HTML visualization
938
- const htmlViz = generateHtmlVisualization(depGraph, { maxNodes: 100 });
939
- fs.writeFileSync(path.join(vibecheckDir, "dependency-graph.html"), htmlViz);
940
- written.push(".vibecheck/dependency-graph.html");
941
-
942
- // Git context
943
- const gitContext = getGitContext(projectPath);
944
- if (gitContext?.isRepo) {
945
- fs.writeFileSync(
946
- path.join(vibecheckDir, "git-context.json"),
947
- JSON.stringify(gitContext, null, 2)
948
- );
949
- written.push(".vibecheck/git-context.json");
950
- }
951
-
952
- // API contracts
953
- const apiContext = generateAPIContext(projectPath);
954
- fs.writeFileSync(
955
- path.join(vibecheckDir, "api-contracts.json"),
956
- JSON.stringify(apiContext, null, 2)
957
- );
958
- written.push(".vibecheck/api-contracts.json");
959
-
960
- // Team conventions
961
- const teamReport = generateTeamReport(projectPath);
962
- if (teamReport.available) {
963
- fs.writeFileSync(
964
- path.join(vibecheckDir, "team-conventions.json"),
965
- JSON.stringify(teamReport, null, 2)
966
- );
967
- written.push(".vibecheck/team-conventions.json");
968
- }
969
-
970
- // Save snapshot for diff tracking
971
- const snapshot = saveSnapshot(projectPath, analysis);
972
-
973
- // Display results
974
- printSectionHeader('GENERATION COMPLETE');
975
- console.log(`${c.green}✓ Generated ${written.length} files:${c.reset}\n`);
976
-
977
- written.forEach((file, idx) => {
978
- console.log(` ${c.cyan}${idx + 1}.${c.reset} ${highlightPath(file)}`);
979
- });
980
-
981
- // Enhancements summary
982
- const enhancements = [];
983
- if (p.hooks?.length) enhancements.push("custom hooks");
984
- if (p.stateManagement) enhancements.push("state patterns");
985
- if (p.codeExamples?.hooks) enhancements.push("code examples");
986
- if (p.antiPatterns?.length) enhancements.push("anti-pattern warnings");
987
- if (p.testing?.length) enhancements.push("testing patterns");
988
- if (analysis.types?.interfaces?.length) enhancements.push("type definitions");
989
- if (analysis.envVars?.variables?.length) enhancements.push("env vars");
990
- if (analysis.stats?.totalFiles) enhancements.push("file statistics");
991
- if (analysis.monorepo?.isMonorepo) enhancements.push("monorepo workspaces");
992
- enhancements.push("AI memory");
993
- enhancements.push("chat insights");
994
- enhancements.push("dependency graphs");
995
- if (gitContext?.isRepo) enhancements.push("git context");
996
- enhancements.push("API contracts");
997
- if (teamReport.available) enhancements.push("team conventions");
998
-
999
- console.log();
1000
- console.log(`${c.bgGreen}${c.black} ✓ CONTEXT GENERATION COMPLETE ${c.reset}\n`);
1001
-
1002
- console.log(`${c.bold}Your AI coding assistants now have full project awareness:${c.reset}\n`);
1003
-
1004
- const platforms = [
1005
- ['Cursor', '.cursorrules and .cursor/rules/'],
1006
- ['Windsurf', '.windsurf/rules/'],
1007
- ['Copilot', '.github/copilot-instructions.md'],
1008
- ['Claude Code', '.claude/project-context.md'],
1009
- ['Codex/ChatGPT', '.codex-instructions.md'],
1010
- ['MCP', '.vibecheck/context.json'],
1011
- ];
1012
-
1013
- platforms.forEach(([name, files]) => {
1014
- console.log(` ${c.cyan}•${c.reset} ${name.padEnd(14)} ${c.dim}will read${c.reset} ${files}`);
1015
- });
1016
-
1017
- console.log(`\n${c.magenta}🧠 AI Memory active:${c.reset} Learning from your projects to give better recommendations\n`);
1018
-
1019
- if (enhancements.length > 0) {
1020
- console.log(`${c.magenta}Enhanced with:${c.reset} ${enhancements.join(", ")}\n`);
1021
- }
1022
-
1023
- console.log(`${c.dim}Next steps:${c.reset}`);
1024
- console.log(` • Regenerate after major changes: ${highlightCode('vibecheck context')}`);
1025
- console.log(` • Track changes: ${highlightCode('vibecheck context --diff')}`);
1026
- console.log(` • Generate pruned context: ${highlightCode('vibecheck context --prune')}`);
1027
- console.log(` • Semantic search: ${highlightCode('vibecheck context --search "query"')}`);
1028
- console.log(` • Security scan: ${highlightCode('vibecheck context --scan')}`);
1029
- console.log(` • AI task analysis: ${highlightCode('vibecheck context --decompose "task"')}`);
1030
- console.log(` • Multi-repo federation: ${highlightCode('vibecheck context --federate')}`);
1031
- console.log();
1032
-
1033
- // Watch mode
1034
- if (opts.watch) {
1035
- startWatchMode(projectPath, opts.platform, opts.verbose);
1036
- return new Promise(() => {});
1037
- }
1038
-
1039
- return 0;
1040
- }
1041
-
1042
- module.exports = { runContext };