feat(memory): implement SYNAPSE spreading activation retrieval over entity graph (#1888)#2080
Merged
feat(memory): implement SYNAPSE spreading activation retrieval over entity graph (#1888)#2080
Conversation
…ntity graph (#1888) Spreading activation engine propagates activation scores hop-by-hop from seed entities over the knowledge graph with: - Exponential decay per hop (decay_lambda parameter, default 0.85) - Edge confidence weighting and temporal recency (reuses temporal_decay_rate) - Lateral inhibition (nodes above inhibition_threshold stop receiving activation) - Per-hop pruning to enforce max_activated_nodes bound (SA-INV-04) - Clamped sum activation merge to preserve multi-path convergence signal - MAGMA edge-type subgraph filtering for causal/semantic/temporal/entity edges - Seed initialization from fuzzy entity search (DRY shared with graph_recall) New module: crates/zeph-memory/src/graph/activation.rs (290 lines) - SpreadingActivation engine with spread() async method - ActivatedNode (entity_id, activation, depth) and ActivatedFact (edge + score) - Temporal recency weighting formula: 1/(1 + age_days * temporal_decay_rate) - Depth tracking for max-activation hop (used for result ranking) Integration: - graph_recall_activated() in retrieval.rs wraps spreading activation - recall_graph_activated() on SemanticMemory delegates to retrieval - fetch_graph_facts() in context assembly routes based on config.spreading_activation.enabled - 500ms tokio::time::timeout() wraps spread() to bound latency Config: [memory.graph.spreading_activation] - enabled (bool, default false) - decay_lambda (f32, validated 0.0 < x <= 1.0, default 0.85) - max_hops (u32, validated >= 1, default 3) - activation_threshold (f32, default 0.1) - inhibition_threshold (f32, default 0.8, cross-validated > activation_threshold) - max_activated_nodes (usize, default 50) GraphStore::edges_for_entities() batch query - Fetches all edges where source_entity_id IN (...) OR target_entity_id IN (...) - SQLite bind limit safety: chunks at 490 IDs (safe under SQLITE_MAX_VARIABLE_NUMBER) - Respects edge_types filter (MAGMA integration) - Reuses valid_to IS NULL active-edge filter CLI/TUI/Wizard: - --init wizard includes spreading_activation toggle in graph-memory block - /status reports "Graph recall: spreading activation (lambda=X.XX, hops=N)" when enabled - Config defaults and migrations included Testing: 11 unit tests covering: 1. Empty graph → empty results 2. Single seed, no edges → seed only 3. Linear chain A→B→C with max_hops=2 → all activated, scores decay 4. Linear chain with max_hops=1 → C not activated 5. Diamond graph → multi-path convergence signal preserved via clamped sum 6. Dense cluster → inhibition_threshold prevents runaway 7. max_activated_nodes pruning → per-hop top-N enforcement 8. Temporal decay → recent edges higher activation 9. decay_lambda=1.0 → full propagation without decay 10. Edge-type filtering → causal-only subgraph traversal 11. Batch seed loading → multiple entities initialized simultaneously Fixes all architect recommendations and critic findings (SA-INV-{01..09}, CRIT-{01..03}, MAJOR-{01..05}, SUGGEST-{01..06}): - Per-hop pruning (CRIT-03) - Lateral inhibition checks both maps (CRIT-02) - SQLite bind limit safety with MAX_BATCH_ENTITIES const (CRIT-01) - Clamped sum for multi-path convergence (MAJOR-01) - 500ms timeout protection (MAJOR-02) - Config validation (MAJOR-03) - Tracing at seed init, per-hop, and completion (SUGGEST-05) - Depth tracking for ranking (SUGGEST-01) - Shared seed-matching helper (SUGGEST-04) Total: 6309 tests, all passing. No clippy warnings.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implement SYNAPSE spreading activation algorithm for entity graph retrieval. Activation scores propagate hop-by-hop from seed entities with exponential decay, lateral inhibition, and temporal recency weighting.
Key improvements:
Architecture
New module:
crates/zeph-memory/src/graph/activation.rs(290 LOC)SpreadingActivationengine withspread()async methodActivatedNode(entity_id, activation, depth)ActivatedFact(edge + score)Integration:
graph_recall_activated()in retrieval.rsrecall_graph_activated()on SemanticMemoryfetch_graph_facts()in context assembly with config gateGraphStore::edges_for_entities()batch query with SQLite bind-limit safetyConfig:
[memory.graph.spreading_activation]Testing
✅ 6309 tests, all passing (no changes to existing tests)
✅ 11 new unit tests covering:
✅ Clippy: zero warnings
✅ Format: passes
cargo +nightly fmt --checkFixes
All architect recommendations and critic findings:
References