{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://siebly.io/.well-known/conformance/exchange-state-management/v1/schema.json",
  "title": "Exchange State Management Workflow Fixture",
  "description": "JSON fixture projection for exchange-state-management workflow conformance. Runner expectations use partial object matching and array containment that consumes one observed item per expected item, with empty expected arrays requiring empty observed arrays.",
  "type": "object",
  "required": ["version", "fixtures"],
  "additionalProperties": false,
  "properties": {
    "version": {
      "type": "string",
      "const": "exchange-state-management.workflow.v1"
    },
    "fixtures": {
      "type": "array",
      "minItems": 1,
      "items": {
        "$ref": "#/$defs/fixture"
      }
    }
  },
  "$defs": {
    "fixture": {
      "type": "object",
      "required": ["name", "intent", "scope", "initial", "steps", "expect"],
      "additionalProperties": false,
      "properties": {
        "name": {
          "type": "string",
          "pattern": "^[a-z0-9]+(?:_[a-z0-9]+)*$"
        },
        "intent": {
          "type": "string",
          "minLength": 1
        },
        "requiredForLiveCapableDemo": {
          "type": "boolean",
          "default": true
        },
        "scope": {
          "$ref": "#/$defs/scope"
        },
        "initial": {
          "$ref": "#/$defs/initial"
        },
        "steps": {
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/$defs/step"
          }
        },
        "expect": {
          "description": "Expected observed state after all steps. Objects are partial matches. Arrays are containment matches that consume one observed item per expected item unless the expected array is empty, in which case the observed array must also be empty.",
          "$ref": "#/$defs/expectation"
        },
        "forbid": {
          "description": "Forbidden transition/action markers. The runner fails when observed.forbiddenObserved contains one of these markers.",
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "notes": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    },
    "scope": {
      "type": "object",
      "required": ["exchange", "product", "symbol", "managedSide"],
      "additionalProperties": false,
      "properties": {
        "exchange": {
          "type": "string"
        },
        "product": {
          "type": "string"
        },
        "symbol": {
          "type": "string"
        },
        "managedSide": {
          "type": "string",
          "enum": ["LONG", "SHORT", "BOTH", "UNKNOWN"]
        },
        "positionIdx": {
          "type": ["integer", "null"]
        },
        "role": {
          "type": ["string", "null"]
        },
        "step": {
          "type": ["integer", "null"]
        }
      }
    },
    "initial": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "config": {
          "type": "object",
          "additionalProperties": true
        },
        "accountState": {
          "type": "object",
          "additionalProperties": true
        },
        "orderContextStore": {
          "type": "object",
          "additionalProperties": true
        },
        "pendingConfirmations": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "clockMs": {
          "type": "integer"
        }
      }
    },
    "step": {
      "type": "object",
      "required": ["type"],
      "additionalProperties": false,
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "start",
            "rest_hydration",
            "private_event",
            "rest_accept",
            "rest_reject",
            "timer",
            "reconnect",
            "planner_tick",
            "submission_result",
            "operator_command"
          ]
        },
        "subject": {
          "type": "string"
        },
        "atMs": {
          "type": "integer"
        },
        "payload": {
          "type": "object",
          "additionalProperties": true
        }
      }
    },
    "expectation": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "accountState": {
          "type": "object",
          "additionalProperties": true
        },
        "affectedScopes": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/scope"
          }
        },
        "actionFamily": {
          "type": "string"
        },
        "pendingConfirmations": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "recoveryRequired": {
          "type": "boolean"
        },
        "syncRequiredSubjects": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "intents": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "blocks": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "logs": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": true
          }
        }
      }
    }
  }
}
