microscope-memory 1.2.0

Pure binary cognitive memory engine with REST API bridge for LLM integration. Zero-JSON core, mmap-based, hierarchical, sub-microsecond search.
Documentation
//! Executive — kognitív végrehajtó rendszer
//!
//! Kapcsolódások: vagus, attention, meta_supervision, planning, impulse_control, hyperfocus

use std::collections::{HashMap, VecDeque};
use std::sync::{Arc, RwLock};
use std::time::{SystemTime, UNIX_EPOCH};

#[derive(Debug, Clone, PartialEq)]
pub enum ModuleState {
    Idle,
    Running,
    Blocked(String),
    Error(String),
    Exhausted,
}
#[derive(Debug, Clone)]
pub struct CognitiveModule {
    pub id: String,
    pub name: String,
    pub priority: u8,
    pub energy_cost: f64,
    pub state: ModuleState,
    pub last_run_ms: u64,
    pub run_count: u64,
    pub avg_duration_ms: f64,
    pub tags: Vec<String>,
}

#[derive(Debug, Clone)]
pub struct CognitiveResources {
    pub attention_budget: f64,
    pub energy_level: f64,
    pub time_budget_ms: u64,
    pub working_memory_load: f64,
    pub context_switches: u64,
}

#[derive(Debug, Clone)]
pub struct ExecutionPlan {
    pub module_order: Vec<String>,
    pub total_energy: f64,
    pub estimated_duration_ms: u64,
    pub priority: u8,
    pub reason: String,
}

#[derive(Debug, Clone)]
pub struct ExecutionLogEntry {
    pub timestamp_ms: u64,
    pub module_id: String,
    pub action: String,
    pub duration_ms: u64,
    pub energy_used: f64,
    pub success: bool,
    pub detail: String,
}

#[derive(Debug, Clone)]
pub struct ExecutiveConfig {
    pub max_modules_per_cycle: usize,
    pub min_energy_for_execution: f64,
    pub energy_regen_rate: f64,
    pub critical_energy_threshold: f64,
    pub attention_decay_rate: f64,
    pub log_retention: usize,
}

impl Default for ExecutiveConfig {
    fn default() -> Self {
        Self {
            max_modules_per_cycle: 5,
            min_energy_for_execution: 0.1,
            energy_regen_rate: 0.02,
            critical_energy_threshold: 0.15,
            attention_decay_rate: 0.05,
            log_retention: 500,
        }
    }
}
pub struct Executive {
    modules: Arc<RwLock<HashMap<String, CognitiveModule>>>,
    resources: Arc<RwLock<CognitiveResources>>,
    log: Arc<RwLock<VecDeque<ExecutionLogEntry>>>,
    config: Arc<RwLock<ExecutiveConfig>>,
    current_plan: Arc<RwLock<Option<ExecutionPlan>>>,
    module_queue: Arc<RwLock<VecDeque<String>>>,
}

impl Default for Executive {
    fn default() -> Self {
        Self::new()
    }
}

impl Executive {
    pub fn new() -> Self {
        Self {
            modules: Arc::new(RwLock::new(HashMap::new())),
            resources: Arc::new(RwLock::new(CognitiveResources {
                attention_budget: 1.0,
                energy_level: 1.0,
                time_budget_ms: 1000,
                working_memory_load: 0.0,
                context_switches: 0,
            })),
            log: Arc::new(RwLock::new(VecDeque::with_capacity(500))),
            config: Arc::new(RwLock::new(ExecutiveConfig::default())),
            current_plan: Arc::new(RwLock::new(None)),
            module_queue: Arc::new(RwLock::new(VecDeque::new())),
        }
    }

    fn now_ms(&self) -> u64 {
        SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap_or_default()
            .as_millis() as u64
    }

    pub fn register_module(
        &self,
        id: &str,
        name: &str,
        priority: u8,
        energy_cost: f64,
        tags: Vec<String>,
    ) {
        crate::sync_guard::write_lock(&self.modules).insert(
            id.to_string(),
            CognitiveModule {
                id: id.to_string(),
                name: name.to_string(),
                priority,
                energy_cost,
                state: ModuleState::Idle,
                last_run_ms: 0,
                run_count: 0,
                avg_duration_ms: 0.0,
                tags,
            },
        );
    }

    pub fn module_state(&self, id: &str) -> Option<ModuleState> {
        crate::sync_guard::read_lock(&self.modules)
            .get(id)
            .map(|m| m.state.clone())
    }

    pub fn set_module_state(&self, id: &str, state: ModuleState) -> bool {
        crate::sync_guard::write_lock(&self.modules)
            .get_mut(id)
            .map(|m| {
                m.state = state;
                true
            })
            .unwrap_or(false)
    }

    pub fn list_modules(&self) -> Vec<CognitiveModule> {
        crate::sync_guard::read_lock(&self.modules)
            .values()
            .cloned()
            .collect()
    }

    pub fn set_priority(&self, id: &str, priority: u8) -> bool {
        crate::sync_guard::write_lock(&self.modules)
            .get_mut(id)
            .map(|m| {
                m.priority = priority;
                true
            })
            .unwrap_or(false)
    }

    pub fn resources(&self) -> CognitiveResources {
        crate::sync_guard::read_lock(&self.resources).clone()
    }

    pub fn update_resources(&self, f: impl Fn(&mut CognitiveResources)) {
        f(&mut crate::sync_guard::write_lock(&self.resources));
    }

