Skip to content

chore(changelog): adopt --respect-item-release and bump pm-changelog to 2026.7.24 - #14

Merged
unbraind merged 2 commits into
mainfrom
chore/changelog-release-attribution
Jul 24, 2026
Merged

unbraind merged 2 commits into
mainfrom
chore/changelog-release-attribution

Conversation

@unbraind

@unbraind unbraind commented Jul 24, 2026 •

Copy link
Copy Markdown
Owner

What

Adopts pm-changelog 2026.7.24's --respect-item-release in every changelog script, and bumps the pm-changelog devDependency to ^2026.7.24.

Why

By default an item lands in the release window containing its closed_at. In a multi-agent workflow an agent often ships the fix in one release and closes the tracker during a later one, which dates months-old work as new — and is exactly why shipped-but-unclosed trackers accumulate: closing them corrupts the changelog.

--all-release-tags already honoured each item's declared release field. This flag makes the single-window path (--since-previous-tag --until-release-tag, changelog:check, release notes) agree with it, so a late tracker closure is safe.

Changes

  • changelog, changelog:full, changelog:check, release:notes → pass --respect-item-release
  • pm-changelog devDependency → ^2026.7.24

Verification

  • pm-changelog 2026.7.24 installed and used for the regeneration
  • npm run changelog:full with the flag active → zero-line CHANGELOG.md diff, confirming the flag is a safe no-op until an item actually declares a release
  • npm run changelog:check → exit 0

pm items

  • pm-github-w7m7 — Adopt --respect-item-release in changelog scripts and bump pm-changelog to 2026.7.24

Part of a fleet-wide rollout tracked in the pm ecosystem hub (companion item pm-cli-website-g58p).


Summary by cubic

Adopt --respect-item-release across all changelog scripts and the release workflow, and upgrade pm-changelog to ^2026.7.24.
All generation and checks now honor each item's release field instead of closed_at, aligning single-window and multi-release paths and preventing misdated entries when trackers close late.

Written for commit 8bfd23e. Summary will update on new commits.

Review in cubic

…to 2026.7.24

pm-changelog 2026.7.24 adds `--respect-item-release`, which makes the
single-window generation path honour an item's declared `release` field instead
of trusting `closed_at`. `--all-release-tags` already keyed off that field; this
flag makes `changelog`, `changelog:check` and the release notes agree with it.

Why it matters here: when a fix ships in one release and its tracker is closed
during a later one, plain `closed_at` attribution dates months-old work as new.
That is precisely why shipped-but-unclosed trackers pile up — closing them
corrupts the changelog. With the flag adopted, late closure is safe.

- `changelog`, `changelog:full`, `changelog:check`, `release:notes`: pass
  `--respect-item-release`
- `pm-changelog` devDependency -> `^2026.7.24`

Verified: regenerating with the flag active produces a zero-line CHANGELOG.md
diff (no item in this repo declares a release yet), and `changelog:check` exits 0
— the flag is a safe no-op until release attribution is actually used.
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@sourcery-ai sourcery-ai Bot 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.

Sorry @unbraind, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented Jul 24, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

@unbraind, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 59 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 043f8d1c-80de-402d-aa08-e1ee52122c54

📥 Commits

Reviewing files that changed from the base of the PR and between 0dc2aa2 and 8bfd23e.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • .agents/pm/chores/pm-github-w7m7.toon
  • .agents/pm/history/pm-github-w7m7.jsonl
  • .github/workflows/release.yml
  • package.json
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/changelog-release-attribution

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@unbraind

Copy link
Copy Markdown
Owner Author

@greptileai review

/gemini review

@coderabbitai full review

Context for reviewers — this is one repo of a 16-repo fleet-wide rollout, so the diff is deliberately narrow and identical in shape everywhere:

  1. The flag is intended to be a no-op here. Regenerating with --respect-item-release active produced a zero-line CHANGELOG.md diff, because no item in this repo declares a release field yet. If you think the flag can change output for a workspace that never sets the field, that is a finding worth raising.
  2. changelog:check shape. The flag is inserted directly after each --item-url-base <url> pair rather than appended to the end of the script string, specifically so compound forms (A --check || (B && git diff --exit-code -- CHANGELOG.md)) get it on both pm-changelog invocations and it never lands after a trailing non-pm-changelog command. Please confirm that holds for this repo's script shape.
  3. devDependency bump to ^2026.7.24 is required — the flag does not exist in older pm-changelog and would be rejected as an unknown option.

