rust-memex 0.6.5

Operator CLI + MCP server: canonical corpus second: semantic index second to aicx
Documentation
use anyhow::{Result, bail};
use serde::Serialize;

#[derive(Debug, Clone, Copy)]
pub struct BatchFailurePolicy {
    pub strict: bool,
    pub max_failure_rate: f64,
}

impl BatchFailurePolicy {
    pub fn new(strict: bool, max_failure_rate: f64) -> Result<Self> {
        if !(0.0..=1.0).contains(&max_failure_rate) {
            bail!("--max-failure-rate must be between 0.0 and 1.0");
        }
        Ok(Self {
            strict,
            max_failure_rate,
        })
    }

    pub fn should_fail(&self, summary: &BatchRunSummary) -> bool {
        (self.strict && summary.failed > 0) || summary.failure_rate() > self.max_failure_rate
    }
}

#[derive(Debug, Clone, Serialize)]
pub struct BatchRunSummary {
    pub indexed: usize,
    pub failed: usize,
    pub total: usize,
    pub failure_rate: f64,
    pub errors: Vec<String>,
}

impl BatchRunSummary {
    pub fn new(indexed: usize, failed: usize, total: usize, errors: Vec<String>) -> Self {
        let failure_rate = if total == 0 {
            0.0
        } else {
            failed as f64 / total as f64
        };
        Self {
            indexed,
            failed,
            total,
            failure_rate,
            errors,
        }
    }

    fn failure_rate(&self) -> f64 {
        self.failure_rate
    }

    pub fn emit_json(&self) -> Result<()> {
        println!("{}", serde_json::to_string(self)?);
        Ok(())
    }

    pub fn emit_warning(&self, noun: &str) {
        if self.failed > 0 {
            eprintln!(
                "WARNING: {}/{} {} failed. See log above.",
                self.failed, self.total, noun
            );
        }
    }

    pub fn enforce(&self, policy: BatchFailurePolicy, noun: &str) -> Result<()> {
        if policy.should_fail(self) {
            let reason = if policy.strict && self.failed > 0 {
                format!("strict=true and {} failure(s) were observed", self.failed)
            } else {
                format!(
                    "failure_rate {:.4} > max_failure_rate {:.4}",
                    self.failure_rate, policy.max_failure_rate
                )
            };
            bail!("{}/{} {} failed ({reason})", self.failed, self.total, noun);
        }
        Ok(())
    }
}