Skip to main content

st/mem8/
integration.rs

1//! Integration of MEM8 with Smart Tree
2//! Provides cognitive memory capabilities for directory analysis
3
4use anyhow::Result;
5use std::path::Path;
6use std::sync::{Arc, RwLock};
7
8use crate::mem8::{
9    consciousness::ConsciousnessEngine,
10    format::{CompressedWave, M8Writer},
11    reactive::{ReactiveLayer, ReactiveMemory, ReactivePattern, ReactiveResponse, SensorInput},
12    wave::{FrequencyBand, MemoryWave, WaveGrid},
13};
14
15/// MEM8 integration for Smart Tree
16pub struct SmartTreeMem8 {
17    /// Wave grid for storing directory memories
18    wave_grid: Arc<RwLock<WaveGrid>>,
19    /// Reactive memory system
20    reactive_memory: Arc<RwLock<ReactiveMemory>>,
21    /// Consciousness engine
22    consciousness: Arc<ConsciousnessEngine>,
23    /// Current directory depth for z-axis mapping
24    current_depth: u16,
25}
26
27impl Default for SmartTreeMem8 {
28    fn default() -> Self {
29        Self::new()
30    }
31}
32
33impl SmartTreeMem8 {
34    /// Create a new MEM8 instance for Smart Tree
35    pub fn new() -> Self {
36        #[cfg(not(test))]
37        let wave_grid = Arc::new(RwLock::new(WaveGrid::new()));
38
39        #[cfg(test)]
40        let wave_grid = Arc::new(RwLock::new(WaveGrid::new_test()));
41
42        let reactive_memory = Arc::new(RwLock::new(ReactiveMemory::new(wave_grid.clone())));
43        let consciousness = Arc::new(ConsciousnessEngine::new(wave_grid.clone()));
44
45        Self {
46            wave_grid,
47            reactive_memory,
48            consciousness,
49            current_depth: 0,
50        }
51    }
52
53    /// Store a directory entry as a wave memory
54    pub fn store_directory_memory(
55        &mut self,
56        path: &Path,
57        metadata: DirectoryMetadata,
58    ) -> Result<()> {
59        // Map directory path to spatial coordinates
60        let (x, y) = self.path_to_coordinates(path);
61
62        // Create memory wave based on directory characteristics
63        let wave = self.create_directory_wave(&metadata);
64
65        // Store in grid
66        self.wave_grid
67            .write()
68            .unwrap()
69            .store(x, y, self.current_depth, wave);
70
71        // Update depth for next entry
72        self.current_depth = if self.current_depth == 65535 {
73            0
74        } else {
75            self.current_depth + 1
76        };
77
78        Ok(())
79    }
80
81    /// Convert directory path to grid coordinates
82    fn path_to_coordinates(&self, path: &Path) -> (u8, u8) {
83        // Hash path components to distribute across grid
84        let path_str = path.to_string_lossy();
85        let hash = self.simple_hash(&path_str);
86
87        let x = (hash & 0xFF) as u8;
88        let y = ((hash >> 8) & 0xFF) as u8;
89
90        (x, y)
91    }
92
93    /// Simple hash function for path distribution
94    pub fn simple_hash(&self, s: &str) -> u64 {
95        let mut hash = 5381u64;
96        for byte in s.bytes() {
97            hash = ((hash << 5).wrapping_add(hash)).wrapping_add(byte as u64);
98        }
99        hash
100    }
101
102    /// Create a wave from directory metadata
103    fn create_directory_wave(&self, metadata: &DirectoryMetadata) -> MemoryWave {
104        // Determine frequency based on content type
105        let frequency = match metadata.primary_type {
106            ContentType::Code => FrequencyBand::Technical.frequency(0.5),
107            ContentType::Documentation => FrequencyBand::Conversational.frequency(0.5),
108            ContentType::Configuration => FrequencyBand::DeepStructural.frequency(0.5),
109            ContentType::Data => FrequencyBand::Implementation.frequency(0.5),
110            ContentType::Media => FrequencyBand::Abstract.frequency(0.5),
111        };
112
113        // Amplitude based on importance/size
114        let amplitude =
115            (metadata.importance * 0.7 + metadata.normalized_size * 0.3).clamp(0.1, 1.0);
116
117        let mut wave = MemoryWave::new(frequency, amplitude);
118
119        // Set emotional context based on directory health
120        wave.valence = match metadata.health {
121            DirectoryHealth::Healthy => 0.5,
122            DirectoryHealth::Warning => -0.2,
123            DirectoryHealth::Critical => -0.8,
124        };
125
126        // Arousal based on activity level
127        wave.arousal = metadata.activity_level;
128
129        // Decay based on last modified time
130        if metadata.days_since_modified > 365 {
131            wave.decay_tau = Some(std::time::Duration::from_secs(86400)); // 1 day
132        } else if metadata.days_since_modified > 30 {
133            wave.decay_tau = Some(std::time::Duration::from_secs(604800)); // 1 week
134        } else {
135            wave.decay_tau = None; // No decay for recent files
136        }
137
138        wave
139    }
140
141    /// Query memories about a specific path pattern
142    pub fn query_path_memories(&self, pattern: &str) -> Vec<PathMemory> {
143        let grid = self.wave_grid.read().unwrap();
144        let mut memories = Vec::new();
145
146        // Sample grid looking for relevant memories
147        for x in 0..=255u8 {
148            for y in 0..=255u8 {
149                // Check recent layers (last 1000)
150                for z in (self.current_depth.saturating_sub(1000)..self.current_depth).step_by(10) {
151                    if let Some(wave) = grid.get(x, y, z) {
152                        if wave.calculate_decay() > 0.1 {
153                            // This is an active memory
154                            memories.push(PathMemory {
155                                coordinates: (x, y, z),
156                                wave: wave.clone(),
157                                relevance: self.calculate_relevance(wave, pattern),
158                            });
159                        }
160                    }
161                }
162            }
163        }
164
165        // Sort by relevance
166        memories.sort_by(|a, b| b.relevance.partial_cmp(&a.relevance).unwrap());
167        memories.truncate(20); // Top 20 results
168
169        memories
170    }
171
172    /// Calculate relevance score for a memory
173    fn calculate_relevance(&self, wave: &MemoryWave, pattern: &str) -> f32 {
174        // Simple relevance based on frequency band matching
175        let pattern_freq = if pattern.contains("src") || pattern.contains("lib") {
176            FrequencyBand::Technical.frequency(0.5)
177        } else if pattern.contains("doc") || pattern.contains("README") {
178            FrequencyBand::Conversational.frequency(0.5)
179        } else if pattern.contains("config") || pattern.contains("toml") {
180            FrequencyBand::DeepStructural.frequency(0.5)
181        } else {
182            FrequencyBand::Implementation.frequency(0.5)
183        };
184
185        // Frequency similarity
186        let freq_diff = (wave.frequency - pattern_freq).abs() / 1000.0;
187        let freq_score = 1.0 - freq_diff.clamp(0.0, 1.0);
188
189        // Combine with amplitude and decay
190        freq_score * wave.amplitude * wave.calculate_decay()
191    }
192
193    /// Register reactive patterns for directory events
194    pub fn register_directory_patterns(&mut self) {
195        // Pattern for large directories
196        let large_dir_pattern = ReactivePattern {
197            id: "large_directory".to_string(),
198            threshold: 0.7,
199            weight: 1.0,
200            response: Arc::new(|| ReactiveResponse {
201                layer: ReactiveLayer::SubcorticalReaction,
202                strength: 0.8,
203                action: "Enable streaming mode for large directory".to_string(),
204                latency: std::time::Duration::from_millis(30),
205            }),
206        };
207
208        // Pattern for security threats
209        let security_pattern = ReactivePattern {
210            id: "security_threat".to_string(),
211            threshold: 0.5,
212            weight: 1.5,
213            response: Arc::new(|| ReactiveResponse {
214                layer: ReactiveLayer::HardwareReflex,
215                strength: 0.95,
216                action: "Block access to suspicious directory".to_string(),
217                latency: std::time::Duration::from_millis(5),
218            }),
219        };
220
221        // Register patterns
222        let mut reactive = self.reactive_memory.write().unwrap();
223        reactive.register_pattern(ReactiveLayer::SubcorticalReaction, large_dir_pattern);
224        reactive.register_pattern(ReactiveLayer::HardwareReflex, security_pattern);
225    }
226
227    /// Process directory scan event through reactive system
228    pub fn process_directory_event(&self, event: DirectoryEvent) -> Option<ReactiveResponse> {
229        let input = match event {
230            DirectoryEvent::LargeDirectory { size, .. } => SensorInput::Visual {
231                intensity: (size as f32 / 1_000_000.0).clamp(0.0, 1.0),
232                motion: 0.0,
233                looming: size > 10_000_000,
234            },
235            DirectoryEvent::SecurityThreat { severity, .. } => SensorInput::Threat {
236                severity,
237                proximity: 1.0,
238                pattern: "malicious_file".to_string(),
239            },
240            DirectoryEvent::RapidChange { rate, .. } => SensorInput::Visual {
241                intensity: 0.5,
242                motion: rate,
243                looming: false,
244            },
245        };
246
247        self.reactive_memory.read().unwrap().process(&input)
248    }
249
250    /// Update consciousness state
251    pub fn update_consciousness(&self) {
252        self.consciousness.update();
253    }
254
255    /// Export memories to .m8 format
256    pub fn export_memories<W: std::io::Write>(&self, writer: W) -> Result<()> {
257        let mut m8_writer = M8Writer::new(writer);
258        let grid = self.wave_grid.read().unwrap();
259
260        // Collect all active memories
261        let mut compressed_waves = Vec::new();
262        let mut id = 0;
263
264        for x in 0..=255u8 {
265            for y in 0..=255u8 {
266                for z in 0..100u16 {
267                    // Sample first 100 layers
268                    if let Some(wave) = grid.get(x, y, z) {
269                        if wave.calculate_decay() > 0.01 {
270                            compressed_waves.push(CompressedWave::from_wave(wave, id));
271                            id += 1;
272                        }
273                    }
274                }
275            }
276        }
277
278        m8_writer.add_wave_memory(&compressed_waves)?;
279        m8_writer.finish()?;
280
281        Ok(())
282    }
283
284    /// Get count of active memories
285    pub fn active_memory_count(&self) -> usize {
286        self.wave_grid.read().unwrap().active_memory_count()
287    }
288
289    /// Store wave at specific coordinates (public helper method)
290    pub fn store_wave_at_coordinates(
291        &mut self,
292        x: u8,
293        y: u8,
294        z: u16,
295        wave: MemoryWave,
296    ) -> Result<()> {
297        self.wave_grid.write().unwrap().store(x, y, z, wave);
298        Ok(())
299    }
300
301    /// Helper to convert string to coordinates
302    pub fn string_to_coordinates(&self, s: &str) -> (u8, u8) {
303        let hash = self.simple_hash(s);
304        ((hash & 0xFF) as u8, ((hash >> 8) & 0xFF) as u8)
305    }
306}
307
308/// Directory metadata for memory creation
309#[derive(Debug)]
310pub struct DirectoryMetadata {
311    pub primary_type: ContentType,
312    pub importance: f32,      // 0.0 to 1.0
313    pub normalized_size: f32, // 0.0 to 1.0
314    pub health: DirectoryHealth,
315    pub activity_level: f32, // 0.0 to 1.0
316    pub days_since_modified: u32,
317}
318
319#[derive(Debug)]
320pub enum ContentType {
321    Code,
322    Documentation,
323    Configuration,
324    Data,
325    Media,
326}
327
328#[derive(Debug)]
329pub enum DirectoryHealth {
330    Healthy,
331    Warning,
332    Critical,
333}
334
335/// A memory associated with a path
336#[derive(Debug)]
337pub struct PathMemory {
338    pub coordinates: (u8, u8, u16),
339    pub wave: Arc<MemoryWave>,
340    pub relevance: f32,
341}
342
343/// Directory events for reactive processing
344#[derive(Debug)]
345pub enum DirectoryEvent {
346    LargeDirectory { path: String, size: u64 },
347    SecurityThreat { path: String, severity: f32 },
348    RapidChange { path: String, rate: f32 },
349}
350
351/// Example usage in Smart Tree
352pub fn integrate_with_smart_tree() -> Result<()> {
353    let mut mem8 = SmartTreeMem8::new();
354
355    // Register reactive patterns
356    mem8.register_directory_patterns();
357
358    // Store a directory memory
359    let metadata = DirectoryMetadata {
360        primary_type: ContentType::Code,
361        importance: 0.8,
362        normalized_size: 0.6,
363        health: DirectoryHealth::Healthy,
364        activity_level: 0.7,
365        days_since_modified: 5,
366    };
367
368    mem8.store_directory_memory(Path::new("src/lib.rs"), metadata)?;
369
370    // Query memories
371    let memories = mem8.query_path_memories("src");
372    println!("Found {} memories related to 'src'", memories.len());
373
374    // Process an event
375    let event = DirectoryEvent::LargeDirectory {
376        path: "node_modules".to_string(),
377        size: 50_000_000,
378    };
379
380    if let Some(response) = mem8.process_directory_event(event) {
381        println!(
382            "Reactive response: {} ({}ms)",
383            response.action,
384            response.latency.as_millis()
385        );
386    }
387
388    // Update consciousness
389    mem8.update_consciousness();
390
391    // Export to .m8 file
392    let mut buffer = Vec::new();
393    mem8.export_memories(&mut buffer)?;
394    println!("Exported {} bytes of memories", buffer.len());
395
396    Ok(())
397}
398
399#[cfg(test)]
400mod tests {
401    use super::*;
402
403    #[test]
404    #[ignore = "Consciousness update or memory export may hang"]
405    fn test_smart_tree_integration() {
406        // Skip in CI as consciousness update or memory export may hang
407        if std::env::var("CI").is_ok() || std::env::var("GITHUB_ACTIONS").is_ok() {
408            println!("Skipping smart tree integration test in CI environment");
409            return;
410        }
411        integrate_with_smart_tree().unwrap();
412    }
413
414    #[test]
415    fn test_path_to_coordinates() {
416        let mem8 = SmartTreeMem8::new();
417        let (x1, y1) = mem8.path_to_coordinates(Path::new("src/main.rs"));
418        let (x2, y2) = mem8.path_to_coordinates(Path::new("src/lib.rs"));
419
420        // Different paths should map to different coordinates (usually)
421        assert!(x1 != x2 || y1 != y2);
422    }
423}