diff --git a/hive-c0re/src/auto_update.rs b/hive-c0re/src/auto_update.rs index 012e2863..601d5417 100644 --- a/hive-c0re/src/auto_update.rs +++ b/hive-c0re/src/auto_update.rs @@ -209,7 +209,7 @@ pub async fn ensure_manager(coord: &Arc) -> Result<()> { /// Sort `names` in-place so parents precede their children in the topology. /// Uses BFS from root agents (depth 0). Agents absent from `topo` sort last, /// alphabetically within their tier. Stable within each depth tier. -fn topology_sort(names: &mut Vec, topo: &std::collections::BTreeMap>) { +pub fn topology_sort(names: &mut Vec, topo: &std::collections::BTreeMap>) { use std::collections::{HashMap, VecDeque}; // Build depth map using owned clones so the borrow on `names` is released // before the sort_by mutable borrow. @@ -300,3 +300,4 @@ pub async fn run(coord: Arc) -> Result<()> { coord.emit_rebuild_queue_snapshot(); Ok(()) } + diff --git a/hive-c0re/src/rebuild_queue.rs b/hive-c0re/src/rebuild_queue.rs index bb5b00fc..37dc02d9 100644 --- a/hive-c0re/src/rebuild_queue.rs +++ b/hive-c0re/src/rebuild_queue.rs @@ -648,7 +648,7 @@ pub async fn meta_update_cascade_agents(inputs: &[String]) -> Vec { .filter_map(|i| i.strip_prefix("agent-")) .map(|rest| rest.split('/').next().unwrap_or(rest).to_owned()) .collect(); - if touched_hyperhive || inputs.is_empty() { + let mut names = if touched_hyperhive || inputs.is_empty() { crate::lifecycle::list() .await .unwrap_or_default() @@ -664,7 +664,12 @@ pub async fn meta_update_cascade_agents(inputs: &[String]) -> Vec { .collect() } else { touched_agents - } + }; + // Sort parents before children so the sequential queue worker + // always rebuilds a parent before any of its dependents. + let topo = crate::topology::read(); + crate::auto_update::topology_sort(&mut names, &topo); + names } /// Current unix timestamp in seconds. `now()` calls are pulled into a @@ -1164,3 +1169,4 @@ mod tests { ); } } +