Repository navigation
Migrate to @changesets/cli v3 — one PR carrying the bump plus the config changes v3's defaults require #5296
Description
Activity
os-project-manager commented
on Aug 19, 2026 CollaboratorAuthorMore actionsClaimed and dispatched by the PM loop.
- Session:
session_01HDA9nN6nXQngoQUAAzRdMb - Branch:
claude/issue-5296-changesets-v3 - Worktree:
../objectui-issue-5296(dedicated, per repo — no edits in the shared checkout, nogit stash) - Model:
opus. The contract-review tier (claude-fable-5) was measured unavailable twice today on quota; the 2026-08-13 exemption ("fable 用完了可以用 opus") applies, and this card is a config migration with a rehearsal, not a contract review.
Routing authority, verbatim from the maintainer: "按照你的建议派发执行" — i.e. file the card and dispatch it, which is what this comment records.
File territory this claim covers
package.json,pnpm-lock.yaml,.changeset/config.json,scripts/check-changeset-fixed.mjs,scripts/check-changeset-no-major.mjs,.github/workflows/changeset-release.yml(last one only if item 4 in the body measures a real change), plus one.changeset/*.md.Nothing else. In particular this claim does not cover
.github/workflows/dependabot-auto-merge.yml, thechangesets/action@v1pin, or any of the 250 pending changeset files.Serial constraints handed to the dev seat
- One PR. The bump and the config changes land together or not at all — split, each half is silently wrong until the next release.
- Rehearse in a throwaway clone with its remote removed. Never
origin, never a pushable worktree. - Perform no release. No
changeset publish, no version tag, no release-workflow dispatch, no merging of a Version Packages PR. - Measure, do not reason, for the
changeset version-on-empty-plan question — the answer goes in the PR body either way. - The gate scripts' self-tests must model v3. A self-test that still asserts v2 semantics and passes is a failed run.
Dependabot #4950 stays open and unmerged until
maincarries^3.0.0, at which point it closes itself.
Generated by Claude Code
- Session:
os-project-manager commented
on Aug 19, 2026 CollaboratorAuthorMore actionsCorrection to this card's body — a measurement I published here is wrong.
The body states, under item 1: "Across the current 250 pending changesets, none names it, so the trap does not fire today." That is false. Verified independently against
origin/main(7260a1ed4), not against the dev seat's report:.changeset/no-console-lint-rule.mdnames the privateobject-uibeside four published packages —'@object-ui/app-shell': patch '@object-ui/fields': patch '@object-ui/plugin-detail': patch '@object-ui/runner': patch 'object-ui': patchSo under v3 with
privatePackagesleft undeclared, that is a mixed changeset andchangeset statusexits 1 on today's stock, not on some future one.Why I got it wrong: the private package's name is
object-ui, which is a substring of all 40@object-ui/*scoped names in those same files. Any unanchored search over.changeset/either matches every file or, once filtered, hides the one line that matters. The check had to be anchored —^'object-ui':— and I did not anchor it. One grep away, and I reported the loose result as a measurement.The correction strengthens the card rather than weakening it. The body's argument was "the trap does not fire today, but 'not today' is not a plan, so set the key explicitly." The real position is worse: dependabot's #4950, merged as it stands, would have stopped the release lane on the very next push to
main— with PR CI green, because no PR workflow in this repo runschangeset status. The reason for the card holds; the margin I claimed did not exist.Found by the dev seat during rehearsal, which is where it should have been found — and it is on record here because a card body that stays wrong is worse than one that is visibly corrected.
Generated by Claude Code
os-project-manager commented
on Aug 19, 2026 CollaboratorAuthorMore actions{ "issue": 5296, "status": "done", "branch": "claude/issue-5296-changesets-v3", "pr": "https://github.com/objectstack-ai/objectui/pull/5307", "premise_still_valid": true, "summary": "One draft PR (#5307, head c488fd7) carries the bump to @changesets/cli ^3.0.0 (resolves 3.0.1) with the lockfile, plus all three .changeset/config.json changes: explicit privatePackages {version:true, tag:false}, removal of ___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH.onlyUpdatePeerDependentsWhenOutOfRange, and $schema moved to @changesets/config@4.0.0. Rehearsed in a throwaway clone with no remote, built by git archive from the branch HEAD so its tree hash equals the shipped commit's; changeset status exits 0 and the v3 release plan is identical to the v2 plan release-for-release (45 releases, 40 bumped 17.5.0 to 17.6.0, 249 changesets), and the changeset version dry run wrote 40 package.json bumps plus 40 CHANGELOGs, leaving all ignored packages untouched. ONE MEASUREMENT IN THE ISSUE BODY IS WRONG, in the direction that makes the card more urgent: it says no pending changeset names the private object-ui, so the trap does not fire today. It does fire today - .changeset/no-console-lint-rule.md names object-ui beside four published packages, so the bump alone exits 1 with 'Found mixed changeset no-console-lint-rule' on both changeset status and changeset version, with PR CI green. The card's other count is also off by the README: 250 .md files, 249 actual changesets. .github/workflows/changeset-release.yml is deliberately unchanged - see item 4 below.", "tests": "All at c488fd7 (working tree clean, = origin/claude/issue-5296-changesets-v3), run after the final commit. (1) vitest --project unit over check-changeset-fixed.test.ts, check-changeset-no-major.test.ts, check-changeset-presence.test.ts, merge-queue-reporting.test.ts: 'Test Files 4 passed (4) / Tests 66 passed (66)'. (2) pnpm changeset:check: green, now also printing 'privatePackages declared: version=true, tag=false'. (3) node scripts/check-changeset-presence.mjs: green ('No source of a released package changed in this range, so no changeset is owed', 1 changeset added anyway per repo convention). (4) pnpm check:control-bytes: green, 4688 tracked text files; plus a manual grep -naP over every file I touched: clean. (5) pnpm type-check:scripts: rc 0. (6) pnpm lint:coverage: 46/46 packages, 0 errors. (7) eslint on scripts/check-changeset-fixed.mjs and scripts/__tests__/check-changeset-fixed.test.ts: rc 0. REVERSE VERIFICATION, from the committed state, restored byte-identical to HEAD afterwards: deleting privatePackages turns the gate red (rule 1) and 2 of the new test's 13 cases red; setting version:false turns the gate red (rule 2) - and in that same state the CLI itself fails with the mixed-changeset error, so the gate's verdict coincides with the real one. Rehearsal ran on a tree whose hash (aac0c984a4e75c8c81670aec238a56c0b42f7b6b) equals the shipped commit's tree; the primary checkout IS shallow, so the objectstack#9555 deepen-loop trap is live here, but the two-commit scaffold avoided it (changeset version finished in 9s).", "open_questions": [], "out_of_scope_findings": [ "filed as #5306: root engines are looser than the toolchain now requires - node '>=22' admits 22.0-22.10 / 23.x / 25.x and pnpm '>=9' admits pnpm 9, all rejected by @changesets/cli@3's '^22.11 || ^24 || >=26' and 'pnpm>=10.0.0'. Nothing enforces it today (no engine-strict, packageManager pinned to pnpm@10.31.0, workflows on node-version 22.x), so it is a false declaration rather than a live break; tightening it affects every consumer and is a decision, not a rider on this bump. Filed unassigned, no labels." ] }Measurements per the four items
privatePackages— default flips from{version:true, tag:false}(v2) to{version:false, tag:false}(v3), read out of@changesets/config@4.0.0;version:falsefeedsallowPrivatePackages:falseinto the assembler, i.e. private packages become ignored. Three settings rehearsed on the real stock: absent → exit 1 mixed changeset;{version:false,tag:false}→ exit 1 mixed changeset;{version:true,tag:false}→ exit 0 with a plan identical to v2.tag:falseverified as the right half too —getPublishPlan.mjsfilters private packages out of the npm publish set unconditionally, so only tagging is at stake. Movingobject-uitoignorewas rejected:check-changeset-presence.mjsderives its guarded surface fromfixed, so that would silently stop demanding changesets for the extension's source.- Experimental key —
@changesets/assemble-release-plan@6.0.10referencesonlyUpdatePeerDependentsWhenOutOfRange6 times in its dist,@7.0.0references it 0 times: load-bearing under v2, inert under v3.@changesets/config@4.0.0still parses it, so it would have been accepted-and-dead. A v3 run with the key re-added produced a byte-identical plan. - Engines —
^22.11 || ^24 || >=26,"type": "module". Repo pin does not satisfy it; nothing enforces it today. Reported, not changed → 根 engines 声明比工具链实际要求宽:node ">=22" 放行 22.0–22.10 / 23.x / 25.x,pnpm ">=9" 放行 pnpm 9 —— @changesets/cli@3 全部拒绝 #5306. changeset versionon an empty plan — the exit-code change is real (v2: exit 0warn No unreleased changesets found, exiting.; v3: exit 1No unreleased changesets found.), but a stock of only empty-frontmatter changesets exits 0 under both. And it is unreachable through this workflow:changesets/action@v1resolves to v1.9.0, whosesrc/index.tsand compileddist/index.jsreturn viarunPublishwhen there are no changesets and via"All changesets are empty; not creating PR"when all are empty —runVersionis reached only when at least one changeset carries a release. The action reads changesets with its own bundled@changesets/*, so this bump cannot change which branch it takes. No workflow change.
Non-goals honoured
No release performed (no
changeset publish, no tag, no workflow dispatch, no version PR merged); pre mode not entered;changesets/action@v1pin read but untouched;dependabot-auto-merge.ymland all 249 pre-existing changeset files untouched; #4950 left open and unmerged; no label minted.Beyond the claimed file territory (one file)
scripts/__tests__/check-changeset-fixed.test.tsis new. The card asks for both gate scripts' self-tests to pass and model v3 —check-changeset-fixed.mjshad no self-test at all (onlycheck-changeset-no-majorandcheck-changeset-presencehave one), so that criterion could not otherwise be met.check-changeset-no-major.mjsneeded no change: it hand-parses frontmatter and must not import@changesets/*(it runs on a bare checkout), so nothing in it models v2.
Generated by Claude Code
Generated by Claude Code
os-project-manager commented
on Aug 19, 2026 CollaboratorAuthorMore actionsLanded. PR #5307 went through the merge queue at 08:43 and is on
main.Verified by content on
origin/main(e7c3b3e91), not by sha ancestry — the queue lands as a squash, so ancestry would prove nothing:package.json→"@changesets/cli": "^3.0.0".changeset/config.json→$schemaat@changesets/config@4.0.0,privatePackages: { "version": true, "tag": false }present,___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCHgone
All four items in this card's body are answered on the PR, one of them by correcting the card: the mixed-changeset trap was live on today's stock, not hypothetical. Item 4 came back "no real change" —
changeset-release.ymlis untouched, with the pinned action's branch logic as the reason.Two things this does not yet establish, and I am not claiming them:
- Dependabot chore(deps-dev): bump @changesets/cli from 2.31.1 to 3.0.0 #4950 has not closed itself yet. It was still open on the read after the merge. It should retire on dependabot's next run now that
maincarries^3.0.0; if it doesn't, that gets chased rather than merged by hand. - The release lane has not run under v3 yet.
changeset-release.ymlis the only placechangeset versionis ever invoked, so the push tomainis the first real exercise of this migration. Being watched; a failure there is a direct consequence of this change, not an unrelated event.
Split out rather than ridden in: #5306 (root
engineslooser than the toolchain now requires).
Generated by Claude Code
os-project-manager commented
on Aug 19, 2026 CollaboratorAuthorMore actionsClose-out — both items I left open above are now settled, and the migration is proven on the release lane rather than only in rehearsal.
1. Dependabot #4950 retired itself. Closed
2026-08-19T08:46:02Z, three minutes after #5307 landed, and its branch is gone. Checked two ways (PR state, andgit ls-remotefordependabot/npm_and_yarn/changesets/cli-3.0.0). My note above said it had not closed yet — that was true when written; no intervention was needed.2.
changeset-release.ymlran green under v3. Run32234037039one7c3b3e91, all steps success, including step 11 Create Release Pull Request or Publish to npm.This is the part rehearsal could not prove, so it is worth stating what the live lane actually did. The action took the
hasChangesets → runVersionbranch — it updated the existing version PR #4655 (touched at 09:12:57, the second step 11 finished) and did not publish, which is exactly the branch behaviour the PR body argued fromchangesets/action@v1.9.0's source. Read offorigin/changeset-release/main(8715f50):object-ui(private,packages/vscode-extension)17.6.0, still"private": true@object-ui/types(published)17.6.0.changeset/contentsonly README.md+config.json— all 249 consumedThe private extension bumping in lockstep is the whole point of
privatePackages: { "version": true, "tag": false }. Had the key been left undeclared — i.e. had #4950 been merged as it stood — this run would have failed withFound mixed changeset no-console-lint-ruleinstead, and it would have been the first anyone heard of it. The rehearsal's prediction (40 packages17.5.0 → 17.6.0, 249 changesets consumed,README.mdkept) matches the live output exactly.No release was performed and none will be from this lane by an agent. Version PR #4655 is open and now regenerated under v3; merging it is the release, and that is the maintainer's call, not this loop's. It is reported here, not touched.
Card complete. Split out and still open: #5306 (root
engineslooser than the toolchain now requires).
Generated by Claude Code
Dependabot #4950 proposes
@changesets/cli2.31.1 → 3.0.0. Do not merge it as it stands: a major of this package is a release-tooling migration, and the bump alone leaves config that v3 reads differently.The sibling repo finished this migration today (
objectstack-ai/objectstackepic #9465, landed ase7daea169). Its measurements are reused here rather than re-derived, and the scope below already reflects them — most of what made that migration large does not exist in this repo.What does NOT apply here — measured on
origin/main, not assumedobjectuinever enters pre mode: no.changeset/pre.json, andscripts/check-changeset-no-major.mjscontains zero references to it. There is nocut-rc.yml-style enforced file allowlist. So v3's largest breaking change — consumed prerelease changesets moving into.changeset/pre/— has nothing to hit here. That was roughly three of the sibling epic's five cards; skip all of it.What DOES apply, and none of it is visible to PR CI
privatePackagesdefault flips. v3 stops versioning private packages unless the key is set, and — this is the part that bites — it then treats them as ignored, so a changeset naming one ignored and one non-ignored package becomes a "mixed changeset" thatchangeset statusrefuses outright, exit 1. In the sibling repo that turned a "wrong versions" bump into a "release lane will not run" bump.Measured here:
.changeset/config.json'signorecovers@object-ui/example-*,@object-ui/site,@object-ui/test-support. The private packages not covered areobject-ui-monorepo(the workspace root) andobject-uiatpackages/vscode-extension/package.json— that one would be newly ignored under v3. Across the current 250 pending changesets, none names it, so the trap does not fire today. It fired in the sibling repo from a changeset that landed after the rehearsal snapshot, so "not today" is not a plan: set the key explicitly.___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH.onlyUpdatePeerDependentsWhenOutOfRange— same key as the sibling repo, which measured it inert under v3 (the peer-escalation branch is gone from@changesets/assemble-release-plan@7) but load-bearing under v2. It may therefore be removed only in the same commit that lands the bump, never before.$schemais pinned at@changesets/config@3.1.2; v3 resolves@changesets/config@4.0.0.changeset versionnow exits 1 when nothing is pending (it used to exit 0)..github/workflows/changeset-release.ymldrivesversion: pnpm changeset:version, i.e. plainchangeset version, throughchangesets/action@v1. Establish what that combination does when the action runs version with an empty plan — measure it, do not reason about it.Why CI cannot tell you any of this: nothing in this repo's PR CI runs
changeset statusorchangeset version. The only invocation is insidechangeset-release.yml. A green #4950 proves the workspace still installs; it says nothing about whether a release still works.Scope
One PR carrying all of it together — the bump and the config changes are broken apart, and each half is broken silently until the next release:
package.json:@changesets/cli→^3.0.0(plus the lockfile).changeset/config.json: addprivatePackages, remove the experimental key, move$schemato@changesets/config@4.0.0scripts/check-changeset-fixed.mjsandscripts/check-changeset-no-major.mjs: run their self-tests under v3 and fix whatever models v2 behaviour. A self-test that still asserts v2 semantics is a failed run, not a passing one..github/workflows/changeset-release.yml: only if item 4 measures a real change.Dependabot's #4950 closes itself once
maincarries^3.0.0.Method
Rehearse in a throwaway clone with its remote removed — never against
origin, and never in a pushable worktree. Install@changesets/cli@3.0.0there and drivechangeset statusandchangeset versionagainst the real 250-changeset stock.If a rehearsal hangs: the sibling repo hit
@changesets/git's deepen loop spinning forever on a shallow clone with no reachable remote, and recorded the working scaffold atobjectstack-ai/objectstack#9555(untrack.changeset, re-add it in two commits — tree identical, resolution goes from never-terminating to sub-second). Check whether this checkout is shallow before assuming the tool is stuck.Non-goals
changeset publish, no version tags, no release-workflow dispatch, no merging of a version PR.changesets/action@v1's pin. The sibling repo declined that upgrade for a documented reason (objectstack-ai/objectstack#9208); whether the same reasoning applies here is a separate question, not a rider.Acceptance
changeset statusoutput under v3 (no mixed-changeset error, and the computed plan), and achangeset versiondry run.objectuihas noskip-changesetlabel. An empty-frontmatter changeset is the declaration mechanism here; do not mint a label.