{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/auditae-app/json-schema/auditae-app-crawl-comparison-schema.json",
  "title": "CrawlComparison",
  "description": "What changed between two Site Audit runs of a site (version 1, ≤40 KB). mode page: same check version, so new / fixed / removed are counted from the stored per-page results (pages for page checks, 0/1 for site-wide checks, the change in n for link, image and script checks). mode summary: different check versions — totals only; new / fixed and the deltas are null.",
  "x-generated": "2026-11-02",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/auditae-app-openapi.json#/components/schemas/CrawlComparison",
  "type": "object",
  "required": [
    "v",
    "base_run_id",
    "base_started_at",
    "mode",
    "versions_match",
    "health",
    "counts",
    "themes",
    "totals",
    "checks",
    "pages",
    "robots",
    "sitemap"
  ],
  "additionalProperties": true,
  "properties": {
    "v": {
      "type": "integer",
      "const": 1
    },
    "base_run_id": {
      "type": "string",
      "format": "uuid"
    },
    "base_started_at": {
      "type": "string",
      "format": "date-time"
    },
    "mode": {
      "type": "string",
      "enum": [
        "page",
        "summary"
      ]
    },
    "versions_match": {
      "type": "boolean"
    },
    "scope_changed": {
      "type": "boolean",
      "description": "The runs' crawl settings scope differs (source, URL list, include/exclude rules, ignored parameters, subdomains or robots group); pages added and removed are then null."
    },
    "note": {
      "type": "string"
    },
    "health": {
      "type": "object",
      "properties": {
        "from": {
          "type": [
            "integer",
            "null"
          ]
        },
        "to": {
          "type": "integer"
        },
        "delta": {
          "type": [
            "integer",
            "null"
          ],
          "description": "null when the check versions differ."
        }
      }
    },
    "counts": {
      "type": "object",
      "additionalProperties": true,
      "description": "errors, warnings, notices: { from, to } failing items."
    },
    "themes": {
      "type": "object",
      "propertyNames": {
        "enum": [
          "crawlability",
          "https",
          "international",
          "core_web_vitals",
          "performance",
          "internal_linking",
          "markup",
          "ai_search",
          "on_page"
        ]
      },
      "additionalProperties": {
        "type": "object",
        "properties": {
          "from": {
            "type": [
              "integer",
              "null"
            ]
          },
          "to": {
            "type": [
              "integer",
              "null"
            ]
          },
          "delta": {
            "type": [
              "integer",
              "null"
            ]
          }
        }
      },
      "description": "Per theme score from → to. Core Web Vitals fill in when they're measured, a few minutes after the crawl."
    },
    "totals": {
      "type": "object",
      "properties": {
        "new_errors": {
          "type": [
            "integer",
            "null"
          ]
        },
        "fixed_errors": {
          "type": [
            "integer",
            "null"
          ]
        },
        "new_items": {
          "type": [
            "integer",
            "null"
          ]
        },
        "fixed_items": {
          "type": [
            "integer",
            "null"
          ]
        }
      }
    },
    "checks": {
      "type": "array",
      "maxItems": 60,
      "description": "Changed checks only, biggest change in Site Health penalty first.",
      "items": {
        "type": "object",
        "required": [
          "id",
          "severity",
          "from",
          "to",
          "new",
          "fixed"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "severity": {
            "type": "string",
            "enum": [
              "error",
              "warning",
              "notice"
            ]
          },
          "from": {
            "type": "integer",
            "description": "Failing items on the base run."
          },
          "to": {
            "type": "integer",
            "description": "Failing items now."
          },
          "new": {
            "type": [
              "integer",
              "null"
            ]
          },
          "fixed": {
            "type": [
              "integer",
              "null"
            ]
          },
          "removed": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Page checks: pages failing on the base run that this crawl didn't reach."
          },
          "new_s": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 3,
            "description": "Sample URLs newly failing."
          },
          "fixed_s": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 3,
            "description": "Sample URLs fixed (page checks only)."
          }
        }
      }
    },
    "pages": {
      "type": [
        "object",
        "null"
      ],
      "additionalProperties": true,
      "description": "Page mode: comparable (false when a crawl stopped at max_pages: added and removed are then null), added, removed, status_changed, became_broken, became_noindex, became_indexable, title_changed, samples { added, removed, status: [{ url, from, to }] }."
    },
    "robots": {
      "type": "object",
      "properties": {
        "changed": {
          "type": "boolean"
        },
        "added_rules": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "User-agent: * rules added, e.g. \"Disallow: /cart\"."
        },
        "removed_rules": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    },
    "sitemap": {
      "type": "object",
      "properties": {
        "urls_from": {
          "type": "integer"
        },
        "urls_to": {
          "type": "integer"
        }
      }
    }
  }
}