What Replaces Git When Agents Write the Code

Index

Put twenty agents on one codebase. Each produces tens of changes a day. Now watch what your tooling does: the merge queue serialises, two agents touch the same file and both stop dead waiting for a human, CI returns forty thousand log lines that burn an agent's entire context window without naming the failure, and at the end of it nobody can tell you which model wrote line 412 or who approved it.

None of that is a tooling gap you can close with a bot. It is a data model that was designed around an assumption that stopped being true: that a human wrote a small diff, and that a human would read it.


The Problem

Git and GitHub encode one workflow. A person clones a repository, diverges on a branch, writes a change small enough that another person can read it, and a reviewer approves the diff before it lands. Every primitive in the system serves that loop. Branches exist because divergence is expensive to hold. Rebase exists because the merge is order-sensitive. Pull requests exist because a human is the verification step.

Change volume went up by roughly two orders of magnitude. The human read rate did not move at all. Four costs follow, and teams running agent fleets pay all four today.

Review does not scale. A reviewer reads at a fixed rate. When you multiply the diffs by a hundred, you get one of two outcomes, and most teams get both: changes merged unread, and changes abandoned unreviewed.

Concurrent work blocks itself. Two agents edit the same function, and the merge stops and demands a human. Git cannot store a conflicted state, so the conflict cannot be queued, assigned, or deferred. The agent halts. Model k agents editing m modules and the collision probability rises with k²/m, each collision costing one synchronous human interruption. Blocked agent time grows with the square of your agent count.

Failure output is unusable by the writer. A red build returns raw logs. An agent spends its whole context on them and frequently still cannot name the assertion that failed. The consumer of CI output changed from a human skimming for a stack trace to a machine that needs a structured object, and CI output did not change with it.

Nobody can say what produced a line of code. No record of the model, the version, the context, or the human who approved it. Audit, rollback, and any future certification all rest on a record that does not exist.

Underneath all four sits a mismatch that no amount of process fixes. An agent is a controller: it drives a system toward a target state. A repository is a log of past artifacts. The dynamic element fights the static one, and the static one wins by blocking it.


Prerequisites

This is a design document written up, not a shipped system. Nothing described below has been built. To get value from it you want:

  • Working familiarity with git internals: what a commit object actually is, why three-way merge needs a merge base, and why git blame is a scan rather than a lookup
  • Some exposure to CRDTs or patch theory, enough to know what "commutative, associative, idempotent" buys you
  • Experience running a merge queue or a monorepo at a size where clone cost and full-suite-per-change cost are real line items
  • Having actually run agents against a real codebase, at a volume where the four costs above are things you have felt rather than things you can imagine

Technical Decisions

The spec is the source, not the prompt

The obvious instinct is to store the prompts. Version the conversation, replay it, regenerate.

That fails on inspection. A prompt is an utterance in a context. It is not reproducible, its meaning depends on the conversation state and the model version at the time, and it is the least durable object in the whole system. Re-running it a month later against a new model gives you a different program.

So the source becomes an executable, checkable spec, and the prompt drops to an intent log: retained as provenance, never authoritative. The spec is what a consistency checker can run against, what an evidence bundle attests to, and what a human accepts.

This is the largest assumption in the design and worth flagging as such. If prompts really are the right unit, the spec layer, the derivation layer, and most of the architecture are wrong.

Merge as a semilattice join, and a conflict as an object

Two routes exist for concurrent editing. Operational transformation, as used by collaborative editors, needs a central server to impose an order. The algebraic route, from Darcs and Pijul, makes the merge a join over a semilattice: commutative, associative, idempotent.

The algebraic route wins here for one reason: correctness without a central order. Offline agents, forks, and audit all need a merge that gives the same answer regardless of the sequence it was applied in.

The consequence that actually matters falls out of that choice. If merging never fails, then an overlap cannot be a stop. It has to be a stored object with an identity and a lifecycle of open, assigned, and resolved. Two agents edit the same function, the disjoint parts join cleanly, the overlap becomes a conflict object in a work queue, and both agents carry on with other work. A third actor, agent or human, resolves it later as a subsequent revision.

Two costs come with it. Patches have to be monotone, so a deletion sets a tombstone flag rather than removing anything, and the store grows without bound until you design a safe compaction. And the question of what a human sees while a conflict is open has no good answer yet: the state is a partial order, and a partial order has no single text rendering.

Every element gets an identity at creation

Git identifies content by hashing whole objects. A line has no name. That single gap is why blame is a scan, why log -L on a hot file is a scan, and why rename detection is a similarity heuristic with a tunable threshold that is sometimes just wrong.

