{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "BatchSummary",
  "description": "Structured summary returned by batch sub-agent after completing a batch. Used by orchestrator for cross-series verification.",
  "type": "object",
  "required": ["batch", "episodes", "batch_summary", "timestamp"],
  "properties": {
    "batch": {
      "type": "integer",
      "minimum": 1,
      "maximum": 12,
      "description": "Batch number (1-12)"
    },
    "timestamp": {
      "type": "string",
      "format": "date-time",
      "description": "When batch was completed"
    },
    "episodes": {
      "type": "array",
      "minItems": 5,
      "maxItems": 5,
      "description": "Summary data for each episode in the batch",
      "items": {
        "type": "object",
        "required": ["number", "threads", "emotional_beat", "hook_type", "cliffhanger_type", "word_count", "dialogue_percent", "exchanges"],
        "properties": {
          "number": {
            "type": "integer",
            "description": "Episode number"
          },
          "title": {
            "type": "string",
            "description": "Episode title"
          },
          "threads": {
            "type": "object",
            "required": ["planted", "advanced", "paid_off"],
            "properties": {
              "planted": {
                "type": "array",
                "items": {"type": "string"},
                "description": "Thread IDs planted in this episode"
              },
              "advanced": {
                "type": "array",
                "items": {"type": "string"},
                "description": "Thread IDs advanced in this episode"
              },
              "paid_off": {
                "type": "array",
                "items": {"type": "string"},
                "description": "Thread IDs paid off in this episode"
              }
            }
          },
          "emotional_beat": {
            "type": ["string", "null"],
            "description": "Emotional beat hit in this episode (e.g., FIRST_CRACK) or null"
          },
          "hook_type": {
            "type": "string",
            "enum": ["silent", "dialogue"],
            "description": "Type of hook used"
          },
          "cliffhanger_type": {
            "type": "string",
            "enum": ["mid-action", "aftermath"],
            "description": "Type of cliffhanger used"
          },
          "word_count": {
            "type": "integer",
            "description": "Total word count"
          },
          "dialogue_percent": {
            "type": "number",
            "description": "Dialogue percentage"
          },
          "exchanges": {
            "type": "integer",
            "description": "Number of dialogue exchanges"
          },
          "key_moment": {
            "type": "string",
            "description": "Brief description of THE MOMENT that landed"
          },
          "cliffhanger_image": {
            "type": "string",
            "description": "Brief description of the cliffhanger visual"
          }
        }
      }
    },
    "batch_summary": {
      "type": "object",
      "required": ["threads_planted_this_batch", "threads_advanced_this_batch", "threads_paid_off_this_batch", "pattern_distribution", "validation_passed"],
      "properties": {
        "threads_planted_this_batch": {
          "type": "array",
          "items": {"type": "string"},
          "description": "All threads planted in this batch"
        },
        "threads_advanced_this_batch": {
          "type": "array",
          "items": {"type": "string"},
          "description": "All threads advanced in this batch"
        },
        "threads_paid_off_this_batch": {
          "type": "array",
          "items": {"type": "string"},
          "description": "All threads paid off in this batch"
        },
        "emotional_beats_hit_this_batch": {
          "type": "array",
          "items": {"type": "string"},
          "description": "Emotional beats hit in this batch"
        },
        "pattern_distribution": {
          "type": "object",
          "required": ["hooks", "cliffhangers"],
          "properties": {
            "hooks": {
              "type": "object",
              "properties": {
                "silent": {"type": "integer"},
                "dialogue": {"type": "integer"}
              }
            },
            "cliffhangers": {
              "type": "object",
              "properties": {
                "mid_action": {"type": "integer"},
                "aftermath": {"type": "integer"}
              }
            }
          }
        },
        "validation_passed": {
          "type": "boolean",
          "description": "Whether batch passed all validation gates"
        },
        "issues_flagged": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "episode": {"type": "integer"},
              "issue_type": {"type": "string"},
              "description": {"type": "string"},
              "severity": {"type": "string", "enum": ["warning", "error"]}
            }
          },
          "description": "Any issues flagged during batch generation"
        }
      }
    },
    "continuity_notes": {
      "type": "object",
      "description": "Notes for the next batch to maintain continuity",
      "properties": {
        "last_location": {
          "type": "string",
          "description": "Where the protagonist is at batch end"
        },
        "character_states": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          },
          "description": "Key character states at batch end"
        },
        "open_tension": {
          "type": "string",
          "description": "The unresolved tension from the cliffhanger"
        },
        "next_batch_setup": {
          "type": "string",
          "description": "Brief setup notes for next batch"
        }
      }
    }
  }
}
