-- Pegas Memory: PostgreSQL — источник истины -- Запускать в atom-db (:5434), БД content_atom (или отдельная БД alicorn) CREATE EXTENSION IF NOT EXISTS pg_trgm; CREATE EXTENSION IF NOT EXISTS btree_gin; -- ============================================================ -- ИСТОЧНИКИ -- ============================================================ CREATE TABLE IF NOT EXISTS pm_document ( id BIGSERIAL PRIMARY KEY, kind TEXT NOT NULL, -- web|pdf|epub|text|code_repo|manual uri TEXT, title TEXT, fetched_at TIMESTAMPTZ, content_hash TEXT, -- дедуп целого источника authority REAL DEFAULT 0.5, -- репутация источника meta JSONB DEFAULT '{}', created_at TIMESTAMPTZ DEFAULT now(), UNIQUE (uri) ); -- ============================================================ -- ЧАНКИ (сырые сегменты — доказательства, НЕ для retrieval напрямую) -- ============================================================ CREATE TABLE IF NOT EXISTS pm_chunk ( id BIGSERIAL PRIMARY KEY, doc_id BIGINT REFERENCES pm_document(id) ON DELETE CASCADE, seq INT, content TEXT NOT NULL, locator JSONB DEFAULT '{}', -- page/§/URL-якорь/строка created_at TIMESTAMPTZ DEFAULT now() ); CREATE INDEX IF NOT EXISTS pm_chunk_doc_idx ON pm_chunk (doc_id, seq); -- ============================================================ -- АТОМЫ ЗНАНИЯ (основная единица retrieval) -- ============================================================ CREATE TABLE IF NOT EXISTS pm_atom ( id BIGSERIAL PRIMARY KEY, type TEXT NOT NULL, -- text|definition|logical_rule|code|table|fact claim TEXT, -- короткое каноническое утверждение content TEXT NOT NULL, -- полное значение (для code — исходник/сигнатура) content_hash TEXT NOT NULL, -- дедуп confidence REAL DEFAULT 0.5, status TEXT DEFAULT 'candidate', -- candidate|verified|stale|contested doc_id BIGINT REFERENCES pm_document(id) ON DELETE SET NULL, locator JSONB DEFAULT '{}', metadata JSONB DEFAULT '{}', -- logical_rule: pattern/conclusion; code: repo/path created_at TIMESTAMPTZ DEFAULT now(), updated_at TIMESTAMPTZ DEFAULT now() ); CREATE UNIQUE INDEX IF NOT EXISTS pm_atom_hash_idx ON pm_atom (content_hash); CREATE INDEX IF NOT EXISTS pm_atom_type_status_idx ON pm_atom (type, status); CREATE INDEX IF NOT EXISTS pm_atom_claim_idx ON pm_atom USING gin (claim gin_trgm_ops); -- ============================================================ -- СВЯЗИ МЕЖДУ АТОМАМИ (граф → Memgraph) -- ============================================================ CREATE TABLE IF NOT EXISTS pm_atom_link ( id BIGSERIAL PRIMARY KEY, src BIGINT REFERENCES pm_atom(id) ON DELETE CASCADE, dst BIGINT REFERENCES pm_atom(id) ON DELETE CASCADE, kind TEXT NOT NULL, -- inference|cause|reference|contradicts|depends_on|calls|defines confidence REAL DEFAULT 0.5, source TEXT, -- manual|extraction|inference inferred BOOLEAN DEFAULT false, -- выведено инференцией (не явно) created_at TIMESTAMPTZ DEFAULT now(), UNIQUE (src, dst, kind) ); CREATE INDEX IF NOT EXISTS pm_link_src_idx ON pm_atom_link (src); CREATE INDEX IF NOT EXISTS pm_link_dst_idx ON pm_atom_link (dst); -- ============================================================ -- ЦИТИРОВАНИЕ (доказательная база) -- ============================================================ CREATE TABLE IF NOT EXISTS pm_citation ( id BIGSERIAL PRIMARY KEY, atom_id BIGINT REFERENCES pm_atom(id) ON DELETE CASCADE, doc_id BIGINT REFERENCES pm_document(id) ON DELETE CASCADE, locator JSONB DEFAULT '{}', quoted_text TEXT, created_at TIMESTAMPTZ DEFAULT now() ); CREATE INDEX IF NOT EXISTS pm_citation_atom_idx ON pm_citation (atom_id); -- ============================================================ -- СИМВОЛЫ КОДА (tree-sitter) -- ============================================================ CREATE TABLE IF NOT EXISTS pm_code_symbol ( id BIGSERIAL PRIMARY KEY, repo TEXT, path TEXT, language TEXT, symbol_name TEXT, kind TEXT, -- function|class|method|type|const signature TEXT, -- индексируется для retrieval body_hash TEXT, -- content-addressed line_start INT, line_end INT, created_at TIMESTAMPTZ DEFAULT now() ); CREATE INDEX IF NOT EXISTS pm_symbol_name_idx ON pm_code_symbol USING gin (symbol_name gin_trgm_ops); CREATE INDEX IF NOT EXISTS pm_symbol_lang_idx ON pm_code_symbol (language, kind); -- ============================================================ -- ЗАВИСИМОСТИ КОДА (граф кода: calls/imports/inherits) -- ============================================================ CREATE TABLE IF NOT EXISTS pm_code_dependency ( id BIGSERIAL PRIMARY KEY, repo TEXT, path TEXT, language TEXT, src TEXT, -- имя символа-источника dst TEXT, -- имя цели kind TEXT NOT NULL, -- calls|imports|inherits created_at TIMESTAMPTZ DEFAULT now(), UNIQUE (repo, path, src, dst, kind) ); CREATE INDEX IF NOT EXISTS pm_code_dep_src_idx ON pm_code_dependency (src); CREATE INDEX IF NOT EXISTS pm_code_dep_kind_idx ON pm_code_dependency (kind); -- ============================================================ -- ПАМЯТЬ АГЕНТА (episodic) — ОТДЕЛЬНО от базы знаний -- ============================================================ CREATE TABLE IF NOT EXISTS pm_episodic_trace ( id BIGSERIAL PRIMARY KEY, session_id TEXT, step INT, kind TEXT, -- plan|action|observation|reflection content TEXT NOT NULL, created_at TIMESTAMPTZ DEFAULT now() ); CREATE INDEX IF NOT EXISTS pm_episodic_session_idx ON pm_episodic_trace (session_id, step); -- ============================================================ -- ПРОБЕЛЫ ДЛЯ ИССЛЕДОВАНИЯ -- ============================================================ CREATE TABLE IF NOT EXISTS pm_research_gap ( id BIGSERIAL PRIMARY KEY, question TEXT NOT NULL, reason TEXT, -- low_coverage|low_confidence|stale|contested|user_query priority REAL DEFAULT 0.5, status TEXT DEFAULT 'open', -- open|researching|resolved|dismissed created_at TIMESTAMPTZ DEFAULT now() ); -- ============================================================ -- OUTBOX (CDC → Qdrant + Memgraph) -- ============================================================ CREATE TABLE IF NOT EXISTS pm_outbox ( id BIGSERIAL PRIMARY KEY, entity_type TEXT NOT NULL, -- atom|link|doc entity_id BIGINT NOT NULL, op TEXT NOT NULL, -- upsert|delete created_at TIMESTAMPTZ DEFAULT now(), processed BOOLEAN DEFAULT false ); CREATE INDEX IF NOT EXISTS pm_outbox_pending_idx ON pm_outbox (processed, id);