{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "recoil/architecture/topology/topology.schema.json",
  "title": "Recoil engine topology \u2014 authored node file (*.topo.yaml)",
  "description": "Schema for an authored per-subsystem topology file. Each file contributes nodes/edges to the merged graph. Capability nodes are FK references into ssot_manifest.yaml (state lives THERE, not copied). See consultations/recoil/engine-topology-ssot-2026-06-19/SYNTHESIS.md.",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "subsystem": {
      "type": "string",
      "description": "Human label for this file's subsystem."
    },
    "out_of_scope_capabilities": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Manifest capability ids intentionally NOT mapped in the engine topology (editor/API, not the visual engine). Satisfies manifest-parity without forcing a node."
    },
    "capabilities": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/capability"
      }
    },
    "entrypoints": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/entrypoint"
      }
    },
    "phases": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/phase"
      }
    },
    "routes": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/route"
      }
    },
    "loops": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/loop"
      }
    },
    "flags": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/flag"
      }
    },
    "artifacts": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/artifact"
      }
    },
    "divergences": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/divergence"
      }
    },
    "symbols": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/symbol"
      }
    },
    "schema": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/schema_model"
      }
    }
  },
  "$defs": {
    "reduced_tier": {
      "enum": [
        "always",
        "auto",
        "never"
      ],
      "description": "always = pin into the reduced in-memory tier; auto = projection rule decides; never = full-tier only."
    },
    "risk_level": {
      "enum": [
        "low",
        "medium",
        "high",
        "critical"
      ]
    },
    "symref": {
      "type": "string",
      "pattern": "^[^:]+\\.py(::[A-Za-z_][A-Za-z0-9_.]*)?$",
      "description": "A 'path/to/file.py' or 'path/to/file.py::symbol' reference; file must exist on disk (CI-checked)."
    },
    "capability": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id"
      ],
      "properties": {
        "id": {
          "type": "string",
          "description": "FK into ssot_manifest.yaml capabilities \u2014 must exist there. No state copied here."
        },
        "reduced_tier": {
          "$ref": "#/$defs/reduced_tier"
        },
        "risk_level": {
          "$ref": "#/$defs/risk_level"
        }
      }
    },
    "entrypoint": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "file",
        "invoke",
        "kind"
      ],
      "properties": {
        "id": {
          "type": "string"
        },
        "file": {
          "$ref": "#/$defs/symref"
        },
        "symbol": {
          "type": "string"
        },
        "invoke": {
          "type": "string",
          "description": "Exact command/import to invoke it."
        },
        "kind": {
          "enum": [
            "cli",
            "module",
            "hook",
            "tool",
            "daemon"
          ]
        },
        "summary": {
          "type": "string"
        },
        "capabilities": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "produces": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "reduced_tier": {
          "$ref": "#/$defs/reduced_tier"
        },
        "risk_level": {
          "$ref": "#/$defs/risk_level"
        }
      }
    },
    "phase": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "summary"
      ],
      "properties": {
        "id": {
          "type": "string"
        },
        "summary": {
          "type": "string"
        },
        "entrypoints": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "produces": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "next": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "reduced_tier": {
          "$ref": "#/$defs/reduced_tier"
        },
        "risk_level": {
          "$ref": "#/$defs/risk_level"
        }
      }
    },
    "route": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "capability",
        "surface",
        "resolves_via",
        "ref_kind",
        "entry"
      ],
      "properties": {
        "id": {
          "type": "string"
        },
        "capability": {
          "type": "string",
          "description": "FK to a capability id."
        },
        "surface": {
          "type": "string",
          "description": "e.g. board, video, r2v, previz."
        },
        "entry": {
          "$ref": "#/$defs/symref"
        },
        "resolves_via": {
          "$ref": "#/$defs/symref"
        },
        "ref_kind": {
          "type": "string",
          "description": "e.g. plate, composite_sheet, individual, turn_view."
        },
        "gated_by": {
          "type": [
            "string",
            "null"
          ],
          "description": "flag id that activates this route, or null."
        },
        "fallback_route": {
          "type": [
            "string",
            "null"
          ]
        },
        "reduced_tier": {
          "$ref": "#/$defs/reduced_tier"
        },
        "risk_level": {
          "$ref": "#/$defs/risk_level"
        }
      }
    },
    "loop": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "kind",
        "trigger",
        "driver",
        "exit"
      ],
      "properties": {
        "id": {
          "type": "string"
        },
        "kind": {
          "enum": [
            "retry",
            "reroll",
            "strategy",
            "convergence",
            "poll"
          ]
        },
        "capability": {
          "type": "string"
        },
        "trigger": {
          "type": "string"
        },
        "driver": {
          "$ref": "#/$defs/symref"
        },
        "bound": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "max": {},
            "source": {
              "type": "string"
            }
          }
        },
        "exit": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "minItems": 1
        },
        "retries_into": {
          "type": "string"
        },
        "reads_artifact": {
          "type": "string"
        },
        "reduced_tier": {
          "$ref": "#/$defs/reduced_tier"
        },
        "risk_level": {
          "$ref": "#/$defs/risk_level"
        },
        "reroll_into": {
          "type": "string",
          "description": "route/loop/entrypoint id this loop re-runs (alt to retries_into)"
        }
      }
    },
    "flag": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "defined"
      ],
      "properties": {
        "id": {
          "type": "string"
        },
        "defined": {
          "$ref": "#/$defs/symref"
        },
        "default": {},
        "forks_capability": {
          "type": "string",
          "description": "capability id this flag forks; presence promotes the flag into the reduced tier."
        },
        "gates_routes": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "summary": {
          "type": "string"
        },
        "reduced_tier": {
          "$ref": "#/$defs/reduced_tier"
        },
        "risk_level": {
          "$ref": "#/$defs/risk_level"
        }
      }
    },
    "artifact": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "path"
      ],
      "properties": {
        "id": {
          "type": "string"
        },
        "path": {
          "type": "string",
          "description": "On-disk path or glob (may contain placeholders)."
        },
        "written_by": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "read_by": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "schema": {
          "type": "string"
        },
        "reduced_tier": {
          "$ref": "#/$defs/reduced_tier"
        },
        "risk_level": {
          "$ref": "#/$defs/risk_level"
        }
      }
    },
    "divergence": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "capability",
        "forks",
        "invariant",
        "risk"
      ],
      "properties": {
        "id": {
          "type": "string"
        },
        "capability": {
          "type": "string",
          "description": "FK to the forked capability id."
        },
        "forks": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "minItems": 2,
          "description": "route ids that fork."
        },
        "on_flag": {
          "type": [
            "string",
            "null"
          ]
        },
        "invariant": {
          "type": "string",
          "description": "A CI-assertable rule, e.g. 'board_ref_path MUST NOT reach the composite-sheet path'."
        },
        "risk": {
          "type": "string"
        },
        "reduced_tier": {
          "$ref": "#/$defs/reduced_tier",
          "default": "always"
        },
        "risk_level": {
          "$ref": "#/$defs/risk_level"
        },
        "allow_same": {
          "type": "boolean",
          "description": "true when route A and B legitimately render identically (with a reason in risk/invariant)"
        }
      }
    },
    "symbol": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "file",
        "symbol",
        "role"
      ],
      "properties": {
        "id": {
          "type": "string"
        },
        "file": {
          "$ref": "#/$defs/symref"
        },
        "symbol": {
          "type": "string"
        },
        "role": {
          "type": "string",
          "description": "Why this junction matters."
        },
        "reduced_tier": {
          "$ref": "#/$defs/reduced_tier"
        },
        "risk_level": {
          "$ref": "#/$defs/risk_level"
        }
      }
    },
    "schema_model": {
      "type": "object",
      "additionalProperties": false,
      "description": "Bible/ref data-model topology node. Freshness model: fields[].name is the authoritative AST-checked Class.<name> anchor; fields[].type and fields[].meaning are descriptive human hints and are not validated against live annotations.",
      "required": [
        "id",
        "model",
        "file",
        "reduced_tier",
        "fields"
      ],
      "properties": {
        "id": {
          "type": "string"
        },
        "model": {
          "type": "string",
          "description": "Python model class name."
        },
        "file": {
          "type": "string",
          "pattern": "^[^:]+\\.py::[A-Za-z_][A-Za-z0-9_.]*$",
          "description": "path::Class symref for the model class."
        },
        "reduced_tier": {
          "$ref": "#/$defs/reduced_tier"
        },
        "fields": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "name",
              "type",
              "meaning",
              "semantic",
              "dup_tier"
            ],
            "properties": {
              "name": {
                "type": "string",
                "description": "Live Python attribute name; Phase 2 checks Class.<name> exists."
              },
              "type": {
                "type": "string",
                "description": "Descriptive annotation hint; not AST-validated."
              },
              "meaning": {
                "type": "string",
                "description": "Human-readable purpose for duplicate detection."
              },
              "semantic": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Semantic duplicate cluster tag, or null when the field is not in a cluster."
              },
              "dup_tier": {
                "enum": [
                  "always",
                  "never"
                ],
                "description": "always = render in reduced duplicate-prone schema block; never = full-map only."
              }
            }
          }
        }
      }
    }
  }
}
