cartulary 0.3.0-alpha.1

The knowledge layer of your project — decisions, issues, docs, all in one place.
Documentation
use crate::domain::model::check::Violations;
use crate::domain::model::decision_record::{DecisionRecord, DecisionRecordCollection};
use crate::domain::model::record_ref::DecisionRecordRef;

/// Port: persistence for decision records of a single kind. Each
/// returned `DecisionRecord` carries its `origin` so callers can tell
/// `Local` from `Union { source }` without a second lookup. Bulk
/// traversal lives behind the separate
/// [`crate::domain::usecases::decision_record::DecisionRecordScanner`]
/// port — see [`crate::domain::usecases::issue::IssueRepository`] for the
/// same split rationale.
pub trait DecisionRecordRepository {
    fn save(&self, record: &DecisionRecord) -> anyhow::Result<()>;
    fn list(&self) -> anyhow::Result<DecisionRecordCollection>;
    fn find_by_id(&self, id: &DecisionRecordRef) -> anyhow::Result<Option<DecisionRecord>>;
    /// Return the configured ID prefix for this kind (e.g. `"ADR-"`), if any.
    /// Used by `check_decision_records` to detect prefix mismatches.
    fn configured_id_prefix(&self) -> Option<&str> {
        None
    }
}

/// A validated result for a single decision record file, combining parse errors
/// and semantic violations.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DecisionRecordCheckResult {
    pub path: std::path::PathBuf,
    pub violations: Violations,
}

impl DecisionRecordCheckResult {
    pub fn has_errors(&self) -> bool {
        self.violations.has_errors()
    }
}