Skip to content

chore!: put all eight packages on one lockstep version at 0.2.0 - #47

Merged
btravers merged 2 commits into
mainfrom
chore/lockstep-versions
Aug 16, 2026
Merged

chore!: put all eight packages on one lockstep version at 0.2.0#47
btravers merged 2 commits into
mainfrom
chore/lockstep-versions

Conversation

@btravers

Copy link
Copy Markdown
Contributor

All eight published packages now share one version number, starting at 0.2.0.

An application installs a kernel and two or three starters together, so "which
@btravstack/http goes with @btravstack/core@0.4.1"
is a question nobody should
have to answer. A changesets fixed group makes every release bump all eight —
Spring Boot's model.

Why 0.2.0

@btravstack/di is the only package with a published history — 0.1.0, from its
standalone repository, before the merge. The unified line has to start above that,
and stays in 0.x because the API still moves: this repo removed Port.many and
withApp in a single afternoon.

before after
@btravstack/di 0.1.0 (published) 0.2.0
@btravstack/core 0.1.0 0.2.0
config · testing · observability · http · temporal · amqp 0.0.0 0.2.0

A latent bug this uncovered

main today would publish six packages at 1.0.0. Not because of anything in
this PR — it is already true. Verified by running changeset version on main
unmodified:

di 0.2.0 | config 1.0.0 | core 1.0.0 | http 1.0.0
testing 1.0.0 | observability 1.0.0 | temporal 1.0.0 | amqp 1.0.0

changesets majors any package whose peerDependency is bumped by a minor, and
from 0.x a major is 1.0.0. Every package here peer-depends on @btravstack/di,
and most on config and core. Isolated to a single changeset: one minor on
@btravstack/config alone drives six unrelated packages to 1.0.0.

So the next pnpm run version on main would have shipped seven packages at 1.0.0
— declaring API stability — while di, the most mature of them, sat at 0.2.0.

What that means going forward, measured

Neither documented escape hatch suppresses the rule
(onlyUpdatePeerDependentsWhenOutOfRange, updateInternalDependents: "out-of-range"
— both tried on changesets 2.31.1, neither changes the result), and the internal
peers cannot become ordinary dependencies: the dual-copy hazard is the reason they
are peers at all.

From 0.2.0 Result
a patch changeset 0.2.1 — the whole group, as intended
a minor changeset 1.0.0 — the whole group

So the first feature release after this one lands on 1.0.0 unless it is overridden
by hand.
This release overrode it: changeset version computed 1.0.0, and the
eight package.json versions and eight CHANGELOG.md headings were rewritten to
0.2.0. That is recorded in CLAUDE.md under a new Versioning section so the
decision is deliberate next time rather than a surprise.

Also in here

  • di's peer range was a hardcoded ^0.1.0 while every other in-repo peer used
    workspace:^. A literal range in a peer field is a pin that goes stale silently
    the first time the dependency is bumped — which lockstep guarantees. It is
    workspace:^ now, which pnpm rewrites to a real ^ range at publish, so a
    consumer still installs their own single copy. CLAUDE.md's paragraph documenting
    the old pin is updated.
  • The 19 pending changesets are consumed into the CHANGELOGs, not squashed
    each was written when its change was fresh and says why.

Gate

format --check, lint, knip, typecheck (28/28), build (9/9) green;
test 24/24 tasks. packages/amqp and examples/order-amqp-worker not run
locally (no Docker daemon). pnpm install --frozen-lockfile is clean — the peer
repin needed no lockfile change.

Nothing is published by this PR. Releases are still manual (pnpm run version,
then pnpm run release); this only sets the policy and the starting line.

An application installs a kernel and two or three starters together, so
'which @btravstack/http goes with @btravstack/core@0.4.1' is a question
nobody should have to answer. A changesets `fixed` group makes every release
bump all eight, whether or not they changed — Spring Boot's model.

@btravstack/di is the only one with a published history (0.1.0, from its
standalone repo). The unified line starts at 0.2.0: above that, and 0.x
because the API still moves.

di's peer range was a hardcoded ^0.1.0 while every other in-repo peer used
workspace:^. That pin would have gone stale silently on the first bump; it is
workspace:^ now, which pnpm rewrites to a real range at publish, so consumers
still install their own copy.

The 19 pending changesets are consumed into the CHANGELOGs rather than
squashed — each was written when its change was fresh.

