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…