Adversarial pass on the previous commit. The warning only inspected
`workspace:` ranges, so it missed the OTHER way a cross-scope pin goes stale: a
literal version range naming a package in another scope. `bumpPackages` rewrites
literal ranges for in-scope packages only, so such a pin survives every bump —
`scope=all` publishes the canary and the artifact still resolves the dependency's
last stable release, silently, which is the exact failure this warning exists to
surface.
`findCrossScopeWorkspaceDeps` becomes `findCrossScopePins`, reporting both shapes
tagged with a `reason`, and the literal case carries its own remedy (convert to
`workspace:`) instead of the useless "re-run with scope=all".
No such pin exists in the tree today — every cross-scope edge is `workspace:` —
so this closes a latent hole rather than a live one, in the one place a future
refactor would reintroduce it.
Also documents the multi-scope partial-failure mode in prerelease.ts: the
cross-scope graph has cycles, so no publish order avoids a package shipping
before the same-run version it pins, and npm's no-republish rule means a failed
run must be retried under a new suffix.
Two release-tooling defects turned a pair of canary publishes into a broken
combination for consumers (a canary runtime resolving the last STABLE
channels-intelligence, which still called the removed `channel.addAdapter`).
1. Canary versions were prereleases of an ALREADY-PUBLISHED version. A stable
release leaves the working tree on the version it just published, and
computePrereleaseVersion appended `-canary.<id>` to exactly that, so the
canary sorted BELOW its own release (`0.2.1-canary.x < 0.2.1`): the `canary`
dist-tag pointed behind `latest`, and no dependent range could ever resolve
it. Base the canary on the next unreleased version instead (patch bump,
reusing computeNextStableVersion's prerelease rule).
2. A canary published one scope at a time, but the scopes are only independent
on the version axis. `@copilotkit/runtime` carries
`"@copilotkit/channels-intelligence": "workspace:*"`, and `pnpm pack`
resolves that against the working tree — so a `monorepo` canary pinned the
channels family to its last stable release even when the commit changed both
sides of the contract. Add a prerelease-only `all` selector that bumps and
publishes every scope from one commit under one shared canary id, and warn
loudly when a single-scope canary leaves a cross-scope pin behind.
`all` is a selector, never a scope: stable releases stay single-scope (their
tag, release branch, and npm/Slack links all derive from one scope name), which
publish-release.yml enforces in both jobs and the dropdown guard enforces per
workflow.
bumpPackages was overwriting internal dependency references like
"workspace:*" with the new version string, causing pnpm to try
resolving the version from the npm registry (which fails because
it hasn't been published yet). Now skips deps using workspace protocol.
Each release scope has its own packages, version source, and
independent version track:
- monorepo: 12 core @copilotkit/* packages (shared version)
- cli: copilotkit CLI (independent version)
- angular: @copilotkitnext/angular (independent version)
Branch pattern is now release/publish/<scope>/v<version> and git
tags use <scope>/v<version> for non-monorepo scopes.
- Replace import.meta.dirname (Node 21.2+) with fileURLToPath
workaround for Node 20 compatibility
- Rename workflows to release / pre, release / publish, release /
create-pr so they group together in the Actions UI
- Fix semver regex to allow hyphens in prerelease identifiers
- Add unit tests for parseSemver, computeNextStableVersion,
computePrereleaseVersion
Replace changesets with a simple, stateless release system:
Stable release (PR-gated):
Actions → "create release PR" → pick patch/minor/major → CI runs →
merge → publishes to npm, creates git tag + GitHub Release
Prerelease (ad-hoc):
Actions → "publish / prerelease" → publishes current version with
-canary.<suffix|timestamp> to npm under "canary" tag
Key features:
- All 12 core @copilotkit/* packages share a single version
- AI-generated release notes via Anthropic API
- Notion draft for team editing before merge
- Notion link commented on the release PR
- Guards: concurrent release PR check, version > npm check, clean
semver check, canary-only prerelease tag
- release/publish/v* branch pattern (hard to accidentally match)
- TypeScript throughout (tsx runner)
- release.config.json with versionedTogether/versionedIndependently