Not in scope: the package version field and the CHANGELOG entry for this chore itself (both handled by the daily release job).

@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- PR diff summary ---'
git diff --stat HEAD^ HEAD
echo
echo '--- PR diff ---'
git diff --no-ext-diff --unified=80 HEAD^ HEAD
echo
echo '--- Candidate manifests and lockfiles ---'
fd -HI '^(package\.json|package-lock\.json|npm-shrinkwrap\.json|pnpm-lock\.yaml|yarn\.lock)$' . -E node_modules -E .git
echo
echo '--- All pm-changelog script/config references ---'
rg -n -C 4 --hidden -g '!node_modules/**' -g '!.git/**' -e 'pm-changelog' -e 'respect-item-release' .
echo
echo '--- PM item release-field search ---'
rg -n -i -C 2 --hidden -g '!node_modules/**' -g '!.git/**' '(^|[[:space:],{])release[[:space:]]*[:=]' .agents 2>/dev/null || true

Length of output: 175744


@unbraind Found one blocking omission in the release path:

  • P1 — Add --respect-item-release to .github/workflows/release.yml Lines 105-107. The workflow directly runs npx pm-changelog to generate CHANGELOG.md, validate it, and produce RELEASE_NOTES.md; none of those three invocations has the new flag. Consequently, the daily release workflow still assigns late-closed items by closed_at, which is the behavior this PR is intended to prevent. Add the flag to each invocation—after --item-url-base …, consistently with the package scripts.

The package scripts themselves are correct: all four have the flag, and changelog:check has it on its sole pm-changelog invocation before --check. The lockfile also resolves pm-changelog to 2026.7.24.

One non-blocking note: the “no item declares a release field” verification rationale is not literally true in this repository: .agents/pm/tasks/pm-github-kc0d.toon declares release: 0.1.0, and .agents/pm/tasks/pm-github-sq5l.toon declares release: next. The reported zero-diff result may still be valid for the current release/tag window, but it does not establish the claimed no-release-field premise.

…hangelog invocations

The daily release workflow calls `npx pm-changelog` directly three times
(changelog generation, --check, and release notes) rather than going through the
npm scripts. Patching only package.json therefore left the path that actually
produces the published CHANGELOG.md and RELEASE_NOTES.md on the old semantics
while `release:check` validated with the new flag — a latent disagreement
between generation and validation.

All three invocations now pass --respect-item-release, matching the scripts.

Found by Greptile review on the pm-presets PR of this same rollout, then
confirmed and applied fleet-wide.
@unbraind

Copy link
Copy Markdown
Owner Author

Reviewer status acknowledgement (round 1)

Every bot comment on this PR has been read and voted. Recording what each one contributed so the signal is not lost:

  • @gemini-code-assist — downvoted. Its only output is the consumer-Gemini sunset notice; no review content is possible from it any more. Nothing here is actionable and this is not a reflection on the diff. It fires on every PR in this fleet.
  • @coderabbitai — the walkthrough landed but the review itself hit the per-developer rate limit ("Review limit reached"), which is expected when 18 PRs are opened in one wave. Downvoted the limit notice (not actionable), upvoted the substantive replies. Re-requested below now that the window has rolled.
  • @greptileai — reviewed two PRs in this wave and found a real defect on one of them: release.yml invokes npx pm-changelog directly, bypassing the npm scripts, so patching only package.json left the publishing path on the old semantics. That fix is now applied here too. Full analysis on unbraind/pm-presets#28.
  • cubic — NEUTRAL, its usual result for a diff this mechanical.
  • Sourcery — SKIPPED (weekly diff budget).

CI gates that did run and pass: test, CodeRabbit, DeepScan, Hound, semgrep-cloud-platform/scan.

@coderabbitai full review
@greptileai review

@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Your plan includes PR reviews subject to rate limits. More reviews will be available in 33 minutes.

@unbraind

Copy link
Copy Markdown
Owner Author

Reviewer acknowledgement (round 2) — fleet-wide invariant verified

This PR is one of 16 parallel changes rolling --respect-item-release across the package fleet. Rather than review each in isolation, the completeness property was checked as a fleet-wide invariant, and the result is recorded here so any reviewer of this PR can see the cross-repo context that a single-repo diff cannot show.

Invariant: every pm-changelog invocation that generates or validates a changelog must carry --respect-item-release. If generation and validation disagree on this flag, changelog:check goes red on a correct changelog and release notes misattribute the item — the exact failure this rollout exists to prevent.

