Rules and workflows for updating docs/CHANGELOG.md, including version grouping, consolidation, and commit-entry attribution.
Use the helper script to generate a draft section from commits since the last tag, grouped into changelog categories, with similar commits consolidated by default (see notes below).
Script path:
.ai/skills/update-changelog/scripts/update-changelog.ps1
Preview only (prints generated markdown):
powershell -NoProfile -ExecutionPolicy Bypass -File .ai/skills/update-changelog/scripts/update-changelog.ps1
Generate draft from an explicit tag/version and save to a file:
powershell -NoProfile -ExecutionPolicy Bypass -File .ai/skills/update-changelog/scripts/update-changelog.ps1 -FromTag v0.18.9 -Version 0.19.0 -OutputPath build/changelog-draft.md
Apply directly to docs/CHANGELOG.md:
powershell -NoProfile -ExecutionPolicy Bypass -File .ai/skills/update-changelog/scripts/update-changelog.ps1 -FromTag v0.18.9 -Version 0.19.0 -Apply
Per-commit lines only (disables automatic similarity merge):
powershell -NoProfile -ExecutionPolicy Bypass -File .ai/skills/update-changelog/scripts/update-changelog.ps1 -FromTag v0.18.9 -Version 0.19.0 -NoConsolidation
Notes:
-Version defaults to root Directory.Build.props.-FromTag defaults to git describe --tags --abbrev=0.## vX.Y.Z (replaces existing section for that version or inserts after ## Unreleased).Get-ConsolidationBucket in scripts/update-changelog.ps1 merges commits that match the same similarity bucket (for example: ShareX.ImageEditor in the subject, 2026-... blog draft series, XIP/IEIP docs, Linux install/capture documentation, IEIP/XIP proposal .md create/update under Changed, multipart / S3 multipart). Extend that function when new repetitive patterns appear.#PR, @user) before publishing.Directory.Build.props version.Directory.Build.props history to identify those boundaries.Feature: ... (originally v0.8.1).298457a under v0.11.0."(#PR_NUMBER, @username)(#77, @Hexeption)McoreD) from having explicit attribution unless they contain significant unique work not covered by other commits. The focus is on crediting other users.Group changes within each version using standard categories:
The helper script maps infrastructure and chore-style commit types into Build unless the commit subject carries a clearer component/category signal.
CRITICAL: Consolidate related commits into single entries to keep the changelog concise and readable.
The automation script does this by default; agents should still edit the draft for narrative quality and any merges the heuristics miss.
Before (verbose):
- **Media Explorer**: Add `IUploaderExplorer` interface `(9deedf9)`
- **Media Explorer**: Implement S3 file browser `(9deedf9)`
- **Media Explorer**: Implement Imgur album browser `(9deedf9)`
- **Media Explorer**: Add navigation, breadcrumbs, search, filter `(9deedf9)`
- **Media Explorer**: Add bandwidth savings banner `(e374160)`
After (consolidated):
- **Media Explorer**: Implement provider file browsing with S3 and Imgur support, including navigation, search, filtering, and CDN thumbnail optimization `(9deedf9, e374160)`
Before (mobile features):
- **Mobile**: Add adaptive mobile theming infrastructure `(4b79ddb)`
- **Mobile**: Refactor mobile views for adaptive native styling `(a7cfb22)`
- **Mobile**: Align mobile heads with native theming defaults `(1e5f9eb)`
- **Mobile**: Complete sprint 5 mobile theming polish and docs `(30bbe98)`
- **Mobile**: Add mobile upload queue and picker `(68d97d9)`
- **Mobile**: Add mobile upload history screens `(52d6ad2)`
After (consolidated):
- **Mobile**: Add adaptive theming infrastructure with native styling polish `(4b79ddb, a7cfb22, 1e5f9eb, 30bbe98)`
- **Mobile**: Add upload queue, picker, and history screens `(68d97d9, 52d6ad2)`
Before (fixes):
- **Scrolling Capture**: Always auto-scroll to top `(1fa45f2)`
- **Scrolling Capture**: Apply workflow settings and refresh hotkeys `(971219c)`
- **Scrolling Capture**: Use current scroll position for detection `(8ac2c8b)`
After (consolidated):
- **Scrolling Capture**: Improve auto-scroll behavior and workflow settings integration `(1fa45f2, 971219c, 8ac2c8b)`
Follow the Keep a Changelog format with Semantic Versioning.
## vX.Y.Z
### Features
- **Component**: Description `(short-hash)`
- **Component**: Description `(short-hash, short-hash)`
### Fixes
- Description `(short-hash)`
Choose the Changelog Mode
Directory.Build.props version as the target heading.Identify the Range
-FromTag to use git describe --tags --abbrev=0.-FromTag v0.21.2 -Version 0.22.0.v0.PREV_STABLE..v0.LATEST_STABLE.Fallback tag listing:
git tag -l --sort=-version:refname | Select-Object -First 10
Check Target Version
Read the root Directory.Build.props <Version> property unless the user explicitly provided a historical target version.
Consolidate Version Headings
## vX.Y.Z heading for the target version.Categorize Commits
Consolidate Related Entries
Format and Verify
Fix Double-Encoding Mojibake
After any write to docs/CHANGELOG.md, scan for corrupted UTF-8 round-trip artifacts and replace them with their correct Unicode equivalents. This occurs when UTF-8 bytes are decoded and re-encoded by the wrong tool chain. Apply this as a final step every time:
$c = [System.IO.File]::ReadAllText('docs/CHANGELOG.md', [System.Text.Encoding]::UTF8)
# Fix mojibake involving the section-sign byte pair and normalize the output.
$c = $c -replace [char]0x00C2 + [char]0x00A7, [char]0x2014
# Normalize any remaining section-sign corruption.
$c = $c -replace [char]0x00C2 + [char]0x00A7, [char]0x00A7
# Collapse 3+ blank lines
$c = $c -replace "\r?\n", "`n"
$c = $c -replace "`n{3,}", "`n`n"
$c = $c -replace "`n", "`r`n"
[System.IO.File]::WriteAllText('docs/CHANGELOG.md', $c, [System.Text.Encoding]::UTF8)
Common victims to watch for:
—, U+2014)§, U+00A7)ó (U+00F3)# Check latest tags with version-aware sorting.
$tags = git tag -l --sort=-version:refname | Select-Object -First 10
# Check current version.
$version = Select-String -Path "Directory.Build.props" -Pattern '<Version>(.*)</Version>' | ForEach-Object { $_.Matches.Groups[1].Value }
# Preview default current-unreleased changelog section.
powershell -NoProfile -ExecutionPolicy Bypass -File .ai/skills/update-changelog/scripts/update-changelog.ps1
# Apply an explicit current-unreleased range.
powershell -NoProfile -ExecutionPolicy Bypass -File .ai/skills/update-changelog/scripts/update-changelog.ps1 -FromTag v0.21.2 -Version $version -Apply
Why: exact-match replacement tools can fail when CHANGELOG.md contains multi-byte UTF-8 sequences that were double-encoded during a tool round trip. Use PowerShell [System.IO.File] plus Regex instead; it reads raw bytes and avoids exact-literal matching against corrupted text.
Pattern (replace all prerelease sections between two stable headings with new consolidated content):
$cl = 'docs/CHANGELOG.md'
$c = [System.IO.File]::ReadAllText($cl, [System.Text.Encoding]::UTF8)
$newSection = @'
## v0.X.Y
### Features
- ...
### Fixes
- ...
'@
# (?s) = dotall (. matches newlines); match from first prerelease heading up to (but not including) the previous stable heading
$c = [System.Text.RegularExpressions.Regex]::Replace(
$c,
'(?s)## v0\.FIRST_PRERELEASE.*?(?=## v0\.PREV_STABLE)',
$newSection
)
# Normalize the double-encoded section-sign artifact (C2 A7 → A7).
$c = $c -replace [char]0x00C2 + [char]0x00A7, [char]0x00A7
# Collapse 3+ consecutive blank lines down to 2
$c = $c -replace "\r\n", "`n"
$c = $c -replace "`n{3,}", "`n`n"
$c = $c -replace "`n", "`r`n" # restore CRLF if the repo uses it
[System.IO.File]::WriteAllText($cl, $c, [System.Text.Encoding]::UTF8)
Key points:
(?s) makes . match newlines so the pattern spans the whole block.(?=## v0\.PREV_STABLE) stops the match at the previous stable heading; it is not consumed.[char]0x00C2 + [char]0x00A7 to [char]0x00A7) should always run after a regex write to guard against double-encoding.\n{3,} to \n\n) prevents the file from accumulating excess whitespace after sections are removed.