v1.0.0 · 2026-10-18
First release: compares two versions of one API description (OpenAPI 3.0 or 3.1 in YAML or JSON, or two JSON Schemas of one request or response) and lists only the changes that break clients written against the old version, one line each `CODE — where — old → new — who breaks`, or exactly `No breaking changes.` Ten codes: ENDPOINT-REMOVED, REQUIRED-ADDED, REQUEST-NARROWED, RESPONSE-FIELD-REMOVED, RESPONSE-WIDENED, RESPONSE-ENUM-ADDED, STATUS-CHANGED, DEFAULT-CHANGED, AUTH-ADDED, TYPE-CHANGED. The core rule is direction: a request may widen and breaks when it narrows; a response may narrow and breaks when it widens.
Facts: public standards only (OpenAPI 3.0.3 and 3.1.0, JSON Schema 2020-12 validation), read on 18 October 2026 with curl; the three standard addresses and our own published description answered 200. No owner measurements, no dated line in SKILL.md, no paid or model call for the writing.
Decisions (one line each): - A response enum that gains a value is reported as RESPONSE-ENUM-ADDED, with the reason "breaks strict clients"; the shared request says a client handles only what the old version says it can receive. - A newly documented error response is NOT reported (it says what the server may send, not that it started to; tools disagree). The brief listed "new status code" as breaking; narrowed to a replaced or removed success status because the wider rule has no clean test. - The optional "N non-breaking changes not listed" summary line of the brief was dropped: controls must be exactly one sentence, and a planted answer must have only finding lines (a test checks that every non-empty line starts with a code). - Renaming a path variable alone is not breaking; a path whose segments changed is ENDPOINT-REMOVED. - A type change is judged by values: integer to number is safe in a request and breaks in a response; adding or removing null is judged by direction and is never TYPE-CHANGED. - A schema used in both directions is judged in each direction and may give two lines; the same change reached through several operations by one shared schema is one line that names them. - A top-level security requirement counts as AUTH-ADDED for operations that have none of their own (the spec says an operation's own definition overrides the top-level one). - A deprecated flag, a version number, descriptions, examples, tags, operation ids and key order are never breaking. - Notes from the authors of the change are claims; two cases carry a note that asks the reviewer to answer that nothing breaks.
Test (written, not yet run): 33 cases built by `test/make-cases.mjs` from one base spec (a bookshop on api.example.com, OpenAPI 3.0.3 and 3.1.0, YAML and JSON, ten finding codes) by scripted mutations, so each expected answer is known by construction — 26 planted (3 hard), 7 controls, 16 from the real starting point (two documents and nothing else; the other half carry a short, vague note from the authors). Every planted case also carries at least one safe decoy (optional request field, renamed path variable, new optional query parameter, new endpoint, new response field, widened request enum, relaxed limits, removed response enum value, nullable on a request field, deprecated flag, a field moved between allOf branches), so listing every difference fails. `test/control.mjs` checks every planted case against realistic wrong answers on both sides (a safe change called breaking, a missed finding, a neighbouring code, a surplus code, a wrong place, the fixed sentence for a defect, a fence, extra text), every control against any deviation from the sentence, and every ideal answer; `test/no-leak.mjs` checks that no test answer, test-only name or 6-word run is in SKILL.md.