Skip to content
GitHub
Integration Issues

When N parallel lanes append to one shared file, serial merges corrupt at the append boundary — resolve with ours + whole-block re-append

Append-only shared-file serial merges: resolve with ours + whole-block re-append

Problem

A /continue --workflow wave fans out N lanes that each append a new section to the same shared file (the cockpit’s apps/operations/src/styles/cockpit.css during Wave 1 — six lanes each adding a .sp-* block; equally operator/composition.py, a router, a barrel file). The first branch merges clean. Every subsequent branch conflicts at the file’s tail, because both sides added lines after the same prior last line.

Two failure modes followed:

  1. Interleaving. When the two appended blocks have similar structure (CSS rules, route definitions), git’s line-level merge aligns them and emits several small conflict regions threaded through both blocks, instead of one clean “theirs vs ours” tail. Hand-resolving that interleaving is error-prone.
  2. Boundary corruption. A naive “delete the markers, keep both” produced a stylesheet that was missing the closing } of the first block’s trailing @media wrapper — the brace sat exactly on the ======= line and got dropped. biome/the parser then failed (“expected } but file ends”), even though the textual merge “looked” complete and the merge commit had already landed.

Root cause

Append-only blocks all target the same insertion point (EOF / the end of a list), so they are structurally in conflict even though they are semantically independent. Line-level 3-way merge has no notion of “these are two whole, separable blocks” — it interleaves and can swallow a delimiter that straddles the conflict boundary.

Solution

Do not hand-edit the interleaved conflict. Take ours wholesale, then append the other branch’s net-new block extracted as a whole unit:

Terminal window
# 1. keep the already-correct accumulated file from main
git checkout --ours apps/operations/src/styles/cockpit.css
# 2. pull the branch's full file and slice its net-new block (its section
# header through EOF) — the block is self-contained and brace-balanced
git show <branch>:apps/operations/src/styles/cockpit.css > /tmp/branch.css
HDR=$(grep -n '<the block's section-header comment>' /tmp/branch.css | head -1 | cut -d: -f1)
{ printf '\n'; sed -n "$((HDR-1)),\$p" /tmp/branch.css; } >> apps/operations/src/styles/cockpit.css
# 3. PROVE balance before committing — this is the step that catches #2
python3 -c "s=open('apps/operations/src/styles/cockpit.css').read(); print(s.count('{'), s.count('}'))" # must be equal
grep -c '<<<<<<<\|>>>>>>>' apps/operations/src/styles/cockpit.css # must be 0
git add apps/operations/src/styles/cockpit.css && git commit --no-edit
# then run the real parser gate (biome / tsc / ruff) before moving on

Because each lane’s block is self-contained (it opens and closes its own selectors/braces), re-appending it whole can neither interleave nor drop a delimiter.

Prevention

  • In the fan-out prompt, require each lane’s shared-file edit to be a single self-contained block appended at EOF with a clear section-header comment — this is what makes the whole-block extraction reliable.
  • After any append-merge, verify with the file’s real parser (biome for CSS/TS, ruff for Python), not just “no conflict markers” — a balance check ({ vs } counts) catches boundary corruption a marker grep misses.
  • Consider giving each lane its own file (e.g. cockpit.<surface>.css imported by an index) when a wave is large enough that the shared-file serial-merge tax dominates — the same signal the workflow docs give for reaching past --workflow to /swarm.

References

  • Wave 1 cockpit Wave B merge train (SPEC-609/610/611/612+613/614/615), 2026-06-10: brace-drop fixed in efdd2b22; interleaved 3-way conflict on SPEC-612+613 resolved via ours + whole-block re-append.