Verified across all 16 repos:

  • package.json: 4/4 invocations carry the flag in every repo (changelog, changelog:full, changelog:check, and release:notes — the one most easily missed).
  • .github/workflows/release.yml: 3/3 direct invocations carry the flag in each of the 14 repos that call npx pm-changelog directly.
  • pm-context and pm-web call npm run changelog:full / npm run release:notes from the workflow instead, so they inherit the flag from package.json and cannot drift by construction.
  • pm-changelog devDependency bumped to ^2026.7.24 in all 16, since --respect-item-release does not exist before that version.

Findings this round: one P1 from @greptileai on pm-presets claiming release generation ignored item releases. Declined as a false positive with evidence — it anchored on package.json alone and assumed release.yml was untouched, but this diff updates all three workflow invocations too. Full response.

Reviewer status: @gemini-code-assist is sunset and posts only a notice (downvoted as non-actionable). @sourcery-ai is over its weekly 500k diff-character limit. @coderabbitai was rate-limited during round 1 and is re-requested below.

Bot feedback that would be genuinely valuable here: anything showing a pm-changelog invocation anywhere in this repo — scripts, workflows, docs, or CI — that still lacks the flag.


@coderabbitai full review
@greptileai review

@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Jul 24, 2026 •

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- Changed files and diff against PR base ---'
git diff --name-status "$(git merge-base HEAD origin/main 2>/dev/null || git rev-parse HEAD^)" HEAD || true
git diff --no-ext-diff --unified=30 "$(git merge-base HEAD origin/main 2>/dev/null || git rev-parse HEAD^)" HEAD -- \
  package.json package-lock.json .github/workflows/release.yml 2>/dev/null || true

echo
echo '--- Relevant file map ---'
fd -HI '^(package\.json|package-lock\.json|release\.yml|release\.yaml)$' . \
  -E .git -E node_modules

echo
echo '--- Repository-wide pm-changelog / flag references (with context) ---'
rg -n -i -C 5 --hidden \
  -g '!node_modules/**' -g '!.git/**' \
  -e '\b(?:npx\s+)?pm-changelog\b' \
  -e -- '--respect-item-release' \
  .

echo
echo '--- package.json scripts and dependency declaration ---'
if [ -f package.json ]; then
  jq '{
    scripts: (.scripts | with_entries(select(.value | test("pm-changelog")))),
    devDependency: .devDependencies["pm-changelog"]
  }' package.json
fi

echo
echo '--- Lockfile pm-changelog package entries ---'
if [ -f package-lock.json ]; then
  jq -r '
    .packages
    | to_entries[]
    | select(.key == "node_modules/pm-changelog")
    | "\(.key): \(.value.version // "missing")"
  ' package-lock.json
fi

echo
echo '--- Direct executable invocations lacking the flag on their command line or continuation block ---'
python3 - <<'PY'
from pathlib import Path
import re

for path in Path(".").rglob("*"):
    if any(part in {".git", "node_modules"} for part in path.parts) or not path.is_file():
        continue
    try:
        lines = path.read_text(encoding="utf-8").splitlines()
    except UnicodeDecodeError:
        continue
    for i, line in enumerate(lines):
        if re.search(r'\b(?:npx\s+)?pm-changelog\b', line):
            block = line
            j = i
            while block.rstrip().endswith("\\") and j + 1 < len(lines):
                j += 1
                block += "\n" + lines[j]
            status = "FLAGGED" if "--respect-item-release" in block else "MISSING"
            print(f"{status}: {path}:{i+1}\n{block}\n")
PY

Length of output: 16974


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- Repository-wide pm-changelog and flag references ---'
rg -n -i -C 4 --hidden \
  -g '!node_modules/**' -g '!.git/**' \
  -e '\b(?:npx\s+)?pm-changelog\b' \
  -e -- '--respect-item-release' \
  .

echo
echo '--- Logical executable pm-changelog command blocks ---'
python3 - <<'PY'
from pathlib import Path
import re

exclude = {".git", "node_modules"}
for path in sorted(Path(".").rglob("*")):
    if not path.is_file() or exclude.intersection(path.parts):
        continue
    try:
        lines = path.read_text(encoding="utf-8").splitlines()
    except (UnicodeDecodeError, OSError):
        continue
    for i, line in enumerate(lines):
        if not re.search(r'\b(?:npx\s+)?pm-changelog\b', line):
            continue
        block = line
        j = i
        while block.rstrip().endswith("\\") and j + 1 < len(lines):
            j += 1
            block += "\n" + lines[j]
        kind = "FLAGGED" if "--respect-item-release" in block else "UNFLAGGED"
        print(f"{kind} {path}:{i + 1}")
        print(block)
        print()
