use sha2::{Digest, Sha256};
use std::fs;
use std::path::Path;
pub fn calculate_epistemic_root(
project_path: &Path,
manifest_version: Option<&str>,
) -> Result<String, String> {
let schema_path = project_path.join("coreason_ontology.schema.json");
let h_ontology = if schema_path.exists() {
let content =
fs::read(&schema_path).map_err(|e| format!("Failed to read ontology schema: {}", e))?;
let mut hasher = Sha256::new();
hasher.update(&content);
hex::encode(hasher.finalize())
} else {
let mut hasher = Sha256::new();
hasher.update(b"");
hex::encode(hasher.finalize())
};
let version = match manifest_version {
Some(v) => v.to_string(),
None => {
let py_exec = std::env::var("PYTHON").unwrap_or_else(|_| "python".to_string());
let output = std::process::Command::new(py_exec)
.args([
"-c",
"import importlib.metadata; print(importlib.metadata.version('coreason-manifest'))",
])
.output();
match output {
Ok(out) if out.status.success() => {
String::from_utf8_lossy(&out.stdout).trim().to_string()
}
_ => "unknown".to_string(),
}
}
};
let env_str = format!(
"coreason-manifest=={}\ncoreason-runtime=={}\n",
version, version
);
let mut hasher = Sha256::new();
hasher.update(env_str.as_bytes());
let h_env = hex::encode(hasher.finalize());
let ledger_path = project_path
.join(".coreason")
.join("capability_ledger.json");
let h_capabilities = if ledger_path.exists() {
let content = fs::read(&ledger_path)
.map_err(|e| format!("Failed to read capability ledger: {}", e))?;
let mut hasher = Sha256::new();
hasher.update(&content);
hex::encode(hasher.finalize())
} else {
let mut hasher = Sha256::new();
hasher.update(b"{}");
hex::encode(hasher.finalize())
};
let combined = format!("{}{}{}", h_ontology, h_env, h_capabilities);
let mut hasher = Sha256::new();
hasher.update(combined.as_bytes());
Ok(hex::encode(hasher.finalize()))
}