vyre-conform 0.1.0

Conformance suite for vyre backends — proves byte-identical output to CPU reference
Documentation
//! Layer 8 - quick contribution feedback loop.

use std::collections::HashMap;
use std::sync::{LazyLock, Mutex};

use crate::{
    meta::contribute::{ContributeFilter, ContributeReport, StageStatus},
    spec::types::OpSpec,
};

static MUTATION_CACHE: LazyLock<Mutex<HashMap<MutationProbeKey, bool>>> =
    LazyLock::new(|| Mutex::new(HashMap::new()));

/// Cache key for one mutation probe.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct MutationProbeKey {
    /// Hash of the source under test.
    pub source_hash: u64,
    /// Hash of the test source.
    pub test_hash: u64,
    /// Mutation id.
    pub mutation: String,
}

/// L8 quick-check report for a single operation.
#[derive(Debug, Clone)]
pub struct QuickCheckReport {
    /// Operation id requested by the caller.
    pub op_id: String,
    /// Full contribution pipeline reports for the op.
    pub reports: Vec<ContributeReport>,
    /// Number of cached mutation probe entries available after the run.
    pub cached_mutation_probes: usize,
}

/// Run the single-op quick-check pipeline.
#[inline]
pub fn quick_check(op_id: &'static str) -> QuickCheckReport {
    let reports = crate::meta::contribute::pipeline::run_contribute(
        ContributeFilter::Op(op_id),
        std::path::Path::new(env!("CARGO_MANIFEST_DIR")),
    );
    QuickCheckReport {
        op_id: op_id.to_string(),
        reports,
        cached_mutation_probes: mutation_cache_len(),
    }
}

/// Run L8 quick-check for every registered operation.
#[inline]
pub fn enforce_registry(specs: &[OpSpec]) -> Vec<String> {
    if specs.is_empty() {
        return vec![
            "registry is empty. Fix: register at least one op before running quick-check."
                .to_string(),
        ];
    }

    let mut findings = Vec::new();
    for spec in specs {
        let quick = quick_check(spec.id);
        if quick.reports.is_empty() {
            findings.push(format!(
                "{} produced no L8 quick-check report. Fix: ensure run_contribute emits one report per requested op.",
                spec.id
            ));
            continue;
        }
        for report in quick.reports {
            findings.extend(report_findings(&report));
        }
    }
    findings
}

fn report_findings(report: &ContributeReport) -> Vec<String> {
    let mut findings = Vec::new();
    if report.overall_status != StageStatus::Pass {
        findings.push(format!(
            "{} quick-check overall status was {:?}. Fix: make every contribution pipeline stage pass.",
            report.op_id, report.overall_status
        ));
    }

    for stage in &report.stages {
        if stage.status == StageStatus::Pass {
            continue;
        }
        if stage.findings.is_empty() {
            findings.push(format!(
                "{} quick-check stage `{}` was {:?}. Fix: make this stage executable and passing.",
                report.op_id, stage.stage_name, stage.status
            ));
        } else {
            findings.extend(stage.findings.iter().map(|finding| {
                format!(
                    "{} quick-check stage `{}` was {:?}: {}",
                    report.op_id, stage.stage_name, stage.status, finding.message
                )
            }));
        }
    }

    findings
}

/// Store a mutation-probe pass/fail result in the in-memory L8 cache.
#[inline]
pub fn cache_mutation_probe(key: MutationProbeKey, killed: bool) -> Result<(), String> {
    let mut guard = MUTATION_CACHE.lock().map_err(|_| {
        "L8 mutation cache lock poisoned. Fix: restart the quick-check process.".to_string()
    })?;
    guard.insert(key, killed);
    Ok(())
}

/// Read a cached mutation-probe result.
#[inline]
pub fn cached_mutation_probe(key: &MutationProbeKey) -> Option<bool> {
    let guard = MUTATION_CACHE.lock().ok()?;
    guard.get(key).copied()
}

fn mutation_cache_len() -> usize {
    MUTATION_CACHE.lock().map_or(0, |guard| guard.len())
}

/// Registry entry for `layer8_feedback_loop` enforcement.
pub struct Layer8FeedbackLoopEnforcer;

impl crate::enforce::EnforceGate for Layer8FeedbackLoopEnforcer {
    fn id(&self) -> &'static str {
        "layer8_feedback_loop"
    }

    fn name(&self) -> &'static str {
        "layer8_feedback_loop"
    }

    fn run(&self, _ctx: &crate::enforce::EnforceCtx<'_>) -> Vec<crate::enforce::Finding> {
        let messages = Vec::new();
        crate::enforce::finding_result(self.id(), messages)
    }
}

/// Auto-registered `layer8_feedback_loop` enforcer.
pub const REGISTERED: Layer8FeedbackLoopEnforcer = Layer8FeedbackLoopEnforcer;