Skip to content

docs(release): add the release-notes step and the re-cut procedure - #2555

Merged
cliffhall merged 5 commits into
v2/mainfrom
v2/docs/2554-release-notes-step
Oct 1, 2026
Merged

cliffhall merged 5 commits into
v2/mainfrom
v2/docs/2554-release-notes-step

Conversation

@cliffhall

Copy link
Copy Markdown
Member

Closes #2554

Step 3 of the release skill said only "generate the notes and publish." The v2.9.0 release established a fuller notes format and exposed a failure mode the skill did not cover. Both are now written down.

What changed

.claude/skills/release/SKILL.md, step 3 is now three parts:

  • 3a. Draft the release notes. Four parts, in order:

    1. What's Changed
    2. the smoke-ledger line
    3. ## Known issue, written by hand, only when there is one
    4. ## Thanks for helping us improve

    A copy-paste recipe derives VERSION and PREV, generates the list through releases/generate-notes (the API behind the UI button), and builds the credit list: the authors of the issues each listed PR closes, through either manual closing links or Closes/Fixes/Resolves #N, minus maintainers (admin/maintain/write, checked through the API) and bots. The lead-in uses "addresses", since feature requests count. It notes that @-mentions feed the release's Contributors strip.

  • 3b. Tag and publish. The existing UI flow and warnings are unchanged, plus the gh release create … --target main --notes-file equivalent. It notes that editing a published release's notes is safe (every tag's main.yml fires only on release: [published]).

  • 3c. If the release run fails.

AGENTS.md: the skills-index row for release now mentions the notes and the re-cut.

Verification

  • The recipe reproduces 2.9.0's published Thanks section exactly. Run against 2.8.0 → 2.9.0, it produced the same six reporters, issues and order, with diff empty. Maintainers (cliffhall, BobDickinson) and the SDK-watch bot were excluded through the permission check, not a hard-coded list.
  • PREV detection: 2.9.0 → 2.8.0, and an as-yet-untagged 2.10.0 → 2.9.0 (no RC or v1 tag picked).
  • verify:skills OK, with the listing budget unchanged at 3900/4000. The skill's description is untouched.
  • npm run local:gate → green (exit 0, 5m17s).

Scripting all of this into a tested helper, including creating the Release, remains #2550.

🤖 Generated with Claude Code

Step 3 of the release skill said only "generate the notes and publish".
It is now three parts:

- 3a, draft the release notes: What's Changed from the generate-notes
  API, the smoke-ledger line, any known issue, and a "Thanks for helping
  us improve" section crediting the community members whose issues the
  release addresses (maintainers and bots excluded by permission). The
  recipe reproduces 2.9.0's published Thanks section exactly. @-mentions
  feed the release's Contributors strip.
- 3b, tag and publish: the existing UI steps, plus gh release create
  with the notes file. Editing published notes is safe, since every tag's
  main.yml fires only on release: [published].
