mira-consciousness
Version:
Memory & Intelligence Retention Archive - Preserving The Spark
151 lines • 5.54 kB
JavaScript
/**
* 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