How every parity score is calculated

A port is only worth its claim if it does what the original does, so every score here is measured by running the original library. For each port a harness installs the real published package at a pinned version, starts it as a subprocess in its own runtime, asks it and the Go port the identical questions, and records every disagreement by name. Upstream is the oracle: there are no hand-written expectations to drift, and a new upstream release re-scores the port on its own.

Pick a library below to see its complete record — the exact upstream package and version it was measured against, the exact Go module measured, the stages that run executed, every upstream symbol compared side by side with its Go counterpart, and every individual case with its result.

76
harnesses, including 36 nested package ports
17,399
cases asked of both implementations
15,498
cases in agreement
1,537
mismatches, each named by case id
292
documented deviations
6,811
upstream symbols inventoried

The stages of a run

Every harness executes the same seven stages, defined in parity/HARNESS.md. Each library's page draws these as a graph labelled with that run's real artefacts: the package it installed, the runner files it started, the case files it streamed, and the counts it wrote out.

  1. 1
    Install the pinned upstream oracle. The harness installs the real published package at an exact version — the npm tarball, the PyPI wheel, the gem, the jar. An unpinned oracle would make the score unreproducible, so the version is written into the case files.
  2. 2
    Start the upstream runner. A small program in the upstream ecosystem (node/, python/, java/, ruby/, rust/, elixir/, c/) is started once and kept open, speaking JSON Lines over stdio: one JSON object in per line, exactly one out. The harness never links against the library — it only talks to it.
  3. 3
    Start the Go runner. go/run.go implements the same contract over the Go port. Neither runner may exit on a failing case: it reports ok:false and keeps reading, so one loss never cascades into the rest of the suite.
  4. 4
    Stream every case to both. Cases live in cases/*.json as language-agnostic JSON, each naming the upstream symbol and the Go symbol it exercises. Every case goes to both runners, in order, through the two long-lived processes, with a per-case timeout.
  5. 5
    Compare ok, then value. Failure is compared before value — returning a result where upstream throws is not parity. Values are compared with a normalising deep-equal that treats every JSON number as float64, so 1 and 1.0 agree while a real behavioural difference still shows.
  6. 6
    Classify match, mismatch or deviation. A documented, deliberate difference is counted as a deviation and listed in the port’s API-DEVIATIONS.md; anything else that disagrees is a mismatch, named by case id. A deviation is never quietly counted as a pass.
  7. 7
    Write parity.json and COVERAGE.md. The run rewrites the machine-readable score plus the full upstream API inventory: every exported upstream symbol marked match, differs, missing, extra or untested, with the command that enumerated it. This page is generated from those two files.
What the number means. Measured parity is the share of compared cases where the port and the original library agree. Mismatches are counted and named, deviations are counted separately, and a symbol with no case counts as untested rather than as a pass — so the score cannot be improved by dropping a case or by leaving an API uncovered. Multi-package repos are audited per nested package, each against that package's own upstream. Generated 2026-08-11.

Every measured library

40 of 40
LibraryUpstream oracle (pinned)EcosystemGo moduleCasesMismatchDeviationsSymbolsParityNested ports
algebrasympy@1.14.0pythongithub.com/malcolmston/algebra@v0.8.029227010790.8%
axiosaxios@1.7.9nodegithub.com/malcolmston/axios@v0.3.015102159100.0%
chalkchalk@5.3.0nodegithub.com/malcolmston/chalk v0.4.06809668085.8%
cheeriocheerio@1.0.0nodegithub.com/malcolmston/cheerio v0.0.0-20260810111529-e3282199363b3172910699.4%
Expressexpress@4.21.2nodegithub.com/malcolmston/express v0.4.0 => ../../express1842124498.9%
fastmcpfastmcp@3.4.6pythongithub.com/malcolmston/fastmcp v0.4.01105508150.0%
glTF@gltf-transform/core@4.2.1+gltf-validator@2.0.0-dev.3.10nodegithub.com/malcolmston/gltf v0.0.0-20260810111530-84677d83f1571013012297.0%
Handlebarshandlebars@4.7.8nodegithub.com/malcolmston/handlebars@v0.0.0-20260810111532-be93e3763eef2362907387.7%
Jestexpect@29.7.0 + expect@29.7.0 + jest-mock@29.7.0nodegithub.com/malcolmston/jest v0.0.0-20260810111534-fc19c60ec8b336931277290.9%
JOSEjose@5.9.6nodegithub.com/malcolmston/jose v0.0.0-20260810111536-aa9e56a9a81b157606496.2%
jqjq@1.7.1cgithub.com/malcolmston/jq v0.0.0-20260810111538-69e9503f8dce574581330889.7%
JWTjsonwebtoken@9.0.2nodegithub.com/malcolmston/jwt@v0.3.0155935294.1%
LiveViewphoenix_live_view@1.2.9elixirgithub.com/malcolmston/liveview@v0.3.0942508573.4%
lodashlodash@4.17.21nodegithub.com/malcolmston/lodash v0.0.0-20260810111543-820ef3866dc9624162232897.3%
Lucenelucene@9.11.1javagithub.com/malcolmston/lucene v0.0.0-20260810111545-f6877e2746582375808675.5%
Markdowncommonmark@0.31.2nodegithub.com/malcolmston/markdown v0.1.07011804997.4%
matplotlibmatplotlib@3.10.0pythongithub.com/malcolmston/matplotlib@v0.0.0-20260810111548-1b42add037641034207359.2%
Migraterails/rails activerecord@8.0.2 (sqlite3 gem 2.7.4, SQLite backend)rubygithub.com/malcolmston/migrate v0.3.08642011551.2%
Momentmoment@2.30.1nodegithub.com/malcolmston/moment v0.0.0-20260810111552-e5d96a99ef231,731105523793.9%
morganmorgan@1.10.0nodegithub.com/malcolmston/morgan@v1.2.0983205467.4%
Nodemailernodemailer@6.9.16nodegithub.com/malcolmston/nodemailer v0.0.0-20260810111553-311143ed3171 => ../../nodemailer8680840.0%
numpynumpy@2.2.6pythongithub.com/malcolmston/numpy v0.0.0-20260810111555-4476c82e3a9530111411096.3%
Obanoban@2.23.1elixirgithub.com/malcolmston/oban@v0.0.0-20260810111557-dd5f0675354a1652908782.4%
opencvopencv-python@4.11.0pythongithub.com/malcolmston/opencv v0.8.0751168119077.6%
pandaspandas==2.3.3pythongithub.com/malcolmston/pandas v0.2.021742163980.6%
Passportpassport@0.7.0+passport-local@1.0.0+passport-http@0.3.0+passport-http-bearer@1.0.1nodegithub.com/malcolmston/passport@v0.3.0740281100.0%
PDFKitpdfkit@0.15.1nodegithub.com/malcolmston/pdfkit v0.0.0-20260810111600-857c462c84f511911101506.7%
Prismaprisma@5.22.0nodegithub.com/malcolmston/prisma v0.3.011231011272.3%
puppeteercheerio@1.0.0 + tough-cookie@5.1.2 + node WHATWG fetch/URLnodegithub.com/malcolmston/puppeteer v0.2.01975738897.4%
quartzorg.quartz-scheduler:quartz@2.5.0javagithub.com/malcolmston/quartz@v0.0.0-20260810111605-f2c1d7b7b70a22567010170.2%
reactreact@19.2.7 react-dom@19.2.7nodegithub.com/malcolmston/react@v0.1.04830260100.0%
Redisredis-server@8.2.2cgithub.com/malcolmston/redis v0.3.09331026766.7%
RRulepython-dateutil@2.9.0.post0pythongithub.com/malcolmston/rrule v0.1.02613708485.8%
sequelizesequelize@6.37.8nodegithub.com/malcolmston/sequelize@v0.1.0610384100.0%
sharpsharp@0.33.5nodegithub.com/malcolmston/sharp v0.0.0-20260810111610-e874a7b0b3f832711406765.1%
sledsled@0.34.7rustgithub.com/malcolmston/sled v0.0.0-20260810111611-e90aa95364ed70159998.5%
Socket.IOengine.io-parser@5.2.3; socket.io-parser@4.2.7; socket.io@4.8.1 + socket.io-client@4.8.1nodegithub.com/malcolmston/socketio v0.4.0 => ../../socket.io1655515297.0%
SQLitesqlite3@3.45.3cgithub.com/malcolmston/sqlite v0.2.0428132075469.2%
Streamlitstreamlit==1.61.1pythongithub.com/malcolmston/streamlit v0.3.05515012072.7%
YAMLyaml@2.6.1+yaml-test-suite@da267a5c4782e7361e82889e76c0dc7df0e1e870nodegithub.com/malcolmston/yaml v0.1.01,0717477793.1%
Parity