{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://torneo.ai/schemas/scheduler_ledger.v1",
  "title": "scheduler_ledger.v1",
  "description": "Hash-chained ledger of the budget scheduler (Scheduler.export_log): one row per transition, hash = sha256(prev + canonical body). Shape only: the chain, generation order, reservation limits and one effect per draw are replayed by scheduler.verify_chain and verify_ledger.",
  "type": "array",
  "items": {
    "type": "object",
    "required": [
      "seq",
      "body",
      "prev",
      "hash"
    ],
    "additionalProperties": false,
    "properties": {
      "seq": {
        "type": "integer",
        "minimum": 1
      },
      "body": {
        "oneOf": [
          {
            "type": "object",
            "required": [
              "event",
              "t",
              "job",
              "org",
              "provider",
              "op",
              "draw_key",
              "ram",
              "cpu",
              "disk",
              "quota",
              "max_retries"
            ],
            "additionalProperties": false,
            "properties": {
              "event": {
                "const": "submit"
              },
              "t": {
                "type": "number"
              },
              "job": {
                "type": "string",
                "minLength": 1
              },
              "org": {
                "type": "string",
                "minLength": 1
              },
              "provider": {
                "type": "string",
                "minLength": 1
              },
              "op": {
                "type": "string",
                "minLength": 1
              },
              "draw_key": {
                "type": "string",
                "minLength": 1
              },
              "ram": {
                "type": "number",
                "minimum": 0
              },
              "cpu": {
                "type": "number",
                "minimum": 0
              },
              "disk": {
                "type": "number",
                "minimum": 0
              },
              "quota": {
                "type": "number",
                "minimum": 0
              },
              "max_retries": {
                "type": "integer",
                "minimum": 0
              }
            }
          },
          {
            "type": "object",
            "required": [
              "event",
              "t",
              "job",
              "draw_key"
            ],
            "additionalProperties": false,
            "properties": {
              "event": {
                "const": "duplicate_submit"
              },
              "t": {
                "type": "number"
              },
              "job": {
                "type": "string",
                "minLength": 1
              },
              "draw_key": {
                "type": "string",
                "minLength": 1
              }
            }
          },
          {
            "type": "object",
            "required": [
              "event",
              "t",
              "job",
              "n",
              "gen"
            ],
            "additionalProperties": false,
            "properties": {
              "event": {
                "const": "register"
              },
              "t": {
                "type": "number"
              },
              "job": {
                "type": "string",
                "minLength": 1
              },
              "n": {
                "type": "integer",
                "minimum": 0
              },
              "gen": {
                "type": "integer",
                "minimum": 1
              }
            }
          },
          {
            "$ref": "#/$defs/claim"
          },
          {
            "type": "object",
            "required": [
              "event",
              "t",
              "job",
              "n",
              "gen"
            ],
            "additionalProperties": false,
            "properties": {
              "event": {
                "const": "start"
              },
              "t": {
                "type": "number"
              },
              "job": {
                "type": "string",
                "minLength": 1
              },
              "n": {
                "type": "integer",
                "minimum": 0
              },
              "gen": {
                "type": "integer",
                "minimum": 1
              }
            }
          },
          {
            "type": "object",
            "required": [
              "event",
              "t",
              "job",
              "draw_key",
              "gen"
            ],
            "additionalProperties": false,
            "properties": {
              "event": {
                "const": "effect"
              },
              "t": {
                "type": "number"
              },
              "job": {
                "type": "string",
                "minLength": 1
              },
              "draw_key": {
                "type": "string",
                "minLength": 1
              },
              "gen": {
                "type": "integer",
                "minimum": 1
              }
            }
          },
          {
            "type": "object",
            "required": [
              "event",
              "t",
              "job",
              "draw_key",
              "gen"
            ],
            "additionalProperties": false,
            "properties": {
              "event": {
                "const": "effect_duplicate_ignored"
              },
              "t": {
                "type": "number"
              },
              "job": {
                "type": "string",
                "minLength": 1
              },
              "draw_key": {
                "type": "string",
                "minLength": 1
              },
              "gen": {
                "type": "integer",
                "minimum": 1
              }
            }
          },
          {
            "type": "object",
            "required": [
              "event",
              "t",
              "job",
              "gen",
              "expires"
            ],
            "additionalProperties": false,
            "properties": {
              "event": {
                "const": "heartbeat"
              },
              "t": {
                "type": "number"
              },
              "job": {
                "type": "string",
                "minLength": 1
              },
              "gen": {
                "type": "integer",
                "minimum": 1
              },
              "expires": {
                "type": "number"
              }
            }
          },
          {
            "type": "object",
            "required": [
              "event",
              "t",
              "job",
              "n",
              "state",
              "gen",
              "terminal"
            ],
            "additionalProperties": false,
            "properties": {
              "event": {
                "const": "finish"
              },
              "t": {
                "type": "number"
              },
              "job": {
                "type": "string",
                "minLength": 1
              },
              "n": {
                "type": "integer",
                "minimum": 0
              },
              "gen": {
                "type": "integer",
                "minimum": 1
              },
              "terminal": {
                "type": "boolean"
              },
              "state": {
                "enum": [
                  "REGISTERED",
                  "STARTED",
                  "SUCCESS",
                  "FAILURE",
                  "TIMEOUT",
                  "SCORER_CRASH",
                  "INFRA_KILL",
                  "INFRA_UNAVAILABLE"
                ]
              },
              "reconciled": {
                "enum": [
                  "adopted_effect",
                  "outcome_unknown"
                ]
              }
            }
          },
          {
            "type": "object",
            "required": [
              "event",
              "t",
              "job",
              "gen"
            ],
            "additionalProperties": false,
            "properties": {
              "event": {
                "const": "lease_expired"
              },
              "t": {
                "type": "number"
              },
              "job": {
                "type": "string",
                "minLength": 1
              },
              "gen": {
                "type": "integer",
                "minimum": 1
              }
            }
          },
          {
            "type": "object",
            "required": [
              "event",
              "t",
              "job",
              "gen",
              "what"
            ],
            "additionalProperties": false,
            "properties": {
              "event": {
                "const": "stale_write_refused"
              },
              "t": {
                "type": "number"
              },
              "job": {
                "type": "string",
                "minLength": 1
              },
              "gen": {
                "type": "integer",
                "minimum": 1
              },
              "what": {
                "enum": [
                  "execute",
                  "start",
                  "effect",
                  "heartbeat",
                  "finish"
                ]
              }
            }
          },
          {
            "type": "object",
            "required": [
              "event",
              "t",
              "provider",
              "until"
            ],
            "additionalProperties": false,
            "properties": {
              "event": {
                "const": "provider_paused"
              },
              "t": {
                "type": "number"
              },
              "provider": {
                "type": "string",
                "minLength": 1
              },
              "until": {
                "type": "number"
              }
            }
          }
        ]
      },
      "prev": {
        "type": "string",
        "pattern": "^[0-9a-f]{64}$"
      },
      "hash": {
        "type": "string",
        "pattern": "^[0-9a-f]{64}$"
      }
    }
  },
  "$defs": {
    "claim": {
      "type": "object",
      "required": [
        "event",
        "t",
        "job",
        "gen",
        "n",
        "holder",
        "provider",
        "ram",
        "cpu",
        "disk",
        "quota",
        "charged",
        "expires"
      ],
      "additionalProperties": false,
      "properties": {
        "event": {
          "const": "claim"
        },
        "t": {
          "type": "number"
        },
        "job": {
          "type": "string",
          "minLength": 1
        },
        "gen": {
          "type": "integer",
          "minimum": 1
        },
        "n": {
          "type": "integer",
          "minimum": 0
        },
        "holder": {
          "type": "string",
          "minLength": 1
        },
        "provider": {
          "type": "string",
          "minLength": 1
        },
        "ram": {
          "type": "number",
          "minimum": 0
        },
        "cpu": {
          "type": "number",
          "minimum": 0
        },
        "disk": {
          "type": "number",
          "minimum": 0
        },
        "quota": {
          "type": "number",
          "minimum": 0
        },
        "charged": {
          "type": "boolean",
          "description": "False when the quota of this attempt number was already charged."
        },
        "expires": {
          "type": "number"
        }
      }
    }
  }
}
