Pin the pm toolchain and assert the changelog-date flag by difference - #74
Conversation
pm-changelog 2026.9.2 stopped stamping the wall clock. An unflagged heading is now the bare `## <version>` instead of `## <version> - <today>`. This repo's control only noted that mismatch and still exited 0, so a no-op `--date-from-version` would have passed. The control now fails when the unflagged heading is missing or identical to the flagged version-dated heading, which is true of both generators. Pinned @unbrained/pm-cli 2026.9.5 (exact), pm-changelog 2026.9.2 (exact), and pm-ops ^2026.9.5 (caret preserved). $ ./scripts/verify-release-changelog-date.sh ok - with the flag the heading is version-derived: ## 2026.1.2 - 2026-01-02 ok - without the flag the heading is undated: ## 2026.1.2 # exit 0 # identical control (unflagged also passed --date-from-version): FAIL: without --date-from-version the heading is already '## 2026.1.2 - 2026-01-02', identical to the flagged run # exit 1 npm run release:check and pm health --strict-exit both exit 0.
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Team Run ID: 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. Comment |
Reviewer's GuideThis PR pins the pm toolchain and updates the changelog-date control to verify the flag has an observable effect by requiring the unflagged heading to differ from the flagged, version-derived heading, while accommodating both legacy clock-stamped and newer undated generator output. Sequence diagram for changelog date flag verificationsequenceDiagram
participant Script as verify-release-changelog-date.sh
participant Generator as pm-changelog
Script->>Generator: generate with --date-from-version
Generator-->>Script: ## 2026.1.2 - 2026-01-02
Script->>Script: compare flagged heading with expected
Script->>Generator: generate without --date-from-version
Generator-->>Script: ## 2026.1.2
Script->>Script: compare unflagged heading with flagged heading
alt headings differ
Script-->>Script: exit 0
else headings identical or missing
Script-->>Script: exit 1
end
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Greptile SummaryPins the repository’s pm toolchain and strengthens changelog-date verification so the flag must produce a distinct, probe-version heading.
Confidence Score: 5/5The PR appears safe to merge with no outstanding findings. The dependency updates remain lockfile-controlled in automated installs, the repository rule is not violated, and the only previous Greptile thread was manually resolved after the author’s follow-up change.
|
| Filename | Overview |
|---|---|
| scripts/verify-release-changelog-date.sh | Reworks the unflagged control to require output distinct from the flagged result while checking that it belongs to the probe version. |
| package.json | Updates the three pm development dependencies while preserving their existing exact and caret range styles. |
| package-lock.json | Locks the updated pm toolchain and its revised transitive dependency graph. |
| CHANGELOG.md | Adds an Unreleased entry describing the toolchain pin and changelog-date assertion. |
| .agents/pm/chores/pm-github-c5i4.toon | Records the completed maintenance item and the response to the previous review. |
| .agents/pm/history/pm-github-c5i4.jsonl | Preserves the task’s lifecycle and review-response history. |
Reviews (2): Last reviewed commit: "fix(release): bound the date control by ..." | Re-trigger Greptile
Greptile raised a valid P2 against the loosened control: asserting only that the unflagged heading DIFFERS from the flagged one means a generator emitting a malformed heading, or a heading for the wrong version, is reported as "undated" and passes. The control then proves the flag changed something, but not that it changed the right thing -- and a control that vouches for output it cannot recognise is exactly the failure the flagged half is there to prevent. The open-ended else is replaced by an explicit allow-list of the two shapes a correct generator can produce for the probe version: ## 2026.1.2 (undated; pm-changelog 2026.9.2 and later) ## 2026.1.2 - <today> (clock-derived; earlier releases) Anything else fails and names both accepted forms next to what was received. This keeps the property that made the loosening necessary -- the control is not pinned to the clock form, so it still passes against the generator that fixed the clock dependence -- while refusing to certify a heading it does not know. Every branch verified to fire: a wrong-version heading fails as unrecognised, undated and clock-derived both pass, a heading identical to the flagged run fails, and an empty heading fails. Tracked as pm-github-c5i4.
|
@greptileai review Pushed f292df1 addressing your P2 in full — the control no longer certifies a heading it cannot recognise. Please re-check that specific hunk in Worth an adversarial second look: the allow-list now hardcodes the two shapes a correct generator produces for the probe version. That is deliberately narrower than "anything different", but it does mean a future legitimate heading format would fail the gate until the allow-list is extended. I think failing closed is right here — this script exists to catch the generator changing its date behaviour, so a new shape SHOULD stop the build and be reviewed rather than pass silently. If you disagree, say so, because that is the one judgement call in the fix. |
…ated spellings The allow-list of two spellings was too brittle. A sibling package's generator also emits a disambiguated `## <probe>-2` heading when a section for that version already exists, which is legitimate output the enumeration would have failed on -- turning Greptile's correctness fix into a false build stop. The bound is now the property rather than the spellings: the unflagged heading must be a heading FOR THE PROBE VERSION, in some form other than the version-derived one. That still rejects the case Greptile raised (a malformed heading, or one for a different version, can no longer be certified as undated), while accepting any legitimate non-version-derived spelling. The trailing `[^0-9]` guard stops probe `2026.1.2` matching a heading for `2026.1.20`. Verified: wrong-version, false-prefix, identical-to-flagged and empty all fail; bare, disambiguated and clock-derived all pass.
|
Final reconciliation. Greptile re-reviewed after the fix and returned 5/5 with no remaining findings; its original P2 is answered in-thread with the per-branch verification table. CodeRabbit and Sourcery summary-only, cubic NEUTRAL on its monthly cap. All upvoted, and the P2 comment itself upvoted — it was the most useful finding of the session. Recording what that finding actually taught, because it generalises beyond this file. The original break was a guard pinned to a symptom (the generator stamps the clock) rather than to the property it exists to prove (the flag determines the date). Fixing that by asserting mere difference swung too far the other way and let the guard certify output it could not recognise. The stable form is a bound that names the property and its domain: the unflagged heading must be a heading for the probe version, in a non-version-derived form. The evidence that settled the shape of the fix came from outside this PR — a sibling package's generator emits The same tightening is now carried to the sibling repository that received the same loosening today (unbraind/pm-linear#101), so this is not being closed as a local fix. |
…obe version (#75) * fix(release): match the control heading as a grammar and escape the probe version Greptile raised a second P2 against the boundary merged here earlier today (#74), on the sibling pm-linear PR. It applies identically, so this carries the fix across rather than leaving it local to the repository that was reviewed. Excluding only a DIGIT immediately after the probe is barely narrower than accepting anything. All three of these passed: ## 2026.1.2.3 a different version ## 2026.1.2-rc1 a different version ## 2026.1.2 - garbage a date position holding something that is not a date The last is the one that matters: it is exactly the shape a broken date implementation would emit, so the control was blind in precisely the direction this gate exists to watch. The suffix is now matched as a grammar of the forms a correct generator produces for one probe version -- the bare version, an optional `-<n>` duplicate-section suffix, an optional ` - <YYYY-MM-DD>` date -- and the failure message names those accepted forms rather than only rejecting. Second defect fixed in passing: `${probe}` was interpolated into the pattern UNESCAPED, so its dots matched any character and `## 2026X1Y2` would have been accepted as a heading for 2026.1.2. It is now escaped before use. Verified across all nine cases: the three above plus the false-prefix `## 2026.1.20 - ...` and a wrong version are rejected; bare, suffixed, dated and suffixed-and-dated headings are accepted. release:check exits 0. Tracked as pm-github-bi6l. * fix(release): bind the control's date to the clock and give the grammar a self-test Two further Greptile P2s on this branch, both correct. MALFORMED DATES STILL PASSED. Matching the optional date by its digit widths (`[0-9]{4}-[0-9]{2}-[0-9]{2}`) accepts `## 2026.1.2 - 2026-13-40`, an impossible date, and `## 2026.1.2 - 1999-01-01`, a stale one -- precisely the malformed date implementations this control exists to reject. The date is now bound to the actual clock date. That is the correct bound rather than a tighter guess: the only date an unflagged run may legitimately carry is TODAY's, because deriving the date from the clock is the defect --date-from-version removes. THE GRAMMAR HAD NO TESTS. A normal run only ever sees the single heading this checkout's generator happens to emit, so every accept and reject boundary was unexercised and could regress silently -- and the aggregate release check does not exercise them either. The script now has a `--self-test` mode that runs the matcher against a fixed 14-case matrix and exits non-zero on any disagreement, and test/release-workflow.test.ts invokes it. That keeps the pattern single-sourced: the test asserts the script's own verdict instead of restating the regular expression and drifting from it. It also asserts that specific matrix rows actually ran, so a self-test that silently checked nothing cannot pass. The matrix covers what review of this control has actually caught: another version, a prerelease suffix, an impossible date, a stale date, a non-date in the date position, a heading matched only because an unescaped probe's dots acted as wildcards, and the empty heading. Confirmed non-vacuous by restoring the shape-only date match: the test fails (8 pass / 1 fail) and passes again with the bound restored (9 / 0). release:check exits 0. --------- Co-authored-by: SteveBot <1153461+unbraind@users.noreply.github.com>
pm-changelog 2026.9.2 stopped stamping the wall clock. An unflagged run now emits the bare
## <version>heading where it used to emit## <version> - <today>.This repository's control in
scripts/verify-release-changelog-date.shonly noted that mismatch and still exited 0. That is vacuous: a--date-from-versionflag that did nothing would still pass, because the flagged heading is asserted independently and the unflagged run could not fail the script.The flagged heading is still the version-dated form (
## 2026.1.2 - 2026-01-02). The control now asserts only that the unflagged heading differs from that. Both the old clock-stamping generator and 2026.9.2 satisfy that property. A control identical to the flagged run still fails.Pinned the current published toolchain, preserving each range style:
@unbrained/pm-cli2026.9.5 (exact)pm-changelog2026.9.2 (exact)pm-ops^2026.9.5 (caret)Evidence from this tree:
npm run release:checkexit 0.pm health --strict-exitexit 0.pm items
Summary by Sourcery
Pin the pm toolchain and make changelog-date verification prove that the flag changes the generated heading.
Bug Fixes:
--date-from-versionfrom passing.Enhancements:
Build:
@unbrained/pm-cliandpm-changelogto exact published versions and updatepm-opswithin its existing caret range.Tests:
Chores:
Summary by cubic
Pins the pm toolchain and hardens changelog-date verification so a no-op
--date-from-versioncan no longer pass.pm-changelog2026.9.2 stopped stamping the wall clock, so the unflagged heading is now bare## <version>.@unbrained/pm-clito 2026.9.5,pm-changelogto 2026.9.2, andpm-opsto ^2026.9.5, preserving the existing exact/caret ranges.## <version>-2are also accepted.npm run release:checkandpm health --strict-exitboth pass.Written for commit 808d51b. Summary will update on new commits.