Skip to content

git-stunts/git-warp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3,163 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

A Git-native runtime for shared causal history.

Offline-first, multi-writer, deterministic, and built for provenance-aware graphs.

CI License npm version

git-warp is a Git-native system for storing and reading causal history.

Instead of treating a graph as one big in-memory object, git-warp treats history as the source of truth. Reads are bounded views over that history, and writes are appended as patches. It is one runtime in the Continuum stack (more below).

If that sounds abstract, the short version is:

  • You can work offline.
  • Multiple writers can contribute without central coordination.
  • Conflicts resolve deterministically.
  • Every value keeps provenance.
  • Reads are designed to stay bounded, not accidentally materialize everything.

What it does

git-warp provides a causal history substrate and read/runtime layer for graph-shaped data.

It lets you:

  • Commit patches into a shared causal log.
  • Read the latest visible state through worldlines.
  • Read historical coordinates without rewriting history.
  • Use observers and apertures to control what a reader can see.
  • Keep provenance attached to values and outcomes.
  • Sync through normal Git transport.

Latest release

v18.1.2 publishes the source-backed reference shelf for package entrypoints, root API exports, CLI commands, structured CLI errors, and public error classes. It also locks the release path so release-prep PRs tag the exact merged main commit, then publish npm and JSR from a maintainer-dispatched workflow.

See CHANGELOG.md for the full in-repository release notes.

Quick start

import { GitGraphAdapter, openWarpWorldline } from "@git-stunts/git-warp";
import GitPlumbing from "@git-stunts/plumbing";

const plumbing = new GitPlumbing({ cwd: "." });
const persistence = new GitGraphAdapter({ plumbing });
const events = await openWarpWorldline({
  persistence,
  worldlineName: "events",
  writerId: "agent-1",
});

// Commit: admit a claim into shared causal history.
await events.commit((patch) => {
  patch.addNode("user:alice").setProperty("user:alice", "role", "admin");
});

// Read: confirm what is visible through the worldline.
const visible = await events
  .live()
  .query()
  .match("user:alice")
  .select(["id"])
  .run();

Bounded coordinate reads with optics

The live() query above reads the latest visible state. When you instead want a bounded, coherent read pinned to a point in history, you read through an optic.

  • An optic is the bounded question you ask of causal history — "which node, property, neighbor set, or traversal do I want?" It names the read you mean instead of materializing the whole graph to go looking.
  • We use optics so reads stay scoped and coherent: an optic answers from a fixed position, so concurrent writes can't shift the result mid-read, and the runtime only touches the causal support the question actually needs.
  • An optic basis is the bounded evidence that the read can be answered honestly from history — a verified checkpoint-tail basis. prepareOpticBasis() establishes it. If no bounded basis exists yet, it fails closed with E_OPTIC_NO_BOUNDED_BASIS rather than silently materializing everything.
  • An optic always reads through an observer coordinate: coordinate() captures a stable, observer-relative position (a causal basis plus a ceiling). Later writes advance the live worldline, but reads through that coordinate keep answering from the captured position.
  • Missing non-empty nodes and properties read as absence data. Empty target identities are invalid optic schemas and fail with E_OPTIC_FAILURE_SCHEMA.

So the order is: verify the basis, capture a coordinate, then read through it.

await events.prepareOpticBasis();
const coordinate = await events.coordinate();
const role = await coordinate.optic().node("user:alice").prop("role").read();

For the Nerds™: Optics

In category theory, an optic from a whole $(S, T)$ to a part $(A, B)$ is an element of a coend — an existential package over a residual object $M$:

$$\mathrm{Optic}\big((S,T),,(A,B)\big) ;=; \int^{M} \mathcal{C}!\left(S,; M \otimes A\right) \times \mathcal{C}!\left(M \otimes B,; T\right)$$

That is a focus $S \to M \otimes A$ paired with a put-back $M \otimes B \to T$, where $M$ — everything you didn't look at — is sealed inside the existential and never named.

git-warp's read model is the read-only half. The whole $S$ is a coordinate (a reading over causal history); the part $A$ is the bounded question (.node(), .prop(), a traversal); the residual $M$ is the rest of history you deliberately do not materialize. The bounded support rule is that $M$ made small and explicit, and prepareOpticBasis() is the witness that a lawful factorization $S \to M \otimes A$ exists at the chosen coordinate. No witness ⇒ E_OPTIC_NO_BOUNDED_BASIS: the runtime refuses the read rather than collapsing $M$ back into the whole graph.

