Skip to content

feat: introduce classifyRuleId's for rules#68

Draft
b41ex wants to merge 100 commits into
developfrom
feature/separate-identification-classification
Draft

feat: introduce classifyRuleId's for rules#68
b41ex wants to merge 100 commits into
developfrom
feature/separate-identification-classification

Conversation

@b41ex
Copy link
Copy Markdown
Collaborator

@b41ex b41ex commented Apr 10, 2026

  • introduce mechanism to allow calculating ruleId for diffs in the core comparison engine

  • provide ability to specify custom (re)classification function

  • provide oob look-up based classification function

    • matching rules in yaml format
  • (prototype) implement ruleId calculation / table lookup-based classification for most of OpenAPI/JSON Schema rules

b41ex added 30 commits April 3, 2026 15:40
…ules in yaml files

provide matchingDiffClassifier that could use a list of matching rules to classify diffs
use it for reclassification internall, use composition of functions with user-provided diff classifier is passed in compare options
add
add some matching rules for the OpenAPI
add some matching rules for the JSON Schema
add general matching rule for breaking -> risky classification in non bwc scope
Covers maxLength, maxItems, maxProperties, and non-draft-04
exclusiveMaximum. Four ruleIds capture the three actions and the
replace split (constraint-relaxed vs constraint-tightened). Response
scope flips all types via reverseClassifyRuleTransformer.

Made-with: Cursor
Covers minLength, minItems, minProperties, and non-draft-04
exclusiveMinimum. Four ruleIds capture the three actions and the
replace split (constraint-relaxed vs constraint-tightened). Response
scope flips all types via reverseClassifyRuleTransformer.

Made-with: Cursor
The add case distinguishes whether the before schema already has a
numeric exclusiveMinimum covering the new minimum (non-breaking) or
not (breaking). The remove and replace cases follow the same
constraint-relaxed / constraint-tightened split as minClassifier.
Response scope flips all types via reverseClassifyRuleTransformer.

Made-with: Cursor
The add case distinguishes whether the before schema already has a
numeric exclusiveMaximum covering the new maximum (non-breaking) or
not (breaking). The remove and replace cases follow the same
constraint-relaxed / constraint-tightened split as maxClassifier.
Response scope flips all types via reverseClassifyRuleTransformer.

Made-with: Cursor
Draft-04 boolean exclusiveMinimum/exclusiveMaximum. Six ruleIds capture
the three actions × two value branches (after/before === true vs not).
The unclassified branch is scope-independent; the breaking/non-breaking
branches flip for response scope via reverseClassifyRuleTransformer.

Made-with: Cursor
Replace splits into new-is-divisor-of-old (non-breaking request /
breaking response, mirroring the explicit position[5]=breaking) and
new-is-not-divisor-of-old (breaking in both contexts).

Made-with: Cursor
…fier

Defined locally in jsonSchema.rules.ts alongside the classifier.
Replace uses four ruleIds encoding the (before-truthy × after-truthy)
combination because request checks before.value while response checks
after.value (explicit positions[2/5] in the 6-element classifier).

Made-with: Cursor
Six ruleIds cover the add (ignored-header / required-no-default /
optional-or-has-default), remove (ignored-header / not-ignored-header),
and replace (always-unclassified) cases. Parameters are in request
context so no scope overrides are needed in the YAML.

Also adds all remaining OpenAPI ruleId string constants to
openapi3.classify.ruleIds.ts (used by subsequent rule commits).

Made-with: Cursor
annotation when the explode value is the OpenAPI default for the
parameter style (explode=true for form, explode=false for others);
breaking otherwise. Replace is always breaking.

Made-with: Cursor
…sifyRule

Non-query parameters always yield unclassified. For query parameters
add and remove share the after-in-query ruleId; the YAML action filter
selects non-breaking (add) vs breaking (remove). Replace resolves to
after-true (non-breaking) or after-false (breaking).