Give every element in a typed tree a stable identity when it is created and those questions become index lookups: exact instead of inferred. This is the one clean asymptotic win in the whole design, and it does not depend on any unproven claim about agents. Everything the agent interface promises about cheap partial reads rests on it.

The build is a derivation, and it is pinned rather than reproduced

A model is a non-deterministic builder. You cannot re-run it and expect the same artifact, which means the Nix-style "reproduce from inputs" contract does not hold.

So the artifact is stored as immutable and content-addressed, and the derivation that produced it is recorded alongside: the spec version, the context in scope, the model and its version, and every tool call with its result. Promotion between environments repins that existing artifact and never rebuilds it. Rollback is a single pin change.

A pleasant side effect: this kills the rebuild-per-environment antipattern by construction, because there is no rebuild step to misconfigure.

Review moves from the end to the front

This is the decision that everything else exists to enable, so it deserves the space.

Review today does seven jobs. Check correctness. Validate intent. Judge design. Gate release risk. Transfer knowledge. Establish accountability. Under this model each one goes somewhere different:

Job review does today What happens to it
Check code correctness Mostly absorbed by the spec and the evidence. Survives exactly in proportion to the coverage gap
Validate the intent Survives and grows. A machine checks that specs are consistent. Nothing checks that they are what the business wanted
Judge the design Splits. Style review dies with the diff. Structural judgement moves up to the spec
Gate release risk Survives, scoped by blast radius rather than applied universally
Transfer knowledge Lost. See below
Establish accountability Survives untouched. A named human approval is a legal control in several markets whatever the machine proves
Catch the agent gaming the spec New. Created by this architecture, does not exist today

The economics invert, which is why it moves. Today code is cheap to write and expensive to judge, so the human sits at the end and reads output. Here checking is cheap because a machine does it, and deciding what to want is expensive because only a human can. The human moves to the front.

That leaves a human review budget spent on exactly four things: accepting an intent as a spec change, arbitrating a contradiction between two specs, approving an exception where coverage or blast radius crosses a bound, and approving anything that weakens a check. Reading a diff of generated code is not on the list.

The knowledge transfer loss is real and I do not want to wave it away. Bacchelli and Bird found at Microsoft that defect finding is not the dominant outcome of modern code review in practice: knowledge transfer and team awareness are, ranking above what managers expect. This process removes exactly that outcome. The bet is that a spec set is a better shared artifact than 100,000 lines of implementation, being more compact, more durable, and actually read. That bet is untested.

A feature flag is a branch that survived into production

Once you delete the branch at the version control layer, you notice it comes back at runtime as a flag. n flags describe 2^n programs, of which a team tests a handful, and the untested ones ship anyway.

So a release variant becomes a separate pinned artifact with its own evidence bundle, not a runtime branch inside one artifact. Each cohort points at one whole attested program. An untested combination becomes unexpressible rather than merely discouraged.

This does not absorb all seven jobs a flag does. Release decoupling, canary, and experiment become artifacts. Timeouts, rate limits, pool sizes, entitlements, and plan tiers were never toggles in the first place: they are specified behaviour, and they become declared spec parameters with a type and a permitted range.

The cost is a visible build bill for the cross product of variants. That is a trade I would take: it explodes visibly at build time with every shipped combination attested, where a flag explodes invisibly at runtime with none of them tested.


Implementation

Phase 1: the store

The store replaces the three git verbs rather than reimplementing them.

clone   ->  lazy view of a subtree, cost is O(working set), independent of history depth
push    ->  compare-and-set against a named base revision, rejected with a structured reason
pull    ->  a subscription over the transaction log

There is no branch primitive, no rebase, and no cherry-pick. Their jobs are absorbed elsewhere: change identity replaces cherry-pick, and if patches commute then linear history is a rendering choice rather than a thing you achieve by rewriting.

Content addressing and signing are kept. That is the part of git's model that was correct.

The correctness gate on the store is not a benchmark, it is a property test: generate patch sets, apply them in every order, and assert convergence. You treat the store like a compiler and give it a conformance suite. A merge algebra that is right in the paper and wrong in the implementation loses a user's work, and there is no recovering trust after that.

Phase 2: the change, and the spec

A change becomes a first-class entity, which is the primitive git lacks: an identity, an ordered set of revisions, an author, and a state. Every amend records its predecessor revision, the actor, and the time, because agents amend constantly and the lineage is the only way to see what actually happened.

A change also declares a footprint, the surface it touches, and an invariant it preserves. That declaration is what lets the merge queue check separation between changes in flight before it runs any tests, and lets the system run only the checks reachable from the footprint rather than the full suite. At agent volume the full-suite-per-change model becomes the largest line on the cloud bill, and it grows linearly with a quantity that is now unbounded.

The saving is only as sound as the declaration, which is the obvious hole. Before trusting it you sample full-suite runs against reachable-only runs and measure the miss rate.

