From 9320d1638a10e790ca7a76ef073a6c3ccf141b77 Mon Sep 17 00:00:00 2001 From: "cmeans-claude-dev[bot]" <272174644+cmeans-claude-dev[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 10:23:03 -0500 Subject: [PATCH 1/2] fix(workflow): insert ### Changed in Keep-a-Changelog order on auto-CHANGELOG (closes #26) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cascades the validated cmeans/mcp-synology PR #63 fix (squash 8a4df0d, merged 2026-04-26 23:24Z) to this repo's .github/workflows/dependabot-changelog.yml. The bug: When `## [Unreleased]` already contained a subsection (e.g., `### Added`) but no `### Changed` block, the auto-CHANGELOG workflow's else-branch inserted the new `### Changed` block at `unreleased_idx + 1` regardless of what subsections already existed. With `### Added` at unreleased_idx + 2, the new `### Changed` landed ABOVE the existing `### Added`, violating Keep-a-Changelog v1.1.0's mandated order: Added → Changed → Deprecated → Removed → Fixed → Security Dormant on this repo until #36 release wave: post-PR #25 cascade the workflow ran on PRs #23 and #24 with both `### Added` and `### Changed` already populated in `## [Unreleased]`, so the if-branch (insert under existing `### Changed`) fired both times — the buggy else-branch never executed. The next time it WOULD fire is post-v0.1.1 release: fresh empty Unreleased section, then a feature PR adds `### Added`, then the next weekly Dependabot Monday bump triggers the workflow's else-branch and produces an out-of-order CHANGELOG. The fix: Walk forward from `## Unreleased` to find either: (a) the first subsection that should sort AFTER `### Changed` per KaC ordering (i.e., `### Deprecated`, `### Removed`, `### Fixed`, `### Security`), or (b) the next `## ` release heading. Insert the new `### Changed` block immediately before whichever comes first. Default insertion point is the end of the Unreleased section (just before the next `## ` heading) when no later-sorting subsections exist. Adaptation preserved from our heading-tolerant variant: the matcher accepts both `## Unreleased` (mcp-synology's form) and `## [Unreleased]` (this repo's Keep-a-Changelog bracketed form). Only the else-branch changes; the if-branch (insert under existing `### Changed`) and the loop guard / idempotency guard / token mint / Dependabot filter are byte-for-byte unchanged. Verification: Reproduced upstream QA's algorithm-extraction smoke test against six KaC layouts on the cascaded fix: A. Empty Unreleased → Changed ✓ B. Added only (the bug case) → Added → Changed ✓ C. Changed already exists → Added → Changed ✓ D. Added + Fixed → Added → Changed → Fixed ✓ E. Fixed only → Changed → Fixed ✓ F. Bracketless heading (## Unreleased) → Added → Changed ✓ All six KaC arrangements produce correctly-ordered subsections. Workflow YAML parses (PyYAML safe_load). The verification gate from the dependabot-pr-hygiene-playbook ("validate on real data before cascading") was met on mcp-synology side via the upstream QA smoke test; live Dependabot validation via @dependabot recreate is belt-and- suspenders that can be exercised on this repo's next weekly Dependabot bump. Per CLAUDE.md: this is a CI/automation fix (not user-visible library behavior), so no operator-impact framing in the CHANGELOG bullet — just the categorization-correctness description. --- .github/workflows/dependabot-changelog.yml | 18 ++++++++++++++---- CHANGELOG.md | 4 ++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/.github/workflows/dependabot-changelog.yml b/.github/workflows/dependabot-changelog.yml index 76e1f58..d23b874 100644 --- a/.github/workflows/dependabot-changelog.yml +++ b/.github/workflows/dependabot-changelog.yml @@ -169,10 +169,20 @@ jobs: insert_at += 1 lines.insert(insert_at, entry) else: - # `### Changed` doesn't exist within Unreleased — create it. - insert_at = unreleased_idx + 1 - if insert_at < end_idx and lines[insert_at].strip() == "": - insert_at += 1 + # `### Changed` doesn't exist within Unreleased — create it + # at the right position per Keep-a-Changelog v1.1.0 ordering: + # Added → Changed → Deprecated → Removed → Fixed → Security. + # Walk forward from `## Unreleased` to find either the first + # subsection that should sort AFTER `### Changed`, or the next + # `## ` release heading; insert immediately before whichever + # comes first. Default insertion point is the end of the + # Unreleased section (just before the next `## ` heading). + after_changed = {"### Deprecated", "### Removed", "### Fixed", "### Security"} + insert_at = end_idx + for j in range(unreleased_idx + 1, end_idx): + if lines[j].strip() in after_changed: + insert_at = j + break block = ["### Changed\n", "\n", entry, "\n"] for k, ln in enumerate(block): lines.insert(insert_at + k, ln) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74b64e1..3b813fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- **`.github/workflows/dependabot-changelog.yml`** subsection-insertion logic now respects Keep-a-Changelog v1.1.0 ordering (Added → Changed → Deprecated → Removed → Fixed → Security). Previously, when `## [Unreleased]` already had `### Added` (or any subsection that sorts after `### Changed`) but no `### Changed` block, the auto-CHANGELOG workflow inserted the new `### Changed` at `unreleased_idx + 1` regardless — producing out-of-order subsections (e.g., `### Changed` above `### Added`). Dormant on this repo until #36 release, would have manifested on the next Dependabot bump after a release with only `### Added` in fresh Unreleased. The fix walks forward from `## Unreleased` to find either the first subsection that should sort AFTER `### Changed`, or the next `## ` release heading, and inserts before whichever comes first. Cascaded from the validated `cmeans/mcp-synology` PR #63 fix (squash 8a4df0d, merged 2026-04-26 23:24Z); upstream QA's algorithm-extraction smoke test against six KaC layouts (empty / Added-only / Changed-already / Added+Fixed / Fixed-only / bracketless) was reproduced locally on the cascaded fix — all six pass. Closes #26. + ## [0.1.2] - 2026-04-27 ### Fixed From 837f5754719f365348a33114d3a2bcd264dff46e Mon Sep 17 00:00:00 2001 From: "cmeans-claude-dev[bot]" <272174644+cmeans-claude-dev[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 21:13:48 -0500 Subject: [PATCH 2/2] =?UTF-8?q?docs(changelog):=20fix=20dormancy=20timelin?= =?UTF-8?q?e=20=E2=80=94=20"#36=20release"=20=E2=86=92=20"the=20v0.1.1=20r?= =?UTF-8?q?elease"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QA round 1 finding: the CHANGELOG bullet conflated PR #36 (the stale_threshold_days warning fix that landed during the v0.1.1 pre-release cycle) with a release version. PR #36 is not a release — v0.1.1 is. Future readers couldn't map "#36 release" to a release tag without spelunking. PR body's narrative already says "v0.1.1 ship" correctly; only the CHANGELOG bullet was off. CHANGELOG-only edit. No workflow change, no test change. Verified at HEAD: pytest 71/71, ruff clean, mypy clean. Co-Authored-By: Claude Opus 4.7 (1M context) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b813fc..26e9309 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- **`.github/workflows/dependabot-changelog.yml`** subsection-insertion logic now respects Keep-a-Changelog v1.1.0 ordering (Added → Changed → Deprecated → Removed → Fixed → Security). Previously, when `## [Unreleased]` already had `### Added` (or any subsection that sorts after `### Changed`) but no `### Changed` block, the auto-CHANGELOG workflow inserted the new `### Changed` at `unreleased_idx + 1` regardless — producing out-of-order subsections (e.g., `### Changed` above `### Added`). Dormant on this repo until #36 release, would have manifested on the next Dependabot bump after a release with only `### Added` in fresh Unreleased. The fix walks forward from `## Unreleased` to find either the first subsection that should sort AFTER `### Changed`, or the next `## ` release heading, and inserts before whichever comes first. Cascaded from the validated `cmeans/mcp-synology` PR #63 fix (squash 8a4df0d, merged 2026-04-26 23:24Z); upstream QA's algorithm-extraction smoke test against six KaC layouts (empty / Added-only / Changed-already / Added+Fixed / Fixed-only / bracketless) was reproduced locally on the cascaded fix — all six pass. Closes #26. +- **`.github/workflows/dependabot-changelog.yml`** subsection-insertion logic now respects Keep-a-Changelog v1.1.0 ordering (Added → Changed → Deprecated → Removed → Fixed → Security). Previously, when `## [Unreleased]` already had `### Added` (or any subsection that sorts after `### Changed`) but no `### Changed` block, the auto-CHANGELOG workflow inserted the new `### Changed` at `unreleased_idx + 1` regardless — producing out-of-order subsections (e.g., `### Changed` above `### Added`). Dormant on this repo until the v0.1.1 release, would have manifested on the next Dependabot bump after a release with only `### Added` in fresh Unreleased. The fix walks forward from `## Unreleased` to find either the first subsection that should sort AFTER `### Changed`, or the next `## ` release heading, and inserts before whichever comes first. Cascaded from the validated `cmeans/mcp-synology` PR #63 fix (squash 8a4df0d, merged 2026-04-26 23:24Z); upstream QA's algorithm-extraction smoke test against six KaC layouts (empty / Added-only / Changed-already / Added+Fixed / Fixed-only / bracketless) was reproduced locally on the cascaded fix — all six pass. Closes #26. ## [0.1.2] - 2026-04-27