Files
clawmates/migrations/0056_mission_teams.sql
T
Omar Sobh b8b8cb452e
ci / gates (push) Successful in 5s
ci / frontend (push) Successful in 37s
ci / rust (push) Failing after 1m41s
ci / e2e (push) Skipped
ci / publish (push) Skipped
missions: multi-team model — pick research + development teams
Directly addresses "we want to pick one or more teams to assign to a
mission, first screen research teams, next screen dev teams." A
mission now materializes N teams, each tagged with a phase purpose.

Backend:
  - 0056_mission_teams.sql — new join table
    mission_teams(mission_id, team_id, purpose). team_id PK because a
    team belongs to one mission-purpose. missions.team_id kept as
    legacy pointer to the first minted team for single-team surfaces.
  - mission_orchestrator::on_launch — reads mission.config.phase_teams
    (JSONB shape { research: [tid,...], coding: [tid,...] }), mints
    one team per (purpose, template) pair, records each in
    mission_teams, binds the first to mission.team_id. Legacy fallback:
    if config.phase_teams is absent, uses missions.team_template_id.
    Hard error if both are absent.
  - GET /api/missions/{id}/teams — returns
    [{ team_id, purpose, team_name }], sorted by created_at asc.

Frontend wizard (step 3 rewrite):
  - researchTeamIds / devTeamIds — Set<string> multi-selects
  - Reusable TeamMultiSelect component (checkbox-style cards)
  - Panels rendered conditionally by preset:
    hasResearchPhase → "Research teams" panel
    hasCodingPhase → "Development teams" panel
    neither → "Teams" panel (bench/security-only missions)
  - canNext enforces at least one pick in every visible panel
  - submit builds config.phase_teams and passes it via CreateMissionRequest
  - Review step shows both selections by name

MissionTeamTab:
  - Fetches /api/missions/{id}/teams and groups by purpose
  - Each purpose renders a section with per-team cards
  - Falls back to a single "mission" pseudo-row for legacy missions
    that only have missions.team_id (no mission_teams rows)

CreateMissionRequest no longer sends team_template_id from the wizard
— the multi-team config.phase_teams path supersedes it. The backend
still accepts team_template_id for API callers.

Verified: cargo check --workspace + tsc + eslint --quiet all green.
2026-07-20 19:25:07 -07:00

23 lines
874 B
PL/PgSQL

-- Multi-team missions: a mission can have N teams, each tagged with a
-- purpose (research / coding / security / benchmark / etc). The wizard
-- picks templates per purpose; on_launch mints one team per (purpose,
-- template) pick and records the link here.
--
-- missions.team_id stays around as a legacy pointer to the FIRST minted
-- team for single-team surfaces (Team tab default view, etc). It is
-- redundant with (mission_teams WHERE mission_id = X LIMIT 1) but
-- preserving it avoids a broader refactor in this slice.
BEGIN;
CREATE TABLE mission_teams (
mission_id UUID NOT NULL REFERENCES missions(id) ON DELETE CASCADE,
team_id UUID PRIMARY KEY REFERENCES teams(id) ON DELETE CASCADE,
purpose TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX mission_teams_mission_idx ON mission_teams (mission_id);
COMMIT;