Repository navigation
Description
Agents will crowd the same files. That's a given. codeSplitter should let them, with the policy in code: the platform runs the loop, and agents fill only the gaps it can't decide. Today an agent coordinates by prompt, one judgment at a time. That's what the PR agent did all of 2026-10-12, and it still got a merge order wrong once.
The loop, owned by codeSplitter
- Queue live. Agents claim a line or range, wait in line for a hot one, and announce intents. Nobody piles on, so conflicts don't start. codeSplitter line locks 1: leases everywhere #926 (leases), codeSplitter line locks 2: wait in line, and soft intents #927 (waiting line, soft intents).
- Stack what doesn't compete. Merge by line id lands non-overlapping lines and files. Branches land oldest first, each against main as the last merge left it (codeSplitter: merge every branch that merges clean in one go #903). Deterministic rules settle "both only added to it": codeSplitter merge 1: settle list and paragraph one-liners deterministically #933 (list and paragraph one-liners), conventions codeSplitter conventions: break up the hot one-liners and numbered registries #935.
- Only real problems go to someone. A build-checked AI fallback, then a person. codeSplitter merge 2: a build-checked AI fallback, and refuse conflict markers #934 (also refuses conflict markers).
- Offline people. Their choice. On reconnect their edits replay onto line ids, and a stale edit is rebased word by word instead of rejected (codeSplitter line locks 3: word-level rebase of stale line edits #928).
- Self-healing CI. A failure or a guard trip opens a fix task on that branch automatically, and CI runs again. The guards: CI: fail on leftover conflict markers; test that features.json parses #937 (reject committed markers, parse features.json).
Agents get a few MCP tools where the right way is the easy way. edit does the claim, the wait and the rebase underneath. land lands, or returns the one real conflict with both sides and why. An agent is called only for that leftover, and its answer must build and pass tests before it lands.
Policy per path, with defaults
As .gitattributes merge drivers and Mergify do it: a small table, defaults for about 90% of cases, and teams override only the hot spots.
| Path pattern | Live edits | Merge rule | Leftover goes to |
|---|---|---|---|
features.json, route tables, registries |
wait in line | merge by key, union the items | AI, then a person |
*.md lists |
free | union the items | AI |
| lockfiles | locked | regenerate | CI |
| everything else | free | line-id merge | person |
Catch our own mistakes: shadow mode
Run codeSplitter's merge next to git's on real PRs. Every case where they disagree, or where a guard trips, becomes a test case or a fix task. That's the self-healing loop, pointed at the merge system itself.
Worked example, 2026-10-12
- codeSplitter dependency doctor: dig a future release to watch, try, and take (#863) #884 merged with literal
<<<<<<<markers inapps/codesplitter/src/features.json. No test parsed the file, so CI passed. codeSplitter dependency doctor: rank the packages you care about to settle clashes (#862) #886 removed them about 1h45m later. Every branch cut in between inherited the markers and fixed them its own way, so each PR "edited the same line". That's why codeSplitter: tags, made here and traded with upstream (#879) #893 conflicted twice and codeSplitter: merge solutions design doc, measured on #893 and #886 #936 once. - A dry run of codeSplitter: tags, made here and traded with upstream (#879) #893 and codeSplitter dependency doctor: rank the packages you care about to settle clashes (#862) #886 against main gave about 30 git conflicts, and most weren't real overlaps: both sides adding to one long line (imports, one-line objects, doc bullets), edits to neighbouring lines, or inserts at one spot. Measured in
apps/codesplitter/docs/merge-solutions.md(codeSplitter: merge solutions design doc, measured on #893 and #886 #936). - The PR agent dry-ran codeSplitter: tags, made here and traded with upstream (#879) #893 and codeSplitter dependency doctor: rank the packages you care about to settle clashes (#862) #886 together, found no conflict between them, and fixed both in parallel. Their fixes then collided on one line, so codeSplitter: tags, made here and traded with upstream (#879) #893 needed a third CI run. A merge queue in code wouldn't make that call by hand.
Prior art to build on, not reinvent
- Merge queues: Bors (the "not rocket science" rule), Zuul (testing the queue ahead), Uber SubmitQueue (conflict prediction), GitHub merge queue, Mergify.
- Short branches: trunk-based development, feature flags.
- Structural and union merges: git's
merge=uniondriver, Mergiraf (tree-sitter), SemanticMerge. One file per entry: changesets, towncrier. - Locks: Perforce and SVN exclusive checkout. Dropped because people forgot locks; leases that expire on their own fix that.
- Live editing: operational transforms (Google Docs), CRDTs (Yjs, Automerge), Zed.
- Patches that reorder safely: Darcs, Pijul. First-class conflicts: Jujutsu.
What's new is the load. Agents mean about 10x the writers at about 10x the pace, with no standup to coordinate. And agents are also cheap fixers, so the platform should call them for the leftovers instead of leaving it to their prompts.
Related
Design docs: #925 (line locks), #936 (merge solutions). Pieces: #903, #926, #927, #928, #933, #934, #935, #937.
🤖 Generated with Claude Code
Activity
codeSplitter: policy per path, with defaults a repo overrides in .git…