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/.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 b3aa2443..0b896316 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -141,6 +141,10 @@ 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. +- **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. - **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..c543aa8e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -141,6 +141,10 @@ 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. +- **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. - **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..75bb0a3a 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -571,6 +571,18 @@ 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 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: @@ -582,8 +594,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..e6b0d401 100644 --- a/docs/engineering.md +++ b/docs/engineering.md @@ -105,6 +105,10 @@ 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-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. Good commit body shape: @@ -125,3 +129,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 +```