Adds the missing pieces the wizard needed and the sidebar controls around it: - LoopsWizard is now a 6-step flow (identity → repo → task/topology → triggers → repeat → assign agents) plus the existing secrets card. ResearchWizard picks up the same repo step and a hard gate when the workspace has zero agents. - New LoopStaffingStep with three tabs — Individual / Team / Organization — that mix freely per loop; selections persist via new loop_agents / loop_teams / loop_orgs join tables (0035 migration), each cascading on loop_id so hard-delete stays a single-row DELETE. - Backend CreateLoopRequest / UpdateLoopRequest accept the three lists and apply_staffing does a transactional replace-all; list_loops / get_loop hydrate the lists via a flattened LoopWithStaffing response. - LoopsList sidebar gains per-row enable/disable, edit (reopens the wizard prefilled with the current loop, PATCHes on submit), and delete with an inline confirm. - NoAgentsGate blocks launching a loop or research topic from a workspace with no roster; the sidebar `+` buttons also disable with a tooltip pointing at the TEAM tier. Not yet wired: the run driver still fills role slots from the workspace-wide pool; teaching enqueue_iteration to prefer loop_agents/loop_teams/loop_orgs is a follow-up.
34 lines
1.4 KiB
SQL
34 lines
1.4 KiB
SQL
-- Loop staffing: attach agents / teams / orgs to a loop so the run driver
|
|
-- knows who fills the role slots baked into loops.graph. Three parallel
|
|
-- join tables, one per selection tier — the wizard lets the user mix modes
|
|
-- (e.g. one team + two individual specialists).
|
|
--
|
|
-- All FKs cascade off loop_id so an existing hard-delete of a loop stays a
|
|
-- single-statement operation with no orphans. Agent/team/org deletions
|
|
-- also cascade so we never point at a phantom entity.
|
|
|
|
CREATE TABLE loop_agents (
|
|
loop_id UUID NOT NULL REFERENCES loops (id) ON DELETE CASCADE,
|
|
agent_id UUID NOT NULL REFERENCES agents (id) ON DELETE CASCADE,
|
|
role_slot TEXT,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
PRIMARY KEY (loop_id, agent_id)
|
|
);
|
|
CREATE INDEX loop_agents_agent_idx ON loop_agents (agent_id);
|
|
|
|
CREATE TABLE loop_teams (
|
|
loop_id UUID NOT NULL REFERENCES loops (id) ON DELETE CASCADE,
|
|
team_id UUID NOT NULL REFERENCES teams (id) ON DELETE CASCADE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
PRIMARY KEY (loop_id, team_id)
|
|
);
|
|
CREATE INDEX loop_teams_team_idx ON loop_teams (team_id);
|
|
|
|
CREATE TABLE loop_orgs (
|
|
loop_id UUID NOT NULL REFERENCES loops (id) ON DELETE CASCADE,
|
|
org_id UUID NOT NULL REFERENCES orgs (id) ON DELETE CASCADE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
PRIMARY KEY (loop_id, org_id)
|
|
);
|
|
CREATE INDEX loop_orgs_org_idx ON loop_orgs (org_id);
|