{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://lems.ai/event-schema.json",
  "title": "LEMs Forecast Document (v1 legacy / v2 canonical)",
  "oneOf": [
    {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "schema_version",
        "forecast",
        "same_type_events",
        "adjacent_events"
      ],
      "properties": {
        "schema_version": {
          "const": "lems.forecast-context.v1"
        },
        "forecast": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "event_type",
            "forecast_time",
            "target_time",
            "question",
            "output"
          ],
          "properties": {
            "event_type": {
              "type": "string",
              "description": "Stable namespace, e.g. finance.bond_trade_price or sports.game_winner."
            },
            "forecast_time": {
              "type": "string",
              "format": "date-time",
              "description": "Information cutoff. Every source_event time must be at or before this timestamp."
            },
            "target_time": {
              "type": "string",
              "format": "date-time"
            },
            "question": {
              "type": "string",
              "maxLength": 10000
            },
            "output": {
              "$ref": "#/$defs/outputSpec"
            },
            "reasoning": {
              "type": "boolean",
              "default": false,
              "description": "Requests a separate hidden deliberation pass when the deployed model supports it; the constrained final output remains the only returned completion."
            }
          }
        },
        "same_type_events": {
          "type": "array",
          "description": "Historical events matching forecast.event_type. Keep the raw fields, outcome and source provenance needed to establish an analogue set.",
          "items": {
            "$ref": "#/$defs/event"
          }
        },
        "adjacent_events": {
          "type": "array",
          "description": "Relevant contemporaneous but different event types: market moves, scheduled releases, team injuries, polling, etc. They must be available before forecast_time.",
          "items": {
            "$ref": "#/$defs/event"
          }
        },
        "assumptions": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "provenance": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          },
          "description": "Dataset identifiers, query hashes, or source URLs. Never send credentials or private identifiers."
        }
      }
    },
    {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "schema_version",
        "forecast",
        "same_type_events",
        "adjacent_events"
      ],
      "properties": {
        "schema_version": {
          "const": "lems.forecast-context.v2"
        },
        "forecast": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "event_type",
            "forecast_time",
            "target_time",
            "question",
            "output",
            "resolution_rule",
            "fields",
            "evidence_refs"
          ],
          "properties": {
            "event_type": {
              "type": "string",
              "description": "Stable namespace, e.g. finance.bond_trade_price or sports.game_winner."
            },
            "forecast_time": {
              "type": "string",
              "format": "date-time",
              "description": "Information cutoff. Every source_event time must be at or before this timestamp."
            },
            "target_time": {
              "type": "string",
              "format": "date-time"
            },
            "question": {
              "type": "string",
              "maxLength": 10000
            },
            "output": {
              "$ref": "#/$defs/outputSpec"
            },
            "reasoning": {
              "type": "boolean",
              "default": false,
              "description": "Requests a separate hidden deliberation pass when the deployed model supports it; the constrained final output remains the only returned completion."
            },
            "resolution_rule": {
              "type": "string",
              "minLength": 1
            },
            "fields": {
              "type": "object",
              "additionalProperties": true
            },
            "evidence_refs": {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "field",
                  "event_id"
                ],
                "properties": {
                  "field": {
                    "type": "string",
                    "description": "Top-level target field supported by this evidence event."
                  },
                  "event_id": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "same_type_events": {
          "type": "array",
          "description": "Historical events matching forecast.event_type. Keep the raw fields, outcome and source provenance needed to establish an analogue set.",
          "items": {
            "$ref": "#/$defs/event"
          }
        },
        "adjacent_events": {
          "type": "array",
          "description": "Relevant contemporaneous but different event types: market moves, scheduled releases, team injuries, polling, etc. They must be available before forecast_time.",
          "items": {
            "$ref": "#/$defs/event"
          }
        }
      }
    }
  ],
  "$defs": {
    "event": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "event_id",
        "event_type",
        "observed_at",
        "fields"
      ],
      "properties": {
        "event_id": {
          "type": "string"
        },
        "event_type": {
          "type": "string"
        },
        "observed_at": {
          "type": "string",
          "format": "date-time"
        },
        "available_at": {
          "type": "string",
          "format": "date-time",
          "description": "When this fact became knowable. Must be <= forecast.forecast_time."
        },
        "fields": {
          "type": "object",
          "additionalProperties": true
        },
        "outcome": {
          "type": [
            "object",
            "string",
            "number",
            "boolean",
            "null"
          ]
        },
        "source": {
          "type": "string"
        }
      }
    },
    "outputSpec": {
      "oneOf": [
        {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "kind",
            "values"
          ],
          "properties": {
            "kind": {
              "const": "categorical"
            },
            "values": {
              "type": "array",
              "minItems": 1,
              "maxItems": 100,
              "items": {
                "type": "string",
                "minLength": 1
              }
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "kind"
          ],
          "properties": {
            "kind": {
              "const": "binary"
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "kind",
            "minimum",
            "maximum"
          ],
          "properties": {
            "kind": {
              "const": "int"
            },
            "minimum": {
              "type": "integer"
            },
            "maximum": {
              "type": "integer"
            },
            "increment": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "kind",
            "minimum",
            "maximum",
            "precision",
            "scientific"
          ],
          "properties": {
            "kind": {
              "const": "float"
            },
            "minimum": {
              "type": "string",
              "pattern": "^-?[0-9]+(\\.[0-9]+)?$"
            },
            "maximum": {
              "type": "string",
              "pattern": "^-?[0-9]+(\\.[0-9]+)?$"
            },
            "increment": {
              "type": [
                "string",
                "null"
              ]
            },
            "precision": {
              "type": "integer",
              "minimum": 0,
              "maximum": 12
            },
            "scientific": {
              "type": "boolean"
            }
          }
        }
      ]
    }
  }
}
