scripts/release.mjs rewrites the manifest files, but it deliberately does not touch the lockfiles. Bumping versions and syncing lockfiles are two separate steps, and keeping them separate is what makes each one reviewable. This is the dance that follows every bump.
Two lockfiles, two package managers
The repo is a polyglot workspace. npm owns the TypeScript side via root package.json workspaces; uv owns the Python side via a root pyproject.toml. Each manager resolves its own lockfile:
# Python side, workspace member versions live here uv lock # npm side: workspace @pyrpc/* ranges live here npm install
Neither lockfile records the package versions directly for workspace members the way you might expect, but both record resolutions that change when versions change.
uv.lock: workspace membership
uv lockfile entries for workspace members carry their version, and workspace members also declare dependencies on each other by version. After the bump script rewrites pyproject.toml files, the lockfile's recorded versions are stale. Running uv lock regenerates them. The result is a lockfile diff that is mostly mechanical, but it has to exist, or CI's --locked checks fail.
package-lock: workspace ranges
On the npm side, the bump script rewrites every @pyrpc/* range in every package.json. The lockfile mirrors those ranges at the workspace link level, so npm install must re-run to refresh it. Failing to do so produces a package-lock.json that disagrees with the manifests, the classic "your lockfile is out of date" CI error that always happens on release day.
Why not fold it into the script?
The release script could shell out to uv lock and npm install. It deliberately does not. Lockfile regeneration can pull in unrelated resolution changes (a transitive bump, a hoist reshuffle), and those deserve their own review. Keeping the bump and the sync as separate commits lets a reviewer see "versions changed" and "resolutions refreshed" as two clean diffs instead of one noisy blob.
The discipline
The release flow is a strict sequence: run the bump script, run the lock sync, verify the lockfile diffs are mechanical, then commit. The lockfile dance is not bureaucracy, it is the difference between a release that CI accepts and one that fails at the first --locked gate.

pyRPC