---
name: changelog-conventions
source: https://app.decimal.ai/s/changelog-conventions@1/SKILL.md
source_sha256: ea28d67e921d
---

# Changelog & Commit Conventions

## Contract

Write changelogs in **Keep a Changelog 1.1.0** and commit messages in **Conventional Commits 1.0.0**,
using the exact vocabulary, headings, and ordering below. Apply whenever producing a `CHANGELOG.md`
entry, release notes, or a git commit subject — substitute none of the fixed names for synonyms.

## Changelog rules

1. **File header.** The first line is exactly `# Changelog`, immediately followed by the boilerplate
   line `All notable changes to this project will be documented in this file.`
2. **Unreleased section first.** An `## [Unreleased]` heading sits above every released version, as a
   landing spot for un-shipped work.
3. **Released version headings.** Each released heading is exactly `## [X.Y.Z] - YYYY-MM-DD`: the
   version in square brackets, an ISO 8601 date, joined by a space-hyphen-space ` - `. Never
   `## v1.2.0`, never `## Version 1.2.0`, never a human date like `(January 5, 2024)`.
4. **Reverse-chronological order.** List versions newest-first; `## [2.0.0]` appears above
   `## [1.9.0]`, which appears above `## [1.0.0]`.
5. **The six change headings, ONLY.** Group entries under these H3 headings and no others, in this
   order when more than one is present:
   `### Added`, `### Changed`, `### Deprecated`, `### Removed`, `### Fixed`, `### Security`.
6. **Map intent to the fixed heading — do not invent names.**
   - New functionality → `### Added` (never "New Features", "Features", "Highlights").
   - Behavior / performance / config changes to existing functionality → `### Changed` (never
     "Improvements", "Performance", "Enhancements").
   - Soon-to-be-removed but still present → `### Deprecated`.
   - Removed functionality → `### Removed`.
   - Bug fixes → `### Fixed` (never "Bug Fixes", "Fixes").
   - Vulnerability fixes → `### Security` (never "Security Fixes", and not `### Fixed`).
7. **Bullets.** Each individual change is a `- ` bullet line under its heading.
8. **Yanked releases.** A release pulled after publishing keeps its heading but appends the literal
   token `[YANKED]` after the date: `## [X.Y.Z] - YYYY-MM-DD [YANKED]`.

## Commit rules

1. **Subject shape.** `<type>(<optional scope>): <description>` — type, an optional parenthesized
   scope, a colon, a space, then the description.
2. **Closed type set.** The type is one of exactly: `feat`, `fix`, `docs`, `style`, `refactor`,
   `perf`, `test`, `build`, `ci`, `chore`, `revert`. Nothing else. A new capability is `feat`, never
   `add`/`update`/`feature`; a code-cleanup with no behavior change is `refactor`; a whitespace/format
   pass is `style`, not `chore` or `refactor`; a speedup is `perf`, not `feat`/`fix`; a dependency or
   pipeline bump is `build` or `ci`, not `chore`/`deps`.
3. **Description form.** Lowercase, imperative mood (`add`, not `added`/`adds`/`adding`), with **no
   trailing period**.
4. **Breaking changes.** Put a `!` immediately before the colon (e.g. `feat(api)!:`) and/or add a
   footer line beginning `BREAKING CHANGE: <text>`. Either signals a major-version break; using both
   is fine.
5. **Semver mapping.** `fix` → bump PATCH (the Z in X.Y.Z); `feat` → bump MINOR (the Y); any breaking
   change → bump MAJOR (the X), and resets MINOR and PATCH to 0.
6. **Issue references.** Link tickets in a footer line such as `Closes #123` (or `Fixes #456`), placed
   after a blank line below the body.

## Worked examples

Each is BEFORE (the free-form default a model reaches for) → AFTER (the conforming form).

**Version heading.**
- BEFORE: `## Version 1.2.0 (January 5, 2024)`
- AFTER: `## [1.2.0] - 2024-01-05`

**New feature → Added.**
- BEFORE:
  ```markdown
  ### New Features
  - Dark mode
  ```
- AFTER:
  ```markdown
  ### Added
  - Dark mode toggle in settings
  ```

**Performance change → Changed (not "Improvements").**
- BEFORE:
  ```markdown
  ### Improvements
  - Checkout is 40% faster
  ```
- AFTER:
  ```markdown
  ### Changed
  - Checkout flow is now 40% faster
  ```

**Bug fix → Fixed (not "Bug Fixes").**
- BEFORE:
  ```markdown
  ### Bug Fixes
  - Fixed the login crash
  ```
- AFTER:
  ```markdown
  ### Fixed
  - Login crash on empty password
  ```

**Vulnerability → Security (not Fixed).**
- BEFORE:
  ```markdown
  ### Bug Fixes
  - Patched an XSS hole in the comment renderer
  ```
- AFTER:
  ```markdown
  ### Security
  - Sanitize comment HTML to close a stored XSS vector
  ```

**Removal vs. deprecation, in order.**
- BEFORE:
  ```markdown
  ### Removed
  - Dropped the /v1 API
  ### Deprecated
  - /v2 API will go away
  ```
- AFTER (Deprecated precedes Removed):
  ```markdown
  ### Deprecated
  - `/v2` API; migrate to `/v3` before the next major
  ### Removed
  - `/v1` API
  ```

