{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/space-ocr-com/json-schema/space-ocr-com-column-spec-schema.json",
  "title": "ColumnSpec",
  "x-generated": "2026-10-31",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/space-ocr-com-openapi.json#/components/schemas/ColumnSpec",
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "type": {
      "type": "string",
      "description": "\"string\" (default) | \"number\" | \"integer\" | \"date\" | \"array\". Scalar types never reach the model — declaring one adds a parsed `normalized` value per cell and raises `type_mismatch` when the printed value won't parse."
    },
    "description": {
      "type": "string"
    },
    "children": {
      "type": "array",
      "items": {}
    },
    "required": {
      "type": "boolean",
      "description": "Review declaration: report reason \"missing\" when this column comes back empty on an upload. Never shown to the model."
    },
    "label": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      ],
      "description": "Printed label to anchor this column's coordinates to when the value repeats on the page (string columns only, engine v64). Never shown to the model."
    },
    "pattern": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      ],
      "description": "Regex the extracted value must match (string columns only, JSON-Schema partial-match semantics — anchor with ^…$ for whole-value). Array = any-one-matches. Violation → review reason `pattern_mismatch`. Never shown to the model."
    },
    "min": {
      "type": "number",
      "description": "Inclusive lower bound for a number/integer column's normalized value. Violation → `out_of_range`."
    },
    "max": {
      "type": "number",
      "description": "Inclusive upper bound for a number/integer column's normalized value. Violation → `out_of_range`."
    },
    "enum": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Allowed values (string columns only). A value outside the set raises review reason `pattern_mismatch`. Never shown to the model."
    },
    "near": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        {
          "type": "object",
          "properties": {
            "terms": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              ]
            },
            "match": {
              "type": "string"
            }
          },
          "required": [
            "terms"
          ]
        }
      ],
      "description": "Vocabulary that must be printed beside the value — one term, a list, or { terms, match }. The check runs over every occurrence of the value: none beside a declared term → `near_mismatch`, one beside a term but not the copy the coordinates landed on → `near_ambiguous`. When the term itself is absent, `review.notes` reports `near_unresolved`. Never shown to the model."
    },
    "not_near": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        {
          "type": "object",
          "properties": {
            "terms": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              ]
            },
            "match": {
              "type": "string"
            }
          },
          "required": [
            "terms"
          ]
        }
      ],
      "description": "The mirror of `near` — vocabulary the value must NOT sit beside (登録番号/TEL/〒 on an addressee column). Sitting beside one raises `near_conflict`. Absence of the vocabulary is not a violation, so this never abstains. Never shown to the model."
    },
    "review": {
      "type": "string",
      "enum": [
        "normal",
        "off"
      ],
      "description": "\"off\" withholds engine-inferred review reasons for this column. Declared-rule violations (missing / pattern / range / enum / near) still report."
    }
  },
  "required": [
    "name",
    "type"
  ]
}