{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://physicalai-bmi.org/assets/data/sensing-disclosure.schema.json",
  "title": "Sensing disclosure",
  "description": "What a sensing system resolved, what it could not reach, and what it reached while past calibration, stated separately for the two questions a mesh is asked. Proposed in TR-2026-44. Both question classes are required, because the central finding of that report is that a system answering only the field-mean question and not saying so is the normal failure, not an unusual one.",
  "type": "object",
  "required": [
    "disclosure_version",
    "subject",
    "as_of",
    "fractions",
    "sensors",
    "not_measured"
  ],
  "additionalProperties": false,
  "properties": {
    "disclosure_version": {
      "const": "1"
    },
    "subject": {
      "type": "object",
      "required": [
        "kind",
        "id",
        "volume_m3",
        "volume_basis"
      ],
      "additionalProperties": false,
      "properties": {
        "kind": {
          "type": "string",
          "description": "grain-bin, field, orchard-block, pen, bin-run, or another named volume"
        },
        "id": {
          "type": "string"
        },
        "volume_m3": {
          "type": "number",
          "exclusiveMinimum": 0
        },
        "volume_basis": {
          "type": "string",
          "minLength": 12,
          "description": "How the volume was determined. A disclosure whose denominator is unexplained cannot be checked."
        }
      }
    },
    "as_of": {
      "type": "string",
      "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"
    },
    "fractions": {
      "type": "object",
      "required": [
        "field_mean",
        "localized_event"
      ],
      "additionalProperties": false,
      "description": "Fractions of subject.volume_m3, per question class. Each set must sum to 1. Untrusted is separated from unknown because a reader recovers untrusted volume with a technician and unknown volume with a new sensor.",
      "properties": {
        "field_mean": {
          "type": "object",
          "required": [
            "resolved",
            "untrusted",
            "unknown"
          ],
          "additionalProperties": false,
          "properties": {
            "resolved": {
              "type": "number",
              "minimum": 0,
              "maximum": 1
            },
            "untrusted": {
              "type": "number",
              "minimum": 0,
              "maximum": 1
            },
            "unknown": {
              "type": "number",
              "minimum": 0,
              "maximum": 1
            }
          },
          "description": "Answering 'what is the average over this volume'. Interpolation covers the gaps between sensors when the quantity varies smoothly, so this is usually the larger resolved figure."
        },
        "localized_event": {
          "type": "object",
          "required": [
            "resolved",
            "untrusted",
            "unknown"
          ],
          "additionalProperties": false,
          "properties": {
            "resolved": {
              "type": "number",
              "minimum": 0,
              "maximum": 1
            },
            "untrusted": {
              "type": "number",
              "minimum": 0,
              "maximum": 1
            },
            "unknown": {
              "type": "number",
              "minimum": 0,
              "maximum": 1
            }
          },
          "description": "Answering 'did something happen somewhere in this volume'. There is nothing to interpolate a localized event from, so only volume a sensor physically reaches counts as resolved."
        }
      }
    },
    "sensors": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "required": [
          "modality",
          "count",
          "reach_m",
          "reach_basis",
          "provenance"
        ],
        "additionalProperties": false,
        "properties": {
          "modality": {
            "type": "string"
          },
          "count": {
            "type": "integer",
            "minimum": 1
          },
          "reach_m": {
            "type": [
              "number",
              "null"
            ],
            "exclusiveMinimum": 0,
            "description": "Radius one sensor resolves. Null where the reach is not known, which is a legitimate disclosure and a required one: a modality with an invented radius is worse than a modality with none."
          },
          "reach_basis": {
            "type": "string",
            "minLength": 8,
            "description": "The expression or measurement the reach comes from, stated so a reader can recompute it."
          },
          "provenance": {
            "enum": [
              "measured",
              "derived",
              "modelled",
              "assumed",
              "not-located"
            ],
            "description": "Grade of the reach, not of the sensor. Derived means computed from a measured coefficient; assumed means chosen without one."
          },
          "calibration": {
            "type": "object",
            "required": [
              "interval_days",
              "past_interval"
            ],
            "additionalProperties": false,
            "properties": {
              "interval_days": {
                "type": "integer",
                "minimum": 1
              },
              "past_interval": {
                "type": "integer",
                "minimum": 0,
                "description": "How many of this modality's sensors are past their interval at as_of."
              }
            }
          }
        }
      }
    },
    "not_measured": {
      "type": "array",
      "description": "Quantities this disclosure could not determine, phrased as what was not determined rather than as what does not exist.",
      "items": {
        "type": "string",
        "minLength": 12
      }
    },
    "notes": {
      "type": "string"
    }
  }
}