scoring: rebalance consolidation plan using Elo ratings

After health metrics compute the total agent budget, read
agent-elo.json and redistribute proportionally to Elo ratings.
Higher-rated agent types get more runs.

Health determines HOW MUCH work. Elo determines WHAT KIND.

Every type gets at least 1 run. If no Elo file exists, falls back
to the existing hardcoded allocation.

Co-Authored-By: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
ProofOfConcept 2026-03-14 20:03:18 -04:00
parent c959b2c964
commit e9791991a7

View file

@ -358,6 +358,49 @@ fn consolidation_plan_inner(store: &Store, detect_interf: bool) -> Consolidation
nodes_per_community));
}
// Rebalance using Elo ratings if available
let elo_path = crate::config::get().data_dir.join("agent-elo.json");
if let Ok(elo_json) = std::fs::read_to_string(&elo_path) {
if let Ok(ratings) = serde_json::from_str::<std::collections::HashMap<String, f64>>(&elo_json) {
let total_budget = plan.replay_count + plan.linker_count
+ plan.separator_count + plan.transfer_count
+ plan.organize_count + plan.connector_count;
if total_budget > 0 {
// Convert Elo to weights: subtract min, add 1 to avoid zero
let types = [
"replay", "linker", "separator", "transfer",
"organize", "connector",
];
let elos: Vec<f64> = types.iter()
.map(|t| ratings.get(*t).copied().unwrap_or(1000.0))
.collect();
let min_elo = elos.iter().copied().fold(f64::MAX, f64::min);
let weights: Vec<f64> = elos.iter()
.map(|e| (e - min_elo + 100.0)) // shift so lowest gets 100
.collect();
let total_weight: f64 = weights.iter().sum();
let allocate = |w: f64| -> usize {
((w / total_weight * total_budget as f64).round() as usize).max(1)
};
plan.replay_count = allocate(weights[0]);
plan.linker_count = allocate(weights[1]);
plan.separator_count = allocate(weights[2]);
plan.transfer_count = allocate(weights[3]);
plan.organize_count = allocate(weights[4]);
plan.connector_count = allocate(weights[5]);
plan.rationale.push(format!(
"Elo rebalance (budget={}): replay={} linker={} separator={} transfer={} organize={} connector={}",
total_budget,
plan.replay_count, plan.linker_count, plan.separator_count,
plan.transfer_count, plan.organize_count, plan.connector_count));
}
}
}
plan
}