corpora-rules 0.1.0

Validation rule pack (E3, held-decision, schema) for the corpora docs validator.
Documentation
//! Flags brittle positional `§` references in normative records. The corpus favours stable
//! ids over section numbers, which drift whenever a document is reorganised.

use corpora_core::{Authority, Diagnostic, Graph};

use crate::Rule;

pub struct PositionalRef;

impl Rule for PositionalRef {
    fn code(&self) -> &'static str {
        "POSITIONAL"
    }

    fn check(&self, g: &Graph, out: &mut Vec<Diagnostic>) {
        for r in g.records().filter(|r| r.authority == Authority::Normative) {
            for s in &r.body.section_refs {
                out.push(Diagnostic::warn(
                    "POSITIONAL",
                    &r.path,
                    format!("positional reference §{s} is brittle; prefer a stable id"),
                ));
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use corpora_core::*;
    use std::sync::Arc;

    #[test]
    fn warns_on_section_ref_in_normative_record() {
        let mut r = Record::minimal(
            Some(Id("A1".into())),
            DocPath("a.md".into()),
            Kind::Architecture,
            Lifecycle::Current,
            Authority::Normative,
            Facet::Canon { implementation: None, code_revision: None },
        );
        r.body.section_refs = vec!["9.6".into()];
        let g = Graph::build(vec![Arc::new(r)]).0;
        let mut out = Vec::new();
        PositionalRef.check(&g, &mut out);
        assert_eq!(out.len(), 1);
        assert_eq!(out[0].code, "POSITIONAL");
    }
}