-- 018_tasks.up.sql
-- Elevate a chat session into a "task": a goal-structured unit of work with a
-- lifecycle status, an outcome, and a one-line summary — the first-class object
-- the task board and the live context panel render. See
-- plans/2026-07-11-goal-oriented-chat-control-panel.md.
--
-- entity_id links the session to its OWN entity (type 'task', registered in
-- seeds/ontology.yaml) so knowledge notes and involved-entity edges hang off
-- the existing relationships graph unchanged — get_relations and
-- get_entity_knowledge just work. Intentionally no hard FK (mirrors 017's
-- decoupling): a race between task-entity creation and the session insert must
-- not be able to break the session.

ALTER TABLE agent_sessions ADD COLUMN IF NOT EXISTS goal      TEXT NOT NULL DEFAULT '';
ALTER TABLE agent_sessions ADD COLUMN IF NOT EXISTS status    TEXT NOT NULL DEFAULT 'active';
ALTER TABLE agent_sessions ADD COLUMN IF NOT EXISTS outcome   TEXT;
ALTER TABLE agent_sessions ADD COLUMN IF NOT EXISTS summary   TEXT NOT NULL DEFAULT '';
ALTER TABLE agent_sessions ADD COLUMN IF NOT EXISTS entity_id UUID;

-- Ordered plan steps. A step is a described unit of work that maps to a
-- run/request_execution call (no fixed step enum, per general-gated-execution).
-- execution_id is the gated action a step runs, if any; its terminal status
-- auto-closes the step server-side.
CREATE TABLE IF NOT EXISTS session_plan_steps (
    id           UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    session_id   UUID NOT NULL REFERENCES agent_sessions(id) ON DELETE CASCADE,
    seq          INT  NOT NULL,
    title        TEXT NOT NULL,
    detail       TEXT NOT NULL DEFAULT '',
    status       TEXT NOT NULL DEFAULT 'pending',
                 -- pending | running | done | failed | skipped | blocked
    execution_id UUID,
    target_slug  TEXT,
    started_at   TIMESTAMPTZ,
    finished_at  TIMESTAMPTZ,
    created_at   TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_plan_steps_session ON session_plan_steps(session_id, seq);

-- Structured decisions the agent surfaces to the operator mid-task. context
-- carries { entities:[], options:[], why:"" } for the pinned question card.
CREATE TABLE IF NOT EXISTS session_questions (
    id          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    session_id  UUID NOT NULL REFERENCES agent_sessions(id) ON DELETE CASCADE,
    prompt      TEXT NOT NULL,
    context     JSONB NOT NULL DEFAULT '{}',
    status      TEXT NOT NULL DEFAULT 'open',   -- open | answered | dismissed
    answer      TEXT,
    created_at  TIMESTAMPTZ NOT NULL DEFAULT now(),
    answered_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_questions_session_open
    ON session_questions(session_id) WHERE status = 'open';
