{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://judgmentpack.org/schema/0.2.0-draft/conformance/evaluation/manifest.schema.json",
  "title": "Judgment Pack evaluation corpus manifest",
  "description": "The case carrier for the evaluation corpus. It describes cases; it defines no evaluator and executes nothing.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "$schema",
    "suiteVersion",
    "specVersion",
    "status",
    "label",
    "cases"
  ],
  "properties": {
    "$schema": {
      "const": "./manifest.schema.json"
    },
    "suiteVersion": {
      "const": "0.2.0-draft"
    },
    "specVersion": {
      "const": "0.2.0-draft"
    },
    "status": {
      "const": "research-preview"
    },
    "label": {
      "const": "seed"
    },
    "cases": {
      "type": "array",
      "minItems": 1,
      "uniqueItems": true,
      "items": {
        "$ref": "#/$defs/case"
      }
    }
  },
  "$defs": {
    "localId": {
      "type": "string",
      "pattern": "^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$"
    },
    "extensionName": {
      "type": "string",
      "pattern": "^(?!org\\.judgmentpack\\.)[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9-]*)+$"
    },
    "reason": {
      "enum": [
        "not-applicable",
        "missing-required-evidence",
        "unknown",
        "conflict",
        "no-match",
        "exception-escalation"
      ]
    },
    "reasonSet": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/reason"
      },
      "uniqueItems": true
    },
    "disposition": {
      "description": "The exact §8.3 disposition expected from a conforming evaluator, with both sets already sorted. Carrier validity does not imply a legal disposition: JSON Schema cannot express that handoff.triggeredBy is a subset of reasons, nor that triggeredBy names only a declared escalation trigger or exception-escalation, so those §8.3 invariants are checked by this repository's tests instead. Core §8.3 is the authority on which dispositions are legal.",
      "type": "object",
      "additionalProperties": false,
      "required": ["kind", "reasons", "handoff"],
      "properties": {
        "kind": {
          "enum": ["outcome", "not-applicable", "unresolved"]
        },
        "outcomeId": {
          "$ref": "#/$defs/localId"
        },
        "reasons": {
          "$ref": "#/$defs/reasonSet"
        },
        "handoff": {
          "type": "object",
          "additionalProperties": false,
          "required": ["state"],
          "properties": {
            "state": {
              "enum": ["none", "requested"]
            },
            "triggeredBy": {
              "allOf": [
                { "$ref": "#/$defs/reasonSet" },
                { "minItems": 1 }
              ]
            }
          },
          "allOf": [
            {
              "if": {
                "properties": { "state": { "const": "requested" } },
                "required": ["state"]
              },
              "then": { "required": ["triggeredBy"] },
              "else": { "not": { "required": ["triggeredBy"] } }
            }
          ]
        }
      },
      "allOf": [
        {
          "if": {
            "properties": { "kind": { "const": "outcome" } },
            "required": ["kind"]
          },
          "then": {
            "required": ["outcomeId"],
            "properties": { "reasons": { "maxItems": 0 } }
          },
          "else": {
            "not": { "required": ["outcomeId"] },
            "properties": { "reasons": { "minItems": 1 } }
          }
        },
        {
          "if": {
            "properties": { "kind": { "const": "not-applicable" } },
            "required": ["kind"]
          },
          "then": {
            "properties": { "reasons": { "const": ["not-applicable"] } }
          }
        }
      ]
    },
    "case": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "origin",
        "pack",
        "facts",
        "supportedExtensions",
        "focus",
        "specSection"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/localId"
        },
        "origin": {
          "type": "string",
          "minLength": 1,
          "description": "Where the case came from, so imported and constructed rows stay distinguishable."
        },
        "pack": {
          "type": "string",
          "pattern": "^packs/[a-z0-9][a-z0-9-]*\\.json$"
        },
        "facts": {
          "description": "The one JSON facts document of §8.2. Any JSON value is admissible, because §7.4's empty pointer selects the document root; every seed row happens to be object-rooted."
        },
        "evidenceAvailability": {
          "description": "The §8.2 tri-state input. An omitted member means the case supplies no evidence document at all, so every declared requirement is unknown.",
          "type": "object",
          "propertyNames": { "$ref": "#/$defs/localId" },
          "additionalProperties": {
            "enum": ["present", "absent", "unknown"]
          }
        },
        "supportedExtensions": {
          "type": "array",
          "items": { "$ref": "#/$defs/extensionName" },
          "uniqueItems": true
        },
        "expectedDisposition": {
          "$ref": "#/$defs/disposition"
        },
        "workBudget": {
          "description": "Optional. A positive integer of evaluation-work units, in the accounting units a future work-accounting model will define. Absent means the case sets no budget and the implementation's own documented §10 limit applies. No row of this suite version uses it (Core §3.4.1).",
          "type": "integer",
          "minimum": 1
        },
        "expectedErrorPhase": {
          "description": "Optional. Which phase an expected error class was reached in: preflight, while admitting the inputs (§8.2), or evaluation, while evaluating an admitted input (§8). It accompanies expectedErrorClass only, never an expected disposition. No row of this suite version uses it (Core §3.4.1).",
          "enum": ["preflight", "evaluation"]
        },
        "expectedErrorClass": {
          "description": "The §8.4 error class a conforming evaluator must report instead of a disposition: one of the four Core classes, or an implementation-defined class in the reverse-domain form §8.4 requires of one.",
          "type": "string",
          "anyOf": [
            {
              "enum": [
                "pack-not-conformant",
                "unsupported-required-extension",
                "malformed-input",
                "resource-exhaustion"
              ]
            },
            {
              "pattern": "^(?!org\\.judgmentpack\\.)[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9-]*)+$"
            }
          ]
        },
        "focus": {
          "type": "string",
          "minLength": 1
        },
        "specSection": {
          "type": "string",
          "pattern": "^§"
        }
      },
      "oneOf": [
        { "required": ["expectedDisposition"] },
        { "required": ["expectedErrorClass"] }
      ],
      "dependentRequired": {
        "expectedErrorPhase": ["expectedErrorClass"]
      }
    }
  }
}
