skills/stacked-prs/SKILL.md
Manages dependent branch stacks and stacked pull requests using safe Git topology rules. Triggers on: "create stacked PRs", "publish this stack", "sync my PR stack", "rebase this stack", "merge the stack", "retarget child PRs", "split this branch into stacked PRs", "validate this stack", "cleanup stacked branches". Use when local branches or one source branch need to become a dependency-ordered PR stack with correct parent bases, validation, synchronization, merge order, and cleanup.
npx skillsauth add mathews-tom/armory stacked-prsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Build, publish, synchronize, validate, merge, and clean up stacked pull requests without corrupting branch topology.
The package identity is provider-neutral. Git is the source of truth for branch ancestry; provider PR metadata is the source of truth for review bases. GitHub through gh is the first documented provider adapter.
| File | Contents | Load When |
| --- | --- | --- |
| references/stack-model.md | Stack inference, explicit ordering, and .stack-prs.yaml rules | Inspecting, publishing, validating, or cleaning a stack |
| references/provider-adapters.md | Provider adapter contract and GitHub gh commands | Creating, retargeting, checking, merging, or deleting PRs |
| references/sync-algorithm.md | Rebase and force-with-lease synchronization workflow | Syncing a stack after a parent or base moves |
| references/merge-discipline.md | Bottom-up merge and branch cleanup rules | Merging or closing out a stack |
| references/metadata-format.md | Optional metadata schema and validation rules | .stack-prs.yaml exists or inference is ambiguous |
| references/provenance.md | Commit-trailer stack identity, stamping, verification, merge-mode coupling | Creating, splitting, syncing, or merging any stack |
| Use this skill | Use another package |
| --- | --- |
| Multiple dependent branches need PRs against parent branches | ship-workflow for one independent release PR |
| A feature branch must be split into reviewable dependent branches | task-decomposer for planning tasks before code exists |
| An existing stack needs rebasing, retargeting, validation, or merge sequencing | pr-review for reviewing one PR diff |
| A stack must be cleaned after merge | General Git commands for unrelated branch cleanup |
git rev-parse --show-toplevel before any workflow.git status --porcelain before rebases, pushes, PR creation, PR retargeting, merge, or cleanup.baseRefName values over inferred ancestry..stack-prs.yaml when parent inference is ambiguous.git push --force; use git push --force-with-lease origin <branch>.Stack-Id and Stack-Position trailers on every commit the skill creates or splits; copy the ID from .stack-prs.yaml or mint it once when absent.Build a stack model without modifying anything:
git rev-parse --show-toplevel
git status --porcelain
git branch --show-current
git for-each-ref --format='%(refname:short)' refs/heads
git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'
gh pr list --state open --json number,title,headRefName,baseRefName,state,url
Produce a table with one row per stack branch:
| Order | Branch | Parent | PR | State | Checks |
| ---: | --- | --- | --- | --- | --- |
| 1 | feat/parser-core | main | #101 | open | pending |
| 2 | feat/parser-cache | feat/parser-core | #102 | open | pending |
Stop when no provider adapter is available, no local branches match the requested stack, or parent order cannot be inferred from PR bases, explicit order, or metadata.
Create missing PRs and retarget wrong bases:
git status --porcelain
git push -u origin <branch>
gh pr create \
--base <parent-branch> \
--head <branch> \
--title "<title>" \
--body-file <generated-body-file>
gh pr edit <number> --base <parent-branch>
Generated PR bodies must include the stack order and validation state:
## Stack
Stack-Id: `auth-refactor-a1b2c3`
Base: `main`
Position: 1/3
1. `feat/parser-core` -> this PR
2. `feat/parser-cache` -> #102
3. `feat/parser-cli` -> #103
Depends on: (none - root)
Upstack: #102
## Validation
- Pending: commands not run yet
For non-root PRs, Depends on: lists the parent PR number. Upstack: lists the immediate child PR number when known.
Stop when a branch has no commits beyond its parent, an existing PR is closed and unmerged, or the provider rejects base retargeting.
Rebase each stack branch onto its parent after main or any parent branch moves:
git status --porcelain
git fetch origin --prune
git switch <branch>
git rebase <parent-branch>
git push --force-with-lease origin <branch>
Start at the first branch above the base and continue toward the leaf. Stop on conflicts, remote lease failures, or a parent PR that closed without merge.
Validate the stack as reviewable slices. Run cheap checks on every branch when practical; run expensive full checks on the leaf when branch-by-branch validation is not reasonable. Record exactly what ran in each PR body.
Use the target repository's detected local gate and provider checks. Do not run armory package-evaluation commands when operating on another repository's stack.
For this armory package implementation only, use:
uv run python scripts/validate_evals.py
uv run python scripts/generate_manifest.py
uv run python scripts/evaluate_package.py --path skills/stacked-prs
Merge root to leaf:
git log --format='%H %(trailers:key=Stack-Id,valueonly)' <parent>..<branch>
gh api repos/{owner}/{repo} \
--jq '{merge: .allow_merge_commit, squash: .allow_squash_merge, rebase: .allow_rebase_merge}'
gh pr list --state open --json number,baseRefName,headRefName \
--jq '.[] | select(.baseRefName == "<branch-being-merged>")'
gh pr merge <root-pr> --merge
git fetch origin --prune
git switch <child-branch>
git rebase origin/main
git push --force-with-lease origin <child-branch>
gh pr edit <child-pr> --base main
If merge commits are allowed, use gh pr merge <pr> --merge. If the repository is squash-only, use the squash-body path from references/provenance.md so the Stack-Id and Stack-Position trailers land in the squash commit body.
On GitHub, do not pass --delete-branch while any open PR still has the branch being merged as its baseRefName. Deleting a parent branch that is still a child PR base can close the child PR unmerged. Repeat for each child. Require trailer verification, parent checks, and provider merge confirmation before moving to the next branch.
After the stack lands:
git switch main
git pull --ff-only origin main
git fetch --prune origin
git branch --merged main
git branch -d <merged-stack-branch>
Delete only branches confirmed merged into the current base.
Delete remote stack branches only after every stack PR has landed or been retargeted away from the branch:
gh pr list --state open --json number,baseRefName,headRefName \
--jq '.[] | select(.baseRefName == "<merged-stack-branch>")'
git push origin --delete <merged-stack-branch>
Use split mode when one source branch contains a feature that needs reviewable dependent PRs. Require the source branch, base branch, and target branch order from the user or from unambiguous commit names.
Inspect first:
git status --porcelain
git fetch origin --prune
git merge-base <base> <source-branch>
git log --oneline --reverse <base>..<source-branch>
git diff --stat <base>...<source-branch>
git diff --name-status <base>...<source-branch>
Select the safest split mode:
| Mode | Use When | Behavior | | --- | --- | --- | | Commit-range split | Contiguous commits map cleanly to slices | Create dependent branches and cherry-pick ranges | | Commit-list split | Non-contiguous commits map cleanly to slices | Cherry-pick explicit commit lists in stack order | | Patch-guided split | File or hunk boundaries are clear but commits are mixed | Stop for user-approved split map before mutation | | Refuse automatic split | Changes are tangled across required boundaries | Report why the split is unsafe |
After creating branches, compare the leaf with the source branch before publishing:
git commit --amend --no-edit \
--trailer "Stack-Id: <stack-id>" \
--trailer "Stack-Position: <n>/<total>"
git diff --stat <source-branch>...<leaf-branch>
git diff --exit-code <source-branch>...<leaf-branch>
Stamp trailers on each slice's commits per references/provenance.md before publishing. Stamping amends commit messages but does not change tree content, so the leaf-vs-source comparison remains a tree comparison with git diff and must still pass.
Do not publish if the leaf differs from the source branch.
| Condition | Action |
| --- | --- |
| Dirty worktree before mutation | Stop and report changed paths |
| Ambiguous parent order | Request explicit branch order or .stack-prs.yaml |
| Existing closed unmerged PR | Stop before creating replacements |
| Closed unmerged child after parent branch deletion | Confirm the head branch and intended commit still exist, recreate the PR against main or the current merged parent, wait for checks, then continue |
| Rebase or cherry-pick conflict | Stop, report branch and conflicted files, do not continue children |
| Remote branch changed since fetch | Stop; do not retry without a fresh inspect |
| Failed validation | Record the failed command and stop merge or publish |
| Top split branch differs from source | Stop before PR creation and report remaining diff |
| Commit in stack range missing Stack-Id trailer | Stop; stamp via provenance backfill before merge |
| Trailer Stack-Id differs from .stack-prs.yaml | Stop; resolve canonical ID before mutation |
| Squash-only repo without trailers folded into squash body | Stop; use the squash-body merge path |
Use this only when a provider closed a child PR because its base branch was deleted during stack landing.
origin.main or the current merged parent.Report:
development
Scaffolds per-repository agent context so coding agents share the same issue tracker rules, triage label vocabulary, domain glossary, ADR layout, and handoff conventions. Triggers on: "set up project context", "configure agent docs", "create CONTEXT.md", "setup agent workflow", "agent issue tracker setup", "triage labels", "domain glossary for agents". Use when a repo needs durable context files before planning, triage, debugging, TDD, architecture review, or multi-agent implementation.
testing
Produces phased task boards from feature requests: dependency-mapped work items, parallelization flags, risk flags, edge cases, test matrices. Triggers on: "decompose this feature", "task breakdown with dependencies", "phased implementation plan", "work breakdown structure". NOT for effort estimates, use estimate-calibrator.
development
Hypothesis-driven debugging with ranked hypotheses, git bisect strategy, instrumentation planning, and minimal reproduction design. Triggers on: "debug this systematically", "root cause analysis", "bisect this bug", "rank hypotheses", "isolate this issue", "minimal reproduction". NOT for general reasoning.
testing
Architecture reviews across 7 dimensions (structural, scalability, enterprise readiness, performance, security, ops, data) with scored reports. Triggers on: "review architecture", "critique design", "audit system", "assess scalability", "enterprise readiness", "technical due diligence". NOT for diagrams, use architecture-diagram.