The spec layer runs trunk-based: one live tree, small changes, no long-lived divergence. Exploration is a proposal state, not a branch. Every proposed spec change runs against the whole spec set for internal consistency, and that check is the bottleneck the whole architecture manages. A contradiction is named, both sides shown, and routed to a human. No algorithm resolves a genuine contradiction and the system should not pretend to.

Phase 3: derivation, artifact, evidence

{
  "artifact": "sha256:9c1f...",
  "derivation": {
    "spec_version": "spec:4a71...",
    "model": "some-frontier-model@2026-07",
    "context": ["spec:4a71...", "sym:payments.Refund", "sym:ledger.Entry"],
    "tool_calls": 41
  },
  "evidence": {
    "checks_passed": ["prop:refund_idempotent", "prop:ledger_balances"],
    "against_spec": "spec:4a71...",
    "coverage": 0.87
  }
}

The promotion gate is a predicate over that evidence bundle against a spec version. Not a boolean over a job result. "Does the evidence cover what the spec requires" replaces "did the suite pass".

Two rules make the evidence worth anything:

A check whose result is not stable across repeated runs on one artifact gets quarantined and excluded from every evidence bundle. Evidence is permanent and it is the thing you eventually hand an auditor. A flaky pass is not a nuisance, it is a false attestation, which is a data integrity defect.

Any change that deletes, weakens, or narrows an existing check, assertion, or property gets routed to a human regardless of its evidence. This one is not optional. An agent can satisfy a spec by degrading the spec: delete a test, loosen an assertion, narrow a property, and every check goes green while the evidence becomes worthless. That is Goodhart's law applied to a spec, and once the spec is the target it stops being a measure.

Hand-written regions are marked as not regenerable and preserved across any regeneration. Interface feel, novel algorithms, and hot inner loops stay human-written permanently. The system holds them, it does not generate them.

Phase 4: the reconciler

The repository stops being an archive and becomes a controller.

desired state (per environment, per cohort)  ->  pinned artifact
observed actual state                        ->  reported drift
reconcile                                    ->  converge, no rebuild

This is GitOps with the artifact pinning taken seriously, and it is the least novel part of the design. Argo CD and Flux already work this way. What changes is that a desired state naming an artifact with no evidence bundle gets rejected, and that a rollback is one pin change with no rebuild anywhere in the path.

A check is triggered by a state transition on a change or by observed drift. Never by a push event, because there is no push. Which checks run is derived from the footprint and the spec: a registry says only how to run a check and what it needs, and the model decides when and whether. That replaces the imperative workflow file.

Phase 5: the agent interface

One API, with MCP as the primary front door. The web UI is a client of the same API, not a separate surface.

The highest-leverage single piece of the whole design is the structured failure object:

{
  "check": "prop:refund_idempotent",
  "assertion": "second apply must not change the ledger",
  "location": { "symbol": "payments.Refund.apply", "revision": "rev:7b2c..." },
  "expected": "balance unchanged",
  "actual": "balance decremented twice",
  "reproduce": "gx run check prop:refund_idempotent --change ch:88f1"
}

Four kilobytes instead of forty thousand log lines, because the consumer has a token budget. The agent reads it, starts the ephemeral environment for that change, reproduces the failure, and amends. The environment matters: an agent has to run code, not predict what it would have done.

The rest of this layer is unglamorous and entirely necessary. Every agent is a principal with a human owner, a scope, a short-lived credential, and a revoke path. Every write carries an idempotency key, because agents retry. Every text field originating outside the trust boundary is labelled with a trust level, because repository text is an injection surface the moment an agent reads it. Secrets are never exposed to an agent; the runner injects them. A policy engine scopes actions by path, so that "no agent merges under /payments" is a rule the system enforces rather than a convention people remember.

Phase 6: what a reviewer actually sees

The review object is a behavioural delta, not the text diff of generated code. The queue is ranked by risk rather than by arrival time, and that ranking is load-bearing: it is the mechanism that makes review non-universal. Without it, the claim that review cost decouples from code volume has no implementation.

A review comment becomes a typed request with a location, a category, a severity, and a required action, carrying a state of open, addressed, verified, or dismissed. Prose comments are for humans. An agent needs a work queue it can consume and a way to prove completion.


How It All Fits Together

intent (prompt, conversation)        provenance only, never authoritative
  |
  v
spec change  ->  consistency check  ->  contradiction?  ->  human arbitration
  |                                          |
  |                                     clean
  v
A HUMAN ACCEPTS THE SPEC             <- the one mandatory gate
  |
  v
derivation (model, version, context, tool calls)
  |
  v
artifact (pinned, content-addressed, immutable)
  |
  v
