khive-runtime 0.10.0

Composable Service API: entity/note CRUD, graph traversal, hybrid search, curation.
Documentation
//! Acceptance-matrix generator (ADR-115 Amendment 1; executable contract §2, §6).
//!
//! The matrix is generated by crossing every row of
//! [`declaration::FINALIZER_ENTRY_POINTS`] with the fixed set of
//! [`MatrixCaseKind`] the executable contract requires each declared entry
//! point to cover. No entry-point list is hand-maintained here or by any
//! consumer — the acceptance harness must iterate [`generated_acceptance_matrix`]
//! rather than enumerate entry points itself.

use super::declaration::{FinalizerEntryPoint, FINALIZER_ENTRY_POINTS};

/// The fixed, closed set of acceptance-case kinds every declared entry point
/// must cover (executable contract §2, §6).
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[allow(dead_code)] // consumed by the execution/outcome increment (step 15)
pub(crate) enum MatrixCaseKind {
    LegacyScannerBehavior,
    FixtureMatch,
    OneByteMiss,
    WrongScopeMiss,
    ReservedKeyMutation,
    SupportedEcho,
    RecordWriteFailure,
    StampFailure,
    SuccessAuditFailure,
    SecondOrderFailureAuditFailure,
    OneSnapshotRefreshRace,
}

impl MatrixCaseKind {
    /// Stable, exhaustive declaration order — the order the generator emits
    /// cases in for every entry point.
    pub(crate) const ALL: &'static [MatrixCaseKind] = &[
        MatrixCaseKind::LegacyScannerBehavior,
        MatrixCaseKind::FixtureMatch,
        MatrixCaseKind::OneByteMiss,
        MatrixCaseKind::WrongScopeMiss,
        MatrixCaseKind::ReservedKeyMutation,
        MatrixCaseKind::SupportedEcho,
        MatrixCaseKind::RecordWriteFailure,
        MatrixCaseKind::StampFailure,
        MatrixCaseKind::SuccessAuditFailure,
        MatrixCaseKind::SecondOrderFailureAuditFailure,
        MatrixCaseKind::OneSnapshotRefreshRace,
    ];
}

/// One generated acceptance-matrix row: a declared entry point crossed with
/// one required case kind.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(dead_code)] // consumed by the execution/outcome increment (step 15)
pub(crate) struct MatrixRow {
    pub(crate) entry_point: &'static FinalizerEntryPoint,
    pub(crate) case: MatrixCaseKind,
}

/// Generate the full acceptance matrix from [`FINALIZER_ENTRY_POINTS`].
///
/// Deterministic: iterates the declaration in its declared order and
/// [`MatrixCaseKind::ALL`] in its declared order, so repeated calls produce
/// an identical sequence. This is the sole source of matrix rows — the
/// harness must not maintain a second, independent entry-point or case list.
#[allow(dead_code)] // consumed by the execution/outcome increment (step 15)
pub(crate) fn generated_acceptance_matrix() -> Vec<MatrixRow> {
    let mut rows = Vec::with_capacity(FINALIZER_ENTRY_POINTS.len() * MatrixCaseKind::ALL.len());
    for entry_point in FINALIZER_ENTRY_POINTS {
        for &case in MatrixCaseKind::ALL {
            rows.push(MatrixRow { entry_point, case });
        }
    }
    rows
}

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

    /// Generation: the matrix is actually produced, and its size is the
    /// exact cross product of declaration rows and case kinds — not a
    /// hand-picked or truncated subset.
    #[test]
    fn generation_produces_full_cross_product() {
        let rows = generated_acceptance_matrix();
        assert_eq!(
            rows.len(),
            FINALIZER_ENTRY_POINTS.len() * MatrixCaseKind::ALL.len()
        );
        assert_eq!(rows[0].entry_point.id, "entity.create");
        assert_eq!(rows[0].case, MatrixCaseKind::LegacyScannerBehavior);
    }

    /// Completeness: every declared entry point appears with every required
    /// case kind exactly once — no declaration row is skipped and no case
    /// kind is missing for any row.
    #[test]
    fn completeness_covers_every_entry_point_and_case_kind() {
        let rows = generated_acceptance_matrix();

        for entry_point in FINALIZER_ENTRY_POINTS {
            let cases_for_entry: BTreeSet<MatrixCaseKind> = rows
                .iter()
                .filter(|row| row.entry_point.id == entry_point.id)
                .map(|row| row.case)
                .collect();
            let expected: BTreeSet<MatrixCaseKind> = MatrixCaseKind::ALL.iter().copied().collect();
            assert_eq!(
                cases_for_entry, expected,
                "entry point {} is missing required case coverage",
                entry_point.id
            );
        }

        let pairs: BTreeSet<(&str, MatrixCaseKind)> = rows
            .iter()
            .map(|row| (row.entry_point.id, row.case))
            .collect();
        assert_eq!(
            pairs.len(),
            rows.len(),
            "generated matrix contains a duplicate (entry point, case) pair"
        );
    }

    /// Stability: the generator is deterministic — repeated calls and
    /// independent iteration produce byte-for-byte identical row sequences,
    /// so downstream generated test names/order never drift between runs.
    #[test]
    fn stability_is_deterministic_across_calls() {
        let first = generated_acceptance_matrix();
        let second = generated_acceptance_matrix();
        assert_eq!(first, second);

        let ids_first: Vec<&str> = first.iter().map(|row| row.entry_point.id).collect();
        let ids_second: Vec<&str> = second.iter().map(|row| row.entry_point.id).collect();
        assert_eq!(ids_first, ids_second);
    }

    /// Visibility: the declaration surface the matrix exposes to the
    /// harness is bounded to exactly the six contract-specified entry
    /// points and no others — nothing declared elsewhere leaks in, and
    /// nothing declared here is silently dropped from the generated matrix.
    #[test]
    fn visibility_exposes_exactly_the_declared_entry_points() {
        let rows = generated_acceptance_matrix();
        let visible_ids: BTreeSet<&str> = rows.iter().map(|row| row.entry_point.id).collect();
        let expected_ids: BTreeSet<&str> = [
            "entity.create",
            "entity.update",
            "entity.bulk",
            "note.create",
            "note.update",
            "note.atomic_message",
        ]
        .into_iter()
        .collect();
        assert_eq!(visible_ids, expected_ids);
    }
}