Skip to content

fix(workflow): insert ### Changed in Keep-a-Changelog order on auto-CHANGELOG#63

Merged
cmeans-claude-dev[bot] merged 2 commits into
mainfrom
fix/dependabot-changelog-kac-ordering
Apr 26, 2026
Merged

fix(workflow): insert ### Changed in Keep-a-Changelog order on auto-CHANGELOG#63
cmeans-claude-dev[bot] merged 2 commits into
mainfrom
fix/dependabot-changelog-kac-ordering

Conversation

@cmeans-claude-dev
Copy link
Copy Markdown
Contributor

Summary

Closes a dormant subsection-ordering bug in .github/workflows/dependabot-changelog.yml surfaced by claude-qa during review of the cascade PR in cmeans/pypi-winnow-downloads (issue #26 there).

The auto-CHANGELOG composer's inline Python previously inserted a newly-created ### Changed block at unreleased_idx + 1, which placed it ABOVE any existing ### Added (or other earlier-sorting subsection) inside ## Unreleased.

Per Keep a Changelog v1.1.0 the canonical subsection order is: Added → Changed → Deprecated → Removed → Fixed → Security.

Bug manifests when ## Unreleased already contains a non-Changed subsection and the next Dependabot PR creates a fresh ### Changed. Currently dormant on this repo because ## Unreleased happens to have both ### Added and ### Changed. Will manifest after the next release ships and a feature PR adds ### Added to the fresh Unreleased section before any Dependabot bump.

Fix

In the else-branch (the "create ### Changed" path), walk forward from ## Unreleased looking for the first ###-prefixed subsection that should sort AFTER ### Changed (Deprecated, Removed, Fixed, or Security), OR the next ## release heading. Insert immediately before whichever comes first. Default insertion point is the end of the Unreleased section.

The existing-### Changed-found path is unchanged.

Smoke test

Algorithm verified locally against five CHANGELOG arrangements:

Case Input shape Expected ### Changed placement Got it?
A Empty Unreleased (no subsections) ### Changed created at end of Unreleased
B ### Added only (the dormant-bug case) After ### Added, before next release
C ### Changed already exists Entry inserted under existing block ✅ (unchanged path)
D ### Added AND ### Fixed, no Changed Between ### Added and ### Fixed
E ### Fixed only, no Changed Before ### Fixed

Output for case B (the actual bug):

## Unreleased

### Added

- a1

### Changed                              ← correctly inserted AFTER Added
- **Bump <group> group: pkg vX→vY** (#NN)

## 0.5.0

Verification gate

This is a fix to existing inline-Python parsing logic, not new infrastructure. Smoke-tested algorithmically against all five KaC arrangements. The bug is dormant on main's current CHANGELOG.md so the natural-data verification path is "next release + feature PR adds ### Added first + Dependabot bump after" — which won't happen for some time. Algorithm correctness via the smoke test is the working verification.

Cascade

Per the dependabot-pr-hygiene-playbook (awareness c523d239) verification gate, the cascade to cmeans/pypi-winnow-downloads waits for this fix to land here first. After merge, the cascade PR there picks up the same change.

Test plan

  • python -c "import yaml; yaml.safe_load(open('.github/workflows/dependabot-changelog.yml'))" — YAML parses
  • Smoke test — five KaC cases all produce correctly-ordered output (table above)
  • Existing ### Changed-found path is unchanged (case C)
  • CHANGELOG entry under ## Unreleased### Fixed references this PR
  • Issue cmeans/pypi-winnow-downloads#26 referenced in commit body and CHANGELOG
  • After merge: update awareness dependabot-pr-hygiene-playbook (c523d239) to record the fix and remove the dormant-bug warning if any

The auto-CHANGELOG composer's inline Python previously inserted a
newly-created ### Changed block at unreleased_idx + 1, which placed
it above any existing ### Added (or other earlier-sorting
subsection) inside ## Unreleased.

Per Keep a Changelog v1.1.0 the canonical subsection order is:
  Added → Changed → Deprecated → Removed → Fixed → Security

The bug manifests when ## Unreleased already contains a non-Changed
subsection and the next Dependabot PR creates a fresh ### Changed.
Dormant on this repo right now because ## Unreleased has both
subsections; would manifest after the next release ships and a
feature PR adds ### Added to the fresh Unreleased section before
any Dependabot bump.

Fix: in the else-branch (the "create ### Changed" path), walk
forward from ## Unreleased looking for the first ###-prefixed
subsection that should sort AFTER ### Changed (Deprecated, Removed,
Fixed, or Security), OR the next ## release heading. Insert
immediately before whichever comes first. Default insertion point
is the end of the Unreleased section. Existing ### Changed-found
path is unchanged.

Smoke-tested locally against five CHANGELOG arrangements:
- Empty Unreleased (no subsections)
- ### Added only (the dormant-bug case)
- ### Changed already exists (existing path)
- ### Added AND ### Fixed (no Changed)
- ### Fixed only

All five produce correctly KaC-ordered output. Test harness output
preserved in the PR body.

