Skip to content

DDR-002 — Bidirectional sync and vault portability

Version: 0.1.0 | Date: 2026-04-12 | Status: Accepted

Context

DDR-001 established a faceted classification system where relations (INSTANCE_OF, COMPOSED_OF, IN_DOMAIN, etc.) are the primary mechanism for cross-domain discovery. These relations lived exclusively in Neo4j. The Obsidian vault stored only node properties in its frontmatter.

This created an asymmetry: if Neo4j was lost, engrama_sync_vault could recreate nodes from the vault, but all faceted relations were gone — the most valuable part of the graph. The vault was portable (plain .md files on any sync service); the graph was not.

Decision

Serialize all relations into each note's YAML frontmatter. Both vault and graph are co-equal sources of truth. Bidirectional sync keeps them coherent.

Frontmatter format

---
engrama_id: 550e8400-e29b-41d4-a716-446655440000
type: Problem
name: implicit-type-coercion-bug
status: resolved
relations:
  INSTANCE_OF: [type-safety-violation]
  COMPOSED_OF: [TypeScript]
  SOLVED_BY: [enable-strict-null-checks]
  BELONGS_TO: [EOElite]
  IN_DOMAIN: [web-development]
---

Sync contract

Direction Trigger What happens
Graph → Vault Model creates/deletes a relation via engrama_relate Relation is written/removed from source note's frontmatter
Vault → Graph engrama_sync_vault (normal mode) All relations in frontmatter are MERGED into Neo4j
Graph → Vault engrama_sync_vault --from-graph All notes regenerated with full frontmatter from graph

Resolution rules

Scenario Resolution
Relation exists in both No action (idempotent MERGE)
Relation in vault, not in graph Create in graph (vault wins — portability)
Relation in graph, not in vault Write to vault frontmatter (graph wins — operational)
Conflict (different targets) Flag for user review, don't auto-resolve

Relation values

  • Values in the relations map are arrays of target node names (or titles), not engrama_ids.
  • Names are human-readable and portable. IDs are internal.
  • If a target node doesn't exist during sync, create a stub node (name only, status: "stub").

Consequences

Positive

  • Full portability: vault on any cloud sync service → new machine → engrama_sync_vault → full graph.
  • True backup: vault IS the backup. No separate export/import needed.
  • Human-readable relations: anyone can read the frontmatter and understand the entity's classification.
  • Git-friendly: relations as YAML diffs are reviewable and mergeable.

Negative

  • Frontmatter size: heavily connected nodes produce verbose frontmatter. Acceptable — YAML handles arrays well and Obsidian doesn't choke on large frontmatter.
  • Dual write cost: every relation write is two operations (graph + vault). Acceptable — the vault write is a small file edit.
  • Sync complexity: bidirectional sync is inherently more complex than unidirectional. Mitigated by MERGE semantics (idempotent) and conflict flagging (no silent overwrites).

Supersedes

This DDR modifies Rule 9 from the system prompt. Previous: "Vault is derived, graph is truth." New: "Bidirectional sync — when creating a relation in the graph, ALWAYS write it to the note's frontmatter too."