{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://www.glyphd.com/schemas/semantic-fractal-topology.scene.schema.json",
  "title": "Semantic Fractal Topology Scene Graph",
  "description": "Public-safe schema for the SFT typed semantic scene graph. Metric and physical claims remain bounded by the declared evidence precision and source pointers.",
  "type": "object",
  "additionalProperties": false,
  "required": ["schemaVersion", "id", "name", "rootEntityId", "frames", "entities", "relations", "metadata"],
  "properties": {
    "schemaVersion": { "const": "sft.scene.v1" },
    "id": { "$ref": "#/$defs/id" },
    "name": { "type": "string", "minLength": 1 },
    "rootEntityId": { "$ref": "#/$defs/id" },
    "frames": {
      "type": "array",
      "minItems": 1,
      "items": { "$ref": "#/$defs/metricFrame" }
    },
    "entities": {
      "type": "array",
      "minItems": 1,
      "items": { "$ref": "#/$defs/entity" }
    },
    "relations": {
      "type": "array",
      "items": { "$ref": "#/$defs/relation" }
    },
    "metadata": {
      "type": "object",
      "additionalProperties": false,
      "required": ["unit", "description", "evidenceState", "tags"],
      "properties": {
        "unit": { "$ref": "#/$defs/lengthUnit" },
        "description": { "type": "string" },
        "evidenceState": { "enum": ["IMPLEMENTED", "SPECIFIED", "AWAITING_LOCAL_RUN"] },
        "tags": { "type": "array", "items": { "type": "string" }, "uniqueItems": true }
      }
    }
  },
  "$defs": {
    "id": {
      "type": "string",
      "minLength": 1,
      "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"
    },
    "lengthUnit": { "enum": ["mm", "cm", "m", "in", "ft"] },
    "evidencePrecision": { "enum": ["EXACT", "BOUNDED"] },
    "vec3": {
      "type": "array",
      "prefixItems": [
        { "type": "number" },
        { "type": "number" },
        { "type": "number" }
      ],
      "minItems": 3,
      "maxItems": 3
    },
    "mat3": {
      "type": "array",
      "prefixItems": [
        { "$ref": "#/$defs/vec3" },
        { "$ref": "#/$defs/vec3" },
        { "$ref": "#/$defs/vec3" }
      ],
      "minItems": 3,
      "maxItems": 3
    },
    "jsonValue": {
      "anyOf": [
        { "type": ["string", "number", "boolean", "null"] },
        { "type": "array", "items": { "$ref": "#/$defs/jsonValue" } },
        { "type": "object", "additionalProperties": { "$ref": "#/$defs/jsonValue" } }
      ]
    },
    "sourcePointer": {
      "type": "object",
      "additionalProperties": false,
      "required": ["adapter", "sourceId"],
      "properties": {
        "adapter": {
          "enum": [
            "authored",
            "gltf-2.0-json",
            "openusd-ascii-subset",
            "cad-manifest-v1",
            "bim-ifc-projection-v1",
            "robot-scene-graph-v1"
          ]
        },
        "sourceId": { "type": "string", "minLength": 1 },
        "sourcePath": { "type": "string" },
        "sourceHash": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" }
      }
    },
    "metricFrame": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "name", "origin", "basis", "unit", "precision", "tolerance"],
      "properties": {
        "id": { "$ref": "#/$defs/id" },
        "name": { "type": "string", "minLength": 1 },
        "origin": { "$ref": "#/$defs/vec3" },
        "basis": { "$ref": "#/$defs/mat3" },
        "unit": { "$ref": "#/$defs/lengthUnit" },
        "precision": { "$ref": "#/$defs/evidencePrecision" },
        "tolerance": { "type": "number", "minimum": 0 },
        "parentFrameId": { "$ref": "#/$defs/id" }
      }
    },
    "bounds3": {
      "type": "object",
      "additionalProperties": false,
      "required": ["min", "max", "unit", "precision", "tolerance", "frameId", "source"],
      "properties": {
        "min": { "$ref": "#/$defs/vec3" },
        "max": { "$ref": "#/$defs/vec3" },
        "unit": { "$ref": "#/$defs/lengthUnit" },
        "precision": { "$ref": "#/$defs/evidencePrecision" },
        "tolerance": { "type": "number", "minimum": 0 },
        "frameId": { "$ref": "#/$defs/id" },
        "source": { "enum": ["authored", "imported", "derived"] }
      }
    },
    "entityKind": {
      "enum": [
        "world",
        "site",
        "building",
        "level",
        "space",
        "opening",
        "object",
        "assembly",
        "part",
        "service",
        "access-zone",
        "robot",
        "robot-link",
        "path-node",
        "obstacle",
        "game-actor",
        "game-item"
      ]
    },
    "relationKind": {
      "enum": [
        "contains",
        "adjacent_to",
        "connected_to",
        "opens_into",
        "supported_by",
        "attached_to",
        "requires_before",
        "blocks",
        "reachable_from",
        "services",
        "mounted_on",
        "joint_to",
        "occupies"
      ]
    },
    "entity": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "name", "kind", "frameId", "attributes", "source"],
      "properties": {
        "id": { "$ref": "#/$defs/id" },
        "name": { "type": "string", "minLength": 1 },
        "kind": { "$ref": "#/$defs/entityKind" },
        "frameId": { "$ref": "#/$defs/id" },
        "bounds": { "$ref": "#/$defs/bounds3" },
        "position": { "$ref": "#/$defs/vec3" },
        "attributes": { "type": "object", "additionalProperties": { "$ref": "#/$defs/jsonValue" } },
        "source": { "$ref": "#/$defs/sourcePointer" }
      }
    },
    "relation": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "kind", "from", "to", "directed", "attributes", "source"],
      "properties": {
        "id": { "$ref": "#/$defs/id" },
        "kind": { "$ref": "#/$defs/relationKind" },
        "from": { "$ref": "#/$defs/id" },
        "to": { "$ref": "#/$defs/id" },
        "directed": { "type": "boolean" },
        "attributes": { "type": "object", "additionalProperties": { "$ref": "#/$defs/jsonValue" } },
        "source": { "$ref": "#/$defs/sourcePointer" }
      }
    }
  }
}
