OpenClaw Changelog Update
Use this for release changelog rewrites and GitHub release-note source text.
This is mandatory before every beta, beta rerun, stable release, or stable
rerun. Use it with release-openclaw-maintainer; this skill owns changelog
content, ordering, grouping, and attribution discipline.
Goal
Rebuild the target CHANGELOG.md version section from a complete, generated
history manifest, not stale draft notes. Produce grouped user-facing release
notes sorted by user interest while preserving every relevant issue/PR ref and
every human Thanks @... attribution.
Inputs
- Target base version:
YYYY.M.PATCH, without beta suffix. - Base tag: last reachable shipped release tag, usually the previous stable or the previous beta train requested by the operator.
- Target ref: exact branch/SHA being released.
Workflow
-
Start on
mainbefore branching when possible:git fetch --tags origingit pull --ff-only- confirm clean
git status -sb
-
Audit history, including direct commits:
git log --first-parent --date=iso-strict --pretty=format:'%h%x09%ad%x09%s' <base-tag>..<target-ref>git log --first-parent --grep='(#' --date=short --pretty=format:'%h%x09%ad%x09%s' <base-tag>..<target-ref>- also inspect
--since='24 hours ago'when main moved during the release.
-
Generate the complete contribution record and editorial manifest before writing grouped prose:
node .agents/skills/openclaw-changelog-update/scripts/verify-release-notes.mjs \ --base <base-tag> \ --target <target-ref> \ --version <YYYY.M.PATCH> \ --manifest /tmp/openclaw-release-<YYYY.M.PATCH>.json \ --write-ledger- the manifest is the required input to the rewrite, not an after-the-fact audit; it contains every referenced PR, eligible contributor credit, inline issue context, every direct commit, and an editorial-eligibility classification for PRs and direct commits
- for a historical backfill, add
--seed-ref <pre-backfill-ref>once so contribution records from the prior changelog are retained even when an older merged commit omitted its PR number; the verifier excludes records for work reverted after the base tag, including beta work reverted before the stable release - source PR discovery combines merged GitHub commit associations with merged PR references explicitly present in active commit subjects/bodies so cherry-picks and squash commits remain accounted for. Resolve every association page and exclude PRs merged after the target release commit
- read the manifest before editing
### Highlights,### Changes, or### Fixes; do not carry old grouped prose forward without re-auditing it - inspect linked PRs/issues or diffs for ambiguous commits. Direct commits are editorial input, not public ledger rows; infer material user outcomes from subject, body, touched files, tests, and nearby commits
-
Rewrite one stable-base section only:
- use
## YYYY.M.PATCH - do not create beta-specific headings
- do not leave a stale
## Unreleasedsection above the target release - if
Unreleasedcontains release-bound notes, fold them into the target section instead of deleting them
- use
-
Section shape:
### Highlights: 5-8 bullets, broad user wins first- include only a clear user-visible capability or workflow unlock, a material reliability/safety fix, a broad cross-surface improvement, or a release-defining integration/compatibility milestone
- every highlight must say what changed for a user in one sentence; use one user story per bullet and group its supporting PRs
- exclude tests, CI, refactors, docs, catalog churn, and implementation detail unless the outcome is a material install/update, data-safety, or widely visible user improvement
### Changes: new capabilities and behavior changes### Fixes: user-facing fixes first, grouped by impact and surface- group related changes/fixes by surface and user impact; avoid one bullet per tiny commit when several commits tell one user-facing story
### Complete contribution record: generated PR-first record after the grouped prose; it is the exhaustive accounting surface, not a second release summary
-
Preserve attribution:
- keep
#issue,(#PR),Fixes #..., andThanks @... - every human-authored merged PR represented by a user-facing entry needs
its PR ref and
Thanks @author, even when the PR had no linked issue - every human issue reporter for a
Fixes #...or referenced bug issue represented by a user-facing entry needsThanks @reporterunless the same handle is already thanked in that bullet - every human
Co-authored-bycontributor on represented user-facing work needsThanks @handlewhen a GitHub handle is known - when grouping multiple PRs/issues in one bullet, include every relevant PR/issue ref and every human contributor handle in that same bullet
- multiple
Thanks @...handles in one bullet are expected; do not drop or collapse contributor credit just because the note is grouped - if one grouped bullet covers both direct commits and PRs, keep all PR refs and thanks, plus any issue refs and human credit from the direct work
- issues remain normal inline
#NNNreferences. Do not add a separate linked-issues inventory. The generated PR record keeps source issues inline asRelated #NNNon the PR that shipped them - when backfilling an older linked-issues inventory, preserve reporter credit inline for every GitHub-confirmed closing PR relationship. Do not infer a PR relationship from a generic cross-reference event, invent an unrelated PR link for a standalone report, or recreate the retired inventory
- the complete contribution record lists every merged source PR exactly once
as
**PR #NNN**; source PRs include GitHub commit associations and merged PR references explicitly present in active commit subjects/bodies. It preserves author/co-author credit and any issue references in the original title - direct commits remain in the manifest with GitHub-resolved author,
co-author, issue, and editorial-eligibility data. They inform grouped
prose but are never rendered as a public
#### Direct commitsdump. Add direct-commit credit to a grouped bullet only when it shares an explicit closing issue reference or at least two distinctive subject terms - the verifier rejects
docs,test,refactor,ci,build,chore, andstylePRs in Highlights, Changes, or Fixes. Keep those internal contributions in the complete PR record, but do not give them editorial release-note space - classify internal-only work from conventional prefixes and clear title
signals such as
QA,test,docs,refactor,lint, orCI; an untyped title is not automatically editorial - do not add GHSA references, advisory IDs, or security advisory slugs to changelog entries or GitHub release-note text unless explicitly requested
- never thank bots,
@claude,@openclaw,@clawsweeper, or@steipete - do not use GitHub's release contributor count as the source of truth; the changelog must carry the complete human credit set itself
- keep
-
Sorting preference:
- security/data-loss and content-boundary fixes
- transcript/replay/reply delivery correctness
- channels and mobile integrations
- providers/Codex/local model reliability
- install/update/release path reliability
- performance and observability
- docs and contributor-only/internal details last or omitted
-
Keep bullets single-line unless existing file style forces otherwise. Avoid internal release-process noise unless it changes user install/update safety.
-
Check release-note side conditions:
- inspect
src/plugins/compat/registry.ts - inspect
src/commands/doctor/shared/deprecation-compat.ts - if any compatibility
removeAfteris on/before release date, resolve it or explicitly record the blocker before shipping
- inspect
-
Validate and ship:
- after the manifest-driven rewrite, regenerate and verify the complete
contribution record before committing:
node .agents/skills/openclaw-changelog-update/scripts/verify-release-notes.mjs \ --base <base-tag> \ --target <target-ref> \ --version <YYYY.M.PATCH> \ --manifest /tmp/openclaw-release-<YYYY.M.PATCH>.json \ --write-ledger - the command fails when any
#NNNreference in release history or the rendered release section cannot resolve, when reverted work is presented as shipped, when a source PR is absent from the contribution record, when direct commits are rendered as a public record dump, when non-editorial PRs appear in grouped prose, or when an eligible PR author or known co-author is missing from that PR'sThanks @...credit - when grouped prose names a PR, that same bullet must retain every contributor and linked-reporter credit from its generated PR record
- unqualified
#NNNreferences resolve againstopenclaw/openclaw; cross-repository references such asopenclaw/imsg#141remain literal text and must not be rewritten as local issue links - after the GitHub release or prerelease is published, verify every matching
release page against the same source section:
node .agents/skills/openclaw-changelog-update/scripts/verify-release-notes.mjs \ --base <base-tag> \ --target <target-ref> \ --version <YYYY.M.PATCH> \ --release-tag v<YYYY.M.PATCH> \ --check-github - add one
--release-tagfor every beta and stable page in the train; a### Release verificationtail is permitted, but any other body drift fails the check; the GitHub body must begin with the complete## YYYY.M.PATCHchangelog section, including its heading - GitHub release bodies are limited to 125,000 characters. If the complete source section plus an existing verification tail exceeds that limit, keep the source section intact and omit the tail; never truncate the contribution record
git diff --check- for docs/changelog-only changes, no broad tests are required
- commit with
scripts/committer "docs(changelog): refresh YYYY.M.PATCH notes" CHANGELOG.md - push, pull/rebase if needed, then branch/rebase release from latest
main
Quota / API Outage Rule
If GitHub API quota is exhausted, do not idle. Continue work that does not need GitHub API:
- local changelog rewrite and release-note extraction
- local pretag checks and package/build sanity
- git push/tag checks over git protocol
- npm registry
npm viewchecks - exact workflow-dispatch command preparation
Only GitHub Release creation, workflow dispatch, run polling, artifact download, and issue/PR mutation need API quota.