VEX Source Control architecture

A JJ-native backend for one continuous software loop

Storage, control plane, policy, leases, and runtime signals are separated by role so the graph can move at agent throughput without losing human-governed truth.

This stack is based on the backend implementation in jj-backend. Its current design is intentionally explicit: immutable object storage for bytes, transactional SQL for active state, and a gRPC contract that is friendly to both human workflows and high-throughput automated clients.

Object storage as immutable truth

Content-addressed blobs, trees, commits, views, operations, and future packs are addressed by SHA-256 and persisted in S3/GCS-compatible object storage.

Postgres as mutable control plane

Repository state, op-head sets, refs, workspace leases, upload sessions, tenant metadata, and audit indexes stay in SQL for transactional correctness.

gRPC API aligned with JJ-native structure

Native operations around BeginUpload, FinalizeUpload, GetObjects, GetOpHeads, CommitOperation, ResolveRefs, UpdateRefs, and future signal/event APIs.

Agentic-era contracts

A live software organism needs contracts Git never had to expose as first-class concepts. VEX makes these explicit so agents can act quickly while the system can still explain, reject, replay, or reverse what happened.

Workspace overlays

Agents need isolated write surfaces that can become JJ changes, be handed to humans, or be discarded without corrupting the base graph.

Actor-scoped leases

High-throughput actors need temporary authority, expiry, ownership, and auditability around the paths and refs they are changing.

Signal events

Runtime health, cache misses, deploy state, and incident conclusions should be written as graph-adjacent events that agents can reason from.

Automation levels

Observe, recommend, guardrailed action, and autonomous remediation are platform states, not informal conventions hidden in prompts.

Consistency and conflict model

CAS on operation heads

Commits advance through compare-and-swap checks so competing updates fail fast instead of silently clobbering remote state.

CAS on refs

Bookmark updates carry versions and can be safely merged with explicit conflict loops.

No hidden mutable state

Presence indexes and op state are explicit and queryable, making caching and policy checks cheap and testable.

Service boundaries we are implementing

jj_backend_service

gRPC transport, config loading, startup migrations, request orchestration.

jj_backend_store

SQL schema, CAS checks for refs/op-heads, transactional safety, presence tracking.

jj_backend_object_store

Object-keyed immutable get/put/exists with pluggable backends.

jj_backend_indexer

Future worker plane for GC, pack materialization, and cross-repo reachability.

Storage layout in one line

The layout already matches explicit object-key patterns for blobs, trees, commits, views, ops, and pack/manifests for future bundling. Repo-scoped paths stay deterministic so pack and manifest builds can be attached without changing history semantics. That matters when the same graph may be read and rewritten by many automated actors in one continuous loop.

In-memory metadata + object key indexing stay near the CLI path for low-latency reads.