| description | Both engines over the same contracts, with what each reported -- including the cases where api-verity-lab loses to oasdiff. Reproducible from committed evidence. |
|---|
Both engines over the same contracts, with what each reported.
The interesting column is the one where oasdiff found something this tool did not. A benchmark that only wins reads as marketing, and the reader who notices that stops believing everything else in the repository.
Rule ids do not align across the two vocabularies -- that is what migrating from oasdiff is about -- so nothing here matches finding against finding. The comparison is at operation granularity: for each pair of contracts, which operations did each tool flag as breaking?
That question has a checkable answer. It is still not a correctness measure. Two tools disagreeing about an operation usually means they model different things, and either may be right; a count is a fact about coverage, not about being correct. Where they disagree below, the other tool's own wording is quoted so a reader can judge rather than take a number.
Every finding from both tools is listed, at every severity, with the severity
each one assigned. An earlier version of this page compared only this tool's
ERROR findings against oasdiff's output and published two changes as gaps
that were not gaps -- both were reported here, one at WARN and one at INFO.
A benchmark that invents a gap is the same defect as one that hides a gap, and
more embarrassing.
Once both tools have found the same change, the interesting comparison is what
each one called it. oasdiff breaking reports only what it considers
breaking; this tool's breaking reports everything the diff produced, with a
severity. The two lists are deliberately not a two-column table: putting one
tool's n-th finding beside the other's implies they correspond, and the
vocabularies differ in granularity, so they often do not. Read them as two
accounts of the same pair of documents.
Only OpenAPI pairs are compared. oasdiff reads OpenAPI, and running it against
a .proto to report that it found nothing would be a rigged comparison.
- Run: 2026-09-10T10:10:39.379176+00:00
- api-verity-lab: 0.2.0
- oasdiff: module v1.31.0, self-reported
oasdiff version main(go installbuilds without the version ldflag, so the binary does not know which tag it came from -- the module version is the one that was asked for) - Specmatic: not run -- needs a JVM, and this machine has none. Listed rather than left out: a benchmark naming two competitors and measuring one has said something about the second by omission
apis/versioned/v1.yaml against apis/versioned/v2.yaml
| This tool | oasdiff | |
|---|---|---|
| Breaking findings | 8 | 6 |
| Operations flagged | 4 | 3 |
| Operations both flagged | 3 | 3 |
Operations only this tool flagged: GET /users/{id}
DELETE /users/{id} — 1 here, 1 from oasdiff
This tool
BRK-OP-REMOVED(ERROR) — operation 'DELETE /users/{id}' was removed
oasdiff
api-removed-without-deprecation(error) — api removed without deprecation
GET /users — 4 here, 3 from oasdiff
This tool
BRK-PARAM-REQUIRED(ERROR) — parameter 'limit' (query) requiredness changed False -> TrueBRK-CONSTRAINT-TIGHTENED(ERROR) — request parameter 'limit': constraint 'minimum' changed 1 -> 10BRK-CONSTRAINT-TIGHTENED(ERROR) — request parameter 'limit': constraint 'maximum' changed 100 -> 50BRK-ENUM-NARROWED-RESPONSE(WARN) — response 200 body (application/json)[].role: enum changed (removed ['guest'], added [])
oasdiff
request-parameter-became-required(error) — thequeryrequest parameterlimitbecame requiredrequest-parameter-max-decreased(error) — for thequeryrequest parameterlimit, the max was decreased from100.00to50.00request-parameter-min-increased(error) — for thequeryrequest parameterlimit, the min was increased from1.00to10.00
GET /users/{id} — 1 here, 0 from oasdiff
This tool
BRK-ENUM-NARROWED-RESPONSE(WARN) — response 200 body (application/json).role: enum changed (removed ['guest'], added [])
oasdiff
- nothing
POST /users — 2 here, 2 from oasdiff
This tool
BRK-ENUM-NARROWED-REQUEST(ERROR) — request body (application/json).role: enum changed (removed ['guest'], added [])BRK-REQ-BODY-REQUIRED(ERROR) — request body requiredness changed False -> True
oasdiff
request-body-became-required(error) — request body became requiredrequest-property-enum-value-removed(error) — removed the enum valueguestof the request propertyrole
apis/jsonschema2020/v1.yaml against apis/jsonschema2020/v2.yaml
| This tool | oasdiff | |
|---|---|---|
| Breaking findings | 6 | 5 |
| Operations flagged | 1 | 1 |
| Operations both flagged | 1 | 1 |
POST /shipments — 6 here, 5 from oasdiff
This tool
BRK-DEPENDENT-REQUIRED-ADDED(ERROR) — request body (application/json): sending 'card' now also requires ['billingPostcode']BRK-CONSTRAINT-TIGHTENED(ERROR) — request body (application/json)/patternProperties/^x-: constraint 'max_length' changed None -> 64BRK-CONSTRAINT-TIGHTENED(ERROR) — request body (application/json)/if.mode: constraint 'const' changed 'road' -> 'sea'BRK-RESP-CONSTRAINT-TIGHTENED(WARN) — response 201 body (application/json).labels/propertyNames: constraint 'pattern' changed '^[a-z][a-z0-9-]*$' -> '^[a-z]+$'BRK-CONTAINS-CHANGED(WARN) — response 201 body (application/json).legs: minContains changed 1 -> 2BRK-TUPLE-SHAPE-CHANGED(ERROR) — response 201 body (application/json).route: the tuple went from 2 positional item(s) to 3
oasdiff
request-body-dependent-required-changed(error) — the request body dependentRequired forcardwas updated:billingPostcode addedrequest-property-const-changed(error) — themoderequest property const value changed fromroadtosearequest-property-max-length-set(error) — the/patternProperties[^x-]/request property's maxLength was set to64response-property-pattern-changed(warning) — thelabels/propertyNames/response's property pattern was changed from^[a-z][a-z0-9-]*$to^[a-z]+$for the status201response-property-prefix-items-added(warning) — addedsubschema #3to therouteresponse property 'prefixItems' list for the response status201
apis/crud/openapi.yaml against apis/drift/openapi.yaml
| This tool | oasdiff | |
|---|---|---|
| Breaking findings | 12 | 5 |
| Operations flagged | 5 | 4 |
| Operations both flagged | 4 | 4 |
Operations only this tool flagged: GET /reports
DELETE /users/{id} — 1 here, 1 from oasdiff
This tool
BRK-OP-REMOVED(ERROR) — operation 'DELETE /users/{id}' was removed
oasdiff
api-removed-without-deprecation(error) — api removed without deprecation
GET /reports — 1 here, 0 from oasdiff
This tool
BRK-OP-ADDED(INFO) — operation 'GET /reports' was added
oasdiff
- nothing
GET /users — 1 here, 1 from oasdiff
This tool
BRK-OP-REMOVED(ERROR) — operation 'GET /users' was removed
oasdiff
api-path-removed-without-deprecation(error) — api path removed without deprecation
GET /users/{id} — 8 here, 2 from oasdiff
This tool
BRK-RESP-STATUS-REMOVED(ERROR) — response status '404' was removedBRK-HEADER-ADDED(INFO) — response 200 header 'X-Request-Id' was addedBRK-RESP-FIELD-REMOVED(ERROR) — response 200 body (application/json): field 'age' was removedBRK-RESP-FIELD-REMOVED(ERROR) — response 200 body (application/json): field 'role' was removedBRK-RESP-FIELD-ADDED(INFO) — response 200 body (application/json): field 'plan' was addedBRK-RESP-TYPE-CHANGED(WARN) — response 200 body (application/json).email: format changed 'email' -> 'None'BRK-RESP-CONSTRAINT-LOOSENED(WARN) — response 200 body (application/json).name: constraint 'min_length' changed 1 -> NoneBRK-RESP-FIELD-GUARANTEED(INFO) — response 200 body (application/json): field 'email' became required
oasdiff
response-property-min-length-unset(error) — thenameresponse property's minLength was unset from1for the response status200response-property-type-changed(error) — theemailresponse's propertyformatchanged fromemailtononefor status200
POST /users — 1 here, 1 from oasdiff
This tool
BRK-OP-REMOVED(ERROR) — operation 'POST /users' was removed
oasdiff
api-path-removed-without-deprecation(error) — api path removed without deprecation
Across every pair, oasdiff flagged 0 operation(s) this tool did not, and this tool flagged 2 oasdiff did not.
On contracts this size that number is usually zero and it is the least informative thing on the page: both tools flag the same handful of operations, and everything interesting is inside them. The per-operation lists above are where the disagreement is, and an operation whose oasdiff list is longer than this tool's is where to look first.
Neither count is a score. Two tools disagreeing about a change usually means they model different things, and either may be right.