Overview Setup Guide Installation Usage CLI Reference API Architecture Use Cases Comparisons Benchmarks Troubleshooting FAQ
neuralmind.uk / Docs / Synapse Module Edit this page on GitHub ↗

Synapse Module

Last updated: 2026-08-21 Version: v3.x Audience: Engineers, operators, and contributors who want to understand (or extend) NeuralMind’s brain-like associative memory layer.

The synapse module is NeuralMind’s hippocampus + associative cortex. It sits as a second, persistent brain alongside the LLM: the agent fires queries and tool calls, NeuralMind reinforces or decays the weighted edges between the code nodes those events activated, and future retrievals spread activation across the resulting graph instead of relying on a flat top-k vector search alone.

This page is the architecture reference for the module as a whole, including the seeding layer (N-13) that solves the cold-start problem. For the learning model itself, see the Learning Guide. For usage in the build/query lifecycle, see the Architecture overview.


Table of contents


The four files

File Responsibility Stdlib-only
neuralmind/synapses.py The SynapseStore itself — SQLite-backed Hebbian store, schema + migration, seeding, spread/recall, stats ✅
neuralmind/synapse_client.py Thin file/activity-level orchestration over the store (activate, spread, compliance) ✅
neuralmind/synapse_feedback.py The write-path: watcher co-activation, Edit/Write reuse detection, decay on delete, query reinforcement ✅
neuralmind/synapse_memory.py Export learned associations to agent-readable markdown (SYNAPSE_MEMORY.md, Claude Code auto-memory) ✅

The whole module is deliberately stdlib-only (SQLite + math) so the synapse layer runs and tests without the heavy embedding/tree-sitter depend cycle. It reaches the graph only through mind.embedder.get_file_nodes / get_graph, never by parsing source itself.


Data model

Five tables in <project>/.neuralmind/synapses.db (WAL mode):

Table Holds
synapses Undirected Hebbian edges (node_a, node_b, namespace, weight, activation_count, …) via canonical ordering node_a < node_b
synapse_transitions Directional, ordered transitions (from_node, to_node, …) — “after touching A, you touched B”
node_activations Per-node activation/salience counters
structural_edges Persisted directed call/import/inherits graph from the build (the seeding substrate)
type_edges Type-inference edges (return type, optionality, confidence, inferrer)
meta Key/value store (schema version stamped here)

Schema versioning is explicit: v0 (pre-namespace) is migrated in place to v1 in a single IMMEDIATE transaction, folding namespace into the primary keys. A migration bug never corrupts learned memory — any failure rolls the whole migration back.


Learning: Hebbian co-activation + decay

The store learns by co-activation: nodes that fire together wire together.


Memory namespaces

Every synapse, transition, and activation row carries a namespace (PRD 4) so different kinds of memory don’t pollute each other. Namespaces are plain single-token strings (normalize_namespace rejects whitespace/empty), so import/export and new kinds stay trivial — there is no enum table.

Namespace Meaning Half-life
personal Default. All pre-namespace memory migrates here. 30 days
shared Imported team baseline — seed_from_*, bundles, neuralmind memory import. 60 days
branch:<name> Per-git-branch working memory. 30 days (active namespace weighting)
ephemeral Session-scoped scratch; decays fast, cleared at session boundaries. 1 day

Merged-read weighting. Reads default to a merged view across the active namespace, personal, and shared, each scaled by a constant:

merged_weight = W_BRANCH · w_active + W_PERSONAL · w_personal + W_SHARED · w_shared

Passing namespaces=[...] reads only those namespaces at raw weights (no multipliers), which is what neuralmind synapse stats, export, and inspection use. On the default branch the active namespace is personal, so merged behavior is byte-identical to the pre-namespace store.


Recall: spreading activation

Retrieval is spreading activation over the weighted graph, not flat vector similarity:

The SynapseClient.spread / spread_detailed / synaptic_neighbors methods wrap these for file-level convenience and fail-open (return [] on a cold graph or any error).


Directional transitions (what comes next)

The synapse_transitions table learns order, not just co-occurrence: “after touching A, you normally touch B.”


Seeding — solving the cold start (Tier 1 / N-13)

A fresh install has no learned associations — the old Hebbian layer waited days/weeks of real use to accumulate signal. Seeding fixes this by loading the writable store with real architectural priors at build time. Seeding is automatic, idempotent, and fail-open: it runs inside build(), never blocks a build if it errors, and re-running only reinforces existing edges.

