Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 23 additions & 14 deletions .claude/skills/pr/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
---
name: pr
description: Write the pull request for the current branch: a title that is the changelog line and a description per the Pull requests rules, both checked with tools/commit-lint. Use when asked to write, draft or open a PR, or to produce its title or squash message.
description: Write the pull request for the current branch: the merge mode (squash or rebase), a title that is the changelog line when squashed, and a description per the Pull requests rules, all checked with tools/commit-lint. Use when asked to write, draft or open a PR, to produce its title or squash message, or to choose how to merge it.
---

# Pull request

A PR is squash merged: the title becomes the commit subject on main and the
release-notes line. `docs/agent/dev.md` ("Commits: the subject is the changelog",
"Pull requests") holds the rules; this file is the procedure. dev.md wins.
A PR is squash merged or rebase merged, never with a merge commit. Squashed,
the title becomes the commit subject on main and the release-notes line.
Rebased, every commit lands as it is and each subject is a release-notes line.
`docs/agent/dev.md` ("Commits: the subject is the changelog", "Pull requests")
holds the rules; this file is the procedure. dev.md wins.

## 1. Read the branch

Expand All @@ -20,14 +22,20 @@ git diff --stat origin/main...HEAD
Read the diff wherever a subject does not state the user-visible change. Report a
non-empty `HEAD..origin/main` as "branch is behind". Do not rebase unasked.

## 2. One entry or two
## 2. Squash or rebase

Count the entries a release-notes reader sees: commits of a shown type (`feat`,
`fix`, `security`, `perf`, `docs`) plus any commit carrying `!`, `Upgrade:` or
`BREAKING CHANGE:`. Tests, refactors and chores serving one of those add no entry.

Two visible entries mean two PRs. Never write a title containing "and": report
the split and which commits belong to which PR.
- One visible entry: squash. The title is that entry.
- Several, and every commit stands alone and passes commit-lint: rebase. Say
so in the handover, and write the title as the lead change; it is not a
changelog line.
- Several, but mixed with fixups or work in progress: report it. The branch
needs cleaning into coherent commits, or splitting. Do not rebase unasked.

Never write a title containing "and".

## 3. Title

Expand Down Expand Up @@ -82,11 +90,12 @@ Add `--draft` when asked. Never merge.

## Merge

The repository builds the squash body from the branch's commit messages, not
from the PR description. A footer written in the description reaches main only
when the merge uses the description as the body: the merge dialog, or
`gh pr merge --squash --body-file`. State this when handing the PR over.
State the merge mode when handing the PR over.

Squash: the repository builds the squash body from the branch's commit
messages, not from the PR description. A footer written in the description
reaches main only when the merge uses the description as the body: the merge
dialog, or `gh pr merge --squash --body-file`.

Rebase merge, when requested, is the exception: every commit becomes its own
changelog line, each must pass commit-lint alone, and the title is not a
changelog line.
Rebase: `gh pr merge --rebase`. The commits land unchanged, so their footers
are the ones that count; one written only in the description is lost.
6 changes: 4 additions & 2 deletions docs/agent/dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -424,8 +424,10 @@ unit test fails when the two disagree.

## Pull requests

- **One PR is one changelog entry.** Squash merge; the PR title is the commit subject, in the format above, under 70 chars. A PR that needs two changelog lines is two PRs.
- PR body: `## Summary` with 1-3 bullets, plus any `Upgrade:` / `BREAKING CHANGE:` footer, which lands in the squashed commit where a reviewer can argue with it. **No "Test plan" section** - project preference.
- **Squash or rebase, never a merge commit.** Pick per PR:
- **Squash** when the branch is one change, or its commits are work in progress. The PR title becomes the commit subject and the changelog line, in the format above, under 70 chars.
- **Rebase** when the branch is a series of coherent commits that each stand alone, for example a fix, then a framework feature, then a stacklet that uses it. Every commit lands on `main` as it is and becomes its own changelog line, so each must pass `tools/commit-lint` and carry its own `Upgrade:` / `BREAKING CHANGE:` footer. The title still has to parse, because CI checks it, but it is not a changelog line.
- PR body: `## Summary` with 1-3 bullets. On a squash merge, an `Upgrade:` / `BREAKING CHANGE:` footer in the body lands in the squashed commit where a reviewer can argue with it; on a rebase merge it must be in the commit. **No "Test plan" section** - project preference.
- **Never `git push` without explicit human approval.** Every push, every branch, every time.

## Releases
Expand Down
Loading