Use when a merge gate (hotpath, philosophy) or dual review BLOCKS on ONE concern of a branch that bundles multiple independent concerns, while the other concern(s) are clean - on a live multi-writer shared branch. Walks the split-land-recut sequence - separate the blocked concern from the clean one(s), land the clean half first, re-cut the blocked half onto the now-moved base, and verify the dropped commits are NOT ancestors of the re-cut tip before re-gating and merging.
Installs into .claude/skills of the current project.
Are you the author of Coordinator Branch Split On Block?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/thrum-team-coordinator-branch-split-on-block)
---
name: coordinator-branch-split-on-block
description: "Use when a merge gate (hotpath, philosophy) or dual review BLOCKS on ONE concern of a branch that bundles multiple independent concerns, while the other concern(s) are clean - on a live multi-writer shared branch. Walks the split-land-recut sequence - separate the blocked concern from the clean one(s), land the clean half first, re-cut the blocked half onto the now-moved base, and verify the dropped commits are NOT ancestors of the re-cut tip before re-gating and merging."
---
# Coordinator: Branch-Split When One Concern Blocks a Multi-Concern Branch
## When to use
- A merge gate (`coordinator-hotpath-merge-gate` or
`coordinator-philosophy-merge-gate`) — or dual review — **BLOCKS on one
identifiable concern** of a branch, while the branch also carries one or
more genuinely independent, unrelated concerns that are clean.
- The clean concern(s) are ready to land on their own merits and gain nothing
from waiting on the blocked concern's fix.
- The branch lives on a **live multi-writer shared branch** — other
coordinators/agents are also pushing, so the base moves under you and a
naive re-cut needs an explicit safety check, not just a rebase.
**Don't use when:**
- The BLOCK concern and the "clean" concern actually share code or intent —
if splitting would require cherry-picking around interdependent commits,
this is not an independent-concerns split; fix the blocker in place
instead.
- Only one concern exists on the branch. A single-concern BLOCK just goes
back to the implementer normally — there is nothing to separate.
## The split decision
When a gate names a BLOCKING finding scoped to one part of the diff, and the
rest of the diff is unrelated to that finding, split the branch into:
- **The clean half** — the concern(s) with zero BLOCKING findings.
- **The blocked half** — the concern the gate flagged.
State the split explicitly in the merge report before doing anything else:
name which commits belong to which half. If a commit touches both concerns,
that commit belongs to the blocked half (never guess a commit apart) or the
split isn't clean enough to attempt this play.
## Land the clean half first
Do not hold the clean half hostage to the blocked half's fix cycle. Route the
clean half through its own merge report to the merge-king (coordinators
never self-merge) and get it merged **first**. This advances the mainline
tip by the clean half's commits.
## Re-cut the blocked half onto the now-moved base
> **This is not the banned rebase.** The project-wide ban (see
> `coordinator-dispatching-work` and `orchestrate` — "merge forward, never
> rebase") targets rebasing a still-live, in-flight branch onto a moved base
> as the pre-MERGE-READY sync step: a stale-local-ref rebase there can
> silently revert commits landed since your last fetch, with no check
> catching it. The re-cut below is a different operation on a different
> object — you are not syncing an existing branch, you are **building a new
> branch from scratch** out of only the blocked half's own unpushed commits,
> and the operation is made safe by an explicit invariant check (below), not
> by care alone. Rebasing (or cherry-picking) a branch's own local, unpushed
> commits onto a fresh base during a deliberate re-cut is legitimate; do not
> "fix" this section by replacing it with merge-forward.
Once the clean half is merged, the blocked half must be **re-cut** — not
merely rebased — onto the new tip, so it carries **only its own commits**,
not a copy of the clean half's commits riding along from the original
branch-off point. Concretely: create the new branch from the merged tip
(the clean half's merge SHA, announced by SHA unprompted, per base-mover
discipline), then cherry-pick or rebase only the blocked half's own commits
onto it. The goal state is a
branch whose full commit range is exactly "the blocked concern's fix,"
nothing else.
## The not-ancestor invariant — the load-bearing check
**Pin exactly which SHAs are the "dropped set" — this is the detail the check
lives or dies on.** The dropped set is the clean half's commits **as they
existed on the original pre-split bundled branch** — their ORIGINAL SHAs,
before the clean half was landed. It is **not** the clean half's merged
form: landing the clean half can rewrite its commits (a rebase, a squash, a
merge-time correction), which mints **new, distinct git objects** with new
SHAs. Those merged-form SHAs are *expected*, *correct* ancestors of the
re-cut tip, because construction branched the re-cut FROM the merged tip —
seeing them as ancestors is not a failure, it's the point.
**After re-cutting, verify the ORIGINAL pre-split SHAs of the clean half's
commits are NOT ancestors of the re-cut branch's tip:**
```bash
git merge-base --is-ancestor <original-pre-split-clean-half-sha> <recut-blocked-tip>
# exit 1 (NOT an ancestor) is the PASS condition
```
Run this for every commit in the dropped set (the original pre-split SHAs),
not just the first one — and never substitute the merged-form SHAs here, or
the check inverts and fails a safe re-cut.
**Why this is the check that matters:** the risk isn't that the re-cut tip
descends from the clean half's *landed* fix — it must, by construction. The
risk is that the re-cut branch was built sloppily (e.g. a naive rebase of
the whole original bundle instead of a cherry-pick of only the blocked
half's commits) and ended up carrying the clean half's **original,
pre-correction commit objects** as ancestors alongside the merged tip. If
that happens, merging the re-cut branch feeds those original objects into a
future merge-base calculation on the same files, and git's three-way merge
can resolve back toward the older, pre-correction content — silently
reverting whatever the clean half's merge fixed. There is no conflict, no
warning, no gate that catches this by construction: the merge just succeeds
and quietly re-applies the older version. Verification (ancestry) has a
shelf life, and re-deriving it AT THIS SPECIFIC HANDOFF (the re-cut) is not
optional.
Run the check at **re-cut time** and again immediately before the merge-king
executes the re-cut branch's merge (the base can move again in between on a
live shared branch — re-run, don't relay a stale result).
## Three-pass re-gate on the re-cut branch
The re-cut branch is a new artifact (different base, different commit set)
and gets a full re-gate, not a diff-against-the-old-gate. Follow the
three-pass order, in order:
1. **UNFRAMED first** — no defect brief, read the full changed functions,
flag anything nobody asked about. Run this before the other two; a
framed pass run first anchors every subsequent pass to the same blind
spot.
2. **CODE-DERIVED enumeration** — terms and symbols pulled from the code
itself (not from the original defect description), enumerate every call
site / consumer.
3. **BY-EFFECT** — assert the specific defect the original BLOCK named
cannot occur, phrased as a checkable behavior. Example from the worked
case: "an inconclusive liveness probe produces neither a tombstone nor a
repair" — a concrete, testable claim, not "the fix looks right."
A code-derived enumeration is not a substitute for the unframed pass — it is
still aimed at symbols the code review chose to look at. Both are required.
## Hold the implementer's retirement until BOTH halves merge
Do not retire (agent.delete / worktree teardown) the implementer who owns
this work until **both** the clean half and the blocked half have merged.
The implementer's context on the blocked half's fix is exactly what the
three-pass re-gate cycle needs if it surfaces further findings; retiring
early forces a cold restart mid-fix-cycle.
## Gate that closes it
Both halves merged, both gate-log lines recorded (one line per merged branch,
not one line for the original bundled branch), the not-ancestor invariant's
PASS result is part of the merge report the merge-king relied on (not
asserted after the fact).
## See also
- `coordinator-hotpath-merge-gate` / `coordinator-philosophy-merge-gate` —
the merge gates whose BLOCK verdict triggers this play.
- `coordinator-running-review-cycles` — the dual-review cycle that may also
originate a scoped BLOCK this play applies to.
## Project-specific rules (already loaded)
Load the /thrum:project-rules-protocol skill and follow it.
If you accumulate a new rule mid-session about branch-splitting, capture it
via the Memory section of your role preamble — it references the
`thrum-memory` skill for the canonical `thrum memory create`
shape.