daemon: add distill agent to consolidation plan

Add distill_count to ConsolidationPlan, daemon health metrics,
and TUI display. Distill agent now participates in the
consolidation budget alongside replay, linker, separator,
transfer, organize, and connector.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kent Overstreet 2026-03-16 17:10:09 -04:00
parent f555fa3c8e
commit e049d4437f
3 changed files with 40 additions and 13 deletions

View file

@ -172,6 +172,7 @@ pub struct ConsolidationPlan {
pub transfer_count: usize,
pub organize_count: usize,
pub connector_count: usize,
pub distill_count: usize,
pub run_health: bool,
pub rationale: Vec<String>,
}
@ -185,9 +186,10 @@ impl ConsolidationPlan {
}
// Build per-type batch lists, then interleave so different agent
// types alternate rather than running all-replay-then-all-linker.
let types: [(&str, usize); 6] = [
let types: [(&str, usize); 7] = [
("linker", self.linker_count),
("organize", self.organize_count),
("distill", self.distill_count),
("replay", self.replay_count),
("connector", self.connector_count),
("separator", self.separator_count),
@ -257,6 +259,7 @@ fn consolidation_plan_inner(store: &Store, detect_interf: bool) -> Consolidation
transfer_count: 0,
organize_count: 0,
connector_count: 0,
distill_count: 0,
run_health: true,
rationale: Vec::new(),
};
@ -341,6 +344,18 @@ fn consolidation_plan_inner(store: &Store, detect_interf: bool) -> Consolidation
plan.rationale.push(format!(
"Organize: {} (half of linker count)", plan.organize_count));
// Distill: core concept maintenance — at least as much as organize
// High gini means hubs need refinement; low alpha means hubs are overloaded
plan.distill_count = plan.organize_count;
if gini > 0.4 {
plan.distill_count += 20;
}
if alpha < 2.0 {
plan.distill_count += 20;
}
plan.rationale.push(format!(
"Distill: {} (synthesize hub content)", plan.distill_count));
// Connector: bridges fragmented communities
let community_count = graph.community_count();
let nodes_per_community = if community_count > 0 {
@ -365,7 +380,7 @@ fn consolidation_plan_inner(store: &Store, detect_interf: bool) -> Consolidation
if let Ok(ratings) = serde_json::from_str::<std::collections::HashMap<String, f64>>(&elo_json) {
let types = [
"replay", "linker", "separator", "transfer",
"organize", "connector",
"organize", "connector", "distill",
];
let elos: Vec<f64> = types.iter()
.map(|t| ratings.get(*t).copied().unwrap_or(1000.0))
@ -392,22 +407,24 @@ fn consolidation_plan_inner(store: &Store, detect_interf: bool) -> Consolidation
plan.transfer_count = allocate(weights[3]);
plan.organize_count = allocate(weights[4]);
plan.connector_count = allocate(weights[5]);
plan.distill_count = allocate(weights[6]);
plan.rationale.push(format!(
"Elo allocation (budget={}): replay={} linker={} separator={} transfer={} organize={} connector={}",
"Elo allocation (budget={}): replay={} linker={} separator={} transfer={} organize={} connector={} distill={}",
budget,
plan.replay_count, plan.linker_count, plan.separator_count,
plan.transfer_count, plan.organize_count, plan.connector_count));
plan.transfer_count, plan.organize_count, plan.connector_count, plan.distill_count));
}
} else {
// No Elo file — use budget with equal distribution
let per_type = budget / 6;
let per_type = budget / 7;
plan.replay_count = per_type;
plan.linker_count = per_type;
plan.separator_count = per_type;
plan.transfer_count = per_type;
plan.organize_count = per_type;
plan.connector_count = per_type;
plan.distill_count = per_type;
plan.rationale.push(format!(
"No Elo ratings — equal distribution ({} each, budget={})", per_type, budget));
}
@ -457,11 +474,17 @@ pub fn format_plan(plan: &ConsolidationPlan) -> String {
if plan.connector_count > 0 {
out.push_str(&format!(" {}. connector ×{} — cross-cluster bridging\n",
step, plan.connector_count));
step += 1;
}
if plan.distill_count > 0 {
out.push_str(&format!(" {}. distill ×{:2} — hub content synthesis + refinement\n",
step, plan.distill_count));
}
let total = plan.replay_count + plan.linker_count
+ plan.separator_count + plan.transfer_count
+ plan.organize_count + plan.connector_count
+ plan.distill_count
+ if plan.run_health { 1 } else { 0 };
out.push_str(&format!("\nTotal agent runs: {}\n", total));