launch: accept config.phase_teams as a valid team source
ci / gates (push) Successful in 5s
ci / rust (push) Failing after 10s
ci / frontend (push) Successful in 26s
ci / e2e (push) Skipped
ci / publish (push) Skipped

Missions created via the new multi-team wizard have neither team_id
nor team_template_id set — they carry config.phase_teams. Both the
frontend Launch button gate and the backend set_status precondition
were checking only the old two fields, disabling launch for every
new wizard-created mission with a "No team" tooltip.

  - MissionCanvas: hasTeam now also returns true when
    mission.config.phase_teams has at least one non-empty list.
  - routes::missions::set_status: same check on the server so a
    direct API caller with only config.phase_teams also gets past
    the gate.

Directly unblocks the "we just finished the wizard, Launch is greyed
out" report. Agents materialize AFTER Launch — the button is the
trigger, not a post-condition of creation.
This commit is contained in:
Omar Sobh
2026-07-21 05:26:27 -07:00
parent f0dd0147f6
commit eb1df6acde
2 changed files with 34 additions and 3 deletions
+20 -2
View File
@@ -483,8 +483,26 @@ pub async fn set_status(
// BEFORE flipping status so a materialization failure keeps the
// mission in draft (no orphaned "running" mission with no agents).
if prior.status == "draft" && body.status == "running" {
if prior.team_id.is_none() && prior.team_template_id.is_none() {
eprintln!("mission {id}: launch rejected — no team_id and no team_template_id");
// Materializable when we have any of:
// - team_id (already exists)
// - team_template_id (legacy single-team path)
// - config.phase_teams with at least one non-empty list (new multi-team)
let has_phase_teams = prior
.config
.get("phase_teams")
.and_then(|v| v.as_object())
.map(|obj| {
obj.values()
.any(|v| v.as_array().map(|a| !a.is_empty()).unwrap_or(false))
})
.unwrap_or(false);
if prior.team_id.is_none()
&& prior.team_template_id.is_none()
&& !has_phase_teams
{
eprintln!(
"mission {id}: launch rejected — no team_id, no team_template_id, no config.phase_teams"
);
return Err(ApiError::BadRequest);
}
if let Err(e) = crate::mission_orchestrator::on_launch(