cordance-advise 0.1.1

Cordance advisory engine. Deterministic doctrine checks against project state.
Documentation
//! R-license-1 — require at least one license file.

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

use super::AdviseRule;

const LICENSE_FILENAMES: &[&str] = &[
    "LICENSE",
    "LICENSE.md",
    "LICENSE-MIT",
    "LICENSE-APACHE",
    "LICENSE-MIT.txt",
];

pub struct RLicense1;

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

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

    fn check(&self, pack: &CordancePack) -> Vec<AdviseFinding> {
        let has_license = pack.sources.iter().any(|r| {
            if r.blocked {
                return false;
            }
            r.path.file_name().is_some_and(|name| {
                LICENSE_FILENAMES
                    .iter()
                    .any(|&known| name.eq_ignore_ascii_case(known))
            })
        });

        if has_license {
            return vec![];
        }

        vec![AdviseFinding {
            id: self.id().into(),
            severity: Severity::Info,
            summary: "No license file detected.".into(),
            doctrine_anchor: Utf8PathBuf::from(self.doctrine_anchor()),
            project_paths: vec![],
            remediation:
                "Add LICENSE-MIT and/or LICENSE-APACHE for open-source projects, or your org's \
                 license."
                    .into(),
        }]
    }
}