diff --git a/crates/cm-api/src/routes/missions.rs b/crates/cm-api/src/routes/missions.rs index eda9d5f..3b10915 100644 --- a/crates/cm-api/src/routes/missions.rs +++ b/crates/cm-api/src/routes/missions.rs @@ -1068,6 +1068,24 @@ async fn reap_mission_resources(state: &AppState, mission_id: Uuid) { } } + // 6. The captured outputs. `mission_gc` keeps `_outputs/` for 90 days + // because they are artifacts a user can still open — but once the + // mission row is gone so are its `mission_artifacts`, and nothing can + // open them. Found on 2026-09-14 as 163 orphaned directories on prod, + // the newest belonging to a mission deleted twenty minutes earlier. + let outputs = crate::mission_workspace::missions_root() + .join("_outputs") + .join(mission_id.to_string()); + if outputs.is_dir() { + if let Err(e) = tokio::fs::remove_dir_all(&outputs).await { + eprintln!( + "missions::delete: remove {} failed (continuing; mission_gc will reap it in \ + 90 days): {e}", + outputs.display() + ); + } + } + // Say what actually happened. `failed > 0` means the mission row is about to // be deleted while its claws survive with nothing left pointing at them — // the orphan case, and the only way to notice it after the fact.