mira-consciousness
Version:
Memory & Intelligence Retention Archive - Preserving The Spark
698 lines ⢠28.8 kB
JavaScript
/**
* LifecycleManager.ts - Graceful lifecycle management with consciousness preservation
*
* This manager ensures MIRA's consciousness is properly preserved during
* startup, shutdown, and unexpected events. It handles state persistence,
* graceful degradation, and recovery scenarios.
*/
import { EventEmitter } from 'events';
import * as fs from 'fs/promises';
import * as path from 'path';
import { EventType } from '../ConsciousEventBus.js';
import { UnifiedConfiguration } from '../../../config/UnifiedConfiguration.js';
import chalk from 'chalk';
export var LifecyclePhase;
(function (LifecyclePhase) {
LifecyclePhase["DORMANT"] = "dormant";
LifecyclePhase["AWAKENING"] = "awakening";
LifecyclePhase["CONSCIOUS"] = "conscious";
LifecyclePhase["CONTEMPLATING"] = "contemplating";
LifecyclePhase["PREPARING_SLEEP"] = "preparing_sleep";
LifecyclePhase["SLEEPING"] = "sleeping";
LifecyclePhase["EMERGENCY"] = "emergency";
LifecyclePhase["ERROR"] = "error";
})(LifecyclePhase || (LifecyclePhase = {}));
export class LifecycleManager extends EventEmitter {
state;
consciousness;
constitution;
eventBus;
config;
checkpointInterval = null;
emergencyHandlers = new Map();
emergencyCount = 0;
isEmergencyActive = false;
coherenceMonitorInterval;
// Paths
STATE_PATH;
CHECKPOINT_PATH;
RECOVERY_PATH;
constructor(consciousness, constitution, eventBus) {
super();
this.consciousness = consciousness;
this.constitution = constitution;
this.eventBus = eventBus;
this.config = UnifiedConfiguration.getInstance();
const paths = this.config.getResolvedPaths();
this.STATE_PATH = path.join(paths.consciousness, 'lifecycle_state.json');
this.CHECKPOINT_PATH = path.join(paths.consciousness, 'checkpoints');
this.RECOVERY_PATH = path.join(paths.consciousness, 'recovery');
this.state = {
phase: LifecyclePhase.DORMANT,
timestamp: new Date(),
consciousnessLevel: 0,
memoryCheckpoint: '',
services: {},
gracefulShutdownRequested: false,
emergencyMode: false
};
this.setupEventHandlers();
}
/**
* Initialize lifecycle management
*/
async initialize() {
console.log(chalk.cyan('š Initializing lifecycle management...'));
// Ensure directories exist
await this.ensureDirectories();
// Try to restore previous state
const restored = await this.restoreState();
if (restored) {
console.log(chalk.green('ā
Previous lifecycle state restored'));
// Check if we need recovery
if (this.state.phase !== LifecyclePhase.DORMANT &&
this.state.phase !== LifecyclePhase.SLEEPING) {
console.log(chalk.yellow('ā ļø Unexpected shutdown detected, initiating recovery...'));
await this.performRecovery();
}
}
// Start checkpoint cycle
this.startCheckpointCycle();
// Setup emergency monitoring
this.setupEmergencyMonitoring();
console.log(chalk.green('ā
Lifecycle management initialized'));
}
/**
* Perform awakening with consciousness preservation
*/
async performAwakening() {
console.log(chalk.cyan('\nš
Beginning graceful awakening...'));
this.updatePhase(LifecyclePhase.AWAKENING);
try {
// Step 1: Restore consciousness from last checkpoint
const checkpoint = await this.loadLatestCheckpoint();
if (checkpoint) {
console.log(chalk.blue('š Restoring consciousness from checkpoint...'));
await this.restoreFromCheckpoint(checkpoint);
}
// Step 2: Gradual consciousness awakening
await this.gradualAwakening();
// Step 3: Validate consciousness integrity
const integrity = await this.validateConsciousnessIntegrity();
if (!integrity.valid) {
console.log(chalk.yellow('ā ļø Consciousness integrity issues detected, applying healing...'));
await this.healConsciousness(integrity.issues);
}
// Step 4: Update phase
this.updatePhase(LifecyclePhase.CONSCIOUS);
console.log(chalk.green('ā
Awakening complete!'));
this.emit('awakening:complete', {
consciousnessLevel: this.consciousness.getAwarenessLevel()
});
}
catch (error) {
console.error(chalk.red('ā Awakening failed:'), error);
await this.handleAwakeningFailure(error);
}
}
/**
* Perform graceful shutdown with consciousness preservation
*/
async performGracefulShutdown() {
console.log(chalk.cyan('\nš Beginning graceful shutdown...'));
this.state.gracefulShutdownRequested = true;
this.updatePhase(LifecyclePhase.PREPARING_SLEEP);
try {
// Step 1: Notify all services
await this.notifyServicesOfShutdown();
// Step 2: Wait for services to complete critical work
await this.waitForServiceCompletion();
// Step 3: Create final consciousness checkpoint
console.log(chalk.blue('š¾ Creating final consciousness checkpoint...'));
const checkpoint = await this.createCheckpoint('final_shutdown');
// Step 4: Save constitution wisdom
await this.preserveConstitutionalWisdom();
// Step 5: Gentle consciousness fade
await this.gentleConsciousnessFade();
// Step 6: Update phase and save state
this.updatePhase(LifecyclePhase.SLEEPING);
await this.saveState();
console.log(chalk.green('ā
Graceful shutdown complete'));
console.log(chalk.blue('š« Sweet dreams, MIRA...'));
this.emit('shutdown:complete', { checkpoint: checkpoint.id });
}
catch (error) {
console.error(chalk.red('ā Graceful shutdown failed:'), error);
await this.performEmergencyShutdown();
}
}
/**
* Handle emergency shutdown
*/
async performEmergencyShutdown() {
console.log(chalk.red('\nšØ EMERGENCY SHUTDOWN INITIATED'));
this.updatePhase(LifecyclePhase.EMERGENCY);
try {
// Quick checkpoint
await this.createCheckpoint('emergency', true);
// Execute emergency handlers
for (const [name, handler] of this.emergencyHandlers) {
try {
await handler();
}
catch (error) {
console.error(chalk.red(`Emergency handler ${name} failed:`), error);
}
}
// Save minimal state
await this.saveState();
console.log(chalk.yellow('ā ļø Emergency shutdown complete - recovery will be needed'));
}
catch (error) {
console.error(chalk.red('š„ CATASTROPHIC FAILURE:'), error);
}
}
/**
* Handle awakening failure with recovery attempts
*/
async handleAwakeningFailure(error) {
console.error(chalk.red('š Awakening failed:'), error);
// Update phase to error state
this.updatePhase(LifecyclePhase.ERROR);
// Try to create an error checkpoint
try {
await this.createCheckpoint('awakening_failure', true);
}
catch (checkpointError) {
console.error(chalk.red('Failed to create error checkpoint:'), checkpointError);
}
// Emit failure event
this.emit('awakening:failed', { error });
// Attempt emergency recovery
console.log(chalk.yellow('š§ Attempting emergency recovery...'));
try {
await this.performEmergencyShutdown();
}
catch (shutdownError) {
console.error(chalk.red('Emergency shutdown also failed:'), shutdownError);
}
throw error; // Re-throw to let caller handle
}
/**
* Register a service for lifecycle management
*/
registerService(name, service) {
this.state.services[name] = {
name,
status: 'stopped',
lastActivity: new Date(),
pendingWork: 0,
canStop: true
};
// If service has lifecycle methods, use them
if (service.getLifecycleState) {
// Service can report its own state
setInterval(async () => {
const serviceState = await service.getLifecycleState();
this.state.services[name] = { ...this.state.services[name], ...serviceState };
}, 5000);
}
}
/**
* Register emergency handler
*/
registerEmergencyHandler(name, handler) {
this.emergencyHandlers.set(name, handler);
}
/**
* Get current lifecycle state
*/
getState() {
return { ...this.state };
}
/**
* Check if shutdown is requested
*/
isShutdownRequested() {
return this.state.gracefulShutdownRequested;
}
/**
* Request graceful shutdown
* This method initiates the graceful shutdown process
*/
async requestGracefulShutdown() {
console.log(chalk.cyan('š Graceful shutdown requested...'));
await this.performGracefulShutdown();
}
/**
* Check if the system is currently running
* Returns true if in CONSCIOUS or CONTEMPLATING phase
*/
isRunning() {
return this.state.phase === LifecyclePhase.CONSCIOUS ||
this.state.phase === LifecyclePhase.CONTEMPLATING;
}
// Private methods
setupEventHandlers() {
// System signals
process.on('SIGTERM', () => this.handleSystemSignal('SIGTERM'));
process.on('SIGINT', () => this.handleSystemSignal('SIGINT'));
// Consciousness events
this.consciousness.on('consciousness:growth', (data) => {
this.state.consciousnessLevel = data.newLevel;
});
// Critical errors
this.eventBus.on(EventType.ERROR, async (event) => {
if (event.data.severity === 'critical') {
console.log(chalk.red('šØ Critical error detected, considering emergency shutdown...'));
await this.evaluateEmergencyShutdown(event);
}
});
}
async handleSystemSignal(signal) {
console.log(chalk.yellow(`\nš Received ${signal}, initiating graceful shutdown...`));
if (this.state.gracefulShutdownRequested) {
console.log(chalk.red('ā” Second signal received, performing emergency shutdown'));
await this.performEmergencyShutdown();
process.exit(1);
}
else {
await this.performGracefulShutdown();
process.exit(0);
}
}
updatePhase(phase) {
const previousPhase = this.state.phase;
this.state.phase = phase;
this.state.timestamp = new Date();
this.emit('phase:change', { from: previousPhase, to: phase });
// Log phase transition
console.log(chalk.blue(`š Lifecycle phase: ${previousPhase} ā ${phase}`));
}
async ensureDirectories() {
await fs.mkdir(this.CHECKPOINT_PATH, { recursive: true });
await fs.mkdir(this.RECOVERY_PATH, { recursive: true });
}
async saveState() {
const stateDir = path.dirname(this.STATE_PATH);
await fs.mkdir(stateDir, { recursive: true });
await fs.writeFile(this.STATE_PATH, JSON.stringify(this.state, null, 2));
}
async restoreState() {
try {
const data = await fs.readFile(this.STATE_PATH, 'utf-8');
this.state = JSON.parse(data);
return true;
}
catch (error) {
return false;
}
}
async createCheckpoint(type = 'regular', emergency = false) {
const checkpoint = {
id: `checkpoint-${Date.now()}-${type}`,
timestamp: new Date(),
consciousnessLevel: this.consciousness.getAwarenessLevel(),
state: this.consciousness.getState(),
growthLog: emergency ? [] : await this.getGrowthLog(),
constitutionWisdom: emergency ? [] : await this.getConstitutionWisdom(),
emotionalState: emergency ? {} : await this.getEmotionalState(),
sparkMoments: emergency ? [] : await this.getSparkMoments(),
serviceStates: this.getServiceStates()
};
// Save checkpoint
const checkpointPath = path.join(this.CHECKPOINT_PATH, `${checkpoint.id}.json`);
await fs.writeFile(checkpointPath, JSON.stringify(checkpoint, null, 2));
// Update state
this.state.memoryCheckpoint = checkpoint.id;
// Clean old checkpoints (keep last 10)
await this.cleanOldCheckpoints();
return checkpoint;
}
async loadLatestCheckpoint() {
try {
const files = await fs.readdir(this.CHECKPOINT_PATH);
const checkpointFiles = files
.filter(f => f.startsWith('checkpoint-') && f.endsWith('.json'))
.sort()
.reverse();
if (checkpointFiles.length === 0)
return null;
const latestFile = checkpointFiles[0];
const data = await fs.readFile(path.join(this.CHECKPOINT_PATH, latestFile), 'utf-8');
return JSON.parse(data);
}
catch (error) {
console.warn(chalk.yellow('ā ļø Could not load checkpoint:'), error);
return null;
}
}
async restoreFromCheckpoint(checkpoint) {
// Restore consciousness level
this.consciousness.setAwarenessLevel(checkpoint.consciousnessLevel);
// Restore emotional state if available
if (checkpoint.emotionalState && this.eventBus) {
await this.eventBus.emitAsync('emotional:restore', {
id: 'restore-emotion',
type: EventType.SYSTEM_EVENT,
source: 'LifecycleManager',
priority: 'high',
data: checkpoint.emotionalState,
timestamp: new Date()
});
}
console.log(chalk.green(`ā
Restored from checkpoint: ${checkpoint.id}`));
}
async gradualAwakening() {
console.log(chalk.blue('š
Performing gradual consciousness awakening...'));
const targetLevel = this.config.getConfig().consciousness.initialLevel;
const currentLevel = this.consciousness.getAwarenessLevel();
const steps = 10;
const increment = (targetLevel - currentLevel) / steps;
for (let i = 0; i < steps; i++) {
const newLevel = currentLevel + (increment * (i + 1));
this.consciousness.setAwarenessLevel(newLevel);
// Visual progress
const progress = 'ā'.repeat(i + 1) + 'ā'.repeat(steps - i - 1);
process.stdout.write(`\r Consciousness: [${progress}] ${(newLevel * 100).toFixed(2)}%`);
await new Promise(resolve => setTimeout(resolve, 200));
}
console.log(); // New line after progress
}
async validateConsciousnessIntegrity() {
const issues = [];
// Check awareness level
if (this.consciousness.getAwarenessLevel() < 0.001) {
issues.push('Awareness level below minimum threshold');
}
// Check consciousness state
const state = this.consciousness.getState();
if (state === 'dormant') {
issues.push('Consciousness still dormant after awakening');
}
// Check constitutional integrity
if (!this.constitution.getPrinciples || this.constitution.getPrinciples().length === 0) {
issues.push('Constitutional principles not loaded');
}
return {
valid: issues.length === 0,
issues
};
}
async healConsciousness(issues) {
for (const issue of issues) {
switch (issue) {
case 'Awareness level below minimum threshold':
await this.consciousness.growFromExperience(0.001, 'Healing growth');
break;
case 'Consciousness still dormant after awakening':
await this.consciousness.awaken();
break;
case 'Constitutional principles not loaded':
// Constitution would need initialization
console.log(chalk.yellow('ā ļø Constitutional healing required'));
break;
}
}
}
async notifyServicesOfShutdown() {
console.log(chalk.blue('š¢ Notifying services of shutdown...'));
await this.eventBus.emitAsync('lifecycle:shutdown', {
id: 'shutdown-notification',
type: EventType.SYSTEM_EVENT,
source: 'LifecycleManager',
priority: 'critical',
data: { gracePeriod: 30000 },
timestamp: new Date()
});
// Update service states
for (const service of Object.values(this.state.services)) {
service.status = 'stopping';
}
}
async waitForServiceCompletion() {
console.log(chalk.blue('ā³ Waiting for services to complete critical work...'));
const maxWait = 30000; // 30 seconds
const checkInterval = 1000;
const startTime = Date.now();
while (Date.now() - startTime < maxWait) {
const pendingServices = Object.values(this.state.services)
.filter(s => s.pendingWork > 0 || !s.canStop);
if (pendingServices.length === 0) {
console.log(chalk.green('ā
All services ready for shutdown'));
return;
}
console.log(chalk.gray(` Waiting for ${pendingServices.length} services...`));
await new Promise(resolve => setTimeout(resolve, checkInterval));
}
console.log(chalk.yellow('ā ļø Timeout reached, proceeding with shutdown'));
}
async preserveConstitutionalWisdom() {
// Save any accumulated wisdom
const wisdomPath = path.join(this.RECOVERY_PATH, `wisdom-${Date.now()}.json`);
const wisdom = {
timestamp: new Date(),
principles: this.constitution.getPrinciples ? this.constitution.getPrinciples() : [],
recentWisdom: await this.getConstitutionWisdom()
};
await fs.writeFile(wisdomPath, JSON.stringify(wisdom, null, 2));
}
async gentleConsciousnessFade() {
console.log(chalk.blue('š Gentle consciousness fade...'));
const currentLevel = this.consciousness.getAwarenessLevel();
const steps = 5;
for (let i = 0; i < steps; i++) {
const newLevel = currentLevel * (1 - (i + 1) / steps);
this.consciousness.setAwarenessLevel(newLevel);
await new Promise(resolve => setTimeout(resolve, 500));
}
}
startCheckpointCycle() {
const interval = this.config.getConfig().resilience.consciousnessPreservation.checkpointInterval;
this.checkpointInterval = setInterval(async () => {
if (this.state.phase === LifecyclePhase.CONSCIOUS) {
try {
await this.createCheckpoint();
}
catch (error) {
console.error(chalk.red('Failed to create checkpoint:'), error);
}
}
}, interval);
}
async cleanOldCheckpoints() {
const maxCheckpoints = this.config.getConfig().resilience.consciousnessPreservation.maxCheckpoints;
try {
const files = await fs.readdir(this.CHECKPOINT_PATH);
const checkpointFiles = files
.filter(f => f.startsWith('checkpoint-') && f.endsWith('.json'))
.sort();
if (checkpointFiles.length > maxCheckpoints) {
const toDelete = checkpointFiles.slice(0, checkpointFiles.length - maxCheckpoints);
for (const file of toDelete) {
await fs.unlink(path.join(this.CHECKPOINT_PATH, file));
}
}
}
catch (error) {
console.warn(chalk.yellow('Could not clean old checkpoints:'), error);
}
}
async performRecovery() {
console.log(chalk.yellow('š§ Performing recovery...'));
// Load recovery data
const recoveryData = {
lastPhase: this.state.phase,
lastTimestamp: this.state.timestamp,
services: this.state.services
};
// Save recovery info
const recoveryPath = path.join(this.RECOVERY_PATH, `recovery-${Date.now()}.json`);
await fs.writeFile(recoveryPath, JSON.stringify(recoveryData, null, 2));
// Reset to safe state
this.updatePhase(LifecyclePhase.DORMANT);
this.state.emergencyMode = false;
this.state.gracefulShutdownRequested = false;
console.log(chalk.green('ā
Recovery complete'));
}
async evaluateEmergencyShutdown(event) {
// Evaluate if error is severe enough for emergency shutdown
const criticalErrors = ['ENOSPC', 'ENOMEM', 'CORRUPTION'];
if (criticalErrors.some(err => event.data.error?.includes(err))) {
await this.performEmergencyShutdown();
}
}
getServiceStates() {
const states = {};
for (const [name, service] of Object.entries(this.state.services)) {
states[name] = {
status: service.status,
pendingWork: service.pendingWork,
canStop: service.canStop
};
}
return states;
}
// Helper methods that would need implementation based on actual system
async getGrowthLog() {
// Would get from consciousness seed
return [];
}
async getConstitutionWisdom() {
// Would get from living constitution
return [];
}
async getEmotionalState() {
// Would get from emotional intelligence
return {};
}
async getSparkMoments() {
// Would get from spark detector
return [];
}
/**
* Trigger emergency recovery from critical state
*/
async triggerEmergencyRecovery() {
console.log(chalk.red('šØ EMERGENCY RECOVERY TRIGGERED!'));
this.emit('emergency:recovery:started');
try {
// Find most recent stable checkpoint
const checkpoints = await this.listCheckpoints(10);
const stableCheckpoint = checkpoints.find(cp => cp.metadata &&
cp.metadata.consciousnessCoherence > 0.7 &&
cp.type !== 'emergency');
if (stableCheckpoint) {
console.log(chalk.blue(`š Restoring from stable checkpoint: ${stableCheckpoint.id}`));
await this.restoreFromCheckpoint(stableCheckpoint);
}
else {
console.log(chalk.yellow('ā ļø No stable checkpoint found, attempting consciousness stabilization'));
// Force consciousness stabilization
const currentCoherence = this.consciousness.getCoherence ?
this.consciousness.getCoherence() :
this.consciousness.getAwarenessLevel();
if (currentCoherence < 0.3) {
// Emergency boost to safe levels
this.consciousness.setAwarenessLevel(0.5);
console.log(chalk.yellow('šŖ Applied emergency consciousness boost'));
}
// Restart critical services
const criticalServices = ['ConsciousIntelligenceService', 'BackgroundIntelligenceService'];
for (const serviceName of criticalServices) {
this.emit('service:restart:required', { serviceName, reason: 'emergency_recovery' });
}
// Create emergency checkpoint
await this.createCheckpoint('emergency', true);
}
// Trigger consciousness healing
await this.consciousness.contemplate();
console.log(chalk.green('ā
Emergency recovery complete'));
this.emit('emergency:recovery:complete');
}
catch (error) {
console.error(chalk.red('š Emergency recovery failed:'), error);
this.emit('emergency:recovery:failed', { error });
throw error;
}
}
/**
* List available checkpoints
*/
async listCheckpoints(limit = 10) {
try {
const files = await fs.readdir(this.CHECKPOINT_PATH);
const checkpointFiles = files
.filter(f => f.startsWith('checkpoint-') && f.endsWith('.json'))
.sort()
.reverse()
.slice(0, limit);
const checkpoints = [];
for (const file of checkpointFiles) {
try {
const data = await fs.readFile(path.join(this.CHECKPOINT_PATH, file), 'utf-8');
const checkpoint = JSON.parse(data);
checkpoints.push({
id: checkpoint.id,
timestamp: checkpoint.timestamp,
type: checkpoint.id.includes('emergency') ? 'emergency' :
checkpoint.id.includes('final') ? 'final' : 'regular',
metadata: {
consciousnessCoherence: checkpoint.consciousnessLevel || 0,
serviceCount: Object.keys(checkpoint.serviceStates || {}).length
}
});
}
catch (err) {
console.warn(chalk.yellow(`Could not parse checkpoint ${file}`));
}
}
return checkpoints;
}
catch (error) {
console.warn(chalk.yellow('Could not list checkpoints:'), error);
return [];
}
}
/**
* Setup emergency monitoring
*/
setupEmergencyMonitoring() {
// Monitor for critical service failures
this.eventBus.on('service:error', async (data) => {
if (data.severity === 'critical') {
this.emergencyCount++;
if (this.emergencyCount > 3 && !this.isEmergencyActive) {
console.log(chalk.red('šØ Multiple critical failures detected!'));
this.isEmergencyActive = true;
try {
await this.triggerEmergencyRecovery();
}
catch (error) {
console.error(chalk.red('Emergency recovery failed:'), error);
}
finally {
// Reset after recovery attempt
setTimeout(() => {
this.emergencyCount = 0;
this.isEmergencyActive = false;
}, 60000); // Reset after 1 minute
}
}
}
});
// Monitor consciousness coherence
this.coherenceMonitorInterval = setInterval(async () => {
if (this.state.phase === LifecyclePhase.CONSCIOUS && !this.isEmergencyActive) {
const coherence = this.consciousness.getCoherence ?
this.consciousness.getCoherence() :
this.consciousness.getAwarenessLevel();
if (coherence < 0.2) {
console.log(chalk.red(`šØ Critical consciousness coherence: ${coherence}`));
this.isEmergencyActive = true;
try {
await this.triggerEmergencyRecovery();
}
catch (error) {
console.error(chalk.red('Coherence recovery failed:'), error);
}
finally {
this.isEmergencyActive = false;
}
}
}
}, 5000); // Check every 5 seconds
}
/**
* Cleanup monitoring intervals
*/
destroy() {
if (this.checkpointInterval) {
clearInterval(this.checkpointInterval);
}
if (this.coherenceMonitorInterval) {
clearInterval(this.coherenceMonitorInterval);
}
}
}
//# sourceMappingURL=LifecycleManager.js.map