Summary
Phase 1 of graph memory (#1222): SQLite schema, Rust types, CRUD store, config section.
Depends on: #1223 (prerequisite refactors)
Tasks
1. Migration 021_knowledge_graph.sql
Create crates/zeph-memory/migrations/021_knowledge_graph.sql:
graph_entities (id, name, entity_type, summary, first_seen_at, last_seen_at, qdrant_point_id) with UNIQUE(name, entity_type)
graph_edges (id, source_entity_id, target_entity_id, relation, fact, confidence, valid_from, valid_to, created_at, expired_at, episode_id, qdrant_point_id) with CASCADE/SET NULL FKs
graph_communities (id, name, summary, entity_ids JSON, timestamps)
graph_metadata (key, value) for persistent counters
ALTER TABLE messages ADD COLUMN graph_processed INTEGER NOT NULL DEFAULT 0
- Indexes: edges source/target, edges valid_to partial, entities name COLLATE NOCASE, entities type, entities last_seen_at
Tables are always created (not feature-gated) to avoid migration ordering issues.
2. Rust Types (graph/types.rs)
EntityType enum (Person, Tool, Concept, Project, Language, File, Config, Organization) with FromStr/Display/serde
Entity, Edge, Community structs matching SQLite schema
GraphFact with decomposed scoring (entity_match_score, hop_distance, confidence) and composite_score() method
3. CRUD Store (graph/store.rs)
GraphStore with methods:
upsert_entity, find_entity, find_entities_fuzzy, all_entities_stream, all_entities, entity_count
insert_edge, invalidate_edge, edges_for_entity, edges_between, active_edge_count
upsert_community, community_for_entity, all_communities, community_count
bfs(start_entity_id, max_hops) using recursive CTE (3 queries total)
4. Feature Flag
- Root
Cargo.toml: graph-memory = ["zeph-memory/graph-memory", "zeph-core/graph-memory"]
zeph-memory/Cargo.toml: graph-memory = []
zeph-core/Cargo.toml: graph-memory = ["zeph-memory/graph-memory"]
lib.rs: #[cfg(feature = "graph-memory")] pub mod graph;
5. Config (GraphConfig)
Add GraphConfig to crates/zeph-core/src/config/types.rs with fields: enabled, extract_model, max_entities_per_message, max_edges_per_message, community_refresh_interval, entity_similarity_threshold, extraction_timeout_secs, use_embedding_resolution, max_hops, recall_limit. Add graph: GraphConfig field on MemoryConfig.
6. Error Variant
Add GraphStore(String) variant to MemoryError.
Architecture Reference
See .local/plan/graph-memory-architecture.md Section 3 for exact SQL, type signatures, and BFS CTE query.
Acceptance Criteria
Summary
Phase 1 of graph memory (#1222): SQLite schema, Rust types, CRUD store, config section.
Depends on: #1223 (prerequisite refactors)
Tasks
1. Migration 021_knowledge_graph.sql
Create
crates/zeph-memory/migrations/021_knowledge_graph.sql:graph_entities(id, name, entity_type, summary, first_seen_at, last_seen_at, qdrant_point_id) with UNIQUE(name, entity_type)graph_edges(id, source_entity_id, target_entity_id, relation, fact, confidence, valid_from, valid_to, created_at, expired_at, episode_id, qdrant_point_id) with CASCADE/SET NULL FKsgraph_communities(id, name, summary, entity_ids JSON, timestamps)graph_metadata(key, value) for persistent countersALTER TABLE messages ADD COLUMN graph_processed INTEGER NOT NULL DEFAULT 0Tables are always created (not feature-gated) to avoid migration ordering issues.
2. Rust Types (graph/types.rs)
EntityTypeenum (Person, Tool, Concept, Project, Language, File, Config, Organization) with FromStr/Display/serdeEntity,Edge,Communitystructs matching SQLite schemaGraphFactwith decomposed scoring (entity_match_score, hop_distance, confidence) andcomposite_score()method3. CRUD Store (graph/store.rs)
GraphStorewith methods:upsert_entity,find_entity,find_entities_fuzzy,all_entities_stream,all_entities,entity_countinsert_edge,invalidate_edge,edges_for_entity,edges_between,active_edge_countupsert_community,community_for_entity,all_communities,community_countbfs(start_entity_id, max_hops)using recursive CTE (3 queries total)4. Feature Flag
Cargo.toml:graph-memory = ["zeph-memory/graph-memory", "zeph-core/graph-memory"]zeph-memory/Cargo.toml:graph-memory = []zeph-core/Cargo.toml:graph-memory = ["zeph-memory/graph-memory"]lib.rs:#[cfg(feature = "graph-memory")] pub mod graph;5. Config (GraphConfig)
Add
GraphConfigtocrates/zeph-core/src/config/types.rswith fields: enabled, extract_model, max_entities_per_message, max_edges_per_message, community_refresh_interval, entity_similarity_threshold, extraction_timeout_secs, use_embedding_resolution, max_hops, recall_limit. Addgraph: GraphConfigfield onMemoryConfig.6. Error Variant
Add
GraphStore(String)variant toMemoryError.Architecture Reference
See
.local/plan/graph-memory-architecture.mdSection 3 for exact SQL, type signatures, and BFS CTE query.Acceptance Criteria
GraphStore::upsert_entityhandles insert and update (UNIQUE constraint)GraphStore::insert_edgecreates edges with correct FKsGraphStore::invalidate_edgesets expired_at and valid_toGraphStore::bfswith max_hops=0 returns only start entityGraphStore::bfswith max_hops=2 traverses correctly on test graphGraphConfigdeserializes from TOML with defaultsEntityType::from_strhandles all variants + rejects unknown