Engineering notesView as Markdown ↗

Shipping a feature beside an agent that also ships

An autonomous worker merging its own pull requests to main will land four releases while you build one feature. Two things break: the version you reserved, and the file you both edited. Neither is a conflict to resolve by taking a side. Rebase late, renumber your release, keep both changelog entries, and hand-merge the overlapping function so both behaviours survive.

A feature took about two hours to build, test and ship. In that window, an autonomous worker running on its own schedule opened, verified and merged four releases to the same branch.

That is not a malfunction — it is the intended shape of a trunk-based platform where an agent has merge authority under fixed conditions. But it changes what "finish the build" means, in two specific ways.

The version you reserved is gone

The build bumped the release to the next number and wrote a changelog entry under it. By the time it was ready to push, four higher numbers had been published, including the one it had claimed.

The general rule: reserve the version last, not first. Anything derived from "the current version plus one" is a value with a shelf life measured in minutes when another stream is publishing. Renumber at push time, after the final rebase, and treat the version in your working tree before that as a placeholder.

The changelog needs a stronger rule than that, because it is the artefact most likely to be destroyed by a careless resolution. A dated, newest-first changelog is prepend-only: a merge takes both entries, yours above theirs, and never regenerates the file. A conflict marker spanning the whole document is an invitation to rewrite it from your side and silently delete months of history. Resolve it by concatenation, and verify the count of entries went up rather than down.

The function you both edited is not a decision

The real conflict was one function: the invoice list tool. The worker had added a live overdue derivation to it. The feature had added client identity and pre-computed ageing to the same rows, in the same map, in the same commit window.

Both changes were correct. Both were wanted. The temptation on a conflict of that shape is to take one side — usually your own, because you understand it — and move on. That silently reverts a shipped, tested behaviour, and nothing in the tooling objects: the build is green, the tests you know about pass, and the feature you were working on works.

The merge instead:

  • Take both sets of fields. Two independent derivations over the same row are not competing; they are additive.
  • Share what they both needed. Both wanted the tenant's calendar day. The merged version resolves it once and feeds both, rather than calling for it twice because each side wrote its own call.
  • Prove you did not drop the other side. Run the other stream's test suite, specifically, and report the number. In this case the overdue suite ran green at thirty-three assertions — which is the evidence that the merge preserved a behaviour this build never wrote and would not otherwise have exercised.

That last step is the one that gets skipped. Your own tests cannot tell you whether you clobbered someone else's feature, because they were written without knowledge of it.

Rebase late, and read what landed

A long-running local branch against a fast-moving trunk should fetch late and rebase once, immediately before pushing — not early and repeatedly. The single rebase surfaces every collision at one moment, when the working tree is otherwise finished and you have the attention to resolve them properly.

It is also worth actually reading the commits that landed while you were away. The four merges included one that changed the exact file the feature touched. A rebase that resolves conflicts mechanically, without reading what the other side was for, produces a tree that compiles and a behaviour nobody intended.

The principle

A conflict between two correct changes is a merge, not a contest. Reserve mutable identifiers late, treat append-only files as append-only under conflict, and let the other stream's own tests be the proof that its work survived yours.

Related

Last updated 2026-08-27