Graphoak
Prototype · Apache-2.0

Source control built for many agents editing one codebase at once

Graphoak stores code as a graph of declarations with stable IDs. Changes are typed semantic operations, such as rename, change signature or edit body, and not line diffs. A sequencer lands them in order, rebasing each one by operation, behind a policy gate that issues signed receipts. Git stays your import source and export mirror.

The problem

Git merges text. When eight coding agents change one repository concurrently, line-based merging breaks in two ways, and the second is worse than the first.

Conflicts that aren't real

One agent renames a function while another adds a call to it on the same line. Git sees overlapping hunks and stops, even though the two intents compose.

Clean merges that are wrong

One agent adds a call to parseIsoDate(x) while another adds a required parameter. Git merges cleanly, and the tree no longer type-checks. Nobody is told.

No evidence trail

A commit says what text changed, not what was intended, what was checked, or who allowed it. That is not enough for reviewing work by autonomous agents.

Demo results

8 concurrent scripted agents make plain text edits to real TypeScript repos. The git agent commits its edit. The Graphoak agent makes the identical edit and the lifter turns its diff into semantic operations. The git baseline is strong: plain merge, then Mergiraf (a structural merge driver), then auto-rebase, then redoing the task. Every integrated tree is checked with the real tsc --noEmit and the repo's vitest suite. All figures are medians.

Overlapping task setyup: gityup: Graphoakdate-fns: gitdate-fns: Graphoak
repo size49 TS files, 11.8k lines, 873 tests; 5 runs1,527 TS files, 100k lines, 3,158 tests; 3 runs
tasks landed8 / 88 / 88 / 88 / 8
true conflicts (left after Mergiraf + auto-rebase)1020
silent breaks (clean integration that introduced tsc errors or failing tests)2020
final trunk: tsc errors3020
final trunk: failing tests4020
run wall time2.7 s1.1 s2.5 s4.5 s

Control sets (8 disjoint tasks): both modes landed 8/8 on both repos, with 0 conflicts, 0 silent breaks, 0 tsc errors and 0 failing tests. Every task was also checked alone on the base tree: each one type-checks and passes the suite, so every break comes from integration. Source: demo/results.md, produced by demo/run_demo.sh.

Caveats. The agents are deterministic scripts, not LLMs, and we wrote the task sets ourselves. A git merge queue that ran tsc and the tests on every merge would catch the git breaks, at a cost of several seconds per integration plus redo work. Graphoak is slower on date-fns because the prototype lifter re-imports the whole tree on every edit; incremental lifting is not built yet.

The recording

The full demo/run_demo.sh run, as recorded with asciinema: a CLI tour, then both task sets in git and in Graphoak mode with the type checker and test suite on every tree. Long idle stretches are capped at 2 seconds.

Loading the recording. If it does not appear, the page must be served over HTTP (for example python3 -m http.server in site/). The raw file is demo.cast.

Architecture

One Rust workspace (graphoak-core, -ops, -git, -gate, -cli), one static binary. TypeScript is the first language, through tree-sitter.

Git importSnapshot or full first-parent history. Each commit's diff is lifted into ops, and declaration IDs are kept across commits.
Declaration graphModules and declarations with stable IDs. Bodies hold reference marks, call sites and module paths. Rendering is byte-faithful: git, then Graphoak, then git gives the same tree SHA.
Semantic opsRenameSymbol, ChangeSignature, EditBody, AddSymbol, DeleteSymbol, MoveModule. Merging is operational, so a rename commutes with new uses.
SequencerLinearizable landing with rebase by operation. Real conflicts are rejected with a precise reason, and trunk is left unchanged.
Policy gateBlocks test weakening (removed or skipped tests, loosened matchers) and changes to protected paths. Issues ed25519-signed land receipts.
Merkle op logAn append-only hash chain with a per-changeset op root. verify replays from genesis and detects tampering.
Git export mirrorOne deterministic commit per landed changeset, with Graphoak-* trailers. Idempotent.

Interfaces: the graphoak CLI, and graphoak serve, an HTTP JSON API with bearer-token roles, path-scoped tokens, rate limiting and TLS via rustls. A Docker image is included.

What it doesn't do yet

  • Name binding is heuristic, without a type checker. Namespace imports and aliased locals stay as text.
  • Body merges are diff3-like at segment granularity, so edits on adjacent lines still conflict.
  • History import is first-parent only and memory-heavy.
  • The log has no external anchor, and the gate reads tests without running them.

License

Graphoak is open source under the Apache License 2.0. The vendored fixtures keep their own MIT licenses, and the embedded asciinema player is Apache-2.0.

Contact

We're looking for design partners who run many coding agents against one repository. Write to hello@graphoak.com.