From 597c6f91b3ea00e2b4f4e48256b95f9270415fd0 Mon Sep 17 00:00:00 2001 From: wasabeef Date: Tue, 12 May 2026 19:04:58 +0900 Subject: [PATCH 1/3] docs: improve release note guidance Why v1.0.1 generated a low-level release note because several review follow-up commits were visible as release bullets. User impact Maintainers and AI agents now have clearer rules for PR titles, commit bodies, and Release note lines before tagging. Verification - git diff --check Release note: skip --- .github/PULL_REQUEST_TEMPLATE.md | 13 +++++++++++++ AGENTS.md | 3 +++ CLAUDE.md | 3 +++ docs/architecture.md | 14 ++++++++++++-- docs/engineering.md | 29 +++++++++++++++++++++++++++++ 5 files changed, 60 insertions(+), 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 58717427..2e9f18ae 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -4,6 +4,19 @@ +## Release Note Plan + + + ## Type of Change - [ ] Fix diff --git a/AGENTS.md b/AGENTS.md index b3aa2443..fb435431 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -141,6 +141,9 @@ Each `UserPromptSubmit` increments a turn counter. File changes inherit the curr - **Write commit subjects for release notes.** The subject should describe the user-facing outcome, not the mechanical edit. Prefer `fix(report): hide absorbed external review prompts` over `fix: address review comments`. - **Use the body when the subject is not enough.** Good AI-generated commits should include `Why`, `User impact`, `Verification`, and `Release note:` sections. Do not write `Why:`, `User impact:`, or `Verification:` with colons because git-cliff may parse them as commit footers instead of body text. - **Release note rules.** `feat:`, `fix:`, and `perf:` commits are included by default. `docs:`, `test:`, `refactor:`, `ci:`, `chore:`, and `build:` commits are omitted unless the body contains `Release note:` with a value other than `skip`. +- **Keep release notes human-sized.** A multi-commit PR should normally produce one clear release bullet per user-visible change, not one bullet per review fix. Put the public wording on the primary implementation commit with `Release note: `, and add `Release note: skip` to follow-up commits such as `address review findings`, `tighten fallback`, `bound window`, or generated bundle syncs unless they describe a distinct user-visible outcome. +- **PR titles should be release-summary quality.** Write PR titles as a user-facing outcome, not an implementation step. Even though GitHub Releases are generated from commits, a good PR title is the easiest review-time signal that the eventual release note will be understandable. +- **Preview release notes before merging release-sensitive PRs.** If `git-cliff --config .github/cliff.toml --latest --strip header` reads like an implementation log, rewrite commit subjects/bodies before merge or tag. Do not leave low-level cleanup commits visible just because tests pass. - **Do not rely on merge commits.** Release notes ignore `Merge pull request...`, version bumps, and generated bundle sync commits, so squash the important public wording into the real implementation commit. - **Structural vs behavioral changes** must not be mixed in a single commit. Renames/reformats separate from feature/fix commits. - **Before committing**, all four checks must pass (run from `packages/cli/`): diff --git a/CLAUDE.md b/CLAUDE.md index 0fafd53e..9e9218ce 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -141,6 +141,9 @@ Each `UserPromptSubmit` increments a turn counter. File changes inherit the curr - **Write commit subjects for release notes.** The subject should describe the user-facing outcome, not the mechanical edit. Prefer `fix(report): hide absorbed external review prompts` over `fix: address review comments`. - **Use the body when the subject is not enough.** Good AI-generated commits should include `Why`, `User impact`, `Verification`, and `Release note:` sections. Do not write `Why:`, `User impact:`, or `Verification:` with colons because git-cliff may parse them as commit footers instead of body text. - **Release note rules.** `feat:`, `fix:`, and `perf:` commits are included by default. `docs:`, `test:`, `refactor:`, `ci:`, `chore:`, and `build:` commits are omitted unless the body contains `Release note:` with a value other than `skip`. +- **Keep release notes human-sized.** A multi-commit PR should normally produce one clear release bullet per user-visible change, not one bullet per review fix. Put the public wording on the primary implementation commit with `Release note: `, and add `Release note: skip` to follow-up commits such as `address review findings`, `tighten fallback`, `bound window`, or generated bundle syncs unless they describe a distinct user-visible outcome. +- **PR titles should be release-summary quality.** Write PR titles as a user-facing outcome, not an implementation step. Even though GitHub Releases are generated from commits, a good PR title is the easiest review-time signal that the eventual release note will be understandable. +- **Preview release notes before merging release-sensitive PRs.** If `git-cliff --config .github/cliff.toml --latest --strip header` reads like an implementation log, rewrite commit subjects/bodies before merge or tag. Do not leave low-level cleanup commits visible just because tests pass. - **Do not rely on merge commits.** Release notes ignore `Merge pull request...`, version bumps, and generated bundle sync commits, so squash the important public wording into the real implementation commit. - **Structural vs behavioral changes** must not be mixed in a single commit. Renames/reformats separate from feature/fix commits. - **Before committing**, all four checks must pass (run from `packages/cli/`): diff --git a/docs/architecture.md b/docs/architecture.md index 1d78076c..bc099680 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -571,6 +571,13 @@ and `build:`) stay out of release notes unless their body contains a `Release note:` line. `Release note: skip` hides an otherwise public-looking commit. +GitHub Release notes do not use PR titles directly. PR titles should still be +written as release-summary-quality text because they are the review-time signal +that the underlying commit subjects and `Release note:` lines are also +user-facing. When a PR contains several follow-up commits for the same behavior, +keep only the primary implementation commit visible in the release note and mark +review-fix commits with `Release note: skip`. + The canonical npm package is `agent-note`. The workflow also publishes `@wasabeef/agentnote` from the same built `dist/` as a reserved alias package, but end-user documentation should continue to point to `agent-note`. Release steps: @@ -582,8 +589,11 @@ Release steps: - `npm -w packages/cli test` 4. Review the generated release note locally before tagging: - `git-cliff --config .github/cliff.toml --latest --strip header` -5. Commit the version bump to `main`. -6. Create and push the matching git tag, for example `v1.0.1`. +5. If the generated note reads like an implementation log, rewrite the relevant + commit subjects or add `Release note:` / `Release note: skip` lines before + tagging. +6. Commit the version bump to `main`. +7. Create and push the matching git tag, for example `v1.0.1`. Important: diff --git a/docs/engineering.md b/docs/engineering.md index 5a1ddce0..d35b0af8 100644 --- a/docs/engineering.md +++ b/docs/engineering.md @@ -105,6 +105,9 @@ subject as public copy unless the commit type is intentionally internal. - If a public-looking commit should be hidden, add `Release note: skip`. - Do not put release-worthy wording only in a PR title or merge commit. Merge commits, version bumps, and generated bundle sync commits are excluded from release notes. - Avoid vague subjects such as `address review notes`, `sync generated bundle`, `polish docs`, or `fix tests`. Name the visible outcome instead. +- Keep multi-commit PRs readable in the generated release note. Review follow-up commits should usually be `Release note: skip` unless they are a separate user-visible change. +- A PR title is not the release-note source, but it should still read like the top-level release summary for the PR. If the title would be a bad release bullet, improve it before opening or merging the PR. +- Before tagging, run `git-cliff --config .github/cliff.toml --latest --strip header`. If the output reads like an implementation log, rewrite commit subjects/bodies before cutting the release. Good commit body shape: @@ -125,3 +128,29 @@ Release note: Compact PR reports now hide absorbed external review prompts. Use `Release note: skip` for commits like version bumps, generated bundles, test-only coverage, local refactors without behavior changes, and docs-only maintenance that does not change user-facing guidance. + +For a PR with several implementation commits for the same behavior, prefer this +shape: + +```text +fix(hooks): recover Codex commits in cmux sessions + +Why +cmux can preserve CODEX_THREAD_ID while the repository-local active-session +pointer is stale. + +User impact +Codex commits created from cmux are recorded again without attributing unrelated +read-only shell commands. + +Verification +- npm -w packages/cli test + +Release note: Codex commits made from cmux sessions are now recorded reliably without pulling in unrelated transcript history. +``` + +Follow-up review commits in that same PR should usually include: + +```text +Release note: skip +``` From fd938a6eee6f9536c07cd61fd41d795680175480 Mon Sep 17 00:00:00 2001 From: wasabeef Date: Tue, 12 May 2026 22:18:06 +0900 Subject: [PATCH 2/3] docs: capitalize generated release notes Why Generated release notes can inherit lower-case imperative commit subjects, which reads awkwardly in English release bullets. User impact Future generated release notes capitalize the first rendered character while still requiring clear human-written release wording. Verification - git-cliff --config .github/cliff.toml --latest --strip header - git diff --check Release note: skip --- .github/cliff.toml | 4 ++-- AGENTS.md | 1 + CLAUDE.md | 1 + docs/architecture.md | 5 +++++ docs/engineering.md | 1 + 5 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/cliff.toml b/.github/cliff.toml index 76fbcdf1..5611cde3 100644 --- a/.github/cliff.toml +++ b/.github/cliff.toml @@ -20,9 +20,9 @@ body = """ {% for commit in commits %} {% if group != "Changed" or (commit.body and "Release note:" in commit.body) %} {% if commit.body and "Release note:" in commit.body -%} - - {{ commit.body | split(pat="Release note:") | last | split(pat="\n") | first | trim }} + - {{ commit.body | split(pat="Release note:") | last | split(pat="\n") | first | trim | upper_first }} {% else -%} - - {{ commit.message | split(pat="\n") | first | trim }} + - {{ commit.message | split(pat="\n") | first | trim | upper_first }} {% endif %} {% endif %} {% endfor %} diff --git a/AGENTS.md b/AGENTS.md index fb435431..0b896316 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -142,6 +142,7 @@ Each `UserPromptSubmit` increments a turn counter. File changes inherit the curr - **Use the body when the subject is not enough.** Good AI-generated commits should include `Why`, `User impact`, `Verification`, and `Release note:` sections. Do not write `Why:`, `User impact:`, or `Verification:` with colons because git-cliff may parse them as commit footers instead of body text. - **Release note rules.** `feat:`, `fix:`, and `perf:` commits are included by default. `docs:`, `test:`, `refactor:`, `ci:`, `chore:`, and `build:` commits are omitted unless the body contains `Release note:` with a value other than `skip`. - **Keep release notes human-sized.** A multi-commit PR should normally produce one clear release bullet per user-visible change, not one bullet per review fix. Put the public wording on the primary implementation commit with `Release note: `, and add `Release note: skip` to follow-up commits such as `address review findings`, `tighten fallback`, `bound window`, or generated bundle syncs unless they describe a distinct user-visible outcome. +- **Write release notes as natural English sentences.** The generator capitalizes the first character as a safety net, but do not rely on that to fix awkward wording. Prefer `Release note: Codex commits made from cmux sessions are now recorded reliably.` over `Release note: recover codex env sessions`. - **PR titles should be release-summary quality.** Write PR titles as a user-facing outcome, not an implementation step. Even though GitHub Releases are generated from commits, a good PR title is the easiest review-time signal that the eventual release note will be understandable. - **Preview release notes before merging release-sensitive PRs.** If `git-cliff --config .github/cliff.toml --latest --strip header` reads like an implementation log, rewrite commit subjects/bodies before merge or tag. Do not leave low-level cleanup commits visible just because tests pass. - **Do not rely on merge commits.** Release notes ignore `Merge pull request...`, version bumps, and generated bundle sync commits, so squash the important public wording into the real implementation commit. diff --git a/CLAUDE.md b/CLAUDE.md index 9e9218ce..c543aa8e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -142,6 +142,7 @@ Each `UserPromptSubmit` increments a turn counter. File changes inherit the curr - **Use the body when the subject is not enough.** Good AI-generated commits should include `Why`, `User impact`, `Verification`, and `Release note:` sections. Do not write `Why:`, `User impact:`, or `Verification:` with colons because git-cliff may parse them as commit footers instead of body text. - **Release note rules.** `feat:`, `fix:`, and `perf:` commits are included by default. `docs:`, `test:`, `refactor:`, `ci:`, `chore:`, and `build:` commits are omitted unless the body contains `Release note:` with a value other than `skip`. - **Keep release notes human-sized.** A multi-commit PR should normally produce one clear release bullet per user-visible change, not one bullet per review fix. Put the public wording on the primary implementation commit with `Release note: `, and add `Release note: skip` to follow-up commits such as `address review findings`, `tighten fallback`, `bound window`, or generated bundle syncs unless they describe a distinct user-visible outcome. +- **Write release notes as natural English sentences.** The generator capitalizes the first character as a safety net, but do not rely on that to fix awkward wording. Prefer `Release note: Codex commits made from cmux sessions are now recorded reliably.` over `Release note: recover codex env sessions`. - **PR titles should be release-summary quality.** Write PR titles as a user-facing outcome, not an implementation step. Even though GitHub Releases are generated from commits, a good PR title is the easiest review-time signal that the eventual release note will be understandable. - **Preview release notes before merging release-sensitive PRs.** If `git-cliff --config .github/cliff.toml --latest --strip header` reads like an implementation log, rewrite commit subjects/bodies before merge or tag. Do not leave low-level cleanup commits visible just because tests pass. - **Do not rely on merge commits.** Release notes ignore `Merge pull request...`, version bumps, and generated bundle sync commits, so squash the important public wording into the real implementation commit. diff --git a/docs/architecture.md b/docs/architecture.md index bc099680..75bb0a3a 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -578,6 +578,11 @@ user-facing. When a PR contains several follow-up commits for the same behavior, keep only the primary implementation commit visible in the release note and mark review-fix commits with `Release note: skip`. +The changelog template applies `upper_first` to each rendered bullet so a +mechanical commit subject such as `recover Codex env sessions` becomes +`Recover Codex env sessions`. This is only a safety net; release-worthy wording +should still be written as a clear sentence in the commit body. + The canonical npm package is `agent-note`. The workflow also publishes `@wasabeef/agentnote` from the same built `dist/` as a reserved alias package, but end-user documentation should continue to point to `agent-note`. Release steps: diff --git a/docs/engineering.md b/docs/engineering.md index d35b0af8..726cd57b 100644 --- a/docs/engineering.md +++ b/docs/engineering.md @@ -106,6 +106,7 @@ subject as public copy unless the commit type is intentionally internal. - Do not put release-worthy wording only in a PR title or merge commit. Merge commits, version bumps, and generated bundle sync commits are excluded from release notes. - Avoid vague subjects such as `address review notes`, `sync generated bundle`, `polish docs`, or `fix tests`. Name the visible outcome instead. - Keep multi-commit PRs readable in the generated release note. Review follow-up commits should usually be `Release note: skip` unless they are a separate user-visible change. +- The release generator capitalizes the first character of each bullet as a safety net. Still write natural English yourself; this only fixes mechanical lower-case commit subjects. - A PR title is not the release-note source, but it should still read like the top-level release summary for the PR. If the title would be a bad release bullet, improve it before opening or merging the PR. - Before tagging, run `git-cliff --config .github/cliff.toml --latest --strip header`. If the output reads like an implementation log, rewrite commit subjects/bodies before cutting the release. From 0047bab0ff5080b6f6a0a75d7e27d95f37491bc6 Mon Sep 17 00:00:00 2001 From: wasabeef Date: Tue, 12 May 2026 22:38:34 +0900 Subject: [PATCH 3/3] docs: clarify release note follow-up wording Why CodeRabbit flagged that the phrase Review follow-up commits could be misread as referring to the review process instead of commits that address review feedback. User impact Maintainer guidance now makes the intended release-note skip rule clearer for multi-commit PRs. Verification - git diff --check Release note: skip --- docs/engineering.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/engineering.md b/docs/engineering.md index 726cd57b..e6b0d401 100644 --- a/docs/engineering.md +++ b/docs/engineering.md @@ -105,7 +105,7 @@ subject as public copy unless the commit type is intentionally internal. - If a public-looking commit should be hidden, add `Release note: skip`. - Do not put release-worthy wording only in a PR title or merge commit. Merge commits, version bumps, and generated bundle sync commits are excluded from release notes. - Avoid vague subjects such as `address review notes`, `sync generated bundle`, `polish docs`, or `fix tests`. Name the visible outcome instead. -- Keep multi-commit PRs readable in the generated release note. Review follow-up commits should usually be `Release note: skip` unless they are a separate user-visible change. +- Keep multi-commit PRs readable in the generated release note. Review-fix follow-up commits in a multi-commit PR should usually use `Release note: skip` unless they describe a distinct user-visible change. - The release generator capitalizes the first character of each bullet as a safety net. Still write natural English yourself; this only fixes mechanical lower-case commit subjects. - A PR title is not the release-note source, but it should still read like the top-level release summary for the PR. If the title would be a bad release bullet, improve it before opening or merging the PR. - Before tagging, run `git-cliff --config .github/cliff.toml --latest --strip header`. If the output reads like an implementation log, rewrite commit subjects/bodies before cutting the release.