{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$defs": {
    "StoryLocator": {
      "description": "Story scope. Defaults to document body when omitted. Use {kind:'story', storyType:'body'} for body, or other storyType values for headers, footers, footnotes, endnotes.",
      "oneOf": [
        {
          "type": "object",
          "properties": {
            "kind": {
              "const": "story"
            },
            "storyType": {
              "const": "body"
            }
          },
          "additionalProperties": false,
          "required": [
            "kind",
            "storyType"
          ]
        },
        {
          "type": "object",
          "properties": {
            "kind": {
              "const": "story"
            },
            "storyType": {
              "const": "headerFooterSlot"
            },
            "section": {
              "$ref": "#/$defs/SectionAddress"
            },
            "headerFooterKind": {
              "enum": [
                "header",
                "footer"
              ]
            },
            "variant": {
              "enum": [
                "default",
                "first",
                "even"
              ]
            },
            "resolution": {
              "enum": [
                "effective",
                "explicit"
              ]
            },
            "onWrite": {
              "enum": [
                "materializeIfInherited",
                "editResolvedPart",
                "error"
              ]
            }
          },
          "additionalProperties": false,
          "required": [
            "kind",
            "storyType",
            "section",
            "headerFooterKind",
            "variant"
          ]
        },
        {
          "type": "object",
          "properties": {
            "kind": {
              "const": "story"
            },
            "storyType": {
              "const": "headerFooterPart"
            },
            "refId": {
              "type": "string"
            }
          },
          "additionalProperties": false,
          "required": [
            "kind",
            "storyType",
            "refId"
          ]
        },
        {
          "type": "object",
          "properties": {
            "kind": {
              "const": "story"
            },
            "storyType": {
              "const": "footnote"
            },
            "noteId": {
              "type": "string"
            }
          },
          "additionalProperties": false,
          "required": [
            "kind",
            "storyType",
            "noteId"
          ]
        },
        {
          "type": "object",
          "properties": {
            "kind": {
              "const": "story"
            },
            "storyType": {
              "const": "endnote"
            },
            "noteId": {
              "type": "string"
            }
          },
          "additionalProperties": false,
          "required": [
            "kind",
            "storyType",
            "noteId"
          ]
        },
        {
          "type": "object",
          "properties": {
            "kind": {
              "const": "story"
            },
            "storyType": {
              "const": "textbox"
            },
            "textboxId": {
              "type": "string"
            }
          },
          "additionalProperties": false,
          "required": [
            "kind",
            "storyType",
            "textboxId"
          ]
        }
      ]
    },
    "SectionAddress": {
      "type": "object",
      "properties": {
        "kind": {
          "const": "section"
        },
        "sectionId": {
          "type": "string"
        }
      },
      "additionalProperties": false,
      "required": [
        "kind",
        "sectionId"
      ]
    },
    "BlockNodeAddress": {
      "type": "object",
      "properties": {
        "kind": {
          "const": "block"
        },
        "nodeType": {
          "enum": [
            "paragraph",
            "heading",
            "listItem",
            "table",
            "tableRow",
            "tableCell",
            "tableOfContents",
            "image",
            "sdt"
          ]
        },
        "nodeId": {
          "type": "string"
        },
        "story": {
          "$ref": "#/$defs/StoryLocator"
        }
      },
      "additionalProperties": false,
      "required": [
        "kind",
        "nodeType",
        "nodeId"
      ]
    },
    "ResolvedHandle": {
      "type": "object",
      "properties": {
        "ref": {
          "type": "string"
        },
        "refStability": {
          "enum": [
            "stable",
            "ephemeral"
          ]
        },
        "targetKind": {
          "$ref": "#/$defs/TargetKind"
        }
      },
      "additionalProperties": false,
      "required": [
        "ref",
        "refStability",
        "targetKind"
      ]
    },
    "TargetKind": {
      "anyOf": [
        {
          "enum": [
            "text",
            "node",
            "list",
            "comment",
            "trackedChange",
            "table",
            "tableCell",
            "tableOfContents",
            "section",
            "sdt",
            "field"
          ]
        },
        {
          "type": "string",
          "pattern": "^ext:.+$"
        }
      ]
    },
    "SelectionTarget": {
      "type": "object",
      "properties": {
        "kind": {
          "const": "selection"
        },
        "start": {
          "$ref": "#/$defs/SelectionPoint"
        },
        "end": {
          "$ref": "#/$defs/SelectionPoint"
        },
        "story": {
          "$ref": "#/$defs/StoryLocator"
        },
        "coordinateSpace": {
          "$ref": "#/$defs/TextCoordinateSpace"
        }
      },
      "additionalProperties": false,
      "required": [
        "kind",
        "start",
        "end"
      ]
    },
    "SelectionPoint": {
      "description": "A point in the document. Use {kind:'text', blockId, offset} for character positions or {kind:'nodeEdge', node:{kind:'block', nodeType, nodeId}, edge:'before'|'after'} for block boundaries.",
      "oneOf": [
        {
          "type": "object",
          "properties": {
            "kind": {
              "const": "text"
            },
            "blockId": {
              "type": "string"
            },
            "offset": {
              "type": "integer",
              "minimum": 0
            },
            "story": {
              "$ref": "#/$defs/StoryLocator"
            }
          },
          "additionalProperties": false,
          "required": [
            "kind",
            "blockId",
            "offset"
          ]
        },
        {
          "type": "object",
          "properties": {
            "kind": {
              "const": "nodeEdge"
            },
            "node": {
              "$ref": "#/$defs/SelectionEdgeNodeAddress"
            },
            "edge": {
              "enum": [
                "before",
                "after"
              ]
            }
          },
          "additionalProperties": false,
          "required": [
            "kind",
            "node",
            "edge"
          ]
        }
      ]
    },
    "SelectionEdgeNodeAddress": {
      "type": "object",
      "properties": {
        "kind": {
          "const": "block"
        },
        "nodeType": {
          "enum": [
            "paragraph",
            "heading",
            "table",
            "tableOfContents",
            "sdt",
            "image"
          ]
        },
        "nodeId": {
          "type": "string"
        },
        "story": {
          "$ref": "#/$defs/StoryLocator"
        }
      },
      "additionalProperties": false,
      "required": [
        "kind",
        "nodeType",
        "nodeId"
      ]
    },
    "TextCoordinateSpace": {
      "enum": [
        "visible",
        "tracked"
      ]
    },
    "Range": {
      "type": "object",
      "properties": {
        "start": {
          "type": "integer"
        },
        "end": {
          "type": "integer"
        }
      },
      "additionalProperties": false,
      "required": [
        "start",
        "end"
      ]
    },
    "MatchBlock": {
      "type": "object",
      "properties": {
        "blockId": {
          "type": "string"
        },
        "nodeType": {
          "type": "string"
        },
        "range": {
          "$ref": "#/$defs/Range"
        },
        "coordinateSpace": {
          "$ref": "#/$defs/TextCoordinateSpace"
        },
        "text": {
          "type": "string"
        },
        "paragraphStyle": {
          "type": "object",
          "properties": {
            "styleId": {
              "type": "string"
            },
            "isListItem": {
              "type": "boolean"
            },
            "listLevel": {
              "type": "integer",
              "minimum": 0
            }
          },
          "additionalProperties": false
        },
        "ref": {
          "type": "string"
        },
        "runs": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/MatchRun"
          }
        }
      },
      "additionalProperties": false,
      "required": [
        "blockId",
        "nodeType",
        "range",
        "text",
        "ref",
        "runs"
      ]
    },
    "MatchRun": {
      "type": "object",
      "properties": {
        "range": {
          "$ref": "#/$defs/Range"
        },
        "coordinateSpace": {
          "$ref": "#/$defs/TextCoordinateSpace"
        },
        "text": {
          "type": "string"
        },
        "styleId": {
          "type": "string"
        },
        "styles": {
          "type": "object",
          "properties": {
            "direct": {
              "type": "object",
              "properties": {
                "bold": {
                  "enum": [
                    "on",
                    "off",
                    "clear"
                  ]
                },
                "italic": {
                  "enum": [
                    "on",
                    "off",
                    "clear"
                  ]
                },
                "underline": {
                  "enum": [
                    "on",
                    "off",
                    "clear"
                  ]
                },
                "strike": {
                  "enum": [
                    "on",
                    "off",
                    "clear"
                  ]
                }
              },
              "additionalProperties": false,
              "required": [
                "bold",
                "italic",
                "underline",
                "strike"
              ]
            },
            "effective": {
              "type": "object",
              "properties": {
                "bold": {
                  "type": "boolean"
                },
                "italic": {
                  "type": "boolean"
                },
                "underline": {
                  "type": "boolean"
                },
                "strike": {
                  "type": "boolean"
                }
              },
              "additionalProperties": false,
              "required": [
                "bold",
                "italic",
                "underline",
                "strike"
              ]
            },
            "color": {
              "type": "string"
            },
            "highlight": {
              "type": "string"
            },
            "fontFamily": {
              "type": "string"
            },
            "fontSizePt": {
              "type": "number"
            }
          },
          "additionalProperties": false,
          "required": [
            "direct",
            "effective"
          ]
        },
        "ref": {
          "type": "string"
        }
      },
      "additionalProperties": false,
      "required": [
        "range",
        "text",
        "styles",
        "ref"
      ]
    },
    "NodeAddress": {
      "oneOf": [
        {
          "$ref": "#/$defs/BlockNodeAddress"
        },
        {
          "$ref": "#/$defs/InlineNodeAddress"
        }
      ]
    },
    "InlineNodeAddress": {
      "type": "object",
      "properties": {
        "kind": {
          "const": "inline"
        },
        "nodeType": {
          "enum": [
            "run",
            "bookmark",
            "comment",
            "hyperlink",
            "sdt",
            "image",
            "footnoteRef",
            "endnoteRef",
            "crossRef",
            "indexEntry",
            "citation",
            "authorityEntry",
            "sequenceField",
            "tab",
            "lineBreak"
          ]
        },
        "anchor": {
          "$ref": "#/$defs/InlineAnchor"
        },
        "story": {
          "$ref": "#/$defs/StoryLocator"
        }
      },
      "additionalProperties": false,
      "required": [
        "kind",
        "nodeType",
        "anchor"
      ]
    },
    "InlineAnchor": {
      "type": "object",
      "properties": {
        "start": {
          "$ref": "#/$defs/Position"
        },
        "end": {
          "$ref": "#/$defs/Position"
        }
      },
      "additionalProperties": false,
      "required": [
        "start",
        "end"
      ]
    },
    "Position": {
      "type": "object",
      "properties": {
        "blockId": {
          "type": "string"
        },
        "offset": {
          "type": "integer"
        }
      },
      "additionalProperties": false,
      "required": [
        "blockId",
        "offset"
      ]
    },
    "PageInfo": {
      "type": "object",
      "properties": {
        "limit": {
          "type": "integer",
          "minimum": 0
        },
        "offset": {
          "type": "integer",
          "minimum": 0
        },
        "returned": {
          "type": "integer",
          "minimum": 0
        }
      },
      "additionalProperties": false,
      "required": [
        "limit",
        "offset",
        "returned"
      ]
    }
  },
  "operationId": "query.match",
  "schemas": {
    "input": {
      "type": "object",
      "properties": {
        "in": {
          "$ref": "#/$defs/StoryLocator"
        },
        "select": {
          "description": "Search selector. Use {type:'text', pattern:'...'} for text search or {type:'node', nodeType:'paragraph'|'heading'|...} for node search.",
          "oneOf": [
            {
              "type": "object",
              "properties": {
                "type": {
                  "const": "text",
                  "description": "Must be 'text' for text pattern search."
                },
                "pattern": {
                  "type": "string",
                  "description": "Text to match. In regex mode, patterns are validated for syntax, maximum length, and safety before execution."
                },
                "mode": {
                  "enum": [
                    "contains",
                    "regex"
                  ],
                  "description": "Match mode: 'contains' (literal substring, recommended for literal text) or 'regex' (validated regular expression)."
                },
                "caseSensitive": {
                  "type": "boolean",
                  "description": "Case-sensitive matching. Default: false."
                },
                "wholeWord": {
                  "type": "boolean",
                  "description": "Require word-boundary matches. Default: false."
                }
              },
              "additionalProperties": false,
              "required": [
                "type",
                "pattern"
              ]
            },
            {
              "type": "object",
              "properties": {
                "type": {
                  "const": "node",
                  "description": "Must be 'node' for node type search."
                },
                "nodeType": {
                  "enum": [
                    "paragraph",
                    "heading",
                    "listItem",
                    "table",
                    "tableRow",
                    "tableCell",
                    "tableOfContents",
                    "image",
                    "sdt",
                    "run",
                    "bookmark",
                    "comment",
                    "hyperlink",
                    "footnoteRef",
                    "endnoteRef",
                    "crossRef",
                    "indexEntry",
                    "citation",
                    "authorityEntry",
                    "sequenceField",
                    "tab",
                    "lineBreak"
                  ],
                  "description": "Block type to match (paragraph, heading, table, listItem, etc.)."
                },
                "kind": {
                  "enum": [
                    "block",
                    "inline"
                  ],
                  "description": "Filter: 'block' or 'inline'."
                }
              },
              "additionalProperties": false,
              "required": [
                "type"
              ]
            }
          ]
        },
        "within": {
          "$ref": "#/$defs/BlockNodeAddress",
          "description": "Limit search scope to within a specific block: {kind:'block', nodeType:'...', nodeId:'...'}."
        },
        "require": {
          "enum": [
            "any",
            "first",
            "exactlyOne",
            "all"
          ],
          "description": "Match cardinality: 'any' (all matches), 'first' (only first), 'exactlyOne' (fail if != 1), 'all' (fail if 0)."
        },
        "mode": {
          "enum": [
            "strict",
            "candidates"
          ],
          "description": "Search mode: 'strict' (default, exact matching) or 'candidates' (returns scored potential matches)."
        },
        "includeNodes": {
          "type": "boolean",
          "description": "When true, includes full node data in results. Default: false."
        },
        "limit": {
          "type": "integer",
          "minimum": 1,
          "description": "Maximum number of matches to return."
        },
        "offset": {
          "type": "integer",
          "minimum": 0,
          "description": "Number of matches to skip for pagination."
        }
      },
      "additionalProperties": false,
      "required": [
        "select"
      ]
    },
    "output": {
      "type": "object",
      "properties": {
        "evaluatedRevision": {
          "type": "string"
        },
        "total": {
          "type": "integer",
          "minimum": 0
        },
        "items": {
          "type": "array",
          "items": {
            "oneOf": [
              {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "handle": {
                    "$ref": "#/$defs/ResolvedHandle"
                  },
                  "matchKind": {
                    "const": "text"
                  },
                  "address": {
                    "$ref": "#/$defs/BlockNodeAddress"
                  },
                  "target": {
                    "$ref": "#/$defs/SelectionTarget"
                  },
                  "coordinateSpace": {
                    "$ref": "#/$defs/TextCoordinateSpace"
                  },
                  "snippet": {
                    "type": "string"
                  },
                  "highlightRange": {
                    "$ref": "#/$defs/Range"
                  },
                  "blocks": {
                    "type": "array",
                    "items": {
                      "$ref": "#/$defs/MatchBlock"
                    },
                    "minItems": 1
                  },
                  "groups": {
                    "type": "array",
                    "items": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "description": "Regex-mode only: capture groups from the match, index i holding group i+1 (null for non-participating groups). Absent for plain text matches."
                  }
                },
                "additionalProperties": false,
                "required": [
                  "id",
                  "handle",
                  "matchKind",
                  "address",
                  "target",
                  "snippet",
                  "highlightRange",
                  "blocks"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "handle": {
                    "$ref": "#/$defs/ResolvedHandle"
                  },
                  "matchKind": {
                    "const": "node"
                  },
                  "address": {
                    "$ref": "#/$defs/NodeAddress"
                  },
                  "blocks": {
                    "type": "array",
                    "items": {
                      "$ref": "#/$defs/MatchBlock"
                    },
                    "maxItems": 0
                  }
                },
                "additionalProperties": false,
                "required": [
                  "id",
                  "handle",
                  "matchKind",
                  "address",
                  "blocks"
                ]
              }
            ]
          }
        },
        "page": {
          "$ref": "#/$defs/PageInfo"
        },
        "meta": {
          "type": "object",
          "properties": {
            "effectiveResolved": {
              "type": "boolean"
            }
          },
          "additionalProperties": false,
          "required": [
            "effectiveResolved"
          ]
        }
      },
      "additionalProperties": false,
      "required": [
        "evaluatedRevision",
        "total",
        "items",
        "page",
        "meta"
      ]
    }
  }
}
