From d6376aba78fe6b422334001192e83dd31635029a Mon Sep 17 00:00:00 2001 From: Vladyslav Novikov Date: Fri, 27 Feb 2026 10:08:49 +0000 Subject: [PATCH 01/16] chore: set feature version for dependecy --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 099d437..9f2afef 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "fast-equals": "6.0.0" }, "devDependencies": { - "@netcracker/qubership-apihub-compatibility-suites": "dev", + "@netcracker/qubership-apihub-compatibility-suites": "feature-rules-reclassification-part-1", "@netcracker/qubership-apihub-graphapi": "1.0.9", "@netcracker/qubership-apihub-npm-gitflow": "3.1.0", "@types/jest": "30.0.0", From 366b68ed17eb301a5f016241a060dc089349c1c3 Mon Sep 17 00:00:00 2001 From: Vladyslav Novikov Date: Fri, 20 Feb 2026 08:20:54 +0200 Subject: [PATCH 02/16] feat!: reclassify `add-required-property-with-default` as breaking for `send` scope --- src/jsonSchema/jsonSchema.classify.ts | 3 ++- .../schemas/schema-test-runner-general.ts | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/jsonSchema/jsonSchema.classify.ts b/src/jsonSchema/jsonSchema.classify.ts index c759ced..71b7bc7 100644 --- a/src/jsonSchema/jsonSchema.classify.ts +++ b/src/jsonSchema/jsonSchema.classify.ts @@ -76,7 +76,8 @@ export const multipleOfClassifier: ClassifyRule = [ ] export const requiredItemClassifyRule: ClassifyRule = [ - ({ after }) => (!isString(after.value) || isExist(strictResolveValueFromContext(after, PARENT_JUMP, PARENT_JUMP, 'properties', after.value, 'default')) ? nonBreaking : breaking), + // classification is the same, but we are keeping the code structure to be able to change it if needed + ({ after }) => (!isString(after.value) || isExist(strictResolveValueFromContext(after, PARENT_JUMP, PARENT_JUMP, 'properties', after.value, 'default')) ? breaking : breaking), nonBreaking, ({ after }) => (!isString(after.value) || isExist(strictResolveValueFromContext(after, PARENT_JUMP, PARENT_JUMP, 'properties', after.value, 'default')) ? nonBreaking : breaking), nonBreaking, diff --git a/test/compatibility-suites/schemas/schema-test-runner-general.ts b/test/compatibility-suites/schemas/schema-test-runner-general.ts index ba4d007..4c44491 100644 --- a/test/compatibility-suites/schemas/schema-test-runner-general.ts +++ b/test/compatibility-suites/schemas/schema-test-runner-general.ts @@ -655,12 +655,12 @@ export function runGeneralSchemaTests( expect.objectContaining({ action: DiffAction.add, afterDeclarationPaths: [[...commonPath, 'required', 0]], - type: nonBreaking, + type: expectedType(breaking, nonBreaking), }), expect.objectContaining({ action: DiffAction.add, afterDeclarationPaths: [[...commonPath, 'required', 1]], - type: nonBreaking, + type: expectedType(breaking, nonBreaking), }), ])) }) From fc3389357f608b55a7d87e9ffd16438057b3b082 Mon Sep 17 00:00:00 2001 From: Vladyslav Novikov Date: Tue, 24 Feb 2026 10:34:00 +0000 Subject: [PATCH 03/16] feat!: reclassify `remove-property-compliance` as non-breaking for `send` scope following cases were also reclassified for consistency - `remove-all-of-option` reclassified as non-breaking for `send` scope - `remove-all-of` reclassified as non-breaking for `send` scope --- src/jsonSchema/jsonSchema.classify.ts | 2 +- .../schemas/schema-test-runner-general.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/jsonSchema/jsonSchema.classify.ts b/src/jsonSchema/jsonSchema.classify.ts index 71b7bc7..0038b02 100644 --- a/src/jsonSchema/jsonSchema.classify.ts +++ b/src/jsonSchema/jsonSchema.classify.ts @@ -91,7 +91,7 @@ export const propertyClassifyRule: ClassifyRule = [ !isExist(getKeyValue(after.value, 'default')) && getArrayValue((strictResolveValueFromContext(after, PARENT_JUMP, PARENT_JUMP, 'required')))?.includes(after.key) ? breaking : nonBreaking ), - breaking, + nonBreaking, unclassified, nonBreaking, ({ before }) => (getArrayValue(strictResolveValueFromContext(before, PARENT_JUMP, PARENT_JUMP, 'required'))?.includes(before.key) ? breaking : nonBreaking), diff --git a/test/compatibility-suites/schemas/schema-test-runner-general.ts b/test/compatibility-suites/schemas/schema-test-runner-general.ts index 4c44491..02d5240 100644 --- a/test/compatibility-suites/schemas/schema-test-runner-general.ts +++ b/test/compatibility-suites/schemas/schema-test-runner-general.ts @@ -628,7 +628,7 @@ export function runGeneralSchemaTests( expect.objectContaining({ action: DiffAction.remove, beforeDeclarationPaths: [[...commonPath, 'properties', 'prop2']], - type: expectedType(breaking, nonBreaking), + type: nonBreaking, }), ])) }) @@ -1026,7 +1026,7 @@ export function runGeneralSchemaTests( expect.objectContaining({ action: DiffAction.remove, beforeDeclarationPaths: [[...commonPath, 'allOf', 2, 'properties', 'prop3']], - type: expectedType(breaking, nonBreaking), + type: nonBreaking, }), ])) }) @@ -1037,7 +1037,7 @@ export function runGeneralSchemaTests( expect.objectContaining({ action: DiffAction.remove, beforeDeclarationPaths: [[...commonPath, 'allOf', 1, 'properties', 'prop2']], - type: expectedType(breaking, nonBreaking), + type: nonBreaking, }), ])) }) From 1ff34d11f2707d45f175d3a7bbf7d87accdd407d Mon Sep 17 00:00:00 2001 From: Vladyslav Novikov Date: Tue, 24 Feb 2026 10:47:10 +0000 Subject: [PATCH 04/16] refactor: rename `remove-required-property` to `remove-required-status-from-property` --- test/compatibility-suites/schemas/schema-test-runner-general.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/compatibility-suites/schemas/schema-test-runner-general.ts b/test/compatibility-suites/schemas/schema-test-runner-general.ts index 02d5240..2226ef1 100644 --- a/test/compatibility-suites/schemas/schema-test-runner-general.ts +++ b/test/compatibility-suites/schemas/schema-test-runner-general.ts @@ -665,7 +665,7 @@ export function runGeneralSchemaTests( ])) }) - test('remove-required-property', async () => { + test('remove-required-status-from-property', async () => { const result = await compareFiles(suiteId, currentTestId(), suiteType) expect(result).toEqual(diffsMatcher([ expect.objectContaining({ From 402a23c14facf3cf26b86176a153cd860cbbdbb6 Mon Sep 17 00:00:00 2001 From: Vladyslav Novikov Date: Tue, 24 Feb 2026 13:50:29 +0000 Subject: [PATCH 05/16] feat: add `remove-required-property-compliance` case for schemas - classify as non-breaking for `send` scope - classify as breaking for `receive` scope --- .../schemas/schema-test-runner-general.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/compatibility-suites/schemas/schema-test-runner-general.ts b/test/compatibility-suites/schemas/schema-test-runner-general.ts index 2226ef1..0dd1eb6 100644 --- a/test/compatibility-suites/schemas/schema-test-runner-general.ts +++ b/test/compatibility-suites/schemas/schema-test-runner-general.ts @@ -676,6 +676,22 @@ export function runGeneralSchemaTests( ])) }) + test('remove-required-property-compliance', async () => { + const result = await compareFiles(suiteId, currentTestId(), suiteType) + expect(result).toEqual(diffsMatcher([ + expect.objectContaining({ + action: DiffAction.remove, + beforeDeclarationPaths: [[...commonPath, 'required', 0]], + type: expectedType(nonBreaking, breaking), + }), + expect.objectContaining({ + action: DiffAction.remove, + beforeDeclarationPaths: [[...commonPath, 'properties', 'prop2']], + type: expectedType(nonBreaking, breaking), + }), + ])) + }) + test('update-required-property', async () => { const result = await compareFiles(suiteId, currentTestId(), suiteType) expect(result).toEqual(diffsMatcher([ From 2e65733fefec83667256ff5722280f0e3c2f5393 Mon Sep 17 00:00:00 2001 From: Vladyslav Novikov Date: Wed, 25 Feb 2026 06:11:55 +0000 Subject: [PATCH 06/16] feat!: reclassify `update-format-for-number-property` as risky for `receive` scope following case was also reclassified for consistency - `update-format-for-string-property` reclassified as risky for `receive` scope --- src/jsonSchema/jsonSchema.rules.ts | 2 +- .../schemas/schema-test-runner-general.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/jsonSchema/jsonSchema.rules.ts b/src/jsonSchema/jsonSchema.rules.ts index 9232ff9..80c40f6 100644 --- a/src/jsonSchema/jsonSchema.rules.ts +++ b/src/jsonSchema/jsonSchema.rules.ts @@ -119,7 +119,7 @@ export const jsonSchemaRules = ({ }, }, - '/format': simpleRule([breaking, nonBreaking, breaking, nonBreaking, breaking, breaking], resolveSchemaDescriptionTemplates('format')), + '/format': simpleRule([breaking, nonBreaking, breaking, nonBreaking, breaking, risky], resolveSchemaDescriptionTemplates('format')), '/default': simpleRule([nonBreaking, breaking, breaking], resolveSchemaDescriptionTemplates('default value')), '/enum': { diff --git a/test/compatibility-suites/schemas/schema-test-runner-general.ts b/test/compatibility-suites/schemas/schema-test-runner-general.ts index 0dd1eb6..eeb7753 100644 --- a/test/compatibility-suites/schemas/schema-test-runner-general.ts +++ b/test/compatibility-suites/schemas/schema-test-runner-general.ts @@ -165,7 +165,7 @@ export function runGeneralSchemaTests( action: DiffAction.replace, beforeDeclarationPaths: [[...commonPath, 'format']], afterDeclarationPaths: [[...commonPath, 'format']], - type: breaking, + type: expectedType(breaking, risky), }), ])) }) @@ -339,7 +339,7 @@ export function runGeneralSchemaTests( action: DiffAction.replace, beforeDeclarationPaths: [[...commonPath, 'format']], afterDeclarationPaths: [[...commonPath, 'format']], - type: breaking, + type: expectedType(breaking, risky), }), ])) }) From b995526674b411479d4e0a80fc856547fcd564d7 Mon Sep 17 00:00:00 2001 From: Vladyslav Novikov Date: Wed, 25 Feb 2026 07:12:04 +0000 Subject: [PATCH 07/16] feat!: reclassify `remove-format-for-number-property` as risky for `receive` scope following case was also reclassified for consistency - `remove-format-for-string-property` reclassified as risky for `receive` scope --- src/jsonSchema/jsonSchema.rules.ts | 2 +- .../schemas/schema-test-runner-general.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/jsonSchema/jsonSchema.rules.ts b/src/jsonSchema/jsonSchema.rules.ts index 80c40f6..5e2e319 100644 --- a/src/jsonSchema/jsonSchema.rules.ts +++ b/src/jsonSchema/jsonSchema.rules.ts @@ -119,7 +119,7 @@ export const jsonSchemaRules = ({ }, }, - '/format': simpleRule([breaking, nonBreaking, breaking, nonBreaking, breaking, risky], resolveSchemaDescriptionTemplates('format')), + '/format': simpleRule([breaking, nonBreaking, breaking, nonBreaking, risky, risky], resolveSchemaDescriptionTemplates('format')), '/default': simpleRule([nonBreaking, breaking, breaking], resolveSchemaDescriptionTemplates('default value')), '/enum': { diff --git a/test/compatibility-suites/schemas/schema-test-runner-general.ts b/test/compatibility-suites/schemas/schema-test-runner-general.ts index eeb7753..504ca1b 100644 --- a/test/compatibility-suites/schemas/schema-test-runner-general.ts +++ b/test/compatibility-suites/schemas/schema-test-runner-general.ts @@ -176,7 +176,7 @@ export function runGeneralSchemaTests( expect.objectContaining({ action: DiffAction.remove, beforeDeclarationPaths: [[...commonPath, 'format']], - type: expectedType(nonBreaking, breaking), + type: expectedType(nonBreaking, risky), }), ])) }) @@ -350,7 +350,7 @@ export function runGeneralSchemaTests( expect.objectContaining({ action: DiffAction.remove, beforeDeclarationPaths: [[...commonPath, 'format']], - type: expectedType(nonBreaking, breaking), + type: expectedType(nonBreaking, risky), }), ])) }) From ce5a21b77762176612e56d40b4bf40a420fc612a Mon Sep 17 00:00:00 2001 From: Vladyslav Novikov Date: Thu, 26 Feb 2026 06:55:45 +0000 Subject: [PATCH 08/16] feat!: reclassify `decrease-minimum-for-number-property` as risky for `receive` scope --- src/jsonSchema/jsonSchema.classify.ts | 7 +++++++ .../schemas/schema-test-runner-general.ts | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/jsonSchema/jsonSchema.classify.ts b/src/jsonSchema/jsonSchema.classify.ts index 0038b02..33a8f39 100644 --- a/src/jsonSchema/jsonSchema.classify.ts +++ b/src/jsonSchema/jsonSchema.classify.ts @@ -5,6 +5,7 @@ import { nonBreaking, PARENT_JUMP, risky, + riskyIf, strictResolveValueFromContext, unclassified, } from '../core' @@ -48,6 +49,12 @@ export const minimumClassifier: ClassifyRule = [ }, nonBreaking, ({ before, after }) => breakingIf(!isNumber(before.value) || !isNumber(after.value) || before.value < after.value), + ({ before, after }) => { + const beforeExclusiveMinimum = strictResolveValueFromContext(before, PARENT_JUMP, 'exclusiveMinimum') + return nonBreakingIf(!isNumber(beforeExclusiveMinimum) || !isNumber(after.value) || beforeExclusiveMinimum < after.value) + }, + breaking, + ({ before, after }) => riskyIf(isNumber(before.value) && isNumber(after.value) && before.value >= after.value), ] export const maximumClassifier: ClassifyRule = [ diff --git a/test/compatibility-suites/schemas/schema-test-runner-general.ts b/test/compatibility-suites/schemas/schema-test-runner-general.ts index 504ca1b..18cede5 100644 --- a/test/compatibility-suites/schemas/schema-test-runner-general.ts +++ b/test/compatibility-suites/schemas/schema-test-runner-general.ts @@ -385,7 +385,7 @@ export function runGeneralSchemaTests( action: DiffAction.replace, beforeDeclarationPaths: [[...commonPath, 'minimum']], afterDeclarationPaths: [[...commonPath, 'minimum']], - type: expectedType(nonBreaking, breaking), + type: expectedType(nonBreaking, risky), }), ])) }) From ac6cfe30ee6f551805ff1ee4dd16dea780b3fbf6 Mon Sep 17 00:00:00 2001 From: Vladyslav Novikov Date: Thu, 26 Feb 2026 12:14:14 +0000 Subject: [PATCH 09/16] feat: add `decrease-minimum-for-required-number-property` case for schemas - classify as non-breaking for `send` scope - classify as breaking for `receive` scope --- src/jsonSchema/jsonSchema.classify.ts | 12 +++++++++++- .../schemas/schema-test-runner-general.ts | 12 ++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/jsonSchema/jsonSchema.classify.ts b/src/jsonSchema/jsonSchema.classify.ts index 33a8f39..9435732 100644 --- a/src/jsonSchema/jsonSchema.classify.ts +++ b/src/jsonSchema/jsonSchema.classify.ts @@ -54,7 +54,17 @@ export const minimumClassifier: ClassifyRule = [ return nonBreakingIf(!isNumber(beforeExclusiveMinimum) || !isNumber(after.value) || beforeExclusiveMinimum < after.value) }, breaking, - ({ before, after }) => riskyIf(isNumber(before.value) && isNumber(after.value) && before.value >= after.value), + ({ before, after }) => { + if (!isNumber(before.value) || !isNumber(after.value) || before.value < after.value) { + return nonBreaking + } + const propertyName = before.parentContext?.key + const requiredArray = getArrayValue(strictResolveValueFromContext(before, PARENT_JUMP, PARENT_JUMP, PARENT_JUMP, 'required')) + if (isString(propertyName) && requiredArray?.includes(propertyName)) { + return breaking + } + return risky + }, ] export const maximumClassifier: ClassifyRule = [ diff --git a/test/compatibility-suites/schemas/schema-test-runner-general.ts b/test/compatibility-suites/schemas/schema-test-runner-general.ts index 18cede5..6d17a69 100644 --- a/test/compatibility-suites/schemas/schema-test-runner-general.ts +++ b/test/compatibility-suites/schemas/schema-test-runner-general.ts @@ -390,6 +390,18 @@ export function runGeneralSchemaTests( ])) }) + test('decrease-minimum-for-required-number-property', async () => { + const result = await compareFiles(suiteId, currentTestId(), suiteType) + expect(result).toEqual(diffsMatcher([ + expect.objectContaining({ + action: DiffAction.replace, + beforeDeclarationPaths: [[...commonPath, 'properties', 'prop1', 'minimum']], + afterDeclarationPaths: [[...commonPath, 'properties', 'prop1', 'minimum']], + type: expectedType(nonBreaking, breaking), + }), + ])) + }) + test('remove-minimum-for-number-property', async () => { const result = await compareFiles(suiteId, currentTestId(), suiteType) expect(result).toEqual(diffsMatcher([ From d219665af90fbf8eeb91cfa9f2aa9e014025e8a2 Mon Sep 17 00:00:00 2001 From: Vladyslav Novikov Date: Thu, 26 Feb 2026 12:29:17 +0000 Subject: [PATCH 10/16] feat!: reclassify `remove-minimum-for-number-property` as risky for `receive` scope --- src/jsonSchema/jsonSchema.classify.ts | 2 +- test/compatibility-suites/schemas/schema-test-runner-general.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jsonSchema/jsonSchema.classify.ts b/src/jsonSchema/jsonSchema.classify.ts index 9435732..84ba45a 100644 --- a/src/jsonSchema/jsonSchema.classify.ts +++ b/src/jsonSchema/jsonSchema.classify.ts @@ -53,7 +53,7 @@ export const minimumClassifier: ClassifyRule = [ const beforeExclusiveMinimum = strictResolveValueFromContext(before, PARENT_JUMP, 'exclusiveMinimum') return nonBreakingIf(!isNumber(beforeExclusiveMinimum) || !isNumber(after.value) || beforeExclusiveMinimum < after.value) }, - breaking, + risky, ({ before, after }) => { if (!isNumber(before.value) || !isNumber(after.value) || before.value < after.value) { return nonBreaking diff --git a/test/compatibility-suites/schemas/schema-test-runner-general.ts b/test/compatibility-suites/schemas/schema-test-runner-general.ts index 6d17a69..2dfc9bf 100644 --- a/test/compatibility-suites/schemas/schema-test-runner-general.ts +++ b/test/compatibility-suites/schemas/schema-test-runner-general.ts @@ -408,7 +408,7 @@ export function runGeneralSchemaTests( expect.objectContaining({ action: DiffAction.remove, beforeDeclarationPaths: [[...commonPath, 'minimum']], - type: expectedType(nonBreaking, breaking), + type: expectedType(nonBreaking, risky), }), ])) }) From 847ff3de0ed0bef45ff7a5be5c863af30822bc81 Mon Sep 17 00:00:00 2001 From: Vladyslav Novikov Date: Thu, 26 Feb 2026 12:40:56 +0000 Subject: [PATCH 11/16] feat: add `remove-minimum-for-required-number-property` case for schemas - classify as non-breaking for `send` scope - classify as breaking for `receive` scope --- src/jsonSchema/jsonSchema.classify.ts | 9 ++++++++- .../schemas/schema-test-runner-general.ts | 11 +++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/jsonSchema/jsonSchema.classify.ts b/src/jsonSchema/jsonSchema.classify.ts index 84ba45a..a933dd1 100644 --- a/src/jsonSchema/jsonSchema.classify.ts +++ b/src/jsonSchema/jsonSchema.classify.ts @@ -53,7 +53,14 @@ export const minimumClassifier: ClassifyRule = [ const beforeExclusiveMinimum = strictResolveValueFromContext(before, PARENT_JUMP, 'exclusiveMinimum') return nonBreakingIf(!isNumber(beforeExclusiveMinimum) || !isNumber(after.value) || beforeExclusiveMinimum < after.value) }, - risky, + ({ before }) => { + const propertyName = before.parentContext?.key + const requiredArray = getArrayValue(strictResolveValueFromContext(before, PARENT_JUMP, PARENT_JUMP, PARENT_JUMP, 'required')) + if (isString(propertyName) && requiredArray?.includes(propertyName)) { + return breaking + } + return risky + }, ({ before, after }) => { if (!isNumber(before.value) || !isNumber(after.value) || before.value < after.value) { return nonBreaking diff --git a/test/compatibility-suites/schemas/schema-test-runner-general.ts b/test/compatibility-suites/schemas/schema-test-runner-general.ts index 2dfc9bf..7bda98d 100644 --- a/test/compatibility-suites/schemas/schema-test-runner-general.ts +++ b/test/compatibility-suites/schemas/schema-test-runner-general.ts @@ -413,6 +413,17 @@ export function runGeneralSchemaTests( ])) }) + test('remove-minimum-for-required-number-property', async () => { + const result = await compareFiles(suiteId, currentTestId(), suiteType) + expect(result).toEqual(diffsMatcher([ + expect.objectContaining({ + action: DiffAction.remove, + beforeDeclarationPaths: [[...commonPath, 'properties', 'prop1', 'minimum']], + type: expectedType(nonBreaking, breaking), + }), + ])) + }) + test('add-maximum-for-number-property', async () => { const result = await compareFiles(suiteId, currentTestId(), suiteType) expect(result).toEqual(diffsMatcher([ From f6842225a05978b96d675f88ffcf9ca9888e66c1 Mon Sep 17 00:00:00 2001 From: Vladyslav Novikov Date: Thu, 26 Feb 2026 15:56:54 +0000 Subject: [PATCH 12/16] feat!: reclassify `mark-minimum-value-as-inclusive-for-number-property` as risky for `receive` scope following case was also reclassified for consistency - `mark-maximum-value-as-inclusive-for-number-property` reclassified as risky for `receive` scope --- src/jsonSchema/jsonSchema.classify.ts | 3 +++ .../schemas/schema-test-runner-openapi-only.ts | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/jsonSchema/jsonSchema.classify.ts b/src/jsonSchema/jsonSchema.classify.ts index a933dd1..052ab93 100644 --- a/src/jsonSchema/jsonSchema.classify.ts +++ b/src/jsonSchema/jsonSchema.classify.ts @@ -87,6 +87,9 @@ export const exclusiveClassifier: ClassifyRule = [ ({ after }) => (after.value === true ? breaking : unclassified), ({ before }) => (before.value === true ? nonBreaking : unclassified), breakingIfAfterTrue, + ({ after }) => (after.value === true ? nonBreaking : unclassified), + ({ before }) => (before.value === true ? risky : unclassified), + ({ after }) => riskyIf(!after.value), ] //todo think about replace multipleOf in inverse case diff --git a/test/compatibility-suites/schemas/schema-test-runner-openapi-only.ts b/test/compatibility-suites/schemas/schema-test-runner-openapi-only.ts index 71fc400..e0f2029 100644 --- a/test/compatibility-suites/schemas/schema-test-runner-openapi-only.ts +++ b/test/compatibility-suites/schemas/schema-test-runner-openapi-only.ts @@ -333,13 +333,13 @@ export function runOpenApiOnlySchemaTests( action: DiffAction.replace, beforeDeclarationPaths: [[...commonPath, 'properties', 'option1', 'exclusiveMinimum']], afterDeclarationPaths: TEST_DEFAULTS_DECLARATION_PATHS, - type: expectedType(nonBreaking, breaking), + type: expectedType(nonBreaking, risky), }), expect.objectContaining({ action: DiffAction.replace, beforeDeclarationPaths: [[...commonPath, 'properties', 'option2', 'exclusiveMinimum']], afterDeclarationPaths: [[...commonPath, 'properties', 'option2', 'exclusiveMinimum']], - type: expectedType(nonBreaking, breaking), + type: expectedType(nonBreaking, risky), }), ])) }) @@ -367,13 +367,13 @@ export function runOpenApiOnlySchemaTests( action: DiffAction.replace, beforeDeclarationPaths: [[...commonPath, 'properties', 'option1', 'exclusiveMaximum']], afterDeclarationPaths: TEST_DEFAULTS_DECLARATION_PATHS, - type: expectedType(nonBreaking, breaking), + type: expectedType(nonBreaking, risky), }), expect.objectContaining({ action: DiffAction.replace, beforeDeclarationPaths: [[...commonPath, 'properties', 'option2', 'exclusiveMaximum']], afterDeclarationPaths: [[...commonPath, 'properties', 'option2', 'exclusiveMaximum']], - type: expectedType(nonBreaking, breaking), + type: expectedType(nonBreaking, risky), }), ])) }) From 418f06476fa93cc4623bf055adb2e5c1125197a0 Mon Sep 17 00:00:00 2001 From: Vladyslav Novikov Date: Fri, 27 Feb 2026 06:01:03 +0000 Subject: [PATCH 13/16] feat!: reclassify `update-multiple-of-for-number-property` as risky for `receive` scope --- src/jsonSchema/jsonSchema.classify.ts | 2 +- test/compatibility-suites/schemas/schema-test-runner-general.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jsonSchema/jsonSchema.classify.ts b/src/jsonSchema/jsonSchema.classify.ts index 052ab93..4efd205 100644 --- a/src/jsonSchema/jsonSchema.classify.ts +++ b/src/jsonSchema/jsonSchema.classify.ts @@ -99,7 +99,7 @@ export const multipleOfClassifier: ClassifyRule = [ ({ before, after }) => breakingIfNotMultiple(before.value, after.value), nonBreaking, breaking, - breaking, + risky, ] export const requiredItemClassifyRule: ClassifyRule = [ diff --git a/test/compatibility-suites/schemas/schema-test-runner-general.ts b/test/compatibility-suites/schemas/schema-test-runner-general.ts index 7bda98d..dc41138 100644 --- a/test/compatibility-suites/schemas/schema-test-runner-general.ts +++ b/test/compatibility-suites/schemas/schema-test-runner-general.ts @@ -488,7 +488,7 @@ export function runGeneralSchemaTests( action: DiffAction.replace, beforeDeclarationPaths: [[...commonPath, 'multipleOf']], afterDeclarationPaths: [[...commonPath, 'multipleOf']], - type: breaking, + type: expectedType(breaking, risky), }), ])) }) From 01d99885f2d01834c6420da73a2bd7cd463adfd4 Mon Sep 17 00:00:00 2001 From: Vladyslav Novikov Date: Fri, 27 Feb 2026 06:32:49 +0000 Subject: [PATCH 14/16] feat!: reclassify `increase-max-properties-for-object-property` as risky for `receive` scope following cases were also reclassified for consistency - `increase-max-length-for-string-property` reclassified as risky for `receive` scope - `increase-max-items-for-array-property` reclassified as risky for `receive` scope - `remove-sibling-maxLength-for-ref` reclassified as risky for `receive` scope --- src/jsonSchema/jsonSchema.classify.ts | 3 +++ .../schemas/schema-test-runner-general.ts | 6 +++--- .../schemas/schema-test-runner-openapi-only.ts | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/jsonSchema/jsonSchema.classify.ts b/src/jsonSchema/jsonSchema.classify.ts index 4efd205..19f0a5d 100644 --- a/src/jsonSchema/jsonSchema.classify.ts +++ b/src/jsonSchema/jsonSchema.classify.ts @@ -34,6 +34,9 @@ export const maxClassifier: ClassifyRule = [ breaking, nonBreaking, ({ before, after }) => breakingIf(!isNumber(before.value) || !isNumber(after.value) || before.value > after.value), + nonBreaking, + breaking, + ({ before, after }) => riskyIf(isNumber(before.value) && isNumber(after.value) && before.value < after.value), ] export const minClassifier: ClassifyRule = [ diff --git a/test/compatibility-suites/schemas/schema-test-runner-general.ts b/test/compatibility-suites/schemas/schema-test-runner-general.ts index dc41138..970f5d2 100644 --- a/test/compatibility-suites/schemas/schema-test-runner-general.ts +++ b/test/compatibility-suites/schemas/schema-test-runner-general.ts @@ -259,7 +259,7 @@ export function runGeneralSchemaTests( action: DiffAction.replace, beforeDeclarationPaths: [[...commonPath, 'maxLength']], afterDeclarationPaths: [[...commonPath, 'maxLength']], - type: expectedType(nonBreaking, breaking), + type: expectedType(nonBreaking, risky), }), ])) }) @@ -570,7 +570,7 @@ export function runGeneralSchemaTests( action: DiffAction.replace, beforeDeclarationPaths: [[...commonPath, 'maxItems']], afterDeclarationPaths: [[...commonPath, 'maxItems']], - type: expectedType(nonBreaking, breaking), + type: expectedType(nonBreaking, risky), }), ])) }) @@ -869,7 +869,7 @@ export function runGeneralSchemaTests( action: DiffAction.replace, beforeDeclarationPaths: [[...commonPath, 'maxProperties']], afterDeclarationPaths: [[...commonPath, 'maxProperties']], - type: expectedType(nonBreaking, breaking), + type: expectedType(nonBreaking, risky), }), ])) }) diff --git a/test/compatibility-suites/schemas/schema-test-runner-openapi-only.ts b/test/compatibility-suites/schemas/schema-test-runner-openapi-only.ts index e0f2029..5f88097 100644 --- a/test/compatibility-suites/schemas/schema-test-runner-openapi-only.ts +++ b/test/compatibility-suites/schemas/schema-test-runner-openapi-only.ts @@ -455,7 +455,7 @@ export function runOpenApiOnlySchemaTests( action: DiffAction.replace, beforeDeclarationPaths: [[...commonPath, 'maxLength']], afterDeclarationPaths: [[...COMPONENTS_SCHEMAS, 'Color', 'maxLength']], - type: expectedType(nonBreaking, breaking), + type: expectedType(nonBreaking, risky), }), ])) }, From bc933acc4baa1aeee3322eba4dccca0e7c742898 Mon Sep 17 00:00:00 2001 From: Vladyslav Novikov Date: Fri, 27 Feb 2026 06:40:40 +0000 Subject: [PATCH 15/16] feat!: reclassify `remove-max-properties-for-object-property` as risky for `receive` scope following cases were also reclassified for consistency - `remove-max-length-for-string-property` reclassified as risky for `receive` scope - `remove-max-items-for-array-property` reclassified as risky for `receive` scope --- src/jsonSchema/jsonSchema.classify.ts | 2 +- .../schemas/schema-test-runner-general.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/jsonSchema/jsonSchema.classify.ts b/src/jsonSchema/jsonSchema.classify.ts index 19f0a5d..7ff01d4 100644 --- a/src/jsonSchema/jsonSchema.classify.ts +++ b/src/jsonSchema/jsonSchema.classify.ts @@ -35,7 +35,7 @@ export const maxClassifier: ClassifyRule = [ nonBreaking, ({ before, after }) => breakingIf(!isNumber(before.value) || !isNumber(after.value) || before.value > after.value), nonBreaking, - breaking, + risky, ({ before, after }) => riskyIf(isNumber(before.value) && isNumber(after.value) && before.value < after.value), ] diff --git a/test/compatibility-suites/schemas/schema-test-runner-general.ts b/test/compatibility-suites/schemas/schema-test-runner-general.ts index 970f5d2..eabb987 100644 --- a/test/compatibility-suites/schemas/schema-test-runner-general.ts +++ b/test/compatibility-suites/schemas/schema-test-runner-general.ts @@ -282,7 +282,7 @@ export function runGeneralSchemaTests( expect.objectContaining({ action: DiffAction.remove, beforeDeclarationPaths: [[...commonPath, 'maxLength']], - type: expectedType(nonBreaking, breaking), + type: expectedType(nonBreaking, risky), }), ])) }) @@ -593,7 +593,7 @@ export function runGeneralSchemaTests( expect.objectContaining({ action: DiffAction.remove, beforeDeclarationPaths: [[...commonPath, 'maxItems']], - type: expectedType(nonBreaking, breaking), + type: expectedType(nonBreaking, risky), }), ])) }) @@ -892,7 +892,7 @@ export function runGeneralSchemaTests( expect.objectContaining({ action: DiffAction.remove, beforeDeclarationPaths: [[...commonPath, 'maxProperties']], - type: expectedType(nonBreaking, breaking), + type: expectedType(nonBreaking, risky), }), ])) }) From d9dc50f079148d925ca65f0a32bad476973cb9a9 Mon Sep 17 00:00:00 2001 From: Vladyslav Novikov Date: Fri, 27 Feb 2026 07:23:16 +0000 Subject: [PATCH 16/16] feat!: reclassify `add-non-boolean-additional-properties` as risky for `receive` scope --- src/jsonSchema/jsonSchema.classify.ts | 2 +- test/compatibility-suites/schemas/schema-test-runner-general.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jsonSchema/jsonSchema.classify.ts b/src/jsonSchema/jsonSchema.classify.ts index 7ff01d4..828fbce 100644 --- a/src/jsonSchema/jsonSchema.classify.ts +++ b/src/jsonSchema/jsonSchema.classify.ts @@ -27,7 +27,7 @@ export const typeClassifier: ClassifyRule = [ ({ before, after }) => nonBreakingIf(isTypeAssignable(before.value, after.value, false)), breaking,//not tested breaking,//not tested - ({ before, after }) => nonBreakingIf(isTypeAssignable(before.value, after.value, true)), + ({ before, after }) => isTypeAssignable(before.value, after.value, true) ? risky : breaking, ] export const maxClassifier: ClassifyRule = [ diff --git a/test/compatibility-suites/schemas/schema-test-runner-general.ts b/test/compatibility-suites/schemas/schema-test-runner-general.ts index eabb987..ee805a1 100644 --- a/test/compatibility-suites/schemas/schema-test-runner-general.ts +++ b/test/compatibility-suites/schemas/schema-test-runner-general.ts @@ -915,7 +915,7 @@ export function runGeneralSchemaTests( afterValue: 'string', beforeDeclarationPaths: TEST_DEFAULTS_DECLARATION_PATHS, afterDeclarationPaths: [[...commonPath, 'additionalProperties', 'type']], - type: expectedType(breaking, nonBreaking), + type: expectedType(breaking, risky), }), ]), )