{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "$ref": "#/definitions/Model",
  "definitions": {
    "Model": {
      "properties": {
        "name": {
          "type": "string",
          "description": "Optional human-readable system name."
        },
        "description": {
          "type": "string",
          "description": "Optional human- and AI-readable description of the system."
        },
        "templates": {
          "items": {
            "$ref": "#/definitions/subcor.v1.Template"
          },
          "type": "array",
          "description": "Reusable entity shapes that can be instantiated by setting `template` on an entity. Templates may contribute fields, ports, and children."
        },
        "entities": {
          "items": {
            "$ref": "#/definitions/subcor.v1.Entity"
          },
          "type": "array",
          "description": "Top-level entities of the model. Entities may nest via `children`. An entity is identified by its path within the hierarchy (period-delimited)."
        },
        "relationships": {
          "items": {
            "$ref": "#/definitions/subcor.v1.Relationship"
          },
          "type": "array",
          "description": "Top-level relationships. Relationships are deliberately flat (not embedded inside entities) so refactors, symmetric relations, queries, and AI authoring stay tractable."
        },
        "metadata": {
          "additionalProperties": true,
          "type": "object",
          "description": "Optional free-form key-value bag for user/AI-authored structured notes. Contents are not validated."
        }
      },
      "additionalProperties": true,
      "type": "object",
      "title": "Model",
      "description": "Model is the identity-free semantic graph of a single system. Model carries no system identity — the system_id lives on SystemConfiguration, which wraps a Model. This keeps Model reusable as a pure content type without binding it to any particular System or Release. Identifier rules for entity ids, field ids, port ids, template names, relation ids: must match `^[a-zA-Z_][a-zA-Z0-9_]*$`. `.` is reserved as the path separator and `#` is reserved for future port-shorthand notation."
    },
    "subcor.v1.ArrayType": {
      "properties": {
        "elements": {
          "enum": [
            "PRIMITIVE_TYPE_UNSPECIFIED",
            0,
            "PRIMITIVE_TYPE_FLOAT32",
            1,
            "PRIMITIVE_TYPE_FLOAT64",
            2,
            "PRIMITIVE_TYPE_INT8",
            3,
            "PRIMITIVE_TYPE_INT16",
            4,
            "PRIMITIVE_TYPE_INT32",
            5,
            "PRIMITIVE_TYPE_INT64",
            6,
            "PRIMITIVE_TYPE_UINT8",
            7,
            "PRIMITIVE_TYPE_UINT16",
            8,
            "PRIMITIVE_TYPE_UINT32",
            9,
            "PRIMITIVE_TYPE_UINT64",
            10,
            "PRIMITIVE_TYPE_BOOL",
            11,
            "PRIMITIVE_TYPE_STRING",
            12
          ],
          "oneOf": [
            {
              "type": "string"
            },
            {
              "type": "integer"
            }
          ],
          "title": "Primitive Type",
          "description": "PrimitiveType enumerates supported scalar value types."
        }
      },
      "additionalProperties": true,
      "type": "object",
      "title": "Array Type",
      "description": "ArrayType is a homogeneous array of primitive elements."
    },
    "subcor.v1.BoolLabels": {
      "properties": {
        "true_label": {
          "type": "string"
        },
        "false_label": {
          "type": "string"
        }
      },
      "additionalProperties": true,
      "type": "object",
      "title": "Bool Labels",
      "description": "BoolLabels is an optional display-label pair for bool-typed fields. See Field.bool_labels."
    },
    "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.Endpoint": {
      "properties": {
        "entity_path": {
          "type": "string",
          "description": "Period-delimited entity path from the system root, e.g. \"plant1.reactor_a\"."
        },
        "port": {
          "type": "string",
          "description": "Optional port id on the referenced entity."
        }
      },
      "additionalProperties": true,
      "type": "object",
      "title": "Endpoint",
      "description": "Endpoint references one end of a relationship. The entity_path resolves to an entity in the Model; if `port` is set, the relationship terminates on that named port; if `port` is unset, it terminates on the entity itself."
    },
    "subcor.v1.Entity": {
      "properties": {
        "id": {
          "type": "string",
          "description": "Path-segment identifier, unique among siblings. Must not contain '.'."
        },
        "name": {
          "type": "string",
          "description": "Optional human-readable name."
        },
        "description": {
          "type": "string",
          "description": "Human- and AI-readable description of what this entity represents."
        },
        "template": {
          "type": "string",
          "description": "Optional template name (declared in Model.templates) whose fields, ports, and children are merged into this entity per the rules above."
        },
        "fields": {
          "items": {
            "$ref": "#/definitions/subcor.v1.Field"
          },
          "type": "array",
          "description": "Inline field declarations. Combined additively with template-contributed fields. Field ids must be unique within the entity (after template merge)."
        },
        "ports": {
          "items": {
            "$ref": "#/definitions/subcor.v1.Port"
          },
          "type": "array",
          "description": "Named handles for connection points. See Port. A relation may terminate on a port or on the entity itself. Combined additively with template ports."
        },
        "children": {
          "items": {
            "$ref": "#/definitions/subcor.v1.Entity"
          },
          "type": "array",
          "description": "Nested child entities. Paths are period-delimited from the system root. Combined additively with template children."
        },
        "metadata": {
          "additionalProperties": true,
          "type": "object",
          "description": "Optional free-form key-value bag."
        }
      },
      "additionalProperties": true,
      "type": "object",
      "title": "Entity",
      "description": "Entity is the basic building block of a model. An entity may have zero or more fields, zero or more ports, and zero or more child entities. A bare entity (no fields, no ports, no children) is valid — it represents a passive component that has semantic value but no measurements. Template merge rules (when `template` is set):   - Final fields   = template.fields   ∪ entity.fields   - Final ports    = template.ports    ∪ entity.ports   - Final children = template.children ∪ entity.children   - Strictly additive: id collisions across the two sets are validation     errors. Override / shadowing is intentionally not supported in MVP.   - Templates may not (yet) reference other templates."
    },
    "subcor.v1.EnumType": {
      "properties": {
        "values": {
          "items": {
            "$ref": "#/definitions/subcor.v1.EnumValue"
          },
          "type": "array",
          "description": "At least one value. Ids and numbers must each be unique within the enum."
        }
      },
      "additionalProperties": true,
      "type": "object",
      "title": "Enum Type",
      "description": "EnumType is a small, named set of discrete states (e.g. idle/running/fault). Carried as int32 on the wire (Value.int32_val); decoded back to its label by every consumer that holds the resolved model — the same model-at-the-edges posture as ord/path duality. Codes are author-assigned and usually dictated by the source (a PLC mode register); sparse and negative codes are legal. Definitions are inline per-field; reuse comes from templates."
    },
    "subcor.v1.EnumValue": {
      "properties": {
        "id": {
          "type": "string",
          "description": "Required. Identifier (same lexical rules as other ids). Referenced symbolically by collector mappings, so renaming an id is a mapping-visible change; display naming belongs in `name`."
        },
        "number": {
          "type": "integer",
          "description": "Required (via explicit presence — 0 is a legal code). Author-assigned wire code. Adding/removing values changes the ingest contract and bumps runtime_release_version; the numbers (not ids/names) enter RuntimeConfig."
        },
        "name": {
          "type": "string",
          "description": "Optional display name. Falls back to id."
        },
        "description": {
          "type": "string",
          "description": "Optional human/AI-facing description of the state."
        }
      },
      "additionalProperties": true,
      "type": "object",
      "title": "Enum Value",
      "description": "EnumValue is one declared state of an EnumType."
    },
    "subcor.v1.Field": {
      "properties": {
        "id": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "type": {
          "$ref": "#/definitions/subcor.v1.FieldType",
          "additionalProperties": true,
          "description": "Type of the field's value (primitive scalar or compound)."
        },
        "quantity": {
          "$ref": "#/definitions/subcor.v1.Quantity",
          "additionalProperties": true,
          "description": "Physical/semantic dimension. Either a named convenience type or, for anything outside the named set, an explicit dimension exponent vector. Units are deliberately not part of the model — they are a presentation/ ingest concern."
        },
        "metadata": {
          "additionalProperties": true,
          "type": "object",
          "description": "Optional free-form key-value bag."
        },
        "bool_labels": {
          "$ref": "#/definitions/subcor.v1.BoolLabels",
          "additionalProperties": true,
          "description": "Optional display labels for bool-typed fields (e.g. true → \"Open\", false → \"Closed\"). Pure display: never affects ingest, validation, or the runtime contract (it does not enter RuntimeConfig), so relabeling is always free. Valid only when `type` is PRIMITIVE_TYPE_BOOL; when present, both labels must be non-empty (both-or-neither). Unlabeled bools render as true/false."
        }
      },
      "additionalProperties": true,
      "type": "object",
      "title": "Field",
      "description": "Field is a primitive-valued (typically scalar) element of data attached to an entity. Always nullable at runtime; null means \"data unavailable for that timestamp\". Populated at runtime by zero or more providers (a runtime concept, not part of the model). Principle: if a relation needs measurements, model it as an entity instead. E.g. a pipe with a flow reading is a flow-sensor entity, not a relation with fields."
    },
    "subcor.v1.FieldType": {
      "properties": {
        "primitive": {
          "enum": [
            "PRIMITIVE_TYPE_UNSPECIFIED",
            0,
            "PRIMITIVE_TYPE_FLOAT32",
            1,
            "PRIMITIVE_TYPE_FLOAT64",
            2,
            "PRIMITIVE_TYPE_INT8",
            3,
            "PRIMITIVE_TYPE_INT16",
            4,
            "PRIMITIVE_TYPE_INT32",
            5,
            "PRIMITIVE_TYPE_INT64",
            6,
            "PRIMITIVE_TYPE_UINT8",
            7,
            "PRIMITIVE_TYPE_UINT16",
            8,
            "PRIMITIVE_TYPE_UINT32",
            9,
            "PRIMITIVE_TYPE_UINT64",
            10,
            "PRIMITIVE_TYPE_BOOL",
            11,
            "PRIMITIVE_TYPE_STRING",
            12
          ],
          "oneOf": [
            {
              "type": "string"
            },
            {
              "type": "integer"
            }
          ],
          "title": "Primitive Type",
          "description": "PrimitiveType enumerates supported scalar value types."
        },
        "array": {
          "$ref": "#/definitions/subcor.v1.ArrayType",
          "additionalProperties": true
        },
        "enum": {
          "$ref": "#/definitions/subcor.v1.EnumType",
          "additionalProperties": true
        }
      },
      "additionalProperties": true,
      "type": "object",
      "title": "Field Type",
      "description": "FieldType is either a primitive scalar or a compound type. proto-JSON wire form is `{\"primitive\": \"PRIMITIVE_TYPE_FLOAT64\"}` or `{\"array\": {\"elements\": \"PRIMITIVE_TYPE_FLOAT64\"}}`. A future authoring-sugar layer in the CLI may collapse these to bare-string shorthand; the wire shape stays as-is."
    },
    "subcor.v1.Port": {
      "properties": {
        "id": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "metadata": {
          "additionalProperties": true,
          "type": "object"
        }
      },
      "additionalProperties": true,
      "type": "object",
      "title": "Port",
      "description": "Port is a named handle on an entity that a relationship can terminate on. Ports are deliberately minimal — no direction, no type, no role. Use metadata for ad-hoc structured hints (e.g. ISA tag, nozzle size) and let relations carry the cross-entity semantics."
    },
    "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.Relationship": {
      "properties": {
        "id": {
          "type": "string",
          "description": "Identifier, unique among relationships."
        },
        "name": {
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "kind": {
          "type": "string",
          "description": "Semantic type of the relation. Free-form string; a recommended starter vocabulary (documented separately) includes:   flow, electrical, signal, control, contains, adjacent_to, mechanical Conventions are encouraged but not enforced."
        },
        "from": {
          "$ref": "#/definitions/subcor.v1.Endpoint",
          "additionalProperties": true
        },
        "to": {
          "$ref": "#/definitions/subcor.v1.Endpoint",
          "additionalProperties": true
        },
        "directed": {
          "type": "boolean",
          "description": "Optional explicit directionality. Unset lets renderers/validators pick a default based on `kind`. Authors may set this to override, e.g. an explicitly bidirectional flow line."
        },
        "metadata": {
          "additionalProperties": true,
          "type": "object",
          "description": "Optional free-form key-value bag."
        }
      },
      "additionalProperties": true,
      "type": "object",
      "title": "Relationship",
      "description": "Relationship is a semantic edge between two endpoints. It is not a physical object; physical things with measurements are entities. Relationships are flat (top-level on the Model). Termination is an entity, optionally narrowed to one of its ports."
    },
    "subcor.v1.Template": {
      "properties": {
        "name": {
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "fields": {
          "items": {
            "$ref": "#/definitions/subcor.v1.Field"
          },
          "type": "array"
        },
        "ports": {
          "items": {
            "$ref": "#/definitions/subcor.v1.Port"
          },
          "type": "array"
        },
        "children": {
          "items": {
            "$ref": "#/definitions/subcor.v1.Entity"
          },
          "type": "array"
        },
        "metadata": {
          "additionalProperties": true,
          "type": "object"
        }
      },
      "additionalProperties": true,
      "type": "object",
      "title": "Template",
      "description": "Template is a reusable bundle of fields, ports, and/or children that can be applied to an entity by name. See merge rules on Entity."
    }
  }
}
