v2.0.1
[2.0.1] — 2026-08-14 — the floor gets a gate, and the toolchain catches up
Nothing that runs has changed. All 17 dist/**/*.js files are byte-identical to
what 2.0.0 published — verified by checksumming every file in both tarballs, not by
reading the diff. No tool was added, removed or altered; no payload, argument or
structuredContent shape moved. A consumer on 2.0.0 gains no behaviour by upgrading.
What this release actually carries is the work of
EPIC-5's last three stories, none of which cut a version of its
own: a gate that stops the Node floor drifting, a dependency bot, and a compiler decision.
Against the published 2.0.0 tarball exactly four things differ — three .js.map files
(source-position attribution, from the new compiler), two reworded sentences in
README.md, and the devDependencies block of package.json, which npm does not install
for consumers.
It is a patch because docs/RELEASE.md §Step 1 measures semver against the
tool surface rather than the diff size, and the tool surface is untouched.
Added
-
release:checknow guards the Node floor. It comparespackage.json
engines.node— the canonical value — against every floor claim inREADME.mdand
docs/SETUP.md, and fails when they disagree or when an artifact states no floor at
all. The floor was stated in three places and compared by nothing, which is the
LESSONS 4 shape that letpackage-lock.jsonsit eight releases behind its
version string (US-5.2).A floor claim is defined narrowly and the narrowness is the contract: a semver
immediately preceded by>=or≥, on a line mentioning Node. The operator is what
separates the floor from the other Node versions in the same prose —AbortSignal.any's
20.3.0is written "landed in 20.3.0", never ">= 20.3.0", so it is excluded without
being special-cased. The practical consequence when the floor next moves: prose about
an old floor must not use the operator form — "the old 20.6.0 floor", not "the old
>= 20.6.0floor". Two README sentences were rephrased accordingly; no claim changed
meaning. CI pins in.github/workflows/are deliberately not checked, because they bind
nobody outside CI andpublishdiffers from the floor on purpose
(LESSONS 7).Ten tests, watched go red before the implementation existed, plus a mutation of the real
docs/SETUP.md—grep-confirmed on disk before the red result was believed
(LESSONS 1) — proving the gate names the exact file, line and both values. -
.github/dependabot.yml— weekly npm updates with minor and patch grouped into one
PR, so currency stops depending on someone remembering to runnpm outdated
(US-5.3). Twoignore
entries, each carrying the reason it exists and the condition under which it should be
removed:@types/nodemajors (see below) andtypescriptmajors (TypeScript 7 is a native
compiler rewrite and gets its own decision in
US-5.4, rather than riding intomain
inside a grouped refresh).Its header states plainly what a green Dependabot PR does not prove: no workflow runs
on a pull request here —release.ymlfires on av*tag and nothing else — so those PRs
arrive with no typecheck, no test run and no tarball verification, and the file lists the
commands to run locally instead. Enabling the bot without saying so would ship a false
signal.
Changed
-
Development toolchain brought current:
vitest3.2.7 → 4.1.10 andtsx4.23.6 →
4.23.12 (in-range, lockfile only —package.json's^4.19.0did not move). The suite is
unchanged at 20 files / 439 tests, 1 skipped, measured against a baseline taken
immediately before the bump: a count that dropped would have meant a silently-skipped
suite rather than a clean upgrade.vitest.config.ts'ssrc/-anchoredinclude
(CONTEXT D13) was re-proven under the major by planting a decoy test under
.claude/worktrees/and confirming it is still not collected — a major version is exactly
when a default changes underneath you. -
@types/nodedeliberately stays on the Node floor's major and is now a written rule
rather than a pin that looks like neglect (CONTEXT D28). Types newer than the
floor lettscaccept calls to APIs the supported runtime does not have: the build stays
green and the failure lands on the user, at run time — the same shape
CONTEXT D5 raised the floor to fix.npm outdatedwill keep reporting
@types/nodeas behind, and that output is now expected. -
typescript5.9.3 → 7.0.2 — the native compiler port
(CONTEXT D29,
US-5.4).tscis this repo's build,
not only its typechecker —binpoints intodist/andfilespublishes it — so the
emit was compared before the decision rather than after: all 17dist/**/*.jsfiles are
byte-identical to the 5.9.3 build, verified by checksumming every file in both trees.Three
.js.mapfiles differ —core/client,core/errorsandserver, which are
exactly the three sources using a parameter default or a parameter property — and only in
which source positions the generated defaults and field assignments are attributed to. The
JavaScript at those sites is character-for-character the same..js.mapships, so the
tarball does change in debug metadata; it stays at 54 entries and nothing that runs is
affected.Typecheck is clean on both tsconfigs, and each was mutation-tested to confirm it still
catches errors — a new compiler exiting 0 proves it ran, not that it checked. The reason
to move is measured rather than assumed: typecheck~1428 ms → ~503 ms, full build
~1412 ms → ~393 ms(~3.6×). Without a number like that the decision would have been
to stay, since a compiler emitting the same JavaScript buys nothing on its own. -
.github/dependabot.ymldrops thetypescriptmajorsignoreadded one story earlier,
which is what its own comment instructed the deciding commit to do. -
docs/RELEASE.md §Step 2 and §Step 5 describe the floor as a second set of
files that must move together, and therelease:checkfailure table gains three rows.
docs/README.md's pre-commit checklist gains a floor item — a floor change is
not a version bump, so nothing else in that list would have caught one.