First commit of the Research + Loops feature arc. Schema only — routes,
runtime hooks, and the UI arrive in subsequent commits.
0030 — research_topics
Container entity with a small state machine (standby → processing →
reviewing → publishing → published). Owns runs via a nullable
topology_runs.research_topic_id FK, so all existing SSE/audit/gated-
approval plumbing surfaces without changes. Many-to-many join table
captures the role_slot the wizard assigns each agent ("lead", "critic",
"writer") so the canvas can group avatars sensibly.
0031 — loops
Durable recurring topology execution. graph + task_template pair with a
triggers JSONB (any of cron / on_completion / webhook, all can be on
simultaneously) and a repeat_policy (infinite / N iters / until). Every
iteration writes a topology_runs row with loop_id, iteration (1-indexed),
and parent_run_id chained back to N-1 — cross-iteration context comes
from that hop, no extra state store needed. Webhook auth is HMAC-SHA256
keyed by webhook_signing_key. Missed cron windows fire once and skip the
backlog (see comment header).
Both migrations only ADD tables/columns and use ON DELETE SET NULL for the
back-refs, so they're safe to run against prod without downtime. The
existing indexes on topology_runs keep serving legacy (non-research,
non-loop) runs unchanged.
Publish approval extension (approvals.kind for the reviewing → publishing
gate) comes as a separate migration in the publish-gate commit.
63 lines
3.1 KiB
SQL
63 lines
3.1 KiB
SQL
-- Research topics: user-scoped inquiry containers that group a set of agents
|
|
-- around a shared question and drive them toward a named outcome (spec,
|
|
-- prod_plan, roadmap, or paper). The status field is a small state machine
|
|
-- driven by the orchestrator + a manual publish gate (approvals; see 0032).
|
|
--
|
|
-- standby — created, agents assigned, not started
|
|
-- processing — running; each iteration writes to topology_runs
|
|
-- (with research_topic_id back-ref)
|
|
-- reviewing — orchestrator flipped it here on last run_completed;
|
|
-- a human approver still has to click Publish
|
|
-- publishing — approval landed; artifact assembly + release in flight
|
|
-- published — terminal
|
|
--
|
|
-- A topic OWNS runs (topology_runs.research_topic_id). Runs carry all the
|
|
-- durable execution state — the topic row is just the container + status.
|
|
|
|
CREATE TABLE research_topics (
|
|
id UUID PRIMARY KEY,
|
|
workspace_id UUID NOT NULL REFERENCES workspaces (id) ON DELETE CASCADE,
|
|
title TEXT NOT NULL,
|
|
-- LLM-refined description from the wizard: structured markdown with the
|
|
-- topic prompt + refined framing + key questions + success criteria.
|
|
description TEXT NOT NULL,
|
|
outcome_kind TEXT NOT NULL
|
|
CHECK (outcome_kind IN ('spec', 'prod_plan', 'roadmap', 'paper')),
|
|
status TEXT NOT NULL DEFAULT 'standby'
|
|
CHECK (status IN ('standby', 'processing', 'reviewing', 'publishing', 'published')),
|
|
created_by UUID NOT NULL REFERENCES users (id) ON DELETE RESTRICT,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
-- Set on the reviewing→publishing transition (after the publish approval
|
|
-- lands). Used by list queries that surface recent publishes.
|
|
published_at TIMESTAMPTZ
|
|
);
|
|
|
|
CREATE INDEX research_topics_workspace_idx
|
|
ON research_topics (workspace_id, updated_at DESC);
|
|
-- Speeds up the "topics in each status" sidebar bucket count.
|
|
CREATE INDEX research_topics_status_idx
|
|
ON research_topics (workspace_id, status);
|
|
|
|
-- Assigned agents (many-to-many). role_slot is a free-form label the wizard
|
|
-- captures ("lead", "critic", "writer") so the canvas can group avatars
|
|
-- when the topic has multiple agents playing different parts.
|
|
CREATE TABLE research_topic_agents (
|
|
topic_id UUID NOT NULL REFERENCES research_topics (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 (topic_id, agent_id)
|
|
);
|
|
CREATE INDEX research_topic_agents_agent_idx
|
|
ON research_topic_agents (agent_id);
|
|
|
|
-- Back-ref from durable runs to the topic they belong to. Nullable — runs
|
|
-- outside a research topic (chat, ad-hoc topology exec) leave this NULL and
|
|
-- the existing indexes keep serving them.
|
|
ALTER TABLE topology_runs
|
|
ADD COLUMN research_topic_id UUID REFERENCES research_topics (id) ON DELETE SET NULL;
|
|
CREATE INDEX topology_runs_research_topic_idx
|
|
ON topology_runs (research_topic_id, created_at DESC)
|
|
WHERE research_topic_id IS NOT NULL;
|