{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://maheshtata.com/wazuh/wazuh-ai-triage/verdict.schema.json",
  "title": "Wazuh finding triage verdict",
  "description": "The only shape a triage model is allowed to return. Validate every response against this schema before any policy is applied. A response that fails validation is discarded and the finding goes to a human unchanged.",
  "type": "object",
  "additionalProperties": false,
  "required": ["finding_ref", "verdict", "confidence", "rationale", "evidence", "proposed_action"],
  "properties": {
    "finding_ref": {
      "type": "object",
      "description": "Echoed back from the context envelope so a verdict can never be applied to the wrong finding. The platform compares these values with what it sent and rejects a mismatch.",
      "additionalProperties": false,
      "required": ["doc_id", "index"],
      "properties": {
        "doc_id": { "type": "string", "minLength": 1 },
        "index": { "type": "string", "minLength": 1 }
      }
    },
    "verdict": {
      "type": "string",
      "description": "insufficient_context is a first-class answer, not a failure. Without it a model handed a thin envelope will produce a confident guess.",
      "enum": ["true_positive", "likely_benign", "needs_human", "insufficient_context"]
    },
    "confidence": {
      "type": "string",
      "enum": ["low", "medium", "high"]
    },
    "rationale": {
      "type": "string",
      "description": "Two or three sentences in plain language. No markdown, no bullet lists, no restating the rule title.",
      "minLength": 20,
      "maxLength": 800
    },
    "evidence": {
      "type": "array",
      "description": "Every item names the envelope field or lookup it came from. A verdict with an empty evidence array is rejected by the platform regardless of how confident the rationale sounds.",
      "minItems": 1,
      "maxItems": 10,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["source", "value", "supports"],
        "properties": {
          "source": {
            "type": "string",
            "description": "The envelope path this came from, for example finding.wazuh.rule.title, asset.exposure, history.count_24h. Must exist in the envelope that was sent.",
            "minLength": 1
          },
          "value": {
            "type": "string",
            "description": "The value as it appeared, quoted, not paraphrased.",
            "minLength": 1,
            "maxLength": 500
          },
          "supports": {
            "type": "string",
            "description": "Which way this cuts.",
            "enum": ["verdict", "against_verdict"]
          }
        }
      }
    },
    "proposed_action": {
      "type": "string",
      "description": "A proposal only. The platform's action handler checks it against the allowed list for this severity band and ignores anything the policy does not permit. Nothing in this enum touches an endpoint.",
      "enum": [
        "enrich_only",
        "downgrade_to_review_queue",
        "escalate_to_analyst",
        "group_with_related",
        "no_action"
      ]
    },
    "unanswered": {
      "type": "array",
      "description": "What the model could not determine, and what would settle it. Cluster these across findings: they map directly to gaps in your context pipeline and in your rule documentation.",
      "maxItems": 5,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["question", "would_resolve_with"],
        "properties": {
          "question": { "type": "string", "minLength": 5, "maxLength": 300 },
          "would_resolve_with": { "type": "string", "minLength": 5, "maxLength": 300 }
        }
      }
    },
    "escalation_question": {
      "type": "string",
      "description": "Required in practice when proposed_action is escalate_to_analyst. One specific question for the human, not a summary of the finding.",
      "maxLength": 400
    },
    "related_findings": {
      "type": "array",
      "description": "Only populated when proposed_action is group_with_related. Document IDs must come from the history section of the envelope.",
      "maxItems": 25,
      "items": { "type": "string", "minLength": 1 }
    }
  }
}