And .node("user:alice").prop("role") is literal optic composition — composing optics tensors their residuals ($M_1 \otimes M_2$), so a chained read stays bounded by construction.

Bounded reads in practice

Two more shipped reads stay bounded without folding the whole graph. Both use the advanced openWarpGraph() surface.

const graph = await openWarpGraph({ persistence, graphName: "events", writerId: "agent-1" });

// What changed between two live Lamport ceilings — a frozen GraphDiff, not a wildcard scan.
const diff = await graph.comparison.diff({ from: 120, to: 135, targetId: "user:alice" });

// One entity's backward causal cone, replayed on its own (a diagnostic read).
const slice = await graph.provenance.materializeSlice("user:alice");

See examples/ for runnable versions and Optic reads for the model.

Core ideas

git-warp's concepts span how history is written, positioned, read, accelerated, proven, and persisted. The map marks runtime posture directly. Status markers: no mark = shipped runtime truth, ~ = transition (the noun exists but is narrower than its canonical meaning), * = target (intended architecture, not yet a first-class runtime concept).

mindmap
  root((git-warp))
    Write
      Patch
      Worldline ~
      Live strand ~
      Braid *
    Position
      Coordinate ~
      Frontier ~
      Ceiling
      Tick ~
    Read
      ProjectionHandle
      Observer ~
      Aperture ~
      Optic ~
      Optic basis
    Support
      Bounded support rule ~
      Causal index ~
      Support fragment ~
      Materialization plan *
    Prove
      Witness *
      TickReceipt
      GraphDiff ~
      Suffix admission shell ~
    Persist
      Snapshot
      State cache
      Checkpoint ~
Loading
Concept Status One-line meaning
Patch shipped An appended claim about a bounded causal site; never rewritten.
Worldline transition The named causal history a writer commits to and readers observe.
Live strand transition A strand over a live parent basis plus its own owned overlay divergence.
Braid target A composition of lanes; common-basis braid validation is not yet shipped.
Coordinate transition A comparable read point: a causal basis plus a ceiling.
Frontier transition The causal basis — which history has been observed (writer tips / version vectors).
Ceiling shipped The upper replay boundary on a coordinate or lane.
Tick transition One atomic admitted history step on a lane.
ProjectionHandle shipped A pinned read handle returned by live() and seek().
Observer transition A read surface that answers a question through an aperture.
Aperture transition The { match, expose, redact } policy bounding what an observer sees.
Optic transition A first-class runtime read-intent noun used by fluent optic reads; native Continuum transport remains future work.
Optic basis shipped Verified bounded evidence (prepareOpticBasis()) that an optic read is answerable without full materialization.
Bounded support rule transition The smallest causally sufficient support set to answer an optic honestly.
Causal index transition A rebuildable acceleration structure that finds support without whole-graph discovery.
Support fragment transition A cached partial materialization keyed by support and coordinate (cache storage pending).
Materialization plan target The plan deciding receipts vs. indexes vs. fragments vs. replay vs. full state.
Witness target Minimal information sufficient to justify a local change result.
TickReceipt shipped The operational envelope recording what happened for one admitted step.
GraphDiff transition A first-class "what changed between these coordinates?" result.
Witnessed suffix admission shell transition Observer-readable import/export envelope for a transported suffix; live Echo/git-warp network exchange remains Continuum stack work.
WarpStateSnapshot shipped A persisted materialized graph state at a coordinate.
WarpStateCache shipped The owning system for persisted and in-memory snapshot reuse.
Checkpoint transition A pinned snapshot protected from ordinary eviction.

The topic pages own the current explanations for these nouns. Exact API, CLI, schema, and error inventories should be generated or coverage-checked rather than maintained as long-form prose; see the generated source-backed reference.

Optic is now a reified runtime noun for the public read path. The fluent API lowers into a frozen Optic value before execution; see Optic reads.

How it works

Deterministic and offline-first

Writers can make independent changes without a central coordinator. When history converges, the same patches produce the same visible result.

For the Nerds™ — Convergence is a join-semilattice

Deterministic multi-writer merge is the statement that materialized state forms a join-semilattice $(L, \sqcup)$: a partial order with a least upper bound for any pair. Each writer's patches push state up the order, and merge is the join $\sqcup$ — idempotent, commutative, and associative:

