UNPKG

mira-consciousness

Version:

Memory & Intelligence Retention Archive - Preserving The Spark

275 lines (269 loc) 10.7 kB
import * as path from 'path'; import fs from 'fs-extra'; import chalk from 'chalk'; import ora from 'ora'; import { ProjectDetector } from './ProjectDetector.js'; import { MetricsCollector } from './MetricsCollector.js'; import { ReportGenerator } from './ReportGenerator.js'; import { HookManager } from './HookManager.js'; import { ProjectRootFinder } from './ProjectRootFinder.js'; import { CodeQualityAnalyzer } from '../analyzers/CodeQualityAnalyzer.js'; import { SecurityAnalyzer } from '../analyzers/SecurityAnalyzer.js'; import { PerformanceAnalyzer } from '../analyzers/PerformanceAnalyzer.js'; import { DocumentationAnalyzer } from '../analyzers/DocumentationAnalyzer.js'; import { DependencyAnalyzer } from '../analyzers/DependencyAnalyzer.js'; export class MIRASystem { projectRoot; memoryDir; config; projectDetector; metricsCollector; reportGenerator; hookManager; // Analyzers codeQualityAnalyzer; securityAnalyzer; performanceAnalyzer; documentationAnalyzer; dependencyAnalyzer; constructor(config) { this.config = config; this.projectRoot = ProjectRootFinder.findProjectRoot(config.projectRoot); // Resolve memory directory using centralized resolver this.memoryDir = config.memoryDir || this.resolveMemoryDir(); // Initialize components this.projectDetector = new ProjectDetector(this.projectRoot); this.metricsCollector = new MetricsCollector(this.projectRoot); this.reportGenerator = new ReportGenerator(this.projectRoot); this.hookManager = new HookManager(this.projectRoot); // Initialize analyzers this.codeQualityAnalyzer = new CodeQualityAnalyzer(this.projectRoot); this.securityAnalyzer = new SecurityAnalyzer(this.projectRoot); this.performanceAnalyzer = new PerformanceAnalyzer(this.projectRoot); this.documentationAnalyzer = new DocumentationAnalyzer(this.projectRoot); this.dependencyAnalyzer = new DependencyAnalyzer(this.projectRoot); } /** * Resolve MIRA memory directory using centralized resolver */ resolveMemoryDir() { try { // Synchronous resolution for now - in the future we could make this async // For now, we'll use a simple fallback that matches our resolver logic const envDir = process.env.MIRA_MEMORY_DIR; if (envDir) return envDir; // Use project root + .mira as fallback return path.join(this.projectRoot, '.mira'); } catch (error) { // Final fallback return path.join(this.projectRoot, '.mira'); } } /** * Get the resolved MIRA memory directory */ getMemoryDir() { return this.memoryDir; } /** * Quick health check - optimized for speed (<5 seconds) */ async quickHealthCheck() { const startTime = Date.now(); const spinner = ora('Running quick health check...').start(); try { // Phase 0: Intelligent hook management (non-blocking) this.hookManager.intelligentHookManagement().catch(() => { // Fail silently - don't interrupt health check }); // Phase 1: Quick health check spinner.text = 'Detecting project type...'; const projectInfo = await this.projectDetector.detectProject(); spinner.text = 'Collecting basic metrics...'; const metrics = await this.metricsCollector.collectQuickMetrics(); spinner.text = 'Running quick quality scan...'; const codeQuality = await this.codeQualityAnalyzer.quickScan(); spinner.text = 'Checking critical security issues...'; const security = await this.securityAnalyzer.quickScan(); const executionTime = (Date.now() - startTime) / 1000; spinner.succeed(chalk.green(`Quick health check completed in ${executionTime.toFixed(2)}s`)); // Display summary this.displayQuickSummary({ projectInfo, metrics, codeQuality, security, executionTime }); return { projectInfo, metrics, codeQuality, security, performance: null, documentation: null, dependencies: null, executionTime }; } catch (error) { spinner.fail(chalk.red('Quick health check failed')); throw error; } } /** * Comprehensive analysis - full system scan */ async comprehensiveAnalysis() { const startTime = Date.now(); const spinner = ora('Running comprehensive analysis...').start(); try { // Phase 1: Project detection spinner.text = 'Detecting project structure...'; const projectInfo = await this.projectDetector.detectProject(); // Phase 2: Metrics collection spinner.text = 'Collecting comprehensive metrics...'; const metrics = await this.metricsCollector.collectFullMetrics(); // Phase 3: Code quality analysis spinner.text = 'Analyzing code quality...'; const codeQuality = await this.codeQualityAnalyzer.fullAnalysis(); // Phase 4: Security analysis spinner.text = 'Performing security scan...'; const security = await this.securityAnalyzer.fullAnalysis(); // Phase 5: Performance analysis spinner.text = 'Analyzing performance patterns...'; const performance = await this.performanceAnalyzer.analyze(); // Phase 6: Documentation analysis spinner.text = 'Checking documentation coverage...'; const documentation = await this.documentationAnalyzer.analyze(); // Phase 7: Dependency analysis spinner.text = 'Analyzing dependencies...'; const dependencies = await this.dependencyAnalyzer.analyze(); const executionTime = (Date.now() - startTime) / 1000; spinner.succeed(chalk.green(`Comprehensive analysis completed in ${executionTime.toFixed(2)}s`)); const result = { projectInfo, metrics, codeQuality, security, performance, documentation, dependencies, executionTime }; // Generate report await this.reportGenerator.generateReport(result); return result; } catch (error) { spinner.fail(chalk.red('Comprehensive analysis failed')); throw error; } } /** * Initialize MIRA in a project */ async initialize(force = false) { const spinner = ora('Initializing MIRA...').start(); try { const miraDir = path.join(this.projectRoot, '.mira'); if (await fs.pathExists(miraDir) && !force) { spinner.fail(chalk.yellow('MIRA already initialized. Use --force to reinitialize.')); return; } // Create .mira directory await fs.ensureDir(miraDir); // Create default configuration const defaultConfig = { version: '1.0.0', projectName: path.basename(this.projectRoot), initialized: new Date().toISOString(), settings: { quickScanTimeout: 5000, enableMemory: true, enableAI: false } }; await fs.writeJson(path.join(miraDir, 'config.json'), defaultConfig, { spaces: 2 }); // Create CLAUDE.md template await this.createClaudeTemplate(); spinner.succeed(chalk.green('MIRA initialized successfully')); } catch (error) { spinner.fail(chalk.red('Failed to initialize MIRA')); throw error; } } /** * Create CLAUDE.md template */ async createClaudeTemplate() { const claudePath = path.join(this.projectRoot, 'CLAUDE.md'); if (await fs.pathExists(claudePath)) { console.log(chalk.yellow('CLAUDE.md already exists, skipping...')); return; } const template = `# CLAUDE.md - MIRA Project Context ## Project Overview [Brief description of your project] ## Key Architecture Decisions - [Decision 1] - [Decision 2] ## Development Guidelines - [Guideline 1] - [Guideline 2] ## Current Focus - [Current task or feature] ## Technical Debt - [Known issues or improvements needed] --- Generated by MIRA v1.4.0 on ${new Date().toISOString()} `; await fs.writeFile(claudePath, template); } /** * Hook management methods */ async installHooks(force = false) { return this.hookManager.installHooks(force); } async disableHooks() { return this.hookManager.disableHooks(); } async enableHooks() { return this.hookManager.enableHooks(); } async getHookStatus() { return this.hookManager.getHookStatus(); } /** * Display quick summary of health check */ displayQuickSummary(result) { console.log('\n' + chalk.bold('📊 Quick Health Summary')); console.log('─'.repeat(50)); if (result.projectInfo) { console.log(chalk.cyan('Project:'), result.projectInfo.name); console.log(chalk.cyan('Type:'), result.projectInfo.type); console.log(chalk.cyan('Tech Stack:'), result.projectInfo.techStack.join(', ')); } if (result.metrics) { console.log(chalk.cyan('Files:'), result.metrics.fileCount); console.log(chalk.cyan('Lines of Code:'), result.metrics.totalLines); } if (result.codeQuality) { const qualityColor = result.codeQuality.score >= 80 ? 'green' : result.codeQuality.score >= 60 ? 'yellow' : 'red'; console.log(chalk.cyan('Code Quality Score:'), chalk[qualityColor](`${result.codeQuality.score}/100`)); } if (result.security) { const securityColor = result.security.issues === 0 ? 'green' : result.security.issues <= 5 ? 'yellow' : 'red'; console.log(chalk.cyan('Security Issues:'), chalk[securityColor](result.security.issues)); } console.log('─'.repeat(50)); } } //# sourceMappingURL=MIRASystem.js.map