-- Mnemosyne Object Store Schema
-- PostgreSQL 16 + pgvector
-- See SCHEMA.md for full documentation.

CREATE EXTENSION IF NOT EXISTS vector;

-- 1.1 Sessions
CREATE TABLE sessions (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    external_id     TEXT UNIQUE NOT NULL,
    model           TEXT NOT NULL,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT now(),
    last_active_at  TIMESTAMPTZ NOT NULL DEFAULT now(),
    total_turns     INTEGER NOT NULL DEFAULT 0,
    total_objects   INTEGER NOT NULL DEFAULT 0,
    total_faults    INTEGER NOT NULL DEFAULT 0,
    total_micro_faults INTEGER NOT NULL DEFAULT 0,
    status          TEXT NOT NULL DEFAULT 'active',
    config          JSONB NOT NULL DEFAULT '{}'
);

CREATE INDEX idx_sessions_external ON sessions(external_id);
CREATE INDEX idx_sessions_active ON sessions(status) WHERE status = 'active';

-- 1.2 Semantic Objects
CREATE TABLE semantic_objects (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    session_id      UUID NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,

    -- Identity
    object_type     TEXT NOT NULL,
    source_tool     TEXT,
    source_key      TEXT,

    -- Multi-fidelity content
    content_full    TEXT NOT NULL,
    summary_detailed TEXT,
    summary_compact  TEXT,
    stub            TEXT NOT NULL,

    -- Declared losses
    losses_l1       JSONB DEFAULT '[]',
    losses_l2       JSONB DEFAULT '[]',
    can_answer_l1   JSONB DEFAULT '[]',
    can_answer_l2   JSONB DEFAULT '[]',
    fault_when      JSONB DEFAULT '[]',

    -- Entities and tags
    key_entities    JSONB DEFAULT '[]',
    tags            TEXT[] DEFAULT '{}',

    -- State
    current_fidelity INTEGER NOT NULL DEFAULT 0,
    pinned          BOOLEAN NOT NULL DEFAULT false,
    pin_reason      TEXT,

    -- Metrics
    created_at      TIMESTAMPTZ NOT NULL DEFAULT now(),
    last_accessed   TIMESTAMPTZ NOT NULL DEFAULT now(),
    access_count    INTEGER NOT NULL DEFAULT 0,
    fault_count     INTEGER NOT NULL DEFAULT 0,
    micro_fault_count INTEGER NOT NULL DEFAULT 0,

    -- Token counts
    tokens_l0       INTEGER NOT NULL DEFAULT 0,
    tokens_l1       INTEGER,
    tokens_l2       INTEGER,
    tokens_l3       INTEGER NOT NULL DEFAULT 0,

    -- Source range
    source_turn_start INTEGER,
    source_turn_end   INTEGER,

    -- Embedding
    embedding       vector(384) NOT NULL
);

CREATE INDEX idx_objects_session ON semantic_objects(session_id);
CREATE INDEX idx_objects_session_fidelity ON semantic_objects(session_id, current_fidelity);
CREATE INDEX idx_objects_session_type ON semantic_objects(session_id, object_type);
CREATE INDEX idx_objects_source_key ON semantic_objects(session_id, source_key)
    WHERE source_key IS NOT NULL;
CREATE INDEX idx_objects_created ON semantic_objects(session_id, created_at);
CREATE INDEX idx_objects_last_accessed ON semantic_objects(session_id, last_accessed);
CREATE INDEX idx_objects_tags ON semantic_objects USING GIN(tags);
CREATE INDEX idx_objects_embedding ON semantic_objects
    USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
CREATE INDEX idx_objects_content_fts ON semantic_objects
    USING GIN(to_tsvector('english', content_full));

-- 1.3 Object Relationships
CREATE TABLE object_relationships (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    session_id      UUID NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
    source_id       UUID NOT NULL REFERENCES semantic_objects(id) ON DELETE CASCADE,
    target_id       UUID NOT NULL REFERENCES semantic_objects(id) ON DELETE CASCADE,
    relationship    TEXT NOT NULL,
    metadata        JSONB DEFAULT '{}',
    created_at      TIMESTAMPTZ NOT NULL DEFAULT now(),

    UNIQUE(source_id, target_id, relationship)
);

CREATE INDEX idx_rels_source ON object_relationships(source_id);
CREATE INDEX idx_rels_target ON object_relationships(target_id);
CREATE INDEX idx_rels_session ON object_relationships(session_id);

-- 1.4 Fault History
CREATE TABLE fault_history (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    session_id      UUID NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
    object_id       UUID NOT NULL REFERENCES semantic_objects(id) ON DELETE CASCADE,
    fault_type      TEXT NOT NULL,
    turn_number     INTEGER NOT NULL,
    content_hash    TEXT NOT NULL,
    question        TEXT,
    answer          TEXT,
    answer_tokens   INTEGER,
    avoided_tokens  INTEGER,
    latency_ms      INTEGER,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX idx_faults_session ON fault_history(session_id);
CREATE INDEX idx_faults_object ON fault_history(object_id);
CREATE INDEX idx_faults_content_hash ON fault_history(content_hash);

-- 1.5 Fidelity Transitions
CREATE TABLE fidelity_transitions (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    session_id      UUID NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
    object_id       UUID NOT NULL REFERENCES semantic_objects(id) ON DELETE CASCADE,
    from_fidelity   INTEGER NOT NULL,
    to_fidelity     INTEGER NOT NULL,
    trigger         TEXT NOT NULL,
    turn_number     INTEGER NOT NULL,
    pressure_zone   TEXT,
    token_count     INTEGER,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX idx_transitions_session ON fidelity_transitions(session_id);
CREATE INDEX idx_transitions_object ON fidelity_transitions(object_id);

-- 1.6 Admission Scores
CREATE TABLE admission_scores (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    session_id      UUID NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
    object_id       UUID REFERENCES semantic_objects(id) ON DELETE SET NULL,
    admitted        BOOLEAN NOT NULL,
    score_total     REAL NOT NULL,
    score_type      REAL NOT NULL,
    score_novelty   REAL NOT NULL,
    score_utility   REAL NOT NULL,
    score_recency   REAL NOT NULL,
    threshold       REAL NOT NULL,
    content_preview TEXT,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX idx_admission_session ON admission_scores(session_id);
