Skip to content

Synapse

Synapse connects what angelo knows to what it can prove. It is a capability inside the zettelkasten MCP server—not a fifth server—with two complementary jobs:

  1. Grounded navigation assembles a bounded neighborhood from memory, zettelkasten, code, and data/experiments; lets an LLM navigate and propose a cited reasoning graph; then lets deterministic code decide whether an answer is supported.
  2. Practice ↔ canon overlay searches, connects, and compares the episodic memory tree with the citation-backed zettelkasten.

Most Synapse actions are read-only. build is the deliberate exception: it writes only the committed typed-link overlay under .synapse/links/. Navigation may update derived caches under .angelo/, but it does not mutate source knowledge.

Grounded navigation: question to verified answer

Four evidence systems feed one bounded turn. The LLM proposes a cited ReasoningDAG; deterministic epistemics and grounding checks decide what may reach the answer surface.

Two capabilities, one connective layer

1. Grounded navigation

Call synapse(action="navigate", question="…") when the answer should be derived from the repository's evidence rather than recalled from model memory. The loop is intentionally asymmetric: the LLM chooses useful moves and writes claims, while the engine owns addresses, provenance, epistemic status, budgets, verification, and the final answer-or-abstain decision.

The four source families keep their own meaning:

  • Memory (blue) — decisions, experiments, checkpoints, and plans from actual project work.
  • Zettelkasten (rose) — extracted claims, findings, methods, and verified quotations.
  • Codebase (teal) — addressable files and symbols pinned to exact git objects.
  • Data and experiments (amber) — measured runs with immutable data and environment provenance.

One turn follows a fixed trust loop:

  1. Adapters resolve the requested scope and assemble a bounded neighborhood.
  2. The engine derives each node's status and renders the neighborhood as MemDSL, with explicit gaps and navigation affordances.
  3. A model may expand, join, ground, or prune, then returns exactly one terminal: @answer with a cited ReasoningDAG or @abstain.
  4. The grounding router re-derives status, verifies citations, checks verbatim restatements and numeric coverage, and rejects unsupported prose.
  5. A deterministic projector emits the versioned answer_surface; any inconsistency fails closed to an abstention.

An accepted answer carries verified text, status, premise claim IDs, canonical citation addresses, and any inseparable outdated disclosure. An abstention instead names the reason—such as missing-hop, stale, false-premise, or low-coverage—and carries answer_surface: null. This is not a model confidence score: it is the result of deterministic checks over the material available to that turn.

Bounded, read-only, and fail-closed

Navigation runs in an isolated subprocess so a timeout or native indexing failure cannot take down the MCP server. Public node, hop, token, and body budgets bound the turn. Source stores are read-only; only derived caches may warm. See Grounded navigation for the full pipeline, status calculus, budgets, public JSON, and validation stack.

2. Practice ↔ canon overlay

The memory tree and the zettelkasten are built on the same embedding model and the same KGLite index machinery. That shared vector space is what makes a bridge cheap: a memory entry and a zettelkasten note are directly comparable without any translation layer. Synapse leans on that to do three things — search across both, connect across both, and compare across both — while keeping each store the sole author of its own contents.

as a source intersecting projects memory tree .memory/ · episodic · practice zettelkasten .zettelkasten/ · propositional · canon synapse cross-store connective layer search + frame RRF-fused · store+tier tags .synapse/links/ typed connection overlay practice × canon matrix lens · read-only
The practice ↔ canon capability bridges the two authored stores. Memory and zettelkasten feed unified search/frame and read-only comparison views; the separately built typed-link overlay is written only under .synapse/links/, never back into either source store.

Every hit synapse returns is tagged by store (memory vs zk) and tier (practice vs canon), so a reader can weigh what was actually done here against what the field says — and, most usefully, notice where they disagree.

The practice ↔ canon pieces

Intersection config

A memory graph rarely relates to every zettelkasten project — only a few are relevant. .synapse/config.yaml names the intersecting ZK projects, and that set scopes every synapse operation by default. Any tool call can override it by passing an explicit project list, or pass an empty list to work over memory alone.

Unified retrieval

Synapse presents the memory tree to the zettelkasten's own framing machinery as just another source (a MemorySourceGraph adapter). On top of that it offers two read operations over the combined scope: a search that runs each store's keyword + semantic channels and fuses the ranked lists with Reciprocal Rank Fusion, and a frame that decomposes a research question into facets and characterizes each as established, contested, or thin across both stores.

Typed cross-store connections

