-- Poimen Memory schema (M2.3, M2.4 spec) -- Tables: memory_node, memory_edge, memory_vector, failure_signature, memory_supersede -- Enable pgvector extension CREATE EXTENSION IF NOT EXISTS vector; -- Core memory node (sha256 = content identity, idempotent upsert key) CREATE TABLE IF NOT EXISTS memory_node ( id BIGSERIAL PRIMARY KEY, sha256 TEXT NOT NULL UNIQUE, level TEXT NOT NULL CHECK (level IN ('L0', 'L1', 'L2', 'R')), project TEXT NOT NULL, query_id TEXT, -- NULL at L2 and R; CHECK enforced below run_id TEXT NOT NULL, t INT NOT NULL, source TEXT, -- set at L0; source URI at R text TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), CONSTRAINT level_query_id_check CHECK ( (level IN ('L2', 'R') AND query_id IS NULL) OR (level NOT IN ('L2', 'R') AND query_id IS NOT NULL) ) ); CREATE INDEX idx_memory_node_project_level ON memory_node(project, level); CREATE INDEX idx_memory_node_sha256 ON memory_node(sha256); -- Memory edges (provenance graph: child → parent) CREATE TABLE IF NOT EXISTS memory_edge ( child_sha TEXT NOT NULL REFERENCES memory_node(sha256) ON DELETE CASCADE, parent_sha TEXT NOT NULL REFERENCES memory_node(sha256) ON DELETE CASCADE, PRIMARY KEY (child_sha, parent_sha) ); CREATE INDEX idx_memory_edge_parent ON memory_edge(parent_sha); -- Vector storage (one node can have multiple kinds: text + symptom) CREATE TABLE IF NOT EXISTS memory_vector ( node_sha TEXT NOT NULL REFERENCES memory_node(sha256) ON DELETE CASCADE, kind TEXT NOT NULL CHECK (kind IN ('text', 'symptom')), embedding vector(768) NOT NULL, PRIMARY KEY (node_sha, kind) ); -- Partial indexes per kind (literal predicate required for planner to use them) CREATE INDEX idx_memory_vector_text ON memory_vector USING hnsw (embedding vector_cosine_ops) WHERE kind = 'text'; CREATE INDEX idx_memory_vector_symptom ON memory_vector USING hnsw (embedding vector_cosine_ops) WHERE kind = 'symptom'; -- Exact-match failure signature tier (M3.7.7) CREATE TABLE IF NOT EXISTS failure_signature ( sig_sha TEXT PRIMARY KEY, -- hash of normalized signature node_sha TEXT NOT NULL REFERENCES memory_node(sha256) ON DELETE CASCADE, tool TEXT NOT NULL, -- 'github-actions' | 'kubectl' | 'npm' | ... raw TEXT NOT NULL, -- pre-normalisation, for display seen_count INT NOT NULL DEFAULT 1, last_seen TIMESTAMPTZ NOT NULL ); CREATE INDEX idx_failure_signature_tool ON failure_signature(tool); CREATE INDEX idx_failure_signature_node ON failure_signature(node_sha); -- Memory supersession (old lesson replaced by new one) CREATE TABLE IF NOT EXISTS memory_supersede ( old_sha TEXT NOT NULL REFERENCES memory_node(sha256) ON DELETE CASCADE, new_sha TEXT NOT NULL REFERENCES memory_node(sha256) ON DELETE CASCADE, reason TEXT, PRIMARY KEY (old_sha, new_sha) ); CREATE INDEX idx_memory_supersede_new ON memory_supersede(new_sha);