-- Slice 8.5 — level-up proposals. -- -- A proposal is an LLM-generated diff of "current state → suggested -- state" for either a specific agent or a whole team. Human approves -- (all or per-item) via a diff-review UI; the applier commits the -- approved subset. -- -- Proposal payload (JSONB) shape — kept schemaless because proposal -- kinds evolve. Documented shapes: -- -- agent proposal: -- { -- "kind": "agent", -- "current": { "system_prompt": "…", "skills": ["…"] }, -- "suggested_items": [ -- { "id": "u1", "kind": "brain_consolidation", -- "rationale": "…", "brain_md_diff": "…" }, -- { "id": "u2", "kind": "identity_refinement", --- "rationale": "…", "new_system_prompt": "…" }, -- { "id": "u3", "kind": "skill_add", "skill_id": "…", -- "rationale": "…" }, -- { "id": "u4", "kind": "skill_candidate", -- "rationale": "…", "draft": { "name": "…", -- "description": "…", -- "when_to_use": "…", -- "body": "…", -- "tags": ["…"] } } -- ] -- } -- -- team proposal — same shape plus: -- { "id": "u5", "kind": "roster_change", -- "op": "add"|"drop"|"rename", "slot": "…", "rationale": "…" } -- { "id": "u6", "kind": "mcp_bundle_change", -- "op": "add"|"drop", "bundle": "…", "rationale": "…" } -- -- `applied_items` is the array of `id`s that the reviewer approved; -- the applier only touches those. CREATE TABLE level_up_proposals ( id UUID PRIMARY KEY, workspace_id UUID NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE, -- Exactly one of these is set; enforced by the CHECK below. agent_id UUID REFERENCES agents(id) ON DELETE CASCADE, team_id UUID REFERENCES teams(id) ON DELETE CASCADE, -- 'pending' | 'applied' | 'rejected' | 'partial' (applied a subset) status TEXT NOT NULL DEFAULT 'pending', -- Full proposal JSONB (see header comment for shape). payload JSONB NOT NULL, -- Ids from payload.suggested_items[] that reviewer approved. applied_items TEXT[] NOT NULL DEFAULT '{}', -- Model used for the LLM analysis pass (audit trail). model TEXT, created_by UUID REFERENCES users(id) ON DELETE SET NULL, approved_by UUID REFERENCES users(id) ON DELETE SET NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), applied_at TIMESTAMPTZ, CONSTRAINT level_up_target_one CHECK ( (agent_id IS NOT NULL AND team_id IS NULL) OR (agent_id IS NULL AND team_id IS NOT NULL) ) ); CREATE INDEX level_up_workspace_idx ON level_up_proposals (workspace_id, created_at DESC); CREATE INDEX level_up_pending_idx ON level_up_proposals (status, created_at DESC) WHERE status = 'pending'; CREATE INDEX level_up_agent_idx ON level_up_proposals (agent_id, created_at DESC) WHERE agent_id IS NOT NULL; CREATE INDEX level_up_team_idx ON level_up_proposals (team_id, created_at DESC) WHERE team_id IS NOT NULL;