{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://cognificance.com/docs/schemas/framework.schema.json",
  "title": "Cognificance framework",
  "description": "One framework (standards, an assessment blueprint or a competency vocabulary) in the Cognificance catalog format, as the import page accepts it. The import also refuses what a schema cannot express: an item code, item identifier or level code listed twice, a parent the file does not list or a parent loop, gradeLow above gradeHigh, levels whose minPercent does not rise, an association from an item the file does not list, to an item the catalog does not hold, to itself or listed twice, a seed framework code, and text with bidirectional override or isolate characters. Every string is trimmed and normalized (Unicode NFC, control characters as spaces) before these rules apply. URLs are stored as text and never fetched.",
  "type": "object",
  "additionalProperties": false,
  "required": ["CFDocument", "CFItems"],
  "properties": {
    "CFDocument": { "$ref": "#/$defs/document" },
    "CFItems": {
      "type": "array",
      "minItems": 1,
      "maxItems": 10000,
      "items": { "$ref": "#/$defs/item" }
    },
    "CFAssociations": {
      "type": ["array", "null"],
      "maxItems": 30000,
      "items": { "$ref": "#/$defs/association" }
    },
    "levels": {
      "type": ["array", "null"],
      "maxItems": 100,
      "items": { "$ref": "#/$defs/level" }
    }
  },
  "$defs": {
    "text": {
      "description": "A required text: something other than white space.",
      "type": "string",
      "pattern": "\\S"
    },
    "httpsUrl": {
      "description": "An absolute https URL with an ASCII host (no percent-escapes) and valid percent-escapes elsewhere, shown as a link and never fetched. The server's URL check is authoritative; this pattern approximates it.",
      "type": ["string", "null"],
      "pattern": "^https://(([A-Za-z0-9\\-._~!$&'()*+,;=]|%[0-9A-Fa-f]{2}|:)+@)?(\\[[0-9A-Fa-f:.]+\\]|[A-Za-z0-9\\-._~!$&'()*+,;=]+)(:[0-9]*)?([/?#]([A-Za-z0-9\\-._~!$&'()*+,;=:@/?#\\[\\]]|%[0-9A-Fa-f]{2})*)?$",
      "maxLength": 500
    },
    "document": {
      "type": "object",
      "additionalProperties": false,
      "required": ["code", "title", "frameworkKind", "version", "jurisdiction", "publisher", "license", "attribution", "isEnabled"],
      "properties": {
        "identifier": { "description": "The CASE CFDocument identifier, when the framework is published as CASE.", "type": ["string", "null"], "maxLength": 100 },
        "code": { "description": "The framework code: the code typed on the import page.", "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9-]{0,31}$" },
        "title": { "$ref": "#/$defs/text", "maxLength": 200 },
        "frameworkKind": { "enum": ["Standards", "Assessment", "Competency"] },
        "version": { "$ref": "#/$defs/text", "maxLength": 50 },
        "jurisdiction": { "$ref": "#/$defs/text", "maxLength": 50 },
        "publisher": { "$ref": "#/$defs/text", "maxLength": 200 },
        "officialSourceURL": { "$ref": "#/$defs/httpsUrl" },
        "license": { "$ref": "#/$defs/text", "maxLength": 200 },
        "attribution": { "$ref": "#/$defs/text", "maxLength": 1000 },
        "coverageNote": { "type": ["string", "null"], "maxLength": 1000 },
        "notice": { "type": ["string", "null"], "maxLength": 1000 },
        "isEnabled": { "type": "boolean" }
      }
    },
    "item": {
      "type": "object",
      "additionalProperties": false,
      "required": ["humanCodingScheme", "CFItemType", "shortLabel"],
      "properties": {
        "identifier": { "description": "The CASE CFItem identifier, when there is one.", "type": ["string", "null"], "maxLength": 100 },
        "humanCodingScheme": { "$ref": "#/$defs/code", "maxLength": 100 },
        "thinkingDemand": { "description": "Cognificance thinking demand: 1 recall, 2 apply, 3 analyze, 4 evaluate/create; null means unrated.", "type": ["integer", "null"], "minimum": 1, "maximum": 4 },
        "CFItemType": { "description": "What the item is: Standard, Anchor, Practice, CrosscuttingConcept, Element, Claim, Target, Domain, PerformanceExpectation, Skill ...", "$ref": "#/$defs/text", "maxLength": 50 },
        "shortLabel": { "description": "A short paraphrase; never the official text where the licence requires a paraphrase.", "$ref": "#/$defs/text", "maxLength": 200 },
        "parent": { "description": "The humanCodingScheme of the item this one sits under, in this file.", "type": ["string", "null"] },
        "gradeLow": { "description": "Kindergarten is 0.", "type": ["integer", "null"], "minimum": 0, "maximum": 2147483647 },
        "gradeHigh": { "type": ["integer", "null"], "minimum": 0, "maximum": 2147483647 },
        "subjectHint": { "oneOf": [{ "$ref": "#/$defs/subject" }, { "type": "null" }] },
        "sourceUrl": { "$ref": "#/$defs/httpsUrl" }
      }
    },
    "association": {
      "type": "object",
      "additionalProperties": false,
      "required": ["originNode", "destinationNode", "associationType"],
      "properties": {
        "originNode": { "$ref": "#/$defs/node" },
        "destinationNode": { "$ref": "#/$defs/node" },
        "associationType": { "enum": ["IsChildOf", "ExactMatchOf", "IsPartOf", "IsRelatedTo", "Assesses", "Measures", "Demands"] },
        "rationale": { "type": ["string", "null"], "maxLength": 200 },
        "subjects": {
          "description": "The subjects the link fits; leave it out to fit every subject.",
          "type": ["array", "null"],
          "minItems": 1,
          "uniqueItems": true,
          "items": { "$ref": "#/$defs/subject" }
        }
      }
    },
    "node": {
      "description": "An item by code. framework is left out (or null) for an item of this file; an origin is always an item of this file.",
      "type": "object",
      "additionalProperties": false,
      "required": ["code"],
      "properties": {
        "framework": { "type": ["string", "null"] },
        "code": { "type": "string" }
      }
    },
    "level": {
      "type": "object",
      "additionalProperties": false,
      "required": ["code", "label"],
      "properties": {
        "code": { "$ref": "#/$defs/code", "maxLength": 50 },
        "label": { "$ref": "#/$defs/text", "maxLength": 100 },
        "minPercent": { "type": ["number", "null"], "minimum": 0, "maximum": 100 }
      }
    },
    "code": {
      "description": "ASCII letters, digits and . - _ : ( ) / +, starting with a letter or digit.",
      "type": "string",
      "pattern": "^[A-Za-z0-9][A-Za-z0-9._:()/+-]*$"
    },
    "subject": {
      "enum": ["EverydayReasoning", "PhilosophyEthics", "DebateCivics", "AiTechnology", "Science", "History", "Mathematics", "Economics", "LiteratureLanguage"]
    }
  }
}
