--- source_keys: - conventional-commits-spec - commitlint-config-conventional - org-commit-conventions --- # Creating a new commit 1. **Gather context** — what changed and why, from the staged diff, the PR description, or the issue. Confirm the staged diff is one logical, independently reviewable and reversible change that leaves the repository buildable and testable. If it bundles unrelated work, suggest splitting it before going further. 2. **Determine the type** — read it off the change itself: a new user-visible feature is `feat`, a bug fix is `fix`. For the full 11-type set and each type's SemVer impact, read `references/conventional-commits-spec.md`. 3. **Determine the scope** — use the scope from plugin config where one is set, otherwise infer it from the files changed (`api`, `db`, `cli`, `config`). Scope is optional, but it identifies which part of the system moved and is worth setting. 4. **Write the description** — imperative mood, no trailing period: "add user authentication", "fix race condition in cache". Neither source spec sets a target below the 100-character header maximum, but convention favours roughly 50 characters so `git log --oneline` stays readable. 5. **Add a body when the change is non-trivial** — blank line first, wrapped at 100 characters. Explain *why*, not what: the diff already shows what changed, and the message's job is the context the diff cannot carry — motivation, root cause, tradeoffs. Follow the Why / Implementation Notes / Impact structure in `references/commit-template.md`. 6. **Add footers where they apply** — `Fixes: #123`, `Refs: #123`, `ADR: 0012`, `Co-authored-by: Name `, `BREAKING CHANGE: description`. For the full trailer list, read `references/commit-template.md`. 7. **Signal a breaking change with `!` before the colon** — `feat!: drop Node 6` is visible in `git log --oneline`, where the `BREAKING CHANGE:` footer alone is machine-readable but hidden. Use both when the break needs describing. 8. **Validate, confirm, execute** — check header length, type, lowercase subject and trailing period against commitlint, show the message, and commit only once the caller has approved. Never add `--no-verify`.