Modes of Use

This page is the diagnostic that decides what the rest of the chapter means for you — whether you are building a Commit Application, a service over the Commit Database, a CLI tool, or a batch script. The architectural choice between single-stream and multi-stream usage — and within multi-stream, between local and strong invariants — is effectively irreversible once a DSM model is sealed: Commit carries no migration tooling, so switching regimes after the fact is a schema rewrite that invalidates existing data.

The asymmetry runs one way: a multi-stream-friendly model is harmless in single-stream usage; a single-stream model has no safe path to multi-stream. In doubt, model for multi-stream.


Two kinds of version DAG

Two distinct families of versioning systems share vocabulary (commit, merge, head, parent) and topology (a DAG of nodes with one or more parents), but differ on what a node contains.

Some systems (git, hg, fossil) are snapshot DAGs: each node contains a full state of the tree. Their merge reconciles states; when states disagree, the algorithm cannot pick and surfaces a conflict for human arbitration.

The Commit Database is a mutation DAG: each node contains a sequence of path-based mutations. Its commitMerge composes mutation sequences; when mutations target the same path, deterministic composition rules apply (last-writer-wins by linearisation order). No conflict is ever surfaced. This is what makes mechanical reduction possible — and what makes the Dual-Layer Contract necessary.

Habits built in snapshot DAGs do not transfer cleanly. Read on with this distinction in mind.


Two orthogonal axes

How you exercise the mutation DAG splits along two independent axes, and conflating them is the most common source of confusion.

  • What you can do — the operation axis. Time travel, undo / redo and multi-head exploration are always available, in every context.

  • Where you do it — the context axis. Single-stream, multi-stream with local invariants, or multi-stream with strong invariants. The context alone decides whether the engine ever has to pick a winner, and therefore whether the Dual-Layer Contract applies to you.

The Dual-Layer Contract applies along the context axis, not the operation axis. An undo is trivial in single-stream; the same undo in multi-stream reads through a state an earlier commitMerge produced. The operation did not change — the context did.

Read both sections as a diagnostic, not a catalogue.


What you can do — the operation axis

These three operations are available regardless of context. What changes with context is not whether you can perform them, but whether the state they read has already passed through commitMerge.

Time travel

Read-only. Reconstruct any past state from a commitId. No writes, so only the read-side structural guarantees apply: determinism, immutability, content-addressing.

Undo / redo

Append-only. Step back along the chain, diverge, redo. Undo never rewrites history — it masks its target with an Enable/Disable commit. All structural guarantees apply.

Multi-head exploration

Parallel heads. Diverge the DAG and keep parallel heads alive, merging them back on your own schedule. Multi-head exploration where a single author reviews each merged result stays single-stream — the merge happens, but one person owns the resulting state.

Important

In single-stream every read returns exactly what you wrote. In multi-stream every read is an import — a state structurally sound but semantically untrusted, to be re-validated at read time. This includes reads of past states, because that state was itself produced by commitMerge. The three operations above do not change between the two contexts; what changes is the contract around the state they read.


Where you do it — the context axis

Single-stream

One author writing at a time. No commitMerge is reconstructed at read time, so the Dual-Layer Contract is reference material, not load-bearing. Time travel, undo / redo and multi-head exploration all apply with only the read-side structural guarantees — there is nothing for the engine to pick between.

Multi-stream

Multiple authors’ writes are reduced automatically by mechanical reduction. Two flavours, split by what your invariants look like.

  • Local invariant — its truth depends only on a structurally disjoint subset of the data (one attachment, one path, one document, or a container used only where it is commutative — a set / map, or an xarray read as a set of elements). Two authors writing on disjoint paths cannot break it: the disjointness shields the invariant from reduction.

  • Strong invariant (also called global) — its truth couples data that multiple authors can write in parallel: uniqueness across the whole model (no two assets share an SKU), referential integrity between attachments (an edge must point to an existing vertex), cross-document consistency, or any domain that does not tolerate silent loss (financial, safety, regulatory).

Re-validating at read time closes the gap for local invariants — there was nothing for reduction to break. It does not close the gap for strong invariants: read-side validation can detect a violation, but cannot reconstruct the intent that reduction dropped. The lost information is not recoverable downstream.

Multi-stream with local invariants

Multiple authors’ writes are reduced automatically, but the structural drops cost you nothing in practice. Two routes lead here:

  • Naturally local invariants — the entire mutable state lives in containers whose convergence is commutative by construction (set / map union / subtract), or in an xarray read only as a set of elements. An xarray converges on membership — no insert is lost — but the relative order of concurrently-inserted elements is not commutative, so an order-dependent invariant is not naturally local. Where the invariant is membership-only, there is nothing for the engine to silently break.

  • Defensive-by-design — cross-attachment references exist and may break under reduction, but the application is built from day one to tolerate the break: load robustly, surface the integrity issue, expose corrective actions to the user. This is an uncommon architectural choice — most applications are not built this way.

The Graph Editor sample exemplifies the second route: EdgeTopology references vertices, and the model ships ModelIntegrity as a user-facing repair pool (recreate, delete, or respawn missing elements), on top of an application that loads graphs with broken integrity without crashing.

For this mode the Dual-Layer Contract is reference material, not load-bearing.

Multi-stream with strong invariants

Multiple authors’ writes are reduced automatically; your invariants are global (uniqueness, referential integrity the engine must uphold), or your domain does not tolerate silent loss (financial, safety, regulatory). This is where the Dual-Layer Contract becomes load-bearing — and where reading it is a diagnostic, not a cookbook: the four post-reduction outcomes (Ignore / Extract a subset / Correct / Reject) collapse to Reject, which is equivalent to saying mechanical reduction was the wrong primitive.

The exit is not better post-reduction handling. It is re-architecting toward multi-stream with local invariants via scope decomposition (see Cooperative Discipline), or building an application-level supervisor on top of Commit — a review UI, a semantic gate, or a coordination protocol that arbitrates before the engine reduces.