{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "dfp/proposals-file/1",
  "title": "A proposals file: one brand, one pass (decisions-model spec 6.1; REVIEW-PROCESS.md section 6)",
  "type": "object",
  "required": [
    "pass",
    "brand",
    "proposals"
  ],
  "additionalProperties": false,
  "properties": {
    "pass": {
      "type": "object",
      "required": [
        "name",
        "kind",
        "process_version",
        "rules_version",
        "generator"
      ],
      "additionalProperties": false,
      "properties": {
        "name": {
          "type": "string",
          "minLength": 3,
          "maxLength": 120,
          "pattern": "^[a-z0-9][a-z0-9._:/-]*$"
        },
        "kind": {
          "type": "string",
          "enum": [
            "session",
            "rule",
            "arrival"
          ]
        },
        "process_version": {
          "type": "string",
          "minLength": 1,
          "maxLength": 20
        },
        "rules_version": {
          "type": "string",
          "minLength": 1,
          "maxLength": 8
        },
        "generator": {
          "type": "string",
          "minLength": 1,
          "maxLength": 80
        },
        "note": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 4000
        },
        "survey": {
          "description": "K12: every kind of difference the pass saw before proposing, new kinds first: [{kind, precedent, registered, examples: [listing keys], question}]",
          "type": ["array", "null"]
        },
        "verdict": {
          "description": "`proposals`, or `settled` for a file with zero proposals that declares the brand has no open question in any layer",
          "type": ["string", "null"],
          "enum": ["proposals", "settled", null]
        },
        "fingerprint": {
          "description": "the brand's listed-words fingerprint the pass worked from (`app.cli pass fingerprint`)",
          "type": ["string", "null"],
          "maxLength": 64
        }
      }
    },
    "brand": {
      "type": "string",
      "minLength": 1,
      "maxLength": 160,
      "pattern": "^[a-z0-9][a-z0-9-]*$"
    },
    "proposals": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "entity",
          "field",
          "value",
          "reason",
          "evidence"
        ],
        "additionalProperties": false,
        "properties": {
          "sheet_line_ref": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 500,
            "pattern": "^line:"
          },
          "position": {
            "type": "integer",
            "minimum": 0
          },
          "entity": {
            "type": "object",
            "required": [
              "type",
              "key"
            ],
            "additionalProperties": false,
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "brand",
                  "product_line",
                  "product_variant",
                  "listing",
                  "attribute_wording",
                  "suggestion"
                ]
              },
              "key": {
                "type": "string",
                "minLength": 3,
                "maxLength": 500,
                "pattern": "^(brand|line|variant|listing|wording|pair):"
              },
              "detail": {
                "type": [
                  "object",
                  "null"
                ]
              }
            }
          },
          "field": {
            "type": "string",
            "maxLength": 80,
            "pattern": "^[a-z_]+(:[a-z0-9_-]{1,40}){0,2}$"
          },
          "value": {
            "type": [
              "string",
              "number",
              "boolean",
              "object",
              "array"
            ]
          },
          "confidence": {
            "type": [
              "number",
              "null"
            ],
            "minimum": 0,
            "maximum": 1
          },
          "reason": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2000
          },
          "origin": {
            "type": "string",
            "maxLength": 80
          },
          "evidence": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "object",
              "required": [
                "listing",
                "source",
                "span",
                "text"
              ],
              "additionalProperties": false,
              "properties": {
                "listing": {
                  "type": "string",
                  "pattern": "^listing:[^/]+/[^/]+/.+$"
                },
                "source": {
                  "type": "string",
                  "pattern": "^(listed_name|listed_variant|listed_quantity_text|listed_category|listed_brand|collected_name|option:[a-z0-9_-]{1,40})$"
                },
                "span": {
                  "type": "array",
                  "items": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "minItems": 2,
                  "maxItems": 2
                },
                "text": {
                  "type": "string",
                  "minLength": 1
                }
              }
            }
          },
          "answers_deferred": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 36,
            "description": "the uid of a deferred proposal this row answers: a deferred question is re-proposed only by a pass that has read its note (K11.4)"
          },
          "precedent": {
            "description": "the kind of judgement this row is: a register slug (`membership:refill-one-line`). Required from process version 6; a slug the register does not hold is critical by construction.",
            "type": ["string", "null"],
            "maxLength": 120,
            "pattern": "^[a-z0-9][a-z0-9:_-]*$"
          },
          "precedent_status": {
            "description": "`sets` when this row is the lead that sets a new precedent, `follows` when the register already holds it",
            "type": ["string", "null"],
            "enum": ["sets", "follows", null]
          },
          "follows": {
            "description": "a follower names its lead's natural key; it is rated none and goes with the lead's answer",
            "type": ["string", "null"],
            "maxLength": 500
          },
          "attention": {
            "description": "How much of a person's judgement this needs. Not confidence: a near-certain merge that sets a precedent needs more of a person than a doubtful attribute on one variant. Omit it and the sheet derives one.",
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "critical",
              "high",
              "medium",
              "low",
              "none",
              null
            ]
          }
        }
      }
    }
  }
}
