-
Notifications
You must be signed in to change notification settings - Fork 0
Federation
Full-size diagram:
public/image/diagram-federation.pdf. Board source:_dream_context/knowledge/diagrams/federation.board.cjs(regenerated bynpm run diagrams).Note: the rendered image still depicts the older PUSH/PULL model (copy-based sync) and is pending regeneration for the read-only pivot — federation now only does the live PULL half described below.
One project rarely lives alone. You have a backend, a marketing site, an internal tool — each its own _dream_context/, each accumulating decisions, and each blind to the others. A decision made in the API repo ("we standardized on cursor pagination") is exactly the kind of thing the dashboard repo's agent should know, but copy-pasting context between projects is the manual re-discovery problem all over again, one directory up.
Federation is the answer, and it is built on the same principle as everything else: opt-in, local, and human-auditable. No server, no account, no background daemon reaching across your machine.
Federation starts with a global registry of vaults — a vault is just a registered _dream_context/ project, addressable by name. The registry (src/lib/vaults.ts) lives in your home directory, not in any one repo, so it is the one shared index every project and the desktop app read from.
dreamcontext vaults discover ~/projects --registervaults discover walks a directory tree (ignoring node_modules), finds every _dream_context/, and — with --register — adds the new ones idempotently. The desktop app's launcher is a GUI over this same registry: every window it opens is a vault by name.
Once vaults are registered, recall can span them. The same BM25 ranker that searches one corpus searches several, and every hit is tagged with the vault it came from:
-
--vault <name>— also search a specific named vault (repeatable). -
--connected— span this vault plus the peers it has an outbound connection to. -
--all-vaults— span this vault plus every vault marked shareable.
The gate is consent: a vault is only reachable from another if its owner ran config shareable on. Recall silently skips vaults that are not shareable or no longer exist on disk, rather than erroring — the same "a missing source is a non-event, not a failure" posture as the version nudge.
You connect two vaults with a direction (out, in, or both); out/both means "this vault may read that peer." There is no per-situation "when to read" rule — a connection is a standing "may read" agreement that resolves live at recall time.
dreamcontext connect api-backend --direction out --topics auth,paginationLive read is the default, not a flag. Plain memory recall already spans connected, shareable peers (memory.ts → resolveConnectedVaults → crossVaultRecall), and the per-prompt UserPromptSubmit recall hook now does too — surfacing each peer's canonical docs (a — Connected peers (live read) — block, namespaced vault::path). It builds the peer corpus at query time and writes nothing; the cost is zero when you have no connections (the path short-circuits). The transitive-leak guard drops federated: true docs from cross-vault serving, so a third vault never sees what merely passed through this one.
dreamcontext federation peers # Compact summary of readable peers (ambient awareness)
dreamcontext federation status # Connections + any leftover federated copies
dreamcontext federation purge --all # Remove leftover federated:true copies from the old sync pathThe desktop launcher's federation network view draws every vault as a card and lets you wire a single relationship by clicking source → target: a violet reads wire — out/both + the target's Readable gate, meaning "A reads B's canonical memory live." A per-node panel and an always-on connections list render the stored directions back as plain sentences ("X reads Y live"), each removable in one click — a direct, auditable window onto the .connections.json direction model.
Earlier builds had a push half: during sleep, a sleep-federation specialist pushed a recall-filtered, lossy digest of each vault into its consenting peers' inboxes (federation sync), and the receiver ingested those as federated: true copies (federation drain). That broke single-source-of-truth — the copies were truncated, went stale the instant the source changed, and a re-edit produced a duplicate plus a false conflict-note instead of refreshing. So it is disabled: federation sync/drain are inert no-ops, the sleep-federation specialist is no longer dispatched, and sleep copies nothing across vaults. The one thing live read structurally can't do is survive a peer going offline; a redesigned, explicitly opt-in offline-mirror mode may return for that case, but only after a proper design.
The security model mirrors the dashboard's loopback-and-CSRF posture. The browser-reachable route (POST /api/federation/sync) is dry-run by construction — it returns deltas with a constant dryRun: true, and no file under src/server/routes/ may import a federation write function, so a crafted loopback request cannot write into a peer vault. The destructive federation purge is CLI-only and guarded: it requires an explicit --all/--vault flag and, before any unlinkSync, resolves symlinks and rejects anything that escapes the vault's knowledge/ directory. .connections.json writes are atomic (temp-file + rename with a per-write nonce) so concurrent CLI/launcher writers never clobber a direction. Dead or unreachable peers are skipped (warned once), so a deleted sibling never stalls recall.
- Why It Exists
- The Problem in Depth
- The Architecture
- The Hook Mechanism
- The Sleep Cycle
- Neuroscience-Inspired Memory
- The Dashboard
- Project task overrides
- Council Debates
- Memory Recall (BM25 over the curated corpus)
- Lab (Insights)
- Automations
- Federation
- Brain Cloud Sync
- Linked Repos
- Obsidian Integration
- CLI Design
- Install & Update
- The Desktop App
- Design Tradeoffs
- What Comes Next