The build pipeline (core.py build(), when synapses are enabled) runs, in order:

  1. seed_from_structural() — persist + seed the real call-graph.
  2. seed_from_bundle(bundle_path) — only when --bootstrap <bundle.json>.
  3. seed_from_documents(all_nodes) — the N-13 business-context matcher.

Structural seeding

PersistStructuralEdges first folds the graphify relation vocabulary into the structural_edges table (calls/imports/inherits/implements/uses/ contains), then seed_from_structural() converts each (caller, callee, call_count) into an undirected synapse edge using a log-scaled weight:

weight = clamp(BASE + LOG_SCALE · ln(call_count + 1), MAX)   # 0.25 → 0.70

Hot call paths grow toward the cap; single-observation edges stay near the floor. Seeded edges land in the shared namespace (60-day half-life), are not LTP-protected, and increment activation_count on re-seed — so a path that disappears from the graph eventually prunes after enough builds skip it.

Business-context seeding — N-13

seed_from_documents(content_nodes) builds deterministic, LLM-free Hebbian edges between ingested business documents (book chapters, decisions, SOPs, meeting notes, policies) and the code symbols they reference — the backbone of the “second brain” expansion. It runs every build() so daemon rebuilds pick up new content, not just the one-shot ingest path.

Which nodes are “business”? Node metadata must carry a content_category of ai-agent-playbook, peptide-patient-guide, or business_context with a file_type of book-chapter / report / source / document / book. Config, plans, progress, and claims files are excluded.

Matching normalizes every node ID by splitting on _ . / - :: and lowercasing, tokenizes business text (content + label + title, words ≥ 3 chars), and classifies stopwords (component appearing in >10% of node IDs, or on a hardcoded common-token blacklist like test, core, api, auth, this, function, …).

Match signal Edge weight Rule
Exact label 0.40 A node’s label tokens are a subset of the business node’s text tokens.
Compound 0.25 2+ consecutive non-stopword ID components appear adjacent in the text (not just present).
Single rare component 0.20 Exactly one non-stopword component appears, and it’s rare (<5% of nodes derive it from a word appearing in fewer than 5% of node IDs) — blocks common prose words like “book”, “system”, “engine”.
Shared specific tag (business↔business) 0.20 Two business nodes share a metadata tag present in <20% of business nodes.
Title reference (business↔business) 0.25 One business node’s title appears in the other’s text.

Idempotency is careful: re-seeding uses MAX(weight) and MAX(activation_count) — never +1 — so keyword-match seeding can’t LTP-protect false positives after ~5 runs the way structural re-observation legitimately can (+1 there is re-observing real call edges). Returns the number of new edges created (0 when no business nodes — fail-open).

Bundle seeding

seed_from_bundle(bundle_path) imports a JSON file mapping (node_a, node_b) → weight — typically exported from a mature project via neuralmind export --synapses. Used for cold-start onboarding when no edit history exists: curated architectural priors land in shared at high confidence (weight = MAX(existing, bundle)). Wire it into a build with --bootstrap <bundle.json>.

LLM-assisted documentation seeding

seed_from_documentation(docs_root) is the opt-in, LLM-based analogue. When NEURALMIND_LLM_SEED=1 and an ANTHROPIC_API_KEY are present, it parses README.md/docs/architecture.md and asks claude-haiku-4-5 for explicit “node_a,node_b,weight” relationships (weight clamped to 0.25–0.40). It’s fully fail-open — any import/parse/API error returns 0 edges. Because it issues an external model call, it is not part of the default build path.


Agent memory export

synapse_memory.py renders the learned weights into agent-readable markdown so the model references associations even without calling the MCP tools:

Content: top strongest pairs (with LTP tags), hub nodes, and directional “what typically comes next” transitions (v0.11.0+). Keys off stats(); an empty store still yields a valid document. Purely an export — never blocks the live store, fails open (returns the paths that succeeded).


Operations: stats, pruning, namespaces

Command What
neuralmind synapse stats Edge/synapse/activation counts, per-namespace breakdown, active namespace, LTP count.
neuralmind synapse prune --days N Delete synapses older than N days (LTP-protected edges survive).
neuralmind memory export\|import --namespace Export/import a learned-weights bundle (neuralmind/ir.py) — team memory hand-off.
neuralmind health End-to-end install check including synapse store status (exit 0/1/2).

Toggle the synapse layer: NEURALMIND_SYNAPSE_INJECT=0 skips prompt-time recall, NEURALMIND_SYNAPSE_EXPORT=0 skips memory export. All fail-open.


Design invariants


This page is part of the NeuralMind docs/wiki. For the higher-level learning model, see Learning-Guide; for the build/query lifecycle, see Architecture.