Skip to main content

microscope_memory/
executive.rs

1//! Executive — kognitív végrehajtó rendszer
2//!
3//! Kapcsolódások: vagus, attention, meta_supervision, planning, impulse_control, hyperfocus
4
5use std::collections::{HashMap, VecDeque};
6use std::sync::{Arc, RwLock};
7use std::time::{SystemTime, UNIX_EPOCH};
8
9#[derive(Debug, Clone, PartialEq)]
10pub enum ModuleState {
11    Idle,
12    Running,
13    Blocked(String),
14    Error(String),
15    Exhausted,
16}
17#[derive(Debug, Clone)]
18pub struct CognitiveModule {
19    pub id: String,
20    pub name: String,
21    pub priority: u8,
22    pub energy_cost: f64,
23    pub state: ModuleState,
24    pub last_run_ms: u64,
25    pub run_count: u64,
26    pub avg_duration_ms: f64,
27    pub tags: Vec<String>,
28}
29
30#[derive(Debug, Clone)]
31pub struct CognitiveResources {
32    pub attention_budget: f64,
33    pub energy_level: f64,
34    pub time_budget_ms: u64,
35    pub working_memory_load: f64,
36    pub context_switches: u64,
37}
38
39#[derive(Debug, Clone)]
40pub struct ExecutionPlan {
41    pub module_order: Vec<String>,
42    pub total_energy: f64,
43    pub estimated_duration_ms: u64,
44    pub priority: u8,
45    pub reason: String,
46}
47
48#[derive(Debug, Clone)]
49pub struct ExecutionLogEntry {
50    pub timestamp_ms: u64,
51    pub module_id: String,
52    pub action: String,
53    pub duration_ms: u64,
54    pub energy_used: f64,
55    pub success: bool,
56    pub detail: String,
57}
58
59#[derive(Debug, Clone)]
60pub struct ExecutiveConfig {
61    pub max_modules_per_cycle: usize,
62    pub min_energy_for_execution: f64,
63    pub energy_regen_rate: f64,
64    pub critical_energy_threshold: f64,
65    pub attention_decay_rate: f64,
66    pub log_retention: usize,
67}
68
69impl Default for ExecutiveConfig {
70    fn default() -> Self {
71        Self {
72            max_modules_per_cycle: 5,
73            min_energy_for_execution: 0.1,
74            energy_regen_rate: 0.02,
75            critical_energy_threshold: 0.15,
76            attention_decay_rate: 0.05,
77            log_retention: 500,
78        }
79    }
80}
81pub struct Executive {
82    modules: Arc<RwLock<HashMap<String, CognitiveModule>>>,
83    resources: Arc<RwLock<CognitiveResources>>,
84    log: Arc<RwLock<VecDeque<ExecutionLogEntry>>>,
85    config: Arc<RwLock<ExecutiveConfig>>,
86    current_plan: Arc<RwLock<Option<ExecutionPlan>>>,
87    module_queue: Arc<RwLock<VecDeque<String>>>,
88}
89
90impl Default for Executive {
91    fn default() -> Self {
92        Self::new()
93    }
94}
95
96impl Executive {
97    pub fn new() -> Self {
98        Self {
99            modules: Arc::new(RwLock::new(HashMap::new())),
100            resources: Arc::new(RwLock::new(CognitiveResources {
101                attention_budget: 1.0,
102                energy_level: 1.0,
103                time_budget_ms: 1000,
104                working_memory_load: 0.0,
105                context_switches: 0,
106            })),
107            log: Arc::new(RwLock::new(VecDeque::with_capacity(500))),
108            config: Arc::new(RwLock::new(ExecutiveConfig::default())),
109            current_plan: Arc::new(RwLock::new(None)),
110            module_queue: Arc::new(RwLock::new(VecDeque::new())),
111        }
112    }
113
114    fn now_ms(&self) -> u64 {
115        SystemTime::now()
116            .duration_since(UNIX_EPOCH)
117            .unwrap_or_default()
118            .as_millis() as u64
119    }
120
121    pub fn register_module(
122        &self,
123        id: &str,
124        name: &str,
125        priority: u8,
126        energy_cost: f64,
127        tags: Vec<String>,
128    ) {
129        crate::sync_guard::write_lock(&self.modules).insert(
130            id.to_string(),
131            CognitiveModule {
132                id: id.to_string(),
133                name: name.to_string(),
134                priority,
135                energy_cost,
136                state: ModuleState::Idle,
137                last_run_ms: 0,
138                run_count: 0,
139                avg_duration_ms: 0.0,
140                tags,
141            },
142        );
143    }
144
145    pub fn module_state(&self, id: &str) -> Option<ModuleState> {
146        crate::sync_guard::read_lock(&self.modules)
147            .get(id)
148            .map(|m| m.state.clone())
149    }
150
151    pub fn set_module_state(&self, id: &str, state: ModuleState) -> bool {
152        crate::sync_guard::write_lock(&self.modules)
153            .get_mut(id)
154            .map(|m| {
155                m.state = state;
156                true
157            })
158            .unwrap_or(false)
159    }
160
161    pub fn list_modules(&self) -> Vec<CognitiveModule> {
162        crate::sync_guard::read_lock(&self.modules)
163            .values()
164            .cloned()
165            .collect()
166    }
167
168    pub fn set_priority(&self, id: &str, priority: u8) -> bool {
169        crate::sync_guard::write_lock(&self.modules)
170            .get_mut(id)
171            .map(|m| {
172                m.priority = priority;
173                true
174            })
175            .unwrap_or(false)
176    }
177
178    pub fn resources(&self) -> CognitiveResources {
179        crate::sync_guard::read_lock(&self.resources).clone()
180    }
181
182    pub fn update_resources(&self, f: impl Fn(&mut CognitiveResources)) {
183        f(&mut crate::sync_guard::write_lock(&self.resources));
184    }
185
186    pub fn schedule(&self) -> ExecutionPlan {
187        let modules = crate::sync_guard::read_lock(&self.modules);
188        let mut sorted: Vec<&CognitiveModule> = modules
189            .values()
190            .filter(|m| m.state == ModuleState::Idle || m.state == ModuleState::Running)
191            .collect();
192        sorted.sort_by_key(|b| std::cmp::Reverse(b.priority));
193        let order: Vec<String> = sorted.iter().map(|m| m.id.clone()).collect();
194        let energy: f64 = sorted.iter().map(|m| m.energy_cost).sum();
195        let plan = ExecutionPlan {
196            module_order: order.clone(),
197            total_energy: energy,
198            estimated_duration_ms: sorted.len() as u64 * 100,
199            priority: sorted.first().map(|m| m.priority).unwrap_or(0),
200            reason: format!("{} modules, {:.2} energy", sorted.len(), energy),
201        };
202        let mut queue = crate::sync_guard::write_lock(&self.module_queue);
203        queue.clear();
204        for id in &order {
205            queue.push_back(id.clone());
206        }
207        *crate::sync_guard::write_lock(&self.current_plan) = Some(plan.clone());
208        plan
209    }
210
211    pub fn execute_next(&self) -> Option<String> {
212        let next = crate::sync_guard::write_lock(&self.module_queue).pop_front()?;
213        {
214            let mut res = crate::sync_guard::write_lock(&self.resources);
215            if let Some(m) = crate::sync_guard::read_lock(&self.modules).get(&next) {
216                res.energy_level = (res.energy_level - m.energy_cost * 0.01).max(0.0);
217                res.context_switches += 1;
218            }
219        }
220        let now = self.now_ms();
221        crate::sync_guard::write_lock(&self.log).push_back(ExecutionLogEntry {
222            timestamp_ms: now,
223            module_id: next.clone(),
224            action: "execute".to_string(),
225            duration_ms: 100,
226            energy_used: 0.01,
227            success: true,
228            detail: "Scheduled by executive".to_string(),
229        });
230        if let Some(m) = crate::sync_guard::write_lock(&self.modules).get_mut(&next) {
231            m.last_run_ms = now;
232            m.run_count += 1;
233            m.state = ModuleState::Running;
234        }
235        Some(next)
236    }
237}
238impl Executive {
239    pub fn cycle(&self) -> Vec<String> {
240        let config = crate::sync_guard::read_lock(&self.config).clone();
241        let mut executed = Vec::new();
242        self.schedule();
243        if crate::sync_guard::read_lock(&self.resources).energy_level
244            < config.min_energy_for_execution
245        {
246            return vec!["__low_energy__".to_string()];
247        }
248        for _ in 0..config.max_modules_per_cycle {
249            if let Some(id) = self.execute_next() {
250                executed.push(id);
251            } else {
252                break;
253            }
254        }
255        self.update_resources(|r| {
256            r.energy_level = (r.energy_level + config.energy_regen_rate).min(1.0);
257            if r.energy_level > 0.9 {
258                r.attention_budget = 1.0;
259            }
260        });
261        executed
262    }
263
264    pub fn homeostasis(&self) -> Vec<String> {
265        let mut actions = Vec::new();
266        let res = crate::sync_guard::read_lock(&self.resources).clone();
267        let config = crate::sync_guard::read_lock(&self.config).clone();
268        if res.energy_level < config.critical_energy_threshold {
269            let mut modules = crate::sync_guard::write_lock(&self.modules);
270            for m in modules.values_mut() {
271                if m.priority < 100 && m.state == ModuleState::Running {
272                    m.state = ModuleState::Exhausted;
273                    actions.push(format!("suspended_{}", m.id));
274                }
275            }
276            actions.push("energy_conservation".to_string());
277        }
278        if res.context_switches > 1000 {
279            self.update_resources(|r| r.context_switches = 0);
280            actions.push("context_switch_throttle".to_string());
281        }
282        actions
283    }
284
285    pub fn stats(&self) -> (usize, usize, f64, f64) {
286        let m = crate::sync_guard::read_lock(&self.modules);
287        let r = crate::sync_guard::read_lock(&self.resources);
288        (
289            m.len(),
290            m.values()
291                .filter(|m| m.state == ModuleState::Running)
292                .count(),
293            r.energy_level,
294            r.attention_budget,
295        )
296    }
297
298    pub fn recent_log(&self, k: usize) -> Vec<ExecutionLogEntry> {
299        crate::sync_guard::read_lock(&self.log)
300            .iter()
301            .rev()
302            .take(k)
303            .cloned()
304            .collect()
305    }
306
307    pub fn recommend_module(&self, vagus_tone: Option<f64>) -> Option<String> {
308        let modules = crate::sync_guard::read_lock(&self.modules);
309        let res = crate::sync_guard::read_lock(&self.resources);
310        let mut candidates: Vec<&CognitiveModule> = modules
311            .values()
312            .filter(|m| m.state == ModuleState::Idle && m.energy_cost <= res.energy_level)
313            .collect();
314        if candidates.is_empty() {
315            return None;
316        }
317        if let Some(tone) = vagus_tone {
318            if tone < 0.4 {
319                candidates.sort_by(|a, b| {
320                    let a_stress = a.tags.contains(&"stress".to_string()) as u8;
321                    let b_stress = b.tags.contains(&"stress".to_string()) as u8;
322                    b_stress
323                        .cmp(&a_stress)
324                        .then_with(|| b.priority.cmp(&a.priority))
325                });
326            } else {
327                candidates.sort_by_key(|b| std::cmp::Reverse(b.priority));
328            }
329        } else {
330            candidates.sort_by_key(|b| std::cmp::Reverse(b.priority));
331        }
332        Some(candidates[0].id.clone())
333    }
334}