zerum 0.4.0

Deterministic Python code governance: ~75 checks, default/strict profiles, explain mode, optional Ruff orchestration
Documentation
use crate::checks::catalog::build_catalog;
use crate::core::Check;

pub struct CheckRegistry {
    checks: Vec<Box<dyn Check>>,
}

impl Default for CheckRegistry {
    fn default() -> Self {
        Self::new()
    }
}

impl CheckRegistry {
    pub fn new() -> Self {
        let checks: Vec<Box<dyn Check>> = build_catalog();
        Self { checks }
    }

    pub fn iter(&self) -> impl Iterator<Item = &dyn Check> {
        self.checks.iter().map(|c| c.as_ref())
    }

    #[must_use]
    pub fn find(&self, id: &str) -> Option<&dyn Check> {
        self.checks
            .iter()
            .find(|c| c.id() == id)
            .map(|c| c.as_ref())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn registry_has_unique_zr_ids() {
        let registry = CheckRegistry::new();
        let mut ids: Vec<_> = registry.iter().map(|c| c.id()).collect();
        ids.sort_unstable();
        assert!(ids.len() >= 75);
        for id in &ids {
            assert!(id.starts_with("ZR"));
            assert_eq!(id.len(), 5);
        }
        assert_eq!(ids.windows(2).filter(|w| w[0] == w[1]).count(), 0);
    }

    #[test]
    fn registry_metadata_is_complete_and_aligned() {
        let registry = CheckRegistry::new();
        for check in registry.iter() {
            let meta = check.metadata();
            assert_eq!(meta.id, check.id());
            assert_eq!(meta.name, check.name());
            assert_eq!(meta.category, check.category());
            assert_eq!(meta.severity, check.severity());
            assert!(!meta.examples.trim().is_empty());
        }
    }
}