**Unreleased + reverse order, a full skeleton.**
- BEFORE:
  ```markdown
  # Change Log
  ## 1.0.0
  - first release
  ## 1.1.0
  - CSV export
  ```
- AFTER:
  ```markdown
  # Changelog

  All notable changes to this project will be documented in this file.

  ## [Unreleased]

  ## [1.1.0] - 2024-03-02
  ### Added
  - Export-to-CSV for reports

  ## [1.0.0] - 2024-01-10
  ### Added
  - Initial release
  ```

**Yanked release.**
- BEFORE: `## 3.2.1 (pulled — broken migration)`
- AFTER: `## [3.2.1] - 2024-05-09 [YANKED]`

**Commit: feature.**
- BEFORE: `Added Google OAuth login.`
- AFTER: `feat(auth): add google oauth2 login`

**Commit: bug fix.**
- BEFORE: `Fixed race condition in payments`
- AFTER: `fix(payments): resolve race condition in payment processing`

**Commit: docs / style / refactor / perf / build, the easily-confused types.**
- BEFORE: `Update README with install steps` → AFTER: `docs(readme): document new install steps`
- BEFORE: `Ran prettier` → AFTER: `style: reformat with prettier`
- BEFORE: `Cleaned up helpers` → AFTER: `refactor(utils): restructure helper functions`
- BEFORE: `Made image resize faster` → AFTER: `perf(images): cache resize results`
- BEFORE: `Bump webpack` → AFTER: `build(deps): upgrade webpack to 5.90`

**Commit: breaking change.**
- BEFORE: `Changed user endpoint to return userId instead of id (breaks clients)`
- AFTER:
  ```
  feat(api)!: return userId instead of id

  BREAKING CHANGE: the user endpoint now returns userId instead of id.
  Update all consumers to read the new field.
  ```

**Commit + semver call-out.**
- BEFORE: `Fixed a typo in an error message — patch release`
- AFTER: `fix(errors): correct typo in timeout message` and "this bumps the PATCH (third) number".

## Edge cases & exceptions

- **Date not yet known / unreleased work.** Keep changes under `## [Unreleased]`; do not invent a
  date. Move them under a dated version heading only when the release is cut.
- **Several change types in one release.** Emit multiple H3 headings under the one version heading, in
  the canonical order (Added → Changed → Deprecated → Removed → Fixed → Security). Omit headings with
  no entries — don't print empty sections.
- **A change is both a fix and security-relevant.** If it closes a vulnerability, it goes under
  `### Security`, not `### Fixed`.
- **A rename or signature change of existing behavior** is `### Changed`, not `### Added` — `Added` is
  for net-new surface only.
- **Commit with no natural scope.** The scope is optional: `docs: fix changelog typo` is valid; drop
  the parentheses entirely rather than inventing a placeholder scope.
- **A revert** uses the `revert` type: `revert: feat(auth): add google oauth2 login`.
- **Breaking change on a non-feat type** is still allowed: `fix(api)!: drop the legacy id field` plus
  the `BREAKING CHANGE:` footer bumps MAJOR regardless of base type.

## Do / Don't

- Do write `## [1.2.0] - 2024-01-05`. Don't write `## v1.2.0` or `## Version 1.2.0`.
- Do use `### Added`. Never use `### New Features` or `### Highlights`.
- Do use `### Fixed`. Never use `### Bug Fixes`.
- Do use `### Changed` for perf/behavior. Never use `### Improvements` or `### Performance`.
- Do file vulnerability fixes under `### Security`. Don't bury them in `### Fixed`.
- Do place `## [Unreleased]` on top. Don't omit it on a fresh file.
- Do start commit subjects with a type from the closed set. Never capitalize the type or use a verb
  like `Add`/`Update`.
- Do keep the description lowercase imperative with no period. Don't write past tense or end with `.`.
- Do mark breaks with `!` and/or a `BREAKING CHANGE:` footer. Don't rely on prose alone.

## Common mistakes

- Reaching for descriptive section names ("Highlights", "Improvements", "Bug Fixes") instead of the
  six fixed headings.
- Writing the version as `v1.2.0` or with a human-readable date instead of `[X.Y.Z] - YYYY-MM-DD`.
- Listing versions oldest-first.
- Filing a vulnerability fix under `### Fixed`.
- Omitting the `## [Unreleased]` section and the boilerplate header line.
- Capitalizing the commit type (`Feat`), using past tense (`added oauth`), or ending with a period.
- Inventing a type (`update`, `add`, `feature`, `deps`) instead of using `feat`/`build`.
- Forgetting the `!` and/or `BREAKING CHANGE:` footer on a breaking change, or mis-mapping the semver
  bump (a `feat` is MINOR, a `fix` is PATCH, a break is MAJOR).

## Quick checklist

- [ ] File opens `# Changelog` + boilerplate line; `## [Unreleased]` on top; newest version first.
- [ ] Version heading is `## [X.Y.Z] - YYYY-MM-DD` (brackets + ISO date); `[YANKED]` appended if pulled.
- [ ] Only the six H3 headings, in canonical order; intents mapped correctly; `- ` bullets.
- [ ] Commit subject `type(scope): description`; type from the closed set; lowercase imperative, no period.
- [ ] Breaking change → `!` and/or `BREAKING CHANGE:` footer; semver bump matches.
