DocsPage
← back to delimit.ai
DELIMIT.AI/DOCS/CHANGES

27 typed change classes

The deterministic taxonomy Delimit's merge gate uses to classify every change in AI-written code before issuing a signed, replayable attestation.

Every change in an OpenAPI diff falls into one of 27 typed classes. Each class has a name, a canonical example, a severity disposition (breaking, additive, or hygiene), and a short consumer-impact note. The merge gate emits a structured record per change; the records are what gets signed into the attestation. This page is the canonical reference.

Source of truth: the ChangeType enum in core/diff_engine_v2.py (lines 10 to 40). The is_breaking property (lines 51 to 70) defines the severity partition shown below.

breaking
17

Wire-incompatible. Existing consumers fail without code change.

additive
9

Pure expansion. Existing consumers keep working unchanged.

hygiene
1

Spec-doc churn. No consumer effect; surfaced for review.

The 27 types

Anchor links are stable. Reports under delimit.ai/reports/ link type IDs back to the matching anchor on this page.

  1. endpoint_removedbreaking

    A path that existed in the old spec is absent from the new spec. Any consumer call to the old path returns 404.

    # old
    paths:
      /v2/organizations/{orgId}/workflows: { get: { ... } }
    
    # new (path absent)

    Live finding: cal.com F2 (99 endpoints removed)

  2. method_removedbreaking

    A specific HTTP method on an existing path is gone. The path may still resolve for other methods, but the dropped verb returns 405.

    # old
    /users/{id}:
      delete: { ... }
      get:    { ... }
    
    # new
    /users/{id}:
      get: { ... }
  3. required_param_addedbreaking

    A new request parameter is marked required. Consumers who do not send it now fail validation at the gateway.

    # new
    parameters:
      - name: tenant_id
        in: query
        required: true
        schema: { type: string }
  4. param_removedbreaking

    A parameter consumers may have been sending is gone. Senders get a strict-mode rejection or silent ignore depending on the runtime.

    # old
    parameters:
      - { name: before, in: query, schema: { type: string } }
    
    # new (parameter absent)

    Live finding: OpenAI F4 (before, cert_id removals)

  5. response_removedbreaking

    A documented response code (e.g. 200, 404) on an operation is no longer declared. Consumers parsing strictly typed clients may not have a branch for the new behavior.

    # old
    responses:
      '200': { ... }
      '404': { ... }
    
    # new
    responses:
      '200': { ... }
  6. required_field_addedbreaking

    A field becomes required on a request schema. Existing consumer payloads that omit the field now fail validation.

    # new
    UserCreate:
      required: [email, name, tenant_id]
      properties:
        email:     { type: string }
        name:      { type: string }
        tenant_id: { type: string }

    Live finding: OpenAI F2 (55 new required fields)

  7. field_removedbreaking

    A schema property is gone. Code that reads the field from a response, or writes it on a request, hits an undefined or rejected field.

    # old
    WebauthnVerify:
      properties:
        rpId:       { type: string }
        rpOrigins:  { type: array, items: { type: string } }
    
    # new
    WebauthnVerify:
      properties: {}

    Live finding: Supabase F1, F2 (rpId, rpOrigins dropped)

  8. type_changedbreaking

    A schema property changed JSON type (string to object, array to string, etc.). Any deserializer with a fixed shape breaks on parse.

    # old
    redirect_uri:
      type: string
    
    # new
    redirect_uris:
      type: array
      items: { type: string }

    Live finding: OpenAI F1 (196 type_changed events)

  9. format_changedbreaking

    The string format on a property changed (date to date-time, uuid to plain string, etc.). Validators with format-aware parsers reject the new shape.

    # old
    created_at:
      type: string
      format: date
    
    # new
    created_at:
      type: string
      format: date-time
  10. enum_value_removedbreaking

    A value disappears from an enum. Consumers sending the dropped value get rejected; consumers branching on the dropped value have dead code paths but no break on read.

    # old
    trigger:
      enum: [BOOKING_CREATED, BOOKING_RESCHEDULED, ROUTING_FORM_FALLBACK_HIT]
    
    # new
    trigger:
      enum: [BOOKING_CREATED, BOOKING_RESCHEDULED]

    Live finding: cal.com F5 (ROUTING_FORM_FALLBACK_HIT)

  11. param_type_changedbreaking

    A parameter (path, query, header) changed type. Senders coercing to the old type get rejected at the boundary.

    # old
    - name: limit
      in: query
      schema: { type: string }
    
    # new
    - name: limit
      in: query
      schema: { type: integer }
  12. param_required_changedbreaking

    A parameter flipped its required disposition. The breaking direction is optional-to-required (forces senders to update); required-to-optional flips also surface here for visibility.

    # old
    - name: org_id
      in: query
      required: false
    
    # new
    - name: org_id
      in: query
      required: true
  13. response_type_changedbreaking

    The schema type of a response changed (e.g. content-type or top-level shape). Strictly typed clients fail to deserialize.

    # old
    responses:
      '200':
        content:
          application/json:
            schema: { type: object }
    
    # new
    responses:
      '200':
        content:
          application/json:
            schema: { type: array, items: { type: object } }
  14. security_removedbreaking

    A security scheme (oauth2 flow, apiKey, http bearer) was removed. Calls authenticated via that scheme now fail authorization.

    # old
    components:
      securitySchemes:
        bearerAuth: { type: http, scheme: bearer }
    
    # new
    components:
      securitySchemes: {}
  15. security_scope_removedbreaking

    An OAuth2 scope was dropped from a flow. Tokens minted against the removed scope no longer authorize calls that required it.

    # old
    flows:
      authorizationCode:
        scopes:
          read:bookings:  Read bookings
          write:bookings: Write bookings
    
    # new
    flows:
      authorizationCode:
        scopes:
          read:bookings: Read bookings
  16. max_length_decreasedbreaking

    A string or array maxLength dropped. Existing values longer than the new limit fail validation on write and may flag on read.

    # old
    description:
      type: string
      maxLength: 500
    
    # new
    description:
      type: string
      maxLength: 200
  17. min_length_increasedbreaking

    A string or array minLength rose. Existing values shorter than the new floor fail validation.

    # old
    password:
      type: string
      minLength: 8
    
    # new
    password:
      type: string
      minLength: 12
  18. endpoint_addedadditive

    A new path landed. No effect on existing consumers; they keep ignoring routes they never called.

    # new
    paths:
      /v2/calendars/connections:
        post: { ... }

    Live finding: cal.com F4 (7 new calendar routes)

  19. method_addedadditive

    A new HTTP method on an existing path. Existing callers on other verbs are unaffected.

    # old
    /users/{id}:
      get: { ... }
    
    # new
    /users/{id}:
      get:    { ... }
      patch:  { ... }
  20. optional_param_addedadditive

    A new parameter with required: false. Existing senders omitting it keep working.

    # new
    parameters:
      - name: include_archived
        in: query
        required: false
        schema: { type: boolean }
  21. response_addedadditive

    A new documented response code. Existing clients that did not branch on it remain correct because the operation can return it for new behavior only.

    # old
    responses:
      '200': { ... }
    
    # new
    responses:
      '200': { ... }
      '202': { ... }
  22. optional_field_addedadditive

    A new property added with required: false. Existing read-side code ignores unknown fields; write-side code keeps omitting it.

    # new
    Recipient:
      properties:
        email:               { type: string }
        delivery_preference: { type: string }   # newly added, optional

    Live finding: DocuSign F1 (delivery_preference, 11 roles)

  23. enum_value_addedadditive

    A new accepted enum value. Existing senders keep working; readers may want to add a branch for the new value.

    # old
    status:
      enum: [pending, sent, delivered]
    
    # new
    status:
      enum: [pending, sent, delivered, queued, retrying]

    Live finding: Twilio F1 (4 new status values)

  24. security_addedadditive

    A new security scheme available. Existing authenticated calls keep working under the prior schemes.

    # new
    components:
      securitySchemes:
        apiKeyAuth:
          type: apiKey
          in:   header
          name: X-API-Key
  25. deprecated_addedadditive

    An operation or field was marked deprecated. The contract still works at runtime; the marker is signal to consumers that removal is coming.

    # new
    /v1/legacy/users:
      get:
        deprecated: true
        summary: Use /v2/users instead
  26. default_changedadditive

    A property default value changed. Senders who omit the field now get the new default, which is a behavior change but does not fail validation.

    # old
    page_size:
      type:    integer
      default: 25
    
    # new
    page_size:
      type:    integer
      default: 50
  27. description_changedhygiene

    Documentation text was edited without changing schema or surface. No consumer effect; recorded so spec-doc churn is visible to attestation review.

    # old
    summary: Get user by id
    
    # new
    summary: Retrieve a user by their unique identifier

How the gate uses these

On every diff, the engine emits one record per change. Each record carries the typed class above, the severity, and the path or schema affected. The semver classifier walks the record set: any breaking class promotes the diff to MAJOR; only additive classes hold it at MINOR; only hygiene classes hold it at PATCH. There is no fuzzy scoring step.

The full record set is what gets signed into the attestation. A consumer who replays the attestation sees the same 27 typed classes, the same per-record evidence, and the same semver classification. That is the deterministic part of the deterministic taxonomy: same inputs, same record set, same bytes.

For AI-written code, this is the merge gate. For an AI-assisted merge, this is the audit trail. The signed, replayable attestation is the artifact downstream consumers verify against.