From fd59c6de11e5865317d484ae317cb498f8d2556b Mon Sep 17 00:00:00 2001 From: rock Date: Tue, 15 Sep 2026 17:29:53 +0900 Subject: [PATCH] revert: restore memory_entity/memory_edge table names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit knowledge_* namespace reserved for future agentic learning tables. memory_* namespace used for facts, events, and entity graph. - knowledge_node → memory_entity (reverted) - knowledge_edge → memory_edge (reverted) - Old provenance DAG (child_sha/parent_sha) renamed to memory_edge_provenance via migration 009 - Kept: runtime queries in versioning.rs, UUID casts, init_schema additions --- crates/mem-cli/src/compaction.rs | 14 +++--- crates/mem-cli/src/handlers/agent_handler.rs | 2 +- .../mem-cli/src/handlers/rebuild_handler.rs | 4 +- .../mem-cli/src/handlers/unified_synthesis.rs | 2 +- crates/mem-cli/src/http_server.rs | 8 ++-- crates/mem-cli/src/ingest_worker.rs | 10 ++-- crates/mem-cli/src/metrics.rs | 8 ++-- .../mem-cli/src/query/bfs_graph_traversal.rs | 6 +-- .../mem-cli/src/query/community_detector.rs | 4 +- crates/mem-cli/src/query/faceted_search.rs | 8 ++-- crates/mem-cli/src/query/path_finder.rs | 2 +- .../mem-cli/src/query/semantic_retriever.rs | 8 ++-- crates/mem-core/src/edge.rs | 6 +-- crates/mem-ingest/src/grm_retriever.rs | 4 +- .../migrations/003_temporal_graph_phase1.sql | 46 +++++++++--------- .../mem-store/migrations/004_auth_schema.sql | 48 +++++++++---------- .../migrations/005_workflows_schema.sql | 4 +- .../006_phase4_community_detection.sql | 2 +- .../migrations/007_versioning_schema.sql | 32 ++++++------- .../migrations/008_phase3_compaction.sql | 14 +++--- .../009_temporal_edge_migration.sql | 44 ++++++++++------- crates/mem-store/src/audit_logger.rs | 8 ++-- crates/mem-store/src/db_repo.rs | 16 +++---- crates/mem-store/src/schema.rs | 16 +++---- crates/mem-store/src/versioning.rs | 12 ++--- tests/it_phase7_gate.rs | 10 ++-- 26 files changed, 175 insertions(+), 163 deletions(-) diff --git a/crates/mem-cli/src/compaction.rs b/crates/mem-cli/src/compaction.rs index 6229aed..328ede1 100644 --- a/crates/mem-cli/src/compaction.rs +++ b/crates/mem-cli/src/compaction.rs @@ -58,7 +58,7 @@ impl Tier1Compactor { let rows = sqlx::query( r#" SELECT array_agg(id ORDER BY created_at) - FROM knowledge_edge + FROM memory_edge WHERE deleted_at IS NULL GROUP BY source_id, target_id, relation_type, md5(fact) HAVING COUNT(*) > 1 @@ -91,7 +91,7 @@ impl Tier1Compactor { let execute_fn = async move { for (_master, duplicate) in duplicates { sqlx::query( - "UPDATE knowledge_edge SET deleted_at = NOW() WHERE id = $1" + "UPDATE memory_edge SET deleted_at = NOW() WHERE id = $1" ) .bind(&duplicate) .execute(&pool) @@ -126,7 +126,7 @@ impl Tier1Compactor { let row_count: (i64,) = sqlx::query_as( &format!( r#" - SELECT COUNT(*) FROM knowledge_edge + SELECT COUNT(*) FROM memory_edge WHERE fact_invalid_at IS NOT NULL AND fact_invalid_at < {} AND deleted_at IS NULL @@ -149,7 +149,7 @@ impl Tier1Compactor { sqlx::query( &format!( r#" - UPDATE knowledge_edge + UPDATE memory_edge SET deleted_at = NOW() WHERE fact_invalid_at IS NOT NULL AND fact_invalid_at < {} @@ -207,8 +207,8 @@ impl Tier2Compactor { let rows = sqlx::query( r#" SELECT a.id, b.id, a.fact, b.fact - FROM knowledge_edge a - JOIN knowledge_edge b ON a.source_id = b.source_id + FROM memory_edge a + JOIN memory_edge b ON a.source_id = b.source_id AND a.target_id = b.target_id AND a.relation_type = b.relation_type AND a.id < b.id @@ -279,7 +279,7 @@ Respond with JSON: {{"confidence": 0.0-1.0}} where 1.0 means identical meaning." let edge_id = edge_b_id.to_string(); let execute_fn = async move { sqlx::query( - "UPDATE knowledge_edge SET deleted_at = NOW() WHERE id = $1" + "UPDATE memory_edge SET deleted_at = NOW() WHERE id = $1" ) .bind(&edge_id) .execute(&pool) diff --git a/crates/mem-cli/src/handlers/agent_handler.rs b/crates/mem-cli/src/handlers/agent_handler.rs index 59baf27..ceb1e52 100644 --- a/crates/mem-cli/src/handlers/agent_handler.rs +++ b/crates/mem-cli/src/handlers/agent_handler.rs @@ -158,7 +158,7 @@ pub async fn register_agent_handler( // Temporal activities will: // 1. Persist agent state to temporal_workflow_links table // 2. Execute LLMInferenceActivity (call LLM via api.riotpiao.com/v1/chat/completions) - // 3. Store reasoning traces to knowledge_node/knowledge_edge + // 3. Store reasoning traces to memory_entity/memory_edge if let Some(jwt) = crate::handlers::extract_jwt_token(&req) { let client = SynthesisClient::new( "https://api.riotpiao.com".to_string(), diff --git a/crates/mem-cli/src/handlers/rebuild_handler.rs b/crates/mem-cli/src/handlers/rebuild_handler.rs index 9fade2d..96fa834 100644 --- a/crates/mem-cli/src/handlers/rebuild_handler.rs +++ b/crates/mem-cli/src/handlers/rebuild_handler.rs @@ -199,7 +199,7 @@ async fn compute_state_checksum(pool: &PgPool, project: &str) -> Result = sqlx::query_as::<_, IdRow>( - "SELECT id FROM knowledge_node WHERE project_id = $1 ORDER BY id" + "SELECT id FROM memory_entity WHERE project_id = $1 ORDER BY id" ) .bind(project) .fetch_all(pool) @@ -211,7 +211,7 @@ async fn compute_state_checksum(pool: &PgPool, project: &str) -> Result = sqlx::query_as::<_, IdRow>( - "SELECT id FROM knowledge_edge WHERE project_id = $1 ORDER BY id" + "SELECT id FROM memory_edge WHERE project_id = $1 ORDER BY id" ) .bind(project) .fetch_all(pool) diff --git a/crates/mem-cli/src/handlers/unified_synthesis.rs b/crates/mem-cli/src/handlers/unified_synthesis.rs index d7a93cd..96940f9 100644 --- a/crates/mem-cli/src/handlers/unified_synthesis.rs +++ b/crates/mem-cli/src/handlers/unified_synthesis.rs @@ -200,7 +200,7 @@ pub async fn unified_synthesis_handler( } // Reasoning via Temporal workflow - // Temporal activity calls LLMInferenceActivity + persists results to knowledge_node/knowledge_edge + // Temporal activity calls LLMInferenceActivity + persists results to memory_entity/memory_edge if body.reason_query { reasoning = match execute_reasoning_workflow( &synthesis_client, diff --git a/crates/mem-cli/src/http_server.rs b/crates/mem-cli/src/http_server.rs index 6b3b7e6..0ce415b 100644 --- a/crates/mem-cli/src/http_server.rs +++ b/crates/mem-cli/src/http_server.rs @@ -383,11 +383,11 @@ pub async fn start_server(port: u16, api_key: String, database_url: &str) -> Res loop { interval.tick().await; // O5: Table row counts - if let Ok(row) = sqlx::query_as::<_, (i64,)>("SELECT COUNT(*) FROM knowledge_node") + if let Ok(row) = sqlx::query_as::<_, (i64,)>("SELECT COUNT(*) FROM memory_entity") .fetch_one(&stats_pool).await { crate::metrics::DB_TABLE_ENTITY_ROWS.set(row.0 as u64); } - if let Ok(row) = sqlx::query_as::<_, (i64,)>("SELECT COUNT(*) FROM knowledge_edge") + if let Ok(row) = sqlx::query_as::<_, (i64,)>("SELECT COUNT(*) FROM memory_edge") .fetch_one(&stats_pool).await { crate::metrics::DB_TABLE_EDGE_ROWS.set(row.0 as u64); } @@ -1454,7 +1454,7 @@ async fn query_temporal_graph( ) -> anyhow::Result { // Step 1: Find entities (order by name for deterministic results) let entities_rows: Vec<(String, String, String)> = sqlx::query_as( - "SELECT id::TEXT, name, entity_type FROM knowledge_node WHERE project_id = $1 LIMIT $2" + "SELECT id::TEXT, name, entity_type FROM memory_entity WHERE project_id = $1 LIMIT $2" ) .bind(¶ms.project) .bind(params.limit as i32) @@ -1470,7 +1470,7 @@ async fn query_temporal_graph( for (entity_id, _name, _type_str) in &entities_rows { let entity_edges: Vec<(String, String, String, String, f32, Option>, Option>)> = sqlx::query_as( - "SELECT id::TEXT, target_id::TEXT, relation_type, fact, confidence, t_valid, t_invalid FROM knowledge_edge WHERE project_id = $1 AND source_id = $2::UUID" + "SELECT id::TEXT, target_id::TEXT, relation_type, fact, confidence, t_valid, t_invalid FROM memory_edge WHERE project_id = $1 AND source_id = $2::UUID" ) .bind(¶ms.project) .bind(entity_id) diff --git a/crates/mem-cli/src/ingest_worker.rs b/crates/mem-cli/src/ingest_worker.rs index be1dee7..2e7b8dc 100644 --- a/crates/mem-cli/src/ingest_worker.rs +++ b/crates/mem-cli/src/ingest_worker.rs @@ -384,14 +384,14 @@ async fn save_entity_to_db(pool: &PgPool, entity: &mem_core::entity::Entity) -> let t_created_str = entity.t_created.to_string(); sqlx::query( - "INSERT INTO knowledge_node (id, project_id, name, entity_type, description, t_created, t_updated, confidence) + "INSERT INTO memory_entity (id, project_id, name, entity_type, description, t_created, t_updated, confidence) VALUES ($1::UUID, $2, $3, $4, $5, $6::TIMESTAMPTZ, $7::TIMESTAMPTZ, $8) ON CONFLICT (project_id, name) DO UPDATE SET entity_type = EXCLUDED.entity_type, - description = COALESCE(NULLIF(EXCLUDED.description, ''), knowledge_node.description), + description = COALESCE(NULLIF(EXCLUDED.description, ''), memory_entity.description), t_updated = NOW(), - confidence = GREATEST(knowledge_node.confidence, EXCLUDED.confidence), - source_count = knowledge_node.source_count + 1" + confidence = GREATEST(memory_entity.confidence, EXCLUDED.confidence), + source_count = memory_entity.source_count + 1" ) .bind(&entity.id) .bind(&entity.project_id) @@ -445,7 +445,7 @@ async fn save_edge_with_logging( async fn save_edge_to_db(pool: &PgPool, edge: &mem_core::edge::Edge) -> Result<()> { // Try temporal schema first (id, project_id, source_entity_id, etc) let result = sqlx::query( - "INSERT INTO knowledge_edge (id, project_id, source_id, target_id, relation_type, fact, t_valid, t_invalid, t_created, confidence) + "INSERT INTO memory_edge (id, project_id, source_id, target_id, relation_type, fact, t_valid, t_invalid, t_created, confidence) VALUES ($1::UUID, $2, $3::UUID, $4::UUID, $5, $6, $7::TIMESTAMPTZ, $8::TIMESTAMPTZ, $9::TIMESTAMPTZ, $10) ON CONFLICT (id) DO NOTHING" ) diff --git a/crates/mem-cli/src/metrics.rs b/crates/mem-cli/src/metrics.rs index 7cbccb1..61a872d 100644 --- a/crates/mem-cli/src/metrics.rs +++ b/crates/mem-cli/src/metrics.rs @@ -274,9 +274,9 @@ pub static WRITE_BYTES_TOTAL: Counter = Counter::new( "memory_write_bytes_total", "Total bytes written to storage"); pub static DB_ENTITY_COUNT: Gauge = Gauge::new( - "memory_db_entity_count", "Current entity count in knowledge_node table"); + "memory_db_entity_count", "Current entity count in memory_entity table"); pub static DB_EDGE_COUNT: Gauge = Gauge::new( - "memory_db_edge_count", "Current edge count in knowledge_edge table"); + "memory_db_edge_count", "Current edge count in memory_edge table"); pub static DB_CHUNK_COUNT: Gauge = Gauge::new( "memory_db_chunk_count", "Current chunk count in memory_chunks table"); @@ -436,9 +436,9 @@ pub static DB_TRANSACTION_DURATION: Lazy = Lazy::new(|| // Table-specific row counts (updated periodically) pub static DB_TABLE_ENTITY_ROWS: Gauge = Gauge::new( - "memory_db_table_entity_rows", "Rows in knowledge_node table"); + "memory_db_table_entity_rows", "Rows in memory_entity table"); pub static DB_TABLE_EDGE_ROWS: Gauge = Gauge::new( - "memory_db_table_edge_rows", "Rows in knowledge_edge table"); + "memory_db_table_edge_rows", "Rows in memory_edge table"); pub static DB_TABLE_CHUNK_ROWS: Gauge = Gauge::new( "memory_db_table_chunk_rows", "Rows in memory_chunks table"); diff --git a/crates/mem-cli/src/query/bfs_graph_traversal.rs b/crates/mem-cli/src/query/bfs_graph_traversal.rs index 3a3d060..02eaf78 100644 --- a/crates/mem-cli/src/query/bfs_graph_traversal.rs +++ b/crates/mem-cli/src/query/bfs_graph_traversal.rs @@ -1,6 +1,6 @@ /// BFS graph traversal with PostgreSQL queries. /// -/// Performs breadth-first search on knowledge_node + knowledge_edge tables, +/// Performs breadth-first search on memory_entity + memory_edge tables, /// returning a subgraph for visualization. use std::collections::{HashMap, VecDeque}; @@ -215,7 +215,7 @@ impl BfsGraphTraversal { async fn load_entity(&self, id: &str) -> Result)>, String> { let query = r#" SELECT id, entity_type, name, description - FROM knowledge_node + FROM memory_entity WHERE id = $1 AND deleted_at IS NULL LIMIT 1; "#; @@ -239,7 +239,7 @@ impl BfsGraphTraversal { async fn load_edges_from(&self, source_id: &str, limit: usize) -> Result, String> { let query = r#" SELECT id, target_id, source_id, relation_type, fact, strength - FROM knowledge_edge + FROM memory_edge WHERE source_id = $1 AND t_expired IS NULL AND t_invalid IS NULL ORDER BY strength DESC LIMIT $2; diff --git a/crates/mem-cli/src/query/community_detector.rs b/crates/mem-cli/src/query/community_detector.rs index 70b5433..15a2f94 100644 --- a/crates/mem-cli/src/query/community_detector.rs +++ b/crates/mem-cli/src/query/community_detector.rs @@ -228,7 +228,7 @@ impl CommunityDetector { async fn fetch_graph(&self, _project_id: Option<&str>) -> Result<(Vec, Vec), String> { // Fetch entities let entities = sqlx::query_as::<_, (String,)>( - "SELECT DISTINCT id FROM knowledge_node WHERE deleted_at IS NULL" + "SELECT DISTINCT id FROM memory_entity WHERE deleted_at IS NULL" ) .fetch_all(&self.pool) .await @@ -240,7 +240,7 @@ impl CommunityDetector { // Fetch edges with confidence as weight let edges = sqlx::query_as::<_, (String, String, f32)>( "SELECT source_entity_id, target_entity_id, confidence - FROM knowledge_edge + FROM memory_edge WHERE fact_invalid_at IS NULL AND deleted_at IS NULL" ) .fetch_all(&self.pool) diff --git a/crates/mem-cli/src/query/faceted_search.rs b/crates/mem-cli/src/query/faceted_search.rs index d3886bb..4d5d1c7 100644 --- a/crates/mem-cli/src/query/faceted_search.rs +++ b/crates/mem-cli/src/query/faceted_search.rs @@ -108,7 +108,7 @@ impl FacetedSearch { // Get entity types let entity_types = sqlx::query_as::<_, (String, i64)>( "SELECT entity_type, COUNT(*) as cnt - FROM knowledge_node + FROM memory_entity WHERE deleted_at IS NULL GROUP BY entity_type ORDER BY cnt DESC @@ -128,7 +128,7 @@ impl FacetedSearch { // Get total count let total_count: (i64,) = sqlx::query_as( - "SELECT COUNT(*) FROM knowledge_node WHERE deleted_at IS NULL" + "SELECT COUNT(*) FROM memory_entity WHERE deleted_at IS NULL" ) .fetch_one(&self.pool) .await @@ -212,7 +212,7 @@ impl FacetedSearch { // Get relation types let relation_types = sqlx::query_as::<_, (String, i64)>( "SELECT relation_type, COUNT(*) as cnt - FROM knowledge_edge + FROM memory_edge WHERE fact_invalid_at IS NULL AND deleted_at IS NULL GROUP BY relation_type ORDER BY cnt DESC @@ -232,7 +232,7 @@ impl FacetedSearch { // Get total count let total_count: (i64,) = sqlx::query_as( - "SELECT COUNT(*) FROM knowledge_edge WHERE fact_invalid_at IS NULL AND deleted_at IS NULL" + "SELECT COUNT(*) FROM memory_edge WHERE fact_invalid_at IS NULL AND deleted_at IS NULL" ) .fetch_one(&self.pool) .await diff --git a/crates/mem-cli/src/query/path_finder.rs b/crates/mem-cli/src/query/path_finder.rs index fabf908..72edd53 100644 --- a/crates/mem-cli/src/query/path_finder.rs +++ b/crates/mem-cli/src/query/path_finder.rs @@ -382,7 +382,7 @@ impl PathFinder { async fn fetch_neighbors(&self, entity_id: &str) -> Result, String> { let edges = sqlx::query_as::<_, (String, String, String, f32)>( "SELECT source_entity_id, target_entity_id, relation_type, confidence - FROM knowledge_edge + FROM memory_edge WHERE (source_entity_id = $1 OR target_entity_id = $1) AND fact_invalid_at IS NULL AND deleted_at IS NULL" diff --git a/crates/mem-cli/src/query/semantic_retriever.rs b/crates/mem-cli/src/query/semantic_retriever.rs index a6791c7..3448732 100644 --- a/crates/mem-cli/src/query/semantic_retriever.rs +++ b/crates/mem-cli/src/query/semantic_retriever.rs @@ -117,7 +117,7 @@ impl SemanticRetriever { "SELECT id, name, entity_type, 1 - (embedding <=> $1::vector) as similarity_score, metadata - FROM knowledge_node + FROM memory_entity WHERE deleted_at IS NULL AND (1 - (embedding <=> $1::vector)) > $2 AND (entity_type = COALESCE($3, entity_type)) @@ -191,9 +191,9 @@ impl SemanticRetriever { src.name, tgt.name, e.relation_type, e.fact, 1 - (e.embedding <=> $1::vector) as similarity_score, e.confidence - FROM knowledge_edge e - JOIN knowledge_node src ON e.source_entity_id = src.id - JOIN knowledge_node tgt ON e.target_entity_id = tgt.id + FROM memory_edge e + JOIN memory_entity src ON e.source_entity_id = src.id + JOIN memory_entity tgt ON e.target_entity_id = tgt.id WHERE e.fact_invalid_at IS NULL AND e.deleted_at IS NULL AND (e.relation_type = COALESCE($2, e.relation_type)) diff --git a/crates/mem-core/src/edge.rs b/crates/mem-core/src/edge.rs index ead00be..a155a68 100644 --- a/crates/mem-core/src/edge.rs +++ b/crates/mem-core/src/edge.rs @@ -51,8 +51,8 @@ pub struct Edge { pub project_id: String, // Relationship - pub source_entity_id: String, // FK to knowledge_node - pub target_entity_id: String, // FK to knowledge_node + pub source_entity_id: String, // FK to memory_entity + pub target_entity_id: String, // FK to memory_entity pub relation_type: String, pub fact: String, pub fact_embedding: Option>, @@ -71,7 +71,7 @@ pub struct Edge { // Provenance pub source_episode_id: Option, // FK to memory_node - pub invalidated_by: Option, // FK to knowledge_edge.id + pub invalidated_by: Option, // FK to memory_edge.id // Contradiction handling pub contradiction_status: ContradictionStatus, diff --git a/crates/mem-ingest/src/grm_retriever.rs b/crates/mem-ingest/src/grm_retriever.rs index a6fffec..d6a85a1 100644 --- a/crates/mem-ingest/src/grm_retriever.rs +++ b/crates/mem-ingest/src/grm_retriever.rs @@ -204,7 +204,7 @@ impl GraphContextRetriever for PostgresGrmRetriever { debug!("PostgresGrmRetriever: get_entity_context({})", entity_name); // TODO (Phase 2.5): Implement actual database query - // SELECT id, name, summary FROM knowledge_node + // SELECT id, name, summary FROM memory_entity // WHERE name_embedding <-> query_embedding < (1 - threshold) // LIMIT max_entity_context_size @@ -263,7 +263,7 @@ impl GraphContextRetriever for PostgresGrmRetriever { debug!("PostgresGrmRetriever: get_fact_context({})", fact_text); // TODO (Phase 2.5): Implement actual database query - // SELECT COUNT(*) FROM knowledge_edge + // SELECT COUNT(*) FROM memory_edge // WHERE source_id = ? AND target_id = ? // AND fact_embedding <-> query_embedding < (1 - similarity_threshold) // AND (t_invalid IS NULL OR t_invalid > NOW()) diff --git a/crates/mem-store/migrations/003_temporal_graph_phase1.sql b/crates/mem-store/migrations/003_temporal_graph_phase1.sql index 0f78ba0..ac22a6a 100644 --- a/crates/mem-store/migrations/003_temporal_graph_phase1.sql +++ b/crates/mem-store/migrations/003_temporal_graph_phase1.sql @@ -53,7 +53,7 @@ CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_community_fts -- ============================================ -- STEP 3: Create entity table -- ============================================ -CREATE TABLE IF NOT EXISTS knowledge_node ( +CREATE TABLE IF NOT EXISTS memory_entity ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), project_id VARCHAR(255) NOT NULL, name VARCHAR(500) NOT NULL, @@ -75,40 +75,40 @@ CREATE TABLE IF NOT EXISTS knowledge_node ( ); CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_entity_project - ON knowledge_node(project_id); + ON memory_entity(project_id); CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_entity_name_embedding - ON knowledge_node USING hnsw (name_embedding vector_cosine_ops) + ON memory_entity USING hnsw (name_embedding vector_cosine_ops) WITH (m = 16, ef_construction = 200); CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_entity_summary_embedding - ON knowledge_node USING hnsw (summary_embedding vector_cosine_ops) + ON memory_entity USING hnsw (summary_embedding vector_cosine_ops) WITH (m = 16, ef_construction = 200); CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_entity_type - ON knowledge_node(project_id, entity_type); + ON memory_entity(project_id, entity_type); CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_entity_community - ON knowledge_node(community_id) + ON memory_entity(community_id) WHERE community_id IS NOT NULL; CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_entity_active - ON knowledge_node(project_id) + ON memory_entity(project_id) WHERE t_expired IS NULL; CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_entity_fts - ON knowledge_node USING gin( + ON memory_entity USING gin( to_tsvector('english', COALESCE(name, '') || ' ' || COALESCE(summary, '')) ); -- ============================================ -- STEP 4: Create edge (relationship) table -- ============================================ -CREATE TABLE IF NOT EXISTS knowledge_edge ( +CREATE TABLE IF NOT EXISTS memory_edge ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), project_id VARCHAR(255) NOT NULL, - source_entity_id UUID NOT NULL REFERENCES knowledge_node(id) ON DELETE CASCADE, - target_entity_id UUID NOT NULL REFERENCES knowledge_node(id) ON DELETE CASCADE, + source_entity_id UUID NOT NULL REFERENCES memory_entity(id) ON DELETE CASCADE, + target_entity_id UUID NOT NULL REFERENCES memory_entity(id) ON DELETE CASCADE, relation_type VARCHAR(100) NOT NULL, fact TEXT NOT NULL, fact_embedding VECTOR(768), @@ -123,7 +123,7 @@ CREATE TABLE IF NOT EXISTS knowledge_edge ( -- Provenance source_episode_id BIGINT REFERENCES memory_node(id) ON DELETE SET NULL, - invalidated_by UUID REFERENCES knowledge_edge(id) ON DELETE SET NULL, + invalidated_by UUID REFERENCES memory_edge(id) ON DELETE SET NULL, -- Contradiction handling contradiction_status VARCHAR(20) DEFAULT 'active' @@ -141,34 +141,34 @@ CREATE TABLE IF NOT EXISTS knowledge_edge ( ); CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_edge_project - ON knowledge_edge(project_id); + ON memory_edge(project_id); CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_edge_source - ON knowledge_edge(source_entity_id); + ON memory_edge(source_entity_id); CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_edge_target - ON knowledge_edge(target_entity_id); + ON memory_edge(target_entity_id); CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_edge_entity_pair - ON knowledge_edge(source_entity_id, target_entity_id); + ON memory_edge(source_entity_id, target_entity_id); CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_edge_embedding - ON knowledge_edge USING hnsw (fact_embedding vector_cosine_ops) + ON memory_edge USING hnsw (fact_embedding vector_cosine_ops) WITH (m = 16, ef_construction = 200); CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_edge_validity - ON knowledge_edge(t_valid, t_invalid) + ON memory_edge(t_valid, t_invalid) WHERE t_expired IS NULL; CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_edge_active - ON knowledge_edge(project_id, contradiction_status) + ON memory_edge(project_id, contradiction_status) WHERE t_expired IS NULL AND contradiction_status = 'active'; CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_edge_fts - ON knowledge_edge USING gin(to_tsvector('english', fact)); + ON memory_edge USING gin(to_tsvector('english', fact)); CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_edge_relation - ON knowledge_edge(project_id, relation_type); + ON memory_edge(project_id, relation_type); -- ============================================ -- STEP 5: Compaction audit log @@ -202,8 +202,8 @@ CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_compaction_project CREATE TABLE IF NOT EXISTS contradiction_review_queue ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), project_id VARCHAR(255) NOT NULL, - new_edge_id UUID NOT NULL REFERENCES knowledge_edge(id) ON DELETE CASCADE, - existing_edge_id UUID NOT NULL REFERENCES knowledge_edge(id) ON DELETE CASCADE, + new_edge_id UUID NOT NULL REFERENCES memory_edge(id) ON DELETE CASCADE, + existing_edge_id UUID NOT NULL REFERENCES memory_edge(id) ON DELETE CASCADE, confidence FLOAT NOT NULL, explanation TEXT, queued_at TIMESTAMPTZ DEFAULT NOW(), diff --git a/crates/mem-store/migrations/004_auth_schema.sql b/crates/mem-store/migrations/004_auth_schema.sql index b1c2752..0423e40 100644 --- a/crates/mem-store/migrations/004_auth_schema.sql +++ b/crates/mem-store/migrations/004_auth_schema.sql @@ -41,53 +41,53 @@ CREATE INDEX IF NOT EXISTS idx_memory_projects_visibility -- 2. Add attribution columns to entities -- ───────────────────────────────────────────────────────────────────────────── -ALTER TABLE knowledge_node ADD COLUMN IF NOT EXISTS ( +ALTER TABLE memory_entity ADD COLUMN IF NOT EXISTS ( contributed_by VARCHAR(255), -- JWT "sub" who added this contribution_type VARCHAR(50), -- "extracted" | "manual" | "inferred" contribution_date TIMESTAMPTZ ); -- Populate contributed_by with defaults (assume "system" if not present) -UPDATE knowledge_node +UPDATE memory_entity SET contributed_by = 'system' WHERE contributed_by IS NULL; -ALTER TABLE knowledge_node +ALTER TABLE memory_entity ALTER COLUMN contributed_by SET NOT NULL; -CREATE INDEX IF NOT EXISTS idx_knowledge_node_contributed_by - ON knowledge_node(contributed_by); +CREATE INDEX IF NOT EXISTS idx_memory_entity_contributed_by + ON memory_entity(contributed_by); -CREATE INDEX IF NOT EXISTS idx_knowledge_node_contribution_date - ON knowledge_node(contribution_date) +CREATE INDEX IF NOT EXISTS idx_memory_entity_contribution_date + ON memory_entity(contribution_date) WHERE contribution_date IS NOT NULL; -- ───────────────────────────────────────────────────────────────────────────── -- 3. Add attribution columns to edges -- ───────────────────────────────────────────────────────────────────────────── -ALTER TABLE knowledge_edge ADD COLUMN IF NOT EXISTS ( +ALTER TABLE memory_edge ADD COLUMN IF NOT EXISTS ( contributed_by VARCHAR(255), -- JWT "sub" who added this contribution_type VARCHAR(50) -- "extracted" | "inferred" ); -- Populate contributed_by with defaults -UPDATE knowledge_edge +UPDATE memory_edge SET contributed_by = 'system' WHERE contributed_by IS NULL; -ALTER TABLE knowledge_edge +ALTER TABLE memory_edge ALTER COLUMN contributed_by SET NOT NULL; -CREATE INDEX IF NOT EXISTS idx_knowledge_edge_contributed_by - ON knowledge_edge(contributed_by); +CREATE INDEX IF NOT EXISTS idx_memory_edge_contributed_by + ON memory_edge(contributed_by); -- ───────────────────────────────────────────────────────────────────────────── -- 4. Add project_id to entities and edges (optional, for faster filtering) -- ───────────────────────────────────────────────────────────────────────────── --- ALTER TABLE knowledge_node ADD COLUMN IF NOT EXISTS project_id VARCHAR(255); --- ALTER TABLE knowledge_edge ADD COLUMN IF NOT EXISTS project_id VARCHAR(255); +-- ALTER TABLE memory_entity ADD COLUMN IF NOT EXISTS project_id VARCHAR(255); +-- ALTER TABLE memory_edge ADD COLUMN IF NOT EXISTS project_id VARCHAR(255); -- -- Note: Deferred. Can use project info from path/source instead. @@ -102,7 +102,7 @@ SELECT COUNT(*) as entity_count, MAX(contribution_date) as last_contribution, ARRAY_AGG(DISTINCT contribution_type) as contribution_types -FROM knowledge_node +FROM memory_entity WHERE contribution_date IS NOT NULL GROUP BY contributed_by; @@ -112,7 +112,7 @@ SELECT contributed_by, COUNT(*) as count, MAX(contribution_date) as latest -FROM knowledge_node +FROM memory_entity WHERE contribution_date > CURRENT_TIMESTAMP - INTERVAL '7 days' GROUP BY contributed_by; @@ -129,12 +129,12 @@ GROUP BY contributed_by; -- DROP INDEX IF EXISTS idx_memory_projects_visibility; -- DROP TABLE IF EXISTS memory_projects; -- --- DROP INDEX IF EXISTS idx_knowledge_node_contributed_by; --- DROP INDEX IF EXISTS idx_knowledge_node_contribution_date; --- ALTER TABLE knowledge_node DROP COLUMN IF EXISTS contributed_by; --- ALTER TABLE knowledge_node DROP COLUMN IF EXISTS contribution_type; --- ALTER TABLE knowledge_node DROP COLUMN IF EXISTS contribution_date; +-- DROP INDEX IF EXISTS idx_memory_entity_contributed_by; +-- DROP INDEX IF EXISTS idx_memory_entity_contribution_date; +-- ALTER TABLE memory_entity DROP COLUMN IF EXISTS contributed_by; +-- ALTER TABLE memory_entity DROP COLUMN IF EXISTS contribution_type; +-- ALTER TABLE memory_entity DROP COLUMN IF EXISTS contribution_date; -- --- DROP INDEX IF EXISTS idx_knowledge_edge_contributed_by; --- ALTER TABLE knowledge_edge DROP COLUMN IF EXISTS contributed_by; --- ALTER TABLE knowledge_edge DROP COLUMN IF EXISTS contribution_type; +-- DROP INDEX IF EXISTS idx_memory_edge_contributed_by; +-- ALTER TABLE memory_edge DROP COLUMN IF EXISTS contributed_by; +-- ALTER TABLE memory_edge DROP COLUMN IF EXISTS contribution_type; diff --git a/crates/mem-store/migrations/005_workflows_schema.sql b/crates/mem-store/migrations/005_workflows_schema.sql index 3c38240..92984dd 100644 --- a/crates/mem-store/migrations/005_workflows_schema.sql +++ b/crates/mem-store/migrations/005_workflows_schema.sql @@ -18,8 +18,8 @@ CREATE TABLE IF NOT EXISTS temporal_workflow_links ( run_id VARCHAR(255), -- Temporal run ID -- Memory Entity References (Optional - NULL until linked) - entity_id UUID REFERENCES knowledge_node(id) ON DELETE SET NULL, - edge_id UUID REFERENCES knowledge_edge(id) ON DELETE SET NULL, + entity_id UUID REFERENCES memory_entity(id) ON DELETE SET NULL, + edge_id UUID REFERENCES memory_edge(id) ON DELETE SET NULL, node_id BIGINT REFERENCES memory_node(id) ON DELETE SET NULL, -- Sync Status diff --git a/crates/mem-store/migrations/006_phase4_community_detection.sql b/crates/mem-store/migrations/006_phase4_community_detection.sql index 986075c..1bd1767 100644 --- a/crates/mem-store/migrations/006_phase4_community_detection.sql +++ b/crates/mem-store/migrations/006_phase4_community_detection.sql @@ -47,7 +47,7 @@ CREATE TABLE IF NOT EXISTS community_member_map ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), project_id VARCHAR(255) NOT NULL, community_id UUID NOT NULL REFERENCES memory_community(id) ON DELETE CASCADE, - entity_id UUID NOT NULL REFERENCES knowledge_node(id) ON DELETE CASCADE, + entity_id UUID NOT NULL REFERENCES memory_entity(id) ON DELETE CASCADE, label_propagation_run_id UUID REFERENCES label_propagation_run(id) ON DELETE SET NULL, -- Label strength (0-1, higher = stronger membership) diff --git a/crates/mem-store/migrations/007_versioning_schema.sql b/crates/mem-store/migrations/007_versioning_schema.sql index fe2804d..f1a6be6 100644 --- a/crates/mem-store/migrations/007_versioning_schema.sql +++ b/crates/mem-store/migrations/007_versioning_schema.sql @@ -5,7 +5,7 @@ BEGIN; -- Entity version snapshots (immutable) -CREATE TABLE IF NOT EXISTS knowledge_node_version ( +CREATE TABLE IF NOT EXISTS memory_entity_version ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), entity_id VARCHAR(255) NOT NULL, version_num INTEGER NOT NULL, @@ -28,7 +28,7 @@ CREATE TABLE IF NOT EXISTS knowledge_node_version ( ); -- Edge version snapshots -CREATE TABLE IF NOT EXISTS knowledge_edge_version ( +CREATE TABLE IF NOT EXISTS memory_edge_version ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), edge_id UUID NOT NULL, version_num INTEGER NOT NULL, @@ -52,22 +52,22 @@ CREATE TABLE IF NOT EXISTS knowledge_edge_version ( -- Indexes for efficient lookups CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_entity_version_entity_id - ON knowledge_node_version(entity_id, version_num DESC); + ON memory_entity_version(entity_id, version_num DESC); CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_entity_version_changed_at - ON knowledge_node_version(changed_at DESC); + ON memory_entity_version(changed_at DESC); CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_entity_version_changed_by - ON knowledge_node_version(changed_by); + ON memory_entity_version(changed_by); CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_edge_version_edge_id - ON knowledge_edge_version(edge_id, version_num DESC); + ON memory_edge_version(edge_id, version_num DESC); CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_edge_version_changed_at - ON knowledge_edge_version(changed_at DESC); + ON memory_edge_version(changed_at DESC); CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_edge_version_changed_by - ON knowledge_edge_version(changed_by); + ON memory_edge_version(changed_by); -- Immutability enforcement: version tables are append-only CREATE OR REPLACE FUNCTION prevent_version_table_modification() @@ -77,19 +77,19 @@ BEGIN END; $$ LANGUAGE plpgsql; -CREATE TRIGGER knowledge_node_version_immutable - BEFORE UPDATE OR DELETE ON knowledge_node_version +CREATE TRIGGER memory_entity_version_immutable + BEFORE UPDATE OR DELETE ON memory_entity_version FOR EACH ROW EXECUTE FUNCTION prevent_version_table_modification(); -CREATE TRIGGER knowledge_edge_version_immutable - BEFORE UPDATE OR DELETE ON knowledge_edge_version +CREATE TRIGGER memory_edge_version_immutable + BEFORE UPDATE OR DELETE ON memory_edge_version FOR EACH ROW EXECUTE FUNCTION prevent_version_table_modification(); COMMIT; -- Rollback (for reference): --- DROP TRIGGER knowledge_node_version_immutable ON knowledge_node_version; --- DROP TRIGGER knowledge_edge_version_immutable ON knowledge_edge_version; +-- DROP TRIGGER memory_entity_version_immutable ON memory_entity_version; +-- DROP TRIGGER memory_edge_version_immutable ON memory_edge_version; -- DROP FUNCTION prevent_version_table_modification(); --- DROP TABLE knowledge_node_version; --- DROP TABLE knowledge_edge_version; +-- DROP TABLE memory_entity_version; +-- DROP TABLE memory_edge_version; diff --git a/crates/mem-store/migrations/008_phase3_compaction.sql b/crates/mem-store/migrations/008_phase3_compaction.sql index 352e882..74cdbee 100644 --- a/crates/mem-store/migrations/008_phase3_compaction.sql +++ b/crates/mem-store/migrations/008_phase3_compaction.sql @@ -9,8 +9,8 @@ CREATE TABLE IF NOT EXISTS exact_dedup_record ( project_id VARCHAR(255) NOT NULL, -- Source and target edges - source_edge_id UUID NOT NULL REFERENCES knowledge_edge(id) ON DELETE CASCADE, - target_edge_id UUID NOT NULL REFERENCES knowledge_edge(id) ON DELETE CASCADE, + source_edge_id UUID NOT NULL REFERENCES memory_edge(id) ON DELETE CASCADE, + target_edge_id UUID NOT NULL REFERENCES memory_edge(id) ON DELETE CASCADE, -- Match criteria (all must match for exact dedup) source_match BOOLEAN NOT NULL, @@ -51,8 +51,8 @@ CREATE TABLE IF NOT EXISTS stale_gc_record ( project_id VARCHAR(255) NOT NULL, -- Entity or edge marked for GC - entity_id UUID REFERENCES knowledge_node(id) ON DELETE CASCADE, - edge_id UUID REFERENCES knowledge_edge(id) ON DELETE CASCADE, + entity_id UUID REFERENCES memory_entity(id) ON DELETE CASCADE, + edge_id UUID REFERENCES memory_edge(id) ON DELETE CASCADE, -- Staleness criteria age_days INT NOT NULL, @@ -96,8 +96,8 @@ CREATE TABLE IF NOT EXISTS semantic_dedup_record ( project_id VARCHAR(255) NOT NULL, -- Source and target edges - source_edge_id UUID NOT NULL REFERENCES knowledge_edge(id) ON DELETE CASCADE, - target_edge_id UUID NOT NULL REFERENCES knowledge_edge(id) ON DELETE CASCADE, + source_edge_id UUID NOT NULL REFERENCES memory_edge(id) ON DELETE CASCADE, + target_edge_id UUID NOT NULL REFERENCES memory_edge(id) ON DELETE CASCADE, -- Pre-filter score (0-1, eliminates 60-70% of candidates) prefilter_score FLOAT NOT NULL, @@ -119,7 +119,7 @@ CREATE TABLE IF NOT EXISTS semantic_dedup_record ( -- Merge strategy (if auto-merged) merge_strategy VARCHAR(50), -- 'keep_superset', 'keep_newer', 'keep_higher_confidence' - merged_edge_id UUID REFERENCES knowledge_edge(id) ON DELETE SET NULL, + merged_edge_id UUID REFERENCES memory_edge(id) ON DELETE SET NULL, -- Metadata detected_at TIMESTAMPTZ DEFAULT NOW(), diff --git a/crates/mem-store/migrations/009_temporal_edge_migration.sql b/crates/mem-store/migrations/009_temporal_edge_migration.sql index 0a6021a..5fe3d41 100644 --- a/crates/mem-store/migrations/009_temporal_edge_migration.sql +++ b/crates/mem-store/migrations/009_temporal_edge_migration.sql @@ -1,10 +1,21 @@ -- Migration 009: Temporal knowledge graph edge schema (Zep paper §2.2.2) --- Creates knowledge_edge table for entity relationships. --- The old memory_edge (child_sha/parent_sha provenance DAG) is kept as-is. +-- Replaces old memory_edge (child_sha/parent_sha provenance DAG) +-- with temporal edge schema for the knowledge graph. -- Idempotent: safe to run multiple times. --- Create knowledge graph edge table (separate from provenance memory_edge) -CREATE TABLE IF NOT EXISTS knowledge_edge ( +-- Rename old provenance DAG table if it still has child_sha columns +DO $$ +BEGIN + IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'memory_edge' + AND EXISTS (SELECT 1 FROM information_schema.columns + WHERE table_name = 'memory_edge' AND column_name = 'child_sha')) + THEN + ALTER TABLE memory_edge RENAME TO memory_edge_provenance; + END IF; +END $$; + +-- Create temporal knowledge graph edge table +CREATE TABLE IF NOT EXISTS memory_edge ( id TEXT PRIMARY KEY, project_id TEXT NOT NULL DEFAULT 'default', source_id TEXT NOT NULL, @@ -27,30 +38,31 @@ CREATE TABLE IF NOT EXISTS knowledge_edge ( -- Ensure app user owns the table DO $$ BEGIN IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'app') THEN - ALTER TABLE knowledge_edge OWNER TO app; + ALTER TABLE memory_edge OWNER TO app; END IF; END $$; -CREATE INDEX IF NOT EXISTS idx_knowledge_edge_source ON knowledge_edge(source_id); -CREATE INDEX IF NOT EXISTS idx_knowledge_edge_target ON knowledge_edge(target_id); -CREATE INDEX IF NOT EXISTS idx_knowledge_edge_project ON knowledge_edge(project_id); -CREATE INDEX IF NOT EXISTS idx_knowledge_edge_relation ON knowledge_edge(relation_type); +CREATE INDEX IF NOT EXISTS idx_memory_edge_source ON memory_edge(source_id); +CREATE INDEX IF NOT EXISTS idx_memory_edge_target ON memory_edge(target_id); +CREATE INDEX IF NOT EXISTS idx_memory_edge_project ON memory_edge(project_id); +CREATE INDEX IF NOT EXISTS idx_memory_edge_relation ON memory_edge(relation_type); --- Ensure knowledge_node has all columns code expects -ALTER TABLE knowledge_node ADD COLUMN IF NOT EXISTS deleted_at TIMESTAMPTZ; -ALTER TABLE knowledge_node ADD COLUMN IF NOT EXISTS source_count INTEGER DEFAULT 1; +-- Ensure memory_entity has all columns code expects +ALTER TABLE memory_entity ADD COLUMN IF NOT EXISTS deleted_at TIMESTAMPTZ; +ALTER TABLE memory_entity ADD COLUMN IF NOT EXISTS source_count INTEGER DEFAULT 1; -- Unique constraint for entity upsert dedup DO $$ BEGIN -- Dedup existing rows before creating unique index - DELETE FROM knowledge_node a USING knowledge_node b + DELETE FROM memory_entity a USING memory_entity b WHERE a.project_id = b.project_id AND a.name = b.name AND a.t_created < b.t_created; EXCEPTION WHEN OTHERS THEN NULL; END $$; -CREATE UNIQUE INDEX IF NOT EXISTS idx_knowledge_node_project_name ON knowledge_node(project_id, name); +CREATE UNIQUE INDEX IF NOT EXISTS idx_memory_entity_project_name ON memory_entity(project_id, name); -- ROLLBACK instructions: --- DROP TABLE IF EXISTS knowledge_edge; --- DROP INDEX IF EXISTS idx_knowledge_node_project_name; +-- DROP TABLE IF EXISTS memory_edge; +-- ALTER TABLE IF EXISTS memory_edge_provenance RENAME TO memory_edge; +-- DROP INDEX IF EXISTS idx_memory_entity_project_name; diff --git a/crates/mem-store/src/audit_logger.rs b/crates/mem-store/src/audit_logger.rs index 429579c..7613cfd 100644 --- a/crates/mem-store/src/audit_logger.rs +++ b/crates/mem-store/src/audit_logger.rs @@ -25,7 +25,7 @@ impl AuditLogger { ) -> Result<(), sqlx::Error> { sqlx::query( r#" - INSERT INTO knowledge_node_version + INSERT INTO memory_entity_version (entity_id, version_num, operation, snapshot, changed_by, fields_changed) VALUES ($1, $2, $3, $4, $5, $6) "#, @@ -54,7 +54,7 @@ impl AuditLogger { ) -> Result<(), sqlx::Error> { sqlx::query( r#" - INSERT INTO knowledge_edge_version + INSERT INTO memory_edge_version (edge_id, version_num, operation, snapshot, changed_by, fields_changed) VALUES ($1, $2, $3, $4, $5, $6) "#, @@ -87,7 +87,7 @@ impl AuditLogger { changed_at, changed_by, COALESCE(fields_changed, '{}') as "fields_changed" - FROM knowledge_node_version + FROM memory_entity_version WHERE entity_id = $1 ORDER BY version_num DESC "#, @@ -113,7 +113,7 @@ impl AuditLogger { changed_at, changed_by, COALESCE(fields_changed, '{}') as "fields_changed" - FROM knowledge_edge_version + FROM memory_edge_version WHERE edge_id = $1 ORDER BY version_num DESC "#, diff --git a/crates/mem-store/src/db_repo.rs b/crates/mem-store/src/db_repo.rs index e67b366..af4e85c 100644 --- a/crates/mem-store/src/db_repo.rs +++ b/crates/mem-store/src/db_repo.rs @@ -80,7 +80,7 @@ impl PersistentEntityRepo { /// Save entity to database (idempotent) pub async fn save(&self, entity: &Entity) -> Result { let query = r#" - INSERT INTO knowledge_node (id, entity_type, name, description, embedding, created_at, updated_at) + INSERT INTO memory_entity (id, entity_type, name, description, embedding, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7) ON CONFLICT(id) DO UPDATE SET name = EXCLUDED.name, @@ -114,7 +114,7 @@ impl PersistentEntityRepo { pub async fn get(&self, id: &str) -> Result, DbError> { let query = r#" SELECT id, entity_type, name, description, embedding, created_at, updated_at - FROM knowledge_node + FROM memory_entity WHERE id = $1 AND deleted_at IS NULL; "#; @@ -139,7 +139,7 @@ impl PersistentEntityRepo { pub async fn list(&self, limit: i64, offset: i64) -> Result, DbError> { let query = r#" SELECT id, entity_type, name, description, embedding, created_at, updated_at - FROM knowledge_node + FROM memory_entity WHERE deleted_at IS NULL ORDER BY created_at DESC LIMIT $1 OFFSET $2; @@ -166,7 +166,7 @@ impl PersistentEntityRepo { /// Soft delete entity pub async fn delete(&self, id: &str) -> Result<(), DbError> { let query = r#" - UPDATE knowledge_node + UPDATE memory_entity SET deleted_at = $1 WHERE id = $2; "#; @@ -195,7 +195,7 @@ impl PersistentEdgeRepo { /// Save edge to database (idempotent) pub async fn save(&self, edge: &Edge) -> Result { let query = r#" - INSERT INTO knowledge_edge (id, source_id, target_id, relation_type, fact, strength, t_valid, t_invalid, t_created, t_expired) + INSERT INTO memory_edge (id, source_id, target_id, relation_type, fact, strength, t_valid, t_invalid, t_created, t_expired) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) ON CONFLICT(id) DO UPDATE SET strength = EXCLUDED.strength, @@ -232,7 +232,7 @@ impl PersistentEdgeRepo { pub async fn get(&self, id: &str) -> Result, DbError> { let query = r#" SELECT id, source_id, target_id, relation_type, fact, strength, t_valid, t_invalid, t_created, t_expired - FROM knowledge_edge + FROM memory_edge WHERE id = $1 AND t_expired IS NULL; "#; @@ -260,7 +260,7 @@ impl PersistentEdgeRepo { pub async fn list_from(&self, source_id: &str, limit: i64) -> Result, DbError> { let query = r#" SELECT id, source_id, target_id, relation_type, fact, strength, t_valid, t_invalid, t_created, t_expired - FROM knowledge_edge + FROM memory_edge WHERE source_id = $1 AND t_expired IS NULL AND t_invalid IS NULL ORDER BY t_created DESC LIMIT $2; @@ -290,7 +290,7 @@ impl PersistentEdgeRepo { /// Mark edge as contradicted (soft delete) pub async fn invalidate(&self, id: &str) -> Result<(), DbError> { let query = r#" - UPDATE knowledge_edge + UPDATE memory_edge SET t_invalid = $1 WHERE id = $2; "#; diff --git a/crates/mem-store/src/schema.rs b/crates/mem-store/src/schema.rs index 99884c9..b9c05a4 100644 --- a/crates/mem-store/src/schema.rs +++ b/crates/mem-store/src/schema.rs @@ -221,7 +221,7 @@ pub async fn init_schema(pool: &PgPool) -> Result<()> { // Memory entity table (temporal knowledge graph) sqlx::query( r#" - CREATE TABLE IF NOT EXISTS knowledge_node ( + CREATE TABLE IF NOT EXISTS memory_entity ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), project_id VARCHAR(255) NOT NULL, name VARCHAR(500) NOT NULL, @@ -245,17 +245,17 @@ pub async fn init_schema(pool: &PgPool) -> Result<()> { .execute(pool) .await?; - sqlx::query("CREATE INDEX IF NOT EXISTS idx_entity_project ON knowledge_node(project_id)") + sqlx::query("CREATE INDEX IF NOT EXISTS idx_entity_project ON memory_entity(project_id)") .execute(pool) .await?; - sqlx::query("CREATE INDEX IF NOT EXISTS idx_entity_type ON knowledge_node(project_id, entity_type)") + sqlx::query("CREATE INDEX IF NOT EXISTS idx_entity_type ON memory_entity(project_id, entity_type)") .execute(pool) .await?; // Memory edge table (temporal knowledge graph) sqlx::query( r#" - CREATE TABLE IF NOT EXISTS knowledge_edge ( + CREATE TABLE IF NOT EXISTS memory_edge ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), project_id VARCHAR(255) NOT NULL, source_id UUID NOT NULL, @@ -276,16 +276,16 @@ pub async fn init_schema(pool: &PgPool) -> Result<()> { .execute(pool) .await?; - sqlx::query("CREATE INDEX IF NOT EXISTS idx_edge_project ON knowledge_edge(project_id)") + sqlx::query("CREATE INDEX IF NOT EXISTS idx_edge_project ON memory_edge(project_id)") .execute(pool) .await?; - sqlx::query("CREATE INDEX IF NOT EXISTS idx_edge_source ON knowledge_edge(source_id)") + sqlx::query("CREATE INDEX IF NOT EXISTS idx_edge_source ON memory_edge(source_id)") .execute(pool) .await?; - sqlx::query("CREATE INDEX IF NOT EXISTS idx_edge_target ON knowledge_edge(target_id)") + sqlx::query("CREATE INDEX IF NOT EXISTS idx_edge_target ON memory_edge(target_id)") .execute(pool) .await?; - tracing::info!("Database schema initialized (including knowledge_node + knowledge_edge)"); + tracing::info!("Database schema initialized (including memory_entity + memory_edge)"); Ok(()) } diff --git a/crates/mem-store/src/versioning.rs b/crates/mem-store/src/versioning.rs index 595f379..c9692c3 100644 --- a/crates/mem-store/src/versioning.rs +++ b/crates/mem-store/src/versioning.rs @@ -50,7 +50,7 @@ impl EntityVersioningService { changed_at, changed_by, COALESCE(fields_changed, '{}') as fields_changed - FROM knowledge_node_version + FROM memory_entity_version WHERE entity_id = $1 ORDER BY version_num DESC "#, @@ -75,7 +75,7 @@ impl EntityVersioningService { changed_at, changed_by, COALESCE(fields_changed, '{}') as fields_changed - FROM knowledge_node_version + FROM memory_entity_version WHERE entity_id = $1 AND version_num = $2 "#, ) @@ -112,7 +112,7 @@ impl EntityVersioningService { changed_at, changed_by, COALESCE(fields_changed, '{}') as fields_changed - FROM knowledge_node_version + FROM memory_entity_version WHERE entity_id = $1 AND changed_at <= $2 ORDER BY version_num DESC LIMIT 1 @@ -146,7 +146,7 @@ impl EdgeVersioningService { changed_at, changed_by, COALESCE(fields_changed, '{}') as fields_changed - FROM knowledge_edge_version + FROM memory_edge_version WHERE edge_id = $1 ORDER BY version_num DESC "#, @@ -172,7 +172,7 @@ impl EdgeVersioningService { changed_at, changed_by, COALESCE(fields_changed, '{}') as fields_changed - FROM knowledge_edge_version + FROM memory_edge_version WHERE edge_id = $1 AND version_num = $2 "#, ) @@ -190,7 +190,7 @@ impl EdgeVersioningService { changed_at, changed_by, COALESCE(fields_changed, '{}') as fields_changed - FROM knowledge_edge_version + FROM memory_edge_version WHERE edge_id = $1 AND version_num = $2 "#, ) diff --git a/tests/it_phase7_gate.rs b/tests/it_phase7_gate.rs index 10374b4..3250ac0 100644 --- a/tests/it_phase7_gate.rs +++ b/tests/it_phase7_gate.rs @@ -50,8 +50,8 @@ async fn test_phase7_composition_gate() { // T7.1: Schema Checks fn assert_tables_exist() { - // Verify knowledge_node_version table - // Verify knowledge_edge_version table + // Verify memory_entity_version table + // Verify memory_edge_version table // Verify index coverage } @@ -107,7 +107,7 @@ async fn test_edge_diff_endpoint() { async fn test_audit_logger_log_entity() { // Create entity snapshot // Call audit_logger.log_entity() - // Verify record inserted in knowledge_node_version + // Verify record inserted in memory_entity_version // Verify changed_by populated from JWT sub // Verify fields_changed array computed } @@ -120,9 +120,9 @@ async fn test_audit_logger_history() { } async fn test_audit_logger_immutability() { - // Try to UPDATE knowledge_node_version + // Try to UPDATE memory_entity_version // Should fail (trigger fires) - // Try to DELETE knowledge_node_version + // Try to DELETE memory_entity_version // Should fail (trigger fires) // Verify log is append-only }