diff --git a/hive-c0re/src/job_queue/exec.rs b/hive-c0re/src/job_queue/exec.rs index 740b3c15..067684a5 100644 --- a/hive-c0re/src/job_queue/exec.rs +++ b/hive-c0re/src/job_queue/exec.rs @@ -548,6 +548,23 @@ async fn run_meta_lock( Some(list) => list, None => meta_update_cascade_agents(inputs).await, }; + // Pull each cascade agent's own input too — an agent's config-repo main + // is trusted, so a meta-input bump is a reasonable place to also catch + // it up. Without this, a meta-input bump rebuilds every affected agent + // against whatever `applied/` + // already happened to be locked to — normally current, but silently + // stale forever if a past deploy failed and nothing since retried it. + // Relocks against each agent's *declared* input (the forge URL, not the + // local `applied/` mirror `prepare_deploy` uses for a reviewed + // deploy) — this path has no PR to review, so there's nothing to gate. + // One combined call, not per-agent: simpler, at the cost of one + // unreachable/broken agent repo failing the whole cascade relock rather + // than just that agent. + if !cascade.is_empty() { + let agent_inputs: Vec = + cascade.iter().map(|name| format!("agent-{name}")).collect(); + crate::meta::lock_update(&agent_inputs).await?; + } // Grow one rebuild subgraph per affected agent into *this* meta-update // DAG (rooted on this `MetaLock`, so they build against the post-bump // lock), rather than fanning out child DAGs. `relock = false` — the