Synapse can propose candidate memory↔zettelkasten pairs from two hands-off signals — semantic nearest-neighbours in the shared embedding space, and shared provenance (a memory entry pinned to a file that a note cites). A tool-free LLM pass then types each surviving pair into a relation — applies, corroborates, contradicts, motivated-by, instantiates, or related — with a confidence and a one-line rationale. The surviving edges are persisted to a committed overlay under .synapse/links/, which is signature-stamped so it can detect when either store has drifted and needs a rebuild.

The matrix lens

Because the overlay is a bipartite set of edges, it projects cleanly into a practice × canon matrix: memory (practice) nodes as rows, zettelkasten (canon) nodes as columns, and each typed edge as a cell. Optionally, an LLM rolls each row and column up into a summary and folds those into an apex synthesis — turning the raw link set into a readable comparison surface. The matrix is a read-only lens; nothing is materialized back into either store.

Claim-aligned overlay and grounded synthesis

The generic overlay above links notes of any register — a useful, broad substrate. On top of it synapse builds a second, claim-aligned overlay (kind claim, persisted separately to .synapse/links/claim_links.json) that narrows both endpoints to the registers where a practice↔canon comparison is meaningful: the canon endpoint is restricted to claim/finding notes (preferring multi-source _cross synthesis claims over single-source findings), and the practice endpoint to substantive memory entries (decision/experiment/checkpoint, not the noise of annotations/notes). Because matching a terse memory decision against a formal claim is a recall risk, the claim path leans on the register-independent shared-provenance channel and overfetches nearest-neighbours before applying the type filter.

Each surviving claim-aligned edge is annotated with the canon claim's claim_strength and a blended priority = typer_confidence × f(claim_strength). The typer confidence stays the sole gate (min_confidence); claim_strength only weights the synthesis order — a weak claim keeps a positive priority floor, so it is never silently dropped.

For the highest-value cells — a strong claim met by a high-confidence relation, or any contradiction — synapse can then produce a grounded per-cell brief: one to three sentences stating what the practice did, what the canon claim asserts, and the agreement or tension between them. The brief cites the memory entry id and quotes only the claim's retrieved verbatim quotes (quotes are retrieved, never generated), and an optional deterministic verifier flags any brief whose content does not trace back to that provided material.

That verifier reports a traceability signal, not a semantic-entailment guarantee. verified=True means only that every numeric token and quoted span in the brief traces to the provided material — a fabricated statistic is caught in digits (400bps) and, when it carries a magnitude word or a statistic unit, spelled out (four hundred basis points, twenty percent) — and that the memory id is cited (the id itself is checked as a literal string, so a real hex-id hash never lends its digits to a fabricated number). A standalone bare cardinal used as ordinary prose ("one of our decisions", "the first experiment") is intentionally not treated as a figure, so grounded prose is not over-flagged. It does not judge whether the brief's meaning is correct. Three error classes are deliberately out of scope and will pass the check: lexical meaning-inversion (asserting the opposite using in-vocabulary words — "momentum decreases returns" when the material says it increases them), unit-variant restatements (2.5% where the material says 250bps), and spelled multiplier / fraction / ordinal magnitudes — the spelled-number check covers cardinals plus a magnitude/unit but not multipliers ("double", "tenfold"), fractions ("a quarter", "half") or ordinals used as magnitudes ("a fourth"). In every case the brief is flagged, never rewritten — the verifier surfaces an unfaithful brief for review rather than silently dropping or editing it.

Finally, a practice node that contradicts a strong canon claim is real-world counter-evidence, so those cross-store contradictions are folded into the same WS3 debate map as literature counter-evidence — a claim's contested status can then reflect practice, not just the published record.

Evaluation

A small CLI harness (python -m zettelkasten.synapse.eval) measures synapse's effect on retrieval — comparing results with and without connection expansion — and helps spot-check the precision of the typed edges.

The interface: one dispatcher tool

All of the above is exposed through a single MCP tool, synapse(action=…), mirroring the zettelkasten server's other dispatchers (note, source, citation):

Action What it does
search Hybrid, RRF-fused search across both stores (optionally 1-hop connection expansion).
frame Frame a research question into facets across both stores.
navigate Navigate a bounded heterogeneous substrate and return a deterministic answer or labeled abstention with a versioned answer_surface.
get Read the full body of a memory entry (ground before quoting).
connections List the typed cross-store edges touching a node (pass kind="claim" for the claim overlay).
matrix Project the overlay as a practice × canon matrix (optional LLM synthesis; kind="claim" uses the claim overlay).
synthesize Grounded per-cell briefs over the claim overlay's high-value cells (cites the memory id + retrieved verbatim quotes).
debate Fold the claim overlay's practice→canon contradictions into the WS3 debate map as cross-store counter-evidence.
build (Re)build a connection overlay — the only synapse write, and only to .synapse/links/. Pass kind="claim" for the claim-aligned overlay.

