use std::fmt::Write;
use crate::binding::BindingRegistry;
use crate::proof_status::compute_proof_level;
use crate::schema::{Contract, ObligationType};
#[path = "explain_render.rs"]
mod explain_render;
use explain_render::{
write_binding_status, write_enforcement, write_falsification_tests, write_kani_harnesses,
write_kernel_phases, write_obligations, write_qa_gate, write_simd_dispatch,
write_verification_ladder,
};
#[cfg(test)]
#[allow(clippy::all)]
#[path = "explain_tests.rs"]
mod tests;
pub fn obligation_pattern(ot: ObligationType) -> &'static str {
match ot {
ObligationType::Invariant => "∀x ∈ Domain: P(f(x)) — property holds for all inputs",
ObligationType::Equivalence => "∀x: |f(x) - g(x)| < ε — two implementations agree",
ObligationType::Bound => "∀x: a ≤ f(x)_i ≤ b — output range bounded",
ObligationType::Monotonicity => "x_i > x_j → f(x)_i > f(x)_j — order preserved",
ObligationType::Idempotency => "f(f(x)) = f(x) — applying twice gives same result",
ObligationType::Linearity => "f(αx) = α·f(x) — homogeneous scaling",
ObligationType::Symmetry => "f(permute(x)) related to f(x) — permutation property",
ObligationType::Associativity => "(a ⊕ b) ⊕ c = a ⊕ (b ⊕ c) — grouping invariant",
ObligationType::Conservation => "Q(before) = Q(after) — conserved quantity",
ObligationType::Ordering => "a ≤ b → f(a) ≤ f(b) — order relation maintained",
ObligationType::Completeness => "∀ required elements present — completeness verified",
ObligationType::Soundness => "∀x: P(x) → Q(f(x)) — soundness of transformation",
ObligationType::Involution => "f(f(x)) = x — involution (self-inverse)",
ObligationType::Determinism => "f(x) = f(x) — deterministic output for same input",
ObligationType::Roundtrip => "decode(encode(x)) = x — roundtrip fidelity",
ObligationType::StateMachine => "S × A → S — valid state transitions",
ObligationType::Classification => "f(x) ∈ C — output belongs to valid class set",
ObligationType::Independence => "P(A∩B) = P(A)·P(B) — statistical independence",
ObligationType::Termination => "algorithm terminates in finite steps",
ObligationType::Precondition => "P(input) — caller must guarantee before call",
ObligationType::Postcondition => "P(in) → Q(out) — kernel guarantees if pre holds",
ObligationType::Frame => "modifies(S) ∧ preserves(T\\S) — only S may change",
ObligationType::LoopInvariant => "∀ iter i: P(state_i) — maintained across iterations",
ObligationType::LoopVariant => "V(state) ∈ ℕ, strictly decreasing — termination witness",
ObligationType::OldState => "Q(old(state), new(state)) — relates pre to post state",
ObligationType::Subcontract => "weaken(pre) ∧ strengthen(post) — behavioral subtyping",
}
}
fn strategy_explanation(strategy: &str) -> &str {
match strategy {
"exhaustive" => "verify for ALL inputs within bound",
"stub_float" => {
"assume Lean-proved postconditions on transcendentals, verify surrounding code"
}
"compositional" => "verify sub-kernels separately, compose proofs",
"bounded_int" => "integer-only verification within bound",
_ => "bounded model check",
}
}
pub fn explain_contract(
contract: &Contract,
stem: &str,
binding: Option<&BindingRegistry>,
) -> String {
let mut out = String::with_capacity(4096);
write_header(&mut out, contract, stem);
write_what(&mut out, contract);
write_equations(&mut out, contract);
write_obligations(&mut out, contract);
write_verification_ladder(&mut out, contract, binding);
write_falsification_tests(&mut out, contract);
write_kani_harnesses(&mut out, contract);
write_kernel_phases(&mut out, contract);
write_simd_dispatch(&mut out, contract);
write_enforcement(&mut out, contract);
write_qa_gate(&mut out, contract);
write_type_invariants(&mut out, contract);
write_coq_status(&mut out, contract);
write_binding_status(&mut out, contract, stem, binding);
out
}
fn write_type_invariants(out: &mut String, contract: &Contract) {
if contract.type_invariants.is_empty() {
return;
}
let _ = writeln!(out, "Type invariants (Meyer's class invariants)");
let _ = writeln!(
out,
" These predicates must hold for every instance at every stable state."
);
let _ = writeln!(out);
for inv in &contract.type_invariants {
let desc = inv
.description
.as_deref()
.map(|d| format!(" — {d}"))
.unwrap_or_default();
let _ = writeln!(out, " {} [{}]{}", inv.name, inv.type_name, desc);
let _ = writeln!(out, " Predicate: {}", inv.predicate);
let _ = writeln!(out);
}
}
fn write_coq_status(out: &mut String, contract: &Contract) {
let Some(ref spec) = contract.coq_spec else {
return;
};
let _ = writeln!(out, "Coq verification ({})", spec.module);
if spec.obligations.is_empty() {
let _ = writeln!(out, " No obligation links defined — stubs only");
} else {
for ob in &spec.obligations {
let _ = writeln!(out, " {} → {} [{}]", ob.links_to, ob.coq_lemma, ob.status);
}
}
let _ = writeln!(out);
}
#[allow(clippy::too_many_lines)]
pub fn explain_contract_markdown(
contract: &Contract,
stem: &str,
binding: Option<&BindingRegistry>,
) -> String {
let mut out = String::with_capacity(4096);
let _ = writeln!(out, "# {stem}\n");
let _ = writeln!(
out,
"**Version:** {} | **Description:** {}\n",
contract.metadata.version, contract.metadata.description
);
if !contract.metadata.references.is_empty() {
let _ = writeln!(out, "## References\n");
for r in &contract.metadata.references {
let _ = writeln!(out, "- {r}");
}
let _ = writeln!(out);
}
if !contract.equations.is_empty() {
let _ = writeln!(out, "## Equations\n");
for (name, eq) in &contract.equations {
let _ = writeln!(out, "### {name}\n");
let latex = crate::latex::math_to_latex(&eq.formula);
let _ = writeln!(out, "$$\n{latex}\n$$\n");
if let Some(ref dom) = eq.domain {
let _ = writeln!(out, "**Domain:** ${}$\n", crate::latex::math_to_latex(dom));
}
if let Some(ref cod) = eq.codomain {
let _ = writeln!(
out,
"**Codomain:** ${}$\n",
crate::latex::math_to_latex(cod)
);
}
if !eq.invariants.is_empty() {
let _ = writeln!(out, "**Invariants:**\n");
for inv in &eq.invariants {
let _ = writeln!(out, "- ${}$", crate::latex::math_to_latex(inv));
}
let _ = writeln!(out);
}
if !eq.preconditions.is_empty() {
let _ = writeln!(out, "**Preconditions:**\n");
for pre in &eq.preconditions {
let _ = writeln!(out, "- `{pre}`");
}
let _ = writeln!(out);
}
if !eq.postconditions.is_empty() {
let _ = writeln!(out, "**Postconditions:**\n");
for post in &eq.postconditions {
let _ = writeln!(out, "- `{post}`");
}
let _ = writeln!(out);
}
}
}
if !contract.proof_obligations.is_empty() {
let _ = writeln!(out, "## Proof Obligations\n");
let _ = writeln!(out, "| # | Type | Property | Formal |");
let _ = writeln!(out, "|---|------|----------|--------|");
for (i, ob) in contract.proof_obligations.iter().enumerate() {
let formal = ob.formal.as_deref().unwrap_or("");
let _ = writeln!(
out,
"| {} | `{}` | {} | {} |",
i + 1,
ob.obligation_type,
ob.property,
formal
);
}
let _ = writeln!(out);
}
let level = compute_proof_level(contract, None);
let _ = writeln!(out, "## Verification\n");
let _ = writeln!(out, "**Proof level:** {level}\n");
if let Some(ref vs) = contract.verification_summary {
let _ = writeln!(
out,
"- Lean: {}/{} proved",
vs.l4_lean_proved, vs.total_obligations
);
}
let _ = writeln!(out, "- Kani: {} harnesses", contract.kani_harnesses.len());
let _ = writeln!(
out,
"- Tests: {} falsification\n",
contract.falsification_tests.len()
);
if let Some(registry) = binding {
let contract_file = format!("{stem}.yaml");
let has_bindings = contract.equations.keys().any(|eq| {
registry
.bindings
.iter()
.any(|b| b.contract == contract_file && b.equation == *eq)
});
if has_bindings {
let _ = writeln!(out, "## Bindings ({})\n", registry.target_crate);
let _ = writeln!(out, "| Equation | Status |");
let _ = writeln!(out, "|----------|--------|");
for eq_name in contract.equations.keys() {
let status = registry
.bindings
.iter()
.find(|b| b.contract == contract_file && b.equation == *eq_name)
.map_or("missing", |b| match b.status {
crate::binding::ImplStatus::Implemented => "implemented",
crate::binding::ImplStatus::Partial => "partial",
crate::binding::ImplStatus::NotImplemented => "not_implemented",
crate::binding::ImplStatus::Pending => "pending",
});
let _ = writeln!(out, "| {eq_name} | {status} |");
}
let _ = writeln!(out);
}
}
out
}
pub fn explain_contract_json(
contract: &Contract,
stem: &str,
binding: Option<&BindingRegistry>,
) -> String {
let level = compute_proof_level(contract, None);
let obligations: Vec<serde_json::Value> = contract
.proof_obligations
.iter()
.map(|ob| {
let mut obj = serde_json::json!({
"type": ob.obligation_type.to_string(),
"property": ob.property,
"pattern": obligation_pattern(ob.obligation_type),
});
if let Some(ref f) = ob.formal {
obj["formal"] = serde_json::json!(f);
}
if let Some(t) = ob.tolerance {
obj["tolerance"] = serde_json::json!(t);
}
if let Some(ref lean) = ob.lean {
obj["lean"] = serde_json::json!({
"theorem": lean.theorem,
"status": lean.status.to_string(),
});
}
if let Some(ref req) = ob.requires {
obj["requires"] = serde_json::json!(req);
}
if let Some(ref phase) = ob.applies_to_phase {
obj["applies_to_phase"] = serde_json::json!(phase);
}
if let Some(ref parent) = ob.parent_contract {
obj["parent_contract"] = serde_json::json!(parent);
}
obj
})
.collect();
let json = serde_json::json!({
"stem": stem,
"version": contract.metadata.version,
"description": contract.metadata.description,
"references": contract.metadata.references,
"depends_on": contract.metadata.depends_on,
"equations": contract.equations.keys().collect::<Vec<_>>(),
"proof_level": level.to_string(),
"obligations": obligations,
"falsification_tests": contract.falsification_tests.len(),
"kani_harnesses": contract.kani_harnesses.len(),
"binding": binding.map(|b| {
let contract_file = format!("{stem}.yaml");
let statuses: std::collections::BTreeMap<String, String> = contract
.equations
.keys()
.map(|eq| {
let status = b.bindings.iter()
.find(|bi| bi.contract == contract_file && bi.equation == *eq)
.map_or_else(|| "missing".to_string(), |bi| bi.status.to_string());
(eq.clone(), status)
})
.collect();
serde_json::json!({
"target_crate": b.target_crate,
"equations": statuses,
})
}),
});
serde_json::to_string_pretty(&json).unwrap_or_else(|_| "{}".to_string())
}
fn write_header(out: &mut String, contract: &Contract, stem: &str) {
use crate::schema::ContractKind;
let kind_tag = if contract.kind() == ContractKind::Kernel {
String::new()
} else {
format!(" [{}]", contract.kind())
};
let _ = writeln!(out, "{stem} (v{}){kind_tag}", contract.metadata.version);
let _ = writeln!(out, "{}", contract.metadata.description);
let _ = writeln!(out);
}
fn write_what(out: &mut String, contract: &Contract) {
let _ = writeln!(out, "What this contract specifies");
let refs = &contract.metadata.references;
if refs.is_empty() {
let _ = writeln!(
out,
" This contract specifies {}.",
contract.metadata.description
);
} else {
let _ = write!(
out,
" This contract specifies {}. It derives from",
contract.metadata.description
);
for (i, r) in refs.iter().enumerate() {
if i == 0 {
let _ = write!(out, " {r}");
} else {
let _ = write!(out, " and {r}");
}
}
let _ = writeln!(out, ".");
}
if !contract.metadata.depends_on.is_empty() {
let _ = write!(out, " Depends on:");
for dep in &contract.metadata.depends_on {
let _ = write!(out, " {dep}");
}
let _ = writeln!(out);
}
let _ = writeln!(out);
}
fn write_equations(out: &mut String, contract: &Contract) {
if contract.equations.is_empty() {
return;
}
let _ = writeln!(out, "Governing equations");
let _ = writeln!(out);
for (name, eq) in &contract.equations {
let _ = writeln!(out, " {name}");
let _ = writeln!(out, " {}", eq.formula);
if let Some(ref dom) = eq.domain {
let _ = writeln!(out, " Domain: {dom}");
}
if let Some(ref cod) = eq.codomain {
let _ = writeln!(out, " Range: {cod}");
}
if !eq.invariants.is_empty() {
let _ = writeln!(out);
let _ = writeln!(out, " Invariants:");
for (i, inv) in eq.invariants.iter().enumerate() {
let _ = writeln!(out, " {}. {inv}", i + 1);
}
}
if !eq.preconditions.is_empty() {
let _ = writeln!(out);
let _ = writeln!(out, " Preconditions (caller must guarantee):");
for pre in &eq.preconditions {
let _ = writeln!(out, " - {pre}");
}
}
if !eq.postconditions.is_empty() {
let _ = writeln!(out);
let _ = writeln!(out, " Postconditions (kernel guarantees):");
for post in &eq.postconditions {
let _ = writeln!(out, " - {post}");
}
}
if let Some(ref theorem) = eq.lean_theorem {
let _ = writeln!(out, " Lean theorem: {theorem}");
}
let _ = writeln!(out);
}
}