{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://demonology.local/demons.schema.json",
  "title": "Demonology Entity Dataset",
  "description": "Machine-readable roster of demonic entities cross-referenced across the source documents in md/demonology/. Each record is a fact-cache derived from whole-file reads of the sources, so AI agents can query attributes without re-reading the corpus. Scope: entities attested in 2 or more sources.",
  "type": "object",
  "required": ["meta", "sources", "demons"],
  "properties": {
    "meta": {
      "type": "object",
      "required": ["topic", "scope", "rank_ladder", "generated_from"],
      "properties": {
        "topic": { "type": "string" },
        "scope": {
          "type": "string",
          "description": "Inclusion rule for this dataset, e.g. 'entities attested in 2+ sources'."
        },
        "rank_ladder": {
          "type": "array",
          "description": "Classical grimoire ranks, highest authority first.",
          "items": { "type": "string" }
        },
        "generated_from": {
          "type": "array",
          "description": "Sibling files this data was derived from / kept in sync with.",
          "items": { "type": "string" }
        },
        "caveat": { "type": "string" }
      }
    },
    "sources": {
      "type": "object",
      "description": "Map of source code -> human-readable source description. Codes are used in each demon's 'sources' array.",
      "patternProperties": {
        "^[A-Z]{2}$": { "type": "string" }
      },
      "additionalProperties": false
    },
    "demons": {
      "type": "array",
      "items": { "$ref": "#/$defs/demon" }
    }
  },
  "$defs": {
    "sourceCode": {
      "type": "string",
      "enum": ["FG", "DM", "PU", "SP", "DJ", "EN"]
    },
    "demon": {
      "type": "object",
      "required": ["id", "name", "type", "tier", "domain", "signs", "origins", "sources", "source_count", "citations"],
      "additionalProperties": false,
      "properties": {
        "id": {
          "type": "string",
          "pattern": "^[a-z0-9-]+$",
          "description": "Stable kebab-case identifier; used as the target of cross_refs."
        },
        "name": { "type": "string", "description": "Primary / most common name." },
        "aliases": {
          "type": "array",
          "items": { "type": "string" }
        },
        "type": {
          "type": "string",
          "enum": ["individual", "collective", "class", "title"],
          "description": "individual = a single named entity; collective = a named group acting as one (e.g. Legion); class = a category of spirits (e.g. Shedim); title = an honorific/role applied to others."
        },
        "tier": {
          "type": "string",
          "enum": ["supreme-prince", "directional-king", "goetia-officer", "watcher", "other-recurring"],
          "description": "Which sub-hierarchy this entity belongs to in the synthesis."
        },
        "rank": {
          "type": ["string", "null"],
          "description": "Grimoire rank as stated (King, Duke, Prince, Marquis, Earl, President, Knight, Emperor, etc.). Null if none stated."
        },
        "legions": {
          "type": ["integer", "null"],
          "description": "Number of legions commanded, if stated."
        },
        "goetia_number": {
          "type": ["integer", "null"],
          "minimum": 1,
          "maximum": 72,
          "description": "Position among the 72 Spirits of the Ars Goetia, if applicable."
        },
        "deadly_sin": {
          "type": ["string", "null"],
          "description": "Associated deadly sin, for the seven Princes of Hell scheme."
        },
        "domain": {
          "type": "array",
          "description": "Spheres of influence / what it governs.",
          "items": { "type": "string" }
        },
        "signs": {
          "type": "array",
          "description": "Identifying marks: apparition form, associations, sigils, manner of manifesting.",
          "items": { "type": "string" }
        },
        "origins": {
          "type": "string",
          "description": "Etymology, backstory, derivation from earlier deities/traditions."
        },
        "sources": {
          "type": "array",
          "minItems": 2,
          "uniqueItems": true,
          "items": { "$ref": "#/$defs/sourceCode" },
          "description": "Source codes that name this entity. Scope rule requires length >= 2."
        },
        "source_count": {
          "type": "integer",
          "minimum": 2,
          "description": "Number of distinct sources; must equal sources.length."
        },
        "citations": {
          "type": "object",
          "description": "Map of source code -> location string within that source file.",
          "patternProperties": {
            "^[A-Z]{2}$": { "type": "string" }
          },
          "additionalProperties": false
        },
        "cross_refs": {
          "type": "array",
          "description": "ids of entities this one is identified/conflated with, or commands/serves.",
          "items": { "type": "string", "pattern": "^[a-z0-9-]+$" }
        },
        "notes": {
          "type": ["string", "null"],
          "description": "Uncertainty flags, conflation warnings, or scope caveats."
        }
      }
    }
  }
}
