chained-pr · diff

v1.0 to v1.0

31 added, 352 removed. Audit A to A.

---
name: chained-pr
- description: "Split oversized changes into chained PRs that protect review focus. Trigger: PRs over 400 lines, stacked PRs, or review slices."
+ description: "Trigger: PRs over 400 lines, stacked PRs, review slices. Split oversized changes into chained PRs that protect review focus."
license: Apache-2.0
metadata:
author: gentleman-programming
version: "1.0"
---
- ## When to Use
-
- Use this skill when:
-
- - A planned PR is likely to exceed **400 changed lines** (`additions + deletions`).
- - An SDD tasks artifact forecasts `400-line budget risk: High` or `Chained PRs recommended: Yes`.
- - A reviewer asks to split a PR for cognitive load, review fatigue, or burnout prevention.
- - You need chained PRs, stacked PRs, or a feature branch with multiple reviewable slices.
- - A change should be reviewed in roughly **60 minutes or less** per PR.
-
- Do not use this skill for small fixes or single-purpose changes that fit comfortably under the review budget.
-
- ## Critical Rules
-
- | Rule | Requirement |
- |------|-------------|
- | Review budget | **MUST split** when a PR exceeds **400 changed lines** (`additions + deletions`), unless it has maintainer-approved `size:exception` |
- | Review time | Design each PR for an approximately **≤60-minute** human review |
- | Review health | Optimize for sustainable maintainer attention, not just CI compliance |
- | Start and finish | Every chained PR MUST state where it starts, where it ends, what came before, and what comes next |
- | Autonomy | Every chained PR MUST be understandable and verifiable on its own |
- | Scope | One deliverable work unit per PR; do not mix unrelated refactors, features, tests, or docs |
- | Dependencies | State what each PR depends on and what follows next |
- | Exceptions | Use `size:exception` only when a maintainer agrees the large diff is unavoidable |
- | SDD handoff | If SDD forecasts a >400-line workload, honor `delivery_strategy`: ask, auto-chain, or require/record `size:exception` |
- | Visual map | Every chained PR MUST include a dependency diagram that marks the current PR |
- | Tracker PR | If the team chooses Feature Branch Chain, create a draft tracker PR that maps every child PR and stays draft/no-merge until final integration |
- | Child PR base | In Feature Branch Chain, PR #1 targets the feature/tracker branch; every later child PR targets the immediate previous PR branch |
- | Diff source of truth | If a child PR shows previous PR changes, its base is wrong; retarget/rebase until the diff contains only the current work unit |
- | Strategy consistency | Once the user picks a chain strategy, follow it for the entire chain — do not mix stacked and feature branch patterns |
-
- The goal is not bureaucracy. The goal is preventing reviewer burnout so maintainers can review with care instead of skimming exhausted. Big PRs create fatigue, hide defects, and slow merge velocity.
-
- ## Autonomy Requirements
-
- Each chained PR must function as a complete review unit:
-
- - **CI green**: checks pass for the PR branch in its intended base context.
- - **Autonomous scope**: the PR has one clear deliverable outcome.
- - **Reasonable rollback**: reverting this PR does not require reverting unrelated work.
- - **Verification included**: tests, docs, or manual verification cover this unit.
- - **Reviewable alone**: reviewers do not need to read future PRs to understand this one.
-
- If a slice cannot meet these rules, split it differently. A chain is not a dumping ground for partial, unreviewable diffs.
-
- ## Choosing the Chain Strategy
-
- When the workload exceeds 400 lines and chained PRs are needed, **ask the user** before proceeding:
-
- ```
- This work exceeds the 400-line review budget. How do you want to split it?
-
- 1. Stacked PRs to main
- Each PR merges to main in order. Fast iteration, fix on the go.
- Best for: speed-first teams, startups, independent slices.
-
- 2. Feature Branch Chain (with tracker)
- Child PRs review against their immediate parent branch; the tracker branch accumulates the final feature and is the only branch that merges to main.
- Best for: rollback control, integration testing before main, coordinated releases.
-
- 3. size:exception
- Keep it as a single PR with maintainer approval.
- Best for: generated code, migrations, vendor diffs where splitting adds noise.
- ```
-
- Cache the user's answer for the rest of the session. Do not ask again unless the user changes scope.
-
- This is a **team decision**, not a technical one. Both strategies are valid — they reflect different priorities:
-
- | | Stacked PRs to main | Feature Branch Chain |
- |---|---|---|
- | Speed | Each slice ships immediately | Waits until the chain is complete |
- | Rollback | Revert individual PRs from main | Revert the whole feature branch |
- | Risk | Partial features may land in main | Nothing lands until everything is ready |
- | Fix flow | Fix on the go in main | Fix on the integration branch |
- | Complexity | Simpler — rebase and retarget | Needs tracker PR, parent bases, and diff hygiene |
- | Best for | Startups, fast-moving teams | Teams needing coordination and control |
-
- ## Chain Boundaries
-
- Every PR in a chain needs explicit boundaries:
-
- | Boundary | What to document |
- |----------|------------------|
- | Start | The branch, PR, or state this PR builds on |
- | End | The finished unit this PR leaves behind |
- | Before | Prior PRs reviewers can assume already exist |
- | After | Follow-up PRs reviewers should ignore for now |
- | Out of scope | Related work intentionally excluded from this review |
-
- ## Tracker PR Requirement
-
- For any chain with more than two PRs, create a draft tracker PR before review starts. The tracker PR is not the review surface. It is the map.
-
- It must include:
-
- - every child PR in merge/review order,
- - current status for each PR,
- - one dependency diagram,
- - explicit instruction not to review the aggregate diff,
- - `size:exception` if the aggregate diff exceeds 400 changed lines,
- - `no-merge` while the chain is incomplete.
-
- ## Diagram Requirement
-
- Every child PR must show where it sits in the chain. Mark the current PR with `📍`.
-
- ```text
- main
- └── #101 Foundation
- └── #102 Work-unit commits
- └── 📍 #103 This PR
- └── #104 Docs
- └── #105 Tracker
- ```
-
- Pair the diagram with a status table:
-
- | PR | Scope | Status |
- |----|-------|--------|
- | #101 | Foundation | ✅ Passing |
- | #102 | Work-unit commits | 🟡 Open |
- | #103 | This PR | 📍 Review here |
- | #104 | Docs | ⚪ Pending |
- | #105 | Tracker | 🟡 Draft |
-
- ## SDD Integration
-
- When SDD planning produces tasks that may exceed 400 changed lines:
-
- 1. Treat the `Review Workload Forecast` as a hard planning signal.
- 2. Follow the cached `delivery_strategy` before `sdd-apply` writes code.
- 3. Convert suggested work units into PR slices.
- 4. Keep each slice autonomous: tests/docs included, CI green, clear rollback.
- 5. Do not let one `sdd-apply` batch silently grow into a burnout-sized PR.
-
- ## Feature Branch Chain
-
- Use this when the user chooses option 2: the feature branch is the accumulator/tracker/final integration branch, while child PRs are reviewed as focused slices against their immediate parent branch.
-
- The tracker PR is the map, not the review surface:
-
- - tracker PR: `feat/my-feature` -> `main`, draft/no-merge,
- - PR #1: child branch -> feature/tracker branch,
- - PR #2: child branch -> PR #1 branch,
- - PR #3: child branch -> PR #2 branch,
- - final merge: tracker PR -> `main` only after the chain is complete.
-
- ```text
- master/main
- └── feat/my-feature ← tracker/final integration branch
- ↑
- │ PR #1 base: feat/my-feature
- │
- └── feat/my-feature-01-core
- ↑
- │ PR #2 base: feat/my-feature-01-core
- │
- └── feat/my-feature-02-shared
- ↑
- │ PR #3 base: feat/my-feature-02-shared
- │
- └── feat/my-feature-03-slice
- ```
-
- Example review chain:
-
- ```text
- #40 tracker: feat/ui-ownership-refactor -> master
- #41 foundation: ui-ownership-refactor/foundation -> feat/ui-ownership-refactor
- #42 shared: ui-ownership-refactor/shared -> ui-ownership-refactor/foundation
- #43 feature: ui-ownership-refactor/<feature> -> ui-ownership-refactor/shared
- ```
-
- ### Steps
-
- 1. Create the feature/tracker branch from `main`.
- 2. Open the tracker PR from the feature branch to `main` — mark it draft with `no-merge`.
- 3. Create PR #1 from the feature/tracker branch and target it back to that branch.
- 4. Create each later child branch from the previous PR branch and target it to that immediate parent branch.
- 5. Review each child PR against its immediate parent branch, not against `main` and not against the tracker branch after PR #1.
- 6. Keep the tracker branch as the accumulator/final integration branch.
- 7. Only merge the tracker PR into `main` after all children are reviewed and integrated.
-
- ### Commands
-
- PR #1 targets the feature/tracker branch:
-
- ```bash
- git checkout feat/ui-ownership-refactor
- git checkout -b ui-ownership-refactor/foundation
- git push -u origin ui-ownership-refactor/foundation
-
- gh pr create \
- --base feat/ui-ownership-refactor \
- --head ui-ownership-refactor/foundation
- ```
-
- PR #2 targets PR #1's branch:
-
- ```bash
- git checkout ui-ownership-refactor/foundation
- git checkout -b ui-ownership-refactor/shared
- git push -u origin ui-ownership-refactor/shared
-
- gh pr create \
- --base ui-ownership-refactor/foundation \
- --head ui-ownership-refactor/shared
- ```
-
- PR #3 targets PR #2's branch:
-
- ```bash
- git checkout ui-ownership-refactor/shared
- git checkout -b ui-ownership-refactor/orgs
- git push -u origin ui-ownership-refactor/orgs
-
- gh pr create \
- --base ui-ownership-refactor/shared \
- --head ui-ownership-refactor/orgs
- ```
-
- ### Diff Hygiene
-
- The diff is the source of truth. A child PR is correctly based only when GitHub shows the current work unit and not previous PR changes.
-
- - If PR #2 shows PR #1 changes, retarget PR #2 to PR #1's branch or rebase it until the diff is clean.
- - If PR #3 shows PR #1 or PR #2 changes, retarget it to PR #2's branch or rebase it until the diff is clean.
- - Do **not** target `main` from child PRs in Feature Branch Chain.
- - Do **not** target the tracker branch from child PRs after PR #1; that inflates review diffs.
-
- ### Common mistakes
-
- If you chose this strategy, no child PR should target `main` — otherwise it bypasses the tracker and lands in `main` before the chain is complete. Later child PRs also should not target the tracker branch, because GitHub will show prior slices again.
-
- ```text
- # WRONG — child bypasses tracker
- main ← #101 (base: main) ← #102 ← #103
-
- # WRONG — later children target tracker and show inflated diffs
- main ← tracker (#105)
- ├── #101 (base: tracker branch)
- ├── #102 (base: tracker branch) # shows #101 again
- └── #103 (base: tracker branch) # shows #101 and #102 again
-
- # CORRECT — each review targets the immediate parent branch
- main ← tracker (#105)
- └── #101 (base: tracker branch)
- └── #102 (base: #101 branch)
- └── #103 (base: #102 branch)
- ```
-
- ### Post-merge Rule
-
- After a parent PR is merged, keep the chain coherent: leave the next PR base as the parent branch if GitHub still shows only the current work unit, or retarget/rebase to the updated accumulator/parent as needed. The diff must stay focused.
-
- ### Tracker PR Expectations
-
- The tracker PR is a **chain map**, not the review surface. Keep it draft/no-merge until the child PRs are reviewed and integrated.
-
- - Reviewers should review child PRs against their immediate parent branches, where each slice stays within the 400-line budget.
- - The tracker PR may exceed 400 changed lines because it aggregates the full feature branch by design.
- - If the tracker PR exceeds the budget, request/obtain maintainer-applied `size:exception` and document why the aggregate diff is unavoidable.
-
- ## Stacked PRs to Main
-
- Use this when each PR can land in `main` in order.
-
- ```text
- main <- PR 1: foundation
- └── PR 2: feature slice built on PR 1
- └── PR 3: docs/tests built on PR 2
- ```
-
- ### Steps
-
- 1. Create PR 1 from `main`.
- 2. Create PR 2 from PR 1's branch and target it to PR 1's branch.
- 3. After PR 1 merges, rebase PR 2 on `main` and retarget it to `main`.
- 4. Repeat until the stack is merged.
-
- ## Chain Context Section
-
- Insert this extra section into the existing `.github/PULL_REQUEST_TEMPLATE.md` body. Do **not** replace the repository PR template; the linked issue, PR type, summary, changes, test plan, automated checks, and contributor checklist sections are still required.
-
- ```markdown
- ## Chain Context
-
- | Field | Value |
- |-------|-------|
- | Chain | <feature or stack name> |
- | Tracker PR | <#NNN or "Not needed"> |
- | Position | <N of total> |
- | Base | `<target branch>` |
- | Depends on | <PR/issue/link or "None"> |
- | Follow-up | <next PR or "None"> |
- | Review budget | <changed lines> / 400 |
- | Starts at | <branch, PR, or state this builds on> |
- | Ends with | <standalone result delivered by this PR> |
-
- ### Chain Overview
-
- ```text
- main
- └── #NNN Previous PR
- └── 📍 #NNN This PR
- └── #NNN Next PR
- └── #NNN Tracker
- ```
-
- ### Chain Status
-
- | PR | Scope | Status |
- |----|-------|--------|
- | #NNN | <scope> | <status> |
- | #NNN | <scope> | 📍 This PR |
-
- ## Scope
-
- - <What this PR includes>
- - <What this PR intentionally excludes>
-
- ## Autonomy
+ ## Activation Contract
- - [ ] CI is expected to pass for this PR branch
- - [ ] This PR has one deliverable scope
- - [ ] This PR can be rolled back without unrelated changes
- - [ ] Tests, docs, or manual verification cover this unit
+ Load this skill when a planned PR may exceed **400 changed lines**, SDD forecasts `400-line budget risk: High` or `Chained PRs recommended: Yes`, or the user asks for chained/stacked PRs, review slices, or reviewer-load control.
- ## Review Notes
+ ## Hard Rules
- - Review this PR in isolation.
- - Do not review dependent PR changes here.
- - If this exceeds 400 changed lines, request/obtain maintainer-applied `size:exception` and document the rationale.
+ - Split PRs over **400 changed lines** unless a maintainer explicitly accepts `size:exception`.
+ - Keep each PR reviewable in about **≤60 minutes**.
+ - Use one deliverable work unit per PR; keep tests/docs with the unit they verify.
+ - State start, end, prior dependencies, follow-up work, and out-of-scope items in every chained PR.
+ - Every child PR must include a dependency diagram marking the current PR with `📍`.
+ - In Feature Branch Chain, create a draft/no-merge tracker PR; child PR #1 targets the tracker branch, later children target the immediate parent branch.
+ - Treat polluted diffs as base bugs: retarget or rebase until only the current work unit appears.
+ - Do not mix chain strategies after the user chooses one.
- ## Test Plan
+ ## Decision Gates
- - <command or manual verification>
- ```
+ | Condition | Action |
+ |---|---|
+ | PR ≤400 changed lines and focused | Keep single PR. |
+ | PR >400, each slice can land independently | Use Stacked PRs to main. |
+ | PR >400, feature must integrate before main | Use Feature Branch Chain with tracker. |
+ | Generated/vendor/migration diff cannot split cleanly | Ask maintainer for `size:exception`. |
+ | SDD provides `delivery_strategy` | Follow it before apply/PR creation. |
- ## Commands
+ ## Execution Steps
- ```bash
- # Check PR size before asking for review
- gh pr view <PR_NUMBER> --json additions,deletions,changedFiles,title,url
+ 1. Estimate changed lines and identify independent work units.
+ 2. Ask for a chain strategy when none is cached and the budget is exceeded.
+ 3. Create branches/PRs using the chosen strategy only.
+ 4. Add Chain Context to each PR without replacing the repo PR template.
+ 5. Verify each PR independently: CI/tests/docs/manual checks, rollback scope, and clean diff.
+ 6. Keep tracker PR draft/no-merge until all child PRs are reviewed and integrated.
- # Create PR #1 in a Feature Branch Chain
- gh pr create --base feat/my-feature --title "feat(scope): focused slice" --body-file pr-body.md
+ ## Output Contract
- # Create the next child PR targeting its immediate parent branch
- gh pr create --base feat/my-feature-01-core --title "feat(scope): next focused slice" --body-file pr-body.md
- ```
+ Return the chosen strategy, PR order, current PR boundary, dependency diagram, review budget (`additions + deletions`), verification plan, and any `size:exception` rationale.
- ## Reviewer Guidance
+ ## References
- - If a PR exceeds 400 changed lines without `size:exception`, ask for a split.
- - Recommend chained PRs when the work must integrate before `main`.
- - Recommend stacked PRs when each slice can merge independently.
- - In Feature Branch Chain, review child PRs against their immediate parent branches and treat a polluted diff as a base/branching bug.
- - Prefer clear dependency notes over clever branch gymnastics.
- - Push for autonomy: green CI, clear rollback, and tests or docs for the unit under review.
- - Protect reviewer energy. If the chain forces reviewers to reconstruct hidden context, ask for clearer boundaries.
+ - [references/chaining-details.md](references/chaining-details.md) — strategy diagrams, PR body section, branch commands, and reviewer guidance.