Skip to content

fix(release): read sync notes edits under the changelog key - #761

Merged
goosewobbler merged 7 commits into
mainfrom
fix/656-sync-notes-region-keys
Oct 24, 2026
Merged

goosewobbler merged 7 commits into
mainfrom
fix/656-sync-notes-region-keys

Conversation

@goosewobbler

@goosewobbler goosewobbler commented Oct 23, 2026 •

Copy link
Copy Markdown
Owner

Summary

In a sync release without version.mainPackage, the notes region is rendered under monorepo, but updates and publish read it back by publishable package name. Edits were dropped and the LLM regenerated every time.

Both paths now use the changelog packageNames (falling back to publishable names when a manifest has no changelogs). A sync edit survives standing-pr update and is what publish sends as the GitHub Release body.

The draft-then-dispatch flow (release --draft / --from-draft) had the same mismatch. extractNotesRegions now takes the version output and works out the keys itself, so no caller can pass a different list. The manifest schema now validates changelogs with the publish package's VersionPackageChangelogSchema (now exported), so a bad manifest is rejected before anything is tagged or published, instead of failing in the GitHub-release step after npm publish. parseManifest returns the validated input rather than zod's copy, so field order survives the round-trip, which the draft plan comparison relies on. Region checks use Object.hasOwn instead of in. Notes keys come only from the changelogs; the fallback to package names served only test fixtures.

In the draft flow, a region that still holds exactly what the draft rendered counts as unedited, so the full drafted notes (stored in the manifest) publish instead of the region's truncated render.