Every action except build is source-read-only. build is the sole authored write, touches only Synapse's own overlay, and is refused when the server runs write-free (for example, the dashboard chat agent). navigate can warm derived indexes and caches under .angelo/, but cannot write memory, zettelkasten, code, datasets, or experiments. The dashboard renders a grounded-answer card only from the trusted navigate tool-completion event—not from model-authored JSON.

Enabling it

Synapse ships with the zettelkasten bundle — there is nothing extra to install:

pip install "angelo[zettelkasten] @ git+https://github.com/natashahirt/angelo"
angelo init --with-zettelkasten

Point it at the relevant projects by listing them in .synapse/config.yaml. The typed-connection overlay lives under .synapse/links/ and is committed to git, so the cross-store links travel with the repo; only the embedding and fulltext caches under .angelo/ are ignored.

Commands

Natural-language phrasings that trigger synapse — say the thing, the agent runs it. See the full command cheatsheet.

Say this What runs
"answer this from the project evidence", "navigate what we know about X", "give me a grounded answer" synapse(action="navigate")
"synthesize", "connect practice to canon", "build the synapse links", "cross-link memory and the zettelkasten" synapse(action="build")
"show the matrix", "practice vs canon", "where do we disagree with the literature" synapse(action="matrix")
"build the claim links", "align practice to claims" synapse(action="build", kind="claim")
"synthesize the cells", "ground the practice–claim briefs" synapse(action="synthesize")
"does practice contradict the literature", "debate map with practice" synapse(action="debate")
"search everything", "look across both stores", "what do we know about X" synapse(action="search")
"frame this across both", "map the landscape (practice + canon)" synapse(action="frame")
"what connects to this", "show the cross-store links" synapse(action="connections")
"find cross-connections", "what links across graphs" suggest(kind="cross-connections")

Design notes

The decisions behind this, drawn as a slice of the memory tree.

  • P Synapse: read-only cross-store layer linking memory tree and zettelkastenactive
    Confirmed plan (in implementation).
  • C Synapse v0 implemented + tools consolidated to one synapse(action=...) dispatcher
    Built the read-only cross-store Synapse layer under zettelkasten/ and consolidated its MCP surface.
  • P Phase: MemDSL grounded navigation capabilityactive
    Build the v1 read engine: a callable, domain-agnostic angelo capability that navigates an n-type substrate and answers with calibrated honesty (grounded where covered, hedged where extrapolated, abstaining where coverage…
  • P Grounded Navigation Productizationactive
    Implement six gated milestones without weakening epistemic honesty: (1) deterministic versioned answer surface, (2) MCP/CLI/dashboard exposure plus model provenance and max_nodes=0 semantics, (3) deterministic and live C…
  • C Grounded Navigation Productization complete
    Completed all six milestones without changing the plan file or canonical corpus_v1 oracle: deterministic answer_surface v1; trusted MCP/CLI/dashboard exposure with transport-authenticated tool provenance, honest model me…
  • P Synapse documentation expansionactive
    Publish the native-resolution Synapse animation, reframe the Synapse explanation as a product hub, add dedicated grounded-navigation and MemDSL v1 pages, wire navigation/cross-links, and verify the strict docs build.
  • R Angelo
    • P synapse — cross-store grounded reasoning layeractive
      • P Synapse: read-only cross-store layer linking memory tree and zettelkastenactive
        • C Synapse v0 implemented + tools consolidated to one synapse(action=...) dispatcher
        • N Added Synapse docs page (own section after Zettelkasten)
        • N Grouped Stream + Synapse under a new docs 'Extensions' section
        • N Docs ang-arch SVG diagrams rendered ~300px left-aligned; root cause = Material figure{width:fit-content}
      • P Phase: MemDSL grounded navigation capabilityactive
        • A Anti-fabrication gotcha: restatement licensing must use verifier-matched SOURCE span, never caller-supplied payload text
        • E Live navigate reaches GROUNDED tier end-to-end; bottleneck is pin-drift staleness starving coverageactive
        • E Live navigate after outdated reframe + git-resolver hardening: grounded+outdated tier solid; the two remaining barriers to a GROUNDED ANSWER are token-budget and MemDSL OUTPUT parse-failactive
        • N Fixed test-pollution: epistemics leaked ZETTEL_SKIP_EMBEDDINGS, starving federated_ann (6 fails -> 0)
        • P Grounded Navigation Productizationactive
          • C Grounded Navigation Productization complete
        • P Synapse documentation expansionactive
          • C Synapse documentation expansion complete

Semantically related entries from the memory graph.