RFC: Native monorepo versioning - #18
Conversation
Propose built-in, changesets-file-format-compatible release management: recording change intents, workspace version bumping with dependent propagation and fixed/linked groups, changelog generation, and per-package prerelease lines (the capability changesets' global pre mode cannot express), configured in pnpm-workspace.yaml. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 52 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe RFC proposes native pnpm monorepo versioning through changeset-compatible intents, CI coverage checks, recursive release planning, workspace configuration, changelog storage modes, release lanes, snapshots, and shared TypeScript/Rust implementation. ChangesNative monorepo versioning
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
Add a changelog.storage option: "repository" keeps the appended, committed CHANGELOG.md; "registry" commits only the newest release's section and composes the full history at publish time by extending the previously published tarball's changelog. Previous-version selection is semver-based so concurrent release lines chain on their own ancestry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Reviewing the composed section in the release PR duplicates text already reviewed in the intent files. Instead of committing the newest section, keep the consumed intent files through the tag, track them in a small consumed-ids ledger, compose the section at publish time, and delete the files on the next version run. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Before publish, the intent file is the only copy of the changelog prose in registry storage mode, so deletion must wait until the ledgered version is confirmed published — which also self-heals releases that were versioned and tagged but never published. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…y the opt-out Document the preconditions as opt-out guidance (foreign publishers, Renovate/Dependabot visibility via GitHub releases, byte-reproducibility for attested builds), harden intent GC to verify the published tarball actually contains the composed section, and have the migration codemod set repository mode when committed changelogs exist. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The intent files' prose survives in git history after deletion, so a committed changelog records nothing the repository doesn't already hold; the browsability trade-off is a convenience, not a loss of information. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add pnpm change check: every package touched by the branch diff must be named in a pending intent or explicitly declined via a none strategy (an additive extension to the changesets format), with ignore patterns for files that never warrant a release. Expand the Yarn prior-art entry and raise its transitive dependent-decision rule as an open question. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add versioning.maxBump (from Rush's lockedMajor version policy): a per-branch cap that makes a cherry-picked minor/major intent fail the version run on a patch-only maintenance branch instead of silently shipping a feature release. Credit rush change --verify as the original diff-derived coverage enforcement and expand the Rush prior-art entry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Bit converges on recorded-intent versioning independently (soft tags persisted by CI), validating the file-per-intent format by counterexample (.bitmap conflicts on concurrent PRs) and the mechanical dependent propagation default (bit auto-tags dependents with an opt-out). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- cite the 2019 request and the catalog change-detection gap in the motivation, and make the coverage check catalog-aware (a catalog entry change touches every package referencing it) - record Yarn's nextVersion-in-manifest rewrite (yarnpkg/berry#682) as a third case for per-change intent files, and lerna-lite's chase of pnpm-native semantics as an argument for the native approach - new open questions from the threads: rebase-i-style interactive UX, a conventional-commits bridge, and Lerna's two-phase atomic publish Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pnpm change check needs no new configuration: the touched-package computation is the detection behind --filter="[<ref>]", and changed-files-ignore-pattern / test-pattern already express which files never warrant a release. Landing catalog-aware attribution in the shared machinery gives filtered builds and tests the same awareness. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pnpm has no --workspace convention for whole-workspace operations; the recursive form of pnpm version (bare, no bump argument) consumes pending intents, the explicit-bump form keeps its npm-style meaning, and --filter selects a subset of the pending plan (with fixed-group companions and invalidated dependents pulled in), enabling single-product releases from multi-product repositories. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…protocol The version step touches only version fields. Internal dependencies must use the workspace: protocol, whose concrete ranges pnpm already materializes at pack time, so range-rewrite machinery doesn't exist here at all and dependent propagation derives from the protocol modifier (* → any bump, ~ → minor+, ^ → major) instead of range matching. Plain-range or catalog-declared internal deps fail loudly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Explain what the grouping keys do and right-size them: fixed groups are a real need (pnpm ships pacquet + napi in lockstep); ignore shrinks to freezing releasable packages because auto-exclusion of versionless private packages covers changesets' main use case; linked is deferred — rare, surprising jump-to-highest semantics, purely additive later. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Native support for the scheme pnpm's monorepo enforces via a meta-updater plugin: member majors live in the lead's major × 100 band (pnpm 11 → 1100-1199), move independently inside it (including their own breaking changes, unlike a fixed group), and re-base to the band floor when the lead reaches a new stable major, waiting out prerelease lines. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A name glob is the wrong membership primitive: pnpm's own repo hosts products outside the TS epic that share the @pnpm scope (@pnpm/napi, @pnpm/pnpr, @pnpm/pnpr.client). Epics select members with pnpm's existing --filter selector language (name globs, directory selectors, negations), and a package matched by an epic while belonging to a fixed group or prerelease line outside it is a configuration error, so an over-broad glob cannot silently re-base an unrelated product. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ycle The consumed-intent ledger is mode-independent, not a registry-storage detail: pending intents are files whose id is not ledgered on any line, which natively absorbs the .changeset-released mechanism pnpm's repo built on top of changesets — cherry-picked intents release once per line, merge-backs cannot re-apply them, and merge-time file resurrection/deletion becomes harmless by construction. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
PR Summary by QodoRFC: Add native pnpm workspace versioning with per-package prerelease lines
AI Description
Diagram
High-Level Assessment
Files changed (1)
|
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@text/0006-monorepo-versioning.md`:
- Around line 32-47: Add language identifiers to every fenced code block in
text/0006-monorepo-versioning.md, including the command examples and changeset
Markdown example. Use sh for shell commands and markdown for the changeset
content, covering the additional referenced fenced blocks as well.
- Line 99: Update the release planning flow described in
text/0006-monorepo-versioning.md so versioning.maxBump is validated only after
dependent propagation, fixed-group resolution, and epic rebasing have produced
the complete final plan. Reject any final package bump exceeding the configured
cap, and report the maxBump constraint that caused the violation rather than
validating only declared intent types.
- Around line 145-151: Revise the proposal’s ledger and pending-set rules so
intent consumption is scoped by release line and package (or target release),
rather than by globally unique intent ID. Ensure an intent consumed on
release/11.0 remains pending for main until main’s corresponding package release
records its own consumption, preserving the required bump and changelog entry.
- Line 172: The prerelease design must define an authoritative per-package
consumption ledger before implementation, including how package/version entries
map to intent IDs and how pending detection uses that state. Specify the exact
per-package pending-changelog representation under .changeset, then document
deletion and garbage-collection behavior for both the ledger and pending state,
including half-consumed intents and post-graduation cleanup.
- Line 78: The workspace:^ propagation rules must account for 0.x semver
behavior. Update the dependency bump logic described in the internal dependency
propagation section to evaluate the materialized published range and propagate
dependent bumps when a new 0.x version falls outside the previous ^ range,
including 0.2.x to 0.3.x transitions, while preserving existing behavior for
ranges that remain compatible.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 8e495b3c-e19f-458d-8029-e16b8263211b
📒 Files selected for processing (1)
text/0006-monorepo-versioning.md
📜 Review details
🧰 Additional context used
🪛 LanguageTool
text/0006-monorepo-versioning.md
[grammar] ~180-~180: Use a hyphen to join words.
Context: ...ctural, not bugs to wait out: global pre mode and name-keyed data cannot be fixed...
(QB_NEW_EN_HYPHEN)
[grammar] ~211-~211: Use a hyphen to join words.
Context: ...le model this RFC adopts; its global pre mode and name-keyed format are the struc...
(QB_NEW_EN_HYPHEN)
[uncategorized] ~223-~223: The official name of this software platform is spelled with a capital “H”.
Context: ...dencies, or start with built-in plain/github formats only? - **Should `.changeset/c...
(GITHUB)
🪛 markdownlint-cli2 (0.22.1)
text/0006-monorepo-versioning.md
[warning] 32-32: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 63-63: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 157-157: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🔇 Additional comments (3)
text/0006-monorepo-versioning.md (3)
1-24: LGTM!Also applies to: 28-59, 80-98, 100-119, 153-171, 174-218
130-130: 🗄️ Data Integrity & IntegrationThis is an open design choice, not a contradiction. The semver-based previous-version rule is the stated default; the graduation-base question below still needs a decision.
> Likely an incorrect or invalid review comment.
76-76: 🗄️ Data Integrity & IntegrationRegistry-mode changelog composition is already built into
pnpm publish -r. It fetches the previous tarball, prepends the composed section, repacks it, and defers intent cleanup to a laterpnpm version -rrun.> Likely an incorrect or invalid review comment.
…n-level maxBump, per-package ledger - propagation evaluates the materialized semver range instead of a per-modifier rule, keeping 0.x caret semantics correct - maxBump is enforced on the final assembled plan (propagation, fixed groups, epic re-base can raise a bump above declared intents) - ledger consumption is scoped per package, with the explanation of why merge-carried entries cannot suppress a needed bump - the ledger is the single authoritative consumption record for half-consumed intents; deletion follows one rule in both storage modes - language identifiers on the command code fences Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…embership is declared directly in pnpm-workspace.yaml Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…stable/unstable The bare "pre" token sits in npm's bump-keyword slot, where it is itself a valid node-semver increment type, so a mode-toggling "pre enter/exit" sub-verb both reads oddly and shadows a real increment. stable/unstable name the state the packages move to. The commands remain convenience editors for versioning.prereleases in pnpm-workspace.yaml, which stays the reviewable source of truth. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…npm lane command Rename the concept to lanes (Bit's name for the same idea) and move the command out of pnpm version's bump-keyword slot to a root command: pnpm lane alpha --filter <pkg>... # move packages onto the alpha lane pnpm lane main --filter <pkg>... # return them to the main lane pnpm lane # show lane membership main is the reserved default lane, as in Bit. The config key becomes versioning.lanes and stays the reviewable source of truth; the command is a convenience editor for it. Freeing the word "line" also removes an overload — it now refers only to maintenance release lines (11.x). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Mirrors the TypeScript implementation of the native monorepo versioning RFC (pnpm/rfcs#18, plan: #12952) in the Rust stack: - New `pacquet-versioning` crate: the changesets-compatible intent reader/writer (plain-text frontmatter parsing, BOM/CRLF tolerant, embedded human-readable id word lists), the per-package consumed-intents ledger (.changeset/ledger.yaml, same YAML shape the TS side writes), the release-plan assembler (direct bumps, dependent propagation through materialized workspace: ranges evaluated with node-semver, fixed groups, ignore, maxBump against the real version distance, --filter narrowing, per-package prerelease lines with cumulative stable-target escalation and graduation, snapshots), and the applier (manifest version updates, byte-identical changelog composition, ledger append, intent GC with the prerelease retention exemption). Error codes and messages match the TypeScript CLI. - `versioning` settings parsed from pnpm-workspace.yaml onto Config (fixed/ignore/maxBump/prereleases/changelog), mirroring PnpmSettings. - New `pnpm change` / `pnpm change status` command (dialoguer prompts in the interactive path, --bump/--summary scriptable path). - New `pnpm version` command: the bare `-r` form consumes intents (--dry-run, --snapshot [tag], --no-git-checks with the same clean-tree check as publish), and `unstable <tag>` / `stable` manage prerelease lines through the format-preserving workspace manifest writer. The npm-style explicit-bump forms error with a clear not-yet-ported message — they did not exist in pacquet before this change either. - Unit tests mirror the TypeScript engine suite one for one (33 tests), and the integration tests drive the built binary through the full record → plan → release → prerelease → graduation → snapshot flow. The two deploy install futures are boxed because Config grew past clippy's large-future threshold with the new settings field. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…anes Tracks the updated RFC (pnpm/rfcs#18): the concept is now a lane — a named parallel release track, with `main` as the reserved default lane every package is on unless assigned elsewhere (the same model, and name, as Bit's lanes). - `versioning.prereleases` becomes `versioning.lanes` in pnpm-workspace.yaml, in both stacks' settings types. - Lane management moves off `pnpm version` onto a new root `pnpm lane` command: `pnpm lane <name> --filter <pkg>` assigns, `pnpm lane main` returns packages to the default lane, and bare `pnpm lane` prints the membership. The version-argument slot stays reserved for npm's bump grammar, where a mode verb would read as a bump and leave the read side homeless. - Engine internals and messages adopt the lane terminology in both stacks. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ames as aliases Two workspace projects can publish the same npm name — pnpm's own repo is heading there with the TS CLI (pnpm11/pnpm, 11.x) and the Rust CLI (pnpm/npm/pnpm, 12.x) releasing concurrently from one branch. Every serialized format gets a collision rule: intent files accept directory path references (the single additive extension to the changesets format), the ledger records the directory, versioning.lanes keys accept paths, and an ambiguous bare name is a listed-candidates error, never a silent pick. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… atomicity for capable registries Snapshot releases are the producer for the proposed bit-registry lanes (automatic branch publishing): snapshot with the branch name, --batch publish so the lane lands atomically, discard — nothing is consumed or ledgered, so nothing can double-release after merge. The stated hard requirement is registry-side isolation: lane versions must stay out of the main packument, or previous-version changelog chaining and ledger GC confirmation both misbehave. New unresolved questions: basing lane snapshots on the plan target instead of 0.0.0-*, and defaulting the dist-tag / registry lane to the versioning-lane name. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Tracks the RFC update (pnpm/rfcs#18): the versioning engine's unit of identity becomes the workspace-relative project directory, not the package name. Names are aliases resolved against the workspace at read time, and a name that resolves to more than one project is a hard validation error naming the candidate directories — never a silent pick. This is the concrete fix for the name-keying flaw the RFC attributes to changesets, and it is not hypothetical: pnpm's own repo is heading toward two workspace projects publishing the name "pnpm" (the TS CLI on the 11.x line and the Rust CLI on the 12.x line) releasing concurrently from one branch. Directory identity surfaces in each serialized format, in both stacks: - Intent files may reference a package by workspace-relative path (`"./pnpm/npm/pnpm": patch`) alongside bare names — the one additive extension to the changesets format. `pnpm change` writes path references automatically when the chosen name is ambiguous, and its interactive picker labels colliding names with their directory, so contributors never need to know the rule exists. - Ledger entries record the released project directory (`{ dir, intents }`) alongside `package@version`; the bare id-list shape is still read for hand-written entries and attributed by the (unambiguous) name in the key. - `versioning.lanes`, `versioning.fixed`, and `versioning.ignore` accept directory paths, and `pnpm lane` reads/writes them keyed by project. - Changelogs already lived in each project directory. Internal plan assembly, propagation, and changelog composition are now directory-keyed throughout. A `workspace:` dependency naming an ambiguous package is rejected (it cannot be linked at install time anyway). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Snapshot is a publish concern: it mutates nothing durable, and the only work it needs — deriving target versions and rewriting version/workspace: fields — is a pack-time in-memory manifest transform, the same category exportable-manifest already owns. pnpm publish -r --snapshot calls the shared assembler and packs against the derived versions without dirtying the working tree, eliminating the version --snapshot -> publish -> git checkout dance. pnpm version -r is now strictly the durable half. The registry-lane flow collapses to one command: pnpm publish -r --batch --snapshot <branch>. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Tracks the RFC update (pnpm/rfcs#18): pnpm version -r is now strictly the durable half of the release pipeline — it mutates manifests, consumes intents, writes changelogs, and ledgers, and nothing else. Snapshot is a pack-time, in-memory concern that belongs to `pnpm publish` (assemble the plan, pack against the derived versions without touching the working tree), tied to the registry-lanes story; it is left for the publish phase tracked in #12952. Removes the --snapshot flag (and its snapshot-suffix / tag-validation plumbing) from the version command in both stacks, and drops the applier's disk-writing snapshot mode — snapshot must never dirty the working tree. The release-plan assembler keeps its snapshot_suffix capability (the in-memory version-derivation primitive the publish path will call). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ection The RFC is about the client half. Snapshots emit 0.0.0-* prereleases through the ordinary publish path with a dist-tag; ephemeral/branch distribution and retention of throwaway versions are the registry's concern and out of scope. Drop the 'versions must stay outside the main packument' isolation requirement (a single packument is fine) and the registry-lane unresolved questions; keep the client-side atomic-publish question. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@text/0006-monorepo-versioning.md`:
- Line 219: Update the CLI commands list in the monorepo versioning plan to
include the first-class `pnpm change check` command alongside `pnpm change` and
`pnpm change status`, while preserving the existing command infrastructure and
configuration wiring references.
- Line 113: Update the membership validation rules in the versioning
specification to detect any package matched by more than one epic, including
overlapping name or directory selectors. Require validation to fail with an
explicit configuration error identifying the package and conflicting epics,
rather than choosing or silently resolving one band.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: ad7ffc08-f8f7-4732-9323-acb17c5f24bc
📒 Files selected for processing (1)
text/0006-monorepo-versioning.md
📜 Review details
🧰 Additional context used
🪛 LanguageTool
text/0006-monorepo-versioning.md
[style] ~184-~184: Consider an alternative for the overused word “exactly”.
Context: ...alpha.9), but "usually unambiguous" is exactly the reasoning being retired. - **versi...
(EXACTLY_PRECISELY)
[style] ~194-~194: ‘by accident’ might be wordy. Consider a shorter alternative.
Context: ...sitting on disk waiting to be committed by accident in CI. In normal mode pnpm publish -r...
(EN_WORDINESS_PREMIUM_BY_ACCIDENT)
[grammar] ~200-~200: Use a hyphen to join words.
Context: ...ctural, not bugs to wait out: global pre mode and name-keyed data cannot be fixed...
(QB_NEW_EN_HYPHEN)
[grammar] ~231-~231: Use a hyphen to join words.
Context: ...le model this RFC adopts; its global pre mode and name-keyed format are the struc...
(QB_NEW_EN_HYPHEN)
🔇 Additional comments (1)
text/0006-monorepo-versioning.md (1)
1-61: LGTM!Also applies to: 62-79, 80-120, 121-152, 153-188, 189-208, 209-218, 220-252
… change intents, release plans, per-package release lanes (#12953) Implements phases 1-2 of the native monorepo versioning plan (#12952, RFC pnpm/rfcs#18) in both stacks. TypeScript: new @pnpm/releasing.versioning package (intent reader/writer for changesets-compatible .changeset/*.md files with the additive 'none' decline; the committed per-package consumed-intents ledger .changeset/ledger.yaml; the release-plan assembler with direct bumps, dependent propagation via materialized workspace: ranges under real semver semantics, fixed groups, ignore, maxBump enforced against the real version distance, --filter narrowing, per-package release lanes with cumulative stable-target escalation and graduation; the applier with format-preserving version-only manifest updates, changelog composition in repository storage mode, ledger append, and intent GC with the prerelease retention exemption). CLI: pnpm change / change status; bare pnpm version -r (--dry-run, the new root pnpm lane command manages versioning.lanes through the format-preserving workspace manifest writer. The versioning key is typed on PnpmSettings/Config and validated by the workspace manifest reader. Rust: new pacquet-versioning crate mirroring the engine (same file formats, error codes, messages, and output), versioning settings on WorkspaceSettings/Config, and new change/version/lane commands in pacquet-cli. The npm-style pnpm version <bump> forms remain unported in pacquet (they did not exist there before) and error with a clear message. The two deploy install futures are boxed because Config grew past clippy's large-future threshold. Both stacks' engine test suites mirror each other one for one; integration tests drive the real binaries through record -> plan -> release -> lane -> graduation.
…t pnpm change check - A package matched by two different epics (overlapping selectors) now fails validation naming the conflicting epics, closing the ambiguous- band gap the epic + fixed-group / epic + lane rules left open. - Add pnpm change check to the implementation CLI command list. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pnpm/rfcs#18 (merged 2026-07-13) proposes a built-in replacement for @changesets/cli with --bump/--summary flags — exactly the non-interactive authoring surface @changesets/cli lacks. Adding a "Future" section to ADR-0026 so a future agent or human has the context to migrate without re-deriving it: stay on Changesets and write files directly (already agent-friendly, format-compatible with the RFC), migrate when pnpm declares native versioning done, our packageManager pin is already past 11.14, and the GitHub-Action question is settled. No code change.
pnpm/rfcs#18 (merged 2026-07-13) proposes a built-in replacement for @changesets/cli with --bump/--summary flags — exactly the non-interactive authoring surface @changesets/cli lacks. Adding a "Future" section to ADR-0026 so a future agent or human has the context to migrate without re-deriving it: stay on Changesets and write files directly (already agent-friendly, format-compatible with the RFC), migrate when pnpm declares native versioning done, our packageManager pin is already past 11.14, and the GitHub-Action question is settled. No code change.
* Automate releases with Changesets and trusted publishing Releases stop being a manual `npm publish` from a laptop. This wires up Changesets (versioning, changelog generation, CI changeset gate) and an npm trusted-publishing release workflow (OIDC, no long-lived NPM_TOKEN). A changeset is required for user-facing CLI changes; private @scholia/* packages are opted out of versioning. CHANGELOG.md is now generated; the existing 0.1.0 entry is preserved. Tags and GitHub Releases are created by changesets/action. End-to-end verification (a registry-installed patch release) is a post-merge step — it requires the npm-side trusted-publisher registration noted in ADR-0026, plus a real release run. Records the decision in ADR-0026 and notes the workflow in CONTRIBUTING.md. Closes #21 * Document the changeset rule in AGENTS.md Every agent session reads AGENTS.md by default, but the changeset requirement lived only in CONTRIBUTING.md (human-facing) and the CI gate (catch-as-fail after the fact). Adding it to AGENTS.md makes agents aware of the rule before they commit, so they add a changeset for user-facing CLI changes rather than learning about it from a red CI run. No changeset needed for this commit — AGENTS.md is internal. * Show the changeset file format in AGENTS.md `pnpm changeset` is interactive, which an agent can't drive. Replacing the "run pnpm changeset" instruction with the file format directly (frontmatter + summary) lets an agent write the changeset file in one shot instead of burning tokens probing the interactive CLI. No changeset needed — AGENTS.md is internal. * Potential fix for pull request finding 'CodeQL / Workflow does not contain permissions' Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * Record pnpm native versioning as the future state in ADR-0026 pnpm/rfcs#18 (merged 2026-07-13) proposes a built-in replacement for @changesets/cli with --bump/--summary flags — exactly the non-interactive authoring surface @changesets/cli lacks. Adding a "Future" section to ADR-0026 so a future agent or human has the context to migrate without re-deriving it: stay on Changesets and write files directly (already agent-friendly, format-compatible with the RFC), migrate when pnpm declares native versioning done, our packageManager pin is already past 11.14, and the GitHub-Action question is settled. No code change. * Trim AGENTS.md Changesets section to a signpost The file format and rules moved to .changeset/README.md (the canonical home for changeset authoring detail). AGENTS.md is sent in every agent message, so it gets a one-paragraph signpost that links there, not the full file-format example. Cuts ~20 lines / ~800 bytes of always-on context. No agent-visible behaviour change — the detail is one click away at the linked file. * Trim AGENTS.md Changesets section to one line One sentence: what needs a changeset, agents write the file directly, link to the format, link to ADR-0026. The detail lives in .changeset/README.md and the ADR. --------- Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Summary
Proposes built-in release management for pnpm workspaces: recording change intents, bumping versions across the workspace (dependent propagation, fixed/linked groups), writing changelogs, and — the headline capability — per-package prerelease lines, which changesets' workspace-global pre mode structurally cannot express.
The intent-file format is changesets-compatible (
.changeset/*.md), so existing repositories can adopt it by deleting a devDependency, and a differential test oracle against changesets keeps parity honest. Configuration moves intopnpm-workspace.yamlunder aversioning:key.Also proposes registry-backed changelog storage as the default (
repositorymode is the changesets-compatible opt-out): no changelog prose lives in version control — a committed changelog only duplicates what git history and the published tarballs already record. Intent files stay the single copy of the text, tracked through the release tag by a consumed-ids ledger and garbage-collected only once the registry confirms the prose is archived in a published tarball; publish composes the full history by extending the previously published version's changelog.Motivated concretely by the workarounds pnpm's own monorepo needed to release the TypeScript CLI, the Rust CLI (on a
12.0.0-alpha.Nline), and pnpr (on a0.1.0-alpha.Nline) from one changesets workspace — see pnpm/pnpm#12949.Rendered: text/0006-monorepo-versioning.md
Opened as a draft for early feedback; the Unresolved Questions section lists the open bikesheds (command naming, config key, changelog pluggability, git/tagging scope, action/bot story).
Written by an agent (Claude Code, claude-fable-5).
Summary by CodeRabbit