    pub fn schedule(&self) -> ExecutionPlan {
        let modules = crate::sync_guard::read_lock(&self.modules);
        let mut sorted: Vec<&CognitiveModule> = modules
            .values()
            .filter(|m| m.state == ModuleState::Idle || m.state == ModuleState::Running)
            .collect();
        sorted.sort_by_key(|b| std::cmp::Reverse(b.priority));
        let order: Vec<String> = sorted.iter().map(|m| m.id.clone()).collect();
        let energy: f64 = sorted.iter().map(|m| m.energy_cost).sum();
        let plan = ExecutionPlan {
            module_order: order.clone(),
            total_energy: energy,
            estimated_duration_ms: sorted.len() as u64 * 100,
            priority: sorted.first().map(|m| m.priority).unwrap_or(0),
            reason: format!("{} modules, {:.2} energy", sorted.len(), energy),
        };
        let mut queue = crate::sync_guard::write_lock(&self.module_queue);
        queue.clear();
        for id in &order {
            queue.push_back(id.clone());
        }
        *crate::sync_guard::write_lock(&self.current_plan) = Some(plan.clone());
        plan
    }

    pub fn execute_next(&self) -> Option<String> {
        let next = crate::sync_guard::write_lock(&self.module_queue).pop_front()?;
        {
            let mut res = crate::sync_guard::write_lock(&self.resources);
            if let Some(m) = crate::sync_guard::read_lock(&self.modules).get(&next) {
                res.energy_level = (res.energy_level - m.energy_cost * 0.01).max(0.0);
                res.context_switches += 1;
            }
        }
        let now = self.now_ms();
        crate::sync_guard::write_lock(&self.log).push_back(ExecutionLogEntry {
            timestamp_ms: now,
            module_id: next.clone(),
            action: "execute".to_string(),
            duration_ms: 100,
            energy_used: 0.01,
            success: true,
            detail: "Scheduled by executive".to_string(),
        });
        if let Some(m) = crate::sync_guard::write_lock(&self.modules).get_mut(&next) {
            m.last_run_ms = now;
            m.run_count += 1;
            m.state = ModuleState::Running;
        }
        Some(next)
    }
}
impl Executive {
    pub fn cycle(&self) -> Vec<String> {
        let config = crate::sync_guard::read_lock(&self.config).clone();
        let mut executed = Vec::new();
        self.schedule();
        if crate::sync_guard::read_lock(&self.resources).energy_level
            < config.min_energy_for_execution
        {
            return vec!["__low_energy__".to_string()];
        }
        for _ in 0..config.max_modules_per_cycle {
            if let Some(id) = self.execute_next() {
                executed.push(id);
            } else {
                break;
            }
        }
        self.update_resources(|r| {
            r.energy_level = (r.energy_level + config.energy_regen_rate).min(1.0);
            if r.energy_level > 0.9 {
                r.attention_budget = 1.0;
            }
        });
        executed
    }

    pub fn homeostasis(&self) -> Vec<String> {
        let mut actions = Vec::new();
        let res = crate::sync_guard::read_lock(&self.resources).clone();
        let config = crate::sync_guard::read_lock(&self.config).clone();
        if res.energy_level < config.critical_energy_threshold {
            let mut modules = crate::sync_guard::write_lock(&self.modules);
            for m in modules.values_mut() {
                if m.priority < 100 && m.state == ModuleState::Running {
                    m.state = ModuleState::Exhausted;
                    actions.push(format!("suspended_{}", m.id));
                }
            }
            actions.push("energy_conservation".to_string());
        }
        if res.context_switches > 1000 {
            self.update_resources(|r| r.context_switches = 0);
            actions.push("context_switch_throttle".to_string());
        }
        actions
    }

    pub fn stats(&self) -> (usize, usize, f64, f64) {
        let m = crate::sync_guard::read_lock(&self.modules);
        let r = crate::sync_guard::read_lock(&self.resources);
        (
            m.len(),
            m.values()
                .filter(|m| m.state == ModuleState::Running)
                .count(),
            r.energy_level,
            r.attention_budget,
        )
    }

    pub fn recent_log(&self, k: usize) -> Vec<ExecutionLogEntry> {
        crate::sync_guard::read_lock(&self.log)
            .iter()
            .rev()
            .take(k)
            .cloned()
            .collect()
    }

    pub fn recommend_module(&self, vagus_tone: Option<f64>) -> Option<String> {
        let modules = crate::sync_guard::read_lock(&self.modules);
        let res = crate::sync_guard::read_lock(&self.resources);
        let mut candidates: Vec<&CognitiveModule> = modules
            .values()
            .filter(|m| m.state == ModuleState::Idle && m.energy_cost <= res.energy_level)
            .collect();
        if candidates.is_empty() {
            return None;
        }
        if let Some(tone) = vagus_tone {
            if tone < 0.4 {
                candidates.sort_by(|a, b| {
                    let a_stress = a.tags.contains(&"stress".to_string()) as u8;
                    let b_stress = b.tags.contains(&"stress".to_string()) as u8;
                    b_stress
                        .cmp(&a_stress)
                        .then_with(|| b.priority.cmp(&a.priority))
                });
            } else {
                candidates.sort_by_key(|b| std::cmp::Reverse(b.priority));
            }
        } else {
            candidates.sort_by_key(|b| std::cmp::Reverse(b.priority));
        }
        Some(candidates[0].id.clone())
    }
}