{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://law.arxo.io/schema/parameter-dataset.schema.json",
  "title": "Arxo A3 parameter dataset 0.1",
  "description": "Canonical immutable temporal scalar parameter dataset (A3 format).",
  "$comment": "SPEC §A3.2",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "schemaVersion": {
      "const": "law.params/0.1"
    },
    "kind": {
      "const": "parameter-dataset"
    },
    "id": {
      "$ref": "#/$defs/StableId"
    },
    "parameter": {
      "$ref": "#/$defs/StableId"
    },
    "valueType": {
      "$ref": "#/$defs/TypeRef"
    },
    "timeAxis": {
      "const": "legal_time"
    },
    "granularity": {
      "enum": [
        "date",
        "instant"
      ]
    },
    "coverage": {
      "$ref": "#/$defs/TemporalRange"
    },
    "values": {
      "type": "array",
      "minItems": 1,
      "items": {
        "$ref": "#/$defs/ParameterValue"
      }
    },
    "labels": {
      "type": "array",
      "description": "Labels of the parameter ITSELF — carried through to its symbol_decl. Not spread across dataset rows: each row has its own carrier, because the parameter spawns a node per row, and a dataset-level label would name them all with the same name.",
      "$comment": "SPEC §218; E-0056",
      "items": {
        "$ref": "#/$defs/Label"
      }
    },
    "metadata": {
      "type": "object",
      "additionalProperties": true
    }
  },
  "required": [
    "schemaVersion",
    "kind",
    "id",
    "parameter",
    "valueType",
    "timeAxis",
    "granularity",
    "coverage",
    "values"
  ],
  "$defs": {
    "StableId": {
      "type": "string",
      "minLength": 1
    },
    "DateString": {
      "type": "string",
      "format": "date",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "InstantString": {
      "type": "string",
      "format": "date-time",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?Z$"
    },
    "TemporalBoundary": {
      "oneOf": [
        {
          "$ref": "#/$defs/DateString"
        },
        {
          "$ref": "#/$defs/InstantString"
        },
        {
          "type": "null"
        }
      ]
    },
    "TemporalRange": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "start": {
          "$ref": "#/$defs/TemporalBoundary"
        },
        "endExclusive": {
          "$ref": "#/$defs/TemporalBoundary"
        }
      },
      "required": [
        "start",
        "endExclusive"
      ]
    },
    "TypeRef": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "name": {
          "$ref": "#/$defs/StableId"
        },
        "args": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/TypeRef"
          }
        },
        "optional": {
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "name"
      ]
    },
    "JsonValue": {
      "oneOf": [
        {
          "type": "null"
        },
        {
          "type": "boolean"
        },
        {
          "type": "integer"
        },
        {
          "type": "string"
        },
        {
          "type": "array",
          "items": {
            "$ref": "#/$defs/JsonValue"
          }
        },
        {
          "type": "object",
          "additionalProperties": {
            "$ref": "#/$defs/JsonValue"
          }
        }
      ]
    },
    "LiteralTerm": {
      "additionalProperties": false,
      "properties": {
        "currency": {
          "type": "string"
        },
        "display": {
          "type": "string"
        },
        "kind": {
          "const": "value"
        },
        "type": {
          "$ref": "#/$defs/TypeRef"
        },
        "unit": {
          "type": "string"
        },
        "value": {
          "$ref": "#/$defs/JsonValue"
        },
        "factors": {
          "description": "The multiset of base units of a quantity. `unit` is not parsed on read but is CHECKED against its rendering: the \"base _per_ base\" grammar is ambiguous.",
          "$comment": "SPEC §49.1; E-0136",
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "unit": {
                "type": "string"
              },
              "exp": {
                "type": "integer"
              }
            },
            "required": [
              "unit",
              "exp"
            ]
          }
        },
        "lower": {
          "description": "Lower bound of the interval, an irreducible fraction `<n>/<d>`.",
          "$comment": "SPEC §259.2; E-0136",
          "type": "string",
          "pattern": "^-?[0-9]+/[1-9][0-9]*$"
        },
        "upper": {
          "description": "Upper bound of the interval.",
          "$comment": "SPEC §259.2; E-0136",
          "type": "string",
          "pattern": "^-?[0-9]+/[1-9][0-9]*$"
        },
        "derivation": {
          "description": "The derivation canon. The bounds are RECOMPUTED from it, not checked field by field.",
          "$comment": "SPEC §259.2; E-0136",
          "type": "string",
          "minLength": 1
        },
        "poly": {
          "description": "Algebraic minimal-polynomial coefficients in ascending order, as ASCII-int decimal strings; verified through the canon funnel on read, never trusted.",
          "$comment": "DECISION-0437; 0.4.1",
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[+-]?[0-9]+$"
          }
        },
        "root": {
          "description": "1-based index of the real root in ascending order; range-checked against the Sturm count on read.",
          "$comment": "DECISION-0437; 0.4.1",
          "type": "integer",
          "minimum": 1
        },
        "expr": {
          "description": "Real-expression canon string; verified through the constructor funnel on read, never trusted.",
          "$comment": "DECISION-0438; 0.5; SPEC §1",
          "type": "string",
          "minLength": 1
        }
      },
      "required": [
        "kind",
        "type"
      ],
      "type": "object"
    },
    "ParameterValue": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "id": {
          "$ref": "#/$defs/StableId"
        },
        "valid": {
          "$ref": "#/$defs/TemporalRange"
        },
        "value": {
          "$ref": "#/$defs/LiteralTerm"
        },
        "anchors": {
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": {
            "$ref": "#/$defs/StableId"
          }
        },
        "labels": {
          "type": "array",
          "description": "Labels of the dataset row. Carried through to the symbol_decl it produces; a dataset-level label is NOT spread across rows — otherwise every rate would be named after the parameter. Outside the semantic hash, inside the content hash of the node.",
          "$comment": "SPEC §218; E-0056; SPEC §209; E-0010; SPEC §202",
          "items": {
            "$ref": "#/$defs/Label"
          }
        }
      },
      "required": [
        "id",
        "valid",
        "value",
        "anchors"
      ]
    },
    "LanguageTag": {
      "type": "string",
      "pattern": "^[A-Za-z]{2,8}(?:-[A-Za-z0-9]{1,8})*$"
    },
    "Label": {
      "type": "object",
      "additionalProperties": false,
      "description": "Copy of the label definition from the intermediate-representation schema: A3 schemas are self-contained and do not borrow their primitives (StableId, LiteralTerm, TypeRef) either.",
      "$comment": "SPEC §218",
      "properties": {
        "grammaticalForms": {
          "type": "object",
          "description": "Morphological forms of the label; the key is a slot from the closed dictionary of its language tag, the value is a non-empty form.",
          "$comment": "SPEC §218.1",
          "propertyNames": {
            "pattern": "^[a-z][a-z0-9_]*$"
          },
          "additionalProperties": {
            "type": "string",
            "minLength": 1
          },
          "minProperties": 1
        },
        "language": {
          "$ref": "#/$defs/LanguageTag"
        },
        "status": {
          "enum": [
            "official",
            "unofficial",
            "translation"
          ]
        },
        "text": {
          "type": "string"
        }
      },
      "required": [
        "language",
        "status",
        "text"
      ]
    }
  }
}
