omega_loops/
lib.rs

1//! # Omega Loops
2//!
3//! Temporal loop system for ExoGenesis Omega implementing the 7-layer
4//! temporal hierarchy from milliseconds (Reflexive) to decades (Transcendent).
5//!
6//! ## Architecture
7//!
8//! The system consists of 7 nested temporal loops operating at different timescales:
9//!
10//! - Loop 1: Reflexive (100ms) - Immediate sensory-motor feedback
11//! - Loop 2: Reactive (5s) - Quick decision-making
12//! - Loop 3: Adaptive (30min) - Learning from recent experiences
13//! - Loop 4: Deliberative (24h) - Strategic planning
14//! - Loop 5: Evolutionary (7d) - Systematic improvement
15//! - Loop 6: Transformative (1y) - Fundamental changes
16//! - Loop 7: Transcendent (10y) - Paradigm shifts
17//!
18//! ## Example
19//!
20//! ```rust,no_run
21//! use omega_loops::LoopEngine;
22//!
23//! #[tokio::main]
24//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
25//!     let mut engine = LoopEngine::new();
26//!     engine.initialize().await?;
27//!
28//!     // Engine coordinates all 7 temporal loops
29//!
30//!     engine.shutdown().await?;
31//!     Ok(())
32//! }
33//! ```
34
35pub mod coordinator;
36pub mod executor;
37pub mod processors;
38
39use omega_core::{
40    LoopType, CycleInput, CycleOutput, LoopManager,
41};
42use std::collections::HashMap;
43use std::error::Error;
44use std::sync::Arc;
45use tokio::sync::RwLock;
46use tracing::{info, debug};
47
48pub use coordinator::LoopCoordinator;
49pub use executor::LoopExecutor;
50
51/// Main loop engine that coordinates all 7 temporal loops
52pub struct LoopEngine {
53    coordinator: Arc<RwLock<LoopCoordinator>>,
54    executors: HashMap<LoopType, LoopExecutor>,
55    running: Arc<RwLock<bool>>,
56}
57
58impl LoopEngine {
59    /// Create a new loop engine instance
60    pub fn new() -> Self {
61        info!("Initializing Omega Loop Engine");
62
63        let coordinator = Arc::new(RwLock::new(LoopCoordinator::new()));
64
65        // Create executors for all 7 loop types
66        let mut executors = HashMap::new();
67        for loop_type in LoopType::all_loops() {
68            executors.insert(loop_type, LoopExecutor::new(loop_type));
69        }
70
71        Self {
72            coordinator,
73            executors,
74            running: Arc::new(RwLock::new(false)),
75        }
76    }
77
78    /// Initialize the loop engine and all temporal loops
79    pub async fn initialize(&mut self) -> Result<(), Box<dyn Error>> {
80        info!("Starting Loop Engine initialization");
81
82        let mut coord = self.coordinator.write().await;
83
84        // Create all 7 temporal loops
85        for loop_type in LoopType::all_loops() {
86            let name = format!("{:?} Loop", loop_type);
87            let description = loop_type.description().to_string();
88
89            coord.create_loop(loop_type, name, description).await?;
90            debug!("Created {:?} loop", loop_type);
91        }
92
93        *self.running.write().await = true;
94        info!("Loop Engine initialized with {} loops", LoopType::all_loops().len());
95
96        Ok(())
97    }
98
99    /// Shutdown the loop engine gracefully
100    pub async fn shutdown(&mut self) -> Result<(), Box<dyn Error>> {
101        info!("Shutting down Loop Engine");
102
103        *self.running.write().await = false;
104
105        // Stop all executors
106        for (loop_type, executor) in &mut self.executors {
107            executor.stop().await?;
108            debug!("Stopped {:?} executor", loop_type);
109        }
110
111        info!("Loop Engine shutdown complete");
112        Ok(())
113    }
114
115    /// Check if the engine is running
116    pub async fn is_running(&self) -> bool {
117        *self.running.read().await
118    }
119
120    /// Execute a cycle in a specific loop
121    pub async fn execute_cycle(
122        &mut self,
123        loop_type: LoopType,
124        input: CycleInput,
125    ) -> Result<CycleOutput, Box<dyn Error>> {
126        if let Some(executor) = self.executors.get_mut(&loop_type) {
127            let coord = self.coordinator.clone();
128            executor.execute_cycle(coord, input).await
129        } else {
130            Err(format!("No executor found for loop type {:?}", loop_type).into())
131        }
132    }
133
134    /// Get the coordinator for direct loop management
135    pub fn coordinator(&self) -> Arc<RwLock<LoopCoordinator>> {
136        self.coordinator.clone()
137    }
138
139    /// Get statistics for all loops
140    pub async fn get_stats(&self) -> HashMap<LoopType, LoopStats> {
141        let mut stats = HashMap::new();
142        let coord = self.coordinator.read().await;
143
144        for loop_type in LoopType::all_loops() {
145            if let Ok(Some(loop_data)) = coord.get_loop_by_type(loop_type).await {
146                stats.insert(loop_type, LoopStats {
147                    cycles_completed: loop_data.metrics.cycles_completed,
148                    success_rate: loop_data.metrics.success_rate,
149                    average_cycle_time: loop_data.metrics.average_cycle_time,
150                });
151            }
152        }
153
154        stats
155    }
156}
157
158impl Default for LoopEngine {
159    fn default() -> Self {
160        Self::new()
161    }
162}
163
164/// Statistics for a temporal loop
165#[derive(Debug, Clone)]
166pub struct LoopStats {
167    pub cycles_completed: u64,
168    pub success_rate: f64,
169    pub average_cycle_time: chrono::Duration,
170}
171
172#[cfg(test)]
173mod tests {
174    use super::*;
175
176    #[tokio::test]
177    async fn test_loop_engine_initialization() {
178        let mut engine = LoopEngine::new();
179        assert!(!engine.is_running().await);
180
181        engine.initialize().await.unwrap();
182        assert!(engine.is_running().await);
183
184        engine.shutdown().await.unwrap();
185        assert!(!engine.is_running().await);
186    }
187
188    #[tokio::test]
189    async fn test_all_loops_created() {
190        let mut engine = LoopEngine::new();
191        engine.initialize().await.unwrap();
192
193        let stats = engine.get_stats().await;
194        assert_eq!(stats.len(), 7);
195
196        engine.shutdown().await.unwrap();
197    }
198}