Files
paperclip/skills/release-changelog/SKILL.md
Dotta cdf63d0024 Add release-changelog skill and releases/ directory
Introduces the release-changelog skill (skills/release-changelog/SKILL.md)
that teaches agents to generate user-facing changelogs from git history,
changesets, and merged PRs. Includes breaking change detection, categorization
heuristics, and structured markdown output template.

Also creates the releases/ directory convention for storing versioned
release notes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 11:21:44 -06:00

9.6 KiB

name, description
name description
release-changelog Generate user-facing release changelogs for Paperclip. Reads git history, merged PRs, and changeset files since the last release tag. Detects breaking changes, categorizes changes, and outputs structured markdown to releases/v{version}.md. Use when preparing a release or when asked to generate a changelog.

Release Changelog Skill

Generate a user-facing changelog for a new Paperclip release. This skill reads the commit history, changeset files, and merged PRs since the last release tag, detects breaking changes, categorizes everything, and writes a structured release notes file.

Output: releases/v{version}.md in the repo root. Review required: Always present the draft for human sign-off before finalizing. Never auto-publish.


Step 1 — Determine the Release Range

Find the last release tag and the planned version:

# Last release tag (most recent semver tag)
git tag --sort=-version:refname | head -1
# e.g. v0.2.7

# All commits since that tag
git log v0.2.7..HEAD --oneline --no-merges

If no tag exists yet, use the initial commit as the base.

The new version number comes from one of:

  • An explicit argument (e.g. "generate changelog for v0.3.0")
  • The bump type (patch/minor/major) applied to the last tag
  • The version already set in cli/package.json if scripts/release.sh has been run

Step 2 — Gather Raw Change Data

Collect changes from three sources, in priority order:

2a. Git Commits

git log v{last}..HEAD --oneline --no-merges
git log v{last}..HEAD --format="%H %s" --no-merges   # full SHAs for file diffs

2b. Changeset Files

Look for unconsumed changesets in .changeset/:

