{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://www.modernedi.com/docs/scenarios/schemas/configuration-scenario-definition-v1.schema.json",
  "title": "ModernEDI configuration ScenarioDefinition",
  "description": "Optional scenario configuration in the same reviewed bundle as connections, partners and maps. Retirement removes current configuration without deleting published revisions or run evidence.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "apiVersion",
    "kind",
    "metadata",
    "spec"
  ],
  "properties": {
    "apiVersion": {
      "const": "modernedi.com/v1"
    },
    "kind": {
      "const": "ScenarioDefinition"
    },
    "metadata": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "key"
      ],
      "properties": {
        "key": {
          "type": "string",
          "format": "uuid",
          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
          "description": "Stable resource key; retain it when copying configuration to another workspace."
        }
      }
    },
    "spec": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "source"
      ],
      "properties": {
        "source": {
          "title": "ModernEDI ScenarioDefinition v1",
          "description": "Maps define how documents are processed; scenarios define and prove the business conversation those maps implement. A ScenarioDefinition is the portable recipe for that conversation: who exchanges each X12 business document, which documents belong together, what order and repetition are allowed, and what evidence must pass. Tenant partners, syntax trees, mappings, and executable targets belong in a ScenarioBinding.",
          "type": "object",
          "additionalProperties": false,
          "required": [
            "apiVersion",
            "kind",
            "metadata",
            "spec"
          ],
          "properties": {
            "$schema": {
              "const": "https://www.modernedi.com/docs/scenarios/schemas/scenario-definition-v1.schema.json",
              "description": "Optional portable tooling hint. It does not participate in the definition's canonical content hash."
            },
            "apiVersion": {
              "const": "modernedi.com/scenario/v1",
              "description": "Wire-contract version for the generally available ScenarioDefinition contract."
            },
            "kind": {
              "const": "ScenarioDefinition",
              "description": "Discriminator for a scenario definition document."
            },
            "metadata": {
              "$ref": "#/$defs/metadata"
            },
            "spec": {
              "$ref": "#/$defs/spec"
            }
          }
        }
      }
    }
  },
  "$defs": {
    "token": {
      "type": "string",
      "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,127}$",
      "description": "A stable identifier beginning with a letter and containing at most 128 letters, digits, underscores, or hyphens."
    },
    "namespace": {
      "type": "string",
      "maxLength": 253,
      "pattern": "^[a-z0-9]+(?:[.-][a-z0-9]+)*$",
      "description": "A lowercase, DNS-like ownership namespace."
    },
    "artifactVersion": {
      "type": "string",
      "minLength": 1,
      "maxLength": 64,
      "pattern": "^(?!\\s)(?!.*\\s$)[^\\u0000-\\u001F\\u007F]+$",
      "description": "A trim-exact artifact version with no control characters. This versions a published definition; it is separate from apiVersion."
    },
    "positiveDuration": {
      "type": "string",
      "format": "duration",
      "pattern": "^P(?=.+)(?!0+(?:D|T(?:0+H)?(?:0+M)?(?:0+(?:\\.0+)?S)?$))(?:[0-9]+D)?(?:T(?=[0-9])(?:[0-9]+H)?(?:[0-9]+M)?(?:[0-9]+(?:\\.[0-9]+)?S)?)?$",
      "description": "A positive ISO 8601 duration accepted by java.time.Duration, no longer than P365D. Examples: PT30M, PT4H, P2D. The server enforces the upper bound."
    },
    "metadata": {
      "title": "Definition metadata",
      "description": "Immutable identity of a published definition. The identity tuple is namespace, key, and version; contentSha256 is computed when the definition is published.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "namespace",
        "key",
        "version"
      ],
      "properties": {
        "namespace": {
          "$ref": "#/$defs/namespace"
        },
        "key": {
          "$ref": "#/$defs/token",
          "description": "Stable definition key within the namespace."
        },
        "version": {
          "$ref": "#/$defs/artifactVersion"
        }
      }
    },
    "spec": {
      "title": "Scenario specification",
      "description": "The business-conversation recipe. Actors name the business roles, steps name their X12 document exchanges, and transitions state how those exchanges relate. ModernEDI also verifies unique IDs, references, a connected conversation, and the absence of ordinary transition cycles during Validate and Publish. Omitted transitions, assertions, parameters, checkpoints, or branches mean empty arrays; published JSON materializes every collection.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "actors",
        "steps"
      ],
      "properties": {
        "actors": {
          "type": "array",
          "description": "Business roles participating in the conversation. Every actor ID must be unique.",
          "minItems": 1,
          "maxItems": 100,
          "items": {
            "$ref": "#/$defs/actor"
          }
        },
        "steps": {
          "type": "array",
          "description": "Business-document exchanges. Every step ID must be unique and must reference two different declared actors.",
          "minItems": 1,
          "maxItems": 500,
          "items": {
            "$ref": "#/$defs/step"
          }
        },
        "transitions": {
          "type": "array",
          "description": "Rules connecting document steps. For example, an 810 invoice can follow its matching 850 purchase order, a later 860 can supersede an earlier order change, and an ocean 303 can cancel a matching 301 booking confirmation. Transition IDs must be unique. Except for a same-step supersedes revision chain, ordinary next-document paths cannot loop and every step must belong to one connected conversation.",
          "default": [],
          "maxItems": 2000,
          "items": {
            "$ref": "#/$defs/transition"
          }
        },
        "assertions": {
          "type": "array",
          "description": "Run-level facts that must hold across one or more observed step occurrences. Assertion IDs must be unique.",
          "default": [],
          "maxItems": 1000,
          "items": {
            "$ref": "#/$defs/assertion"
          }
        },
        "parameters": {
          "type": "array",
          "description": "Prepared values supplied when a run starts. Parameters declare only their semantic type, required flag, and optional default; bindings and runtime APIs supply values.",
          "default": [],
          "maxItems": 100,
          "items": {
            "$ref": "#/$defs/parameter"
          }
        },
        "checkpoints": {
          "type": "array",
          "description": "Named completion events emitted after a step finishes a declared processing stage. A checkpoint can trigger a choice between allowed next steps. For example, a bookingDisposition checkpoint emitted after an X12 301 booking confirmation can choose between an X12 303 cancellation and X12 304 shipping instructions.",
          "default": [],
          "maxItems": 100,
          "items": {
            "$ref": "#/$defs/checkpoint"
          }
        },
        "branches": {
          "type": "array",
          "description": "Explicit choices between allowed next-document transitions, evaluated only after a named checkpoint is emitted. For example, after an X12 301 booking confirmation emits bookingDisposition, cancelRequested=true can select the X12 303 cancellation path and otherwise can select X12 304 shipping instructions. Choices are evaluated in deterministic rounds from the steps already available at the start of that round; a destination document cannot provide the fact that selects its own path.",
          "default": [],
          "maxItems": 100,
          "items": {
            "$ref": "#/$defs/branch"
          }
        }
      }
    },
    "actor": {
      "title": "Actor",
      "description": "A business role. Bindings later connect each role to this workspace or a trading partner.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/token"
        }
      }
    },
    "step": {
      "title": "Step",
      "description": "One directed X12 business-document exchange. Functional acknowledgments (997/999) are evidence requirements, not business steps.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "fromActor",
        "toActor",
        "transaction",
        "occurrence",
        "facts",
        "pipeline"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/token",
          "description": "Stable ID used by transitions, assertions, and bindings."
        },
        "fromActor": {
          "$ref": "#/$defs/token",
          "description": "ID of the actor sending this business document."
        },
        "toActor": {
          "$ref": "#/$defs/token",
          "description": "ID of the actor receiving this business document; it must differ from fromActor."
        },
        "transaction": {
          "$ref": "#/$defs/transaction"
        },
        "occurrence": {
          "$ref": "#/$defs/occurrence"
        },
        "assurance": {
          "$ref": "#/$defs/assurance"
        },
        "facts": {
          "type": "array",
          "description": "Typed semantic facts exposed by this step. Use an empty array when the step exposes none. Declarations name the stable ABI only; extraction provenance belongs to runtime capability and binding layers.",
          "maxItems": 100,
          "items": {
            "$ref": "#/$defs/factDeclaration"
          }
        },
        "pipeline": {
          "type": "array",
          "description": "Ordered abstract processing stages for each step occurrence. Stages describe behavior without naming mapper or transport artifacts.",
          "minItems": 1,
          "maxItems": 20,
          "items": {
            "$ref": "#/$defs/pipelineStage"
          }
        }
      }
    },
    "transaction": {
      "title": "Transaction",
      "description": "The business document carried by a step. The server verifies the transaction-set code against ModernEDI's X12 catalog.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "standard",
        "transactionSet",
        "businessUsage"
      ],
      "properties": {
        "standard": {
          "const": "X12",
          "description": "Transaction standard. v1 supports X12."
        },
        "transactionSet": {
          "type": "string",
          "pattern": "^(?!(?:997|999)$)[0-9]{3}$",
          "description": "Known three-digit X12 business transaction set, such as 850, 855, 856, 810, 875, 880, 940, 945, 204, 214, 300, 301, or 315. Use assurance for 997/999 acknowledgments."
        },
        "businessUsage": {
          "$ref": "#/$defs/token",
          "description": "Scenario-specific semantic role, such as purchase_order, shipment_notice, or ocean_status. It is intentionally more precise than the transaction-set code."
        }
      }
    },
    "occurrence": {
      "title": "Occurrence bounds",
      "description": "How many documents this step may contribute to one run and the rule that says when no more are expected. One observed document is one occurrence. For example, an 850 order can be exactly once while 856 shipment notices can repeat. The server also enforces min <= max.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "min",
        "max"
      ],
      "properties": {
        "min": {
          "type": "integer",
          "minimum": 0,
          "maximum": 1000,
          "description": "Minimum accepted count once a reachable step closes. Zero permits a no-document outcome when expected_count resolves to 0, explicit closure records no documents, or branch selection makes the step unreachable; zero alone does not close a stream."
        },
        "max": {
          "type": "integer",
          "minimum": 1,
          "maximum": 1000,
          "description": "Structural per-step ceiling for authored occurrences. Validate and Apply also enforce one conservative run-state capacity budget across all steps, paired documents, checks, and durable evidence."
        },
        "closure": {
          "$ref": "#/$defs/occurrenceClosure",
          "description": "The closure rule: the signal that no more documents are expected for this step. It may be omitted while authoring; Publish writes fixed when min equals max and max_reached otherwise. Because max_reached waits for the maximum, a min-zero unbranched step must instead use expected_count or explicit so a zero-document outcome is deliberate."
        }
      }
    },
    "assurance": {
      "title": "Evidence requirements",
      "description": "Operational evidence required for each occurrence of this step. Duplicate requirement types are rejected by the server.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "requirements"
      ],
      "properties": {
        "requirements": {
          "type": "array",
          "minItems": 1,
          "maxItems": 4,
          "items": {
            "$ref": "#/$defs/assuranceRequirement"
          },
          "allOf": [
            {
              "contains": {
                "type": "object",
                "properties": {
                  "type": {
                    "const": "mapping_succeeded"
                  }
                }
              },
              "minContains": 0,
              "maxContains": 1
            },
            {
              "contains": {
                "type": "object",
                "properties": {
                  "type": {
                    "const": "transport_receipt_accepted"
                  }
                }
              },
              "minContains": 0,
              "maxContains": 1
            },
            {
              "contains": {
                "type": "object",
                "properties": {
                  "type": {
                    "const": "interchange_acknowledgment_accepted"
                  }
                }
              },
              "minContains": 0,
              "maxContains": 1
            },
            {
              "contains": {
                "type": "object",
                "properties": {
                  "type": {
                    "const": "functional_or_implementation_acknowledgment_accepted"
                  }
                }
              },
              "minContains": 0,
              "maxContains": 1
            }
          ]
        }
      }
    },
    "assuranceRequirement": {
      "title": "Evidence requirement",
      "description": "One observable proof required for a step. For example, mapping_succeeded proves that the selected map ran, while functional_or_implementation_acknowledgment_accepted proves accepted 997 or 999 evidence. Outgoing mapping proof may predate the document occurrence because mapping runs immediately before exchange; receipts and acknowledgments may not. A deadline is measured from the document occurrence to the terminal evidence time, and requires that evidence's own timestamp. Terminal evidence timestamped after the run's evaluation time is invalid.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "type"
      ],
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "mapping_succeeded",
            "transport_receipt_accepted",
            "interchange_acknowledgment_accepted",
            "functional_or_implementation_acknowledgment_accepted"
          ],
          "description": "mapping_succeeded proves mapper execution; transport_receipt_accepted proves the AS2 receipt; interchange_acknowledgment_accepted proves TA1 acceptance; functional_or_implementation_acknowledgment_accepted proves accepted 997 or 999 evidence."
        },
        "within": {
          "$ref": "#/$defs/positiveDuration",
          "description": "Optional deadline from the business document occurrence to terminal evidence. An outgoing mapping completed before exchange satisfies the lower timing boundary, but its own source timestamp is still required; missing terminal source time cannot prove a deadline."
        }
      }
    },
    "transition": {
      "title": "Transition",
      "description": "A rule from one document step to another. Correlations identify which actual documents belong together. follows models ordinary order, such as a matching 810 invoice after an 850 order. supersedes records a replacement, such as a later 860 order change replacing the prior 850 or 860. cancels records a removal, such as an ocean 303 cancellation for a 301 booking confirmation. Supersedes and cancels inspect every stored observation before any replacement or cancellation is applied; they do not make an otherwise unavailable next-document path available and cannot themselves be branch alternatives.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "fromStep",
        "toStep",
        "relationship",
        "matching"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/token"
        },
        "fromStep": {
          "$ref": "#/$defs/token",
          "description": "Predecessor step ID."
        },
        "toStep": {
          "$ref": "#/$defs/token",
          "description": "Successor step ID. It may equal fromStep only for a supersedes transition that uses previous matching; cancellation is represented by a distinct cancellation-document step."
        },
        "relationship": {
          "type": "string",
          "enum": [
            "follows",
            "supersedes",
            "cancels"
          ],
          "description": "Choose follows when a matched later document must occur at or after the earlier one, such as an 810 invoice after its 850 order. Choose supersedes when the later document replaces the matched earlier occurrence, such as an 860 order change replacing an 850 or prior 860. Choose cancels when the later document cancels the matched earlier occurrence, such as an ocean 303 cancelling a 301 booking confirmation. supersedes and cancels require effect to say when the change begins and whether later checks keep using the original document or reevaluate with the replacement/removal. Business labels such as acknowledges, reports status, or settles belong in the transition ID and prose unless an assertion or evidence requirement actually verifies them."
        },
        "within": {
          "$ref": "#/$defs/positiveDuration",
          "description": "Optional maximum elapsed time from the correlated fromStep occurrence to the toStep occurrence."
        },
        "correlations": {
          "type": "array",
          "description": "Conditions the scenario evaluator uses to pair actual source and target documents. For example, compare the purchase-order number extracted from an 850 with the purchase-order number extracted from an 810. Correlation IDs must be unique within this transition.",
          "minItems": 0,
          "maxItems": 100,
          "items": {
            "$ref": "#/$defs/correlation"
          }
        },
        "matching": {
          "$ref": "#/$defs/occurrenceMatching",
          "description": "Required quantification and pairing semantics for concrete occurrences; the server does not infer them from correlations."
        },
        "effect": {
          "$ref": "#/$defs/revisionEffect",
          "description": "Required effective-time and downstream behavior for supersedes and cancels. Forbidden for follows."
        }
      },
      "allOf": [
        {
          "if": {
            "properties": {
              "relationship": {
                "const": "follows"
              }
            },
            "required": [
              "relationship"
            ]
          },
          "then": {
            "not": {
              "required": [
                "effect"
              ]
            }
          }
        },
        {
          "if": {
            "properties": {
              "relationship": {
                "enum": [
                  "supersedes",
                  "cancels"
                ]
              }
            },
            "required": [
              "relationship"
            ]
          },
          "then": {
            "required": [
              "effect"
            ]
          }
        }
      ]
    },
    "correlation": {
      "title": "Correlation",
      "description": "A condition that decides whether two actual documents belong to the same transition pair. equal can match the purchase-order number on an 850 and 810; same_set can compare their item sets; reply_link uses ModernEDI's stored reply relationship and accepts no fact operands.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "operator"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/token"
        },
        "operator": {
          "type": "string",
          "enum": [
            "equal",
            "same_set",
            "reply_link"
          ]
        },
        "left": {
          "$ref": "#/$defs/factOperand",
          "description": "For fact operators, must reference the transition's fromStep."
        },
        "right": {
          "$ref": "#/$defs/factOperand",
          "description": "For fact operators, must reference the transition's toStep."
        }
      },
      "oneOf": [
        {
          "properties": {
            "operator": {
              "enum": [
                "equal",
                "same_set"
              ]
            }
          },
          "required": [
            "left",
            "right"
          ]
        },
        {
          "properties": {
            "operator": {
              "const": "reply_link"
            }
          },
          "not": {
            "anyOf": [
              {
                "required": [
                  "left"
                ]
              },
              {
                "required": [
                  "right"
                ]
              }
            ]
          }
        }
      ]
    },
    "assertion": {
      "title": "Assertion",
      "description": "A fact rule that must hold for the run to pass. sum_equal compares overall totals. keyed_sum_equal instead sums decimal amounts per item key across occurrences, then requires identical keys and per-key totals on both sides. keyed_equal requires identical keys and consistent decimal values per key, including across repeated occurrences (useful for unit prices). Keyed comparisons wait for both steps to close before passing and require keyed_facts operands. Binary operators require right; unary operators reject it.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "operator",
        "left"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/token"
        },
        "operator": {
          "type": "string",
          "enum": [
            "equal",
            "not_equal",
            "exists",
            "unique",
            "same_set",
            "subset",
            "sum_equal",
            "keyed_sum_equal",
            "keyed_equal",
            "less_than_or_equal",
            "greater_than_or_equal",
            "monotonic"
          ]
        },
        "left": {
          "$ref": "#/$defs/assertionOperand"
        },
        "right": {
          "$ref": "#/$defs/assertionOperand"
        }
      },
      "oneOf": [
        {
          "properties": {
            "left": {
              "$ref": "#/$defs/valueOperand"
            },
            "right": {
              "$ref": "#/$defs/valueOperand"
            },
            "operator": {
              "enum": [
                "equal",
                "not_equal",
                "same_set",
                "subset",
                "sum_equal",
                "less_than_or_equal",
                "greater_than_or_equal"
              ]
            }
          },
          "required": [
            "right"
          ]
        },
        {
          "properties": {
            "operator": {
              "enum": [
                "exists",
                "unique",
                "monotonic"
              ]
            },
            "left": {
              "$ref": "#/$defs/valueOperand"
            }
          },
          "not": {
            "required": [
              "right"
            ]
          }
        },
        {
          "properties": {
            "operator": {
              "enum": [
                "keyed_sum_equal",
                "keyed_equal"
              ]
            },
            "left": {
              "$ref": "#/$defs/keyedFactOperand"
            },
            "right": {
              "$ref": "#/$defs/keyedFactOperand"
            }
          },
          "required": [
            "right"
          ]
        }
      ]
    },
    "valueType": {
      "type": "string",
      "enum": [
        "string",
        "decimal",
        "date",
        "time",
        "timestamp",
        "boolean",
        "list",
        "set"
      ],
      "description": "Closed evaluator value type. list and set contain scalar values only and require elementType."
    },
    "scalarType": {
      "type": "string",
      "enum": [
        "string",
        "decimal",
        "date",
        "time",
        "timestamp",
        "boolean"
      ],
      "description": "Closed scalar type used directly or as the element type of list and set values."
    },
    "factProjection": {
      "type": "string",
      "enum": [
        "value",
        "list",
        "set",
        "first",
        "latest"
      ],
      "description": "Select one declared per-occurrence fact value, aggregate values across occurrences as a list or set, or select the first/latest observed occurrence. Correlations require value."
    },
    "decimalJson": {
      "description": "A finite JSON number or exact base-10 string. The scenario evaluator normalizes scale without precision loss.",
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "string",
          "pattern": "^-?(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?(?:[eE][+-]?[0-9]+)?$"
        }
      ]
    },
    "parameter": {
      "title": "Prepared run parameter",
      "description": "A typed value supplied when a run starts through the Workspace UI or API, or resolved from its declared default when optional.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "type",
        "required"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/token",
          "description": "Stable name used by prepare stages, expected-count closure, and parameter operands."
        },
        "type": {
          "$ref": "#/$defs/valueType"
        },
        "elementType": {
          "$ref": "#/$defs/scalarType",
          "description": "Required exactly when type is list or set."
        },
        "required": {
          "type": "boolean",
          "description": "Whether the run must explicitly provide this value. A required parameter cannot also have a default."
        },
        "default": {
          "description": "Optional JSON value used when the run omits a non-required parameter."
        }
      },
      "allOf": [
        {
          "if": {
            "properties": {
              "type": {
                "enum": [
                  "list",
                  "set"
                ]
              }
            },
            "required": [
              "type"
            ]
          },
          "then": {
            "required": [
              "elementType"
            ]
          },
          "else": {
            "not": {
              "required": [
                "elementType"
              ]
            }
          }
        },
        {
          "if": {
            "properties": {
              "required": {
                "const": true
              }
            },
            "required": [
              "required"
            ]
          },
          "then": {
            "not": {
              "required": [
                "default"
              ]
            }
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "string"
              }
            },
            "required": [
              "type"
            ]
          },
          "then": {
            "properties": {
              "default": {
                "type": "string"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "decimal"
              }
            },
            "required": [
              "type"
            ]
          },
          "then": {
            "properties": {
              "default": {
                "$ref": "#/$defs/decimalJson"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "date"
              }
            },
            "required": [
              "type"
            ]
          },
          "then": {
            "properties": {
              "default": {
                "type": "string",
                "format": "date"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "time"
              }
            },
            "required": [
              "type"
            ]
          },
          "then": {
            "properties": {
              "default": {
                "type": "string",
                "format": "time"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "timestamp"
              }
            },
            "required": [
              "type"
            ]
          },
          "then": {
            "properties": {
              "default": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "boolean"
              }
            },
            "required": [
              "type"
            ]
          },
          "then": {
            "properties": {
              "default": {
                "type": "boolean"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "enum": [
                  "list",
                  "set"
                ]
              }
            },
            "required": [
              "type"
            ]
          },
          "then": {
            "properties": {
              "default": {
                "type": "array"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "set"
              }
            },
            "required": [
              "type"
            ]
          },
          "then": {
            "properties": {
              "default": {
                "type": "array",
                "uniqueItems": true
              }
            }
          }
        }
      ]
    },
    "checkpoint": {
      "title": "Checkpoint declaration",
      "description": "A named completion event emitted by exactly one checkpoint pipeline stage after its preceding stages finish. For example, an X12 301 booking-confirmation step can emit bookingDisposition after exchange and fact extraction, allowing the run to choose the cancellation or shipping-instructions path.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/token"
        }
      }
    },
    "factDeclaration": {
      "title": "Typed fact declaration",
      "description": "Stable semantic ABI for one fact exposed by a step occurrence. The binding/runtime capability separately defines extraction provenance.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "name",
        "type",
        "cardinality",
        "normalization",
        "sensitivity"
      ],
      "properties": {
        "name": {
          "$ref": "#/$defs/token",
          "description": "Stable fact name used by discriminated fact operands and binding-side fact sources."
        },
        "type": {
          "$ref": "#/$defs/valueType"
        },
        "elementType": {
          "$ref": "#/$defs/scalarType",
          "description": "Required exactly when type is list or set; nested collections are not supported."
        },
        "cardinality": {
          "type": "string",
          "enum": [
            "one",
            "optional"
          ],
          "description": "Presence of the typed value on each occurrence. Collection multiplicity is expressed by type list/set, never by a separate many cardinality."
        },
        "normalization": {
          "type": "array",
          "description": "Ordered, deterministic normalization applied before typed evaluation.",
          "maxItems": 5,
          "uniqueItems": true,
          "items": {
            "type": "string",
            "enum": [
              "trim",
              "collapse_whitespace",
              "uppercase",
              "lowercase",
              "decimal_canonical"
            ]
          }
        },
        "sensitivity": {
          "type": "string",
          "enum": [
            "business",
            "personal",
            "financial",
            "health",
            "restricted"
          ],
          "description": "Data-handling classification carried with evidence and diagnostics."
        }
      },
      "allOf": [
        {
          "if": {
            "properties": {
              "type": {
                "enum": [
                  "list",
                  "set"
                ]
              }
            },
            "required": [
              "type"
            ]
          },
          "then": {
            "required": [
              "elementType"
            ]
          },
          "else": {
            "not": {
              "required": [
                "elementType"
              ]
            }
          }
        }
      ]
    },
    "pipelineStage": {
      "title": "Composed step pipeline stage",
      "description": "One named action in the ordered processing of an observed document. A definition says prepare, map, exchange, extract facts, check evidence, or emit a checkpoint; the binding later selects the concrete map, partner, or adapter. Keeping those artifact IDs out of the definition lets the same conversation recipe be reused by another tenant.",
      "oneOf": [
        {
          "title": "Prepare stage",
          "type": "object",
          "additionalProperties": false,
          "required": [
            "id",
            "kind",
            "parameters"
          ],
          "properties": {
            "id": {
              "$ref": "#/$defs/token"
            },
            "kind": {
              "const": "prepare",
              "description": "Journal that named run parameters are available. Every referenced parameter must either be required at run start or declare a default."
            },
            "parameters": {
              "type": "array",
              "minItems": 1,
              "maxItems": 100,
              "uniqueItems": true,
              "items": {
                "$ref": "#/$defs/token"
              }
            }
          }
        },
        {
          "title": "Map stage",
          "type": "object",
          "additionalProperties": false,
          "required": [
            "id",
            "kind"
          ],
          "properties": {
            "id": {
              "$ref": "#/$defs/token"
            },
            "kind": {
              "const": "map",
              "description": "Confirm the exact runtime mapping selected by an applied binding. A step may declare this stage once, immediately next to exchange. Apply requires it before exchange for outgoing documents and after exchange for incoming documents."
            }
          }
        },
        {
          "title": "Exchange stage",
          "type": "object",
          "additionalProperties": false,
          "required": [
            "id",
            "kind"
          ],
          "properties": {
            "id": {
              "$ref": "#/$defs/token"
            },
            "kind": {
              "const": "exchange",
              "description": "Observe or perform the business-document exchange. Exactly one is required per step."
            }
          }
        },
        {
          "title": "Extract stage",
          "type": "object",
          "additionalProperties": false,
          "required": [
            "id",
            "kind",
            "facts"
          ],
          "properties": {
            "id": {
              "$ref": "#/$defs/token"
            },
            "kind": {
              "const": "extract",
              "description": "Materialize declared semantic facts using binding/runtime-provided sources. Every declared fact must appear in exactly one extract stage."
            },
            "facts": {
              "type": "array",
              "minItems": 1,
              "maxItems": 100,
              "uniqueItems": true,
              "items": {
                "$ref": "#/$defs/token"
              }
            }
          }
        },
        {
          "title": "Assure stage",
          "type": "object",
          "additionalProperties": false,
          "required": [
            "id",
            "kind"
          ],
          "properties": {
            "id": {
              "$ref": "#/$defs/token"
            },
            "kind": {
              "const": "assure",
              "description": "Evaluate the step's declared operational evidence requirements. A step may declare this stage at most once."
            }
          }
        },
        {
          "title": "Checkpoint stage",
          "type": "object",
          "additionalProperties": false,
          "required": [
            "id",
            "kind",
            "checkpoint"
          ],
          "properties": {
            "id": {
              "$ref": "#/$defs/token"
            },
            "kind": {
              "const": "checkpoint",
              "description": "Emit a declared global checkpoint after the preceding stages complete. In v1, the containing step must have occurrence max 1 so the emitting occurrence is unambiguous."
            },
            "checkpoint": {
              "$ref": "#/$defs/token"
            }
          }
        }
      ]
    },
    "occurrenceClosure": {
      "title": "Occurrence closure",
      "description": "The rule that tells a run no more documents will be attached to a step. fixed closes at the fixed count; max_reached closes at the maximum; expected_count uses a required or defaulted count parameter. explicit waits for an authorized browser or API decision, even at max: advance with closeSteps records the exact attached count and time, then evaluates all existing checks. Closing does not assert success, reopen the step, or send EDI. An explicit min-zero step can close with no documents. Existing attachments may still refresh pending evidence while the run is active. A new run is required for additional documents after closure. Branch selection supplies the no-document outcome for an unselected destination.",
      "oneOf": [
        {
          "title": "Fixed closure",
          "type": "object",
          "additionalProperties": false,
          "required": [
            "kind"
          ],
          "properties": {
            "kind": {
              "const": "fixed",
              "description": "Close after the fixed min=max count is observed. Example: an 850 step with min=1 and max=1 closes after its one purchase order."
            }
          }
        },
        {
          "title": "Maximum-reached closure",
          "type": "object",
          "additionalProperties": false,
          "required": [
            "kind"
          ],
          "properties": {
            "kind": {
              "const": "max_reached",
              "description": "Close only when the declared maximum count is observed. Example: a 315 status step with max=2 closes after the second status document."
            }
          }
        },
        {
          "title": "Explicit closure",
          "type": "object",
          "additionalProperties": false,
          "required": [
            "kind"
          ],
          "properties": {
            "kind": {
              "const": "explicit",
              "description": "Wait for an explicit no-more-documents decision through the browser or advance API closeSteps field. The maximum is a safety limit, not an expected final count. Quantity equality alone never closes the step."
            }
          }
        },
        {
          "title": "Expected-count closure",
          "type": "object",
          "additionalProperties": false,
          "required": [
            "kind",
            "parameter"
          ],
          "properties": {
            "kind": {
              "const": "expected_count",
              "description": "Close when the number of occurrences reaches an exact integer supplied by a required run parameter or a declared default. The value must fit this step's occurrence bounds; steps sharing one count parameter must have overlapping bounds. Example: expectedShipmentCount=2 closes a repeated 945 step after two shipping-advice documents."
            },
            "parameter": {
              "$ref": "#/$defs/token"
            }
          }
        }
      ]
    },
    "matchQuantifier": {
      "title": "Occurrence match quantifier",
      "description": "An explicit requirement over source occurrences, target occurrences, matched pairs, or matches per endpoint occurrence.",
      "oneOf": [
        {
          "title": "Any quantifier",
          "type": "object",
          "additionalProperties": false,
          "required": [
            "kind",
            "scope"
          ],
          "properties": {
            "kind": {
              "const": "any"
            },
            "scope": {
              "type": "string",
              "enum": [
                "from",
                "to",
                "pairs",
                "per_from",
                "per_to"
              ]
            }
          }
        },
        {
          "title": "Every quantifier",
          "type": "object",
          "additionalProperties": false,
          "required": [
            "kind",
            "scope"
          ],
          "properties": {
            "kind": {
              "const": "every"
            },
            "scope": {
              "type": "string",
              "enum": [
                "from",
                "to",
                "pairs",
                "per_from",
                "per_to"
              ]
            }
          }
        },
        {
          "title": "Exact-count quantifier",
          "type": "object",
          "additionalProperties": false,
          "required": [
            "kind",
            "scope",
            "count"
          ],
          "properties": {
            "kind": {
              "const": "exactly"
            },
            "scope": {
              "type": "string",
              "enum": [
                "from",
                "to",
                "pairs",
                "per_from",
                "per_to"
              ]
            },
            "count": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000
            }
          }
        }
      ]
    },
    "occurrenceMatching": {
      "title": "Occurrence matching",
      "description": "How actual repeated documents are paired across a transition, plus what happens to documents with no match. correlate pairs documents whose declared fact or reply-link conditions pass; position pairs by observation order; previous pairs each revision with the immediately preceding occurrence of the same step, such as the second 860 order change with the first.",
      "oneOf": [
        {
          "title": "Correlation matching",
          "type": "object",
          "additionalProperties": false,
          "required": [
            "strategy",
            "quantifiers",
            "unmatched"
          ],
          "properties": {
            "strategy": {
              "const": "correlate",
              "description": "Pair occurrences whose declared correlation conditions pass."
            },
            "quantifiers": {
              "type": "array",
              "minItems": 1,
              "maxItems": 10,
              "items": {
                "$ref": "#/$defs/matchQuantifier"
              }
            },
            "unmatched": {
              "type": "string",
              "enum": [
                "fail",
                "record"
              ]
            }
          }
        },
        {
          "title": "Positional matching",
          "type": "object",
          "additionalProperties": false,
          "required": [
            "strategy",
            "quantifiers",
            "unmatched"
          ],
          "properties": {
            "strategy": {
              "const": "position",
              "description": "Pair source and target occurrences by stable observation order; correlations are forbidden."
            },
            "quantifiers": {
              "type": "array",
              "minItems": 1,
              "maxItems": 10,
              "items": {
                "$ref": "#/$defs/matchQuantifier"
              }
            },
            "unmatched": {
              "type": "string",
              "enum": [
                "fail",
                "record"
              ]
            }
          }
        },
        {
          "title": "Previous-occurrence matching",
          "description": "For a same-step supersedes transition whose step occurrence max is at least 2, pair occurrence n with n-1. The first occurrence is recorded as the initial revision, so both matching.unmatched and effect.unmatched must be record. A separate cross-step transition can link an initial 850 to the first 860. cancels uses a distinct cancellation-document step and cannot use previous matching.",
          "type": "object",
          "additionalProperties": false,
          "required": [
            "strategy",
            "quantifiers",
            "unmatched"
          ],
          "properties": {
            "strategy": {
              "const": "previous"
            },
            "quantifiers": {
              "type": "array",
              "minItems": 1,
              "maxItems": 1,
              "items": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "kind",
                  "scope"
                ],
                "properties": {
                  "kind": {
                    "const": "every"
                  },
                  "scope": {
                    "const": "to"
                  }
                }
              }
            },
            "unmatched": {
              "const": "record",
              "description": "Record the first occurrence because it has no predecessor; later occurrences must match their immediate predecessor."
            }
          }
        }
      ]
    },
    "factOperand": {
      "title": "Fact operand",
      "description": "A declared semantic fact from a concrete step occurrence.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "kind",
        "stepId",
        "fact",
        "projection"
      ],
      "properties": {
        "kind": {
          "const": "fact"
        },
        "stepId": {
          "$ref": "#/$defs/token"
        },
        "fact": {
          "$ref": "#/$defs/token",
          "description": "Name from the referenced step's facts declaration."
        },
        "projection": {
          "$ref": "#/$defs/factProjection",
          "description": "How values are selected or aggregated across this step's occurrences. list/set require occurrence max greater than 1 and a scalar declared fact."
        }
      }
    },
    "keyedFactOperand": {
      "title": "Keyed fact operand",
      "description": "Conversation assertion input: align the required string-list keyFact and required decimal-list fact by index within each effective occurrence of stepId. List lengths must agree. Keys must be nonblank and unique within each occurrence; the same key may recur in later documents. Both the keys and values retain source evidence. No projection or parameter is accepted. This does not combine quantities in different units: include unit in your Mapper-produced key. Keyed operators are not available in branch predicates, correlations, or revision timestamps.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "kind",
        "stepId",
        "keyFact",
        "fact"
      ],
      "properties": {
        "kind": {
          "const": "keyed_facts"
        },
        "stepId": {
          "$ref": "#/$defs/token"
        },
        "keyFact": {
          "$ref": "#/$defs/token",
          "description": "Required list of string keys on this step."
        },
        "fact": {
          "$ref": "#/$defs/token",
          "description": "Required list of decimal values aligned with keyFact on this step."
        }
      }
    },
    "assertionOperand": {
      "title": "Assertion operand",
      "oneOf": [
        {
          "$ref": "#/$defs/factOperand"
        },
        {
          "$ref": "#/$defs/parameterOperand"
        },
        {
          "$ref": "#/$defs/literalOperand"
        },
        {
          "$ref": "#/$defs/keyedFactOperand"
        }
      ]
    },
    "parameterOperand": {
      "title": "Parameter operand",
      "description": "A prepared run parameter usable in assertions, branch predicates, and effective-time expressions.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "kind",
        "parameter"
      ],
      "properties": {
        "kind": {
          "const": "parameter"
        },
        "parameter": {
          "$ref": "#/$defs/token"
        }
      }
    },
    "literalOperand": {
      "title": "Typed literal operand",
      "description": "A closed typed JSON literal. list and set literals require scalar elementType and use a JSON array value.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "kind",
        "type",
        "value"
      ],
      "properties": {
        "kind": {
          "const": "literal"
        },
        "type": {
          "$ref": "#/$defs/valueType"
        },
        "elementType": {
          "$ref": "#/$defs/scalarType"
        },
        "value": {
          "description": "JSON value matching type and elementType. The server performs format and exact type validation."
        }
      },
      "allOf": [
        {
          "if": {
            "properties": {
              "type": {
                "enum": [
                  "list",
                  "set"
                ]
              }
            },
            "required": [
              "type"
            ]
          },
          "then": {
            "required": [
              "elementType"
            ],
            "properties": {
              "value": {
                "type": "array"
              }
            }
          },
          "else": {
            "not": {
              "required": [
                "elementType"
              ]
            }
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "string"
              }
            },
            "required": [
              "type"
            ]
          },
          "then": {
            "properties": {
              "value": {
                "type": "string"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "decimal"
              }
            },
            "required": [
              "type"
            ]
          },
          "then": {
            "properties": {
              "value": {
                "$ref": "#/$defs/decimalJson"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "date"
              }
            },
            "required": [
              "type"
            ]
          },
          "then": {
            "properties": {
              "value": {
                "type": "string",
                "format": "date"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "time"
              }
            },
            "required": [
              "type"
            ]
          },
          "then": {
            "properties": {
              "value": {
                "type": "string",
                "format": "time"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "timestamp"
              }
            },
            "required": [
              "type"
            ]
          },
          "then": {
            "properties": {
              "value": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "boolean"
              }
            },
            "required": [
              "type"
            ]
          },
          "then": {
            "properties": {
              "value": {
                "type": "boolean"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "set"
              }
            },
            "required": [
              "type"
            ]
          },
          "then": {
            "properties": {
              "value": {
                "type": "array",
                "uniqueItems": true
              }
            }
          }
        }
      ]
    },
    "valueOperand": {
      "title": "Value operand",
      "description": "Closed discriminated union used by assertions, branch predicates, and effective-time expressions.",
      "oneOf": [
        {
          "$ref": "#/$defs/factOperand"
        },
        {
          "$ref": "#/$defs/parameterOperand"
        },
        {
          "$ref": "#/$defs/literalOperand"
        }
      ]
    },
    "effectiveAt": {
      "title": "Revision effective time",
      "description": "When a replacement or cancellation begins to govern the conversation. observed_at uses the time ModernEDI observed the later document. value uses an explicit timestamp, such as effectiveTimestamp extracted from an X12 860 order change. The value must be a timestamp, not only a date or clock time. A fact value belongs to the matched revision pair and must come from its source or later document; for a previous-matched same-step revision, it is read from the later revision occurrence.",
      "oneOf": [
        {
          "title": "Time ModernEDI observed the revision",
          "type": "object",
          "additionalProperties": false,
          "required": [
            "kind"
          ],
          "properties": {
            "kind": {
              "const": "observed_at"
            }
          }
        },
        {
          "title": "Business effective timestamp",
          "type": "object",
          "additionalProperties": false,
          "required": [
            "kind",
            "value"
          ],
          "properties": {
            "kind": {
              "const": "value"
            },
            "value": {
              "$ref": "#/$defs/valueOperand",
              "description": "Must resolve to a timestamp. For example, bind it to effectiveTimestamp extracted from the later X12 860. A fact operand requires value projection and one of the revision transition's endpoint steps; for a previous-matched same-step revision, it is read from the later revision occurrence."
            }
          }
        }
      ]
    },
    "revisionEffect": {
      "title": "Revision or cancellation effect",
      "description": "What a matched replacement or cancellation changes. Raw immutable observation history means every received document remains stored unchanged; the revision rule changes only the run's interpreted business view. A revision transition does not open a next-document path by itself. Each branch-decision round first snapshots the steps already allowed; its conditions see only active reevaluate effects whose original and later-document steps are both in that snapshot, and a chosen path becomes available only in the next round. After branch selection, a revision affects checks only when both endpoint steps remain on the selected conversation path. If several active reevaluate effects target the same original document, the later effectiveAt wins; equal latest times fail with REVISION_EFFECT_CONFLICT instead of choosing arbitrarily.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "effectiveAt",
        "downstream",
        "unmatched"
      ],
      "properties": {
        "effectiveAt": {
          "$ref": "#/$defs/effectiveAt",
          "description": "When this replacement or cancellation begins to govern checks. Later active reevaluate effects take precedence for the same original document."
        },
        "downstream": {
          "type": "string",
          "enum": [
            "retain",
            "reevaluate"
          ],
          "description": "retain records the change and effective time but keeps using the original document for branch conditions, ordinary follows transitions, and assertions; for example, record an advisory 860 while later shipment checks still use the original 850. reevaluate recomputes those same consumers with the replacement or removal; for example, use the revised 860 values for later 856/810 checks, or remove a 301 booking confirmation after its 303 cancellation."
        },
        "unmatched": {
          "type": "string",
          "enum": [
            "fail",
            "record"
          ],
          "description": "Behavior when no prior effective occurrence can be revised or cancelled. previous matching requires record because the first occurrence is the initial revision and necessarily has no prior occurrence."
        }
      }
    },
    "predicate": {
      "title": "Branch predicate",
      "description": "A yes/no condition evaluated after the branch's named checkpoint is emitted. For example, after an X12 301 emits bookingDisposition, compare the cancelRequested run parameter with true to select the X12 303 path. A fact condition must read the common source step of every alternative and that fact's extract stage must precede the checkpoint; it cannot read a destination document or later pipeline evidence to make that destination eligible. Every condition sees the conversation view from the start of the decision round, so one branch cannot use evidence made available by itself or a sibling branch in that round.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "operator",
        "left"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/token"
        },
        "operator": {
          "type": "string",
          "enum": [
            "equal",
            "not_equal",
            "exists",
            "unique",
            "same_set",
            "subset",
            "sum_equal",
            "less_than_or_equal",
            "greater_than_or_equal",
            "monotonic"
          ]
        },
        "left": {
          "$ref": "#/$defs/valueOperand"
        },
        "right": {
          "$ref": "#/$defs/valueOperand"
        }
      },
      "oneOf": [
        {
          "properties": {
            "operator": {
              "enum": [
                "equal",
                "not_equal",
                "same_set",
                "subset",
                "sum_equal",
                "less_than_or_equal",
                "greater_than_or_equal"
              ]
            }
          },
          "required": [
            "right"
          ]
        },
        {
          "properties": {
            "operator": {
              "enum": [
                "exists",
                "unique",
                "monotonic"
              ]
            }
          },
          "not": {
            "required": [
              "right"
            ]
          }
        }
      ]
    },
    "branchAlternative": {
      "title": "Branch alternative",
      "description": "One ordinary follows transition that a branch may select, either when its conditions pass or as the explicit otherwise fallback. For example, cancelRequested=true selects the 301-to-303 follows transition; otherwise selects 301-to-304. supersedes and cancels transitions are revision records, not branch alternatives.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "kind",
        "transitionId",
        "conditions"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/token"
        },
        "kind": {
          "type": "string",
          "enum": [
            "when",
            "otherwise"
          ]
        },
        "transitionId": {
          "$ref": "#/$defs/token",
          "description": "ID of a follows transition selected by this branch; supersedes and cancels transitions are not allowed."
        },
        "conditions": {
          "type": "array",
          "maxItems": 20,
          "items": {
            "$ref": "#/$defs/predicate"
          },
          "description": "Conditions may use parameters, literals, or facts from the alternatives' shared fromStep. They cannot read a destination step to select that destination."
        }
      },
      "oneOf": [
        {
          "properties": {
            "kind": {
              "const": "when"
            },
            "conditions": {
              "type": "array",
              "minItems": 1
            }
          }
        },
        {
          "properties": {
            "kind": {
              "const": "otherwise"
            },
            "conditions": {
              "type": "array",
              "maxItems": 0
            }
          }
        }
      ]
    },
    "branch": {
      "title": "Explicit branch",
      "description": "A choice between mutually exclusive next-document paths after a named checkpoint. The checkpoint must be emitted by the alternatives' shared source step, so the decision precedes every controlled destination. The emitter must also necessarily observe at least one document; expected_count or explicit closure with occurrence min 0 cannot emit a branch checkpoint. All alternatives leave the same source step. Example: after a 301 booking confirmation emits bookingDisposition, choose the 303 cancellation path when cancelRequested=true; otherwise choose 304 shipping instructions. exactly_one must choose one path and therefore requires an otherwise fallback. at_most_one may choose no path. A round evaluates only evidence already available when that round began; its selection can make later steps available in the next round.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "mode",
        "checkpoint",
        "alternatives"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/token"
        },
        "mode": {
          "type": "string",
          "enum": [
            "exactly_one",
            "at_most_one"
          ]
        },
        "checkpoint": {
          "$ref": "#/$defs/token"
        },
        "alternatives": {
          "type": "array",
          "minItems": 1,
          "maxItems": 20,
          "items": {
            "$ref": "#/$defs/branchAlternative"
          },
          "description": "at_most_one accepts one or more when alternatives; exactly_one requires at least two alternatives and exactly one otherwise."
        }
      }
    }
  }
}
