{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://verio.dev/schema/release.schema.json",
  "title": "Version",
  "description": "One version: the interval it covers, and the changes it carries. The file is named for it \u2014 1.0.0.yaml is version 1.0.0 \u2014 except unreleased.yaml, which is the version being worked on and has no number yet, because that is decided by what ends up in it.",
  "type": "object",
  "additionalProperties": true,
  "properties": {
    "from": {
      "description": "Where this version starts, exclusive. Everything that changed after this commit belongs to the version.",
      "oneOf": [
        {
          "type": "string",
          "description": "A commit hash."
        },
        {
          "type": "object",
          "required": [
            "commit"
          ],
          "additionalProperties": true,
          "properties": {
            "commit": {
              "type": "string",
              "minLength": 7,
              "description": "Authoritative. A tag is a movable pointer; a commit is not."
            },
            "label": {
              "type": "string",
              "description": "How it was chosen \u2014 a tag or a commit subject. It reads; the commit decides."
            }
          }
        }
      ]
    },
    "to": {
      "description": "Where it ended, inclusive: the commit that released it. Only a version that has been released has one \u2014 the one being worked on has not ended and cannot name the commit it is being written into, so this being set is what released means. It cannot equal `from`: a version spans two commits, and one spanning none is not a version.",
      "oneOf": [
        {
          "type": "string",
          "description": "A commit hash."
        },
        {
          "type": "object",
          "required": [
            "commit"
          ],
          "additionalProperties": true,
          "properties": {
            "commit": {
              "type": "string",
              "minLength": 7,
              "description": "Authoritative. A tag is a movable pointer; a commit is not."
            },
            "label": {
              "type": "string",
              "description": "How it was chosen \u2014 a tag or a commit subject. It reads; the commit decides."
            }
          }
        }
      ]
    },
    "version": {
      "type": "string",
      "description": "On unreleased.yaml only: the number this version is meant to be. Its file cannot be named for it \u2014 nobody has decided it for certain yet, and the path has to hold still while branches merge \u2014 but it is often known long before it is released. A released version\u2019s number is its filename, so this says nothing there."
    },
    "changes": {
      "description": "The changes this version carries, keyed by identifier \u2014 CHANGE-7 \u2014 in the order they were written. The numbering runs on across versions, so an identifier names one change wherever it is quoted.",
      "type": "object",
      "propertyNames": {
        "pattern": "^CHANGE-[0-9]+$"
      },
      "additionalProperties": {
        "$ref": "#/$defs/change"
      }
    }
  },
  "$defs": {
    "change": {
      "type": "object",
      "additionalProperties": true,
      "required": [
        "title"
      ],
      "properties": {
        "title": {
          "type": "string",
          "minLength": 1,
          "description": "What is being changed, in one line."
        },
        "description": {
          "type": "string",
          "description": "The change in full: what should change and why. Markdown."
        },
        "source": {
          "type": "object",
          "description": "Where the change came from. A change to a released design is not self-justifying, and its origin decides how much scrutiny it needs.",
          "additionalProperties": true,
          "properties": {
            "type": {
              "type": "string",
              "description": "The kind of origin. The listed values are what the editor offers; any other value is allowed, because no closed list fits every quality system.",
              "examples": [
                "capa",
                "post-market feedback",
                "problem report",
                "soup upgrade",
                "regulatory change",
                "risk control",
                "planned feature"
              ]
            },
            "link": {
              "type": "string",
              "description": "Where that origin lives \u2014 a CAPA in the QMS, an issue, an advisory."
            }
          }
        },
        "modifications": {
          "type": "array",
          "description": "What this change did: the commits it accounts for, and the design paths each reached. Nothing about the design's values is stored \u2014 the commit is when, the paths are where, and what actually changed is the repository's to answer (git show has the real diff). paths is written even when the whole commit is claimed: redundant while the commit lives, load-bearing when history is rewritten, and what keeps the record readable with no repository at all. Written by the editor when a commit is allocated to this change; a claim typed by hand is as valid as one the editor wrote.",
          "items": {
            "type": "object",
            "required": [
              "commit",
              "paths"
            ],
            "additionalProperties": false,
            "properties": {
              "commit": {
                "type": "string",
                "pattern": "^[0-9a-fA-F]{7,40}$",
                "description": "The commit that made these changes. The whole hash, or git's short form."
              },
              "paths": {
                "type": "array",
                "minItems": 1,
                "items": {
                  "type": "string",
                  "minLength": 1
                },
                "description": "The design paths this claim accounts for, of what the commit reached \u2014 requirements/REQ-AUT01/description, documents/SRS/content. All of them for a commit claimed whole, the part for a commit claimed in part."
              }
            }
          }
        }
      },
      "description": "One change: what was asked for, where that came from, and the modifications it accounts for. It lives here, in the version that carries it \u2014 a change belongs to one version, and an outside change process is pointed at through source.link."
    }
  }
}
