{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://torneo.ai/schemas/availability_window.v1",
  "title": "availability_window.v1",
  "description": "Read availability over a window computed offline from the production probe receipts (tools/availability_report.py build_report). A day without a valid receipt is never up: PASS and FAIL need a complete window, INCOMPLETE lists the missing days, NO_DATA has no covered day.",
  "type": "object",
  "required": [
    "schema",
    "base_url",
    "criterion_pct",
    "window",
    "first_receipt",
    "covered_days",
    "missing_days",
    "reads",
    "reads_up",
    "availability_pct",
    "covered_only",
    "lower_bound_pct",
    "by_kind",
    "ignored_other_origin",
    "problems",
    "verdict",
    "note"
  ],
  "additionalProperties": false,
  "properties": {
    "schema": {
      "const": "availability_window.v1"
    },
    "base_url": {
      "type": "string",
      "minLength": 1
    },
    "criterion_pct": {
      "type": "number"
    },
    "window": {
      "type": "object",
      "required": [
        "start",
        "end",
        "requested_days"
      ],
      "additionalProperties": false,
      "properties": {
        "start": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "end": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "requested_days": {
          "type": "integer",
          "minimum": 1
        }
      }
    },
    "first_receipt": {
      "anyOf": [
        {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        {
          "type": "null"
        }
      ]
    },
    "covered_days": {
      "type": "integer",
      "minimum": 0
    },
    "missing_days": {
      "type": "array",
      "items": {
        "type": "string",
        "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
      }
    },
    "reads": {
      "type": "integer",
      "minimum": 0
    },
    "reads_up": {
      "type": "integer",
      "minimum": 0
    },
    "availability_pct": {
      "type": [
        "number",
        "null"
      ],
      "minimum": 0,
      "maximum": 100
    },
    "covered_only": {
      "type": "boolean"
    },
    "lower_bound_pct": {
      "type": "number",
      "minimum": 0,
      "maximum": 100
    },
    "by_kind": {
      "type": "object",
      "additionalProperties": {
        "type": "object",
        "required": [
          "reads",
          "up"
        ],
        "additionalProperties": false,
        "properties": {
          "reads": {
            "type": "integer",
            "minimum": 0
          },
          "up": {
            "type": "integer",
            "minimum": 0
          }
        }
      }
    },
    "ignored_other_origin": {
      "type": "integer",
      "minimum": 0
    },
    "problems": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "verdict": {
      "enum": [
        "PASS",
        "FAIL",
        "INCOMPLETE",
        "NO_DATA"
      ]
    },
    "note": {
      "type": "string"
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "verdict": {
            "const": "PASS"
          }
        },
        "required": [
          "verdict"
        ]
      },
      "then": {
        "properties": {
          "missing_days": {
            "maxItems": 0
          },
          "covered_only": {
            "const": false
          },
          "covered_days": {
            "minimum": 1
          },
          "availability_pct": {
            "minimum": 99.5
          }
        }
      }
    },
    {
      "if": {
        "properties": {
          "verdict": {
            "const": "FAIL"
          }
        },
        "required": [
          "verdict"
        ]
      },
      "then": {
        "properties": {
          "missing_days": {
            "maxItems": 0
          },
          "covered_only": {
            "const": false
          },
          "covered_days": {
            "minimum": 1
          },
          "availability_pct": {
            "exclusiveMaximum": 99.5
          }
        }
      }
    },
    {
      "if": {
        "properties": {
          "verdict": {
            "const": "INCOMPLETE"
          }
        },
        "required": [
          "verdict"
        ]
      },
      "then": {
        "properties": {
          "missing_days": {
            "minItems": 1
          },
          "covered_only": {
            "const": true
          },
          "covered_days": {
            "minimum": 1
          }
        }
      }
    },
    {
      "if": {
        "properties": {
          "verdict": {
            "const": "NO_DATA"
          }
        },
        "required": [
          "verdict"
        ]
      },
      "then": {
        "properties": {
          "covered_days": {
            "const": 0
          },
          "reads": {
            "const": 0
          }
        }
      }
    }
  ]
}
