aethellib 0.9.6

Composable text generation primitives over target-specific TOML corpora with provenance tracking.
Documentation
//! error types for generation engine execution.

use thiserror::Error;

#[derive(Debug, Error, Clone)]
/// errors produced during typed plan construction and validation.
pub enum PlanError {
    /// one of rule key, section, or field had invalid characters or empty content.
    #[error("invalid {kind} '{value}': {reason}")]
    InvalidIdentifier {
        kind: String,
        value: String,
        reason: String,
    },
    /// plan contains duplicate rule keys.
    #[error("duplicate rule key '{0}'")]
    DuplicateRuleKey(String),
    /// a rule recalls a dependency that is not present in the plan.
    #[error("missing dependency: '{from}' recalls '{to}'")]
    MissingDependency { from: String, to: String },
    /// rule dependency graph contains a cycle.
    #[error("cycle detected in rule graph: {0:?}")]
    CycleDetected(Vec<String>),
    /// typed pool selector could not be resolved in the corpus.
    #[error("pool not found for section '{section}', field '{field}'")]
    PoolRefNotFound { section: String, field: String },
    /// chance probability is outside [0, 1].
    #[error("invalid probability for rule '{rule}': {value}")]
    InvalidChanceProbability { rule: String, value: f64 },
    /// weighted expression has zero total weight.
    #[error("weighted expression for rule '{rule}' has a total weight of 0")]
    WeightedTotalZero { rule: String },
}

#[derive(Debug, Clone)]
/// aggregate validation error report returned by `PlanBuilder::validate`.
pub struct PlanErrorReport {
    pub errors: Vec<PlanError>,
}

impl std::fmt::Display for PlanErrorReport {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        if self.errors.is_empty() {
            return write!(f, "plan validation failed with no reported errors");
        }

        for (idx, error) in self.errors.iter().enumerate() {
            if idx > 0 {
                write!(f, "; ")?;
            }
            write!(f, "{error}")?;
        }

        Ok(())
    }
}

impl std::error::Error for PlanErrorReport {}

#[derive(Debug, Error)]
/// errors produced by the generation engine.
pub enum AethelError {
    /// no value pool exists for the given section and field pair.
    #[error("pool not found for section '{section}', field '{field}'")]
    PoolNotFound { section: String, field: String },
    /// a rule required a previous result that is absent from the context history.
    #[error("missing dependency in generation context: '{0}'")]
    MissingDependency(String),
    /// a user-defined or configuration error with a descriptive message.
    #[error("{0}")]
    Custom(String),
}