codex_memory/memory/
cognitive_memory_system.rs

1//! Cognitive Memory System Integration
2//!
3//! This module provides a unified interface for the SOTA cognitive memory system,
4//! integrating all cognitive enhancement components into a cohesive architecture.
5//!
6//! ## System Architecture
7//!
8//! The Cognitive Memory System combines several research-backed components:
9//!
10//! ### Core Components
11//! 1. **Three-Component Scoring**: Real-time memory importance calculation
12//! 2. **Cognitive Consolidation**: Enhanced memory strengthening with spacing effects
13//! 3. **Reflection Engine**: Meta-memory and insight generation
14//! 4. **Knowledge Graph**: Semantic relationship tracking
15//! 5. **Loop Prevention**: Quality control and duplicate detection
16//!
17//! ### Research Foundation
18//! - **Park et al. (2023)**: Generative agents three-component scoring
19//! - **Ebbinghaus (1885)**: Forgetting curve and spaced repetition
20//! - **Collins & Loftus (1975)**: Semantic network theory
21//! - **Flavell (1979)**: Metacognition and reflection processes
22//! - **Bjork (1994)**: Desirable difficulties and testing effects
23//!
24//! ## Usage Example
25//!
26//! ```rust
27//! use codex::memory::CognitiveMemorySystem;
28//!
29//! let mut system = CognitiveMemorySystem::new(repository).await?;
30//!
31//! // Store memory with cognitive enhancement
32//! let memory = system.store_memory_with_cognitive_processing(
33//!     "Important information to remember",
34//!     context
35//! ).await?;
36//!
37//! // Retrieve with enhanced scoring
38//! let results = system.cognitive_search(
39//!     "find related information",
40//!     search_context
41//! ).await?;
42//!
43//! // Trigger reflection for insight generation
44//! let insights = system.trigger_reflection_if_needed().await?;
45//! ```
46
47use super::cognitive_consolidation::{
48    CognitiveConsolidationConfig, CognitiveConsolidationEngine, CognitiveConsolidationResult,
49    RetrievalContext,
50};
51use super::error::Result;
52use super::insight_loop_prevention::{
53    LoopPreventionConfig, LoopPreventionEngine, PreventionAction,
54};
55use super::models::*;
56use super::reflection_engine::{
57    Insight, ReflectionConfig, ReflectionEngine, ReflectionSession,
58};
59use super::repository::MemoryRepository;
60use super::three_component_scoring::{
61    EnhancedSearchService, ScoringContext, ThreeComponentConfig, ThreeComponentEngine,
62};
63
64use chrono::{DateTime, Utc};
65use serde::{Deserialize, Serialize};
66use std::sync::Arc;
67use tokio::sync::RwLock;
68use tracing::{debug, info, warn};
69use uuid::Uuid;
70
71/// Configuration for the complete cognitive memory system
72#[derive(Debug, Clone, Serialize, Deserialize)]
73pub struct CognitiveMemoryConfig {
74    /// Three-component scoring configuration
75    pub scoring_config: ThreeComponentConfig,
76
77    /// Cognitive consolidation configuration
78    pub consolidation_config: CognitiveConsolidationConfig,
79
80    /// Reflection engine configuration
81    pub reflection_config: ReflectionConfig,
82
83    /// Loop prevention configuration
84    pub loop_prevention_config: LoopPreventionConfig,
85
86    /// Enable automatic cognitive processing
87    pub enable_auto_processing: bool,
88
89    /// Enable background reflection monitoring
90    pub enable_background_reflection: bool,
91
92    /// Minimum time between automatic processing (minutes)
93    pub auto_processing_interval_minutes: u64,
94
95    /// Performance monitoring configuration
96    pub enable_performance_monitoring: bool,
97
98    /// Maximum concurrent cognitive operations
99    pub max_concurrent_operations: usize,
100}
101
102impl Default for CognitiveMemoryConfig {
103    fn default() -> Self {
104        Self {
105            scoring_config: ThreeComponentConfig::default(),
106            consolidation_config: CognitiveConsolidationConfig::default(),
107            reflection_config: ReflectionConfig::default(),
108            loop_prevention_config: LoopPreventionConfig::default(),
109            enable_auto_processing: true,
110            enable_background_reflection: true,
111            auto_processing_interval_minutes: 30,
112            enable_performance_monitoring: true,
113            max_concurrent_operations: 10,
114        }
115    }
116}
117
118/// Performance metrics for the cognitive system
119#[derive(Debug, Clone, Serialize, Deserialize)]
120pub struct CognitivePerformanceMetrics {
121    pub total_memories_processed: u64,
122    pub total_insights_generated: u64,
123    pub total_reflections_completed: u64,
124    pub average_scoring_time_ms: f64,
125    pub average_consolidation_time_ms: f64,
126    pub average_reflection_time_ms: f64,
127    pub loop_prevention_blocks: u64,
128    pub quality_rejections: u64,
129    pub system_uptime_hours: f64,
130    pub last_updated: DateTime<Utc>,
131}
132
133impl Default for CognitivePerformanceMetrics {
134    fn default() -> Self {
135        Self {
136            total_memories_processed: 0,
137            total_insights_generated: 0,
138            total_reflections_completed: 0,
139            average_scoring_time_ms: 0.0,
140            average_consolidation_time_ms: 0.0,
141            average_reflection_time_ms: 0.0,
142            loop_prevention_blocks: 0,
143            quality_rejections: 0,
144            system_uptime_hours: 0.0,
145            last_updated: Utc::now(),
146        }
147    }
148}
149
150/// Enhanced memory storage request with cognitive context
151#[derive(Debug, Clone)]
152pub struct CognitiveMemoryRequest {
153    pub content: String,
154    pub embedding: Option<Vec<f32>>,
155    pub importance_score: Option<f64>,
156    pub metadata: Option<serde_json::Value>,
157    pub retrieval_context: RetrievalContext,
158    pub enable_immediate_consolidation: bool,
159    pub enable_quality_assessment: bool,
160}
161
162/// Enhanced memory with cognitive processing results
163#[derive(Debug, Clone)]
164pub struct CognitiveMemoryResult {
165    pub memory: Memory,
166    pub consolidation_result: Option<CognitiveConsolidationResult>,
167    pub quality_assessment: Option<super::insight_loop_prevention::QualityAssessment>,
168    pub processing_time_ms: u64,
169    pub cognitive_flags: CognitiveFlags,
170}
171
172/// Flags indicating cognitive processing status
173#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct CognitiveFlags {
175    pub consolidation_applied: bool,
176    pub reflection_triggered: bool,
177    pub quality_validated: bool,
178    pub loop_prevention_checked: bool,
179    pub three_component_scored: bool,
180}
181
182impl Default for CognitiveFlags {
183    fn default() -> Self {
184        Self {
185            consolidation_applied: false,
186            reflection_triggered: false,
187            quality_validated: false,
188            loop_prevention_checked: false,
189            three_component_scored: false,
190        }
191    }
192}
193
194/// Main cognitive memory system orchestrator
195pub struct CognitiveMemorySystem {
196    repository: Arc<MemoryRepository>,
197    config: CognitiveMemoryConfig,
198
199    // Cognitive engines
200    scoring_engine: ThreeComponentEngine,
201    consolidation_engine: CognitiveConsolidationEngine,
202    reflection_engine: Arc<RwLock<ReflectionEngine>>,
203    loop_prevention_engine: Arc<RwLock<LoopPreventionEngine>>,
204    search_service: EnhancedSearchService,
205
206    // System state
207    performance_metrics: Arc<RwLock<CognitivePerformanceMetrics>>,
208    last_background_processing: Arc<RwLock<DateTime<Utc>>>,
209    system_start_time: DateTime<Utc>,
210}
211
212impl CognitiveMemorySystem {
213    /// Create a new cognitive memory system
214    pub async fn new(
215        repository: Arc<MemoryRepository>,
216        config: CognitiveMemoryConfig,
217    ) -> Result<Self> {
218        info!("Initializing Cognitive Memory System with enhanced features");
219
220        // Initialize cognitive engines
221        let scoring_engine = ThreeComponentEngine::new(config.scoring_config.clone())?;
222        let consolidation_engine =
223            CognitiveConsolidationEngine::new(config.consolidation_config.clone());
224        let reflection_engine = Arc::new(RwLock::new(ReflectionEngine::new(
225            config.reflection_config.clone(),
226            repository.clone(),
227        )));
228        let loop_prevention_engine = Arc::new(RwLock::new(LoopPreventionEngine::new(
229            config.loop_prevention_config.clone(),
230        )));
231        let search_service = EnhancedSearchService::new(config.scoring_config.clone())?;
232
233        let performance_metrics = Arc::new(RwLock::new(CognitivePerformanceMetrics::default()));
234        let last_background_processing = Arc::new(RwLock::new(Utc::now()));
235        let system_start_time = Utc::now();
236
237        info!("Cognitive Memory System initialized successfully");
238
239        Ok(Self {
240            repository,
241            config,
242            scoring_engine,
243            consolidation_engine,
244            reflection_engine,
245            loop_prevention_engine,
246            search_service,
247            performance_metrics,
248            last_background_processing,
249            system_start_time,
250        })
251    }
252
253    /// Store memory with full cognitive processing
254    pub async fn store_memory_with_cognitive_processing(
255        &self,
256        request: CognitiveMemoryRequest,
257    ) -> Result<CognitiveMemoryResult> {
258        let start_time = std::time::Instant::now();
259        let mut cognitive_flags = CognitiveFlags::default();
260
261        info!("Processing memory storage with cognitive enhancements");
262
263        // Create base memory
264        let create_request = CreateMemoryRequest {
265            content: request.content.clone(),
266            embedding: request.embedding.clone(),
267            tier: Some(MemoryTier::Working),
268            importance_score: request.importance_score,
269            metadata: request.metadata.clone(),
270            parent_id: None,
271            expires_at: None,
272        };
273
274        let mut memory = self.repository.create_memory(create_request).await?;
275
276        // Apply three-component scoring
277        let scoring_context = ScoringContext {
278            query_embedding: request.embedding.clone().map(pgvector::Vector::from),
279            context_factors: request.retrieval_context.environmental_factors.clone(),
280            query_time: Utc::now(),
281            user_preferences: std::collections::HashMap::new(),
282        };
283
284        if let Ok(scoring_result) =
285            self.scoring_engine
286                .calculate_score(&memory, &scoring_context, false)
287        {
288            // Update memory with scores (would be persisted in production)
289            cognitive_flags.three_component_scored = true;
290            debug!(
291                "Three-component scoring applied: combined score {:.3}",
292                scoring_result.combined_score
293            );
294        }
295
296        // Apply cognitive consolidation if enabled
297        let consolidation_result = if request.enable_immediate_consolidation {
298            let similar_memories = self.find_similar_memories(&memory, 10).await?;
299
300            match self
301                .consolidation_engine
302                .calculate_cognitive_consolidation(
303                    &memory,
304                    &request.retrieval_context,
305                    &similar_memories,
306                )
307                .await
308            {
309                Ok(result) => {
310                    self.consolidation_engine
311                        .apply_consolidation_results(&mut memory, &result, &self.repository)
312                        .await?;
313                    cognitive_flags.consolidation_applied = true;
314                    debug!(
315                        "Cognitive consolidation applied: strength {:.3}",
316                        result.new_consolidation_strength
317                    );
318                    Some(result)
319                }
320                Err(e) => {
321                    warn!("Consolidation failed: {}", e);
322                    None
323                }
324            }
325        } else {
326            None
327        };
328
329        // Quality assessment if enabled
330        let quality_assessment = if request.enable_quality_assessment {
331            // Create a mock insight for quality assessment
332            let mock_insight = Insight {
333                id: Uuid::new_v4(),
334                insight_type: super::reflection_engine::InsightType::Pattern,
335                content: request.content.clone(),
336                confidence_score: 0.8,
337                source_memory_ids: vec![memory.id],
338                related_concepts: Vec::new(), // Would extract from content
339                knowledge_graph_nodes: Vec::new(),
340                importance_score: memory.importance_score,
341                generated_at: Utc::now(),
342                validation_metrics: super::reflection_engine::ValidationMetrics {
343                    novelty_score: 0.8,
344                    coherence_score: 0.9,
345                    evidence_strength: 0.7,
346                    semantic_richness: 0.6,
347                    predictive_power: 0.5,
348                },
349            };
350
351            match self
352                .loop_prevention_engine
353                .write()
354                .await
355                .validate_insight(&mock_insight)
356            {
357                Ok(loop_result) => {
358                    cognitive_flags.quality_validated = true;
359                    cognitive_flags.loop_prevention_checked = true;
360
361                    if loop_result.prevention_action == PreventionAction::RejectInsight {
362                        warn!("Memory quality assessment failed - would be rejected as insight");
363                    }
364
365                    Some(super::insight_loop_prevention::QualityAssessment {
366                        novelty_score: 0.8,
367                        coherence_score: 0.9,
368                        evidence_strength: 0.7,
369                        semantic_richness: 0.6,
370                        predictive_power: 0.5,
371                        overall_quality: 0.74,
372                        quality_factors: vec!["High coherence".to_string()],
373                        deficiency_reasons: Vec::new(),
374                    })
375                }
376                Err(e) => {
377                    warn!("Quality assessment failed: {}", e);
378                    None
379                }
380            }
381        } else {
382            None
383        };
384
385        // Check if reflection should be triggered
386        if self.config.enable_auto_processing {
387            if let Ok(should_reflect) = self
388                .reflection_engine
389                .read()
390                .await
391                .should_trigger_reflection()
392                .await
393            {
394                if should_reflect.is_some() {
395                    cognitive_flags.reflection_triggered = true;
396                    debug!("Reflection will be triggered in background");
397
398                    // Trigger background reflection (non-blocking)
399                    let reflection_engine = self.reflection_engine.clone();
400                    let trigger_reason = should_reflect.unwrap();
401                    tokio::spawn(async move {
402                        let mut engine = reflection_engine.write().await;
403                        match engine.execute_reflection(trigger_reason).await {
404                            Ok(session) => {
405                                info!(
406                                    "Background reflection completed: {} insights generated",
407                                    session.generated_insights.len()
408                                );
409                            }
410                            Err(e) => {
411                                warn!("Background reflection failed: {}", e);
412                            }
413                        }
414                    });
415                }
416            }
417        }
418
419        let processing_time = start_time.elapsed().as_millis() as u64;
420
421        // Update performance metrics
422        self.update_performance_metrics(processing_time, &cognitive_flags)
423            .await;
424
425        info!(
426            "Cognitive memory processing completed in {}ms",
427            processing_time
428        );
429
430        Ok(CognitiveMemoryResult {
431            memory,
432            consolidation_result,
433            quality_assessment,
434            processing_time_ms: processing_time,
435            cognitive_flags,
436        })
437    }
438
439    /// Perform enhanced search with cognitive scoring
440    pub async fn cognitive_search(
441        &self,
442        query: &str,
443        context: ScoringContext,
444        limit: Option<i32>,
445    ) -> Result<Vec<super::three_component_scoring::EnhancedSearchResult>> {
446        let start_time = std::time::Instant::now();
447
448        info!("Performing cognitive search for: {}", query);
449
450        // Create base search request
451        let search_request = SearchRequest {
452            query_text: Some(query.to_string()),
453            query_embedding: context
454                .query_embedding
455                .as_ref()
456                .map(|v| v.as_slice().to_vec()),
457            search_type: Some(SearchType::Hybrid),
458            limit,
459            explain_score: Some(true),
460            ..Default::default()
461        };
462
463        // Perform base search
464        let search_response = self.repository.search_memories(search_request).await?;
465
466        // Apply cognitive ranking
467        let enhanced_results =
468            self.search_service
469                .rank_search_results(search_response.results, &context, true)?;
470
471        let processing_time = start_time.elapsed().as_millis() as u64;
472
473        debug!(
474            "Cognitive search completed in {}ms, {} results",
475            processing_time,
476            enhanced_results.len()
477        );
478
479        Ok(enhanced_results)
480    }
481
482    /// Manually trigger reflection for insight generation
483    pub async fn trigger_reflection(&self, reason: String) -> Result<ReflectionSession> {
484        info!("Manually triggering reflection: {}", reason);
485
486        let mut reflection_engine = self.reflection_engine.write().await;
487        let session = reflection_engine.execute_reflection(reason).await?;
488
489        // Process generated insights through loop prevention
490        let mut loop_prevention = self.loop_prevention_engine.write().await;
491        for insight in &session.generated_insights {
492            match loop_prevention.validate_insight(insight) {
493                Ok(validation_result) => {
494                    if validation_result.prevention_action == PreventionAction::Allow {
495                        // Register valid insight
496                        let quality = super::insight_loop_prevention::QualityAssessment {
497                            novelty_score: insight.validation_metrics.novelty_score,
498                            coherence_score: insight.validation_metrics.coherence_score,
499                            evidence_strength: insight.validation_metrics.evidence_strength,
500                            semantic_richness: insight.validation_metrics.semantic_richness,
501                            predictive_power: insight.validation_metrics.predictive_power,
502                            overall_quality: (insight.validation_metrics.novelty_score
503                                + insight.validation_metrics.coherence_score
504                                + insight.validation_metrics.evidence_strength
505                                + insight.validation_metrics.semantic_richness
506                                + insight.validation_metrics.predictive_power)
507                                / 5.0,
508                            quality_factors: vec!["Validated through reflection".to_string()],
509                            deficiency_reasons: Vec::new(),
510                        };
511
512                        if let Err(e) = loop_prevention.register_insight(insight, quality) {
513                            warn!("Failed to register insight {}: {}", insight.id, e);
514                        }
515                    } else {
516                        warn!(
517                            "Insight {} blocked by loop prevention: {:?}",
518                            insight.id, validation_result.prevention_action
519                        );
520                    }
521                }
522                Err(e) => {
523                    warn!("Failed to validate insight {}: {}", insight.id, e);
524                }
525            }
526        }
527
528        // Update metrics
529        {
530            let mut metrics = self.performance_metrics.write().await;
531            metrics.total_reflections_completed += 1;
532            metrics.total_insights_generated += session.generated_insights.len() as u64;
533            metrics.last_updated = Utc::now();
534        }
535
536        info!(
537            "Reflection completed: {} insights generated, {} clusters analyzed",
538            session.generated_insights.len(),
539            session.generated_clusters.len()
540        );
541
542        Ok(session)
543    }
544
545    /// Get current system performance metrics
546    pub async fn get_performance_metrics(&self) -> CognitivePerformanceMetrics {
547        let mut metrics = self.performance_metrics.read().await.clone();
548
549        // Update uptime
550        metrics.system_uptime_hours = Utc::now()
551            .signed_duration_since(self.system_start_time)
552            .num_seconds() as f64
553            / 3600.0;
554
555        metrics
556    }
557
558    /// Get loop prevention statistics
559    pub async fn get_loop_prevention_statistics(
560        &self,
561    ) -> super::insight_loop_prevention::PreventionStatistics {
562        self.loop_prevention_engine
563            .read()
564            .await
565            .get_prevention_statistics()
566    }
567
568    /// Update system configuration
569    pub async fn update_configuration(&mut self, config: CognitiveMemoryConfig) -> Result<()> {
570        info!("Updating cognitive memory system configuration");
571
572        // Validate configuration components
573        config.scoring_config.validate()?;
574
575        // Update engines
576        self.scoring_engine
577            .update_config(config.scoring_config.clone())?;
578
579        // Update system config
580        self.config = config;
581
582        info!("Configuration updated successfully");
583        Ok(())
584    }
585
586    /// Perform background maintenance tasks
587    pub async fn background_maintenance(&self) -> Result<()> {
588        if !self.config.enable_background_reflection {
589            return Ok(());
590        }
591
592        let last_processing = *self.last_background_processing.read().await;
593        let minutes_since_last = Utc::now()
594            .signed_duration_since(last_processing)
595            .num_minutes() as u64;
596
597        if minutes_since_last < self.config.auto_processing_interval_minutes {
598            return Ok(());
599        }
600
601        debug!("Performing background maintenance");
602
603        // Check if reflection should be triggered
604        if let Ok(should_reflect) = self
605            .reflection_engine
606            .read()
607            .await
608            .should_trigger_reflection()
609            .await
610        {
611            if let Some(reason) = should_reflect {
612                match self.trigger_reflection(reason).await {
613                    Ok(_) => {
614                        info!("Background reflection completed successfully");
615                    }
616                    Err(e) => {
617                        warn!("Background reflection failed: {}", e);
618                    }
619                }
620            }
621        }
622
623        // Update last processing time
624        *self.last_background_processing.write().await = Utc::now();
625
626        Ok(())
627    }
628
629    // Private helper methods
630
631    async fn find_similar_memories(&self, memory: &Memory, limit: usize) -> Result<Vec<Memory>> {
632        if memory.embedding.is_none() {
633            return Ok(Vec::new());
634        }
635
636        let search_request = SearchRequest {
637            query_embedding: Some(memory.embedding.as_ref().unwrap().as_slice().to_vec()),
638            search_type: Some(SearchType::Semantic),
639            similarity_threshold: Some(0.7),
640            limit: Some(limit as i32),
641            ..Default::default()
642        };
643
644        let search_response = self.repository.search_memories(search_request).await?;
645
646        Ok(search_response
647            .results
648            .into_iter()
649            .filter(|result| result.memory.id != memory.id)
650            .map(|result| result.memory)
651            .collect())
652    }
653
654    async fn update_performance_metrics(&self, processing_time_ms: u64, flags: &CognitiveFlags) {
655        let mut metrics = self.performance_metrics.write().await;
656
657        metrics.total_memories_processed += 1;
658
659        // Update timing averages (simple moving average)
660        let count = metrics.total_memories_processed as f64;
661        metrics.average_scoring_time_ms =
662            (metrics.average_scoring_time_ms * (count - 1.0) + processing_time_ms as f64) / count;
663
664        if flags.consolidation_applied {
665            metrics.average_consolidation_time_ms =
666                (metrics.average_consolidation_time_ms * (count - 1.0) + processing_time_ms as f64)
667                    / count;
668        }
669
670        metrics.last_updated = Utc::now();
671    }
672}
673
674#[cfg(test)]
675mod tests {
676    use super::*;
677    use std::collections::HashMap;
678
679    async fn create_test_repository() -> Arc<MemoryRepository> {
680        // This would create a test repository in real implementation
681        panic!("Test repository creation not implemented - requires database setup");
682    }
683
684    #[tokio::test]
685    #[ignore] // Ignore for now as it requires database setup
686    async fn test_cognitive_memory_system_creation() {
687        let repository = create_test_repository().await;
688        let config = CognitiveMemoryConfig::default();
689
690        let system = CognitiveMemorySystem::new(repository, config).await;
691        assert!(system.is_ok());
692    }
693
694    #[test]
695    fn test_cognitive_memory_config_defaults() {
696        let config = CognitiveMemoryConfig::default();
697
698        assert!(config.enable_auto_processing);
699        assert!(config.enable_background_reflection);
700        assert_eq!(config.auto_processing_interval_minutes, 30);
701        assert_eq!(config.max_concurrent_operations, 10);
702    }
703
704    #[test]
705    fn test_cognitive_flags_default() {
706        let flags = CognitiveFlags::default();
707
708        assert!(!flags.consolidation_applied);
709        assert!(!flags.reflection_triggered);
710        assert!(!flags.quality_validated);
711        assert!(!flags.loop_prevention_checked);
712        assert!(!flags.three_component_scored);
713    }
714
715    #[test]
716    fn test_performance_metrics_default() {
717        let metrics = CognitivePerformanceMetrics::default();
718
719        assert_eq!(metrics.total_memories_processed, 0);
720        assert_eq!(metrics.total_insights_generated, 0);
721        assert_eq!(metrics.total_reflections_completed, 0);
722        assert_eq!(metrics.average_scoring_time_ms, 0.0);
723    }
724}