Skip to main content

agentic_evolve_core/storage/
versioner.rs

1//! PatternVersioner — manages pattern version history.
2
3use std::collections::HashMap;
4
5use crate::types::error::{EvolveError, EvolveResult};
6use crate::types::pattern::Pattern;
7
8/// Version history entry.
9#[derive(Debug, Clone)]
10pub struct VersionEntry {
11    pub version: u32,
12    pub pattern_snapshot: String, // JSON
13    pub created_at: i64,
14    pub change_description: String,
15}
16
17/// Manages versioning of patterns.
18#[derive(Debug, Default)]
19pub struct PatternVersioner {
20    history: HashMap<String, Vec<VersionEntry>>,
21}
22
23impl PatternVersioner {
24    pub fn new() -> Self {
25        Self::default()
26    }
27
28    pub fn record_version(&mut self, pattern: &Pattern, description: &str) -> EvolveResult<u32> {
29        let snapshot = serde_json::to_string(pattern)
30            .map_err(|e| EvolveError::SerializationError(e.to_string()))?;
31        let entry = VersionEntry {
32            version: pattern.version,
33            pattern_snapshot: snapshot,
34            created_at: chrono::Utc::now().timestamp(),
35            change_description: description.to_string(),
36        };
37        self.history
38            .entry(pattern.id.as_str().to_string())
39            .or_default()
40            .push(entry);
41        Ok(pattern.version)
42    }
43
44    pub fn get_history(&self, pattern_id: &str) -> Vec<&VersionEntry> {
45        self.history
46            .get(pattern_id)
47            .map(|entries| entries.iter().collect())
48            .unwrap_or_default()
49    }
50
51    pub fn get_version(&self, pattern_id: &str, version: u32) -> EvolveResult<&VersionEntry> {
52        let entries = self
53            .history
54            .get(pattern_id)
55            .ok_or_else(|| EvolveError::PatternNotFound(pattern_id.to_string()))?;
56        entries
57            .iter()
58            .find(|e| e.version == version)
59            .ok_or_else(|| EvolveError::PatternNotFound(format!("{pattern_id}@v{version}")))
60    }
61
62    pub fn latest_version(&self, pattern_id: &str) -> Option<u32> {
63        self.history
64            .get(pattern_id)
65            .and_then(|entries| entries.last())
66            .map(|e| e.version)
67    }
68
69    pub fn total_versions(&self) -> usize {
70        self.history.values().map(|v| v.len()).sum()
71    }
72
73    pub fn clear(&mut self) {
74        self.history.clear();
75    }
76}