{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://siteline.to/schemas/scan-result.schema.json",
  "title": "Siteline Scan Result",
  "description": "The structured result of a Siteline agent-readiness scan. Covers Signal, Navigate, Absorb, and Perform pillars.",
  "type": "object",
  "required": ["ok", "normalizedURL", "domain", "scannedAt", "grade", "score", "label"],
  "properties": {
    "ok": { "type": "boolean", "const": true },
    "normalizedURL": { "type": "string", "format": "uri" },
    "domain": { "type": "string" },
    "scannedAt": { "type": "string", "format": "date-time" },
    "resultId": { "type": "string", "description": "Stable identifier. Homepage scans use domain-slug-YYYYMMDD; path/query-scoped scans use domain-slug-path-scope-hash-YYYYMMDD." },
    "grade": { "type": "string", "enum": ["A", "B", "C", "D", "F"] },
    "score": { "type": "integer", "minimum": 0, "maximum": 100 },
    "label": {
      "type": "string",
      "enum": ["Agent-Usable", "Mostly Usable", "Needs Clearer Paths", "Hard for Agents", "Agent-Blocked or Unusable"]
    },
    "likelyFailureMode": { "type": "string" },
    "pillars": {
      "type": "object",
      "description": "Per-pillar scores (0-100).",
      "properties": {
        "access": { "type": "integer", "minimum": 0, "maximum": 100 },
        "navigability": { "type": "integer", "minimum": 0, "maximum": 100 },
        "readability": { "type": "integer", "minimum": 0, "maximum": 100 },
        "actionHandoff": { "type": "integer", "minimum": 0, "maximum": 100 }
      }
    },
    "provenance": {
      "type": "object",
      "properties": {
        "rubricVersion": { "type": "string" },
        "scannerVersion": { "type": "string" },
        "scanDurationMs": { "type": "integer" },
        "pagesFetched": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "url": { "type": ["string", "null"] },
              "statusCode": { "type": ["integer", "null"] },
              "role": { "type": "string", "enum": ["primary", "robots", "llms-txt", "agents-json", "feed", "sitemap", "route", "https-probe"] }
            }
          }
        },
        "checksRun": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "pillar": { "type": "string" },
              "check": { "type": "string" },
              "status": { "type": "string", "enum": ["pass", "warn", "fail", "blocked", "not_applicable"] }
            }
          }
        },
        "agentUAsTested": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "userAgent": { "type": "string" },
              "statusCode": { "type": "integer" },
              "blocked": { "type": "boolean" }
            }
          }
        }
      }
    },
    "page": {
      "type": "object",
      "properties": {
        "statusCode": { "type": "integer" },
        "timedOut": { "type": "boolean" },
        "botBlocked": { "type": "boolean" },
        "blockType": { "type": ["string", "null"] }
      }
    },
    "robots": {
      "type": "object",
      "properties": {
        "url": { "type": ["string", "null"] },
        "statusCode": { "type": ["integer", "null"] },
        "ok": { "type": "boolean" }
      }
    },
    "informationalResources": {
      "type": "object",
      "properties": {
        "llmsTxt": {
          "type": ["object", "null"],
          "properties": {
            "url": { "type": "string" },
            "statusCode": { "type": "integer" },
            "ok": { "type": "boolean" }
          }
        },
        "agentsJson": {
          "type": ["object", "null"],
          "properties": {
            "url": { "type": "string" },
            "statusCode": { "type": "integer" },
            "ok": { "type": "boolean" }
          }
        }
      }
    },
    "summary": {
      "type": "object",
      "properties": {
        "headline": { "type": "string" },
        "detail": { "type": "string" }
      }
    },
    "findings": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "status": { "type": "string", "enum": ["pass", "warn", "fail", "blocked", "not_applicable"] },
          "reason": { "type": "string" },
          "title": { "type": "string" },
          "impact": { "type": "string" },
          "remediation": { "type": ["string", "null"] },
          "group": { "type": "string", "enum": ["blockers", "coreIssues", "opportunities"] },
          "summary": { "type": "string" },
          "confidence": { "type": "string", "enum": ["high", "medium", "low"] },
          "evidence": {
            "type": "object",
            "description": "Raw evidence for reproducibility (present on serverReachability findings).",
            "properties": {
              "url": { "type": ["string", "null"] },
              "statusCode": { "type": "integer" },
              "blockType": { "type": ["string", "null"] },
              "serverHeader": { "type": ["string", "null"] },
              "bodyExcerpt": { "type": ["string", "null"] }
            }
          }
        }
      }
    },
    "findingGroups": {
      "type": "object",
      "properties": {
        "blockers": { "type": "array" },
        "coreIssues": { "type": "array" },
        "opportunities": { "type": "array" }
      }
    },
    "agenticEnablement": {
      "type": "object",
      "description": "Layer 2 assessment: qualitative evaluation of machine-readable resources the site provides for AI agents. The level caps the maximum achievable grade.",
      "properties": {
        "level": {
          "type": "integer",
          "minimum": 0,
          "maximum": 4,
          "description": "Agentic enablement level. 0=no resources (cap D), 1=minimal (cap D), 2=moderate (cap C), 3=strong (cap B), 4=comprehensive (no cap, can reach A)."
        },
        "totalQuality": {
          "type": "integer",
          "minimum": 0,
          "description": "Sum of quality scores across all assessed purposes. Each purpose scores 0 (absent), 1 (present but weak), or 2 (well-implemented)."
        },
        "maxQuality": {
          "type": "integer",
          "description": "Maximum possible quality score (number of purposes times 2)."
        },
        "purposes": {
          "type": "object",
          "description": "Per-purpose quality scores. Where multiple resources serve the same purpose, the best score counts.",
          "additionalProperties": {
            "type": "integer",
            "minimum": 0,
            "maximum": 2
          }
        },
        "details": {
          "type": "object",
          "description": "Per-resource quality scores (individual resource breakdown).",
          "additionalProperties": {
            "type": "integer",
            "minimum": 0,
            "maximum": 2
          }
        }
      }
    },
    "remediationTier": {
      "type": "string",
      "enum": ["self-fix", "workshop", "audit", "none"],
      "description": "Suggested remediation approach based on the primary failure mode."
    },
    "requestId": { "type": "string" },
    "_cacheStatus": { "type": "string", "enum": ["HIT", "KV_HIT", "MISS"] },
    "_rescanBlocked": { "type": "boolean" }
  }
}
