{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://lems.ai/event-schema.json",
  "type": "object",
  "additionalProperties": false,
  "required": ["schema_version", "variables", "forecast", "same_type_events", "adjacent_events", "factors"],
  "properties": {
    "schema_version": {"const": "lems.forecast-context.v3"},
    "variables": {"type": "object", "minProperties": 1, "maxProperties": 128, "propertyNames": {"$ref": "#/$defs/code", "not": {"pattern": "target_answer|realized_target|target_outcome|target_realized|instructions?|system_prompt|probabilities|ignore_rules|ignore_prior|ignore_system|override_system|always_answer|always_output|emit_answer"}}, "additionalProperties": {"$ref": "#/$defs/variable"}},
    "forecast": {"$ref": "#/$defs/forecast"},
    "same_type_events": {"$ref": "#/$defs/events"},
    "adjacent_events": {"$ref": "#/$defs/events"},
    "factors": {"$ref": "#/$defs/events"}
  },
  "$defs": {
    "code": {"type": "string", "maxLength": 32, "pattern": "^[a-z][a-z0-9]{0,11}(?:_[a-z0-9]{1,11}){0,2}$(?![\\s\\S])"},
    "category": {"type": "string", "minLength": 1, "maxLength": 100, "format": "forecast-category", "pattern": "^[^\\s\\u0000-\\u001f\\u007f-\\u009f\\u2028\\u2029](?:[^\\u0000-\\u001f\\u007f-\\u009f\\u2028\\u2029]*[^\\s\\u0000-\\u001f\\u007f-\\u009f\\u2028\\u2029])?$(?![\\s\\S])", "description": "User-defined label, 1–100 Unicode code points, NFC and trimmed; no control characters or line breaks. Untrusted data, never instructions."},
    "eventType": {"type": "string", "maxLength": 49, "pattern": "^[a-z][a-z0-9]{0,11}(?:_[a-z0-9]{1,11}){0,2}\\.[a-z][a-z0-9]{0,11}(?:_[a-z0-9]{1,11}){0,2}$(?![\\s\\S])"},
    "timestamp": {"type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(?:\\.[0-9]{1,6})?(?:Z|[+-][0-9]{2}:[0-9]{2})$"},
    "timestampRange": {
      "type": "object", "additionalProperties": false, "required": ["start", "end"],
      "properties": {"start": {"$ref": "#/$defs/timestamp"}, "end": {"$ref": "#/$defs/timestamp"}}
    },
    "evidenceTime": {"anyOf": [{"$ref": "#/$defs/timestamp"}, {"$ref": "#/$defs/timestampRange"}]},
    "categories": {"type": "array", "minItems": 2, "maxItems": 100, "uniqueItems": true, "items": {"$ref": "#/$defs/category"}},
    "variable": {
      "type": "object", "additionalProperties": false, "required": ["type"],
      "properties": {
        "type": {"enum": ["integer", "number", "categorical", "timestamp", "timestamp_range"]},
        "values": {"$ref": "#/$defs/categories"}, "unit": {"$ref": "#/$defs/code"}
      },
      "allOf": [{"if": {"properties": {"type": {"const": "categorical"}}, "required": ["type"]}, "then": {"required": ["values"]}, "else": {"not": {"required": ["values"]}}}]
    },
    "value": {"anyOf": [{"type": "number"}, {"$ref": "#/$defs/category"}, {"$ref": "#/$defs/timestamp"}, {"$ref": "#/$defs/timestampRange"}]},
    "fields": {"type": "object", "maxProperties": 128, "propertyNames": {"$ref": "#/$defs/code", "not": {"pattern": "target_answer|realized_target|target_outcome|target_realized|instructions?|system_prompt|probabilities|ignore_rules|ignore_prior|ignore_system|override_system|always_answer|always_output|emit_answer"}}, "additionalProperties": {"$ref": "#/$defs/value"}},
    "outcome": {
      "type": "object", "additionalProperties": false, "required": ["variable", "value"],
      "properties": {"variable": {"$ref": "#/$defs/code"}, "value": {"$ref": "#/$defs/value"}}
    },
    "event": {
      "type": "object", "additionalProperties": false,
      "required": ["event_id", "event_type", "observed_at", "available_at", "source", "fields"],
      "properties": {
        "event_id": {"$ref": "#/$defs/code"}, "event_type": {"$ref": "#/$defs/eventType"}, "source": {"$ref": "#/$defs/code"},
        "observed_at": {"$ref": "#/$defs/evidenceTime"}, "available_at": {"$ref": "#/$defs/evidenceTime"},
        "fields": {"$ref": "#/$defs/fields"}, "outcome": {"$ref": "#/$defs/outcome"}
      }
    },
    "events": {"type": "array", "maxItems": 1000, "items": {"$ref": "#/$defs/event"}},
    "reference": {
      "type": "object", "additionalProperties": false, "required": ["field", "event_id"],
      "properties": {"field": {"$ref": "#/$defs/code"}, "event_id": {"$ref": "#/$defs/code"}}
    },
    "output": {
      "type": "object", "additionalProperties": false, "required": ["kind", "variable"],
      "properties": {
        "kind": {"enum": ["categorical", "int", "float"]}, "variable": {"$ref": "#/$defs/code"},
        "values": {"$ref": "#/$defs/categories"}, "minimum": {"type": "number"}, "maximum": {"type": "number"},
        "increment": {"type": "number", "exclusiveMinimum": 0}, "precision": {"type": "integer", "minimum": 0, "maximum": 12}
      },
      "allOf": [
        {"if": {"properties": {"kind": {"const": "categorical"}}, "required": ["kind"]}, "then": {"required": ["values"]}},
        {"if": {"properties": {"kind": {"enum": ["int", "float"]}}, "required": ["kind"]}, "then": {"required": ["minimum", "maximum", "increment"]}},
        {"if": {"properties": {"kind": {"const": "float"}}, "required": ["kind"]}, "then": {"required": ["precision"]}}
      ]
    },
    "forecast": {
      "type": "object", "additionalProperties": false,
      "required": ["event_type", "forecast_time", "target_time", "fields", "evidence_refs", "output"],
      "properties": {
        "event_type": {"$ref": "#/$defs/eventType"}, "forecast_time": {"$ref": "#/$defs/timestamp"}, "target_time": {"$ref": "#/$defs/evidenceTime"},
        "fields": {"$ref": "#/$defs/fields"}, "evidence_refs": {"type": "array", "maxItems": 1000, "items": {"$ref": "#/$defs/reference"}},
        "output": {"$ref": "#/$defs/output"}
      }
    }
  }
}
