{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://mirzahusadzic.github.io/gadfly/frame.schema.json",
  "title": "Gadfly frame",
  "description": "Structural validation for editors. midwife.frame.parse remains authoritative for cross-field invariants and trial non-vacuity.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "name",
    "relation",
    "locus",
    "role",
    "grain",
    "purpose",
    "trajectory",
    "crossing",
    "promise",
    "baseline",
    "body",
    "anchors",
    "inputs",
    "observe",
    "interventions",
    "allowed",
    "standing",
    "battery"
  ],
  "properties": {
    "name": {
      "type": "string",
      "minLength": 1
    },
    "relation": {
      "type": "string",
      "minLength": 1
    },
    "locus": {
      "type": "string",
      "minLength": 1
    },
    "role": {
      "type": "string",
      "minLength": 1
    },
    "grain": {
      "type": "string",
      "minLength": 1
    },
    "purpose": {
      "type": "string",
      "minLength": 1
    },
    "trajectory": {
      "type": "string",
      "minLength": 1
    },
    "crossing": {
      "type": "string",
      "minLength": 1
    },
    "promise": {
      "type": "string",
      "minLength": 1
    },
    "baseline": {
      "oneOf": [
        {
          "type": "string",
          "minLength": 1
        },
        {
          "type": "object",
          "minProperties": 1
        }
      ]
    },
    "body": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "spans"
      ],
      "properties": {
        "spans": {
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/$defs/span"
          }
        }
      }
    },
    "anchors": {
      "$ref": "#/$defs/ids"
    },
    "inputs": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "text"
        ],
        "properties": {
          "id": {
            "type": "string",
            "minLength": 1
          },
          "text": {
            "type": "string",
            "minLength": 1
          }
        }
      }
    },
    "observe": {
      "type": "object",
      "required": [
        "labels",
        "instruction"
      ],
      "properties": {
        "labels": {
          "type": "array",
          "minItems": 2,
          "uniqueItems": true,
          "items": {
            "type": "string",
            "minLength": 1
          }
        },
        "instruction": {
          "type": "string",
          "minLength": 1
        },
        "order": {
          "type": "array",
          "uniqueItems": true,
          "items": {
            "type": "string",
            "minLength": 1
          }
        }
      },
      "description": "labels and instruction are read by Gadfly; other keys are for your battery."
    },
    "interventions": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "ablation"
      ],
      "properties": {
        "repeat": {
          "type": "boolean"
        },
        "ablation": {
          "const": true
        },
        "eachAnchor": {
          "type": "boolean"
        },
        "cumulative": {
          "$ref": "#/$defs/ids"
        },
        "sham": {
          "oneOf": [
            {
              "type": "boolean"
            },
            {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "draws"
              ],
              "properties": {
                "draws": {
                  "type": "integer",
                  "minimum": 1
                },
                "kind": {
                  "type": "object",
                  "minProperties": 1,
                  "propertyNames": {
                    "minLength": 1
                  },
                  "additionalProperties": {
                    "type": "string",
                    "minLength": 1
                  }
                }
              }
            }
          ]
        },
        "presentation": {
          "type": "object",
          "minProperties": 1,
          "additionalProperties": {
            "type": "string",
            "minLength": 1
          }
        },
        "placement": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "span",
            "after"
          ],
          "properties": {
            "span": {
              "type": "string",
              "minLength": 1
            },
            "after": {
              "type": "string",
              "minLength": 1
            }
          }
        },
        "inversion": {
          "type": "object",
          "minProperties": 1,
          "additionalProperties": {
            "type": "string",
            "minLength": 1
          }
        },
        "inputInversion": {
          "type": "object",
          "minProperties": 1,
          "additionalProperties": {
            "type": "string",
            "minLength": 1
          }
        },
        "bypass": {
          "$ref": "#/$defs/ids"
        },
        "control": {
          "$ref": "#/$defs/ids"
        }
      }
    },
    "allowed": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "ablation"
      ],
      "properties": {
        "ablation": {
          "$ref": "#/$defs/influence"
        },
        "bypass": {
          "$ref": "#/$defs/influence"
        },
        "inversion": {
          "$ref": "#/$defs/influence"
        },
        "inputInversion": {
          "$ref": "#/$defs/influence"
        }
      }
    },
    "standing": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "quorum",
        "agree"
      ],
      "properties": {
        "quorum": {
          "type": "integer",
          "minimum": 1
        },
        "agree": {
          "type": "integer",
          "minimum": 1
        },
        "stable": {
          "type": "boolean"
        }
      }
    },
    "battery": {
      "type": "object",
      "required": [
        "kind"
      ],
      "properties": {
        "kind": {
          "type": "string",
          "minLength": 1
        }
      }
    },
    "materialized": {
      "type": "boolean"
    },
    "outsideScope": {
      "type": "string",
      "minLength": 1
    },
    "carriage": {
      "enum": [
        "all-checks",
        "listed"
      ],
      "description": "all-checks (default): carried and cooled need their checks passed; listed: open checks are listed beside the category."
    },
    "scopeCheck": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "owner",
        "statement",
        "source",
        "encounter"
      ],
      "properties": {
        "owner": {
          "type": "string",
          "minLength": 1
        },
        "statement": {
          "type": "string",
          "minLength": 1
        },
        "source": {
          "type": "string",
          "minLength": 1
        },
        "encounter": {
          "type": "string",
          "minLength": 1
        }
      },
      "description": "The receiving owner's independent check of the outsideScope exclusion."
    }
  },
  "$defs": {
    "span": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "text"
      ],
      "properties": {
        "id": {
          "type": "string",
          "minLength": 1
        },
        "text": {
          "type": "string",
          "minLength": 1
        },
        "kind": {
          "type": "string",
          "minLength": 1,
          "default": "text"
        }
      }
    },
    "ids": {
      "type": "array",
      "minItems": 1,
      "uniqueItems": true,
      "items": {
        "type": "string",
        "minLength": 1
      }
    },
    "influence": {
      "oneOf": [
        {
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": {
            "type": "string",
            "minLength": 1
          }
        },
        {
          "enum": [
            "lower",
            "higher"
          ]
        }
      ]
    }
  },
  "dependentRequired": {
    "scopeCheck": [
      "outsideScope"
    ]
  }
}