Made-with: Cursor
Replace yields annotation when the parameter is a path parameter (the
name change is reflected in the path template) and breaking otherwise.

Made-with: Cursor
Replace yields non-breaking when the schema already has a default value.
When no default is present: breaking if required becomes true, non-breaking
if required becomes false.

Made-with: Cursor
…eterClassifyRule

Uses a single-function ruleId rule since all actions share the same
condition: not-query → unclassified; query + after=true → non-breaking
(reversed booleanClassifier); query + after≠true → breaking.

Made-with: Cursor
…ssifyRule

apihubParametersRemovalClassifyRule is the remove slot in a 3-tuple at
the /parameters array node. The ruleId rule adds static add and replace
slots around it. Remove is non-breaking only when every before-entry is
an ignored header parameter.

Made-with: Cursor
Add yields non-breaking for empty security (no requirements added) and
breaking for non-empty. Remove is always non-breaking. Replace yields
non-breaking when the after-value is a subset of before or is empty.

Made-with: Cursor
…Rule

Add is breaking when the before-parent OR-list was empty (first security
requirement introduced). Remove is breaking only when the after-parent
OR-list is empty (last entry removed). Replace uses subset-or-empty vs
not-subset logic matching the classifier.

Made-with: Cursor
Replace yields annotation when the unified server-prefixed path is
unchanged (only path-parameter placeholder names changed); breaking
otherwise.

The pathChangeClassifyRuleIdRule is attached to the /* wildcard inside
/paths, which also matches specification extensions (x-* keys). A
key-starts-with-'/' guard assigns rest.path.not-applicable to extension
diffs so the OOB classifier correctly reflects their unclassified type.

Made-with: Cursor
…keyword

Adds PATTERN ADD/REMOVE/REPLACE constants, YAML classification with scope:response
overrides, and wires classifyRuleId on /pattern in jsonSchema.rules.

Made-with: Cursor
…eyword

Adds FORMAT ADD/REMOVE/REPLACE constants, YAML classification with scope:response
overrides, and wires classifyRuleId on /format in jsonSchema.rules.

Made-with: Cursor
…ems keyword

Adds UNIQUE_ITEMS_AFTER_TRUE/AFTER_NOT_TRUE/REMOVE constants, wires a
conditional 3-tuple classifyRuleId on the /uniqueItems rule entry, and
adds YAML rules with scope:response overrides (standard booleanClassifier
reversal applies in both directions).

Made-with: Cursor
… and writeOnly keywords

readOnly uses a 6-element rule where response slots are all non-breaking
(not a simple reversal), requiring explicit scope:response entries for
after-true but none for after-not-true and remove. writeOnly is all
non-breaking in every context.

Made-with: Cursor
…keyword

Adds DEFAULT ADD/REMOVE/REPLACE constants, YAML classification rules with
scope:response overrides, and wires classifyRuleId on /default in jsonSchema.rules.

Made-with: Cursor
…yword

Adds CONST ADD/REMOVE/REPLACE constants, YAML classification rules with
scope:response overrides, and wires classifyRuleId on /const in jsonSchema.rules.

Made-with: Cursor
b41ex added 26 commits April 4, 2026 14:12
…tags, schemes, tag object

Adds stable IDs for document metadata (/openapi, /info, /** under info),
servers list root, operation tags array and entries, security scheme
annotation-only properties (bearerFormat, description, openIdConnectUrl),
components.schemas named-definition wrapper, and Tag Object root/field.

Does not attach classifyRuleId to servers /** (deep wildcard merges with
x-* and would mismatch OOB). Operation /* catch-all stays without an id for
the same reason; operation tags use dedicated rest.operation.tags* IDs.

Made-with: Cursor
@github-actions github-actions Bot added documentation Improvements or additions to documentation enhancement New feature or request refactor labels Apr 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request refactor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FE] BWC engine - separate change identification and classification

1 participant