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
relationsmap 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."