# TypeScript never ships x.y.0: classifying releases the way projects actually version

> Source: <https://dev.to/robzepdev/typescript-never-ships-xy0-classifying-releases-the-way-projects-actually-version-56a>
> Published: 2026-09-22 14:13:13+00:00

I'm building a tracker that tells developers which releases of their stack actually matter.

The first problem wasn't AI or scraping. It was a deceptively simple question:

**Given a version string, how important is this release?**

The naive rule: `x.0.0` is a major, `x.y.0` is a minor, everything else is a patch.

It holds for many libraries, and breaks for some of the most popular ones.

I ended up with one *classification strategy* per project, mapping a version

to one of four buckets: **Spotlight** (you should look), **Latest** (new stuff),

**Digest** (patches, batched weekly) and **Preview** (beta and rc).

`semver`: the default
`x.0.0` → Spotlight, `x.y.0` → Latest, patches → Digest. Vite fits perfectly:

after 8.0.0 came 16 patches, 8.0.1 through 8.0.16, in under three months.

A good tracker shows you 8.0.0 and quietly folds the rest into a digest.

`node`: even majors become LTS
Node's even majors (20, 22, 24) become Long Term Support; odd ones don't.

So an even `x.0.0` goes to Spotlight, while odd majors and `x.y.0` go to Latest.

Same version shape, different meaning.

`typescript`: there is no stable x.y.0
TypeScript doesn't follow SemVer: every `x.y` can contain breaking changes.

And the numbering is unusual:

```
5.9.0-beta → 5.9.1-rc → 5.9.2   ← first stable 5.9
```

A rule that looks for `x.y.0` would never flag TypeScript 5.9 at all.

So the strategy is: **the first stable version of each `x.y` that the sources observed is Spotlight**;

later ones are Digest. The strategy has to look at history, not just the string.

`zerover`: in 0.x the minor breaks
For libraries still in `0.x`, `0.y.0` is effectively a major.

So `0.y.0` → Spotlight, other `0.y.z` → Digest, and from `1.0.0` on it falls back to `semver`.

Every strategy treats pre-releases the same way. Only suffixes that are exactly

`beta` or `rc` (optionally numbered, like `-rc.1`) count as previews.

Canary, nightly, experimental, alpha and hash- or date-stamped builds

(`-rc.0-next-…`) aren't tracked at all. They're the bulk of the noise.

Each strategy is a pure TypeScript function, with no I/O,

tested against real version histories from npm and GitHub.

Real data catches what toy examples don't: TypeScript's `.2`, React's

`-rc.0-next-<hash>` tags, `v`-prefixed tags.

And when a rule is still wrong for an edge case, a manual override lives

in the database and is never overwritten by the next sync.

Classification decides *what deserves your attention*. The next step decides

*what to do about it*: an AI summary of each important release, with breaking changes,

migration steps and an explicit **Action required / Safe to upgrade** verdict.

It will be grounded only in the official release notes. If they don't mention

a breaking change, neither will the summary.

You can see the classification at work on an early preview:

[Vite's release page](https://release-tracker-drab.vercel.app/technologies/vite): 8.0.0 up front,

the 16 patches folded into a digest. Name and domain are still provisional.

I'm building this in public. If your stack has a versioning scheme that would

break these rules, I'd love to hear about it in the comments.