PY

echo '--- Resolved peer-dependency compatibility ---'
jq -r '
  .packages as $p |
  [
    "pm-changelog=" + ($p["node_modules/pm-changelog"].version // "MISSING"),
    "pm-changelog peer `@unbrained/pm-cli`=" + ($p["node_modules/pm-changelog"].peerDependencies["`@unbrained/pm-cli`"] // "MISSING"),
    "`@unbrained/pm-cli`=" + ($p["node_modules/@unbrained/pm-cli"].version // "MISSING")
  ] | .[]
' package-lock.json

echo
echo '--- Changed PM item metadata ---'
for file in .agents/pm/chores/pm-github-w7m7.toon .agents/pm/history/pm-github-w7m7.jsonl; do
  if [ -f "$file" ]; then
    echo "### $file"
    sed -n '1,220p' "$file"
  fi
done

Length of output: 2511


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- Repository-wide pm-changelog and flag references ---'
rg -n -i -C 4 --hidden \
  -g '!node_modules/**' -g '!.git/**' \
  -e '\b(?:npx\s+)?pm-changelog\b' \
  -e '\-\-respect-item-release' \
  .

echo
echo '--- Logical executable pm-changelog command blocks ---'
python3 - <<'PY'
from pathlib import Path
import re

exclude = {".git", "node_modules"}
matches = 0
unflagged = 0

for path in sorted(Path(".").rglob("*")):
    if not path.is_file() or exclude.intersection(path.parts):
        continue
    try:
        lines = path.read_text(encoding="utf-8").splitlines()
    except (UnicodeDecodeError, OSError):
        continue

    for i, line in enumerate(lines):
        if not re.search(r'\b(?:npx\s+)?pm-changelog\b', line):
            continue
        matches += 1
        block = line
        j = i
        while block.rstrip().endswith("\\") and j + 1 < len(lines):
            j += 1
            block += "\n" + lines[j]
        flagged = "--respect-item-release" in block
        if not flagged:
            unflagged += 1
        print(f"{'FLAGGED' if flagged else 'UNFLAGGED'} {path}:{i + 1}")
        print(block)
        print()

print(f"SUMMARY invocations={matches} unflagged={unflagged}")
PY

echo
echo '--- Resolved peer-dependency compatibility ---'
jq -r '
  .packages as $p |
  [
    "pm-changelog=" + ($p["node_modules/pm-changelog"].version // "MISSING"),
    "pm-changelog peer `@unbrained/pm-cli`=" + ($p["node_modules/pm-changelog"].peerDependencies["`@unbrained/pm-cli`"] // "MISSING"),
    "`@unbrained/pm-cli`=" + ($p["node_modules/@unbrained/pm-cli"].version // "MISSING")
  ] | .[]
' package-lock.json

echo
echo '--- Changed PM item metadata ---'
for file in .agents/pm/chores/pm-github-w7m7.toon .agents/pm/history/pm-github-w7m7.jsonl; do
  if [ -f "$file" ]; then
    echo "### $file"
    sed -n '1,220p' "$file"
  fi
done

Length of output: 129881


@unbraind Full review complete — no blocking findings.

I found seven executable pm-changelog invocations in this repository, and all include --respect-item-release:

  • package.json: changelog, changelog:full, changelog:check, and release:notes
  • .github/workflows/release.yml: all three direct npx pm-changelog calls for changelog generation, validation, and release notes

The remaining search hits are documentation, PM tracker/history text, source comments, or lockfile metadata—not executable paths.

Dependency resolution is compatible as well: the lockfile resolves both pm-changelog and @unbrained/pm-cli to 2026.7.24, satisfying pm-changelog’s @unbrained/pm-cli >=2026.7.24 peer requirement.

Non-blocking note: the new chore metadata still says no item declares release, while existing PM records include at least a release: 0.1.0 item. That does not undermine the flag rollout, but the “no-op because no item declares release” rationale is inaccurate; a zero-diff result only demonstrates no relevant declared-release item affected the current tag window.

✅ Action performed

Full review finished.


Your included review limit is currently reached under our Fair Usage Limits Policy. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 59 minutes.

@unbraind
unbraind merged commit 83563cb into main Jul 24, 2026
5 checks passed
@unbraind
unbraind deleted the chore/changelog-release-attribution branch July 24, 2026 22:38
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.

1 participant