-- Evolve topology_runs from a write-once result store into a DURABLE JOB table. -- A topology run becomes a first-class job with a lifecycle (queued -> running -> -- completed/failed/cancelled), a checkpoint of completed-step outputs (for -- crash-resumable long-horizon execution), and an event-journal offset. This -- reuses the agent-run lifecycle pattern (RunState + checkpoint CAS + run_events -- journal) without coupling to the chat-session FK that agent_runs requires. -- -- Back-compat: existing rows are finished "compare" results, so the new columns -- default to status='completed', kind='compare'. The result blob keeps living in -- `comparison`, which becomes nullable (a queued/running run has no result yet). ALTER TABLE topology_runs ALTER COLUMN comparison DROP NOT NULL, ADD COLUMN kind TEXT NOT NULL DEFAULT 'compare', ADD COLUMN status TEXT NOT NULL DEFAULT 'completed' CHECK (status IN ('queued', 'running', 'completed', 'failed', 'cancelled')), ADD COLUMN graph JSONB, ADD COLUMN checkpoint JSONB, ADD COLUMN error TEXT, ADD COLUMN last_event_id BIGINT NOT NULL DEFAULT 0, ADD COLUMN started_at TIMESTAMPTZ, ADD COLUMN finished_at TIMESTAMPTZ, ADD COLUMN updated_at TIMESTAMPTZ NOT NULL DEFAULT now(); -- The background worker claims the oldest queued job; index that scan. CREATE INDEX topology_runs_status_idx ON topology_runs (status, created_at);