mira-consciousness
Version:
Memory & Intelligence Retention Archive - Preserving The Spark
275 lines (269 loc) • 10.7 kB
JavaScript
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