cordance-advise 0.1.1

Cordance advisory engine. Deterministic doctrine checks against project state.
Documentation
//! R-contracts-1 — every .schema.json must have a matching example fixture.

use camino::Utf8PathBuf;
use cordance_core::advise::{AdviseFinding, Severity};
use cordance_core::pack::CordancePack;
use cordance_core::source::SourceClass;

use super::AdviseRule;

pub struct RContracts1;

impl AdviseRule for RContracts1 {
    fn id(&self) -> &'static str {
        "R-contracts-1"
    }

    fn doctrine_anchor(&self) -> &'static str {
        "doctrine/principles/event-contracts.md"
    }

    fn check(&self, pack: &CordancePack) -> Vec<AdviseFinding> {
        let mut findings = Vec::new();

        let schemas: Vec<_> = pack
            .sources
            .iter()
            .filter(|r| {
                r.class == SourceClass::ProjectSchema && r.path.as_str().ends_with(".schema.json")
            })
            .collect();

        for schema in schemas {
            // Extract the stem from the schema path, e.g. "foo" from "contracts/foo.schema.json".
            let path_str = schema.path.as_str();
            let stem = path_str
                .rsplit('/')
                .next()
                .unwrap_or(path_str)
                .trim_end_matches(".schema.json");

            let has_fixture = pack
                .sources
                .iter()
                .any(|r| r.path.as_str() != path_str && r.path.as_str().contains(stem));

            if !has_fixture {
                findings.push(AdviseFinding {
                    id: self.id().into(),
                    severity: Severity::Warning,
                    summary: format!("Schema {path_str} has no example fixture."),
                    doctrine_anchor: Utf8PathBuf::from(self.doctrine_anchor()),
                    project_paths: vec![schema.path.clone()],
                    remediation: format!(
                        "Add a fixture file alongside the schema: {stem}.example.json or \
                         tests/{stem}.json."
                    ),
                });
            }
        }

        findings
    }
}