use super::hf_config::KernelRequirement;
use std::path::Path;
#[derive(Debug, Clone, PartialEq)]
pub struct ContractStub {
pub filename: String,
pub yaml_content: String,
}
pub fn scaffold_contracts(missing: &[KernelRequirement], author: &str) -> Vec<ContractStub> {
missing
.iter()
.map(|req| {
let yaml = format!(
concat!(
"# Provable contract stub for {op}\n",
"# Generated by forjar — fill in equations and proof obligations\n",
"\n",
"metadata:\n",
" name: {contract}\n",
" version: \"0.1.0-stub\"\n",
" author: \"{author}\"\n",
" kernel_op: {op}\n",
"\n",
"equations:\n",
" - id: EQ-{op_upper}-01\n",
" description: \"TODO: Define primary equation for {op}\"\n",
" formula: \"TODO\"\n",
"\n",
"proof_obligations:\n",
" - id: PO-{op_upper}-01\n",
" equation: EQ-{op_upper}-01\n",
" description: \"TODO: Define proof obligation\"\n",
" strategy: \"TODO\"\n",
"\n",
"falsification_tests:\n",
" - id: FALSIFY-{op_upper}-001\n",
" equation: EQ-{op_upper}-01\n",
" description: \"TODO: Define falsification test\"\n",
" input: \"TODO\"\n",
" expected: \"TODO\"\n",
),
op = req.op,
contract = req.contract,
author = author,
op_upper = req.op.to_uppercase(),
);
ContractStub {
filename: format!("{}.yaml", req.contract),
yaml_content: yaml,
}
})
.collect()
}
pub fn write_stubs(stubs: &[ContractStub], output_dir: &Path) -> Result<Vec<String>, String> {
std::fs::create_dir_all(output_dir)
.map_err(|e| format!("create dir {}: {e}", output_dir.display()))?;
let mut written = Vec::new();
for stub in stubs {
let path = output_dir.join(&stub.filename);
if path.exists() {
continue;
}
std::fs::write(&path, &stub.yaml_content)
.map_err(|e| format!("write {}: {e}", path.display()))?;
written.push(stub.filename.clone());
}
Ok(written)
}