cordance-core 0.1.1

Cordance core types, schemas, and ports. No I/O.
Documentation
//! Deterministic advisory findings — `cordance advise`.
//!
//! Every finding cites a specific doctrine file. No LLM. No heuristics.
//!
//! Round-4 bughunt #1: the `generated_at: DateTime<Utc>` field made
//! `pack.advise` (and any caller that serialised `AdviseReport` standalone)
//! non-deterministic across runs. Removed — see `pack.rs` module doc for the
//! full determinism rationale.

use camino::Utf8PathBuf;
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AdviseReport {
    pub schema: String,
    pub findings: Vec<AdviseFinding>,
}

impl AdviseReport {
    #[must_use]
    pub fn empty() -> Self {
        Self {
            schema: crate::schema::CORDANCE_ADVISE_REPORT_V1.into(),
            findings: vec![],
        }
    }
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AdviseFinding {
    pub id: String,
    pub severity: Severity,
    pub summary: String,
    /// Doctrine file that defines the rule this finding cites.
    pub doctrine_anchor: Utf8PathBuf,
    /// Project paths that triggered the finding (may be empty).
    pub project_paths: Vec<Utf8PathBuf>,
    /// Concrete remediation step.
    pub remediation: String,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Severity {
    Error,
    Warning,
    Info,
}

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

    #[test]
    fn empty_report_has_schema() {
        let r = AdviseReport::empty();
        assert_eq!(r.schema, crate::schema::CORDANCE_ADVISE_REPORT_V1);
        assert!(r.findings.is_empty());
    }
}