# Changesets Releases run through [changesets](https://github.com/changesets/changesets). Add one in the same commit as the change it describes: ```bash npm run changeset # describe the change, pick a bump npm run version-packages # apply pending changesets, write CHANGELOGs npm run release # build, then publish ``` `release` builds first because the `.d.ts` files are generated output — they have to exist before packing, or the published packages ship without types. ## Two release groups The ten runtime and adapter packages are a **fixed** group: one version across all of them, always released together. A consumer cannot end up with `@pdsjs/node` built against a different `@pdsjs/core` than it expects, which is the failure mode a repo full of independently-versioned packages invites. Internal `workspace:*` ranges resolve to that exact version at pack time. `@pdsjs/spaces` versions on its own, and must stay out of the fixed group. Inside it, **every** release escalated to a major regardless of what the changesets asked for — a minor and a patch shipped as 2.0.0 with no `### Major Changes` in any changelog. Measured from a 2.0.0 baseline with a single `core: minor` changeset: | fixed group | result | |---|---| | all eleven packages | 3.0.0 | | spaces excluded | 2.1.0 | | no fixed group | 2.1.0 | `@pdsjs/cloudflare` depends on spaces and cannot defer the import — the Durable Object constructor is synchronous — so a spaces bump still propagates to the whole group. That is one major per upstream change to [proposal 0016](https://github.com/bluesky-social/proposals/tree/main/0016-permissioned-data), which is the price of the coupling; it is not a reason to put spaces back in the group and pay a major on every release instead. The lever on the remaining propagation is that cloudflare import, not the release config. `npm run version-packages` refuses to continue if the version moves further than any changeset asked for, because this failure was otherwise invisible until after publishing. ## `@pdsjs/account-ui` is a private devDependency `@pdsjs/account-ui` (the built account-page bundle) is imported by both `@pdsjs/node` (dynamically) and `@pdsjs/cloudflare` (statically, for the synchronous Durable Object constructor), and both are in the fixed group. It is **private** (never published) and declared a **devDependency** of both, on purpose — do not change either. - **Private**, because it is an internal build input: the fixed-group packages inline it at build time and nobody installs it standalone. Being private keeps it out of changeset versioning entirely (`privatePackages.version: false`), so it needs no changeset and has no npm version to reconcile. - **devDependency, not `dependencies`/`peerDependencies`**, for two reasons. First, a published package must not carry a private (unpublished) package in its runtime deps, or consumers cannot install it — a devDependency is not installed by consumers, so this is fine. Second, declaring it a runtime or even an optional peer dependency escalated *every* account-ui change into a whole-group **major**: `workspace:*` pins the exact version, so any bump read as out-of-range and the fixed group carried the escalation with a version number ahead of its changelog. Because it is decoupled, an account-ui change does **not** auto-bump the fixed group. To ship a UI change, add a changeset for the fixed group (e.g. `@pdsjs/core` patch) so those packages republish with the rebuilt bundle. Private packages (the examples) are neither versioned nor published.