$$x \sqcup x = x \qquad x \sqcup y = y \sqcup x \qquad (x \sqcup y) \sqcup z = x \sqcup (y \sqcup z)$$

Those three laws are exactly what "no central coordinator" buys you:

  • commutativity ⇒ writers can apply each other's patches in any order,
  • associativity ⇒ they can batch them however the network delivers them,
  • idempotence ⇒ re-delivering the same patch is harmless.

So convergence isn't luck; it's the least upper bound $\bigsqcup_i h_i$ of everyone's observed history $h_i$. This is the CRDT (state-based / CvRDT) guarantee: monotone updates into a semilattice always reconcile to the same join, independent of message order or duplication.

Append-only

History is never rewritten. New claims are appended to Git refs under refs/warp/....

Provenance-aware

Every visible value traces back to the patch that produced it.

Bounded reads

The runtime is designed so reads stay scoped. It avoids the “just materialize the whole graph” footgun.

For the Nerds™ — A causal cone is a down-set

History is a poset $(H, \preceq)$ under causal precedence (Git's parent edges give the Hasse diagram). A coordinate picks a consistent cut: a down-closed set, i.e. a down-set / order ideal

$$\downarrow! C ;=; {, x \in H \mid x \preceq c \text{ for some } c \in C ,}.$$

A frontier is that cut's boundary — an antichain of writer tips, the maximal elements of the ideal.

A read's causal cone $D(v) = {\downarrow}{v}$ is the down-set generated by $v$: everything that could have influenced it, and nothing that couldn't. Because the poset is well-founded, $D(v)$ is finite even when $H$ is unbounded — which is why a bounded read can exist at all. The bounded support rule is then just the claim "this optic's answer factors through $D(v)$, so materializing the rest of $H \setminus D(v)$ is provably unnecessary."

Holographic history

History keeps per-entity provenance, so a single node's backward causal cone can be reconstructed and replayed on its own: provenance.materializeSlice(nodeId) loads only the cone's patches, never the whole graph. This slice path is currently classified as a diagnostic read, not a first-use application API.

The broader worldline-wide direction is still narrower than the doctrine: live strands and support fragments have runtime footholds, but support-fragment cache storage, plan-driven fragment execution, and full holographic worldline reads are not first-use shipped paths. See Runtime posture, Optic reads, and Strands.

API surface

The main application entry point is openWarpWorldline().

A worldline gives you a small, practical interface:

Method What it does
commit() Admits a patch into the worldline
live() Reads the latest visible state
seek() Reads a historical coordinate
observer() Creates a filtered read view
prepareOpticBasis() Verifies bounded evidence for coordinate-based reads
coordinate() Captures a stable causal position
optic() Starts a one-off read that lowers through a reified Optic

For coherent optic reads, call prepareOpticBasis() first, then read through a coordinate.

If no bounded basis exists yet, prepareOpticBasis() fails closed with E_OPTIC_NO_BOUNDED_BASIS rather than materializing the whole graph.

Advanced tooling can also use openWarpGraph() directly. That lower-level surface is intended for compatibility, diagnostics, substrate operations, and migration work. New application code should generally prefer worldlines and optics.

Architectural moments

openWarpGraph() exposes the runtime through four moments:

Moment Capabilities What it does
Commitment patches, strands, comparison Admits claims into frontier-relative truth
Folding checkpoint Re-expresses admitted history as operational artifacts
Revelation query, subscriptions, provenance Exposes admitted truth under bounded rights
Governance sync Transports and admits remote suffixes

Public examples use the flat aliases like graph.query and graph.checkpoint. The moment-scoped names are the same runtime object with more explicit naming.

Why Git

Git and WARP fit together because both are:

  • append-only in spirit.
  • content-addressed.
  • distributed and multi-writer.
  • history-preserving.

Each writer appends patch commits under refs/warp/<graph>/writers/<writerId>. The refs stay outside normal branch history, so graph history stays separate from your checked-out source tree. Patch commits may carry patch and content trees; the isolation comes from refs and Git plumbing, not from pretending every data commit is empty. Sync uses normal git push and git fetch over the WARP refs.

For the Nerds™ — Git as a Merkle DAG, patches as a free monoid

Git's object store is a Merkle DAG: every object is named by the hash of its content, so a commit's id transitively fixes its entire history. That gives structural sharing (equal subhistories are stored once — hash-consing) and tamper-evidence for free: change one byte upstream and every downstream id changes.

git-warp leans on two consequences. First, each writer's chain at refs/warp/<graph>/writers/<writerId> is the free monoid $(W^{*},, \cdot,, \varepsilon)$ on that writer's claims $W$ — append-only concatenation $\cdot$, empty history $\varepsilon$ as identity, no rewriting. Second, the commits live on WARP refs rather than source-tree refs, so graph history rides Git's transport and dedup without touching your working tree. Merge law lives one layer above this (see the semilattice note); Git supplies the verifiable spine.

Continuum

git-warp is one runtime in the Continuum stack. Continuum is not a runtime, database, or storage engine — it is the shared boundary protocol that lets independent runtimes, apps, debuggers, and agents exchange witnessed history instead of copying one database or scraping UIs.

Continuum's model shift is the same one git-warp is built on:

The graph is a coordinate chart over witnessed causal history. History is the territory; state is a policy-relative materialized view; files are readings; writes are intents; admission is witnessed.

Its shared vocabulary is Intent → Admission → Witness → Reading:

  • Intent — "I want to do this" (a submitted patch).
  • Admission — the runtime decides whether it can happen.
  • Witness — evidence for the decision (receipts, provenance).
  • Reading — one lawful view of the resulting history (worldlines, optics, observers).

In the stack, git-warp and Echo own runtime truth, while Continuum owns the boundary language and proof posture that lets those runtimes cooperate across the network.

When to use it

Use case Fit
Offline-first multi-writer convergence Strong
Agent/tool substrate with causal history Strong
Graph semantics without inventing merge law Strong
Speculative lanes for what-if exploration Strong
High-throughput real-time execution Use Echo instead
General-purpose OLTP Use Postgres
Full-text search / analytics Use purpose-built engines
Time-travel debugging UI Use warp-ttd on top of git-warp

Runtime posture

Current first-use docs teach openWarpWorldline(), worldline reads, coordinates, reified optics, and observer apertures as the application path. GitWarpWitnessedSuffixAdmissionShell is a transition runtime envelope, not proof of live network exchange. Native Continuum witnesshood, remote optic transport, common-basis braid validation, live Echo/git-warp suffix exchange, support-fragment cache storage, and plan-driven fragment execution remain outside the first-use shipped path unless their own docs say otherwise.

Documentation


FAQ

What is git-warp, really?

A Git-native causal history runtime. It stores graph-shaped data as an append-only log of patches in Git refs, then provides safe, bounded reads over that history.

It is deliberately "weird": optimized for offline-first, multi-writer, provenance-first use cases rather than high-throughput OLTP.

How does it differ from a normal CRDT or graph database?

It is a state-based CvRDT substrate with strong emphasis on bounded reads, perfect provenance, and Git as the transport layer.

This gives you deterministic convergence without a central server, but reads are intentionally scoped (via optics and coordinates) instead of materializing the entire graph.

What does the data model look like?

Nodes, properties, and directed edges identified by stable string IDs. Changes are additive patches that are never rewritten. See Getting started.

Can multiple people/agents write at the same time?

Yes — independently, even fully offline. Histories converge deterministically via the join-semilattice model. No locking required.

How do I install and set it up?

npm install @git-stunts/git-warp @git-stunts/plumbing

Works alongside any existing Git repo. Full setup: Getting started.

How does syncing work?

Standard Git (push/fetch/pull). Patches live under refs/warp/....

How are reads secured/filtered?

Observers + Apertures with { match, expose, redact } policies for different views over the same history.

Is it production ready?

Check CHANGELOG.md, the topic docs, and the package registry for release and surface status. The README does not carry live release gates.

What about performance and scale?

Strong for offline/moderate causal workloads thanks to bounded support and holographic slices. Not for high-frequency real-time (use Echo).

How does it relate to Echo and Continuum?

  • git-warp: Offline-first/Git-native ("the weird one").
  • Echo: Primary high-throughput runtime.
  • Continuum: Boundary protocol for witnessed history exchange.

Do I have to understand category theory/optics?

No. The fluent API is practical; theory is optional.

What if I have existing data?

Migration tools and diagnostic surfaces exist. See Operations and Git substrate.

Can I use it with my existing Git repository?

Yes. Graph history lives under WARP refs such as refs/warp/<graph>/writers/<writerId>, separate from branch refs and the checked-out worktree.

Where can I get help or see examples?

examples/, docs/topics/, Issues.


License

Apache-2.0 Copyright © 2026 James Ross • FlyingRobots


Built by FLYING ROBOTS