skills/engineering/stack-pr/SKILL.md
Analyze committed changes on the current local branch, propose a dependency-ordered stacked PR plan, then after explicit approval create multiple upstream stacked PRs. Use when the user asks to "stack this PR", "create a PR stack", "split this branch into PRs", "split PR", "拆 PR", "split into reviewable PRs", or says a branch/PR is too big to review.
npx skillsauth add arctuition/skills stack-prInstall 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.
Turn the committed changes on the current local branch into a set of true stacked GitHub PRs. The default flow is:
This skill only creates new stacks. It does not update, overwrite, retarget, close, or repair existing stack PRs.
git worktree for stack construction so the user's checkout remains on the source branch.upstream when it exists; otherwise use origin.This is the only supported execution mode. Analyze the current branch and create a new stack after explicit approval.
If the user says "只规划", "先别动", "don't create PRs", or similar, stop after the plan.
Do not update existing stack branches or PRs. If an inferred branch name already exists locally or on the target remote, generate a new non-conflicting stack prefix, usually by suffixing the inferred prefix with -v2, -v3, etc. Show both the originally inferred prefix and the final prefix in the plan.
Start from the current checkout.
git status --short
git branch --show-current
git remote -v
gh auth status
Fetch before resolving the base:
if git remote get-url upstream >/dev/null 2>&1; then
git fetch upstream --prune
else
git fetch origin --prune
fi
If the current branch already has an open PR, read its title, body, and base as intent metadata. Do not edit, close, retarget, or replace that source PR automatically. After creating the stack, report the original PR URL and leave it unchanged.
Resolve the base in this order:
upstream/<default-branch> when upstream exists.origin/<default-branch>.master, then main, only if remote default resolution fails.Derive remote default branches from GitHub or remote refs; do not hard-code master or main.
git remote get-url upstream
git remote get-url origin
gh repo view <OWNER/REPO> --json defaultBranchRef --jq .defaultBranchRef.name
git symbolic-ref refs/remotes/origin/HEAD
Record the resolved base ref and SHA. Before execution, re-check the base SHA. If it changed since planning, stop and refresh the plan unless the user explicitly accepts proceeding.
Default source scope is committed changes on the current branch.
If the worktree is dirty, analysis may continue using committed diff only, but report that uncommitted changes are excluded. Execution must stop while the worktree is dirty unless the user explicitly says how to handle it. Never auto-stash, auto-commit, auto-reset, or auto-clean.
Use two-dot and merge-base diffs for different purposes:
git log --oneline <base>..HEAD
MERGE_BASE=$(git merge-base <base> HEAD)
git diff --stat "$MERGE_BASE"..HEAD
git diff --name-only "$MERGE_BASE"..HEAD
git diff "$MERGE_BASE"..HEAD
Use git log <base>..HEAD for commits reachable from the source branch but not from base. Use git diff "$MERGE_BASE"..HEAD for the actual patch introduced by the branch. Do not use git diff <base>..HEAD as the source patch if the branch is behind or diverged from base.
If there are no commits and no committed diff, stop. If the worktree has uncommitted changes, ask the user to commit them first.
List merge commits during analysis, but do not copy merge commits into the stack by default. Ignore pure sync merges. If conflict-resolution edits in a merge commit affect the feature, preserve the resulting file changes in the appropriate reconstructed commit.
Read the changed files in full enough context to understand each file's role. Do not split from filenames alone.
Use the commit history as a hint, not the answer:
git log --oneline --decorate <base>..HEAD
git diff --name-status "$MERGE_BASE"..HEAD
git diff --stat "$MERGE_BASE"..HEAD
Cluster changes by the dimension that produces clean, independently reviewable stack layers:
Splitting defaults:
Sizing target: keep each PR under roughly 400 net lines when practical. Larger PRs are allowed only when the scope is genuinely indivisible; state why splitting further would make the stack less reviewable or less mergeable.
Infer a short stack prefix from the overall change intent using PR metadata if available, commit messages, changed files, symbols, Jira keys, and user constraints. Prefer including a clear Jira key. Use the current branch name only as a fallback.
Infer each PR slug from that PR's proposed scope. Do not derive PR titles or slugs from the source branch except as a fallback.
Format:
<stack-prefix>/NN-<content-derived-slug>
Example:
billing-export/01-shared-format-types
billing-export/02-export-service
billing-export/03-admin-ui-wiring
Check local and target remote branch names before execution. If there is a collision, select a new non-conflicting prefix such as billing-export-v2 and show it in the plan. Never delete, overwrite, or force-push existing branches.
For each planned PR, state how to carve it from the source branch:
Commit construction:
Allowed edits during execution:
Not allowed:
Before any branch, commit, push, or PR creation, present the plan and wait for explicit execution approval.
Plan output:
## Stack plan: <feature name>
Base: <resolved base ref> (<sha>)
Target remote/repo: <TARGET_REMOTE> / <OWNER/REPO>
Source branch: <branch name> (left unchanged)
Dirty worktree: <clean / dirty, excluded from source>
Inferred prefix: <original>
Final prefix: <non-conflicting prefix>
PR readiness: <ready for review / draft with reason>
### PR 1 - <title>
Branch: <prefix>/01-...
Base: <resolved base branch>
Scope: <one sentence>
Files: <key paths, can elide with "+N more">
Commits: <oids or "reconstructed from mixed commits">
Extraction: <cherry-pick / file-level patch / hunk-level patch / manual reconstruction>
Validation: <targeted command(s)>
Risk: low / medium / high - <reason>
### PR 2 - <title>
Branch: <prefix>/02-...
Base: <prefix>/01-...
...
What this optimizes for: <one sentence>
What it costs: <one sentence>
Open question: <one concrete question, or "none">
Reply `执行` / `create stack` to create these upstream branches and PRs. Plain `ok` / `可以` means the plan is accepted but git will not be mutated.
Treat "ok", "可以", "looks good", and similar as plan approval only. Proceed to mutation only on explicit execution language such as "执行", "create stack", "open the PRs", or "go ahead and create them".
After explicit approval, re-check:
git status --short
git rev-parse <base>
Stop if the worktree is dirty or the base SHA changed unexpectedly.
Create a temporary worktree from the resolved base:
WORKTREE_DIR=$(mktemp -d /tmp/stack-pr-XXXXXX)
git worktree add "$WORKTREE_DIR" <base>
Build stack branches linearly:
Do not merge while constructing the stack. Use cherry-pick, scoped patch application, or manual hunk reconstruction according to the approved plan.
Before moving to the next layer, inspect the layer diff:
git diff --stat <parent-branch-or-base>..<head-branch>
git diff --name-only <parent-branch-or-base>..<head-branch>
If extraction, cherry-pick, or patch application conflicts, stop at the first conflict. Report the layer, temporary worktree path, conflicting files, failed command, already-created local branches, and whether anything remote was created. Do not continue to later branches.
Run the planned targeted validation for each branch where practical. Prefer focused checks over full suites.
If any validation fails, stop before pushing/opening PRs. Summarize the failure and whether it appears related. Continue only if the user explicitly approves proceeding despite the failure. Record any user-approved validation exception in the PR body test plan.
Only after all local branches are built and validation is acceptable:
upstream.Derive the target repo from the target remote URL. Do not rely on gh defaults when a repo can be ambiguous.
git push <TARGET_REMOTE> <branch-name>
gh pr create --repo <OWNER/REPO> --base <base-branch> --head <branch-name> --title "<title>" --body "<body>"
Default PR readiness is ready for review. Create draft PRs only if the user asks, validation is materially incomplete, a PR has known unresolved follow-up before review, or the repo clearly prefers draft stacked PRs.
Follow the repo's PR template when present:
.github/PULL_REQUEST_TEMPLATE.md.github/pull_request_template.md.github/PULL_REQUEST_TEMPLATE/Fill every applicable section with real content. Do not leave placeholder prompts.
Each PR body should describe only that PR's scope, not the whole stack in full detail. Include stack context near the top:
Stack: <N>/<total>
Base: <base branch>
Previous: <previous PR URL or ->
Next: <next PR URL or pending>
This PR only contains: <one sentence>
Fallback body when there is no template:
## Summary
- ...
## Stack
- Position: <N>/<total>
- Base: <base branch>
- Previous: <previous PR URL or ->
- Next: <next PR URL or pending>
## Test Plan
- ...
After all PRs are created, best-effort update PR bodies with previous/next/full-stack links using gh pr edit. If link backfill fails, report it and leave the PRs open. Do not delete or recreate PRs just to fix links.
After execution, output:
## Stack created
Review/merge order:
1. <PR URL> - <title> (`<branch>`)
2. <PR URL> - <title> (`<branch>`)
Validation:
- <branch>: <command> - <result>
Notes:
- Source branch `<source>` left unchanged.
- <Any skipped validation or best-effort body-link failures.>
Do not include a long recap. The PR URLs and merge order are the handoff.
testing
Iteratively detect and fix everything outstanding on a GitHub PR — CI failures, bot review findings, and human inline comments — then push, wait for CI, and re-scan until nothing actionable remains. Use when asked to "fix the remaining issues on a PR", "address PR feedback", "loop until CI is green", "auto-fix PR comments", "run a final fix pass before merge", or 检查 PR 状态和 comment 自动修复 / 修到没有新 finding 为止. Author-side by default; runs on any PR branch you have push access to, including PRs that already look ready to merge.
testing
Research what real people have actually been saying about a topic over a recent time window (default last 30 days) across Reddit, Hacker News, X, YouTube, and GitHub — then synthesize an engagement-weighted, cited brief. Use when the user asks: what's new/recent buzz/trending with X, community sentiment on X, what people are saying about X lately, last30days, past week/last N days, 最近大家在聊什么 / 最近 X 有什么新动态 / 时效性调研 / 选型/产品调研. Complements deep-research (fact-checking) by focusing on recency + community signal rather than authoritative sources.
data-ai
Wrap up the work you just did and open a PR for it — branch off main/master if needed, commit only the changes you made, push, open a pull request (following .github/PULL_REQUEST_TEMPLATE.md when present), and open the PR in the browser. Targets the `upstream` remote's default branch as the base when an `upstream` remote exists, otherwise `origin`. Use when the user says "sign off", "signoff", "ship it", "open a PR for this", "commit and PR", or "wrap this up".
development
Produce a single-file HTML "thread recap" artifact that captures what was discussed in an agent / pairing / chat conversation — the questions explored, the decisions made and their tradeoffs, the dead ends we walked into, the open questions left, and the artifacts produced — so a teammate who wasn't in the room can pick up the context. Use this skill whenever the user asks to summarize a conversation/thread/session, mentions sharing a thread with colleagues, says things like "把这个对话总结一下", "share this thread with the team", "write up what we decided", "decision log for this conversation", "document the tradeoffs we made", "recap of our pairing session", or wants to hand off a Claude/ChatGPT/agent transcript as context. Trigger even when "HTML" isn't said — the artifact format is the whole point. Input can be the current session's own conversation context OR a transcript the user pastes in.