diff --git a/hive-c0re/src/lifecycle.rs b/hive-c0re/src/lifecycle.rs index bff0965..2f6b622 100644 --- a/hive-c0re/src/lifecycle.rs +++ b/hive-c0re/src/lifecycle.rs @@ -337,11 +337,17 @@ pub async fn rebuild_no_meta( let flake_ref = format!("{}#{name}", crate::meta::meta_dir().display()); if container_exists(name).await { // Existing container: preserve the prior running state across - // rebuild (closes #371). If it was running, cycle stop+start so - // any bind-mount / networking changes in the nspawn conf take - // effect. If it was stopped, leave it stopped — even if - // `nixos-container update` brought it up to run the in-container - // switch, the operator's explicit "stopped" intent wins. + // rebuild (closes #371). `nixos-container update` itself is + // already state-preserving — its only side effect on the running + // unit is a `systemctl reload container@` gated on + // `isContainerRunning`, so a stopped container stays stopped + // after the build + profile bump. We only need to recycle the + // outer unit when the container was running, so that any + // changes to `/etc/nixos-containers/.conf` (EXTRA_NSPAWN_FLAGS) + // or our systemd drop-ins (resource limits, stale-mount + // cleanup) are re-read by the next nspawn invocation. If a + // racing operator action started the container during the + // rebuild, that's their intent — don't override. let was_running = is_running(name).await; set_nspawn_flags(&container, agent_dir, claude_dir, notes_dir)?; set_resource_limits(&container)?; @@ -349,8 +355,6 @@ pub async fn rebuild_no_meta( run(&["update", &container, "--flake", &flake_ref]).await?; if was_running { run(&["restart", &container]).await - } else if is_running(name).await { - run(&["stop", &container]).await } else { Ok(()) }