vyre-conform 0.1.0

Conformance suite for vyre backends — proves byte-identical output to CPU reference
Documentation
//! Layer 5 - implementor/prosecutor/defender agent stream wiring.

pub use crate::adversarial::{
    full_catalog, run_gauntlet, Defendant, DefendantCatalog, GauntletFinding, GauntletReport,
};

/// Agent task kind used by the three-role adversarial contribution flow.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AgentTaskKind {
    /// Submit an operation, CPU reference, WGSL source, category, and metadata.
    Implementor,
    /// Write tests graded by mutation kill count and defendant capture rate.
    Prosecutor,
    /// Submit intentionally wrong references that must be caught mechanically.
    Defender,
}

/// A task routed to the agent stream.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AgentTask {
    /// The role expected to handle the task.
    pub kind: AgentTaskKind,
    /// Target operation id.
    pub op_id: String,
    /// Actionable instruction for the agent.
    pub instruction: String,
}

/// Return the three L5 task kinds for one operation.
#[inline]
pub fn task_stream_for_op(op_id: &str) -> Vec<AgentTask> {
    vec![
        AgentTask {
            kind: AgentTaskKind::Implementor,
            op_id: op_id.to_string(),
            instruction:
                "Fix: submit the op spec, reference function, WGSL source, category, and metadata."
                    .to_string(),
        },
        AgentTask {
            kind: AgentTaskKind::Prosecutor,
            op_id: op_id.to_string(),
            instruction:
                "Fix: write tests that kill every selected mutation and catch every defender."
                    .to_string(),
        },
        AgentTask {
            kind: AgentTaskKind::Defender,
            op_id: op_id.to_string(),
            instruction:
                "Fix: submit a plausible wrong reference that preserves as many laws as possible."
                    .to_string(),
        },
    ]
}

/// Run the existing defender gauntlet against the current registry.
#[inline]
pub fn enforce_current_registry() -> GauntletReport {
    let specs = crate::spec::op_registry::all_specs();
    let catalogs = full_catalog();
    run_gauntlet(&catalogs, &specs)
}

/// Registry entry for `layer5_adversarial` enforcement.
pub struct Layer5AdversarialEnforcer;

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

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

    fn run(&self, _ctx: &crate::enforce::EnforceCtx<'_>) -> Vec<crate::enforce::Finding> {
        // Audit fix (conform-gate finding 5.3): previously this enforcer
        // returned Ok(()) unconditionally — every call site treated L5
        // as a no-op, and mutated or divergent backends passed. Now L5
        // runs the defender gauntlet against the current registry and
        // emits one finding per defendant that escaped detection.
        let report = enforce_current_registry();
        let messages: Vec<String> = report
            .escaped()
            .into_iter()
            .map(|finding| {
                format!(
                    "Fix: defendant `{}` escaped detection on op `{}`; the test suite is not strong enough to catch it. Declare an additional law or strengthen archetypes until this defendant is caught.",
                    finding.defendant_id, finding.target_op_id,
                )
            })
            .collect();
        crate::enforce::finding_result(self.id(), messages)
    }
}

/// Auto-registered `layer5_adversarial` enforcer.
pub const REGISTERED: Layer5AdversarialEnforcer = Layer5AdversarialEnforcer;