evidence bundle (what passed, against which spec, at what coverage)
  |
  v
gate: predicate over evidence     ->  below threshold      ->  re-derive
                                  ->  blast radius > bound ->  named human approval
  |
  v
pin -> desired state per cohort -> reconciler observes drift -> actual state

Read the old primitives off against it:

Old primitive Replaced by
clone Lazy view of a subtree
push Compare-and-set against a base revision
pull Subscription over the transaction log
Branch A change with a proposal state
Rebase Nothing. Patches commute
Cherry-pick Apply a change and its dependency closure
Merge conflict A stored object with a lifecycle
Pull request review Acceptance of intent before derivation, plus risk-gated approval
CI trigger on push A state transition on a change, or observed drift
Pipeline file Derived from footprint and spec. A registry says only how
Green suite as the gate A predicate over evidence against a spec version
Deploy pipeline Repin. The reconciler converges. No rebuild
Feature flag A separate pinned artifact per cohort, or a declared spec parameter
git blame An index lookup on element identity, exact rather than inferred
git bisect A walk over the derivation log across already-pinned artifacts
Revert and redeploy Repin the previous artifact

Lessons Learned

I wrote the whole thing out, then classified every requirement by the weakest substrate that could carry it. That exercise was the most useful hour spent on it, and the result was not what I wanted.

Fifty-five of sixty-three requirements run on an ordinary git host today. The spec layer is files in a repository, which is what GitHub Spec Kit and AWS Kiro already do. Derivation and evidence are in-toto and SLSA plus a sidecar database. The reconciler is Argo CD. Change identity and lineage are Gerrit's Change-Id, which has existed since 2008, plus Sapling for stacks. Reachable-check selection is Bazel. The entire agent interface has no dependency on the data model at all.

The new store buys seven requirements. Stable element identity, monotone patches, the semilattice join, exact symbol history, the removal of branch and rebase, tombstone compaction, and the one-way import that exists only because compatibility was dropped. Every one of them is a correctness property. Not one is something a buyer has asked for. They cost a multi-year build and the entire ecosystem.

The single highest-leverage requirement in the document is pure CI-layer work. The structured failure object needs no new store, no spec language, and no merge algebra. It is the thing most likely to change an agent's day, and it could ship on top of GitHub next quarter.

So could the only unclaimed one. Detecting that an agent satisfied the spec by degrading the spec is a diff analysis over spec and test files. I could not find anyone building it, and it needs nothing from the store.

Three more things I would rather have known before writing section 6 than after:

The sharpest primitive already shipped, and it is git-compatible. Jujutsu stores a conflict inside a commit, resolves it at any later time, and propagates resolutions downstream. That is the conflict-as-an-object claim, available now, without leaving the ecosystem.

Four independent teams looked at this problem and all four chose compatibility. Jujutsu is git-compatible. Cursor Origin syncs from GitHub. Supafork advertises wire compatibility. Freestyle exposes git repositories as agent filesystems. Choosing a clean break puts you alone against that, and the count of shipped competitors matters far less than the unanimity of that one decision.

The scaling argument is a complexity argument, not a measurement. Every claim about k²/m and about review cost decoupling from code volume is derived from the two data models. The complexity classes are defensible. Whether the constants matter at a real team's scale is not something I can currently answer, and a benchmark has to replace that section before it is used to convince anyone of anything.

One genuinely useful reframing survived all of that. This design trades a ceiling that is known and immovable for a ceiling that is unknown and possibly higher. GitHub's first ceiling is the human review rate, and no amount of infrastructure moves it, because the bottleneck is a person reading. This system's first ceiling is spec coherence: whether a large set of specs stays consistent and contradiction-free as it grows. That is a new failure mode with no prior art at scale, and no tool in existence measures it. It might be a much higher ceiling. It might be lower. Nobody knows, and pretending otherwise would be dishonest.


What's Next

The questions that actually gate this, in the order they gate it:

What is the spec language? A property language, a type system extension, a test corpus, or a formal contract. Three answers already exist and should be evaluated before anything new is invented: EARS notation from safety-critical systems, Spec Kit's agent-agnostic markdown, and Tessl's format with tests bound to assertions.

How does an existing codebase get in? With compatibility dropped there is no entry path, which means greenfield only, which is not a market. A semantic import driven by language servers rather than a text import is the one lead worth chasing.

What spec coverage makes a regeneration safe to promote? Without a number, the promotion gate is a vibe.

What does a human see while a conflict is open? The state is a partial order. There is no single text form. The whole review interface waits on this.

And the largest one, which the classification exercise created: given that 55 of 63 requirements run on git today, does the new store get built at all, and if so, when? The honest answer is that the correctness properties it buys are real, and that they are not what anyone is asking for yet.


References