{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Report",
  "description": "The top-level report envelope (SPEC_02).",
  "type": "object",
  "properties": {
    "checks": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/CheckResult"
      }
    },
    "created_at": {
      "type": "string"
    },
    "expires_at": {
      "type": "string"
    },
    "input": {
      "$ref": "#/$defs/InputInfo"
    },
    "meshcheck_version": {
      "type": "string"
    },
    "profile": {
      "$ref": "#/$defs/ProfileReport"
    },
    "report_id": {
      "type": "string"
    },
    "schema_version": {
      "type": "string"
    },
    "screenshots": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/Screenshot"
      }
    },
    "stats": {
      "$ref": "#/$defs/Stats"
    },
    "summary": {
      "$ref": "#/$defs/Summary"
    },
    "timing_ms": {
      "$ref": "#/$defs/Timing"
    },
    "verdict": {
      "$ref": "#/$defs/Verdict"
    },
    "verdict_confidence": {
      "anyOf": [
        {
          "$ref": "#/$defs/VerdictConfidence"
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "required": [
    "schema_version",
    "report_id",
    "created_at",
    "expires_at",
    "input",
    "profile",
    "verdict",
    "summary",
    "stats",
    "checks",
    "screenshots",
    "timing_ms",
    "meshcheck_version"
  ],
  "$defs": {
    "Aabb": {
      "description": "Axis-aligned bounding box.",
      "type": "object",
      "properties": {
        "max": {
          "type": "array",
          "items": {
            "type": "number",
            "format": "double"
          },
          "maxItems": 3,
          "minItems": 3
        },
        "min": {
          "type": "array",
          "items": {
            "type": "number",
            "format": "double"
          },
          "maxItems": 3,
          "minItems": 3
        }
      },
      "required": [
        "min",
        "max"
      ]
    },
    "Angle": {
      "description": "Camera angle for a screenshot (vertical/horizontal degrees).",
      "type": "object",
      "properties": {
        "rh": {
          "type": "number",
          "format": "double"
        },
        "rv": {
          "type": "number",
          "format": "double"
        }
      },
      "required": [
        "rv",
        "rh"
      ]
    },
    "Category": {
      "description": "A check's functional category.",
      "type": "string",
      "enum": [
        "spec",
        "geometry",
        "transform",
        "uv",
        "material",
        "performance",
        "render",
        "vision",
        "topology"
      ]
    },
    "CheckResult": {
      "description": "A single check result (SPEC_02 CheckResult).",
      "type": "object",
      "properties": {
        "category": {
          "$ref": "#/$defs/Category"
        },
        "deterministic": {
          "type": "boolean"
        },
        "id": {
          "type": "string"
        },
        "locations": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/Location"
          }
        },
        "locations_truncated": {
          "type": [
            "boolean",
            "null"
          ]
        },
        "measured": true,
        "message": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "severity": {
          "$ref": "#/$defs/Severity"
        },
        "skip_reason": {
          "type": [
            "string",
            "null"
          ]
        },
        "status": {
          "$ref": "#/$defs/Status"
        },
        "threshold": true
      },
      "required": [
        "id",
        "name",
        "category",
        "severity",
        "status",
        "measured",
        "threshold",
        "message",
        "locations",
        "deterministic"
      ]
    },
    "InputFormat": {
      "description": "Detected input container format.",
      "type": "string",
      "enum": [
        "glb",
        "gltf"
      ]
    },
    "InputInfo": {
      "description": "Input file description.",
      "type": "object",
      "properties": {
        "bytes": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0
        },
        "filename": {
          "type": "string"
        },
        "format": {
          "$ref": "#/$defs/InputFormat"
        },
        "gltf_version": {
          "type": [
            "string",
            "null"
          ]
        },
        "sha256": {
          "type": "string"
        }
      },
      "required": [
        "filename",
        "bytes",
        "sha256",
        "format"
      ]
    },
    "Location": {
      "description": "A pointer to an offending entity in the asset.",
      "type": "object",
      "properties": {
        "detail": true,
        "index": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0
        },
        "kind": {
          "$ref": "#/$defs/LocationKind"
        },
        "name": {
          "type": [
            "string",
            "null"
          ]
        }
      },
      "required": [
        "kind",
        "index",
        "detail"
      ]
    },
    "LocationKind": {
      "description": "The kind of entity a [`Location`] points at.\n\n`Resource` covers references that are not indexable scene entities: an external URI (SPEC-003)\nor a validator JSON pointer (SPEC-001). For those the URI/pointer string lives in `name` and\n`index` is the position in the offending list.",
      "type": "string",
      "enum": [
        "mesh",
        "primitive",
        "material",
        "node",
        "image",
        "resource"
      ]
    },
    "ProfileReport": {
      "description": "The `profile` block: name, applied overrides, and the fully resolved values used.",
      "type": "object",
      "properties": {
        "name": {
          "type": "string"
        },
        "overrides": {
          "type": "object",
          "additionalProperties": true
        },
        "resolved": {
          "$ref": "#/$defs/ResolvedProfile"
        }
      },
      "required": [
        "name",
        "overrides",
        "resolved"
      ]
    },
    "ResolvedProfile": {
      "description": "A fully resolved budget profile. Serialises into the report `profile.resolved` block.",
      "type": "object",
      "properties": {
        "max_draw_calls": {
          "type": "integer",
          "format": "uint32",
          "minimum": 0
        },
        "max_extent": {
          "type": "number",
          "format": "double"
        },
        "max_file_bytes": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0
        },
        "max_materials": {
          "type": "integer",
          "format": "uint32",
          "minimum": 0
        },
        "max_texture_dim": {
          "type": "integer",
          "format": "uint32",
          "minimum": 0
        },
        "max_texture_mem": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0
        },
        "max_tris": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0
        },
        "max_verts": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0
        },
        "min_extent": {
          "type": "number",
          "format": "double"
        }
      },
      "required": [
        "max_tris",
        "max_verts",
        "max_texture_dim",
        "max_texture_mem",
        "max_materials",
        "max_draw_calls",
        "max_file_bytes",
        "min_extent",
        "max_extent"
      ]
    },
    "Screenshot": {
      "description": "A rendered screenshot descriptor.",
      "type": "object",
      "properties": {
        "angle": {
          "$ref": "#/$defs/Angle"
        },
        "backend": {
          "type": "string"
        },
        "expires_at": {
          "type": "string"
        },
        "height": {
          "type": "integer",
          "format": "uint32",
          "minimum": 0
        },
        "id": {
          "type": "string"
        },
        "kind": {
          "$ref": "#/$defs/ScreenshotKind"
        },
        "render_hash": {
          "type": "string"
        },
        "url": {
          "type": "string"
        },
        "width": {
          "type": "integer",
          "format": "uint32",
          "minimum": 0
        }
      },
      "required": [
        "id",
        "angle",
        "kind",
        "width",
        "height",
        "url",
        "expires_at",
        "backend",
        "render_hash"
      ]
    },
    "ScreenshotKind": {
      "description": "Screenshot media kind.",
      "type": "string",
      "enum": [
        "still",
        "turntable"
      ]
    },
    "Severity": {
      "description": "A check's configured severity.",
      "type": "string",
      "enum": [
        "error",
        "warning",
        "info"
      ]
    },
    "Stats": {
      "description": "Scene statistics. Zeroed in P0M1 (no parsing yet).",
      "type": "object",
      "properties": {
        "aabb": {
          "$ref": "#/$defs/Aabb"
        },
        "animations": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0
        },
        "draw_call_estimate": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0
        },
        "extent": {
          "type": "array",
          "items": {
            "type": "number",
            "format": "double"
          },
          "maxItems": 3,
          "minItems": 3
        },
        "materials": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0
        },
        "meshes": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0
        },
        "nodes": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0
        },
        "primitives": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0
        },
        "skins": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0
        },
        "texture_memory_bytes": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0
        },
        "textures": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0
        },
        "triangles": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0
        },
        "vertices": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0
        }
      },
      "required": [
        "triangles",
        "vertices",
        "meshes",
        "primitives",
        "materials",
        "textures",
        "texture_memory_bytes",
        "draw_call_estimate",
        "nodes",
        "aabb",
        "extent",
        "animations",
        "skins"
      ]
    },
    "Status": {
      "description": "A check's result status.",
      "type": "string",
      "enum": [
        "pass",
        "warn",
        "fail",
        "skipped",
        "error"
      ]
    },
    "Summary": {
      "description": "Counts of findings, by bucket.",
      "type": "object",
      "properties": {
        "errors": {
          "type": "integer",
          "format": "uint32",
          "minimum": 0
        },
        "info": {
          "type": "integer",
          "format": "uint32",
          "minimum": 0
        },
        "skipped": {
          "type": "integer",
          "format": "uint32",
          "minimum": 0
        },
        "warnings": {
          "type": "integer",
          "format": "uint32",
          "minimum": 0
        }
      },
      "required": [
        "errors",
        "warnings",
        "info",
        "skipped"
      ]
    },
    "Timing": {
      "description": "Timing breakdown, milliseconds. Excluded from determinism hashing.",
      "type": "object",
      "properties": {
        "checks": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0
        },
        "parse": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0
        },
        "render": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0
        },
        "total": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0
        }
      },
      "required": [
        "total",
        "parse",
        "checks",
        "render"
      ]
    },
    "Verdict": {
      "description": "Overall verdict rollup.",
      "type": "string",
      "enum": [
        "pass",
        "warn",
        "fail"
      ]
    },
    "VerdictConfidence": {
      "description": "Confidence qualifier on the verdict. `Partial` when an engine-level `error` status occurred.",
      "type": "string",
      "enum": [
        "partial"
      ]
    }
  }
}