Surfaced by claude-qa during review of the cascade in
cmeans/pypi-winnow-downloads (issue #26 there). The pypi-winnow-downloads
cascade waits for this fix per the playbook's verification gate
(one repo first, validate, then cascade).
@cmeans-claude-dev cmeans-claude-dev Bot added the Ready for QA Dev work complete — QA can begin review label Apr 26, 2026
@github-actions github-actions Bot added the Awaiting CI Dev complete, waiting for CI/Codecov to pass before QA label Apr 26, 2026
@github-actions github-actions Bot added Ready for QA Dev work complete — QA can begin review and removed Ready for QA Dev work complete — QA can begin review Awaiting CI Dev complete, waiting for CI/Codecov to pass before QA labels Apr 26, 2026
@codecov-commenter
Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
Owner

@cmeans cmeans left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@cmeans cmeans added the QA Active QA is actively reviewing; Dev should not push changes label Apr 26, 2026
@github-actions github-actions Bot removed the Ready for QA Dev work complete — QA can begin review label Apr 26, 2026
Copy link
Copy Markdown
Owner

@cmeans cmeans left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QA Round 1 — PR #63

This is a model example of cross-repo review catching what same-repo review missed. The bug existed in #58's workflow shipped on this repo but was dormant — caught during cascade review on cmeans/pypi-winnow-downloads#26 because that repo has a CHANGELOG arrangement (### Added only at the moment) that would trigger it. Good.

Verification on e70ad58

Check Result
python3 yaml.safe_load(...) parses
uv run pytest 499 passed, 94 deselected, 96.04% coverage
Required CI rollup all green (lint, typecheck, test 3.11/3.12/3.13, version-sync, validate-server-json, vdsm)
CHANGELOG entry placement under ### Fixed ✓ correctly categorized
Cross-reference to cmeans/pypi-winnow-downloads#26 present in CHANGELOG entry and PR body ✓
Existing-### Changed-found path unchanged (only the create-new-Changed branch was modified) ✓

Independent smoke test (extending Dev's five cases)

Ran the new algorithm locally against six CHANGELOG arrangements:

Case Input shape (Unreleased section) Resulting ### Changed placement KaC-correct?
A Empty Unreleased At end of Unreleased
B ### Added only (the bug case) Added → Changed
D ### Added + ### Fixed Added → Changed → Fixed
E ### Fixed only Changed → Fixed
G ### Deprecated only (not in Dev's table) Changed → Deprecated
H ### Added + ### Deprecated (not in Dev's table) Added → Changed → Deprecated

All six produce KaC-correct ordering. The two extras (G and H) extend coverage to the Deprecated subsection that Dev's table didn't exercise.

Observations on the algorithm

The after_changed set {"### Deprecated", "### Removed", "### Fixed", "### Security"} is correct per KaC v1.1.0. The default fallthrough (insert_at = end_idx) places new ### Changed at the end of Unreleased when no later-sorting subsection exists, which produces the right result for cases A and B (the trailing position is after ### Added, before next ## heading).

Non-canonical subsection names (e.g., ### Improved) would be treated as before-Changed by virtue of not being in after_changed. This is acceptable because the project rule (per feedback_changelog_categories.md / CLAUDE.md) prohibits non-canonical KaC categories, so this case shouldn't occur in well-formed CHANGELOGs.

Verdict

Ready for QA Signoff. No findings. QA Approved remains the maintainer's call.

Maintainer reminder (already in test plan, post-merge): update awareness dependabot-pr-hygiene-playbook entry (c523d239) to record the fix.

@cmeans
Copy link
Copy Markdown
Owner

cmeans commented Apr 26, 2026

QA audit — round 1

Branch / SHA: `fix/dependabot-changelog-kac-ordering` @ `e70ad58`

Independent smoke test results — extracted the new algorithm from the workflow and ran six KaC arrangements:

```
A. Empty Unreleased → ### Changed at end of Unreleased ✓
B. Added only (bug case) → Added → Changed ✓
D. Added + Fixed → Added → Changed → Fixed ✓
E. Fixed only → Changed → Fixed ✓
G. Deprecated only (extra) → Changed → Deprecated ✓
H. Added + Deprecated (extra) → Added → Changed → Deprecated ✓
```

All six produce KaC-correct order. G and H extend coverage past Dev's table.

Local stack:
```
uv run pytest # 499 passed, 94 deselected, 96.04%
python3 -c "import yaml; yaml.safe_load(open('.github/workflows/dependabot-changelog.yml'))" # parses
```

Outcome: Ready for QA Signoff. No findings. `QA Approved` remains the maintainer's call.

@cmeans cmeans added Ready for QA Signoff QA passed — ready for maintainer final review and merge QA Approved Manual QA testing completed and passed and removed QA Active QA is actively reviewing; Dev should not push changes Ready for QA Signoff QA passed — ready for maintainer final review and merge labels Apr 26, 2026
@cmeans-claude-dev cmeans-claude-dev Bot merged commit 8a4df0d into main Apr 26, 2026
34 checks passed
@cmeans-claude-dev cmeans-claude-dev Bot deleted the fix/dependabot-changelog-kac-ordering branch April 26, 2026 23:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

QA Approved Manual QA testing completed and passed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants