Skip to main content

do_memory_core/episode/
validation.rs

1//! Episode validation logic.
2//!
3//! Contains validation methods for Episode and `ExecutionStep`.
4
5use super::structs::{Episode, ExecutionStep};
6use crate::types::ExecutionResult;
7
8impl ExecutionStep {
9    /// Validate that the step has required fields set.
10    pub fn validate(&self) -> Result<(), String> {
11        if self.step_number == 0 {
12            return Err("Step number must be greater than 0".to_string());
13        }
14        if self.tool.is_empty() {
15            return Err("Tool name cannot be empty".to_string());
16        }
17        if self.action.is_empty() {
18            return Err("Action description cannot be empty".to_string());
19        }
20        Ok(())
21    }
22
23    /// Validate that the step has a valid result if present.
24    pub fn validate_result(&self) -> Result<(), String> {
25        if let Some(ref result) = self.result {
26            match result {
27                ExecutionResult::Success { output } if output.is_empty() => {
28                    Err("Success result must have non-empty output".to_string())
29                }
30                ExecutionResult::Error { message } if message.is_empty() => {
31                    Err("Error result must have non-empty message".to_string())
32                }
33                _ => Ok(()),
34            }
35        } else {
36            Ok(())
37        }
38    }
39}
40
41impl Episode {
42    /// Validate that the episode has required fields.
43    pub fn validate(&self) -> Result<(), String> {
44        if self.task_description.is_empty() {
45            return Err("Task description cannot be empty".to_string());
46        }
47        if self.context.domain.is_empty() {
48            return Err("Task domain cannot be empty".to_string());
49        }
50        Ok(())
51    }
52
53    /// Validate that the episode is ready for completion.
54    pub fn validate_for_completion(&self) -> Result<(), String> {
55        self.validate()?;
56
57        if self.steps.is_empty() {
58            return Err("Episode must have at least one step before completion".to_string());
59        }
60
61        for step in &self.steps {
62            step.validate()?;
63        }
64
65        Ok(())
66    }
67
68    /// Get a summary of the episode for logging purposes.
69    #[must_use]
70    pub fn summary(&self) -> String {
71        format!(
72            "Episode {}: {} ({} steps, {})",
73            self.episode_id,
74            self.task_description,
75            self.steps.len(),
76            match &self.outcome {
77                Some(o) => o.to_string(),
78                None => "in progress".to_string(),
79            }
80        )
81    }
82}