{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/3gppscout-com/json-schema/3gppscout-com-section-window-schema.json",
  "title": "SectionWindow",
  "description": "The part of one clause around a term, with its citation (3GP-340).",
  "x-generated": "2026-10-31",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/3gppscout-com-openapi.json#/components/schemas/SectionWindow",
  "properties": {
    "doc_number": {
      "type": "string",
      "title": "Doc Number"
    },
    "doc_type": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Doc Type",
      "description": "'TS' or 'TR'."
    },
    "version": {
      "type": "string",
      "title": "Version"
    },
    "release": {
      "type": "string",
      "title": "Release"
    },
    "section_number": {
      "type": "string",
      "title": "Section Number"
    },
    "section_title": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Section Title"
    },
    "term": {
      "type": "string",
      "title": "Term"
    },
    "match": {
      "type": "string",
      "title": "Match",
      "description": "'phrase' (the term appears in the clause; the window is around the occurrence asked for), 'terms' (it does not appear as a phrase; the window holds most of its words) or 'none' (no text returned)."
    },
    "match_count": {
      "anyOf": [
        {
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "title": "Match Count",
      "description": "Occurrences of the phrase in the clause. Null for match 'terms'."
    },
    "occurrence": {
      "anyOf": [
        {
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "title": "Occurrence",
      "description": "Which occurrence the window is around (1 is the first)."
    },
    "match_positions": {
      "items": {
        "type": "integer"
      },
      "type": "array",
      "title": "Match Positions",
      "description": "Word numbers (1 is the clause's first word) where the phrase occurs, up to 30. A window starts a quarter of its length before the occurrence."
    },
    "text": {
      "type": "string",
      "title": "Text",
      "description": "The window: whole words, in the clause's own spacing.",
      "default": ""
    },
    "window_start_word": {
      "anyOf": [
        {
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "title": "Window Start Word",
      "description": "Clause word number of the window's first word."
    },
    "window_end_word": {
      "anyOf": [
        {
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "title": "Window End Word",
      "description": "Clause word number of the window's last word."
    },
    "returned_words": {
      "type": "integer",
      "title": "Returned Words",
      "default": 0
    },
    "total_words": {
      "type": "integer",
      "title": "Total Words",
      "description": "Words in the whole clause.",
      "default": 0
    },
    "limit_words": {
      "type": "integer",
      "title": "Limit Words",
      "description": "Most words one call returns."
    },
    "truncated": {
      "type": "boolean",
      "title": "Truncated",
      "description": "True when the window is not the whole clause.",
      "default": false
    },
    "truncation_reason": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Truncation Reason",
      "description": "'window' (the rest of the clause is outside the window) or 'clause_daily_limit' (the day's limit for windows of this clause was reached)."
    },
    "latest_version": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Latest Version"
    },
    "latest_release": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Latest Release"
    },
    "same_text_as_latest": {
      "anyOf": [
        {
          "type": "boolean"
        },
        {
          "type": "null"
        }
      ],
      "title": "Same Text As Latest"
    },
    "citation": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Citation"
    },
    "official_url": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Official Url"
    },
    "next_step": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Next Step"
    },
    "provenance": {
      "anyOf": [
        {
          "$ref": "#/$defs/SpecProvenance"
        },
        {
          "type": "null"
        }
      ],
      "description": "When this version was uploaded to the 3GPP archive and the TSG plenary it came from, with sources. Null when the version has no provenance row yet."
    }
  },
  "type": "object",
  "required": [
    "doc_number",
    "version",
    "release",
    "section_number",
    "term",
    "match",
    "limit_words"
  ],
  "$defs": {
    "SpecProvenance": {
      "properties": {
        "statement": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Statement",
          "description": "The known facts as plain sentences, ready to quote, e.g. 'Uploaded to the 3GPP archive on 2026-09-24 at 16:47 UTC. Approved at TSG SA #113 (2026-09-15 to 2026-09-18).' It says 'uploaded to the 3GPP archive' and 'approved at', never 'published': no source states a publication date."
        },
        "archive_uploaded_at": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Archive Uploaded At",
          "description": "When this version's zip was uploaded to the 3GPP archive (ISO 8601, UTC), as the 3GPP FTP folder listing at archive_url shows it. If 3GPP re-uploaded the file, the earliest time seen. Null when not found; see unknown_reasons."
        },
        "archive_url": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Archive Url",
          "description": "The zip on the 3GPP FTP server whose folder listing gives archive_uploaded_at; open its folder to verify the time."
        },
        "archive_date_source": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Archive Date Source",
          "description": "'ftp_archive_listing' (the spec's folder under /ftp/Specs/archive/) or 'ftp_plenary_folder_listing' (a dated plenary folder that showed an earlier time)."
        },
        "plenary_batch": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Plenary Batch",
          "description": "YYYY-MM of the plenary round whose batch of specifications includes this version (3GPP's dated folders, /ftp/Specs/YYYY-MM/)."
        },
        "plenary_batch_source": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Plenary Batch Source",
          "description": "'tsg_spec_list' (stated in 3GPP's list of specifications arising from that TSG round), 'tsg_meeting_start' (the month the plenary in tsg_meeting started) or 'ftp_plenary_folder' (the earliest dated folder holding the zip)."
        },
        "tsg_meeting": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Tsg Meeting",
          "description": "Plenary meeting ID: 'SP-113' (TSG SA #113), 'RP-109' (TSG RAN), 'CP-110' (TSG CT); a trailing '-e' marks an electronic meeting."
        },
        "tsg_meeting_name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Tsg Meeting Name",
          "description": "The meeting as 3GPP names it, e.g. 'TSG SA #113'."
        },
        "tsg_meeting_relation": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Tsg Meeting Relation",
          "description": "'approved': change requests approved at this meeting created this version (3GPP CR database). 'arising_from': 3GPP lists this version among the specifications arising from this meeting. 'presented': a draft (below version 3.0.0) presented to this meeting."
        },
        "tsg_meeting_start": {
          "anyOf": [
            {
              "type": "string",
              "format": "date"
            },
            {
              "type": "null"
            }
          ],
          "title": "Tsg Meeting Start",
          "description": "First day of the plenary meeting."
        },
        "tsg_meeting_end": {
          "anyOf": [
            {
              "type": "string",
              "format": "date"
            },
            {
              "type": "null"
            }
          ],
          "title": "Tsg Meeting End",
          "description": "Last day of the plenary meeting."
        },
        "tsg_meeting_source": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Tsg Meeting Source",
          "description": "'cr_database' (3GPP change request database export) or 'tsg_spec_list' (3GPP's list of specifications arising from that TSG round)."
        },
        "tsg_meeting_source_url": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Tsg Meeting Source Url",
          "description": "The 3GPP file that names the meeting."
        },
        "unknown_reasons": {
          "anyOf": [
            {
              "additionalProperties": {
                "type": "string"
              },
              "type": "object"
            },
            {
              "type": "null"
            }
          ],
          "title": "Unknown Reasons",
          "description": "Why a field is null, by field name. archive_uploaded_at: 'not_in_archive_listing'. tsg_meeting: 'before_tsg_lists_no_approved_cr' (uploaded before March 2023, when 3GPP's per-round spec lists start, and created by no approved change request, e.g. a release upgrade), 'draft_not_listed', or 'not_in_cr_database_or_tsg_lists'. Nothing is guessed."
        },
        "notes": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Notes",
          "description": "Anything a reviewer should know, e.g. the file was re-uploaded or two sources name different meetings."
        }
      },
      "type": "object",
      "title": "SpecProvenance",
      "description": "When this spec version reached the public 3GPP archive, and the TSG plenary it came from.\n\nEvery value comes from the 3GPP FTP server: archive and dated plenary folder listings, 3GPP's lists of\nspecifications arising from each TSG round, and the 3GPP change request database. Unknown values stay null."
    }
  }
}