Short version: each surface carries its own semver. A lower npm number is
not a “behind” copy of the Python one — it is a separate line for a surface
that deliberately covers different (smaller) scope. See
Python vs TypeScript: the surface boundary.
Each surface versions independently
The PyPI version and the npm version of a package are not kept in lockstep, and one is not derived from the other. They move at their own cadence:- GoldenMatch’s Python line is well into
3.xwhile its TypeScript line is in1.x— the0.x → 1.0.0jump was a one-time “this is now stable” signal, not an attempt to match PyPI. - InferMap’s two lines happen to sit at the same version — parity, not policy.
- GoldenGraph’s TypeScript line leads its Python line — the delta runs the other way.
What a version does — and does not — guarantee
- Within one line, the number is a normal semver contract for that surface: no breaking changes before the next major on that package.
- Across the two lines, the shared operations carry the same public names
and the same computation — but that is guaranteed by a CI gate, not by
the version numbers matching. The
api_paritygate fails the build on any undeclared drift between the Python and TypeScript surfaces, and scorer outputs are held to a 4-decimal cross-language tolerance.
Why not lockstep
Strict lockstep — forcing both lines to the same number always — would be actively misleading here, for two reasons:- The surfaces are deliberately non-equivalent. The TypeScript package is the edge-safe, stateless subset of the Python one (it holds no server-side dataset, ships no distributed engine or web UI). A shared version number would imply an equivalence that does not exist.
- It publishes empty releases. A breaking change in Python would force a no-op major bump on npm even when zero TypeScript code changed, and vice versa — the standard “lockstep tax,” paid to make the number less honest.
docs/versioning-policy.md.
Why there is no “version-lag” gate
It would be easy to add a CI check that flags a TypeScript package for sitting several majors behind its Python sibling — and it would be the wrong check. Under this policy a lagging number is not a defect; an independent line is supposed to sit at its own version. Gating it would flag a non-problem and pressure teams toward the empty-release lockstep this policy rejects. What is gated is the thing that actually matters:api_parity— fails on any undeclared drift in the shared Python↔TypeScript surface (a tool/command/skill added, renamed, or removed on one side without being reflected in the manifest).gen_api_surface— regenerates the capability matrix (versions + tool counts) from the manifests and fails if the published page is stale.