diff --git a/hive-c0re/src/swarm_status.rs b/hive-c0re/src/swarm_status.rs index 4f17bb1c..c6bc815b 100644 --- a/hive-c0re/src/swarm_status.rs +++ b/hive-c0re/src/swarm_status.rs @@ -279,6 +279,20 @@ async fn handle_deploy_request( // repo and its config; what is left is hive-local, and there is no // approval to wait on because the operator's click at swarm level is // the authorisation. + // + // Seed the power intent to `Up` before queuing, same as + // `actions::approve`'s `ApprovalKind::Spawn` arm does for the + // operator-approved path: `first_deploy`'s tail `Reconcile` node + // seeds `Wanted` from the container's *currently observed* running + // state when no row exists yet (`power::Store::get_or_seed`), and at + // that point in a first deploy the container is freshly created but + // not yet started — so an unseeded row locks the agent's wanted + // state to `Offline` on its very first reconcile, and `Reconcile` + // never emits the `Start` node. Setting the row up front here closes + // that window the same way the approval path already does. + if let Err(e) = coord.power.set(&agent, crate::power::Wanted::Up) { + tracing::warn!(%agent, error = ?e, "agent_power: seed on swarm first-deploy failed"); + } coord .job_queue .insert_job(|b| crate::job_queue::templates::first_deploy(b, &agent))