fix(mission-runtime): a mission with no egress no longer launches

`clawmates_core` is `internal: true`. Verified from a container attached to it
and nothing else: no default route, and every external address unreachable —
the positive control fails, which is what makes the network's own configuration
visible rather than inferred.

So the attach to `clawmates_edge` is not an optimisation. Without it a mission
has no route off the host: no provider call, no fetch, no work. The result was
discarded:

    let _ = self.docker.connect_network(EDGE_NETWORK, …).await;

which makes a failure here indistinguishable from success. The mission starts,
the phase runs, every tool call fails for a reason nothing reports, and the
phase can still reach `completed`. Green-with-nothing, again.

Not fatal on the error alone: re-attaching an already-connected container is
also an error, and a benign one on any relaunch path. So the container's own
network list settles it rather than the return code — already attached is
logged and continues, genuinely not attached fails the launch with a message
that says what it means. `inspect` failing counts as NOT attached, because the
whole point is to stop guessing that egress is present.

Behaviour change worth stating plainly: a mission that would previously have
run blind now refuses to start. That is the intended trade — a mission which
cannot reach anything cannot do the work it reports having done.

Suite: 108 binaries, 838 tests, green.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01WZb5A2kfVfjpdwSochkuHz
This commit is contained in:
Omar Sobh
2026-08-27 09:11:09 -05:00
co-authored by Claude Opus 5
parent fe5c7d2c87
commit bd7fd46305
+44 -2
View File
@@ -591,6 +591,20 @@ impl MissionRuntimeProvisioner {
Some(MissionRuntimeProvisioner { docker, image }) Some(MissionRuntimeProvisioner { docker, image })
} }
/// Is this container actually attached to the egress network?
///
/// Asked only when the attach reported an error, to tell "already connected"
/// apart from "not connected". Inspect failing is treated as NOT attached:
/// the whole point is to stop guessing that egress is present.
async fn is_on_edge_network(&self, name: &str) -> bool {
self.docker
.inspect_container(name, None::<bollard::query_parameters::InspectContainerOptions>)
.await
.ok()
.and_then(|c| c.network_settings?.networks)
.is_some_and(|nets| nets.contains_key(EDGE_NETWORK))
}
/// Idempotent: returns the endpoint URL, creating the container /// Idempotent: returns the endpoint URL, creating the container
/// on first call. If the container exists but is stopped, starts /// on first call. If the container exists but is stopped, starts
/// it. If it exists and is running, returns its endpoint. /// it. If it exists and is running, returns its endpoint.
@@ -775,7 +789,19 @@ impl MissionRuntimeProvisioner {
.map_err(|e| format!("create mission runtime container: {e}"))?; .map_err(|e| format!("create mission runtime container: {e}"))?;
// Attach to the edge network for outbound provider egress. // Attach to the edge network for outbound provider egress.
let _ = self //
// `clawmates_core` is `internal: true` and has NO default route —
// verified from a container on it, where every external address is
// unreachable. So this attach is not an optimisation: without it the
// mission cannot reach a provider, cannot fetch anything, and cannot do
// its work. The result used to be discarded, which made a failure here
// indistinguishable from success and produced the green-with-nothing
// shape this codebase keeps meeting.
//
// Not fatal on the error alone: re-attaching an already-connected
// container is an error too, and a benign one on any relaunch path. The
// container's own network list is the fact that settles it.
if let Err(e) = self
.docker .docker
.connect_network( .connect_network(
EDGE_NETWORK, EDGE_NETWORK,
@@ -784,7 +810,23 @@ impl MissionRuntimeProvisioner {
endpoint_config: Some(EndpointSettings::default()), endpoint_config: Some(EndpointSettings::default()),
}, },
) )
.await; .await
{
if self.is_on_edge_network(&name).await {
eprintln!(
"mission_runtime: {name} was already on {EDGE_NETWORK} ({e}) — \
egress is present, continuing"
);
} else {
return Err(format!(
"attach mission runtime container to {EDGE_NETWORK}: {e} — \
{CORE_NETWORK} is internal and has no route off the host, so \
this mission would run with no egress at all: every provider \
call and every fetch would fail while the phase still \
reported completion"
));
}
}
self.docker self.docker
.start_container(&name, None::<StartContainerOptions>) .start_container(&name, None::<StartContainerOptions>)