{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://uwmd.org/schemas/metric-dictionary.schema.json",
  "title": "UW Metric Dictionary",
  "description": "Normative class-scoped calculation definitions, minimum comparison precision (RFC 0079), and unrounded primary-size selectors (RFC 0078). Expression syntax, resolution and numeric semantics are Protocol VIII.1, VIII.2 and VIII.5. See spec/metrics/README.md. RFC 0125 registers data-center rentable_square_feet as secondary for price_per_sqft; critical IT kW remains primary. RFC 0126 binds land carry NOI at matching block scope/period/variant, including nonpositive results.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "$schema",
    "calculations",
    "size_intensives",
    "statement_bindings"
  ],
  "properties": {
    "$schema": {
      "const": "https://uwmd.org/schemas/metric-dictionary.schema.json"
    },
    "calculations": {
      "type": "array",
      "minItems": 1,
      "items": {
        "$ref": "#/$defs/calculation"
      }
    },
    "size_intensives": {
      "type": "array",
      "minItems": 1,
      "items": {
        "$ref": "#/$defs/size"
      }
    },
    "statement_bindings": {
      "description": "RFC 0099: the closed registry of where a document states each dictionary metric, beyond frontmatter `quick_metrics.<id>`. A statement is a finite number at `S.<id>` for each output section S, or at an alias path. No binding is inferred from a field name.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "output_sections",
        "aliases"
      ],
      "properties": {
        "output_sections": {
          "description": "Section roots at which a metric's own id is a statement of it.",
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9_]*$"
          }
        },
        "aliases": {
          "description": "Further `section.path` addresses that state a metric, by metric id.",
          "type": "object",
          "propertyNames": {
            "pattern": "^[a-z][a-z0-9_]*$"
          },
          "additionalProperties": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$"
            }
          }
        }
      }
    }
  },
  "$defs": {
    "calculation": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "label",
        "asset_classes",
        "formula",
        "input_paths",
        "unit",
        "section_roles",
        "round_to",
        "null_semantics",
        "deterministic",
        "minimum_stated_decimals"
      ],
      "properties": {
        "id": {
          "type": "string",
          "pattern": "^[a-z][a-z0-9_]*$"
        },
        "label": {
          "type": "string",
          "minLength": 1
        },
        "asset_classes": {
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": {
            "enum": [
              "multifamily",
              "office",
              "retail",
              "industrial",
              "self_storage",
              "hospitality",
              "mixed_use",
              "senior_housing",
              "student_housing",
              "land",
              "data_center",
              "manufactured_housing"
            ]
          }
        },
        "formula": {
          "type": "string",
          "minLength": 1
        },
        "input_paths": {
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": {
            "type": "string",
            "minLength": 1
          }
        },
        "unit": {
          "type": "string",
          "minLength": 1
        },
        "section_roles": {
          "type": "object",
          "propertyNames": {
            "pattern": "^[a-z][a-z0-9_]*$"
          },
          "additionalProperties": {
            "enum": [
              "primary",
              "senior",
              "junior",
              "summary",
              "detail"
            ]
          }
        },
        "round_to": {
          "type": "integer",
          "minimum": 0,
          "maximum": 12
        },
        "null_semantics": {
          "description": "expression: Protocol VIII.2 semantics. positive_size_denominator (RFC 0100): the same, and unverifiable when a registered size the formula divides by is stated below zero.",
          "enum": [
            "expression",
            "positive_size_denominator"
          ]
        },
        "deterministic": {
          "const": true
        },
        "minimum_stated_decimals": {
          "type": "integer",
          "minimum": 0,
          "maximum": 12,
          "description": "Comparison floor in stored units: compare at min(max(source decimals, this minimum), round_to); a coarser statement is checked at this floor, not refused."
        }
      },
      "allOf": [
        {
          "if": {
            "properties": {
              "round_to": {
                "const": 0
              }
            }
          },
          "then": {
            "properties": {
              "minimum_stated_decimals": {
                "maximum": 0,
                "type": "integer"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "round_to": {
                "const": 1
              }
            }
          },
          "then": {
            "properties": {
              "minimum_stated_decimals": {
                "maximum": 1,
                "type": "integer"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "round_to": {
                "const": 2
              }
            }
          },
          "then": {
            "properties": {
              "minimum_stated_decimals": {
                "maximum": 2,
                "type": "integer"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "round_to": {
                "const": 3
              }
            }
          },
          "then": {
            "properties": {
              "minimum_stated_decimals": {
                "maximum": 3,
                "type": "integer"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "round_to": {
                "const": 4
              }
            }
          },
          "then": {
            "properties": {
              "minimum_stated_decimals": {
                "maximum": 4,
                "type": "integer"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "round_to": {
                "const": 5
              }
            }
          },
          "then": {
            "properties": {
              "minimum_stated_decimals": {
                "maximum": 5,
                "type": "integer"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "round_to": {
                "const": 6
              }
            }
          },
          "then": {
            "properties": {
              "minimum_stated_decimals": {
                "maximum": 6,
                "type": "integer"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "round_to": {
                "const": 7
              }
            }
          },
          "then": {
            "properties": {
              "minimum_stated_decimals": {
                "maximum": 7,
                "type": "integer"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "round_to": {
                "const": 8
              }
            }
          },
          "then": {
            "properties": {
              "minimum_stated_decimals": {
                "maximum": 8,
                "type": "integer"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "round_to": {
                "const": 9
              }
            }
          },
          "then": {
            "properties": {
              "minimum_stated_decimals": {
                "maximum": 9,
                "type": "integer"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "round_to": {
                "const": 10
              }
            }
          },
          "then": {
            "properties": {
              "minimum_stated_decimals": {
                "maximum": 10,
                "type": "integer"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "round_to": {
                "const": 11
              }
            }
          },
          "then": {
            "properties": {
              "minimum_stated_decimals": {
                "maximum": 11,
                "type": "integer"
              }
            }
          }
        }
      ]
    },
    "size": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "label",
        "asset_classes",
        "formula",
        "input_paths",
        "unit",
        "section_roles",
        "round_to",
        "null_semantics",
        "path",
        "secondary",
        "minimum_stated_decimals"
      ],
      "properties": {
        "id": {
          "type": "string",
          "pattern": "^[a-z][a-z0-9_]*$"
        },
        "label": {
          "type": "string",
          "minLength": 1
        },
        "asset_classes": {
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": {
            "enum": [
              "multifamily",
              "office",
              "retail",
              "industrial",
              "self_storage",
              "hospitality",
              "mixed_use",
              "senior_housing",
              "student_housing",
              "land",
              "data_center",
              "manufactured_housing"
            ]
          }
        },
        "formula": {
          "type": "string",
          "minLength": 1
        },
        "input_paths": {
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": {
            "type": "string",
            "minLength": 1
          }
        },
        "unit": {
          "type": "string",
          "minLength": 1
        },
        "section_roles": {
          "type": "object",
          "propertyNames": {
            "pattern": "^[a-z][a-z0-9_]*$"
          },
          "additionalProperties": {
            "enum": [
              "primary",
              "senior",
              "junior",
              "summary",
              "detail"
            ]
          }
        },
        "round_to": {
          "type": "null"
        },
        "null_semantics": {
          "const": "finite_stated_number"
        },
        "path": {
          "type": "string",
          "pattern": "^[a-z][a-z0-9_]*$"
        },
        "secondary": {
          "type": "array",
          "uniqueItems": true,
          "items": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9_]*$"
          }
        },
        "minimum_stated_decimals": {
          "const": 0,
          "description": "Raw size selectors retain exact finite-number identity and impose no fractional minimum."
        }
      }
    }
  }
}
