Commit Graph

2 Commits

Author SHA1 Message Date
Colby Mchenry f6fabe9b5a docs(claude): rewrite release section for auto-promote workflow + link-ref on promote (#437)
Two paired updates:

1. **`CLAUDE.md` § Releases** — rewritten to match the actual workflow now
   that #436's auto-promote step lands the entries automatically.

   The old text told Claude to 'Add a new `## [X.Y.Z] - YYYY-MM-DD`
   block at the top of CHANGELOG.md' as the first step. That instruction
   is the exact pattern that caused the v0.9.5 sparse-release-notes
   incident — a hand-added sparse `[X.Y.Z]` block (one early fix
   pre-staged) is what the extractor picked, ignoring everything under
   `[Unreleased]` above it.

   New default: write entries under `## [Unreleased]` during normal
   work. The Release workflow promotes them at release time. The
   formatting rules (sub-section grouping, user-perspective wording,
   issue/PR refs) are preserved. The link-reference rule moves to 'don't
   add it yourself' since `prepare-release.mjs` now appends it.

2. **`scripts/prepare-release.mjs`** — extended to also append a
   `[X.Y.Z]: https://github.com/colbymchenry/codegraph/releases/tag/vX.Y.Z`
   link reference at the end of CHANGELOG.md when promoting (idempotent
   — no-op if one already exists, regardless of where in the file it
   sits). This is what makes the `## [X.Y.Z]` heading text auto-link
   to its release tag in GitHub's renderer; without it the heading still
   renders, just unlinked. 3 new tests cover Case A append, Case B
   append-when-merging, and no-double-add.

940/942 existing tests still pass (2 pre-existing skips); +3 new tests.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 03:25:06 -05:00
Colby Mchenry b77af782c5 feat(release): auto-promote [Unreleased] into [<version>] on release workflow run (#436)
Fixes the silent-sparse-release-notes failure mode that surfaced on
v0.9.5: the Release workflow used to do a literal
`extract-release-notes.mjs <version>` lookup with an `[Unreleased]`
fallback. The fallback only triggered when the `[<version>]` block
DIDN'T exist at all — and in practice maintainers sometimes had a
sparse `[<version>]` block pre-populated (e.g. one early fix
documented before the rest of the work landed). The workflow then
extracted that sparse block, ignoring the much-larger `[Unreleased]`
section above it. Result: the published v0.9.5 release notes were
missing the shared MCP daemon, the per-file staleness banner, the
Objective-C indexing, AND the Mixed iOS/RN/Expo bridging.

The fix is a new `scripts/prepare-release.mjs` step that runs at the
start of the workflow:

  Case A — `[<version>]` does not yet exist:
    Rename `[Unreleased]` → `[<version>] - <today>`. Add a fresh
    empty `[Unreleased]` above. The common path.

  Case B — `[<version>]` exists AND `[Unreleased]` has content:
    Merge `[Unreleased]`'s sub-sections (### Added / ### Fixed /
    ### Changed / ### Removed / ### Deprecated / ### Security) into
    the corresponding sub-sections of `[<version>]`. Unmatched
    sub-sections are appended. Then empty `[Unreleased]`.

  Case C — `[Unreleased]` is empty:
    No-op. Re-runs of the workflow are safe.

After the script runs, the workflow auto-commits + pushes the
CHANGELOG.md change back to main (with a `[skip ci]` tag in the
commit body) so future runs and human eyes both see the same
on-disk truth.

9 unit tests (`__tests__/prepare-release.test.ts`) cover all three
cases, idempotency, version-source precedence, and an
extract-release-notes.mjs integration check.

Workflow comment header rewritten to reflect the new flow.

Trigger reminder going forward: bump package.json. CHANGELOG entries
can live under `[Unreleased]` — the workflow takes care of moving
them.

937/939 existing tests pass (2 pre-existing skips); +9 new tests.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 03:21:06 -05:00