{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "schemas/dependency_wait_state.schema.json",
  "title": "dependency_wait_state.v1",
  "description": "task-2613 Track D — batch_dependency_classifier OUTPUT. Per-track classification of tracks that have NO terminal result yet: upstream gate 미충족으로 아직 dispatch되지 않은 정상 보류(NOT_STARTED_BY_DESIGN / WAITING_FOR_DEPENDENCY)를, 봇 미수신 사고(DISPATCH_NOT_RECEIVED)와 ENUM 차원에서 분리한다. 이 산출물은 Track A anu_v3.batch_hold_adjudicator 의 입력이다. INVARIANT: gate_satisfied=false 인 track 은 절대 DISPATCH_NOT_RECEIVED 로 분류될 수 없다(정상 보류 vs 미수신 사고는 별개 상태).",
  "type": "object",
  "required": [
    "schema",
    "classifier_version",
    "generated_at_basis",
    "batch_id",
    "tracks",
    "anti_conflation_invariant_held",
    "adjudicator_input_contract"
  ],
  "properties": {
    "schema": {"const": "dependency_wait_state.v1"},
    "classifier_version": {"type": "string", "minLength": 1},
    "generated_at_basis": {
      "const": "batch_context_scan",
      "description": "실 batch context(preflight decision + memory/events durable-success/dispatch-fired evidence) 스캔 결과. fixed-time/dead-man/fallback 진행 트리거 아님 — 순수 판정."
    },
    "batch_id": {"type": "string", "minLength": 1},
    "anti_conflation_invariant_held": {
      "const": true,
      "description": "gate 미충족 정상보류 ↔ DISPATCH_NOT_RECEIVED(봇 미수신 사고) ENUM 분리가 모든 track 에서 보존됨. false 면 산출 거부(ConflationError)."
    },
    "adjudicator_input_contract": {
      "type": "object",
      "required": ["consumer", "blocking_verdicts", "non_blocking_verdicts"],
      "properties": {
        "consumer": {"const": "anu_v3.batch_hold_adjudicator"},
        "blocking_verdicts": {
          "type": "array",
          "items": {"const": "DISPATCH_NOT_RECEIVED"},
          "description": "adjudicator 가 HOLD_CANDIDATE 로 받아야 하는 verdict (봇 미수신 사고만)."
        },
        "non_blocking_verdicts": {
          "type": "array",
          "items": {
            "enum": [
              "NOT_STARTED_BY_DESIGN",
              "WAITING_FOR_DEPENDENCY",
              "ELIGIBLE_NOT_YET_DISPATCHED",
              "TERMINAL_PRESENT"
            ]
          },
          "description": "정상 보류/정상 진행 — adjudicator 가 HOLD 로 올리면 안 되는 verdict."
        }
      },
      "additionalProperties": false
    },
    "tracks": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "track_id",
          "task_id",
          "verdict",
          "gate_kind",
          "gate_satisfied",
          "dispatch_fired",
          "dispatch_receipt",
          "terminal_result_present",
          "is_incident",
          "is_blocking_for_adjudicator",
          "reasons"
        ],
        "properties": {
          "track_id": {"type": "string", "minLength": 1},
          "task_id": {"type": "string", "minLength": 1},
          "verdict": {
            "type": "string",
            "enum": [
              "TERMINAL_PRESENT",
              "NOT_STARTED_BY_DESIGN",
              "WAITING_FOR_DEPENDENCY",
              "ELIGIBLE_NOT_YET_DISPATCHED",
              "DISPATCH_NOT_RECEIVED"
            ]
          },
          "gate_kind": {
            "type": "string",
            "enum": ["NONE", "EVENT_GATED", "AUTO_SEQUENCED", "DEPENDS_ON"]
          },
          "gate_satisfied": {"type": "boolean"},
          "declared_upstream": {"type": "array", "items": {"type": "string"}},
          "upstream_durable_success": {"type": "array", "items": {"type": "string"}},
          "upstream_unmet": {"type": "array", "items": {"type": "string"}},
          "dispatch_fired": {"type": "boolean"},
          "dispatch_receipt": {"type": "boolean"},
          "terminal_result_present": {"type": "boolean"},
          "is_incident": {
            "type": "boolean",
            "description": "true iff verdict==DISPATCH_NOT_RECEIVED (봇 미수신 사고). gate 미충족 정상보류는 항상 false."
          },
          "is_blocking_for_adjudicator": {"type": "boolean"},
          "reasons": {"type": "array", "items": {"type": "string"}}
        },
        "allOf": [
          {
            "description": "INVARIANT 1: DISPATCH_NOT_RECEIVED ⟹ gate_satisfied=true ∧ dispatch_fired=true ∧ dispatch_receipt=false",
            "if": {"properties": {"verdict": {"const": "DISPATCH_NOT_RECEIVED"}}},
            "then": {
              "properties": {
                "gate_satisfied": {"const": true},
                "dispatch_fired": {"const": true},
                "dispatch_receipt": {"const": false},
                "is_incident": {"const": true},
                "is_blocking_for_adjudicator": {"const": true}
              }
            }
          },
          {
            "description": "INVARIANT 2: gate_satisfied=false ⟹ verdict ∈ {NOT_STARTED_BY_DESIGN, WAITING_FOR_DEPENDENCY} (절대 DISPATCH_NOT_RECEIVED 아님)",
            "if": {"properties": {"gate_satisfied": {"const": false}}},
            "then": {
              "properties": {
                "verdict": {"enum": ["NOT_STARTED_BY_DESIGN", "WAITING_FOR_DEPENDENCY"]},
                "is_incident": {"const": false}
              }
            }
          },
          {
            "description": "INVARIANT 3: 정상 보류 4종은 incident/blocking 아님",
            "if": {
              "properties": {
                "verdict": {
                  "enum": [
                    "NOT_STARTED_BY_DESIGN",
                    "WAITING_FOR_DEPENDENCY",
                    "ELIGIBLE_NOT_YET_DISPATCHED",
                    "TERMINAL_PRESENT"
                  ]
                }
              }
            },
            "then": {
              "required": ["is_incident", "is_blocking_for_adjudicator"],
              "properties": {
                "is_incident": {"const": false},
                "is_blocking_for_adjudicator": {"const": false}
              }
            }
          },
          {
            "description": "INVARIANT 4 (forward-invariant 강화): verdict==DISPATCH_NOT_RECEIVED ⟹ is_incident==true ∧ is_blocking_for_adjudicator==true. then 절 required 명시로 top-level required 약화와 무관하게 독립 강제.",
            "if": {
              "required": ["verdict"],
              "properties": {"verdict": {"const": "DISPATCH_NOT_RECEIVED"}}
            },
            "then": {
              "required": ["is_incident", "is_blocking_for_adjudicator"],
              "properties": {
                "is_incident": {"const": true},
                "is_blocking_for_adjudicator": {"const": true}
              }
            }
          },
          {
            "description": "INVARIANT 5 (역방향 forward-invariant): is_incident==true ⟹ verdict==DISPATCH_NOT_RECEIVED. 정상보류가 incident 로 표기된 산출을 schema 가 reject.",
            "if": {
              "required": ["is_incident"],
              "properties": {"is_incident": {"const": true}}
            },
            "then": {
              "required": ["verdict"],
              "properties": {"verdict": {"const": "DISPATCH_NOT_RECEIVED"}}
            }
          }
        ],
        "additionalProperties": true
      }
    },
    "summary": {
      "type": "object",
      "properties": {
        "total": {"type": "integer", "minimum": 0},
        "by_verdict": {"type": "object"},
        "incident_count": {"type": "integer", "minimum": 0},
        "blocking_for_adjudicator_count": {"type": "integer", "minimum": 0}
      },
      "additionalProperties": true
    },
    "reasons": {"type": "array", "items": {"type": "string"}}
  },
  "additionalProperties": true
}
