{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://elections.dutystation.ai/data/election-insights.schema.json",
  "title": "DutyStation Senate evidence insights1.0",
  "description": "Schema for analytics.insights in election-lab.json. Descriptive diagnostics; published forecast odds unchanged.",
  "type": "object",
  "required": [
    "schema_version",
    "insights_version",
    "generated_at",
    "model_version",
    "source_hashes",
    "forecast_sha256",
    "sample_sha256",
    "methodology",
    "pathways",
    "poll_sensitivity"
  ],
  "properties": {
    "schema_version": {
      "const": "1.0"
    },
    "generated_at": {
      "type": "string",
      "format": "date-time"
    },
    "model_version": {
      "type": "string"
    },
    "forecast_sha256": {
      "type": "string",
      "pattern": "^[a-f0-9]{64}$"
    },
    "sample_sha256": {
      "type": "string",
      "pattern": "^[a-f0-9]{64}$"
    },
    "pathways": {
      "type": "object",
      "required": [
        "race_order",
        "simulations",
        "control_counts",
        "patterns"
      ],
      "properties": {
        "simulations": {
          "type": "integer",
          "minimum": 1
        },
        "race_order": {
          "type": "array",
          "maxItems": 6,
          "uniqueItems": true,
          "items": {
            "type": "string"
          }
        },
        "patterns": {
          "type": "array",
          "maxItems": 64,
          "items": {
            "type": "object",
            "required": [
              "pattern_id",
              "sample_count",
              "probability",
              "control_counts",
              "joint_control_probability",
              "control_given_pattern",
              "pattern_given_control"
            ],
            "properties": {
              "sample_count": {
                "type": "integer",
                "minimum": 0
              },
              "probability": {
                "type": "number",
                "minimum": 0,
                "maximum": 1
              },
              "control_given_pattern": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "P(control|pattern); null for empty pattern denominator."
              },
              "pattern_given_control": {
                "type": "object",
                "description": "P(pattern|control); individual values null when control count is zero."
              },
              "joint_control_probability": {
                "type": "object",
                "description": "P(pattern AND control), denominator all simulations."
              }
            }
          }
        }
      }
    },
    "poll_sensitivity": {
      "type": "object",
      "required": [
        "scope",
        "races"
      ],
      "properties": {
        "races": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "state",
              "baseline_margin",
              "concentration",
              "leave_one_out",
              "margin_range"
            ],
            "properties": {
              "state": {
                "type": "string"
              },
              "baseline_margin": {
                "type": "number"
              },
              "margin_range": {
                "type": [
                  "array",
                  "null"
                ],
                "description": "Range of available omission projected means, percentage points; not an outcome uncertainty interval."
              },
              "leave_one_out": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "pollster",
                    "available",
                    "margin",
                    "mode",
                    "change_pp"
                  ],
                  "properties": {
                    "pollster": {
                      "type": "string"
                    },
                    "available": {
                      "type": "boolean"
                    },
                    "margin": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "change_pp": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "mode": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}