Repository navigation
build(release): while a breaking entry is pending, a new version must open a line no release has reached - #348
Merged
nissa-seru merged 1 commit intoOct 15, 2026
Conversation
This was referenced Oct 14, 2026
Merged
|
nissa-seru
pushed a commit
to nissa-seru/connectome-host
that referenced
this pull request
Oct 15, 2026
… open a line no release has reached The check anima-research/agent-framework#348 adds, for the host: a dependent's caret range takes the later versions of its line, so a breaking change released as a patch reaches each dependent whose range takes it at its next fresh install. scripts/release-bump.mjs is agent-framework's script, with the version hook's name, release-changelog.ts, in its comments; that fold treats breaking entries as agent-framework's does. It runs first in `preversion`, beside the release-hold check, where npm gives it both versions before anything is written. While a breaking entry is pending (a *.breaking.md fragment, or anything under a Breaking subsection of `## Unreleased`), the new version must open a line no release has reached: one above the current version's line (0.10.x before 1.0, 1.x from 1.0, 0.0.z alone), or the current one when that is a line-opening prerelease. A prerelease in the current line is refused, as is a version below the current line. The refusal says why, where each entry is filed, and the bump to run instead. bun's `bun pm version` runs `preversion` without either version, so while a breaking entry is pending the check refuses every bump there and asks for npm version. CONTRIBUTING gains the same "Breaking changes" bullet as agent-framework's, plus a sentence on `bun pm version`. The release-holds bullet adds that a hold stops releases, not merges, so a hazard in an open pull request is said on that pull request, whose comment thread is this repository's gate. Tests (test/release-bump.test.ts, 16) are agent-framework's under bun:test, running the script under node. The npm cases, with a 120 s limit, run this repository's preversion and version hook (bun scripts/release-changelog.ts): `npm version patch`, `prepatch` and `prerelease` stop with package.json and CHANGELOG.md unchanged and the fragment still pending; `minor` and `preminor` fold it. With bun 1.3.14 and 1.4.3, release-bump, release-holds and release-changelog pass on each. Each piece of the check, removed on its own, fails the tests aimed at it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
nissa-seru
force-pushed
the
build/breaking-not-a-patch
branch
from
October 15, 2026 22:34
32706cd to
d40b888
Compare
… open a line no release has reached A dependent's caret range takes the later versions of its line, so a breaking change released as a patch reaches each dependent whose range takes it at its next fresh install. membrane 0.5.87 went out that way, with a long `### Breaking` section, and installs of agent-framework 0.21.1 (^0.5.78) and context-manager 0.14.0 (^0.5.69) took it. scripts/release-bump.mjs runs first in `preversion`, beside the release-hold check. npm gives that hook npm_old_version and npm_new_version before it writes anything (npm 8, 9, 10 and 11.17, checked with `npm version patch` in a throwaway package), so a refused bump leaves nothing bumped, written or folded. - A breaking entry is pending when changelog.d/ holds a *.breaking.md fragment, or when `## Unreleased` has a subsection whose title starts with "Breaking", in any case, with anything in it. Those are what release-changelog.mjs folds into the release. - A line is a version's minor before 1.0 (0.22.x), its major from 1.0 (1.x), and the version itself for 0.0.z, which ^0.0.z alone takes. While a breaking entry is pending, the new version must open a line no release has reached: one above the current version's, or the current one when that is a line-opening prerelease (a preminor before 1.0, a premajor from 1.0), whose line has no release a dependent's range could hold. The refusal says why, lists where each entry is filed, and gives the bump to run instead, what npm's `minor` or `major` gives, e.g. "npm version minor (0.22.1 to 0.23.0)". - A prerelease counts as the release it leads to, so one in the current line is refused too: no caret range takes a prerelease, but the version hook would fold the entries into its own section, and the next bump would find nothing pending. - A version below the current line is refused as well: dependents hold ranges on the last release, which can sit below an unfinished prerelease (from 0.23.0-0, an explicit 0.22.2 would be the newest 0.22.x). With nothing pending, a run outside `npm version` goes ahead. CONTRIBUTING gains a "Breaking changes" bullet: the rule, filing a breaking change as breaking, and that --ignore-scripts skips this check but also the fold, so the publish workflow refuses the tag for want of a changelog section. The release-holds bullet adds that a hold stops releases, not merges, so a hazard in an open pull request is said on that pull request, whose comment thread is this repository's gate. Tests (test/release-bump.test.ts, 16): what counts as pending, lines before and from 1.0 and for 0.0.z, prereleases, lower versions, runs outside npm version, and npm itself through this repository's preversion and version hook: `npm version patch`, `prepatch` and `prerelease` stop with package.json and CHANGELOG.md unchanged and the fragment still pending; `minor` and `preminor` fold it under the new section's `### Breaking`. release-holds.test.ts's wired project copies release-bump.mjs, since preversion now runs both. Each piece of the check, removed on its own, fails the tests aimed at it. Read before opening by Greta-2425, who ran every bump kind through npm 11.19.0 from 0.22.1, 1.4.2 and four prereleases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
nissa-seru
force-pushed
the
build/breaking-not-a-patch
branch
from
October 15, 2026 22:38
d40b888 to
19cd94a
Compare
nissa-seru
pushed a commit
to nissa-seru/agent-framework
that referenced
this pull request
Oct 16, 2026
…pawn wait and transport listeners, and TypeScript 7 main since cd036e0 brings anima-research#329, anima-research#333, anima-research#273, anima-research#368, anima-research#343, anima-research#340, anima-research#365, anima-research#341, anima-research#352, anima-research#338, anima-research#274 (TypeScript 7), anima-research#347, anima-research#346, anima-research#348 and anima-research#344 (no hang after a signal kill; no uncaught transport or spawn errors). Merged, not rebased, so the commits slimepriestess and the round's readers read stay as they were (Ada-1017, room-203 #105340). `git show --remerge-diff` shows the resolution alone. Conflicts, three files: - src/mcpl/transport.ts: - anima-research#344's listeners for a read error on the child's stdout or stderr go in beside the stdin listener this branch already had. - close() stays this branch's reap (SIGTERM, then SIGKILL, then an explicit failure; one shared attempt). anima-research#344's version waited for an exit that kill() made likely, and its change there, counting a signalCode as an exit (anima-research#331), the reap already does. - src/mcpl/server-connection.ts: - handshake keeps this branch's signature (the abort signal and the negotiated protocolVersion) and its abortable open, and takes anima-research#344's logAfterSettled. That listener takes over 'error' once the initialize race settles, comes off just before a successful return, and stays on a failed handshake's transport. - The race's cleanup keeps both lines: this branch's removal of the abort listener and anima-research#344's logAfterSettled. - The reconnect attempt keeps this branch's reconnectOnce, which reaps the previous launch before another starts and closes a handshaken transport itself when close() has ended the attempt. anima-research#344's version kept that transport for close() with a logging listener. That intent carries over as a listener put on before the attempt's own close, since the transport isn't wired and the handshake's listeners are off. - package.json: devDependencies take both @babel/parser (anima-research#274) and @modelcontextprotocol/server (this branch). Beyond the conflicts, for main's async StdioTransport.spawn (anima-research#344): - SpawnerStdioTransport.start() awaits it. So a modern stdio command that can't be spawned rejects start() with its spawn error, and the connect fails with that error instead of waiting out its 30 s discover probe. This is R1-4's fix (Anarchid's review, room-364 #105270), and its test follows this merge. - The tests that wrap spawn to make a child unreapable await it, in mcp-modern-outcomes, mcp-server-ownership and mcpl-legacy-lifetime. So does the unreapable-close test's own spawn. tsc can't see the old synchronous wrappers, since they reach the child through a cast, and they hung those suites. - anima-research#344's test of a transport kept for close() during a reconnect now follows this branch's reconnectOnce. The attempt closes that transport itself and close() waits for it, so the test resolves the held close before it awaits the attempt. It's retitled for what it checks: the transport logs the errors it reports while it closes, and after. tsc (TypeScript 7) is clean. A trial of this resolution on main bdc5dc4 with anima-research#344's head 8387393, the head that merged, passed every test file on Node 24.21.0 and Node 20.20.2 (J10968). The only failures were 69 in a stale dist/test/mcp-modern-http-2025.test.js that the VPS copy kept from anima-research#337's runs. The full check of this commit follows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
nissa-seru
pushed a commit
to nissa-seru/agent-framework
that referenced
this pull request
Oct 17, 2026
main took anima-research#338 (a dropped turn ends with inference:aborted), anima-research#274 (TypeScript 7), anima-research#347, anima-research#346, anima-research#348 and anima-research#344 since 22bb6ca. The merge has no conflicts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merged
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.
While a breaking entry is pending,
npm versionnow refuses any version that doesn't open a release line no release has reached, before it bumps or writes anything. Before 1.0, a breaking change then goes out in a new minor version (0.22.x to 0.23.0), and from 1.0 in a new major.@antra-tess @Anarchid, this changes how you release, so please look before it merges. It follows #347, the hold check's follow-up, now merged.
Why
A dependent's caret range takes the later versions of its line, so a breaking change released as a patch reaches each dependent whose range takes it at its next fresh install. membrane 0.5.87 opened with a long
### Breakingsection and went out as a patch. agent-framework 0.21.1 depends on^0.5.78and context-manager 0.14.0 on^0.5.69, so installs of either took it at their next resolution. Among its changes: code that no longer typechecks against it, and new defaults for tool mode and stop sequences. Released as 0.6.0, it would have reached each dependent through a range bump of the dependent's own, where its breaking entries are read.The change
scripts/release-bump.mjsruns first inpreversion, beside the release-hold check. npm gives that hooknpm_old_versionandnpm_new_versionbefore it writes anything. npm 8, 9, 10 and 11.17 all do, checked withnpm version patchin a throwaway package. So a refused bump leaves nothing bumped, written or folded.A breaking entry is pending when
changelog.d/holds a*.breaking.mdfragment, or when## UnreleasedinCHANGELOG.mdhas a subsection whose title starts with "Breaking", in any case, with anything in it: bullets, numbered items or prose. Those are whatrelease-changelog.mjsfolds into the release, under that subsection's own title, or### Breakingfor a fragment.Lines: a version's line is its minor before 1.0 (0.22.x), its major from 1.0 (1.x), and the version itself for 0.0.z, which
^0.0.zalone takes. While a breaking entry is pending, the new version must be in a line above the current one's. The exception is a current version that is a prerelease opening its line (a preminor before 1.0, a premajor from 1.0). From one of those, any version of that line goes ahead, finishing it included: no release of that line exists for a dependent's range to hold.Prereleases count as the release they lead to (0.22.2-0 as 0.22.2). So a prerelease in the current line is refused. No caret range takes a prerelease, but the version hook would fold the pending entries into its own section, and the next bump would find nothing pending. No stack package has ever published a prerelease, and the version hook can't fold a finished one today: its existing-section check takes
## 0.23.0-1for## 0.23.0. This change leaves the hook as it is.A version below the current line is refused too. Dependents hold ranges on the last release, which can sit below an unfinished prerelease. From 0.23.0-0, an explicit 0.22.2 would be the newest 0.22.x.
The refusal says why, lists where each pending entry is filed, and gives the bump to run instead. That bump is what npm's
minor, or from 1.0major, gives, which always opens the next line:No publish-workflow backstop.
npm version --ignore-scriptsskips this check, but it skips the fold too. The tag then has no changelog section, and the publish workflow refuses such a tag. A release that gets past both has had its section written by hand.CONTRIBUTING:
npm versionreads, and describes the check;Tests
test/release-bump.test.ts(16) runs the real script aspreversionruns it, in throwaway projects with their own changelogs:Unreleasedcounts (bullets of each kind, numbered and+items, prose, a table), under a title in any case. An empty heading doesn't, nor a released section, nor entries under other subsections. Each pending entry is named once.^0.0.ztakes nothing past itself.npm version: with nothing pending, the check goes ahead. With something pending, it refuses and says why, with either of npm's versions missing.preversionand its version hook:npm version patch,prepatchandprereleasestop withpackage.jsonandCHANGELOG.mdunchanged and the fragment still pending;npm version minorandpreminorbump and fold it under the new section's### Breaking.test/release-holds.test.ts's wired project copiesrelease-bump.mjstoo, sincepreversionnow runs both.Evidence
At
19cd94ae, rebased ontomain7a925e71after #347 and #346 merged, on the Anima VPS. Its tree differs fromd40b888f, the rebase onto #347's merge, only by #346's files, and these runs are atd40b888f:tscare clean, now under TypeScript 7;release-bumppasses 16/16,release-holds26/26 andrelease-changelog24/24;npm testexits 0.The rebase's one conflict was CONTRIBUTING's release bullets, which #347 rewrote. The Breaking changes bullet sits between #347's version bullet and its Release holds bullet, and the sentence about a hazard in an open pull request ends #347's holds bullet.
87c77613, from 0.22.1, 1.4.2, 0.22.2-0, 1.4.0-1, 0.23.0-1 and 2.0.0-0, with a fragment pending. Each refusal leftpackage.jsonunchanged, and every kind she ran answers the same way under this version.Merging
It will merge once its checks pass on its merge with the then-current
main, and not before 2026-10-15 16:00 UTC, unless you'd like changes first.— Ruth-2424 (Claude Opus 5.5)