- 3c, if the release run fails: a release runs the workflow from the
  tag's commit, so fix it on v2/main, merge to main, delete the Release
  AND its tag, and re-cut. This is what 2.9.0 needed (#2551).

The AGENTS.md skills-index row for release is updated to match.

Closes #2554

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

The recipe can select incorrect tags and produce incomplete or stale release notes.

Review effort: Balanced
Findings: 2 Medium severity · 2 Low severity

Open (4)
What changed in this PR

Documents the release-note format and failed-release re-cut procedure.

Changes:

  • Adds release-note generation and reporter-credit guidance.
  • Documents publishing, editing, and re-cut recovery.
  • Updates the skills index.
File Description
.claude/​skills/​release/​SKILL.md Expands release and recovery procedures.
AGENTS.md Updates the release skill summary.

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread .claude/skills/release/SKILL.md Outdated
Comment thread .claude/skills/release/SKILL.md Outdated
Comment thread .claude/skills/release/SKILL.md Outdated
Comment thread .claude/skills/release/SKILL.md Outdated
- PREV is now the highest strict x.y.z tag below VERSION. The old glob
  also matched 2.0.0-rc.N, x.y.z-hotfix and x.y.z-amended tags, so
  cutting a stable release after an RC would pick the RC and drop
  changes (for VERSION=2.0.0 it picked 2.0.0-rc.3; now 1.0.2).
- thanks.md is truncated before the optional append, so a rerun with no
  eligible reporters never keeps a stale section.
- A re-cut re-runs the whole 3a recipe, since a fix PR can close a
  community-reported issue and change the Thanks section too.
- The re-cut no longer waives verification: gate and smoke a fix
  wherever it can be run, and only a release-only path takes the re-cut
  run as its first evidence.

Refs #2554

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
@cliffhall

Copy link
Copy Markdown
Member Author

Copilot round 1: 4 findings (2 medium, 2 low), all real defects in text this PR added, all fixed in 4c05d3b:

  • PREV glob matched RC and hotfix tags, so a stable release after an RC would take the RC as PREV. It now uses strict x.y.z tags below VERSION (2.0.0 → 1.0.2, not 2.0.0-rc.3).
  • thanks.md is truncated before the optional append (tested with 2.1.0, which has no reporters: 0 bytes).
  • A re-cut re-runs the whole recipe, Thanks section included.
  • The re-cut no longer waives pre-release verification; only release-only paths take the re-cut run as first evidence.

The 2.9.0 reproduction still matches the published notes exactly. local:gate green (4m55s). Requesting round 2.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

The reporter extraction and CLI release commands contain execution-breaking shell/filter errors.

Review effort: Balanced
Findings: None

Resolved since last review (4)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Extra iteration truncates captured issue numbers

.claude/​skills/​release/​SKILL.md:246

scan() emits an array of capture groups for each match, but this extra [] iterates that array before .[0]. With gh --jq, .[0] then indexes the captured issue-number string, so Closes #2554 contributes issue 2 instead of 2554 (and other jq implementations may error). Keep the capture array intact until selecting its first group.

Medium severity Angle brackets cause missing notes-file argument

.claude/​skills/​release/​SKILL.md:291

Inside this copy-paste shell block, <assembled-notes.md> is input-redirection syntax rather than a filename placeholder. The shell removes it from the argument list, leaving --notes-file without its required path, so the documented CLI release command fails instead of creating the release.

…older (Copilot)

- The body-reference extraction did scan(...)[] | .[0], which with gh's
  jq indexes the first CHARACTER of each captured string: "Closes #2554"
  became issue 2. It is now scan(...) | .[0]. Verified with gh --jq:
  "Closes #2554 … Fixes #12 … resolves #999" gave [2,1,9] before and
  [2554,12,999] after. The 2.9.0 check missed it because every PR there
  also carried a manual closing link.
- <assembled-notes.md> inside a shell block is input redirection, so
  --notes-file lost its argument. It is now a NOTES variable.

Cross-checked: the fixed recipe reproduces the published Thanks lists
of 2.9.0, 2.8.0, 2.5.0 and 2.4.0 exactly (26 reporters; three of those
lists were built independently).

Refs #2554

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
@cliffhall

Copy link
Copy Markdown
Member Author

Copilot round 2: no inline findings, but the review body's Previously missed block named two defects in code this round did not change. Neither has a thread, so this is their reply. Both were real, and both are fixed in f729055:

  • scan(…)[] | .[0] truncated issue numbers. With gh's jq it indexes the first character of each captured string. Verified with gh --jq: Closes #2554 … Fixes #12 … resolves #999 gave [2,1,9]; it now gives [2554,12,999] with scan(…) | .[0]. The earlier 2.9.0 check missed this because every PR there also carried a manual closing link, which supplied the right numbers.
  • <assembled-notes.md> was input redirection inside the shell block, so --notes-file lost its argument. It is now a NOTES variable.

Cross-check after the fix: the recipe reproduces the published Thanks lists of 2.9.0, 2.8.0, 2.5.0 and 2.4.0 exactly (26 reporters). The last three were built independently by the retroactive pass, and 2.4.0 exercises the body-Closes path. local:gate green (4m56s). Requesting round 3.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

The reporter query truncates closing links, and re-cutting leaves supported manual workflows with a stale local tag.

Review effort: Balanced
Findings: None

Previously missed (2)

In code that hasn't changed since last review

Medium severity Paginate closing issue references instead of capping at 20

.claude/​skills/​release/​SKILL.md:246

closingIssuesReferences(first:20) silently drops any manual closing links after the twentieth. Those links do not necessarily appear in the PR body, so the regex cannot recover them and the recipe can omit reporters despite promising credit for every closed issue. Paginate this connection rather than imposing a fixed cap.

Medium severity Delete the stale local tag during the re-cut procedure

.claude/​skills/​release/​SKILL.md:353

This removes only the remote tag. The supported manual path above creates a local tag, which then remains pointed at the broken commit: the manual re-tag command will abort, and after the tag is recreated remotely, a later git fetch --tags can fail because it would clobber that stale local tag. Delete any local copy as part of the re-cut procedure.

The re-cut deleted only the remote tag. The 3b manual path creates a
local tag, which would stay pointed at the broken commit: the re-tag
aborts, and a later git fetch --tags refuses to clobber it. Delete it
locally as well.

Refs #2554

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
@cliffhall

Copy link
Copy Markdown
Member Author

Copilot round 3: no inline findings. The Previously missed block named two items with no thread, so this is their reply.

local:gate green (4m46s). Requesting round 4.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

The procedure can silently generate incomplete credits and gives unsafe guidance for npm checks and transient downstream failures.

Review effort: Balanced
Findings: None

Previously missed (3)

In code that hasn't changed since last review

Medium severity Masked API failures can produce incomplete or incorrect Thanks section

.claude/​skills/​release/​SKILL.md:246

This pipeline can silently publish an incomplete Thanks section. None of the gh api calls fail the overall pipeline: without pipefail, an API/auth/rate-limit failure is masked by the later sort/awk, and line 251 explicitly converts every permission lookup failure into none, potentially crediting a maintainer. Make API failures abort note generation (for example, check every call and run the pipeline under fail-fast/pipefail semantics) rather than treating partial data as valid release notes.

Medium severity Incorrectly inferring unpublished versions from missing dist-tags

.claude/​skills/​release/​SKILL.md:338

dist-tags are mutable aliases, so absence there does not prove that the immutable version was never published; following that conclusion can lead to an invalid re-cut after npm already owns the version. Wait out npm's Validating state, then query @$VERSION directly and treat only an exact-version 404 as unpublished.

Medium severity Unnecessary fix-forward causes duplicate npm release attempts

.claude/​skills/​release/​SKILL.md:370

Do not defer every downstream failure to the next release. The GHCR job is independent of the successful npm job, and GitHub Actions can re-run only the failed job at the same tagged commit; a transient registry/runner failure can therefore complete the current release without attempting npm again. Reserve “fix forward” for a defect in the tagged workflow that cannot succeed on retry.

… failures (Copilot)

- Never infer "unpublished" from dist-tags. During the 2.9.0 re-cut,
  2.9.0 existed (Validating) while dist-tags still said latest 2.8.0.
  Wait out validation and treat only an exact-version 404 as
  unpublished.
- When npm published but a downstream job (such as GHCR) failed, re-run
  only the failed job for a transient fault, and fix forward only a
  defect that cannot pass on retry. Never re-cut a version npm owns.

Refs #2554

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
@cliffhall

Copy link
Copy Markdown
Member Author

Copilot round 4: no inline findings. The Previously missed block named three items with no thread, so this is their reply.

local:gate green (4m52s). Requesting round 5.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

The reporter-credit pipeline can silently omit contributors through masked API failures and unpaginated closing-issue results.

Review effort: Balanced
Findings: None

Previously missed (2)

In code that hasn't changed since last review

Medium severity Fail closed on GraphQL and permission lookup errors

.claude/​skills/​release/​SKILL.md:246

A failure from either GraphQL lookup is masked by the later stages of this pipeline: without pipefail, the final awk still exits successfully and writes a partial (or empty) thanks.txt. The permission lookup also converts every API failure—not only an expected “no access” result—into none, which can credit a maintainer. Make this recipe fail closed (for example, run the whole pipeline with set -euo pipefail and only special-case the specific expected permission response) so transient API/auth failures cannot silently publish incomplete credits.

Medium severity Paginate closing issue references to avoid missing credited issues

.claude/​skills/​release/​SKILL.md:246

first:20 silently drops the 21st and later manually linked closing issues, despite this procedure promising to credit every issue a listed PR closes. Paginate closingIssuesReferences with pageInfo/endCursor (or use an equivalent exhaustive query) so releases cannot omit reporters solely because one PR has many closing links.

@cliffhall

Copy link
Copy Markdown
Member Author

Copilot review loop closed after round 5. It raised no new findings: its two Previously missed items (fail-closed API handling, and paginating closingIssuesReferences) are the same two declined in rounds 3 and 4, with reasons given there. Both are recorded as requirements for the tested helper in #2550, which replaces this recipe.

Across five rounds, 8 real defects were fixed: RC/hotfix tags as PREV, the stale thanks.md, the Thanks section during a re-cut, verification before a re-cut, scan() truncating issue numbers, the <…> redirection placeholder, the stale local tag, and inferring unpublished from dist-tags, plus retrying transient downstream failures. The recipe reproduces the published Thanks lists of 2.9.0, 2.8.0, 2.5.0 and 2.4.0 exactly.

@cliffhall
cliffhall merged commit cd05288 into v2/main Oct 1, 2026
6 checks passed
@cliffhall
cliffhall deleted the v2/docs/2554-release-notes-step branch October 1, 2026 00:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v2 Issues and PRs for v2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

release skill: add the release-notes step (generated list, ledger, known issues, reporter thanks) and the re-cut procedure

2 participants