diff --git a/crates/cm-api/src/mission_orchestrator.rs b/crates/cm-api/src/mission_orchestrator.rs index df54158..5da4aad 100644 --- a/crates/cm-api/src/mission_orchestrator.rs +++ b/crates/cm-api/src/mission_orchestrator.rs @@ -79,7 +79,12 @@ pub async fn on_launch( // The mission's own runtime endpoint. Claws MUST be provisioned against // THIS gateway, not the global one — see RuntimeProvisioner::for_gateway. let mut mission_gateway: Option = None; - if let Some(prov) = crate::mission_runtime::MissionRuntimeProvisioner::from_env() { + // Not for a microVM mission: the ZeroClaw daemon it would start is never + // spoken to, and it would sit holding a pairing code and ~3 GB of image for + // the life of the mission. Observed doing exactly that on the first real run. + if let Some(prov) = crate::mission_runtime::MissionRuntimeProvisioner::from_env() + .filter(|_| mission.runtime_kind != "microvm") + { match prov.ensure_container(mission_id).await { Ok(ec) => { mission_gateway = Some(ec.endpoint.clone()); @@ -115,6 +120,24 @@ pub async fn on_launch( ); } + // A microVM mission materialises no team. Its phases run as one `claude -p` + // inside a VM (`microvm_executor`), so there is no claw graph to provision — + // and demanding one rejected the launch of a well-formed mission with "pick + // teams in the wizard". This is the third of three team gates on a path that + // uses no teams; the other two are in `routes::missions` (draft→running) and + // `phase_runner::launch_phase` (no matching teams → stay pending). + // + // Returning before the picks below, not filtering them, because provisioning + // claws that never run is not a cheaper version of the same thing — it is a + // runtime binding and a pairing code describing something nothing uses. + if mission.runtime_kind == "microvm" { + eprintln!( + "mission_orchestrator: mission {mission_id} is a microvm mission — no team to \ + materialise; its phases execute in a VM" + ); + return Ok(None); + } + // Skip team materialization if already bound. if mission.team_id.is_some() { eprintln!(