Skip to main content

st/
mem8_lite.rs

1//! MEM8 Lite - Minimal wave-based memory for Smart Tree
2//!
3//! This is a self-contained subset of mem8-core from the Aye project.
4//! It provides the Wave struct for hot directory tracking without
5//! requiring the full MEM8 crate as a dependency.
6//!
7//! "Memory is wave interference patterns in cognitive space." - MEM8
8
9use serde::{Deserialize, Serialize};
10
11/// A wave pattern representing activity/state
12///
13/// For hot directory tracking, we use:
14/// - frequency: Change rate (events per hour)
15/// - emotional_valence: Security concern (-1.0 danger to +1.0 safe)
16/// - arousal: Activity level (0.0 cold to 1.0 hot)
17#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
18pub struct Wave {
19    /// Frequency in Hz (for directories: change rate)
20    pub frequency: f64,
21    /// Emotional valence (-1.0 to 1.0) - security concern level
22    pub emotional_valence: f64,
23    /// Arousal level (0.0 to 1.0) - activity/hotness
24    pub arousal: f64,
25}
26
27impl Wave {
28    /// Create a new wave
29    pub fn new(frequency: f64, emotional_valence: f64, arousal: f64) -> Self {
30        Self {
31            frequency,
32            emotional_valence: emotional_valence.clamp(-1.0, 1.0),
33            arousal: arousal.clamp(0.0, 1.0),
34        }
35    }
36
37    /// Compute resonance score with another wave
38    ///
39    /// Higher score = more similar frequencies and emotional states.
40    /// Used to detect directories with correlated activity patterns.
41    pub fn resonance_with(&self, other: &Wave) -> f64 {
42        // Frequency similarity (closer = higher score)
43        let freq_diff = (self.frequency - other.frequency).abs();
44        let max_freq = self.frequency.max(other.frequency);
45        let freq_score = if max_freq > 0.0 {
46            (-freq_diff / max_freq).exp()
47        } else {
48            1.0
49        };
50
51        // Emotional similarity
52        let valence_diff = (self.emotional_valence - other.emotional_valence).abs();
53        let arousal_diff = (self.arousal - other.arousal).abs();
54        let emotion_score = 1.0 - ((valence_diff + arousal_diff) / 4.0);
55
56        // Combined resonance (weighted average)
57        0.7 * freq_score + 0.3 * emotion_score
58    }
59}
60
61impl Default for Wave {
62    fn default() -> Self {
63        Self::new(1.0, 0.0, 0.5)
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    #[test]
72    fn test_wave_creation() {
73        let wave = Wave::new(10.0, 0.5, 0.8);
74        assert_eq!(wave.frequency, 10.0);
75        assert_eq!(wave.emotional_valence, 0.5);
76        assert_eq!(wave.arousal, 0.8);
77    }
78
79    #[test]
80    fn test_clamping() {
81        let wave = Wave::new(1.0, 2.0, -0.5);
82        assert_eq!(wave.emotional_valence, 1.0); // Clamped
83        assert_eq!(wave.arousal, 0.0); // Clamped
84    }
85
86    #[test]
87    fn test_resonance_identical() {
88        let wave1 = Wave::new(10.0, 0.5, 0.5);
89        let wave2 = Wave::new(10.0, 0.5, 0.5);
90        let resonance = wave1.resonance_with(&wave2);
91        assert!(resonance > 0.95); // Nearly identical
92    }
93
94    #[test]
95    fn test_resonance_different() {
96        let wave1 = Wave::new(10.0, 0.5, 0.5);
97        let wave2 = Wave::new(100.0, -0.5, 0.1);
98        let similar_resonance = wave1.resonance_with(&Wave::new(11.0, 0.5, 0.5));
99        let different_resonance = wave1.resonance_with(&wave2);
100        assert!(similar_resonance > different_resonance);
101    }
102}