[
 {
  "rule": "operation-removed",
  "kind": "catalog",
  "severity": "breaking",
  "reported": true,
  "trigger": "A tool present in the earlier contract is absent from the later one.",
  "consequence": "Every call to that tool now fails; an agent that learned it yesterday has nothing to call today.",
  "count": 38
 },
 {
  "rule": "operation-renamed",
  "kind": "catalog",
  "severity": "breaking",
  "reported": true,
  "trigger": "A tool disappeared and one with an identical input schema appeared under another name.",
  "consequence": "Callers using the old name fail until they are updated; the capability itself is still there.",
  "count": 12
 },
 {
  "rule": "catalog-moved-behind-meta-tools",
  "kind": "catalog",
  "severity": "info",
  "reported": true,
  "trigger": "A server's tools moved behind discovery meta-tools: tools/list now lists a search or toolset tool in their place.",
  "consequence": "The tools still exist, reached a different way. Recorded as ONE event, never as one removal per tool no longer listed.",
  "count": 1
 },
 {
  "rule": "operation-added",
  "kind": "catalog",
  "severity": "",
  "reported": false,
  "trigger": "A tool is present in the later contract and was not in the earlier one.",
  "consequence": "Nothing that worked before is affected; the surface grew. Not reported.",
  "count": 0
 },
 {
  "rule": "input-required-property-added",
  "kind": "input",
  "severity": "warning",
  "reported": true,
  "trigger": "A property joined a tool's input schema and is listed as required.",
  "consequence": "A caller that does not send the new field is rejected, with no change on its own side.",
  "count": 10
 },
 {
  "rule": "input-optional-property-added",
  "kind": "input",
  "severity": "",
  "reported": false,
  "trigger": "A property joined a tool's input schema and is not required.",
  "consequence": "Existing calls keep working; the new field is accepted if sent. Not reported.",
  "count": 0
 },
 {
  "rule": "input-property-renamed",
  "kind": "input",
  "severity": "info",
  "reported": true,
  "trigger": "A property left a tool's input schema and a same-typed one arrived under a name that normalises to the same key (branchId, branch_id and branch-id are one name).",
  "consequence": "Callers still sending the old name must switch to the new one; the parameter itself is unchanged.",
  "count": 86
 },
 {
  "rule": "input-required-property-removed",
  "kind": "input",
  "severity": "info",
  "reported": true,
  "trigger": "A property callers were required to send left a tool's input schema.",
  "consequence": "Callers can stop sending it; a server that rejects unknown fields rejects callers that do not.",
  "count": 8
 },
 {
  "rule": "input-optional-property-removed",
  "kind": "input",
  "severity": "info",
  "reported": true,
  "trigger": "A property callers could send left a tool's input schema.",
  "consequence": "Depending on whether the new schema forbids unknown fields, a caller still sending it is ignored or rejected; the row says which.",
  "count": 30
 },
 {
  "rule": "input-type-widened",
  "kind": "input",
  "severity": "",
  "reported": false,
  "trigger": "The declared type of an input property now accepts more than it did.",
  "consequence": "Every argument sent before still validates. Not reported.",
  "count": 0
 },
 {
  "rule": "input-type-narrowed",
  "kind": "input",
  "severity": "info",
  "reported": true,
  "trigger": "The declared type of an input property now accepts less than it did (number to integer, a union that lost a member).",
  "consequence": "A caller sending the dropped type is rejected.",
  "count": 7
 },
 {
  "rule": "input-type-changed",
  "kind": "input",
  "severity": "info",
  "reported": true,
  "trigger": "The declared type of an input property was replaced outright.",
  "consequence": "Values that validated yesterday do not today; the caller's code has to change to keep calling.",
  "count": 0
 },
 {
  "rule": "input-enum-value-removed",
  "kind": "input",
  "severity": "info",
  "reported": true,
  "trigger": "A value left an input property's enum.",
  "consequence": "A caller still sending that value is rejected.",
  "count": 1
 },
 {
  "rule": "input-enum-value-added",
  "kind": "input",
  "severity": "",
  "reported": false,
  "trigger": "A value joined an input property's enum.",
  "consequence": "Existing calls keep working; one more value is accepted. Not reported.",
  "count": 0
 },
 {
  "rule": "input-enum-value-replaced",
  "kind": "input",
  "severity": "info",
  "reported": true,
  "trigger": "Values left and arrived in an input property's enum in one revision.",
  "consequence": "A caller still sending a departed value is rejected.",
  "count": 1
 },
 {
  "rule": "output-required-property-removed",
  "kind": "output",
  "severity": "breaking",
  "reported": true,
  "trigger": "A property the output schema listed as required is gone.",
  "consequence": "A field the consumer could rely on being present can now be absent; code that reads it unconditionally breaks.",
  "count": 0
 },
 {
  "rule": "output-optional-property-renamed",
  "kind": "output",
  "severity": "warning",
  "reported": true,
  "trigger": "An output property the schema declared without requiring it left, and a same-typed one arrived under a name that normalises to the same key.",
  "consequence": "A consumer reading the old name finds nothing there; the row says what it is called now.",
  "count": 0
 },
 {
  "rule": "output-optional-property-removed",
  "kind": "output",
  "severity": "warning",
  "reported": true,
  "trigger": "A property the output schema declared, without requiring it, is gone.",
  "consequence": "A field the consumer may have been reading is no longer declared.",
  "count": 3
 },
 {
  "rule": "output-property-renamed",
  "kind": "output",
  "severity": "breaking",
  "reported": true,
  "trigger": "A required output property left and a same-typed one arrived under a name that normalises to the same key.",
  "consequence": "Consumer code reading the old name finds nothing there.",
  "count": 0
 },
 {
  "rule": "output-optional-property-added",
  "kind": "output",
  "severity": "",
  "reported": false,
  "trigger": "A property joined a tool's output schema.",
  "consequence": "A consumer that ignores unknown fields is unaffected. Not reported.",
  "count": 0
 },
 {
  "rule": "output-property-type-widened",
  "kind": "output",
  "severity": "breaking",
  "reported": true,
  "trigger": "The declared type of an output property now admits more than it did.",
  "consequence": "The consumer may receive a type it never handled.",
  "count": 0
 },
 {
  "rule": "output-property-type-narrowed",
  "kind": "output",
  "severity": "breaking",
  "reported": true,
  "trigger": "The declared type of an output property now admits less than it did.",
  "consequence": "A branch the consumer wrote for the dropped type is dead, or the field's data is gone.",
  "count": 0
 },
 {
  "rule": "output-property-type-changed",
  "kind": "output",
  "severity": "breaking",
  "reported": true,
  "trigger": "The declared type of an output property was replaced outright.",
  "consequence": "Consumer code that parsed the old type breaks on the new one, silently if it does not validate.",
  "count": 1
 },
 {
  "rule": "output-enum-value-removed",
  "kind": "output",
  "severity": "breaking",
  "reported": true,
  "trigger": "A value left an output property's enum.",
  "consequence": "A value the consumer's code may branch on has disappeared from the declared set.",
  "count": 0
 },
 {
  "rule": "output-enum-value-added",
  "kind": "output",
  "severity": "warning",
  "reported": true,
  "trigger": "A value joined an output property's enum.",
  "consequence": "Responses may carry a value the consumer has no branch for; nothing it already handles stopped being valid.",
  "count": 1
 },
 {
  "rule": "output-enum-value-replaced",
  "kind": "output",
  "severity": "breaking",
  "reported": true,
  "trigger": "Values left and arrived in an output property's enum in one revision.",
  "consequence": "A value the consumer branches on is gone, and one it has never seen can arrive.",
  "count": 1
 },
 {
  "rule": "output-schema-removed",
  "kind": "output",
  "severity": "breaking",
  "reported": true,
  "trigger": "A tool that declared an outputSchema no longer does.",
  "consequence": "A consumer validating responses against the declared shape has nothing to validate against.",
  "count": 0
 },
 {
  "rule": "output-schema-declared",
  "kind": "output",
  "severity": "",
  "reported": false,
  "trigger": "A tool that declared no outputSchema now does.",
  "consequence": "The response shape is now stated where it was not. Not reported.",
  "count": 0
 },
 {
  "rule": "description-changed",
  "kind": "wording",
  "severity": "warning",
  "reported": true,
  "trigger": "A tool's description text differs between the two contracts — beyond whitespace, case and punctuation, and at most once per tool per day.",
  "consequence": "The wording an agent reads to choose and call the tool changed; its behaviour may or may not have.",
  "count": 470
 }
]
