fix(changelog): every release since 0.14.31 writes two sections for one version - #1219
Merged
Merged
Conversation
Claiming the duplicate-section regression. Diagnosis in the PR body: the release commit emits both an auto-generated section and a promoted-highlights section for the same version, with two different date sources (local vs UTC).
There was a problem hiding this comment.
Copilot wasn't able to review any files in this pull request.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
… own diagnosis The CHANGELOG is a shipped artefact — #815 surfaces it inside the panel and changelog-delta reads it to tell a user what changed under them after an unattended update — so its shape is testable and was not tested. This is the fourth pass over this area (#1197, #1202, #1203) and every prior defect was found by a human reading the file afterwards. WHAT THE GUARD FOUND, beyond the duplicate sections I went looking for: 1. The 0.2.0/0.3.0/0.4.0/0.4.1 pairs are NOT duplicates. They are version-number COLLISIONS holding genuinely different content: `0.4.1 - 06-26` announces graph_set_node_mode, while `0.4.1 - 06-17` announces the Connect button that replaced auto-spawn after the Registry scanner flagged 0.4.0. Two real releases reused one number. Merging them would assert a release that shipped both — the same fabrication #1203 had to undo. They are recorded as fact, with the exemption list asserted EXHAUSTIVE so it cannot rot into a blanket hole. 2. The single ordering break is where that older history block begins. Same treatment. 3. 0.11.84 was a FALSE POSITIVE in my first draft of this guard: its body is the deliberate `_No user-facing changes._`. A release that truthfully reports having nothing to report is correct; the guard demanding a list item was the defect. AND A CORRECTION TO MY OWN CLAIM ON THE PR. I wrote that the generator emits two bodies per release. It cannot: buildEntry produces exactly one `## [ver] - today()` section, and line 375 aborts when the version already exists. The two-section mechanism is upstream in the release PROCESS and I have not located it — recorded as unknown rather than left as a plausible-sounding guess, which is the failure this session has already produced four times in one changelog note. What IS real in the generator: the highlights dedupe is /\(#(\d+)\)/g, which cannot match (comfyui-mcp#1478). So work described upstream-first is never recognised as covered and gets re-listed by its panel PR number. The guard is RED on the three recent pairs by design. It stays red until the cause is found, which is the point of committing it first. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…g in the wrong place DATA. 0.14.31, 0.14.32 and 0.14.33 each carried two headings whose bodies described the SAME work through different identifiers — the panel PR (#1206/#1208/#1211) and the upstream mcp issue (comfyui-mcp#1448/#1467/#1478). Merged into one section per version, citing both ids, keeping the more specific wording. Safe precisely because the two bodies were the same change; the 0.2.0-0.4.1 pairs are NOT and are left alone. web/changelog.json regenerated, since the panel reads that rather than the markdown. DATE. today() read LOCAL calendar fields while hand-written notes used UTC, which is why the pairs sat a day apart: the release commits were authored near 23:00-0600. Now one source, UTC, via toISOString — a changelog is read across timezones and by changelog-delta, so "the day it shipped" has to mean one thing. AND I REMOVED MY OWN FIX, because it could not fire. I had added a post-write duplicate-heading assertion here. Testing it showed the pre-write check returns first in the only ordering where a duplicate exists at write time — and in the ordering that actually caused this, the hand-written section was added AFTER the script exited, so at write time there was exactly one heading. It was dead code shaped like a guard, which this session has already established reads as coverage and is worse than nothing. The reasoning is left in place so it does not get re-added. A script cannot defend against an edit made after it exits. The check that DOES catch this is browser_tests/unit/changelog-integrity.test.mjs (5f66e35), which asserts the committed file's shape and so runs on the release PR regardless of which step wrote the second heading. The pre-write "nothing to do" message now also explains the failure mode it can mask: notes under a pre-numbered heading ship WITHOUT the auto-generated commit body, because that branch returns before writing it. Also widened then REVERTED the highlights dedupe: matching (comfyui-mcp#N) as well as (#N) cannot work, because the two are different numbers in different namespaces, and it would let an upstream issue number silently suppress an unrelated panel PR's commit. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Codex P2. The comment explaining why cross-namespace dedupe was reverted said the duplication was "prevented by the post-write assertion at the bottom of this file" — and that assertion was removed in the same change, as unreachable. So the comment claimed a protection that does not exist, in the file whose entire subject is a guard that could not see what it claimed to. Stated accurately now: a highlight citing comfyui-mcp#1478 and a commit carrying panel PR #1211 for the same change will BOTH be listed, as two bullets in one section. changelog-integrity.test.mjs catches duplicate version HEADINGS; it does not compare bullet text, so that redundancy is unguarded and only a human reading the notes will catch it. Smaller than the duplicate sections this issue was about — one release saying a thing twice, rather than two releases — and closing it needs an identifier map the repo does not have. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
artokun
marked this pull request as ready for review
August 14, 2026 07:01
artokun
added a commit
that referenced
this pull request
Aug 14, 2026
Ships two fixes, and is the first release cut through the repaired changelog path. - #1218 / #1172 — panel_refresh_nodes no longer answers `refreshed: true` while a newly added CheckpointLoaderSimple keeps an empty ckpt_name list. The reapply sweep now rebuilds combo option arrays from the /object_info payload it just fetched instead of relying on a frontend call whose per-node effect the panel never observed, and an authoritative list that comes back EMPTY is disclosed rather than hidden behind a structural "refreshed" verdict. - #1219 — every release since 0.14.31 had written TWO changelog sections for one version. Cause: notes hand-written under a pre-numbered heading, then the generator adding its own; the hand edit landed after the script exited, so no in-script guard could see it. The three duplicated releases are merged (losslessly — verified entry by entry against the original release commits), `today()` now has one UTC source instead of local calendar fields, and a committed test asserts the shipped file's shape so the next occurrence fails on the release PR rather than months later. VERIFIED BY BEING THE FIRST USER OF THE FIX: notes went under [Unreleased], the generator promoted them into exactly ONE dated section, and changelog-integrity.test.mjs passes. Under the old path this commit would have been the fourth duplicate pair. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Every release since 0.14.31 has written two
## [x.y.z]sections intoCHANGELOG.md. Found while checking whether #1172 was releasable; no issue is filed yet — say the word and I'll open one.The evidence
git log -Sconfirms both sections of a given version arrive in the same release commit (0.14.33's pair inf0532584, PR #1214). This is not two runs racing; one release step emits both.Two distinct defects, and the dates prove it
f0532584is authoredThu Aug 13 23:18:14 2026 -0600— which is 2026-08-14 in UTC. So:scripts/gen-changelog.mjs's own header states the contract: promote the hand-written[Unreleased]highlights verbatim, then append the commits those highlights did not already mention, deduped by PR number — into a single section. What ships instead is the auto-generated body in one section and the promoted highlights in another. The existing guard (if (md.includes("## [" + version + "]"))→ "nothing to do") only defends against a second invocation; it cannot see a second section produced within one.Why it starts at 0.14.31
6aa29670 fix(1191): the changelog generator cannot see this repo's own release commits (#1197)taught the generator to read this repo's own release commits. That is what introduced the second body. The dedupe is by PR number, and the two bodies describe the same work through different identifiers —#1211(panel PR) versuscomfyui-mcp#1478(upstream issue) — so nothing matches and neither body suppresses the other.Why this matters beyond tidiness
CHANGELOG.mdin the panel, so users read this.Work in progress
#Nandcomfyui-mcp#N)🤖 Generated with Claude Code
Correction: the diagnosis above is partly wrong
gen-changelog.mjscannot emit two sections.buildEntryproduces exactly one## [ver] - today(), and line 375 aborts with "already has a [version] section — nothing to do" when the version is present. My claim that it emits an auto body and a highlights body as separate sections does not survive reading the code.The two-section mechanism is upstream in the release process, and I have not found it. Recorded as unknown rather than left as a plausible guess — this session has already produced four rejected versions of one changelog sentence for exactly that habit.
What is real in the generator: the highlights dedupe is
/\(#(\d+)\)/g, which cannot match(comfyui-mcp#1478). Work described upstream-first is never recognised as covered, so it gets re-listed under its panel PR number. That explains why the two bodies never suppress each other — but not why there are two bodies.What the guard found that I wasn't looking for
Committed in
5f66e35f—browser_tests/unit/changelog-integrity.test.mjs. It is deliberately red on the three recent pairs and stays red until the cause is found.The 0.2.0–0.4.1 pairs are not duplicates at all. They are version-number collisions holding different content:
0.4.1 - 2026-06-26→graph_set_node_mode0.4.1 - 2026-06-17→ the Connect button replacing auto-spawn, after the Registry scanner flagged 0.4.0Two real releases reused one number, early on. Merging them would fabricate a release that shipped both — precisely what #1203 had to undo. They are exempted as documented fact, and the exemption list is asserted exhaustive, so a future repair cannot leave a permanent hole for the next regression to hide in. The lone ordering break (
0.1.3 precedes 0.4.1) is where that older history block begins, and gets the same treatment.0.11.84was a false positive in my own first draft of the guard: its body is the deliberate_No user-facing changes._. A release that truthfully reports having nothing to report is correct; the assertion demanding a list item was the defect.Revised remaining work
gen-changelog.mjscomfyui-mcp#Nas well as#Ntoday()is local; the 08-14 headings are UTC)The mechanism, located
git log -Sacross all refs shows that no commit ever introduced only one variant. Both sections for a version always appear together, in a single release commit (496cf404pre-squash,f0532584after). So the release step produced both in one working-tree state — this is not two runs, not a merge, and not the generator looping.The identifiers say where the second one comes from. The
08-14bodies citecomfyui-mcp#1448,#1467,#1478— and the repo contains worktrees namedwt-1448b,wt-1467io,wt-1478, one per upstream issue. Each release was cut on a branch dedicated to fixing an upstreamcomfyui-mcpissue, where the release notes were written as a versioned section (## [0.14.33] - 2026-08-14, UTC-dated, citing the upstream issue) rather than under## [Unreleased].gen-changelog.mjsthen ran on that branch and added its own## [0.14.33] - 2026-08-13from the commit log. Its guard —if (md.includes("## [" + version + "]")) → nothing to do— protects the script from running twice. It cannot protect against a hand-written versioned section added after the script runs. Both end up staged into one release commit.That also explains the date split cleanly:
today()is local (getFullYear/getMonth/getDate, line 274-276) so the generator stamped08-13, while the hand-written section used the UTC date — the release commit is authoredAug 13 23:18 -0600, which isAug 14UTC.So the fix is process + guard, not generator logic
## [Unreleased], whichbuildEntrypromotes verbatim into the single dated section. Writing them as a pre-numbered section is what defeats the design./\(#(\d+)\)/gto also matchcomfyui-mcp#N, so upstream-first descriptions register as covered.The committed guard (
5f66e35f) catches the outcome regardless of which of these regresses, which is why it went in first.