Files
clawmates/migrations/0045_teams.sql
T
Omar Sobh 6066e93889
ci / gates (push) Successful in 6s
ci / frontend (push) Successful in 26s
ci / rust (push) Successful in 3m24s
ci / e2e (push) Skipped
ci / publish (push) Successful in 2m19s
teams: per-team runtime posture (risk_profile + mcp_bundles) + FK from loops/topics
Foundation slice for letting a coding loop bring its own team instead
of reusing the paired research topic's team. Turns out the teams
table already exists (0010_teams.sql) with full CRUD — this scales
back to the minimal missing bits:

Schema (0045_teams.sql)
- ALTER TABLE teams ADD risk_profile TEXT (NULL = template default)
- ALTER TABLE teams ADD mcp_bundles JSONB DEFAULT '[]'
- ALTER TABLE loops ADD team_id UUID REFERENCES teams ON DELETE SET NULL
- ALTER TABLE research_topics ADD team_id UUID REFERENCES teams
- Two partial indexes (team_id NOT NULL) for the future cascade queries

cm-db (dynamic sqlx::query so the existing get_team's compile-time
cache doesn't need regenerating):
- TeamRuntimeConfig struct
- get_team_runtime_config / set_team_runtime_config
- team_for_loop / team_for_research_topic (resolvers)
- set_team_for_loop / set_team_for_research_topic (binders)

cm-api
- GET /api/teams/{id} now surfaces risk_profile + mcp_bundles
- PATCH /api/teams/{id}/runtime-config sets them

Not touched (comes in follow-up slices):
- Wizard picker exposing 'reuse research team' vs 'fresh coding team'
- Runtime container spawn keyed on team_id
- Migration of existing paired coding loops onto their own team
2026-07-16 18:16:28 -07:00

47 lines
2.2 KiB
SQL

-- Teams-for-loops foundation. The `teams` table already exists (see
-- 0010_teams.sql) — a workspace-scoped topology graph + node→claw
-- bindings via team_members. This migration adds only the fields
-- needed to make an existing team attachable to a loop or research
-- topic with its own runtime constitution.
--
-- Motivation: today the paired coding loop reuses the research topic's
-- ZeroClaw team container, which forces one risk_profile on both the
-- read-heavy research workload and the write-heavy coding workload.
-- Attaching a distinct team lets a loop bring its own risk_profile
-- (e.g. "coding_readwrite" allowing file_write + shell) without
-- weakening the research team's posture.
--
-- Backward compat: every new column is NULLABLE. NULL preserves the
-- legacy "inherit from wherever the runtime template says" behavior.
-- No existing row is invalidated; wizards + runtime opt into the new
-- fields in follow-up slices.
-- Per-team runtime posture. NULL falls back to the runtime template
-- default (currently `research_readonly` for research-spawned
-- containers). Named profiles resolve at daemon startup against
-- [risk_profiles.<name>] in the runtime config.
ALTER TABLE teams
ADD COLUMN IF NOT EXISTS risk_profile TEXT;
-- Extra MCP bundle aliases the team's agents load in addition to the
-- template defaults. Stored as JSONB array of strings so a team can
-- carry {"clawmates_door", "git_writer"} for a coding pair without
-- affecting other teams. Empty array = inherit template only.
ALTER TABLE teams
ADD COLUMN IF NOT EXISTS mcp_bundles JSONB NOT NULL DEFAULT '[]'::jsonb;
-- Wire loops and research_topics to an optional team_id. ON DELETE SET
-- NULL so deleting a team unbinds without destroying the loop/topic
-- (the runtime falls back to the template default).
ALTER TABLE loops
ADD COLUMN IF NOT EXISTS team_id UUID
REFERENCES teams(id) ON DELETE SET NULL;
CREATE INDEX IF NOT EXISTS loops_team_idx ON loops (team_id)
WHERE team_id IS NOT NULL;
ALTER TABLE research_topics
ADD COLUMN IF NOT EXISTS team_id UUID
REFERENCES teams(id) ON DELETE SET NULL;
CREATE INDEX IF NOT EXISTS research_topics_team_idx
ON research_topics (team_id) WHERE team_id IS NOT NULL;