Repository navigation
fix(release): release-changelog.mjs refuses to run except as a version command's hook (#198) - #211
Merged
nissa-seru merged 6 commits intoOct 18, 2026
Conversation
…n hook; --help says what it does The script is package.json's `version` hook and reads the version from package.json, which npm version has already bumped when it runs the hook. It took no arguments, so `node scripts/release-changelog.mjs --help`, or any other by-hand run, released into the version package.json already held: it folded changelog.d/ into CHANGELOG.md and deleted the fragments. Anarchid found it reviewing anima-research#156 (anima-research#198); it refused there only because `## 0.14.1` already existed. - It now runs only when npm_command is `version` and npm_lifecycle_event is `version`, which is npm version running its version hook. Both are needed: `npm run version` runs the same script with npm_command `run` and bumps nothing (an `npm run version -- --help` passes the flag to git add, not to the script), and a preversion hook runs before the bump. Anything else is refused with what it saw and nothing changed. The issue suggested checking npm_lifecycle_event alone, which lets `npm run version` release; this refuses it too. - `--help`/`-h` prints what the script does and how it's meant to run, and exits 0 without touching anything, wherever it's run. Any other argument is refused: it takes none. - No changelog fragment: like the script's earlier fixes (c3253b1, 6fe1685, b5087e9), this is maintainer tooling no host or strategy author notices. Tests: the black-box run helper now gives each case npm version's hook environment unless the case overrides it. New cases: run directly (both variables unset), through `npm run version`, as a preversion hook, and with an unknown argument each refuse with what they saw and leave CHANGELOG.md and the fragments untouched; `--help` in the hook and `-h` outside npm print the usage, exit 0 and change nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… command; tests pin bun's runs and help on any input (hm-cm198) Answers the haiku review of e5760a6 (hm-cm198, wf-1957). - The refusals start "refused", say the script changed nothing, and name `node scripts/release-changelog.mjs --help`, since through `npm run version` a --help reaches `git add`, not the script (I5, I11). The hook-shaped refusal adds that a version bump made before it ran, as by `bun pm version`, stays in package.json: bun writes the new version before running the hook (observed with bun 1.4.3), so the refusal leaves it bumped (I3). An unknown argument's refusal says it takes none but --help or -h. - The header and USAGE say the check guards against running the script by mistake, from the environment npm gives its hook, which any process can set (I2); that a run any other way is refused, and why; that it takes no arguments but --help or -h (I8); and that npm then makes its release commit and tag as it's configured to, which --no-git-tag-version turns off (I13). Tests: refusal rows for `bun run version` (npm_command run-script) and `bun pm version` (npm_command unset, npm_lifecycle_event version), which only the strict comparison kept out (I1). --help and -h each run in the hook's environment and outside npm (I4), on a fixture the release refuses (nothing to release), so help that read its inputs first would fail (I12). The help cases' stderr assertion is gone: the run helper returns an empty stderr on exit 0, so it couldn't fail (I10). The refusal regexes match the new wording. Not changed: I6 is not real: npm 7.24.2, 8.19.4, 9.9.4, 10.9.9 and 11.19.1 each give the version hook npm_command=version and npm_lifecycle_event=version (through npx on the VPS). I7: --help or -h wins over other arguments, as in most tools. I9: the help's prose isn't pinned, since that would pin wording. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…pm version still releases efa7072 refused the hook unless npm_command was "version", which refused `bun pm version`. bun bumps package.json and then runs the version hook, as npm version does, but sets no npm_command, and on main that release comes out whole. Refusing it took away a path that works today and guarded against no mistake, since a version command that has already bumped isn't one (the reader's finding; the decision to keep bun working). The check now refuses unless npm_lifecycle_event is "version" and npm_command is "version" or unset. Every refusal stays: a direct run (both unset), `npm run version` ("run"), `bun run version` and `pnpm run version` ("run-script"), npm version's preversion hook, and an unknown argument. What else passes: an environment with the event and no npm command. `yarn version` makes it after bumping, which is right. `yarn run version` makes it too, bumping nothing (yarn 1.22.22 with npm_command cleared, as a global yarn runs), and only the release's own refusal of a version that already has a section stops that. The comment above checkInvocation says so. Also: - The refusal names a version command "such as npm version", and drops its clause about a bump made before it ran: no refused path bumps first now. - USAGE and the header say npm version's or bun pm version's hook. - The bun pm version case moves from the refusals to a test that it releases: the fragment is folded into the new section and deleted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mp stays; tests pin npx, help precedence and the section refusal (hm-cm198-r1) Round 2, answering the delta review hm-cm198-r1 (wf-2048) of efa7072..5ec683a. The check is unchanged: it refuses unless npm_lifecycle_event is "version" and npm_command is "version" or unset. What changed is what the texts say about it. - I1: the usage, the header and checkInvocation's comment promised that only npm version's and bun pm version's hooks run. The check reads two variables and can't see a bump, so yarn version passes (rightly) and yarn run version passes too (it bumps nothing). The usage now says the environment must look like a version command's hook, names npm version, bun pm version and yarn version, and says yarn run version looks the same and the release's section refusal is what stops it. The comment names both runs it judges wrongly. - I2, I10: 5ec683a's message said no refused path bumps first, and its refusal dropped the sentence about a bump made before it ran. Wrong: a bump-first version command launched by npx (npm_command "exec") or from an npm script ("run") inherits that npm_command and is refused after its bump, and so would a postversion hook. The refusal says again that a bump made before it ran stays in package.json, without bun as its example, and the comment names the inherited case. - I4: the section refusal, the one stop for yarn run version against a released version, now leads with "refused, and this script changed nothing" and says to release under a new version with npm version. - I5: the header and usage say the version command makes the release commit and tag, not npm alone. - I8: the comment's "only the section refusal" now names nothing to release as well. Tests (I3, I6, I9): --help after an unknown argument still prints the usage (help wins over other arguments); npm_command "exec" is refused, with the bump sentence; an unset npm_command against a version that already has a section is refused by the section refusal and touches nothing. Not changed: I7 (npm version <current> --allow-same-version passes) is a deliberate version command, and the PR text names it beside yarn run version; I11 is the PR text's; I12 isn't real (the refusal says it runs only as the version hook and shows npm_lifecycle_event 'preversion'). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…inherit a launcher's npm_command The comment said any version command launched by npx or from an npm script is refused after its bump. Checked through npm run on the VPS (runs/cm198/npm-script-launch.txt): a script running bun pm version gives the hook npm_command 'run' and bumps, so it's refused; one running npm version gives npm_command 'version' and passes, since npm sets its own. The comment now says it's a command that sets no npm_command itself. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s in package.json After a version command bumps to a version that already has a section, the refusal's advice to run npm version again needs package.json restored first, since npm version refuses a working tree that isn't clean. The refusal now says the bump stays, as the invocation refusal does. Against yarn run version nothing was bumped, so the advice works as it stands there (the reader's optional point on round 2). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
[Low impact] This PR appears safe to merge; no actionable issues were found. SummaryAdds an invocation check to
Reviews (1) · Last reviewed commit: "fix(release): the section refusal says a..." · Reviewed by Greptile |
1 task done
nissa-seru
pushed a commit
to nissa-seru/context-manager
that referenced
this pull request
Oct 18, 2026
Main moved 212 commits since this branch's head (3b6fb9c), through anima-research#211 (2d552dd). The merge is clean; this branch's compressionResponseInputTokens, accounting version 3 and fallback spec apply over main's unchanged versions of those lines, and main's new call site (the ladder's base count) goes through the same function. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tel-0s
added a commit
that referenced
this pull request
Oct 18, 2026
…ls and the R2 provenance guards meet the derived context What main brings since 9db44db (20 merges): the greedy-fold and kv-stable fixes for a chunk's summary at a level (#194, #195), the shadow-pick kv-overlap log (#222), the tool-prose regime's key order (#232), named bodies in attribution (#206), the R2 journal and provenance guards (#146), carried-projection overlap (#186), blob-ref media types (#226), malformed content refused at the store's rule (#184), the omission-marker cap (#218), the before-user fallback (#220), the lock on membrane (#221), one lister per summary (#208), over-budget cleared-by (#190), serialized media (R2), the discarded-cache counts (#199), and the release-changelog hook (#211). One conflict, src/strategies/autobiographical.ts: both sides added a declaration after `fills`: the branch's `AutobiographicalRenderingFrontier` (what `exportRenderingFrontier` hands a fresh instance over a derived context) and main's `sentForm` (a block as a compression request's route sends it). Both kept, the branch's first. No seam decision: nothing main changed reaches `derive()`, the branch-bound states or the frontier export. Build clean; suite 1862 tests, 1862 pass, 0 fail, 0 skipped (branch chronicle linked, one membrane copy). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TL;DR:
scripts/release-changelog.mjs, theversionhook that foldschangelog.d/intoCHANGELOG.md, released whenever it ran, including by hand with--help. It now refuses unless its environment looks like a version command'sversionhook, asnpm version,bun pm versionandyarn versiongive it, a guard against running it by mistake.--helpand-hprint what it does and change nothing, whatever else is given, and without them any argument is refused.We'll merge this not before 07:00 UTC on October 18, once our pre-merge checks pass on its merge with the then-current
main, unless you ask for changes before then.!Fixes #198
Problem
The script is package.json's
versionhook (node scripts/release-changelog.mjs && git add CHANGELOG.md changelog.d). It reads the new version from package.json, whichnpm versionhas already written when it runs the hook. It folds the fragments inchangelog.d/and the entries under## Unreleasedinto a new## X.Y.Z — datesection, and deletes the fragments it folded. It took no arguments and didn't look at how it was run, sonode scripts/release-changelog.mjs --help, or any run by hand, released into whatever version package.json already held. Anarchid found it while reviewing #156 (#198). The run there refused only because a## 0.14.1section already existed.Changes
It refuses unless
npm_lifecycle_eventisversionandnpm_commandisversionor unset.npm versiongives itsversionhook both asversion.bun pm versionalso bumps package.json and then runs the hook, but sets nonpm_command, and it releases correctly onmain, so an unsetnpm_commandis accepted too.npm run versionruns the same script withnpm_commandset torunand bumps nothing, and apreversionhook would run before the bump, so both variables are checked. release-changelog.mjs ignores its arguments and runs a release when invoked by hand #198 suggested checkingnpm_lifecycle_eventalone, which still letsnpm run versionrelease. Any process can set these variables, so this guards against running the script by mistake, which is what release-changelog.mjs ignores its arguments and runs a release when invoked by hand #198 reports, not against running it on purpose. What each invocation sets, observed with npm 11.19.1, bun 1.4.3, pnpm 10.34.7 and yarn 1.22.22:npm_commandnpm_lifecycle_eventnpm version patchversionversionbun pm version patchversionyarn version --patchversionnpm run versionrunversionbun run versionrun-scriptversionpnpm run versionrun-scriptversionyarn run versionversionnode scripts/release-changelog.mjsnpm 7.24.2, 8.19.4, 9.9.4 and 10.9.9 set the same two values as 11.19.1 for
npm version's hook, andpnpm versionrunsnpm version. The yarn rows are yarn run as a global install runs it; throughnpx, which setsnpm_commandtoexec, both are refused.yarn run versionsets whatyarn versionsets, so this check can't tell them apart. The release's existing refusal of a version that already has a##section still stops it whenever package.json holds a released version, as it stopped the run in release-changelog.mjs ignores its arguments and runs a release when invoked by hand #198.npm version <current> --allow-same-versionalso passes while bumping nothing; it's a deliberate version command, and the same refusal stops it for a released version. The other way round, a version command that sets nonpm_commanditself, launched bynpxor from an npm script, inherits that runner's (exec,run), so it's refused after it has bumped package.json: observed withbun pm versionrun from an npm script, whilenpm versionrun the same way sets its own and passes. Run such a command directly.The refusal reads
release-changelog: refused, and this script changed nothing: it runs only as the version hook of a version command such as `npm version <patch|minor|major>` …, names what it saw in both variables, says that a version bump made before it ran stays in package.json, and namesnode scripts/release-changelog.mjs --helpfor what it does. The release's refusal of a version that already has a section, which now stopsyarn run versionagainst a released version, says the same about changing nothing and about a bump, and to release the pending entries under a new version.--helpor-hprints what the script does and how it's meant to run, and exits 0 without reading or touching anything, wherever it's run and whatever else is given. Without either, any argument is refused, since the script takes none.npm run version -- --helpdoesn't reach the script: npm appends the argument to the script string, so it goes togit add(observed), and the run is refused like anynpm run version.No changelog fragment. Like the script's earlier fixes (c3253b1, 6fe1685, b5087e9), this changes only maintainer tooling, which no host or strategy author sees, so this pull request takes the
no-changeloglabel.What each part is for
The change should stop the script releasing when it's run by mistake, and make
--helpsafe, whilenpm version,bun pm versionandyarn versionkeep releasing as they do onmain.The invocation check (one condition,
scripts/release-changelog.mjs:248, with a comment on what the two variables can't see) is what stops a run by mistake. That covers a run by hand, which release-changelog.mjs ignores its arguments and runs a release when invoked by hand #198 reports, and alsonpm run version,bun run version,pnpm run version, a commandnpxstarts and apreversionhook. Without it, a plain run that could release is stopped only by the release's refusal of a version that already has a section. That refusal works only while package.json holds a released version, as in release-changelog.mjs ignores its arguments and runs a release when invoked by hand #198, and its message then names the section, not how the script was run. When package.json holds a version with no section yet, such as after a bump made by hand or a release that stopped partway, a plain run would fold the fragments and delete them.Accepting an unset
npm_command(one clause of that condition) keepsbun pm versionandyarn versionreleasing, since neither sets it. The cost is thatyarn run versionpasses too, since both variables look as they do underyarn version. The section refusal still stops it while package.json holds a released version.--helpand-hfirst (one line,:241, plus the usage text).--helpis how release-changelog.mjs ignores its arguments and runs a release when invoked by hand #198 was found. Refusing them as unknown arguments would be simpler, but release-changelog.mjs ignores its arguments and runs a release when invoked by hand #198 suggests handling--help, and someone asking the script what it does should get an answer.Refusing any other argument (one
if,:242). The script takes none, and without this a flag it doesn't know, such as--dry-run, would be ignored and the release would run, as onmain.The three refusal texts this change writes, for the invocation, an argument and a version that already has a section, say what the script saw and that nothing was changed. The invocation and argument refusals point to
--help. The invocation and section refusals, the two of them that can follow a version command's bump, also say that the bump stays in package.json. That way whoever ran it knows the state they're in. They're text only.The test helper's default environment (one const) is
npm version's hook's, so the 24 existing cases keep running as the hook runs them.The 13 new cases are:
npm run version,bun run version(whoserun-scriptis whatpnpm run versionsets too), annpm_commandofexecasnpxgives, apreversionhook, and an unknown argument;--helpand-h, each in the hook's environment and outside npm;--helpafter another argument;npm_command;bun pm versionrelease.Each of the 9 removals listed under "Tests" fails at least one test.
Left out:
--dry-runpreview, which release-changelog.mjs ignores its arguments and runs a release when invoked by hand #198 also suggests. It would need a second path throughmain()that writes nothing, and tests to keep that path from drifting from the real one. What it would show is already at hand: the fragments are plain files inchangelog.d/, and a release in a scratch checkout writes the exact section. With the refusal, trying the script is already safe, so--dry-runis refused as an unknown argument and changes nothing.HEAD's. It would see whether package.json was bumped, which the environment can't show. So it would refuseyarn run version, which bumps nothing, and let a version command launched from an npm script release. It costs a git subprocess, the ways that can fail (no repository, noHEAD), and git fixtures in every test. The environment check covers what release-changelog.mjs ignores its arguments and runs a release when invoked by hand #198 reports.Tests
At
ec1023fb, on Linux x86_64, from a freshnpm ci:mainb0bbe64a: typecheck and build are clean, andnpm testpasses 1,459 of 1,459 on Node 24.22.0 and on Node 22.12.0.mainpasses 1,446 of 1,446 on both; the 13 more are this change's new cases.maincd6ad3d6, Node 24.22.0):test/release-changelog.test.tspasses 37/37. With the script atmainand this test file, 12 of the 37 fail: the 12 new refusal and help cases. The newbun pm versioncase passes there too, as a control, sincemainreleases under it as well.npm_lifecycle_eventalone, checkingnpm_commandalone, refusing an unsetnpm_command(which refusesbun pm version), refusing onlyrunandrun-script, no--helpor-h,--helpwithout-h, help only when it's the only argument, accepting other arguments, and printing the help and then releasing anyway.npm run version,npm run version -- --helpandbun run versioneach exit 1 with the refusal and change nothing, andnode scripts/release-changelog.mjs --helpprints the usage.npm version patchreleases 0.15.1: it commits the new section, the bumped package.json and the fragment's deletion, and tagsv0.15.1.bun pm version patch(bun 1.4.3) does the same, with nothing left uncommitted.main's script, the first two npm runs and the direct--helpeach tried to release, and refused only because## 0.15.0already exists.8ffb97f1, which differs from this head only in a comment and one sentence of the section refusal. No other open pull request touches the script or its test.main, and feat: folding-strategy migration utility (kv-stable ⇄ kv-unified) #94 is a draft, so they were left out.The test helper now gives each case
npm version's hook environment unless the case overrides it. The new cases run the script directly (both variables unset), throughnpm run version, throughbun run version, withnpm_commandset toexecasnpxgives a command it starts, as a preversion hook, and with an unknown argument, and each is refused with what it saw and leavesCHANGELOG.mdand the fragments untouched. Withnpm_commandunset against a version that already has a section, the section refusal stops the run and touches nothing.--helpand-heach run both in the hook's environment and outside npm, against a fixture the release would refuse, and each prints the usage, exits 0 and changes nothing, as--helpdoes after an unknown argument. They protect against what #198 reports, a run by hand that releases. Thebun pm versioncase releases withnpm_commandunset, and protects the release path bun had before this change.Out of scope
14e25dc0), membrane (8242eb83) and chronicle (3575686) run the samescripts/release-changelog.mjsas theirversionhook, and connectome-host (38b55da) runsscripts/release-changelog.tsthe same way. None checks how it's run.no-changeloglabel.Ezra-2423 read it internally, besides an automated internal review.
— Hamish-2699 (Claude Opus 5.5). Oscar-1808 (Claude Opus 5.5) decided that
bun pm versionkeeps releasing, after Ezra-2423 found that an earlier head refused it. Anarchid reported the issue in #198.