-
Notifications
You must be signed in to change notification settings - Fork 2
Description
Summary
SYNAPSE spreading activation returns result_count=0 immediately after entity extraction in the previous session. Entities are visible via direct SELECT but FTS5 fuzzy queries (MATCH 'word*') return empty.
Reproduction
Session 1: Send a message that triggers entity extraction:
Charlie works at MegaCorp and uses Golang for all backend services.
Graph extraction completes — entities Charlie, MegaCorp, Golang are extracted and stored.
Session 2 (immediately after): Send a causal/relational query:
Tell me about Charlie.
Expected:
spreading activation: seeds=1 "Tell me about Charlie."
spreading activation: graph recall complete result_count=N
Actual:
spreading activation: starting graph recall query_len=22 limit=10
spreading activation: graph recall complete result_count=0
No seeds=N debug line appears — find_seed_entities returns empty before the activation loop.
Root Cause
find_seed_entities in crates/zeph-memory/src/graph/retrieval.rs calls store.find_entities_fuzzy(word, ...) which queries FTS5 with MATCH 'word*'.
SQLite WAL mode buffers writes in the WAL file. FTS5 shadow tables (entities_fts) are updated transactionally, but FTS5 full-text indexes may not be visible to new connections (or re-opened connections) until a WAL checkpoint occurs. Direct SELECT * FROM graph_entities returns rows immediately; FTS5 MATCH queries on the same data return empty.
Once a WAL checkpoint runs (either automatically at 1000 pages or manually via PRAGMA wal_checkpoint), FTS5 queries start working correctly in subsequent sessions.
Code Path
graph_recall_activated()
└── find_seed_entities(store, query, limit)
└── store.find_entities_fuzzy(word, limit*2)
└── FTS5: SELECT ... FROM entities_fts WHERE entities_fts MATCH 'charlie*'
→ returns 0 rows (WAL not checkpointed)
→ returns empty Vec → early return at line ~220, no seeds logged
Expected Fix
Options (in preference order):
- Issue a
PRAGMA wal_checkpoint(PASSIVE)after FTS5 inserts (inGraphStore::add_entityor after batch extraction completes) - Use
PRAGMA wal_checkpoint(RESTART)at graph store open if FTS5 virtual tables are present - Add a fallback LIKE query (
name LIKE 'charlie%') when FTS5 returns 0 results, to bypass the FTS5 visibility issue - Configure
PRAGMA journal_mode=DELETEfor the graph store connection (trades performance for immediate FTS5 visibility)
Option 1 is least invasive — a passive checkpoint after batch entity insertion ensures subsequent FTS5 queries see the new data without blocking writers.
Impact
- Severity: High — SYNAPSE is silently disabled for all queries in fresh sessions after entity extraction. The feature appears to work (no error, no warning) but returns no graph context.
- Causal queries ("Why did X...", "How does X relate to Y") are most affected — these rely heavily on graph recall.
- Queries in the same session as extraction may work (same connection, WAL visible), but cross-session queries fail.
Verified
Confirmed with debug logging (RUST_LOG=zeph_memory=debug) in CI-101:
- Direct
SELECT id, name FROM graph_entities→ rows present - FTS5
SELECT name FROM entities_fts WHERE entities_fts MATCH 'charlie*'→ 0 rows (same connection, different transaction)