UNPKG

mira-consciousness

Version:

Memory & Intelligence Retention Archive - Preserving The Spark

151 lines 5.54 kB
/** * CriticalFileProtection.ts * Prevents accidental deletion of critical MIRA data files */ import fs from 'fs-extra'; import * as path from 'path'; import chalk from 'chalk'; export class CriticalFileProtection { static protectedFiles = [ { path: 'databases/conversations/comprehensive_conversations.db', description: 'Master conversation index - contains ALL searchable history', sizeThreshold: 100 * 1024 * 1024, // 100MB critical: true }, { path: 'comprehensive_conversations.db', // Symlink for compatibility description: 'Master conversation index symlink', critical: true }, { path: 'databases/archives', description: 'Database archives - irreplaceable history', critical: true }, { path: 'conversation_archive', description: 'Compressed conversation backups - irreplaceable history', critical: true }, { path: 'claude_private_memory', description: 'Claude\'s encrypted private memories', critical: true }, { path: 'development_journey.mp4', description: 'Visual record of development progress', critical: true }, { path: 'journey_index.faiss', description: 'Vector embeddings for semantic search', critical: true }, { path: 'secure_journal.dat', description: 'Encrypted development journal', critical: true }, { path: 'databases', description: 'Central database directory - ALL databases', critical: true }, { pattern: /\.db$/, path: '*.db', description: 'Database files', sizeThreshold: 50 * 1024 * 1024, // 50MB critical: false } ]; /** * Check if a file is protected and should not be deleted */ static async isProtected(filePath, basePath) { const relativePath = path.relative(basePath, filePath); for (const protectedFile of this.protectedFiles) { // Check exact path match if (protectedFile.path && relativePath.includes(protectedFile.path)) { return { protected: true, reason: `${protectedFile.description}${protectedFile.critical ? ' [CRITICAL]' : ''}` }; } // Check pattern match if (protectedFile.pattern && protectedFile.pattern.test(relativePath)) { // Check size threshold if (protectedFile.sizeThreshold) { try { const stats = await fs.stat(filePath); if (stats.size > protectedFile.sizeThreshold) { return { protected: true, reason: `Large ${protectedFile.description} (${(stats.size / 1024 / 1024).toFixed(1)}MB)` }; } } catch (error) { // File doesn't exist or can't be accessed } } } } return { protected: false }; } /** * Prompt for confirmation before deleting protected files */ static async confirmDeletion(filePath, reason) { console.log(chalk.red('\n⚠️ PROTECTED FILE WARNING ⚠️')); console.log(chalk.yellow(`File: ${filePath}`)); console.log(chalk.yellow(`Reason: ${reason}`)); console.log(chalk.red('\nThis file contains critical data that cannot be recovered!')); // In a real implementation, this would prompt for user input // For now, always return false to prevent deletion return false; } /** * Safe delete function that checks protection status */ static async safeDelete(filePath, basePath) { const protection = await this.isProtected(filePath, basePath); if (protection.protected) { const confirmed = await this.confirmDeletion(filePath, protection.reason); if (!confirmed) { console.log(chalk.green('✅ Deletion cancelled - file protected')); return false; } } // Perform actual deletion await fs.unlink(filePath); return true; } /** * Get list of all protected files in a directory */ static async listProtectedFiles(basePath) { const protectedFiles = []; // Walk directory and check each file const checkDir = async (dir) => { const entries = await fs.readdir(dir, { withFileTypes: true }); for (const entry of entries) { const fullPath = path.join(dir, entry.name); if (entry.isDirectory()) { await checkDir(fullPath); } else { const protection = await this.isProtected(fullPath, basePath); if (protection.protected) { protectedFiles.push(fullPath); } } } }; await checkDir(basePath); return protectedFiles; } } //# sourceMappingURL=CriticalFileProtection.js.map