{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "$ref": "#/definitions/Dashboard",
  "definitions": {
    "Dashboard": {
      "properties": {
        "id": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "default_window": {
          "pattern": "^([0-9]+\\.?[0-9]*|\\.[0-9]+)s$",
          "type": "string",
          "description": "Initial visible time window (e.g. 15m). Absent -> the platform's shared live-tail default. All widgets share one playhead/window; a widget cannot set its own.",
          "format": "regex"
        },
        "rows": {
          "items": {
            "$ref": "#/definitions/subcor.v1.Row"
          },
          "type": "array"
        }
      },
      "additionalProperties": true,
      "type": "object",
      "title": "Dashboard",
      "description": "Dashboard is one configured view. `id` matches the dashboards/<id>.json filename slug."
    },
    "subcor.v1.Dimension": {
      "properties": {
        "length": {
          "type": "integer",
          "description": "L — length"
        },
        "mass": {
          "type": "integer",
          "description": "M — mass"
        },
        "time": {
          "type": "integer",
          "description": "T — time"
        },
        "current": {
          "type": "integer",
          "description": "I — electric current"
        },
        "temperature": {
          "type": "integer",
          "description": "Θ — thermodynamic temperature"
        },
        "amount": {
          "type": "integer",
          "description": "N — amount of substance"
        },
        "luminous_intensity": {
          "type": "integer",
          "description": "J — luminous intensity"
        }
      },
      "additionalProperties": true,
      "type": "object",
      "title": "Dimension",
      "description": "Dimension is the exponent vector over the seven SI base quantities. A scalar dimensionless value is all-zero (equivalent to NAMED_QUANTITY_DIMENSIONLESS)."
    },
    "subcor.v1.FieldSelection": {
      "properties": {
        "selectors": {
          "items": {
            "$ref": "#/definitions/subcor.v1.Selector"
          },
          "type": "array"
        }
      },
      "additionalProperties": true,
      "type": "object",
      "title": "Field Selection",
      "description": "FieldSelection pairs an ordered list of authored selectors with their resolution. Resolution is additive: `selectors` is preserved as provenance, `resolved` is added at push."
    },
    "subcor.v1.LinePlot": {
      "properties": {
        "selection": {
          "$ref": "#/definitions/subcor.v1.FieldSelection",
          "additionalProperties": true
        },
        "series_label": {
          "type": "string",
          "description": "Optional CEL expression producing each line's legend name, evaluated per resolved field at push. Context variables: field.id, field.path, field.name, field.metadata (map), field.quantity. MUST type-check to string. Absent -> the default label (metadata name, path fallback, collision disambiguation). Empty result -> falls back to the default."
        }
      },
      "additionalProperties": true,
      "type": "object",
      "title": "Line Plot",
      "description": "LinePlot draws one line per resolved field (numeric only). Non-numeric matches are dropped at resolve time with a warning."
    },
    "subcor.v1.Quantity": {
      "properties": {
        "named": {
          "enum": [
            "NAMED_QUANTITY_UNSPECIFIED",
            0,
            "NAMED_QUANTITY_DIMENSIONLESS",
            1,
            "NAMED_QUANTITY_LENGTH",
            10,
            "NAMED_QUANTITY_MASS",
            11,
            "NAMED_QUANTITY_TIME",
            12,
            "NAMED_QUANTITY_CURRENT",
            13,
            "NAMED_QUANTITY_TEMPERATURE",
            14,
            "NAMED_QUANTITY_AMOUNT",
            15,
            "NAMED_QUANTITY_LUMINOUS_INTENSITY",
            16,
            "NAMED_QUANTITY_AREA",
            30,
            "NAMED_QUANTITY_VOLUME",
            31,
            "NAMED_QUANTITY_DENSITY",
            32,
            "NAMED_QUANTITY_VELOCITY",
            33,
            "NAMED_QUANTITY_ACCELERATION",
            34,
            "NAMED_QUANTITY_FORCE",
            35,
            "NAMED_QUANTITY_PRESSURE",
            36,
            "NAMED_QUANTITY_ENERGY",
            37,
            "NAMED_QUANTITY_POWER",
            38,
            "NAMED_QUANTITY_TORQUE",
            39,
            "NAMED_QUANTITY_FREQUENCY",
            40,
            "NAMED_QUANTITY_FLOW_VOLUMETRIC",
            41,
            "NAMED_QUANTITY_FLOW_MASS",
            42,
            "NAMED_QUANTITY_VOLTAGE",
            43,
            "NAMED_QUANTITY_RESISTANCE",
            44,
            "NAMED_QUANTITY_CHARGE",
            45,
            "NAMED_QUANTITY_CAPACITANCE",
            46,
            "NAMED_QUANTITY_INDUCTANCE",
            47,
            "NAMED_QUANTITY_MAGNETIC_FLUX",
            48,
            "NAMED_QUANTITY_ANGLE",
            60,
            "NAMED_QUANTITY_ANGULAR_VELOCITY",
            61,
            "NAMED_QUANTITY_ANGULAR_ACCELERATION",
            62,
            "NAMED_QUANTITY_RATIO",
            63,
            "NAMED_QUANTITY_PERCENT",
            64
          ],
          "oneOf": [
            {
              "type": "string"
            },
            {
              "type": "integer"
            }
          ],
          "title": "Named Quantity",
          "description": "NamedQuantity is a curated set of common quantities. Extend as we hit real plants. Use Dimension for anything outside the named set rather than stuffing free-form names through here."
        },
        "dimension": {
          "$ref": "#/definitions/subcor.v1.Dimension",
          "additionalProperties": true
        }
      },
      "additionalProperties": true,
      "type": "object",
      "title": "Quantity",
      "description": "Quantity describes the physical/semantic dimension of a field value. Two arms:   - `named`: a convenience enum covering common quantities. Carries semantic     intent in addition to dimension (e.g. torque vs energy share dimension     L²·M·T⁻² but mean different things).   - `dimension`: explicit exponent vector over the seven SI base     dimensions. Use this for anything outside the named set rather than     stuffing free-form names through `named`. Validation can compute the dimension of any named quantity from a static table and surface dimensional mismatches as warnings."
    },
    "subcor.v1.ResolvedSeries": {
      "properties": {
        "field_ord": {
          "type": "integer",
          "description": "Release-minted field identity (model.proto Field.field_ord)."
        },
        "label": {
          "type": "string",
          "description": "Flattened legend/display name: the series_label CEL result, else the default (metadata name, path fallback, collision disambiguation)."
        },
        "quantity": {
          "$ref": "#/definitions/subcor.v1.Quantity",
          "additionalProperties": true,
          "description": "Denormalized from the model so the render path can choose presentation by data type without refetching the model."
        }
      },
      "additionalProperties": true,
      "type": "object",
      "title": "Resolved Series",
      "description": "ResolvedSeries is the self-contained render unit for one field: the render path binds by field_ord and reads label/quantity without consulting the model."
    },
    "subcor.v1.Row": {
      "properties": {
        "title": {
          "type": "string"
        },
        "default_collapsed": {
          "type": "boolean",
          "description": "Rows are always collapsible; this sets the initial state."
        },
        "height": {
          "enum": [
            "ROW_HEIGHT_UNSPECIFIED",
            0,
            "ROW_HEIGHT_S",
            1,
            "ROW_HEIGHT_M",
            2,
            "ROW_HEIGHT_L",
            3
          ],
          "oneOf": [
            {
              "type": "string"
            },
            {
              "type": "integer"
            }
          ],
          "title": "Row Height",
          "description": "RowHeight is a named vertical size. No FULL arm (no vertical fill); room for an XL preset later."
        },
        "default_size": {
          "enum": [
            "WIDGET_SIZE_UNSPECIFIED",
            0,
            "WIDGET_SIZE_S",
            1,
            "WIDGET_SIZE_M",
            2,
            "WIDGET_SIZE_L",
            3,
            "WIDGET_SIZE_FULL",
            4
          ],
          "oneOf": [
            {
              "type": "string"
            },
            {
              "type": "integer"
            }
          ],
          "title": "Widget Size",
          "description": "WidgetSize is a named target width that flexes to fill the row. FULL spans the whole row width."
        },
        "widgets": {
          "items": {
            "$ref": "#/definitions/subcor.v1.Widget"
          },
          "type": "array"
        }
      },
      "additionalProperties": true,
      "type": "object",
      "title": "Row",
      "description": "Row is an ordered band of widgets. Widgets that exceed the available width flow-wrap onto the next line."
    },
    "subcor.v1.Selector": {
      "properties": {
        "path": {
          "type": "string",
          "description": "Exact field path, e.g. \"pump.speed\"."
        },
        "path_pattern": {
          "type": "string",
          "description": "Segment glob over `.`-delimited paths: `*` matches exactly one segment, `**` matches any depth. E.g. \"reactor_a.*\" (direct children) vs \"reactor_a.**\" (the whole subtree)."
        },
        "quantity_filter": {
          "items": {
            "enum": [
              "NAMED_QUANTITY_UNSPECIFIED",
              0,
              "NAMED_QUANTITY_DIMENSIONLESS",
              1,
              "NAMED_QUANTITY_LENGTH",
              10,
              "NAMED_QUANTITY_MASS",
              11,
              "NAMED_QUANTITY_TIME",
              12,
              "NAMED_QUANTITY_CURRENT",
              13,
              "NAMED_QUANTITY_TEMPERATURE",
              14,
              "NAMED_QUANTITY_AMOUNT",
              15,
              "NAMED_QUANTITY_LUMINOUS_INTENSITY",
              16,
              "NAMED_QUANTITY_AREA",
              30,
              "NAMED_QUANTITY_VOLUME",
              31,
              "NAMED_QUANTITY_DENSITY",
              32,
              "NAMED_QUANTITY_VELOCITY",
              33,
              "NAMED_QUANTITY_ACCELERATION",
              34,
              "NAMED_QUANTITY_FORCE",
              35,
              "NAMED_QUANTITY_PRESSURE",
              36,
              "NAMED_QUANTITY_ENERGY",
              37,
              "NAMED_QUANTITY_POWER",
              38,
              "NAMED_QUANTITY_TORQUE",
              39,
              "NAMED_QUANTITY_FREQUENCY",
              40,
              "NAMED_QUANTITY_FLOW_VOLUMETRIC",
              41,
              "NAMED_QUANTITY_FLOW_MASS",
              42,
              "NAMED_QUANTITY_VOLTAGE",
              43,
              "NAMED_QUANTITY_RESISTANCE",
              44,
              "NAMED_QUANTITY_CHARGE",
              45,
              "NAMED_QUANTITY_CAPACITANCE",
              46,
              "NAMED_QUANTITY_INDUCTANCE",
              47,
              "NAMED_QUANTITY_MAGNETIC_FLUX",
              48,
              "NAMED_QUANTITY_ANGLE",
              60,
              "NAMED_QUANTITY_ANGULAR_VELOCITY",
              61,
              "NAMED_QUANTITY_ANGULAR_ACCELERATION",
              62,
              "NAMED_QUANTITY_RATIO",
              63,
              "NAMED_QUANTITY_PERCENT",
              64
            ]
          },
          "type": "array",
          "title": "Named Quantity",
          "description": "NamedQuantity is a curated set of common quantities. Extend as we hit real plants. Use Dimension for anything outside the named set rather than stuffing free-form names through here."
        }
      },
      "additionalProperties": true,
      "type": "object",
      "title": "Selector",
      "description": "Selector matches one field (exact path) or many (segment glob), optionally narrowed by quantity."
    },
    "subcor.v1.Stat": {
      "properties": {
        "selection": {
          "$ref": "#/definitions/subcor.v1.FieldSelection",
          "additionalProperties": true
        },
        "trend": {
          "enum": [
            "STAT_TREND_UNSPECIFIED",
            0,
            "STAT_TREND_NONE",
            1,
            "STAT_TREND_SPARKLINE",
            2,
            "STAT_TREND_TIMELINE",
            3
          ],
          "oneOf": [
            {
              "type": "string"
            },
            {
              "type": "integer"
            }
          ],
          "title": "Stat Trend",
          "description": "StatTrend selects the Stat's at-a-glance trend affordance."
        }
      },
      "additionalProperties": true,
      "type": "object",
      "title": "Stat",
      "description": "Stat shows the current value at the playhead, over the at-a-glance trend chosen by `trend`. Its selection MUST resolve to exactly one field."
    },
    "subcor.v1.StateTimeline": {
      "properties": {
        "selection": {
          "$ref": "#/definitions/subcor.v1.FieldSelection",
          "additionalProperties": true
        },
        "series_label": {
          "type": "string",
          "description": "Optional CEL expression producing each lane's label — same contract and context variables as LinePlot.series_label."
        }
      },
      "additionalProperties": true,
      "type": "object",
      "title": "State Timeline",
      "description": "StateTimeline draws one horizontal state lane per resolved field — colored bands showing which discrete state the field was in over time. Discrete only (bool, enum, int); non-discrete matches are dropped at resolve time with a warning, mirroring LinePlot's numeric gate. (Strings join when the browser cache learns string history — state-timeline.md R1.3.)"
    },
    "subcor.v1.Widget": {
      "properties": {
        "title": {
          "type": "string",
          "description": "Panel header — distinct from the per-series legend names. A single-field widget defaults its header to the field label; a multi-field LinePlot has no default header (author-set)."
        },
        "size": {
          "enum": [
            "WIDGET_SIZE_UNSPECIFIED",
            0,
            "WIDGET_SIZE_S",
            1,
            "WIDGET_SIZE_M",
            2,
            "WIDGET_SIZE_L",
            3,
            "WIDGET_SIZE_FULL",
            4
          ],
          "oneOf": [
            {
              "type": "string"
            },
            {
              "type": "integer"
            }
          ],
          "title": "Widget Size",
          "description": "WidgetSize is a named target width that flexes to fill the row. FULL spans the whole row width."
        },
        "line_plot": {
          "$ref": "#/definitions/subcor.v1.LinePlot",
          "additionalProperties": true
        },
        "stat": {
          "$ref": "#/definitions/subcor.v1.Stat",
          "additionalProperties": true
        },
        "state_timeline": {
          "$ref": "#/definitions/subcor.v1.StateTimeline",
          "additionalProperties": true
        }
      },
      "additionalProperties": true,
      "type": "object",
      "title": "Widget",
      "description": "Widget is one panel: a LinePlot, a Stat, or a StateTimeline."
    }
  }
}
