-- Schema RAG do projeto Jhonny (projeto MCP TypeScript em code/). -- Idempotente: seguro rodar múltiplas vezes (CREATE ... IF NOT EXISTS). -- Segue o padrão do banco irmão rag_tigre (schema tigre): um banco por sistema -- dentro do container compartilhado rag-hub-db, schema próprio. -- -- Este arquivo é o estado FINAL desejado do schema — inclui o que as -- migrations `002-*-search.sql` e `003-file-summary-embedding.sql` aplicaram -- num banco já existente. Num banco novo, rodar só este arquivo basta. -- -- O schema tem um hífen no nome ("jhonny-rag"), entao todos os identificadores -- de schema sao escapados com aspas duplas. CREATE EXTENSION IF NOT EXISTS vector; CREATE EXTENSION IF NOT EXISTS pg_trgm; CREATE SCHEMA IF NOT EXISTS "jhonny-rag"; CREATE TABLE IF NOT EXISTS "jhonny-rag".code_chunks ( id bigserial PRIMARY KEY, file_path text NOT NULL, content text NOT NULL, chunk_index int, embedding vector(768), content_hash text, file_mtime double precision, -- Faixa de linhas do trecho no arquivo original. É o que permite ao -- agente ler só a janela relevante em vez do arquivo inteiro. start_line int, end_line int, -- Nomes declarados no trecho, separados por espaço — o lado lexical -- (pg_trgm) da busca híbrida casa contra isto. symbols text, -- Módulo derivado do caminho relativo em code/ (ex: code/src/tools -> tools). module text, -- 'decl' | 'header' | 'window' (fallback por janela de linhas, usado fora -- de Swift/Python — será o caso dos arquivos .ts/.js deste projeto). kind text, updated_at timestamp DEFAULT now() ); -- HNSW, não ivfflat: com poucas centenas de chunks o ivfflat particiona o -- espaço em listas quase vazias e a busca com probes=1 varre quase nada -- (media das migrations 002 registra o recall baixo que isso causava). CREATE INDEX IF NOT EXISTS code_chunks_embedding_hnsw_idx ON "jhonny-rag".code_chunks USING hnsw (embedding vector_cosine_ops) WITH (m = 16, ef_construction = 64); -- Acelera a reindexação incremental (busca por file_path). CREATE INDEX IF NOT EXISTS idx_code_chunks_file_path ON "jhonny-rag".code_chunks (file_path); -- Lado lexical da busca híbrida. CREATE INDEX IF NOT EXISTS code_chunks_file_path_trgm_idx ON "jhonny-rag".code_chunks USING gin (file_path gin_trgm_ops); CREATE INDEX IF NOT EXISTS code_chunks_symbols_trgm_idx ON "jhonny-rag".code_chunks USING gin (symbols gin_trgm_ops); CREATE INDEX IF NOT EXISTS code_chunks_module_idx ON "jhonny-rag".code_chunks (module); -- Hash de conteúdo por arquivo, usado pelo indexador para pular arquivos -- que não mudaram desde a última rodada (reindexação incremental). CREATE TABLE IF NOT EXISTS "jhonny-rag".indexed_files ( file_path text PRIMARY KEY, content_hash text NOT NULL, updated_at timestamp DEFAULT now() ); -- Mapa de arquivos: 1 linha por arquivo. Responde "onde fica X" e "o que -- tem no módulo Y" sem trazer nenhum corpo de código. CREATE TABLE IF NOT EXISTS "jhonny-rag".file_index ( file_path text PRIMARY KEY, module text, main_type text, public_symbols text[], summary text, n_lines int, content_hash text, summary_embedding vector(768), updated_at timestamp DEFAULT now() ); CREATE INDEX IF NOT EXISTS file_index_module_idx ON "jhonny-rag".file_index (module); CREATE INDEX IF NOT EXISTS file_index_path_trgm_idx ON "jhonny-rag".file_index USING gin (file_path gin_trgm_ops); CREATE INDEX IF NOT EXISTS file_index_summary_hnsw_idx ON "jhonny-rag".file_index USING hnsw (summary_embedding vector_cosine_ops) WITH (m = 16, ef_construction = 64);