Decision
Switch the version format from 6.0.3-bridge.N.tsgo.M to 6.0.3-tsgo.M.bridge.N at the next stock-or-tsgo base bump (the bump that resets bridge to 0 anyway). Not before — switching at the reset point is zero-friction: no counter-continuity handling, no duplicate bridge.0 ambiguity.
Why
semver prerelease precedence compares dot-separated identifiers left to right. The bump rule resets bridge.N to 0 whenever the tsgo (or stock) base changes, so bridge-first ordering inverts release chronology at every tsgo bump:
semver.gt("6.0.3-bridge.0.tsgo.7.0.3", "6.0.3-bridge.8.tsgo.7.0.2") === false
- tsgo-first ordering is monotone under all three release events (bridge bump / tsgo bump / stock bump): the counter sits to the right of its reset scope, matching the scoping semantics.
Impact: anything that filters upgrades by semver.gt (Renovate / Dependabot / npm-check-updates / taze) — which is the only update channel users have, since TNB is always pinned exactly. At each tsgo bump those tools stop offering the new line, and can actively recommend the old line's tail as an "upgrade" to users who switched manually.
tsgo-first also matches the prior-art invariant (@prisma/engines-version, JetBrains kotlin-wrappers): a counter that resets is never placed left of its reset basis.
Why deferred
Every published line stays valid forever (exact pins), and bridge < tsgo in ASCII, so all old-format versions always sort below all new-format versions — update automation self-heals the moment the first new-format release lands. There is no urgency that justifies a mid-line format break.
Execution checklist (when bumping the next stock/tsgo base)
tools/bump-version.mjs: switch VERSION_RE and the doc header to <stock>-tsgo.<tsgo>.bridge.<N> (accept the old regex read-only for one transition, or seed the new-format version manually).
- First new-format version is
<stock>-tsgo.<M>.bridge.0 (natural reset — no continuity special-casing).
README.md: the example pin (~line 74) and the "version string ends in tsgo.M" sentence (~line 344) — the second becomes literally false under the new format.
- Normal release flow (tag, release.yml, platform subpackages follow the same string unchanged).
- Volar
pnpm-workspace.yaml pin rides the next routine dogfood bump.
Note
A cheaper alternative was considered and rejected: keep bridge-first but stop resetting on tsgo bumps (only stock bumps reset). It is zero-migration and monotone, but keeps the counter left of its scope and weakens bridge.N's meaning.
Decision
Switch the version format from
6.0.3-bridge.N.tsgo.Mto6.0.3-tsgo.M.bridge.Nat the next stock-or-tsgo base bump (the bump that resets bridge to 0 anyway). Not before — switching at the reset point is zero-friction: no counter-continuity handling, no duplicatebridge.0ambiguity.Why
semver prerelease precedence compares dot-separated identifiers left to right. The bump rule resets
bridge.Nto 0 whenever the tsgo (or stock) base changes, so bridge-first ordering inverts release chronology at every tsgo bump:semver.gt("6.0.3-bridge.0.tsgo.7.0.3", "6.0.3-bridge.8.tsgo.7.0.2") === falseImpact: anything that filters upgrades by
semver.gt(Renovate / Dependabot / npm-check-updates / taze) — which is the only update channel users have, since TNB is always pinned exactly. At each tsgo bump those tools stop offering the new line, and can actively recommend the old line's tail as an "upgrade" to users who switched manually.tsgo-first also matches the prior-art invariant (
@prisma/engines-version, JetBrains kotlin-wrappers): a counter that resets is never placed left of its reset basis.Why deferred
Every published line stays valid forever (exact pins), and
bridge<tsgoin ASCII, so all old-format versions always sort below all new-format versions — update automation self-heals the moment the first new-format release lands. There is no urgency that justifies a mid-line format break.Execution checklist (when bumping the next stock/tsgo base)
tools/bump-version.mjs: switchVERSION_REand the doc header to<stock>-tsgo.<tsgo>.bridge.<N>(accept the old regex read-only for one transition, or seed the new-format version manually).<stock>-tsgo.<M>.bridge.0(natural reset — no continuity special-casing).README.md: the example pin (~line 74) and the "version string ends intsgo.M" sentence (~line 344) — the second becomes literally false under the new format.pnpm-workspace.yamlpin rides the next routine dogfood bump.Note
A cheaper alternative was considered and rejected: keep bridge-first but stop resetting on tsgo bumps (only stock bumps reset). It is zero-migration and monotone, but keeps the counter left of its scope and weakens bridge.N's meaning.