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()));
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct MutationProbeKey {
pub source_hash: u64,
pub test_hash: u64,
pub mutation: String,
}
#[derive(Debug, Clone)]
pub struct QuickCheckReport {
pub op_id: String,
pub reports: Vec<ContributeReport>,
pub cached_mutation_probes: usize,
}
#[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(),
}
}
#[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
}
#[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(())
}
#[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())
}
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)
}
}
pub const REGISTERED: Layer8FeedbackLoopEnforcer = Layer8FeedbackLoopEnforcer;