ccf-core 1.0.0

Canonical CCF core v1 trust-update and runtime-certificate primitives for filed-Prov6 contract enforcement
Documentation
use ccf_core::qac::{
    qac_update_3x3, reject_arithmetic_interpolation_regression,
    reject_missing_positive_diagonal_gauge, reject_scalar_accumulator_update, Matrix3,
    PositiveDiagonal3, QacInputs3, ARITHMETIC_INTERPOLATION_OLD_WRONG_PATH,
    MISSING_POSITIVE_DIAGONAL_GAUGE_OLD_WRONG_PATH, QAC_JOURNEY_ID, QAC_STORY_ID,
    SCALAR_ACCUMULATOR_OLD_WRONG_PATH,
};

const EXPECTED_QAC: Matrix3 = Matrix3::new([
    [0.98190658848882018, 1.2947637401235284, 0.71866568469348002],
    [0.83870014968076223, 1.1484222048498280, 0.90773678135167934],
    [0.92507475466515798, 1.2991347723221549, 0.99724185998841852],
]);

fn fixture() -> QacInputs3 {
    QacInputs3 {
        prior_a_t: Matrix3::new([[0.82, 1.15, 0.64], [1.04, 0.91, 1.33], [0.77, 1.28, 1.09]]),
        reference_r_t: Matrix3::new([[1.21, 0.73, 1.08], [0.88, 1.42, 0.96], [1.31, 0.69, 1.17]]),
        left_l_t: PositiveDiagonal3::try_new([1.10, 0.90, 1.05]).unwrap(),
        right_c_t: PositiveDiagonal3::try_new([0.95, 1.20, 0.85]).unwrap(),
        alpha_t: 0.35,
        epsilon_floor: 1.0e-12,
    }
}

fn max_abs_error(actual: Matrix3, expected: Matrix3) -> f64 {
    let mut max_error = 0.0_f64;
    for row in 0..3 {
        for col in 0..3 {
            max_error =
                max_error.max((actual.entries[row][col] - expected.entries[row][col]).abs());
        }
    }
    max_error
}

#[test]
fn qac_update_matches_hand_computed_3x3_fixture() {
    eprintln!("journey={QAC_JOURNEY_ID} story={QAC_STORY_ID}");

    let actual = qac_update_3x3(&fixture()).expect("QAC update implementation is required");
    let max_matrix_error = max_abs_error(actual, EXPECTED_QAC);

    eprintln!("max_matrix_error={max_matrix_error:.16e}");
    assert!(
        max_matrix_error <= 1.0e-12,
        "max matrix error {max_matrix_error:.16e} exceeds 1e-12"
    );
}

#[test]
fn arithmetic_interpolation_negative_fixture_reports_kappa_excursion() {
    eprintln!("journey={QAC_JOURNEY_ID} story={QAC_STORY_ID}");

    let report = reject_arithmetic_interpolation_regression(&fixture())
        .expect("arithmetic interpolation negative guard is required");

    assert_eq!(
        report.old_wrong_path,
        ARITHMETIC_INTERPOLATION_OLD_WRONG_PATH
    );
    assert!(report.rejected);
    assert!(
        report.kappa_excursion > 0.0,
        "arithmetic interpolation must produce a positive kappa excursion"
    );
    eprintln!(
        "arithmetic_interpolation_negative=PASS kappa_excursion={:.16e}",
        report.kappa_excursion
    );
}

#[test]
fn missing_positive_diagonal_gauge_negative_fixture_is_rejected() {
    eprintln!("journey={QAC_JOURNEY_ID} story={QAC_STORY_ID}");

    let report = reject_missing_positive_diagonal_gauge(&fixture())
        .expect("missing positive diagonal gauge negative guard is required");

    assert_eq!(
        report.old_wrong_path,
        MISSING_POSITIVE_DIAGONAL_GAUGE_OLD_WRONG_PATH
    );
    assert!(report.rejected);
    eprintln!("missing_positive_diagonal_gauge_negative=PASS");
}

#[test]
fn scalar_accumulator_negative_fixture_reports_kappa_excursion() {
    eprintln!("journey={QAC_JOURNEY_ID} story={QAC_STORY_ID}");

    let report = reject_scalar_accumulator_update(&fixture())
        .expect("scalar accumulator negative guard is required");

    assert_eq!(report.old_wrong_path, SCALAR_ACCUMULATOR_OLD_WRONG_PATH);
    assert!(report.rejected);
    assert!(
        report.kappa_excursion > 0.0,
        "scalar accumulator update must produce a positive kappa excursion"
    );
    eprintln!(
        "scalar_accumulator_negative=PASS kappa_excursion={:.16e}",
        report.kappa_excursion
    );
}