
# Storage Model

Version history uses a **keyframe + change-log** model for storage efficiency. Keyframes are full snapshots stored as separate `vN.md` files; every intermediate version is stored as a **unified-diff change log** for that version.

## Directory structure

```
.versions/
├── context_history.yaml          # Vault-level checkpoint history
└── nodes/
    └── architecture/
        ├── history.yaml          # Version history + per-version diffs
        ├── v1.md                 # Keyframe (full snapshot)
        └── v4.md                 # Keyframe (full snapshot, every N versions)
```

In the inspected engine build, each intermediate version's **unified-diff change log is stored inline** in `history.yaml` as a `diff:` field on that version's entry — only keyframes are written as separate `vN.md` files. (Separate suggestion patches — `.patch` files — are drift suggestions, not version change logs.)

## history.yaml

Each document's version history — including the per-version diff:

```yaml
document_id: nodes/architecture
versions:
  - version: 1
    edited_by: "alice@example.com"
    edited_at: "2026-01-15T10:00:00Z"
    published_at: "2026-01-15T10:00:00Z"
    content_hash: "sha256:a1b2c3..."
    chain_hash: "sha256:d4e5f6..."
    keyframe: true
    note: "Initial version"
  - version: 2
    edited_by: "bob@example.com"
    edited_at: "2026-02-01T14:30:00Z"
    published_at: "2026-02-01T14:30:00Z"
    content_hash: "sha256:g7h8i9..."
    chain_hash: "sha256:j0k1l2..."
    keyframe: false
    diff: |                       # unified diff v1 → v2, stored inline
      Index: v2
      ===================================================================
      --- v1
      +++ v2
      @@ ...
```

Keyframes are written every `keyframe_interval` versions (default **10**), so no read ever replays more than ~10 diffs from a keyframe.

Version numbering is **graft-proof**: numbering is fixed at the source (the engine's `nextVersion`), and the `repair-version-chains` path re-anchors any already-grafted document onto its live bytes without renumbering, so a node cannot be grafted onto another history. New nodes start at **version 1** (`ctx add` creates v1).

## Reconstruction

Any version can be reconstructed by applying change-log diffs forward from the nearest keyframe:

```bash
ctx reconstruct nodes/architecture 3
```

Reconstruction is **lazy** — it reads the nearest keyframe (≤ the target version) and applies only the diffs needed to reach the requested version, rather than replaying the whole chain. Keyframe files are self-contained and safe to read without the diff chain.

## Performance

The published storage model is designed to scale **linearly** with vault size — the keyframe + per-version diff layout and lazy chain reads keep throughput proportional to document count rather than degrading as history grows. A reference benchmark cited for the current engine is roughly **~108 seconds for 10,000 documents**.