Known consequence for sync releases with release:preview-notes: the single region now counts as an edit, like package regions already did. So notes seeded once stay frozen, notes over 8000 characters publish truncated, and later updates skip the LLM, which also leaves CHANGELOG.md uncategorized (#789). Telling a seed from an edit needs machine state; #782 tracks that, and docs/standing-pr-body.md now mentions the cap.

Fixes #656

Made with Cursor

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge.

Summary

Fixes how standing PRs read edited release notes for sync releases.

  • Sync release notes edits stay with their changelog key.

No actionable issues found. Review was based on code inspection; tests were not run.

Reviews (1) · Last reviewed commit: "fix(release): read sync notes edits unde..." · Reviewed by Greptile

Co-authored-by: Cursor <cursoragent@cursor.com>
@goosewobbler

Copy link
Copy Markdown
Owner Author

@greptile review

@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Standing release PR: #730 · v0.42.1 queued (4 packages) · open 7h 32m · ✅ ready to merge

Release Preview — v0.42.0 → v0.42.1

Note: Labels on this PR are advisory in standing-pr mode. Bumps come from conventional commits in the standing PR; override by editing labels on the standing PR itself. Add release:immediate to bypass the standing PR and release this PR directly.

These changes will be added to the release PR (#730) when merged:

Changelog

monorepo 0.42.0 → 0.42.1

Fixed

  • publish full drafted notes from an untouched truncated draft region (release)
  • drop the truncation heuristic and keep manifest field order (release)
  • validate manifest changelog entries and keep truncated regions out of edits (release)
  • reject a manifest without changelogs before publishing (release)
  • read sync draft edits by notes key and tolerate missing changelogs (release)
  • read sync notes edits under the changelog key (release)

All packages → 0.42.1 (sync versioning)

  • @releasekit/version
  • @releasekit/notes
  • @releasekit/publish
  • @releasekit/release

After merge — predicted release

No version escalation — this PR's changes will be included in the queued release without affecting the projected versions.

Package Standing PR This PR After merge
monorepo 0.42.1 0.42.1 0.42.1

Updated automatically by ReleaseKit

… changelogs

The draft-then-dispatch flow had the same key mismatch as the standing
PR. The draft issue renders its notes region under the changelog key
(`monorepo` for a sync release without mainPackage), but publishFromDraft
read it back by package names. A sync draft edit was dropped, and a
"markers may have been removed" warning fired on every sync draft.

The key helper now lives with the notes region code and serves both
flows. It also tolerates a manifest without changelogs: the manifest is
parsed back from a PR or issue body, its schema doesn't check
changelogs, and a missing list used to crash the publish.

Region checks use Object.hasOwn rather than `in`. The sync test fixtures
use a shared v1.2.3 tag, as a real sync release does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The previous commit let notes keying tolerate a missing changelogs list,
which made things worse. The GitHub-release stage also reads changelogs,
and it runs after npm publish and the tag push, so a bad manifest failed
halfway through the release instead of up front. The manifest schema
now validates changelogs, so both the standing-PR publish and the draft
dispatch reject such a manifest before tagging or publishing anything.
Every manifest releasekit writes includes changelogs.

extractNotesRegions now derives the keys from the version output
itself. Callers can no longer pass a different key list, which is how
the sync mismatch arose.

The sync publish test asserts the exact notes map, so a second
package-keyed entry (the original failure shape) would fail it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…regions out of edits

The manifest schema checked only changelogs[].packageName, so a
changelog without entries still passed and failed after npm publish,
when the GitHub-release step formats it. It now validates version and
entries as well.

Validating those fields reorders each parsed changelog's keys, and the
draft dispatch compared plans with a key-order-sensitive JSON string, so
every real draft would have read as drifted. The plan fingerprint now
sorts object keys.

A notes region still ending in the truncation note is releasekit's own
cut-down seed, not a human edit, so it no longer overrides the full
regenerated notes. Without this, a sync release over 8000 characters
published notes ending in "…(truncated)".

Notes keys now come only from the changelogs, which every real run
produces and the schema requires; the fallback to package names served
only test fixtures, which now carry real changelogs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
github-actions Bot and others added 2 commits October 24, 2026 02:32
…rder

The previous commit treated a notes region ending in the truncation
note as unedited. That inferred machine state from the human-editable
prose, against the marker rule in AGENTS.md. It also discarded real
edits that kept the trailing note, threw away hand-written notes over
the cap once re-rendered, re-ran the LLM on every update for oversized
notes, and made the draft flow warn falsely. Reverted. Telling a seed
from an edit needs machine state, which #782 tracks; the docs now say
notes over 8000 characters are cut and the cut text publishes unless
edited.

parseManifest now returns the validated input rather than zod's copy,
so field order survives the round-trip for every consumer. The draft
plan fingerprint no longer needs to sort keys, so that change is
reverted too.

The manifest's changelogs are validated with the publish package's
full VersionPackageChangelogSchema, now exported, instead of a partial
copy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolves the export conflict in packages/publish/src/index.ts by keeping
both pipelineErrorEnvelope (from #760) and VersionPackageChangelogSchema.
…draft region

A sync draft's single notes region is now read back, so a draft whose
notes exceed the 8000-character region cap published the truncated
render, although the manifest holds the full drafted text. A region
that still holds exactly what the draft rendered is now treated as
unedited, so the full drafted notes win; a changed region still ships
as edited. The check compares the body with the manifest's stored
notes, not the prose.

The standing-PR body docs now say edits are capped too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@goosewobbler
goosewobbler merged commit 39ffbe2 into main Oct 24, 2026
32 checks passed
@goosewobbler
goosewobbler deleted the fix/656-sync-notes-region-keys branch October 24, 2026 02:10
goosewobbler pushed a commit that referenced this pull request Oct 24, 2026
#761 exported VersionPackageChangelogSchema from @releasekit/publish so
the standing-PR manifest schema could use it. This branch moves that
schema to @releasekit/core/version-output-schema, so release imports it
from there and publish no longer re-exports it. A publish re-export
would leave publish's bundled types pointing at the core subpath, which
isn't one of its dependencies.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Standing PR: edits to the release-notes region are discarded in sync releases without version.mainPackage

1 participant