{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://law.arxo.io/schema/population-binding.schema.json",
  "title": "Arxo population binding 0.1",
  "description": "An authoring, pinnable binding of microdata tables to the cases of a case package: the model and its semanticHash, the case package, a source as a closed CSV subset with tables, keys, entities, and parent-child relations, column-to-literal translation via TypeRef, the root population table (rowId, case name, weight, legalTime), and fact entries. It carries no legal meaning: the adapter computes nothing — each cell becomes a literal of an origin case_input fact. The contentHash self-pin is the canonical form without the contentHash field. The runner checks table and column name uniqueness, column existence in the header, and predicates and types against the CLIR (POPULATION_BINDING_INVALID / POPULATION_BINDING_MODEL_MISMATCH); the schema only holds the shape.",
  "$comment": "SPEC §168.4; DECISION-0264 §2; SPEC §208",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "schemaVersion",
    "id",
    "dataClass",
    "model",
    "casePackage",
    "source",
    "population",
    "facts",
    "contentHash"
  ],
  "properties": {
    "schemaVersion": {
      "const": "law.population.binding/0.1"
    },
    "id": {
      "$ref": "screen-binding.schema.json#/$defs/StableId"
    },
    "dataClass": {
      "description": "Data class of the source: real triggers a POPULATION_BINDING_DATA_CLASS rejection pending a separate decision on storage. The field is required: its absence is not treated as synthetic.",
      "$comment": "DECISION-0264, F7-5",
      "enum": ["synthetic", "real"]
    },
    "model": {
      "type": "object",
      "additionalProperties": false,
      "required": ["name", "version", "semanticHash"],
      "properties": {
        "name": {
          "description": "Model package name — as in the case's import and in the <name>::<local name> prefix.",
          "$ref": "#/$defs/PackageName"
        },
        "version": {
          "$ref": "#/$defs/Version"
        },
        "semanticHash": {
          "description": "semanticHash of the model's CLIR as fed to the adapter (--clir); a mismatch triggers POPULATION_BINDING_MODEL_MISMATCH.",
          "$ref": "screen-binding.schema.json#/$defs/Digest"
        }
      }
    },
    "casePackage": {
      "type": "object",
      "additionalProperties": false,
      "required": ["name", "version", "namespace"],
      "properties": {
        "name": {
          "$ref": "#/$defs/PackageName"
        },
        "version": {
          "$ref": "#/$defs/Version"
        },
        "namespace": {
          "type": "string",
          "minLength": 1
        }
      }
    },
    "source": {
      "type": "object",
      "additionalProperties": false,
      "required": ["encoding", "delimiter", "decimalSeparator", "nullMarkers", "timezone", "tables"],
      "properties": {
        "encoding": {
          "const": "utf-8"
        },
        "delimiter": {
          "enum": [",", ";", "\t"]
        },
        "decimalSeparator": {
          "enum": [".", ","]
        },
        "nullMarkers": {
          "description": "Cell values read as NULL; a column may override the list.",
          "$comment": "DECISION-0264 §4",
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "timezone": {
          "description": "Timezone of each case's context.",
          "$comment": "SPEC §168.3",
          "type": "string",
          "minLength": 1
        },
        "tables": {
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/$defs/Table"
          }
        }
      }
    },
    "population": {
      "type": "object",
      "additionalProperties": false,
      "required": ["table", "rowId", "caseName", "weight", "legalTime"],
      "properties": {
        "table": {
          "description": "Root table: one row is one case and one bank row.",
          "$ref": "#/$defs/TableName"
        },
        "rowId": {
          "description": "Template for the bank's rowId with {column} substitutions; the result must satisfy the bank schema's Name.",
          "$ref": "#/$defs/Pattern"
        },
        "caseName": {
          "description": "Template for the case declaration name; the result must satisfy the bank schema's CaseName.",
          "$ref": "#/$defs/Pattern"
        },
        "weight": {
          "description": "Weight column: Decimal ≥ 0; NULL or negative triggers the row rejection ROW_WEIGHT_INVALID.",
          "$ref": "#/$defs/ColumnRef"
        },
        "legalTime": {
          "description": "The case's legal_time: a column of type Date or Instant, or a constant in the same recording form; one form per binding.",
          "$comment": "DECISION-0264 §5",
          "oneOf": [
            {
              "$ref": "#/$defs/ColumnRef"
            },
            {
              "type": "object",
              "additionalProperties": false,
              "required": ["constant"],
              "properties": {
                "constant": {
                  "type": "string",
                  "minLength": 1
                }
              }
            }
          ]
        }
      }
    },
    "facts": {
      "type": "array",
      "minItems": 1,
      "items": {
        "$ref": "#/$defs/Fact"
      }
    },
    "contentHash": {
      "$ref": "screen-binding.schema.json#/$defs/Digest"
    }
  },
  "$defs": {
    "PackageName": {
      "type": "string",
      "pattern": "^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)*$"
    },
    "Version": {
      "type": "string",
      "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
    },
    "TableName": {
      "type": "string",
      "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
    },
    "ColumnName": {
      "description": "Name of a CSV header column.",
      "type": "string",
      "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$"
    },
    "Pattern": {
      "type": "object",
      "additionalProperties": false,
      "required": ["pattern"],
      "properties": {
        "pattern": {
          "description": "Text with {column} substitutions; the column's raw value — NULL triggers the row rejection ROW_KEY_NULL.",
          "type": "string",
          "minLength": 1
        }
      }
    },
    "ColumnRef": {
      "type": "object",
      "additionalProperties": false,
      "required": ["column"],
      "properties": {
        "column": {
          "$ref": "#/$defs/ColumnName"
        }
      }
    },
    "Table": {
      "type": "object",
      "additionalProperties": false,
      "required": ["name", "file", "key", "entity", "columns"],
      "properties": {
        "name": {
          "$ref": "#/$defs/TableName"
        },
        "file": {
          "description": "Path to the CSV relative to the binding file.",
          "type": "string",
          "minLength": 1
        },
        "key": {
          "description": "Key columns; uniqueness is a property of the source (POPULATION_SOURCE_INVALID).",
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/$defs/ColumnName"
          }
        },
        "entity": {
          "$ref": "#/$defs/Entity"
        },
        "parent": {
          "$ref": "#/$defs/Parent"
        },
        "columns": {
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/$defs/Column"
          }
        }
      }
    },
    "Entity": {
      "type": "object",
      "additionalProperties": false,
      "required": ["idPattern", "type"],
      "properties": {
        "idPattern": {
          "description": "Template for the row entity's identifier (URN/IRI) with {column} substitutions.",
          "$comment": "SPEC §36",
          "type": "string",
          "minLength": 1
        },
        "type": {
          "description": "TypeRef of the model's nominal entity type; checked against the predicate's parameter.",
          "$ref": "legal-ir.schema.json#/$defs/TypeRef"
        }
      }
    },
    "Parent": {
      "description": "Child table: the foreign key column points to the key of table table (a single-column key); an orphan triggers POPULATION_SOURCE_INVALID; more than one row when cardinality is one triggers the row rejection ROW_CARDINALITY.",
      "type": "object",
      "additionalProperties": false,
      "required": ["table", "column", "cardinality"],
      "properties": {
        "table": {
          "$ref": "#/$defs/TableName"
        },
        "column": {
          "$ref": "#/$defs/ColumnName"
        },
        "cardinality": {
          "enum": ["one", "many"]
        }
      }
    },
    "Column": {
      "type": "object",
      "additionalProperties": false,
      "required": ["name", "type"],
      "properties": {
        "name": {
          "$ref": "#/$defs/ColumnName"
        },
        "type": {
          "description": "TypeRef of a literal type (Integer, Decimal, Money, Boolean, Text, Date, Instant), or the name of a model enumeration (in which case members is required).",
          "$ref": "legal-ir.schema.json#/$defs/TypeRef"
        },
        "currency": {
          "description": "Currency of a Money literal; required for Money, forbidden otherwise (checked by the tool).",
          "type": "string",
          "pattern": "^[A-Z]{3}$"
        },
        "members": {
          "description": "Enumeration: source value → model member name.",
          "type": "object",
          "minProperties": 1,
          "additionalProperties": {
            "type": "string",
            "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
          }
        },
        "trueValues": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "string"
          }
        },
        "falseValues": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "string"
          }
        },
        "nullMarkers": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    },
    "Fact": {
      "type": "object",
      "additionalProperties": false,
      "required": ["predicate", "table", "arguments", "presence"],
      "properties": {
        "predicate": {
          "description": "Identifier of the model's CLIR symbol_decl (a URN with a #local name).",
          "$ref": "screen-binding.schema.json#/$defs/StableId"
        },
        "table": {
          "description": "Table whose rows generate the fact; argument entities are this table or its ancestors along the parent chain.",
          "$ref": "#/$defs/TableName"
        },
        "arguments": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/Argument"
          }
        },
        "presence": {
          "oneOf": [
            {
              "type": "object",
              "additionalProperties": false,
              "required": ["kind"],
              "properties": {
                "kind": {
                  "const": "row"
                }
              }
            },
            {
              "type": "object",
              "additionalProperties": false,
              "required": ["kind", "column"],
              "properties": {
                "kind": {
                  "const": "boolean_column"
                },
                "column": {
                  "$ref": "#/$defs/ColumnName"
                }
              }
            }
          ]
        },
        "required": {
          "description": "NULL in the column argument triggers the row rejection ROW_REQUIRED_NULL instead of the fact simply being absent.",
          "$comment": "DECISION-0264 §4",
          "type": "boolean",
          "default": false
        }
      }
    },
    "Argument": {
      "oneOf": [
        {
          "type": "object",
          "additionalProperties": false,
          "required": ["kind", "table"],
          "properties": {
            "kind": {
              "const": "entity"
            },
            "table": {
              "$ref": "#/$defs/TableName"
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": ["kind", "column"],
          "properties": {
            "kind": {
              "const": "column"
            },
            "column": {
              "$ref": "#/$defs/ColumnName"
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": ["kind", "value", "type"],
          "properties": {
            "kind": {
              "const": "constant"
            },
            "value": {
              "description": "Literal text as written in .lawcase (e.g. fr.apl::ZONE_1 or true).",
              "type": "string",
              "minLength": 1
            },
            "type": {
              "$ref": "legal-ir.schema.json#/$defs/TypeRef"
            }
          }
        }
      ]
    }
  }
}