ls .changeset/*.md | grep -v README.md

Each changeset file has YAML frontmatter with package names and bump types (patch, minor, major), followed by a description. Parse these — the bump type is a strong categorization signal, and the description may contain user-facing summaries.

2c. Merged PRs (when available)

If GitHub access is available via gh:

gh pr list --state merged --search "merged:>={last-tag-date}" --json number,title,body,labels

PR titles and bodies are often the best source of user-facing descriptions. Prefer PR descriptions over raw commit messages when both are available.


Step 3 — Detect Breaking Changes

Scan for breaking changes using these signals. Any match flags the release as containing breaking changes, which affects version bump requirements and changelog structure.

3a. Migration Files

Check for new migration files since the last tag:

git diff --name-only v{last}..HEAD -- packages/db/src/migrations/
  • New migration files exist = DB migration required in upgrade.
  • Inspect migration content: look for DROP, ALTER ... DROP, RENAME to distinguish destructive vs. additive migrations.
  • Additive-only migrations (new tables, new nullable columns, new indexes) are safe but should still be mentioned.
  • Destructive migrations (column drops, type changes, table drops) = breaking.

3b. Schema Changes

git diff v{last}..HEAD -- packages/db/src/schema/

Look for:

  • Removed or renamed columns/tables
  • Changed column types
  • Removed default values or nullable constraints
  • These indicate breaking DB changes even if no explicit migration file exists

3c. API Route Changes

git diff v{last}..HEAD -- server/src/routes/ server/src/api/

Look for:

  • Removed endpoints
  • Changed request/response shapes (removed fields, type changes)
  • Changed authentication requirements

3d. Config Changes

git diff v{last}..HEAD -- cli/src/config/ packages/*/src/*config*

Look for renamed, removed, or restructured configuration keys.

3e. Changeset Severity

Any .changeset/*.md file with a major bump = explicitly flagged breaking.

3f. Commit Conventions

Scan commit messages for:

  • BREAKING: or BREAKING CHANGE: prefix
  • ! after the type in conventional commits (e.g. feat!:, fix!:)

Version Bump Rules

Condition Minimum Bump
Destructive migration (DROP, RENAME) major
Removed API endpoints or fields major
Any major changeset or BREAKING: commit major
New (additive) migration minor
New features (feat: commits, minor changesets) minor
Bug fixes only patch

If the planned bump is lower than the minimum required, warn the reviewer and recommend the correct bump level.


Step 4 — Categorize Changes

Assign every meaningful change to one of these categories:

Category What Goes Here Shows in User Notes?
Breaking Changes Anything requiring user action to upgrade Yes (top, with warning)
Highlights New user-visible features, major behavioral changes Yes (with 1-2 sentence descriptions)
Improvements Enhancements to existing features Yes (bullet list)
Fixes Bug fixes Yes (bullet list)
Internal Refactoring, deps, CI, tests, docs No (dev changelog only)

Categorization Heuristics

Use these signals to auto-categorize. When signals conflict, prefer the higher-visibility category and flag for human review.

Signal Category
Commit touches migration files, schema changes Breaking Change (if destructive)
Changeset marked major Breaking Change
Commit message has BREAKING: or !: Breaking Change
New UI components, new routes, new API endpoints Highlight
Commit message starts with feat: or add: Highlight or Improvement
Changeset marked minor Highlight
Commit message starts with fix: or bug: Fix
Changeset marked patch Fix or Improvement
Commit message starts with chore:, refactor:, ci:, test:, docs: Internal
PR has detailed body with user-facing description Use PR body as the description

Writing Good Descriptions

  • Highlights get 1-2 sentence descriptions explaining the user benefit. Write from the user's perspective ("You can now..." not "Added a component that...").
  • Improvements and Fixes are concise bullet points.
  • Breaking Changes get detailed descriptions including what changed, why, and what the user needs to do.
  • Group related commits into a single changelog entry. Five commits implementing one feature = one Highlight entry, not five bullets.
  • Omit purely internal changes from user-facing notes entirely.

Step 5 — Write the Changelog

Output the changelog to releases/v{version}.md using this template:

# v{version}

> Released: {YYYY-MM-DD}

{If breaking changes detected, include this section:}

## Breaking Changes

> **Action required before upgrading.** Read the Upgrade Guide below.

- **{Breaking change title}** — {What changed and why. What the user needs to do.}

## Highlights

- **{Feature name}** — {1-2 sentence description of what it does and why it matters.}

## Improvements

- {Concise description of improvement}

## Fixes

- {Concise description of fix}

---

{If breaking changes detected, include this section:}

## Upgrade Guide

### Before You Update

1. **Back up your database.**
   - SQLite: `cp paperclip.db paperclip.db.backup`
   - Postgres: `pg_dump -Fc paperclip > paperclip-pre-{version}.dump`
2. **Note your current version:** `paperclip --version`

### After Updating

{Specific steps: run migrations, update configs, etc.}

### Rolling Back

If something goes wrong:
1. Restore your database backup
2. `npm install @paperclipai/server@{previous-version}`

Template Rules

  • Omit any empty section entirely (don't show "## Fixes" with no bullets).
  • The Breaking Changes section always comes first when present.
  • The Upgrade Guide always comes last when present.
  • Use **bold** for feature/change names, regular text for descriptions.
  • Keep the entire changelog scannable — a busy user should get the gist from headings and bold text alone.

Step 6 — Present for Review

After generating the draft:

  1. Show the full changelog to the reviewer (CTO or whoever triggered the release).
  2. Flag ambiguous items — commits you weren't sure how to categorize, or items that might be breaking but aren't clearly signaled.
  3. Flag version bump mismatches — if the planned bump is lower than what the changes warrant.
  4. Wait for approval before considering the changelog final.

If the reviewer requests edits, update releases/v{version}.md accordingly.

Do not proceed to publishing, website updates, or social announcements. Those are handled by the release coordination skill (separate from this one).


Directory Convention

Release changelogs live in releases/ at the repo root:

releases/
  v0.2.7.md
  v0.3.0.md
  ...

Each file is named v{version}.md matching the git tag. This directory is committed to the repo and serves as the source of truth for release history.

The releases/ directory should be created with a .gitkeep if it doesn't exist yet.


Quick Reference

# Full workflow summary:

# 1. Find last tag
LAST_TAG=$(git tag --sort=-version:refname | head -1)

# 2. Commits since last tag
git log $LAST_TAG..HEAD --oneline --no-merges

# 3. Files changed (for breaking change detection)
git diff --name-only $LAST_TAG..HEAD

# 4. Migration changes specifically
git diff --name-only $LAST_TAG..HEAD -- packages/db/src/migrations/

# 5. Schema changes
git diff $LAST_TAG..HEAD -- packages/db/src/schema/

# 6. Unconsumed changesets
ls .changeset/*.md | grep -v README.md

# 7. Merged PRs (if gh available)
gh pr list --state merged --search "merged:>=$(git log -1 --format=%aI $LAST_TAG)" \
  --json number,title,body,labels