use crate::{
config::BranchConfig,
diff::extractor::DiffExtractor,
error::BranchResult,
sandbox::environment::SimulationEnvironment,
types::{Branch, BranchMetrics, DiffResult},
};
use std::sync::Arc;
pub struct SandboxEvaluator;
#[derive(Debug, Clone)]
pub enum Recommendation {
Commit,
Discard,
NeedsReview(Vec<String>),
}
#[derive(Debug)]
pub struct EvaluationReport {
pub diff: DiffResult,
pub metrics: BranchMetrics,
pub recommendation: Recommendation,
}
impl SandboxEvaluator {
pub async fn evaluate(
&self,
env: &SimulationEnvironment,
parent: &Branch,
config: Arc<BranchConfig>,
) -> BranchResult<EvaluationReport> {
let extractor = DiffExtractor::new(Arc::clone(&config));
let diff = extractor.diff(&env.branch, parent, None).await?;
let metrics = env.branch.metrics.clone();
let threshold = config.divergence_threshold;
let recommendation = recommend(&diff, &metrics, threshold);
Ok(EvaluationReport {
diff,
metrics,
recommendation,
})
}
}
pub fn recommend(diff: &DiffResult, metrics: &BranchMetrics, threshold: f64) -> Recommendation {
let mut notes: Vec<String> = Vec::new();
if diff.divergence_score >= threshold {
notes.push(format!(
"divergence score {:.3} meets or exceeds threshold {:.3}",
diff.divergence_score, threshold
));
}
if metrics.op_count == 0
&& diff.stats.added == 0
&& diff.stats.modified == 0
&& diff.stats.removed == 0
{
return Recommendation::Discard;
}
if !notes.is_empty() {
return Recommendation::NeedsReview(notes);
}
Recommendation::Commit
}