Parity overview
Cross-engine conformance summary of @knowvah/dot-engine vs the native Graphviz oracle, one row per track (engine × comparison surface). A report, not a gate. Regenerate: npx tsx test/corpus/parity-report.ts (after refreshing the per-track surveys it reads).
conformant / pass is the ±0.01 deterministic-tolerance verdict per docs/conformance.md — numeric payloads agree within tolerance and non-numeric content is exactly equal — not byte equality. errors = oracle-error + port-error/errored + timeout (excluded from scoring). accepted = documented won't-fix deltas (0 for engines without an acceptance list).
Tracks
| track | surveyed | conformant / pass | diverged | accepted | errors | pass % |
|---|---|---|---|---|---|---|
| dot (SVG) | 939 | 910 | 0 | 17 | 12 | 96.9% |
| dot (xdot) | 905 | 905 | 0 | 0 | 0 | 100.0% |
| dot (json) | 905 | 903 | 0 | 2 | 0 | 99.8% |
| circo (xdot) | 910 | 902 | 0 | 4 | 4 | 99.1% |
| twopi (xdot) | 910 | 893 | 0 | 16 | 1 | 98.1% |
| osage (xdot) | 905 | 897 | 0 | 8 | 0 | 99.1% |
| patchwork (xdot) | 905 | 905 | 0 | 0 | 0 | 100.0% |
| dot (imagemap) | 905 | 905 | 0 | 0 | 0 | 100.0% |
| dot (plain) | 905 | 897 | 0 | 8 | 0 | 99.1% |
| circo (plain) | 905 | 887 | 0 | 13 | 5 | 98.0% |
| twopi (plain) | 905 | 881 | 0 | 23 | 1 | 97.3% |
| osage (plain) | 905 | 889 | 0 | 16 | 0 | 98.2% |
| patchwork (plain) | 905 | 897 | 0 | 8 | 0 | 99.1% |
| dot (dot) | 905 | 905 | 0 | 0 | 0 | 100.0% |
| circo (json) | 905 | 894 | 0 | 6 | 5 | 98.8% |
| twopi (json) | 905 | 887 | 0 | 17 | 1 | 98.0% |
| osage (json) | 905 | 892 | 0 | 13 | 0 | 98.6% |
| patchwork (json) | 905 | 903 | 0 | 2 | 0 | 99.8% |
| circo (imagemap) | 905 | 900 | 0 | 0 | 5 | 99.4% |
| twopi (imagemap) | 905 | 904 | 0 | 0 | 1 | 99.9% |
| osage (imagemap) | 905 | 904 | 0 | 1 | 0 | 99.9% |
| patchwork (imagemap) | 905 | 905 | 0 | 0 | 0 | 100.0% |
Iterative engines (±0.5 characterization)
neato/fdp/sfdp are iterative force-directed solvers whose results depend on floating-point accumulation (FMA, Math.pow, libm) that JavaScript cannot reproduce bit-for-bit — accepted class A1. These rows are compared at a ±0.5pt tolerance to characterize behavior, not to gate byte-fidelity; do not read their pass % against the deterministic bar above.
| track | surveyed | conformant / pass | diverged | accepted | errors | pass % |
|---|---|---|---|---|---|---|
| neato (xdot) | 910 | 826 | 0 | 83 | 1 | 90.8% |
| fdp (xdot) | 910 | 703 | 0 | 204 | 3 | 77.3% |
| sfdp (xdot) | 910 | 619 | 0 | 290 | 1 | 68.0% |
| neato (plain) | 905 | 896 | 0 | 8 | 1 | 99.0% |
| fdp (plain) | 905 | 893 | 0 | 8 | 4 | 98.7% |
| sfdp (plain) | 905 | 896 | 0 | 8 | 1 | 99.0% |
| neato (json) | 910 | 825 | 0 | 84 | 1 | 90.7% |
| fdp (json) | 910 | 701 | 0 | 205 | 4 | 77.0% |
| sfdp (json) | 910 | 617 | 0 | 292 | 1 | 67.8% |
| neato (imagemap) | 910 | 902 | 0 | 7 | 1 | 99.1% |
| fdp (imagemap) | 905 | 883 | 0 | 18 | 4 | 97.6% |
| sfdp (imagemap) | 910 | 880 | 0 | 29 | 1 | 96.7% |
Dot output formats (SVG · xdot · json)
How faithfully the port renders each input across all three deterministic dot outputs, joined by id. xdot and json survey the SVG-conformant roster, so this is the intersection (905 inputs); an input is conformant in all three only when every format agrees with the oracle within tolerance.
| status across SVG · xdot · json | count | % |
|---|---|---|
| conformant in all three | 903 | 99.8% |
| accepted (won't-fix) in ≥1, diverged in none | 2 | 0.2% |
| diverged / errored in ≥1 | 0 | 0.0% |
Per-format status of the ids not conformant in all three:
| id | SVG | xdot | json |
|---|---|---|---|
share-Latin1 | conformant | conformant | accepted |
windows-Latin1 | conformant | conformant | accepted |
Engine exclusions
Graphs NOT walked on the listed engines, because the engine cannot meaningfully exercise them. These carry no verdict — they are not accepted divergences. An entry requires all three of: structurally degenerate for that engine, expensive enough that skipping it buys something, and covered on a cheaper track. Source of truth: test/corpus/engine-exclusions.json.
| id | engines | why it measures nothing | covered instead by |
|---|---|---|---|
2222 | neato, fdp, sfdp, circo, twopi | 28,303 node declarations and ZERO edges, so every node is its own connected component. With no edges there are no springs to relax, no circular ordering and no radial tree: all five engines delegate to the engine-INDEPENDENT component packer (lib/pack), whose polyomino packing is visible in the output as a grid (861 distinct x by 1632 distinct y). Their own algorithms never run — confirmed by all four measured oracle outputs being BYTE-IDENTICAL (16,390,698 bytes, cmp-verified). Ruled out a layout= attribute override (none) and fixed pos= (none). | The four dot tracks (SVG, xdot, json, imagemap), where 2222 is conformant and the native render takes 6s. dot does NOT use lib/pack — its output differs from the neato-family — so dot coverage exercises a different disconnected-component path, and the packer path itself remains covered by the 157 other edgeless corpus graphs, all of which are cheap (<=7KB). |
Goldens
247 pinned golden inputs (test/golden/manifest.json), by engine:
| engine | goldens |
|---|---|
| dot | 178 |
| neato | 18 |
| fdp | 7 |
| sfdp | 6 |
| circo | 15 |
| twopi | 8 |
| osage | 7 |
| patchwork | 8 |
The golden xdot suite gates these in CI (test/golden/xdot-suite.test.ts).
Per-track dashboards
- PARITY-dot.md — dot (SVG) dashboard (
dashboard.ts) - PARITY-XDOT.md — dot (xdot) dashboard (
xdot-dashboard.ts) - PARITY-JSON.md — dot (json) dashboard (
json-dashboard.ts) - PARITY-MAP.md — dot (imagemap) dashboard (
map-dashboard.ts) - PARITY-circo.md — circo (xdot) dashboard (
parity-report.ts) - PARITY-twopi.md — twopi (xdot) dashboard (
parity-report.ts) - PARITY-osage.md — osage (xdot) dashboard (
parity-report.ts) - PARITY-patchwork.md — patchwork (xdot) dashboard (
parity-report.ts) - PARITY-neato.md — neato (xdot) dashboard (
parity-report.ts) - PARITY-fdp.md — fdp (xdot) dashboard (
parity-report.ts) - PARITY-sfdp.md — sfdp (xdot) dashboard (
parity-report.ts) - PARITY-dot-plain.md — dot (plain) dashboard (
parity-report.ts) - PARITY-circo-plain.md — circo (plain) dashboard (
parity-report.ts) - PARITY-twopi-plain.md — twopi (plain) dashboard (
parity-report.ts) - PARITY-osage-plain.md — osage (plain) dashboard (
parity-report.ts) - PARITY-patchwork-plain.md — patchwork (plain) dashboard (
parity-report.ts) - PARITY-neato-plain.md — neato (plain) dashboard (
parity-report.ts) - PARITY-fdp-plain.md — fdp (plain) dashboard (
parity-report.ts) - PARITY-sfdp-plain.md — sfdp (plain) dashboard (
parity-report.ts) - PARITY-circo-json.md — circo (json) dashboard (
parity-report.ts) - PARITY-twopi-json.md — twopi (json) dashboard (
parity-report.ts) - PARITY-osage-json.md — osage (json) dashboard (
parity-report.ts) - PARITY-patchwork-json.md — patchwork (json) dashboard (
parity-report.ts) - PARITY-neato-json.md — neato (json) dashboard (
parity-report.ts) - PARITY-fdp-json.md — fdp (json) dashboard (
parity-report.ts) - PARITY-sfdp-json.md — sfdp (json) dashboard (
parity-report.ts) - PARITY-circo-map.md — circo (imagemap) dashboard (
parity-report.ts) - PARITY-twopi-map.md — twopi (imagemap) dashboard (
parity-report.ts) - PARITY-osage-map.md — osage (imagemap) dashboard (
parity-report.ts) - PARITY-patchwork-map.md — patchwork (imagemap) dashboard (
parity-report.ts) - PARITY-neato-map.md — neato (imagemap) dashboard (
parity-report.ts) - PARITY-fdp-map.md — fdp (imagemap) dashboard (
parity-report.ts) - PARITY-sfdp-map.md — sfdp (imagemap) dashboard (
parity-report.ts)