graft

How it works

How a carry works

One real carry, step by step: a platform team's fork of a Go infrastructure project, moved onto a release two minor versions newer in October 2026. The project and its code are anonymised here. The counts, verdicts and times are from that run.

We run your carry before you pay.

The report you get first is the real carry, built and tested. You pay only if you want the branch.

If we can't deliver a carry we quoted, you get the $990 back.

All of it, and you keep the report and anything we've already sent. Refund terms.

Step 1

Your fork becomes a short stack of patches

A fork that syncs by merging upstream in has a messy history: its own commits, upstream backports, CI tweaks, and edits made while resolving merges. Graft doesn't replay that history. It takes the fork's net change, what the fork's tree has that the release it's based on doesn't, and splits it by file into patches.

This fork had 19 commits of its own and 5 merges from upstream. 12 of those commits were already in upstream, so they leave nothing to carry. 5 only touched the fork's own CI, which stays on your branch. What's left is 4 patches, two of them made only of edits from merge resolutions.

Graft then checks its own work: the 4 patches on the old release must give exactly the fork's tree, apart from the skipped CI files. This step took 2 seconds.

Fork history since the old release
The patch stack
0001 A DNS provider exception in the scheduler13 files: 1 commit, plus 3 files only merges explain
0002 A parsing test1 file: 1 commit
0003 A credentials endpoint setting1 file: from merge resolutions
0004 Blank lines left by merges2 files: whitespace only
24 entries in, 4 patches out. Checked: the stack rebuilds the fork's tree.
Step 2

Each patch goes onto the new release, and gets a route

Upstream made over a thousand commits between the two releases. Graft tries each patch on the new release and routes it by what happened:

auto when it applies and you've approved it unchanged for two releases; confirm when it applies but hasn't earned that yet, or upstream edited the same file; propose-drop when upstream already has it; race when it no longer applies, so agents rewrite it.

Here, two patches went on and wait for a one-click confirm. The other two conflicted, but only in some files: 11 of the 13 files in 0001 merged cleanly and went on as they are. Only the files that actually conflicted go to the agents.

Carrying onto the new release
your patchnew release
0002 Parsing testconfirm
on, 1 file
0003 Credentialsconfirm
on, 1 file; upstream edited it too
0001 Schedulerrace
11 on, 2 to agents
0004 Blank linesrace
1 on, 1 to agents
14 of 17 files on before any agent runs. Dashed lane: the 3 files agents rewrite.
Step 3

Agents rewrite what broke, or stop and ask

For each conflicting file, three Claude agents work separately. Each sees the file as it was, the fork's version, upstream's new version and the rest of the change. Each returns a merged file, a drop, or a question.

On a defaults fixture, all three returned the same file: upstream's new one with the fork's setting kept. On the README, all three said drop: upstream regenerated that section, and the fork's only edit there was a stray blank line.

On the scheduler all three stopped. The fork lets one DNS provider run same-name challenges in parallel, and the new release added a comment saying such challenges must never run in parallel, whatever the provider. That's a policy call, so it goes to you with both options, and each option is built and tested so you can see what it costs.

The scheduler, three agents
agent 1Should the fork keep its provider exception that schedules them in parallel?
agent 2Should the fork keep its parallel-scheduling exception anyway?
agent 3Should the fork keep running same-name challenges concurrently for its provider?
Your call, 3 of 3 agents asked

Upstream now runs same-name challenges one at a time. Keep running them in parallel for your provider?

1. Keep the provider exception

  • buildpass
  • build-controllerpass
  • testpass
  • test-controllerpass

2. Follow upstream

  • buildpass
  • build-controllerpass
  • testbroken by the carry
  • test-controllerpass
FAIL: the fork's own scheduler test
The fork's own test is what fails under option 2: it checks the parallel scheduling the fork added.
Step 4

Build and test against the release as upstream shipped it

Graft runs your build and test commands twice: on the new release alone, which is the baseline, and on the new release with every change that went on. Tests that already fail on upstream's release don't count against the carry, because they fail in the baseline too.

With 3 of the 4 changes on, and 0001 waiting on the question above, both builds and both test commands passed, with 0 new failures. Each command gets one of five verdicts:

  • passNo failure the baseline doesn't have.
  • already failingIt fails on the new release alone too. Upstream's problem, and we tell you.
  • broken by the carryA new failure, with the test names. Option 2 above is one.
  • fixed by the carryFails on the new release alone and passes with your changes on.
  • timeoutRan out of time and was stopped. Never counted as a pass.
Step 5

A person reviews it, then you get the report

Craig reads every rewrite, every drop and every confirm before anything reaches you. Questions like the one above go into your report as cards with both options and their test results. You pick one, and that's the branch we deliver.

The report is free. If you want the carried branch, it's $990 for the release, and if we can't deliver a carry we quoted, you get the full $990 back.

Machine time for this carry, on a Raspberry Pi 5:

2 sto build the stack
10 min 53 sto carry, then build and test the baseline
4 min 35 sfor the agents
4 min 52 sfor the final build and tests