|
| 1 | +# ADR-0004: Content Attachments Belong in git-warp |
| 2 | + |
| 3 | +- **Status:** Accepted |
| 4 | +- **Date:** 2026-02-20 |
| 5 | +- **Deciders:** Git Mind maintainers |
| 6 | +- **Related:** ADR-0002, ADR-0003, WARP Paper I (aion-paper-01), M13A VESSEL-CORE roadmap milestone |
| 7 | +- **Upstream impact:** git-warp, git-cas |
| 8 | + |
| 9 | +--- |
| 10 | + |
| 11 | +## 1. Context |
| 12 | + |
| 13 | +The M13A (VESSEL-CORE) roadmap milestone calls for a content-on-node system: the ability to attach rich content (documents, specs, narratives) to graph nodes, stored as content-addressed blobs, with full CRDT versioning and time-travel. |
| 14 | + |
| 15 | +The original plan placed this system entirely in git-mind: a `ContentStore` abstraction, a `_content` property convention, `git mind content set/show` commands, storage policy engine, and provenance receipts. |
| 16 | + |
| 17 | +On review, the storage primitive — attaching a content-addressed blob to a graph node — is not a domain concern. It is a graph-level operation that belongs in git-warp. |
| 18 | + |
| 19 | +### 1.1 The Paper Says So |
| 20 | + |
| 21 | +WARP Paper I defines a WARP graph as `(S, α, β)` where: |
| 22 | + |
| 23 | +- `S` is a finite directed multigraph (the skeleton) |
| 24 | +- `α : V_S → WARP` assigns an **attachment** to every vertex |
| 25 | +- `β : E_S → WARP` assigns an **attachment** to every edge |
| 26 | + |
| 27 | +Attachments are full WARP graphs or **atoms**: `Atom(p)` for some payload `p ∈ P`, where P is "the stuff we are not going to model internally (bytestrings, floats, external object IDs, ...)". |
| 28 | + |
| 29 | +Currently, git-warp models nodes and edges with flat key-value properties. There is no first-class concept of an attachment payload. Content-addressed blob attachment is the concrete realization of `Atom(p)` — it gives nodes (and potentially edges) the ability to carry opaque payload data, exactly as the paper's formalism requires. |
| 30 | + |
| 31 | +### 1.2 The Layering Argument |
| 32 | + |
| 33 | +If content attachment lives in git-warp: |
| 34 | + |
| 35 | +- **Time-travel works for free.** Content SHAs are properties; `materialize({ ceiling })` already handles property-level time-travel. |
| 36 | +- **Multi-writer merge works for free.** CRDT conflict resolution on the SHA property follows existing semantics. |
| 37 | +- **Observer scoping works for free.** Content visibility follows node visibility. |
| 38 | +- **Provenance is already tracked.** Every property mutation carries tick/writer metadata. |
| 39 | +- **Any tool on git-warp gets it.** Not just git-mind — any future consumer of the WARP graph API can attach and retrieve content. |
| 40 | + |
| 41 | +If content attachment lives in git-mind, all of the above must be re-implemented or worked around at the application layer, duplicating guarantees that already exist in the substrate. |
| 42 | + |
| 43 | +--- |
| 44 | + |
| 45 | +## 2. Decision |
| 46 | + |
| 47 | +**Content attachment is a git-warp responsibility, not a git-mind responsibility.** |
| 48 | + |
| 49 | +git-warp should: |
| 50 | + |
| 51 | +1. **Install `git-cas` as a dependency** — providing content-addressed blob storage backed by the git object store. |
| 52 | +2. **Expose an API for attaching content to nodes** — this could be as simple as a property convention (e.g., a CAS key stored as a node property), or a dedicated method on the patch/node API. The exact API design is git-warp's decision. |
| 53 | +3. **Expose content read/retrieval** — given a node, retrieve its attached content blob. |
| 54 | + |
| 55 | +git-mind's role becomes a thin CLI/UX layer: |
| 56 | + |
| 57 | +- `git mind content set <node> <file>` — CLI command that calls the git-warp attachment API |
| 58 | +- `git mind content show <node>` — CLI command that reads and displays attached content |
| 59 | +- `git mind content edit <node>` — editor integration, crash recovery, conflict handling (M13B) |
| 60 | +- Storage policy (MIME thresholds, size limits) — domain-level configuration |
| 61 | +- Materialization templates that consume attached content (M14) |
| 62 | + |
| 63 | +--- |
| 64 | + |
| 65 | +## 3. Alternatives Considered |
| 66 | + |
| 67 | +### 3A: Content system entirely in git-mind (original M13A plan) |
| 68 | + |
| 69 | +git-mind implements `ContentStore` over git plumbing, manages `_content` property convention, handles CAS operations directly. |
| 70 | + |
| 71 | +**Rejected because:** |
| 72 | +- Duplicates CRDT/time-travel/observer guarantees already in git-warp |
| 73 | +- Other git-warp consumers cannot benefit |
| 74 | +- Thickens the git-mind layer with storage plumbing that isn't domain logic |
| 75 | +- Diverges from the paper's formalism, which places attachments at the graph level |
| 76 | + |
| 77 | +### 3B: Content as plain git-warp properties (no CAS, inline values) |
| 78 | + |
| 79 | +Store content directly as property values on nodes. |
| 80 | + |
| 81 | +**Rejected because:** |
| 82 | +- Property values are not designed for large payloads (documents, images) |
| 83 | +- No deduplication across nodes with identical content |
| 84 | +- No streaming/chunking for large files |
| 85 | +- Misses the `Atom(p)` semantics — atoms are opaque external references, not inline data |
| 86 | + |
| 87 | +--- |
| 88 | + |
| 89 | +## 4. Consequences |
| 90 | + |
| 91 | +### For git-warp |
| 92 | + |
| 93 | +- New dependency: `git-cas` |
| 94 | +- New API surface: content attachment on nodes (and potentially edges) |
| 95 | +- Closer alignment with Paper I's `(S, α, β)` formalism |
| 96 | +- git-warp's README/docs should reference the attachment concept |
| 97 | + |
| 98 | +### For git-mind |
| 99 | + |
| 100 | +- M13A scope shrinks significantly — git-mind provides CLI/UX, not storage |
| 101 | +- M13B (content editing UX) is unaffected — editor integration remains a git-mind concern |
| 102 | +- Existing property-based workflows are unaffected |
| 103 | +- The `_content` property convention (if that's the API shape) is documented as a git-warp concern, not a git-mind convention |
| 104 | + |
| 105 | +### For the roadmap |
| 106 | + |
| 107 | +- M13A splits: upstream work in git-warp (attachment API), then thin git-mind CLI layer |
| 108 | +- M14 (FORGE/materialization) benefits — the materialization pipeline reads content via the same git-warp API, no git-mind-specific content abstraction needed |
| 109 | +- M16 (CITADEL/trust) benefits — trust-scoped content visibility is just trust-scoped property visibility |
| 110 | + |
| 111 | +--- |
| 112 | + |
| 113 | +## 5. Relationship to the Paper |
| 114 | + |
| 115 | +| Paper concept | git-warp realization | |
| 116 | +|---|---| |
| 117 | +| `Atom(p)` — opaque payload | CAS blob referenced by SHA | |
| 118 | +| `α(v)` — vertex attachment | Content property on node | |
| 119 | +| `β(e)` — edge attachment | Content property on edge (future) | |
| 120 | +| `P` — set of atomic payloads | Git object store (content-addressed) | |
| 121 | +| Depth-0 attachment | A node whose attachment is a single blob | |
| 122 | +| Deeper attachments | Future: nested WARP graphs as attachments (not in scope for this decision) | |
| 123 | + |
| 124 | +This ADR addresses the depth-0 case: nodes carry `Atom(p)` payloads via CAS. The full recursive attachment model (`α(v)` mapping to arbitrary WARP graphs) is a future concern — but this decision establishes the correct layering so that deeper attachments can be added later without architectural rework. |
| 125 | + |
| 126 | +--- |
| 127 | + |
| 128 | +## 6. Open Questions (for git-warp) |
| 129 | + |
| 130 | +These are implementation details for the git-warp maintainers: |
| 131 | + |
| 132 | +1. **API shape:** Dedicated `node.attach(blob)` / `node.content()` methods, or a property convention like `_content: <cas-sha>`? Either works; the former is more discoverable. |
| 133 | +2. **Edge attachments:** Should edges also support content attachment from day one, or is node-only sufficient for the first iteration? |
| 134 | +3. **Integrity verification:** Should `getContent()` verify the SHA on read, or trust the object store? |
| 135 | +4. **MIME / metadata:** Should git-warp store content metadata (MIME type, size, encoding) alongside the CAS reference, or leave that to consumers like git-mind? |
0 commit comments