{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://theamateur.co.uk/schemas/dpl/dpl.summary-1.schema.json",
  "title": "DPL plan summary (dpl.summary/1)",
  "description": "What `dpl summary <plan>` writes: a plan in about 300 words, assembled from the plan itself with no model: title, planned runtime, counts, thesis and journey, one line per sequence and scene (as many as fit), the open findings by severity with the first five, the missing-detail counts, the plan hash and the rules version. Every member listed here is always written, or left out when null; nothing else appears.",
  "$comment": "`dpl summary --format markdown` renders the same facts as the seed of a continuation brief; its words are counted by PlanSummary.WordCount and kept near PlanSummary.WordBudget (300). `scene_ids` names every scene so a scene the outline left out can be fetched with `dpl slice --scene`.",
  "type": "object",
  "properties": {
    "format": {
      "type": "string",
      "const": "dpl.summary/1"
    },
    "work_id": {
      "type": "string"
    },
    "title": {
      "type": "string"
    },
    "plan_hash": {
      "description": "SHA-256 of the plan in its standard layout (the same revision hash dpl readiness and dpl missing report).",
      "type": "string",
      "pattern": "^[0-9a-f]{64}$"
    },
    "rules_version": {
      "type": "string"
    },
    "runtime_ms": {
      "description": "Where the last scene ends, in milliseconds: the length the plan actually plans.",
      "type": "integer",
      "minimum": 0
    },
    "target_runtime_ms": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 1
    },
    "counts": {
      "$ref": "#/$defs/SummaryCounts"
    },
    "profile": {
      "description": "The work's profile when it is not an ordinary film: short for a short-form plan (kit, people, light and a shoot day).",
      "type": [
        "string",
        "null"
      ]
    },
    "thesis": {
      "type": [
        "string",
        "null"
      ]
    },
    "journey": {
      "description": "The film's journey in a line (axis, the stages, where it ends and why), when the plan declares one.",
      "type": [
        "string",
        "null"
      ]
    },
    "slice_of": {
      "anyOf": [
        {
          "$ref": "#/$defs/SummarySlice"
        },
        {
          "type": "null"
        }
      ]
    },
    "sequences": {
      "description": "The sequences that fit in the word budget, in plan order.",
      "type": "array",
      "items": {
        "$ref": "#/$defs/SummarySequence"
      }
    },
    "sequences_omitted": {
      "type": "integer",
      "minimum": 0
    },
    "scenes": {
      "description": "The scenes that fit in the word budget, in plan order. After them come ScenesOmitted more; SceneIds names every scene, and dpl slice --scene fetches one.",
      "type": "array",
      "items": {
        "$ref": "#/$defs/SummaryScene"
      }
    },
    "scenes_omitted": {
      "type": "integer",
      "minimum": 0
    },
    "scene_ids": {
      "description": "Every scene id, in plan order, so a scene the outline left out can be asked for.",
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "findings": {
      "description": "Open findings by severity and the first five in the readiness order; absent when no findings document was given.",
      "anyOf": [
        {
          "$ref": "#/$defs/SummaryFindings"
        },
        {
          "type": "null"
        }
      ]
    },
    "missing": {
      "description": "What dpl missing would ask the human.",
      "$ref": "#/$defs/SummaryMissing"
    }
  },
  "required": [
    "format",
    "work_id",
    "title",
    "plan_hash",
    "rules_version",
    "runtime_ms",
    "counts",
    "sequences",
    "sequences_omitted",
    "scenes",
    "scenes_omitted",
    "scene_ids",
    "missing"
  ],
  "additionalProperties": false,
  "$defs": {
    "FindingSeverity": {
      "type": "string",
      "enum": [
        "blocker",
        "major",
        "minor",
        "note"
      ]
    },
    "SummaryCounts": {
      "type": "object",
      "properties": {
        "scenes": {
          "type": "integer",
          "minimum": 0
        },
        "shots": {
          "type": "integer",
          "minimum": 0
        },
        "characters": {
          "type": "integer",
          "minimum": 0
        },
        "locations": {
          "type": "integer",
          "minimum": 0
        },
        "props": {
          "type": "integer",
          "minimum": 0
        },
        "sequences": {
          "type": "integer",
          "minimum": 0
        }
      },
      "required": [
        "scenes",
        "shots",
        "characters",
        "locations",
        "props",
        "sequences"
      ],
      "additionalProperties": false
    },
    "SummaryFinding": {
      "type": "object",
      "description": "One of the first findings, with the message cut short. The finding's own document has the rest.",
      "properties": {
        "id": {
          "type": "string",
          "pattern": "^f-[0-9a-f]{12}$"
        },
        "code": {
          "type": "string",
          "pattern": "^(DPL|RDY|REC)-[A-Z0-9-]+$"
        },
        "severity": {
          "$ref": "#/$defs/FindingSeverity"
        },
        "scene": {
          "type": [
            "string",
            "null"
          ]
        },
        "shot": {
          "type": [
            "string",
            "null"
          ]
        },
        "message": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "code",
        "severity",
        "message"
      ],
      "additionalProperties": false
    },
    "SummaryFindings": {
      "type": "object",
      "description": "What the findings document handed to the summary says. ForThisPlan is false when its plan hash is not this plan's: the findings are from another revision.",
      "properties": {
        "for_this_plan": {
          "type": "boolean"
        },
        "findings_plan_hash": {
          "type": "string",
          "pattern": "^[0-9a-f]{64}$"
        },
        "open": {
          "$ref": "#/$defs/SummaryOpen"
        },
        "closed": {
          "type": "integer",
          "minimum": 0
        },
        "top": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/SummaryFinding"
          }
        }
      },
      "required": [
        "for_this_plan",
        "findings_plan_hash",
        "open",
        "closed",
        "top"
      ],
      "additionalProperties": false
    },
    "SummaryMissing": {
      "type": "object",
      "properties": {
        "questions": {
          "type": "integer",
          "minimum": 0
        },
        "blocking_assessment": {
          "type": "integer",
          "minimum": 0
        },
        "improves_assessment": {
          "type": "integer",
          "minimum": 0
        }
      },
      "required": [
        "questions",
        "blocking_assessment",
        "improves_assessment"
      ],
      "additionalProperties": false
    },
    "SummaryOpen": {
      "type": "object",
      "properties": {
        "blocker": {
          "type": "integer",
          "minimum": 0
        },
        "major": {
          "type": "integer",
          "minimum": 0
        },
        "minor": {
          "type": "integer",
          "minimum": 0
        },
        "note": {
          "type": "integer",
          "minimum": 0
        }
      },
      "required": [
        "blocker",
        "major",
        "minor",
        "note"
      ],
      "additionalProperties": false
    },
    "SummaryScene": {
      "type": "object",
      "description": "A scene in one line: its purpose and its dramatic functions.",
      "properties": {
        "id": {
          "type": "string"
        },
        "sequence": {
          "type": [
            "string",
            "null"
          ]
        },
        "shots": {
          "type": "integer"
        },
        "start_ms": {
          "type": "integer"
        },
        "end_ms": {
          "type": "integer"
        },
        "line": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "shots",
        "start_ms",
        "end_ms",
        "line"
      ],
      "additionalProperties": false
    },
    "SummarySequence": {
      "type": "object",
      "description": "A sequence in one line; its scenes are the ones from FirstScene to LastScene (SceneCount of them).",
      "properties": {
        "id": {
          "type": "string"
        },
        "line": {
          "type": "string"
        },
        "scene_count": {
          "type": "integer"
        },
        "first_scene": {
          "type": "string"
        },
        "last_scene": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "line",
        "scene_count",
        "first_scene",
        "last_scene"
      ],
      "additionalProperties": false
    },
    "SummarySlice": {
      "type": "object",
      "description": "Set when the summarised plan is itself a slice (dpl slice): which revision of which whole plan it was cut from.",
      "properties": {
        "plan_hash": {
          "type": "string",
          "pattern": "^[0-9a-f]{64}$"
        },
        "scenes": {
          "type": "integer",
          "minimum": 0
        },
        "shots": {
          "type": "integer",
          "minimum": 0
        }
      },
      "required": [
        "plan_hash",
        "scenes",
        "shots"
      ],
      "additionalProperties": false
    }
  }
}
