Skip to main content

do_memory_core/procedural/
mod.rs

1//! Procedural memory management
2//!
3//! Procedural memory stores learned heuristics-as-skills, providing actionable
4//! workflows synthesized from past experiences.
5
6mod types;
7
8pub use types::ProceduralMemory;
9
10#[cfg(test)]
11mod tests;
12
13use crate::types::TaskContext;
14use chrono::Utc;
15use uuid::Uuid;
16
17impl ProceduralMemory {
18    /// Create a new procedural memory
19    pub fn new(
20        name: String,
21        description: String,
22        context: TaskContext,
23        steps: Vec<crate::memory::playbook::PlaybookStep>,
24    ) -> Self {
25        let now = Utc::now();
26        Self {
27            id: Uuid::new_v4(),
28            name,
29            description,
30            context,
31            steps,
32            effectiveness: crate::patterns::PatternEffectiveness::default(),
33            source_episodes: Vec::new(),
34            source_patterns: Vec::new(),
35            created_at: now,
36            updated_at: now,
37        }
38    }
39
40    /// Check if this procedural memory is relevant to a given context
41    #[must_use]
42    pub fn is_relevant_to(&self, query_context: &TaskContext) -> bool {
43        // Match on domain
44        if self.context.domain == query_context.domain {
45            return true;
46        }
47
48        // Match on language
49        if self.context.language == query_context.language && self.context.language.is_some() {
50            return true;
51        }
52
53        // Match on tags
54        let common_tags: Vec<_> = self
55            .context
56            .tags
57            .iter()
58            .filter(|t| query_context.tags.contains(t))
59            .collect();
60
61        if !common_tags.is_empty() {
62            return true;
63        }
64
65        false
66    }
67
68    /// Record that this procedural memory was retrieved in a query
69    pub fn record_retrieval(&mut self) {
70        self.effectiveness.record_retrieval();
71        self.updated_at = Utc::now();
72    }
73
74    /// Record that this procedural memory was applied with an outcome
75    pub fn record_application(&mut self, success: bool, reward_delta: f32) {
76        self.effectiveness.record_application(success, reward_delta);
77        self.updated_at = Utc::now();
78    }
79
80    /// Add a source episode ID
81    pub fn add_source_episode(&mut self, episode_id: Uuid) {
82        if !self.source_episodes.contains(&episode_id) {
83            self.source_episodes.push(episode_id);
84            self.updated_at = Utc::now();
85        }
86    }
87
88    /// Add a source pattern ID
89    pub fn add_source_pattern(&mut self, pattern_id: crate::episode::PatternId) {
90        if !self.source_patterns.contains(&pattern_id) {
91            self.source_patterns.push(pattern_id);
92            self.updated_at = Utc::now();
93        }
94    }
95}