agentleFS
Gord1yGord1y/countersign-skills/skills/feature-pr-description/SKILL.md

feature-pr-description

Skill2 starsChanged 39 days agoMITView on GitHub

Write the body of a feature or fix PR from the branch's real diff, following the repo's PR contract.

  • Commits and pushes

The file

We split this skill into the rules it gives an agent

9 rules. About 0 are common, 6 are distinctive, and 3 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈6

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Use the three-dot form for the diff so the base's own commits stay out of it.

    line 40
  2. Distinctive:

    When a PR already exists and the branch gained commits since its body was written, the description covers the whole branch again, never …

    line 44
  3. Distinctive:

    Commit subjects are what you intended.

    line 49
  4. Distinctive:

    When the branch adds or renames translation keys, name them, and check every locale that consumes them.

    line 72
  5. Very specific:

    Every other block is fixed text: a heading with content under it, a table, a checklist, a footer after a --- rule.

    line 85
  6. Very specific:

    Write the body to changes/<date>-<branch>/pr.md in the uncommitted drafts location from Repo facts: <date> is today as YYYY-MM-DD, <branch> …

    line 93
  7. Distinctive:

    Do not open or edit a PR as part of writing the description.

    line 106
  8. Distinctive:

    Use only the allowed PR title types from Repo facts.

    line 115
  9. Very specific:

    If local.md exists next to this file, read it.

    line 146

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Feature PR description

Repo facts

This skill needs the facts below. Look each one up in the repo's CLAUDE.md (or AGENTS.md) and the files it imports or points to (of a repo-facts file, only this skill's section: sed -n '/^## feature-pr-description$/,/^## /p' <file>), then in local.md next to this file. If neither has it, ask the user once, then suggest the one line to add to CLAUDE.md so the next run finds it.

FactExample
PR description contract (a doc the description must follow, if any)docs/pr-description.md
Branch flow and the default base branch for a feature PRfeature → release-<semver> → staging → main; a feature targets the open release-<semver> branch
Paths whose change widens a PR's blast radius (for example middleware, auth, shared UI)src/lib/, src/middleware.ts, CI config, lint and test config, package.json
Where uncommitted drafts goa gitignored writeups/ folder in the main checkout
Allowed PR title typesfeat, fix, refactor, chore, docs, ci, with release reserved for promotion merges
Release index command, if anyscripts/release-index.sh

The contract doc, when the repo has one, owns the shape, the section rules, the tone and the list of things that must not appear. This skill is the workflow around it: how to gather the material the contract asks for, and where the result goes. If the two ever disagree, the doc wins.

1. Establish the range

A description covers a branch, not a working tree.

git log --oneline <base>..HEAD          # base is the PR's target branch
git diff --stat <base>...HEAD
gh pr view <N> --json title,body,baseRefName,headRefName   # when a PR already exists

Use the three-dot form for the diff so the base's own commits stay out of it. If no PR exists yet, target the base the branch flow from Repo facts names for a feature PR. Ask rather than assume when the branch name does not make it obvious.

When a PR already exists and the branch gained commits since its body was written, the description covers the whole branch again, never only the new commits. Propose the title with it every time.

2. Read the diff, not the commit messages

Commit subjects are what you intended; the diff is what shipped. Every claim in the description has to come from one of:

  • a hunk you read,
  • a test that pins the behaviour,
  • a command you ran and whose output you saw.

The contract's highest-value section is where you deviated from the obvious approach, and that is never in a commit subject. Look for it deliberately: a shared primitive you touched, a wire payload you changed, a route you renamed, a default you flipped, a second design you rejected. If a commit was a follow-up fixing an earlier commit on the same branch, describe the end state, never the detour.

3. Find the blast radius yourself

Anything under the blast-radius paths from Repo facts reaches past the feature. Name the other consumers and say why they stay inert. Search the source folder for every use of what changed, excluding the files the branch already touches:

grep -rn "<ChangedComponent" <source-folder> | grep -v "$(git diff --name-only <base>...HEAD | tr '\n' '|')"

When the branch adds or renames translation keys, name them, and check every locale that consumes them. A reviewer who discovers a shared change you did not mention reads the rest of the document with less trust.

4. Carry the repo's PR template

gh pr create --body-file never applies the repo's pull request template, so whatever the template holds reaches the PR only if the body carries it. Look for the template in GitHub's places: .github/pull_request_template.md, pull_request_template.md, docs/pull_request_template.md (any case), or one file under a PULL_REQUEST_TEMPLATE/ folder there when it fits this PR.

  • Guidance in the template (HTML comments, italic placeholder lines, "describe your change here") is an instruction: follow it, then replace it with the text it asks for.
  • Every other block is fixed text: a heading with content under it, a table, a checklist, a footer after a --- rule. Copy it verbatim, in the template's order and position.

A footer such as a list of review commands goes at the end of the body, exactly as the template has it, even when the contract doc never mentions it.

5. Write it to a file

Write the body to changes/<date>-<branch>/pr.md in the uncommitted drafts location from Repo facts: <date> is today as YYYY-MM-DD, <branch> the branch name with / written as -. When the branch already has a folder under changes/ (a QA run or a walkthrough made it), write into that one instead. Resolve the location from the main checkout, never from a worktree: a gitignored folder inside a worktree is deleted along with the worktree. For a writeups/ folder in the main checkout, this resolves to the right folder from the main checkout and from any worktree alike:

WRITEUPS="$(dirname "$(git rev-parse --path-format=absolute --git-common-dir)")/writeups"
PR_BODY="$WRITEUPS/changes/<date>-<branch>/pr.md"

Do not open or edit a PR as part of writing the description. Pushing a branch, creating a PR, and editing a PR body are visible actions that need the user's explicit go-ahead each time. When they give it:

gh pr create --base <base> --head <branch> --title "<type>: <subject>" --body-file "$PR_BODY"
gh pr edit <N> --body-file "$PR_BODY"

Use only the allowed PR title types from Repo facts.

6. Check it against the contract before handing it over

Diff the body against the template: every fixed block from step 4 is there, word for word.

Walk the contract's "Do not include" list and delete anything that crept in: a verification or testing section, a locales section, a recap of what a backend now sends, a commit list, a file-by-file tour, a screenshot gallery, a restatement of the ticket.

Then check that the title and body describe this repo's change only: no other repo by name, no machine path, no private infrastructure. That context goes in the uncommitted drafts. Anything another repo needs goes to the maintainer as a private brief, briefs/<date>-<topic>.md in the drafts location, never into the PR.

Then check the headings. Each one has to be a claim a reviewer could disagree with. Contract changes, Improvements, Testing and Other are labels, not claims: rewrite them into the sentence the section actually argues, or fold the section into a neighbour.

Last, read the opening two paragraphs alone. A reader who stops there should know what merged and why it was needed. If they only learn that "several improvements" landed, the description has not started yet.

Related

  • promotion-pr-description: release branch → staging and staging → main PRs, built from the release note
  • release-notes: the release record a release branch carries, and the release index command from Repo facts that regenerates its index
  • thorough-diff-review: review the diff before describing it

If local.md exists next to this file, read it; where it disagrees with this file, it wins.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.