Skip to content
Back to skills

Pr Batching

ASecurity

Decide whether several finished branches ship as ONE PR or stay separate. Use when holding 2+ green branches before `shipyard pr`. Trades CI cost against revert granularity, urgency, and the diff-coverage gate.

  • 22 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 3, 2026
toolsgoshellbashgit

Security analysis

A100/100

Scanned September 30, 2026

npx -y skills add danielraffel/pulp --skill pr-batching --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Pr Batching?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Pr Batching
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/danielraffel-pr-batching/badge)](https://www.skillsdirectory.com/skills/danielraffel-pr-batching)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: pr-batching
description: Decide whether several finished branches ship as ONE PR or stay separate. Use when holding 2+ green branches before `shipyard pr`. Trades CI cost against revert granularity, urgency, and the diff-coverage gate.
---

# PR batching

**A PR costs ~an hour before it can merge:** a ~25-min local diff-coverage build,
then a Shipyard validation. Validations must run **serially** (concurrent runs
from worktrees sharing one `.git` race on `config.lock`). So *n* related PRs is
*n* **sequential** hours, not *n* parallel ones.

That makes "ship these together?" a real question. This is the checklist.

## Default: combine

If you hold 2+ finished, green, **related** branches — combine. Separate PRs are
what you justify, not the reverse.

## Combine when

- **They share unmerged work.** Check first — you may already have the combined
  branch:
  ```bash
  git merge-base --is-ancestor feature/a feature/b && echo "b already contains a"
  # siblings: is their common point AHEAD of origin/main?
  git rev-list --count origin/main..$(git merge-base feature/a feature/b)
  ```
  A chain *is* the combined PR — open it from the tip. Siblings fold with a
  cherry-pick.
- **One depends on the other.** If B only compiles because of A, they were always
  one change.
- **Same subsystem.** One context, one adoption note, one revert.
- **A well-tested branch would lift a weak one over the coverage gate.** Coverage
  is computed over the **whole PR diff**, so folding in a densely-tested branch
  *raises* the ratio. A branch stuck at 68% can clear 75% by merging with a
  sibling that ships 20 test cases. This is adding covered lines, not hiding
  uncovered ones — legitimate.
- **Fewer chances to re-conflict the version-bump line** on a busy `main`.

## One PR per family per session

A single agent session routinely produces a run of small, related changes to
one manifest or branch family on the same day. Shipped one at a time, each pays
its own PR-head gate and its own merge-group gate; the merged-change average was
4.2 native gate runs per change when sessions did this. The rule:

- **Same session + same manifest or branch family + same day ⇒ one PR per
  family.** A session with fourteen such changes ships two to four PRs, not
  fourteen.
- Before running `shipyard pr` on the second change of a family, check whether
  the first is still open. If it is, and it is not yet in the merge queue, push
  the new commit onto that branch instead of opening a sibling PR.
- The pre-push advisor lists the related local branches it found and records
  each firing in `${XDG_STATE_HOME:-~/.local/state}/pulp/pr-batch-advice.jsonl`;
  that log is how the advice is measured.

**Never fold**, even inside one family:

- anything likely to be ejected (a known-flaky area, a change to a test the
  queue is currently failing on) — one ejection costs every entry of the batch;
- anything urgent, especially a fix for a red `main` — it ships alone and jumps;
- a docs-only PR into one that runs the native gate, since the docs PR would then
  pay for a build it does not need;
- unrelated subsystems, unfinished work, or a change that may need reverting
  alone (see below).

## Keep separate when — any ONE of these

- **One is urgent, the other is gated.** Never make a ready branch hostage to a
  blocked one. An hour of CI is cheaper than a day of someone else's blocked work.
- **One is unfinished** — a library with no caller, an unwired command,
  uncommitted files. **Never ship half-done work to save a CI run.** This is the
  trade that looks tempting and is always wrong.
- **Unrelated subsystems.** Costs revert granularity, muddies the migration note.
- **One is risky enough it might need reverting** — isolate it, or a revert drags
  good work out with it.
- **One carries a large untestable surface** (native window hosts, format adapters
  needing a real DAW). It drags combined coverage *down* — the inverse of the lift
  above. Check which way it cuts.

## Folding siblings

```bash
cd <worktree-of-primary-branch>
git log --oneline <shared-base>..feature/sibling   # confirm its OWN commits
git cherry-pick <sha>...
tools/ci/governed-build.sh cmake --build build
ctest --test-dir build --output-on-failure -R '<affected>'
```

Cherry-picks compile and still break behaviour — a change fine against the old
base can violate an invariant the other branch just introduced. Run the suites
**together** before shipping.

## Don't

- **Don't run two heavy builds at once to "save time."** They contend, and the
  contention surfaces as *test failures* (shellout tests time out under load),
  costing you an investigation into a bug that does not exist.
- **Don't batch to dodge a gate.** Adding covered lines to raise a ratio is fine.
  A `PULP_SKIP_*` bypass is not.

## Enforcement

This skill is the *judgment*. `tools/scripts/pr_batch_advisor.py` runs from
`.githooks/pre-push` (advisory, never blocks) so the question gets asked no matter
who is driving — Claude, Codex, a human, `gh pr create`, or `shipyard pr`. A skill
only reaches an agent that reads it; a push reaches everyone.

Silence one push: `PULP_SKIP_PR_BATCH_ADVICE=1`.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.