This document explains how git-warp is structured internally.
If you are learning the product for the first time, start with:
v19.0.2 is the current release. Applications open a Runtime, address causal
Lanes, write validated Intents, consume bounded Observation streams of
Readings, and keep Receipts. The patch makes the safe one-shot retained-v18
migration observable at per-commit granularity and durable after the TUI exits,
without changing the v19 application grammar. Git history and git-cas remain
separate infrastructure concerns composed behind the Runtime.
The longer release notes live in CHANGELOG.md. The runtime architecture below describes current implementation boundaries, not aspirational roadmap state.
┌──────────────────────────────────────────────────┐
│ Runtime.open() -> Runtime -> Lane │
│ Intent · Observer · Observation │
│ Reading · Receipt │
├──────────────────────────────────────────────────┤
│ Runtime-owned storage composition │
│ GitStorage.open() behind the Runtime boundary │
├──────────┬───────────┬────────────┬──────────────┤
│ Query │ Patch │ Materialize│ Sync │
│Controller│Controller │ Controller │ Controller │
│ Strand │Checkpoint │ Provenance │ Comparison │
├──────────┴───────────┴────────────┴──────────────┤
│ Domain services and semantic storage ports │
│ CorePersistence · RuntimeStorageProviderPort │
├───────────────────────┬──────────────────────────┤
│ GitTimelineHistory │ GitCasRepositoryAdapter │
│ Adapter │ content/cache/retention │
├───────────────────────┼──────────────────────────┤
│ @git-stunts/plumbing │ @git-stunts/git-cas │
└───────────────────────┴──────────────────────────┘
Domain code (src/domain/) never imports infrastructure or Node
globals. All I/O goes through ports. Adapters wire ports to Git,
the filesystem, Node, Bun, Deno, or the browser.
The system decomposes into three moments:
- Commitment — admits plural claims into frontier-relative truth
- Folding — re-expresses admitted history (checkpoints, materialization)
- Revelation — exposes truth under bounded rights (queries, observers)
Runtime.open() gives application code a Runtime handle.
runtime.lane(name) opens one named admitted causal lane without exposing the
internal worldline, graph, persistence, or CAS vocabulary.
git-warp does not treat a materialized graph as substrate truth. Witnessed causal history is the authority. A graph-shaped value is an observer-relative reading over that history, and it is valid only for the basis, aperture, law, projection, support obligations, rights posture, budget posture, and witness posture it names.
The public direction is:
bounded causal basis
+ optic law
+ observer aperture
+ support obligations
+ capability, budget, and evidence posture
-> witnessed reading artifact
Git object IDs, CAS hashes, retained payload hashes, commitment roots, proof references, basis identities, and semantic reading identities must stay separate. A byte hash identifies bytes; it does not answer a semantic question by itself. Keep semantic read identity in the owning runtime object or generated reference, not in ad hoc prose.
Adapters and CLI commands must not hide full-materialization fallback, missing witnesses, missing rights evidence, or budget limits. Missing support is an obstruction, residual posture, redaction, plurality, or rehydration requirement, not a cache miss to paper over.
The engineering standard for this codebase. Key rules:
- Runtime truth wins over type annotations
- Domain concepts are classes, not interfaces or typedefs
- Validation at boundaries and constructors
instanceofdispatch over tag switching- No
any, nounknown(outside parsers), noas(outside boundaries) - One file per concept, 500 LOC max
- Tests are the spec
Full standard: Systems-Style TypeScript.
The package root exports exactly one runtime value. Runtime.open() owns
production storage composition:
import { Runtime } from '@git-stunts/git-warp';
const runtime = await Runtime.open({ at: '.', writer: 'agent-1' });
const team = await runtime.lane('team');
// After the final lane operation:
await runtime.close();Application code writes validated Intents with lane.write(intent) and runs
Observers with lane.observe(observer). Formal coordinate reads and Receipt
inspection live on the explicit /advanced and /diagnostics subpaths.
GitStorage is the package composition root, not a Git-shaped persistence
port. Its runtime storage boundary owns two sibling adapters:
GitTimelineHistoryAdapterimplements append-only causal history through@git-stunts/plumbing.GitCasRepositoryAdapterowns one repository-scoped git-cas facade and supplies semantic content, patch-journal, checkpoint, index, state, seek, trie, and trust storage services.
The same composition also supplies repository tooling, such as hook-path resolution, through narrow ports backed by the same plumbing instance.
The domain receives CorePersistence and RuntimeStorageProviderPort. It does
not inspect plumbing fields, dynamically import adapters, or construct CAS
services.
9 controllers, one per capability namespace. Each accepts a typed dependency bag and owns the orchestration for its domain:
| Controller | Capability | Key responsibility |
|---|---|---|
| QueryController | query | Node/edge reads, observers, worldlines |
| PatchController | patches | Patch creation, commit, deterministic fold |
| MaterializeController | materialize | Full and incremental materialization |
| SyncController | sync | Frontier, sync, serve |
| StrandController | strands | Strand lifecycle, braid, collapse |
| CheckpointController | checkpoint | Checkpoint create/restore |
| ProvenanceController | provenance | Provenance index, BTR access |
| ComparisonController | comparison | Coordinate comparison, transfer planning |
| SubscriptionController | subscriptions | Reactive state change notification |
WarpStream is the domain stream primitive used by storage and traversal
ports when an operation may be unbounded. It is an async-iterable wrapper with
composition helpers for stream pipelines; adapters convert host streams,
arrays, cursors, or generated records into WarpStream at the boundary.
The stream layer keeps large reads from pretending to be ordinary in-memory arrays. Current advanced ports that use this boundary include:
| Port | Streamed surface | Role |
|---|---|---|
CommitPort |
logNodesStream(...) |
Git commit-log chunks without loading the full log |
PatchJournalPort |
scanPatchRange(...) |
Patch journal entries over a writer/range |
IndexStorePort |
writeShards(...), scanShards(...) |
Bitmap/index shards as bounded stream units |
CheckpointStorePort is the checkpoint storage boundary. It does not expose a
general stream API today, but it sits beside the streamed stores because it
owns folded state persistence rather than live query semantics.
Stateless services that implement domain logic:
- JoinReducer — deterministic CRDT fold for laws that admit a semilattice join
- OpStrategy — per-op-type mutation/outcome/snapshot logic
- StrandCoordinator — strand lifecycle orchestration
- ConflictAnalyzer — conflict detection and trace assembly
- MaterializedViewService — bitmap index build/rebuild
- StateHashService — canonical state hash computation
- SyncProtocol — request/response for distributed sync
Abstract contracts between domain and infrastructure:
- GraphPersistencePort — runtime composite of CommitPort + BlobPort + TreePort + RefPort
- WarpKernelPort — type-only kernel persistence contract for CommitPort + BlobPort + TreePort + RefPort
- CodecPort — encode/decode (CBOR)
- CryptoPort — hash, hmac, sign, verify
- ClockPort — wall clock (injected, not ambient)
- LoggerPort — structured logging
- PatchJournalPort — streamed patch-entry scans
- CheckpointStorePort — folded checkpoint state storage
- IndexStorePort — streamed index shard storage
Concrete implementations of ports:
- GitTimelineHistoryAdapter — timeline-history Git commands via @git-stunts/plumbing
- GitCasRepositoryAdapter — repository-scoped git-cas service composition
- CborCodec — CBOR encoding via cbor-x
- NodeCryptoAdapter / WebCryptoAdapter — hash/sign via node:crypto or SubtleCrypto
- CasBlobAdapter — content-addressable blob storage via @git-stunts/git-cas
In-memory persistence implementations live under test/helpers/; they are not
production adapters or package exports.
Graph history lives under WARP refs, not source-tree refs. Each writer
maintains an independent patch chain under
refs/warp/<graph>/writers/<writerId>, so graph history does not appear in the
checked-out working directory and does not rewrite refs/heads/*.
Patch, checkpoint, coverage, cursor, and audit commits may carry Git trees for patch payloads, checkpoint state, receipts, or content attachments. Isolation comes from the ref namespace and Git plumbing, not from a rule that every graph commit has no payload tree.
refs/warp/events/writers/alice → commit-sha-1
refs/warp/events/writers/bob → commit-sha-2
refs/warp/events/checkpoint → checkpoint-sha
refs/warp/events/coverage → coverage-sha
Reads open a bounded timeline basis over those refs. Diagnostic materialization
walks visible writer chains, applies admitted patches through JoinReducer,
and produces a frozen WarpState; application code should prefer readings and
receipts before whole-graph replay.
JoinReducer is not the admission authority and does not imply that every pair
of concurrent histories has a least upper bound. Admission first classifies a
well-formed proposal as derived, plural, conflict, or obstruction, with
a required variant-specific witness. A CRDT join is one possible settlement
law for a domain that can prove the semilattice obligations. Other domains may
retain plurality, require explicit conflict resolution, or obstruct admission.
Settlement is a later cross-lane operation. A preview is non-authoritative and
produces an immutable SettlementPlan bound to the exact source and target
frontiers, proposal, law, and policy. Execution must revalidate those bindings;
any bound-input change invalidates the plan rather than silently applying it to
a different history.