Recorded in CLAUDE.md, including the constraint that bit here: changesets
majors any package whose peer dependency takes a minor, so from 0.2.0 a patch
gives 0.2.1 but a minor gives 1.0.0. Neither documented escape hatch
suppresses it, and the internal peers cannot become ordinary dependencies.
This release overrode the computed 1.0.0 by hand.
Copilot AI lite review requested due to automatic review settings August 16, 2026 17:09

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR establishes lockstep versioning across the eight published @btravstack/* packages starting at 0.2.0, enforced via a Changesets fixed group, and updates release documentation to make the policy explicit.

Changes:

  • Adds a Changesets fixed group so all eight packages always share one version number.
  • Aligns package versions to 0.2.0 and normalizes internal peer dependency ranges to workspace:^.
  • Consumes existing pending changesets into per-package CHANGELOG.md files and removes the consumed .changeset/*.md entries.

Reviewed changes

Copilot reviewed 37 out of 37 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
packages/testing/package.json Bumps package version to 0.2.0 and repins @btravstack/di peer range to workspace:^.
packages/testing/CHANGELOG.md Adds 0.2.0 changelog content (consumed changesets).
packages/temporal/package.json Bumps package version to 0.2.0 and repins @btravstack/di peer range to workspace:^.
packages/temporal/CHANGELOG.md Adds 0.2.0 changelog content (consumed changesets).
packages/observability/package.json Bumps package version to 0.2.0 and repins @btravstack/di peer range to workspace:^.
packages/observability/CHANGELOG.md Adds 0.2.0 changelog content (consumed changesets).
packages/http/package.json Bumps package version to 0.2.0 and repins @btravstack/di peer range to workspace:^.
packages/http/CHANGELOG.md Adds 0.2.0 changelog content (consumed changesets).
packages/di/package.json Bumps @btravstack/di from 0.1.0 to 0.2.0.
packages/di/CHANGELOG.md Adds 0.2.0 section documenting relevant changes.
packages/core/package.json Bumps @btravstack/core from 0.1.0 to 0.2.0 and repins @btravstack/di peer range to workspace:^.
packages/core/CHANGELOG.md Adds 0.2.0 changelog content (consumed changesets).
packages/config/package.json Bumps package version to 0.2.0 and repins @btravstack/di peer range to workspace:^.
packages/config/CHANGELOG.md Adds 0.2.0 changelog content (consumed changesets).
packages/amqp/package.json Bumps package version to 0.2.0 and repins @btravstack/di peer range to workspace:^.
packages/amqp/CHANGELOG.md Adds 0.2.0 changelog content (consumed changesets).
CLAUDE.md Documents the lockstep versioning policy and rationale.
.changeset/config.json Adds the fixed group containing all eight published packages.
.changeset/unit-signal.md Removed (consumed into CHANGELOGs).
.changeset/unit-module.md Removed (consumed into CHANGELOGs).
.changeset/testing-package.md Removed (consumed into CHANGELOGs).
.changeset/temporal.md Removed (consumed into CHANGELOGs).
.changeset/temporal-starter.md Removed (consumed into CHANGELOGs).
.changeset/runtime-port.md Removed (consumed into CHANGELOGs).
.changeset/run-main-front-door.md Removed (consumed into CHANGELOGs).
.changeset/ponytail-audit.md Removed (consumed into CHANGELOGs).
.changeset/observability.md Removed (consumed into CHANGELOGs).
.changeset/initial-kernel.md Removed (consumed into CHANGELOGs).
.changeset/http.md Removed (consumed into CHANGELOGs).
.changeset/http-unit-defects.md Removed (consumed into CHANGELOGs).
.changeset/http-handler-port.md Removed (consumed into CHANGELOGs).
.changeset/drop-version-const.md Removed (consumed into CHANGELOGs).
.changeset/drain-and-shutdown-fixes.md Removed (consumed into CHANGELOGs).
.changeset/di-declared-pieces.md Removed (consumed into CHANGELOGs).
.changeset/config-and-starters.md Removed (consumed into CHANGELOGs).
.changeset/amqp.md Removed (consumed into CHANGELOGs).
.changeset/amqp-starter.md Removed (consumed into CHANGELOGs).

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/temporal/CHANGELOG.md Outdated
Comment thread packages/testing/CHANGELOG.md Outdated
Comment thread packages/http/CHANGELOG.md Outdated
Comment thread packages/observability/CHANGELOG.md Outdated
Comment thread packages/amqp/CHANGELOG.md Outdated
Comment thread packages/core/CHANGELOG.md Outdated
Comment thread packages/config/CHANGELOG.md Outdated
Comment thread CLAUDE.md Outdated
Rewriting the computed 1.0.0 down to 0.2.0 caught the eight CHANGELOG
headings and the eight package.json versions, but not the 'Updated
dependencies' lists inside seven of those changelogs — which changesets also
writes with the computed version. Left alone they would have published
@btravstack/di@1.0.0 and friends as the dependency line of a 0.2.0 release.

CLAUDE.md now names that third place explicitly, and disambiguates the two
escape hatches: both are under ___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH
and neither is the updateInternalDependencies already in our config.
@btravers
btravers merged commit d47db6a into main Aug 16, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants