fix(miner): use precision-safe numeric comparison in the CLI update-check semver comparator#3053
Conversation
…heck semver comparator
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
|
Warning 🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨 ⏸️ Gittensory review result - manual review recommendedReview updated: 2026-07-04 10:41:08 UTC
⏸️ Suggested Action - Manual Review Review summary Nits — 5 non-blocking
Review context
Contributor next steps
Signal definitions
🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3053 +/- ##
=======================================
Coverage 96.10% 96.10%
=======================================
Files 261 261
Lines 28895 28895
Branches 10520 10520
=======================================
Hits 27769 27769
Misses 492 492
Partials 634 634 🚀 New features to boost your workflow:
|
Summary
comparePrereleasein bothpackages/gittensory-miner/lib/update-check.jsandpackages/gittensory-mcp/bin/gittensory-mcp.js(two independent, byte-identical copies used by each CLI's own npm-registry upgrade-nudge check) compares numeric semver prerelease identifiers viaNumber(leftId) !== Number(rightId):Number()loses precision pastNumber.MAX_SAFE_INTEGER(2^53-1 = 9007199254740991). Two distinct digit strings past that width can round to the exact same float64 value — e.g."9007199254740993"(2^53+1) is not representable and rounds down to9007199254740992(2^53), the same value"9007199254740992"itself produces.Number(leftId) !== Number(rightId)then readsfalse, so the comparator wrongly reports two genuinely different, orderable numeric identifiers as equal.Fix
Compare numeric identifiers as decimal strings instead: with no leading zeros (semver's own rule for numeric identifiers), a longer digit string is unconditionally the larger number, and equal-length strings compare lexicographically — never through
Number(). Applied identically to both copies so the two CLIs' upgrade-nudge comparisons stay byte-identical, per the existing "mirrors gittensory-mcp" comments already in both files.This is the exact same fix already applied to
compareMcpSemver'scomparePrereleaseinsrc/services/mcp-compatibility.tsin the recently-merged #3049 — that fix's own doc comment explicitly calls out avoidingNumber()for this reason. These two CLI-package copies are separate, independent implementations (not touched by #3049, which only fixed thesrc/services/MCP-compatibility service) that had the identical latent gap.Why no linked issue
Small, self-evident, mechanical fix mirroring an already-merged sibling fix (#3049) in a different pair of files; this repo's
linkedIssuePolicyispreferred, not required, for a change this scoped.Scope
type(scope): short summaryConventional Commit format, for examplefix(api): restore profile access checks.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Validation
git diff --checknpm run actionlintnpm run typechecknpm run test:coveragelocally — see note below onpackages/**scope.npm run test:workersnpm run build:mcpnpm run test:mcp-packnpm run ui:openapi:checknpm run ui:lintnpm run ui:typechecknpm run ui:buildnpm audit --audit-level=moderateIf any required check was skipped, explain why:
packages/**(plus atest/unit/miner-cli.test.tsregression test), nosrc/**API/OpenAPI/UI surface, soui:openapi:check,ui:lint,ui:typecheck, andui:buildare not applicable. Percodecov.yml, coverage is collected by vitest oversrc/**only —packages/**is outside the Codecov patch-coverage gate entirely — but I still added a real regression test (test/unit/miner-cli.test.ts, exercisingpackages/gittensory-miner/lib/update-check.js's exportedcompareSemver) proving the exact precision bug and its fix, and ran the fulltest/unit/miner-cli.test.tssuite (23 tests) clean.packages/gittensory-mcp/bin/gittensory-mcp.jshas no existing unit-test entry points for its internal (non-exported)comparePrerelease/compareSemver— consistent with the file's current test coverage, I verified it only vianpm run build:mcp(node --check, syntax/build validity) plus a manual read-through confirming byte-parity with the now-fixed, testedupdate-check.jscopy.npm run build:minerandnpm run build:mcpboth ran clean (node --checkon every changed file).npm run test:mcp-packhits a Windows-onlyspawnSync("npm", ...)resolution failure locally (noshell: true,npmresolves tonpm.cmdon Windows) — unrelated to this diff, expected to run on the Linux CI runner.test:coveragesuite could not be run clean in my local Windows dev environment for unrelated reasons: several test files depend on tooling not present there (Docker daemon, Python,sentry-cli), and generated-file "stale" checks (openapi.json, cf-typegen, selfhost-env-reference) false-positive on this checkout's CRLF line endings vs. the repo's LF convention — confirmed unrelated to this diff by reproducing them identically on a clean, unmodifiedmain.npm run actionlint,npm run typecheck,npm run test:workers, andnpm auditall ran clean.Safety
UI Evidencesection below. — N/A, no UI changes.UI Evidence
N/A — no UI/frontend/docs changes.
Notes
test/unit/miner-cli.test.ts.