chore(repo): upgrade to Biome 2.5.7 and make the catalog authoritative - #5
Merged
Merged
Conversation
Completes F2, which shipped TypeScript 7 alone because minimumReleaseAge: 4320 still rejected Biome 2.5.7. Waiting the delay out was chosen over the escape hatch the policy itself offers - a reviewed minimumReleaseAgeExclude entry - because the delay's first real encounter is when weakening it would be least defensible. It is enforced live rather than cached: pnpm prints "Lockfile passes supply-chain policies (verified 23h ago)", yet raising the threshold to 5000 minutes failed the same lockfile with ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION across all nine @biomejs/* entries. The binding publish time is the last platform binary's, 2026-08-04 13:28:24 UTC, not the meta-package's 13:23. Raising the catalog alone was not enough, and that is most of this commit. autoInstallPeers is pnpm 11's default, so each config workspace's wide peer range was resolved separately from the catalog, and pnpm kept the version it had already found: configs/biome-config installed Biome 2.5.6 against a root on 2.5.7, and configs/typescript-config installed TypeScript 6.0.3 against a root on 7.0.2. The second was already on main, so F2's own title was untrue at the workspace level. Declaring each peer as an explicit catalog: devDependency makes pnpm satisfy it from the catalog instead of resolving a second copy; install reports Packages: -3 and all four version probes now agree. autoInstallPeers: false was rejected as the alternative, because it changes resolution for every dependency in the workspace to fix two known declarations. A devDependency is invisible to consumers, so neither published manifest changes its public contract. packages/ai-tooling/README.md claimed pnpm 10.28.0, TypeScript 6.0.3 and Biome 2.5.6 - all three false, and shipped, since README.md is in the package's files array. It went stale exactly because F1 and F2 were forbidden to touch that tree and no phase manifest lists the file. It now names the catalog as the single source rather than restating versions, the reasoning F1 used when it stripped the version from twelve $schema URLs. This is the first deliberate edit to the approved Phase 1 tree outside a Stage 1 phase: the --phase 1 --tree digest is pinned nowhere and no test asserts README bytes. Four of the six Stage 1 plan documents change, not the six F2 listed, because the Phase 2 and Phase 4 plans never named a Biome version.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What lands and why
Biome
2.5.6→2.5.7, completing foundation phase F2. F2 shipped TypeScript 7 alone because therepository's own
minimumReleaseAge: 4320still rejected 2.5.7 at the time. The delay expired and thebump is now taken.
Waiting it out was chosen over the escape hatch the policy itself offers — a reviewed
minimumReleaseAgeExcludeentry — because the delay's first real encounter is when weakening it wouldbe least defensible.
Raising the catalog alone was not enough
The bump exposed that the catalog was not actually single-sourcing the toolchain.
autoInstallPeersispnpm 11's default and appears in the lockfile's
settings:block, not in any file this repositorywrote. Each config workspace declares its tool as a peer dependency with a wide range, so pnpm
satisfied that peer by resolving it separately from the catalog — and having already found a
satisfying version, it had no reason to move:
configs/biome-config^2.3.11configs/typescript-config^6.0.0 || ^7.0.0The second row was already on
main. F2 was titled "upgrade to TypeScript 7", yetpnpm -C configs/typescript-config exec tsc --versionansweredVersion 6.0.3, and 24 MB of the oldcompiler sat in the virtual store. Neither workspace defines a script, so nothing executed the stale
tool — which is why it went unnoticed, and precisely the trap the first script added in either
directory would have hit.
Fixed by declaring each peer as an explicit
catalog:devDependency in the samepackage.json, sopnpm satisfies the peer from the catalog instead of resolving a second copy.
autoInstallPeers: falsewas rejected as the alternative: it changes resolution for every dependency in the workspace in order
to fix two known declarations. A devDependency is invisible to consumers of a published package, so
neither manifest changes its public contract — unlike F2's peer-range widening, which did.
packages/ai-tooling/README.mdLine 27 claimed "The workspace pins pnpm
10.28.0, TypeScript6.0.3, Biome2.5.6" — all threealready false. It went stale exactly because F1 and F2 were forbidden to touch
packages/ai-tooling,and no phase manifest lists the file, so no scheduled work would ever have corrected it.
README.mdisin the package's
filesarray, so a publish would have shipped the wrong claim.Rather than restate three versions and set up the same drift again, the line now names the
catalogblock as the single source and keeps only the two facts that do not drift:
engines.nodeand thispackage's own literal pins. Same reasoning F1 applied when it stripped the Biome version from twelve
$schemaURLs.This is the first deliberate change to the approved Phase 1 tree made outside a Stage 1 phase,
authorised by the owner. Safe against the gates for reasons that were checked, not assumed: the
--phase 1 --treecontent digest is pinned nowhere in the repository, no test asserts README bytes(only its presence in
filesand in the tarball), and the Phase 2 plan asserts nothing about it.Plan documents
Four of the six Stage 1 plan documents change, not the six F2's Task 3 listed: the Phase 2 and Phase 4
plans never named a Biome version. Nine
2.5.6occurrences, replaced byte-for-byte — file lengths areunchanged and no CR was introduced.
How it was verified
Every command below exits
0against the committed tree5c0bd65.Three claims were measured rather than assumed.
The delay is enforced live, not cached.
pnpm installprintsLockfile passes supply-chain policies (verified 23h ago), which invites the assumption that a recentpass short-circuits the check — and 23 hours earlier 2.5.7 was still too young. It does not
short-circuit: raising the threshold to 5000 minutes made the very same lockfile fail with
ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION, naming all nine@biomejs/*entries and printing thecomputed cutoff. That failed run left
pnpm-lock.yamlbyte-identical, SHA-25685876dbc5c4d6aa630bad8bef6ebc036fc0a7ec4633b27dc2a65dcca44d4b26a.The binding publish time is 13:28 UTC, not 13:23. The delay applies to all nine
@biomejs/*entries, not to the meta-package alone, and the last platform binary —
@biomejs/cli-linux-arm64@2.5.7— was published 2026-08-04 13:28:24 UTC.
Biome 2.5.7 rewrites nothing. Read-only first, as F2 Task 2 Step 2 requires:
biome check packages/ai-tooling configs/aiexits0over 56 files, andbiome check --write .overthe whole repository reports
No fixes appliedfor all 85. The only change underpackages/ai-toolingis the hand-editedREADME.md; nothing was formatter-driven.Duplicate removal confirmed.
pnpm installreportsPackages: -3, the lockfile now holds exactlyone version of each tool, and all four probes agree — root and both configs answer Biome
2.5.7andtsc
Version 7.0.2.Deliberately not included
check-licenses.mjscounts orphans in the virtual store. While reconciling package counts, thelicence guard reported 89 where the lockfile implied 86.
scripts/check-licenses.mjs:57enumeratesnode_modules/.pnpm— the physical virtual store — rather than the lockfile, and an incrementalpnpm installunlinked the superseded@biomejs/biome@2.5.6,@biomejs/cli-win32-x64@2.5.6andtypescript@6.0.3without deleting their directories. So the guard licence-checked three packagesnothing referenced. Consequences: the printed count drifts upward across incremental installs, a local
run and a CI run of the same commit disagree, and a package long gone from the lockfile can still fail
the build on its licence. A clean reinstall gives the honest figure — 86 here against 87 for
main,the difference being exactly the removed
typescript@6.0.3. Recorded inPROGRESS.mdand left for aseparate decision, because changing what a supply-chain guard reads is its own call.
No changelog fragment. Pure
choretoolchain work with no shipped behaviour change, and thechangelog.d/directory stays dormant until Stage 1 Phase 5 completes — no Stage 1 phase manifestlists it.
No Stage 1 product code. The Stage 1 Phase 1 deferred items and Phase 2 are separate work.