Skip to main content

do_memory_core/reflection/
mod.rs

1//! # Reflection Generator
2//!
3//! Generates structured reflections from completed episodes by analyzing:
4//! - Successful strategies and patterns
5//! - Areas for improvement
6//! - Key insights and learnings
7//!
8//! ## Example
9//!
10//! ```
11//! use do_memory_core::reflection::ReflectionGenerator;
12//! use do_memory_core::{Episode, TaskContext, TaskType, TaskOutcome, ExecutionStep};
13//!
14//! let context = TaskContext::default();
15//! let mut episode = Episode::new("Test task".to_string(), context, TaskType::Testing);
16//!
17//! let mut step = ExecutionStep::new(1, "test_runner".to_string(), "Run tests".to_string());
18//! episode.add_step(step);
19//!
20//! episode.complete(TaskOutcome::Success {
21//!     verdict: "All tests passed".to_string(),
22//!     artifacts: vec!["test_results.json".to_string()],
23//! });
24//!
25//! let generator = ReflectionGenerator::new();
26//! let reflection = generator.generate(&episode);
27//!
28//! assert!(!reflection.successes.is_empty() || !reflection.insights.is_empty());
29//! ```
30
31mod helpers;
32mod improvement_analyzer;
33mod insight_generator;
34mod success_analyzer;
35
36#[cfg(test)]
37mod tests;
38
39use crate::episode::Episode;
40use crate::types::Reflection;
41use chrono::Utc;
42use tracing::{debug, instrument};
43
44/// Maximum items in each reflection category
45const MAX_REFLECTION_ITEMS: usize = 5;
46
47/// Generator for episode reflections
48#[derive(Clone)]
49pub struct ReflectionGenerator {
50    /// Maximum items per category
51    max_items: usize,
52}
53
54impl Default for ReflectionGenerator {
55    fn default() -> Self {
56        Self::new()
57    }
58}
59
60impl ReflectionGenerator {
61    /// Create a new reflection generator
62    #[must_use]
63    pub fn new() -> Self {
64        Self {
65            max_items: MAX_REFLECTION_ITEMS,
66        }
67    }
68
69    /// Create a generator with custom max items
70    #[must_use]
71    pub fn with_max_items(max_items: usize) -> Self {
72        Self { max_items }
73    }
74
75    /// Generate reflection from a completed episode
76    #[instrument(skip(self, episode), fields(episode_id = %episode.episode_id))]
77    pub fn generate(&self, episode: &Episode) -> Reflection {
78        let mut successes = success_analyzer::identify_successes(episode, self.max_items);
79        let mut improvements = improvement_analyzer::identify_improvements(episode, self.max_items);
80        let mut insights = insight_generator::generate_insights(episode, self.max_items);
81
82        // Add sophisticated analysis
83        successes.extend(success_analyzer::analyze_success_patterns(episode));
84        improvements.extend(improvement_analyzer::analyze_improvement_opportunities(
85            episode,
86        ));
87        insights.extend(insight_generator::generate_contextual_insights(episode));
88
89        // Limit to max items after combining all sources
90        successes.truncate(self.max_items);
91        improvements.truncate(self.max_items);
92        insights.truncate(self.max_items);
93
94        debug!(
95            successes_count = successes.len(),
96            improvements_count = improvements.len(),
97            insights_count = insights.len(),
98            "Generated reflection"
99        );
100
101        Reflection {
102            successes,
103            improvements,
104            insights,
105            generated_at: Utc::now(),
106        }
107    }
108}