{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://theamateur.co.uk/schemas/dpl/dpl.draft-1.schema.json",
  "title": "DPL draft (dpl.draft/1)",
  "description": "What `dpl draft start <brief.json> --format json` writes: a valid skeleton plan (`dpl.plan/1`; placeholders start with TODO), the protocol, the layers to write it in with what each requires, the coverage recipes on offer, notes on the ids the brief's names became, and the first next action. Every member listed here is always written, or left out when null; nothing else appears.",
  "$comment": "Nothing here is written by a model. The skeleton passes `dpl validate`; it is not complete: `dpl draft next` says what is missing, and `dpl draft gate` decides when it is ready.",
  "type": "object",
  "properties": {
    "format": {
      "type": "string",
      "const": "dpl.draft/1"
    },
    "work_id": {
      "type": "string"
    },
    "profile": {
      "description": "film or short.",
      "type": "string",
      "enum": [
        "film",
        "short"
      ]
    },
    "brief_hash": {
      "description": "SHA-256 of the brief in its standard layout.",
      "type": "string",
      "pattern": "^[0-9a-f]{64}$"
    },
    "grammar_version": {
      "description": "The version of the grammar (recipes and platform defaults) the protocol used.",
      "type": "string"
    },
    "rules_version": {
      "description": "The readiness rules the plan will be held to.",
      "type": "string"
    },
    "plan_hash": {
      "description": "The same revision hash `dpl readiness` reports for the skeleton.",
      "type": "string",
      "pattern": "^[0-9a-f]{64}$"
    },
    "plan": {
      "description": "The skeleton: a valid dpl.plan/1 (it passes `dpl validate`) whose placeholders start with TODO. Write the layers into it.",
      "$ref": "https://theamateur.co.uk/schemas/dpl/dpl.plan-1.schema.json"
    },
    "protocol": {
      "description": "How to use the protocol, in order.",
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "layers": {
      "description": "The layers to write, in order, for this profile.",
      "type": "array",
      "items": {
        "$ref": "#/$defs/LayerDefinition"
      }
    },
    "recipes": {
      "description": "The coverage recipes the grammar offers (`draft next` says which fits each scene).",
      "type": "array",
      "items": {
        "$ref": "#/$defs/RecipeSummary"
      }
    },
    "notes": {
      "description": "Facts from the brief that the skeleton could not carry into the plan, and what to do about each.",
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "next": {
      "$ref": "#/$defs/NextAction"
    }
  },
  "required": [
    "format",
    "work_id",
    "profile",
    "brief_hash",
    "grammar_version",
    "rules_version",
    "plan_hash",
    "plan",
    "protocol",
    "layers",
    "recipes",
    "notes",
    "next"
  ],
  "additionalProperties": false,
  "$defs": {
    "FieldSpec": {
      "type": "object",
      "description": "A plan path ($.scenes[*].purpose; [*] is every element) and what to put there.",
      "properties": {
        "path": {
          "type": "string"
        },
        "text": {
          "type": "string"
        }
      },
      "required": [
        "path",
        "text"
      ],
      "additionalProperties": false
    },
    "LayerDefinition": {
      "type": "object",
      "properties": {
        "id": {
          "description": "work, world, structure, coverage, performance, sound or production.",
          "type": "string"
        },
        "order": {
          "description": "Where it comes in the order, from 1.",
          "type": "integer",
          "minimum": 1
        },
        "title": {
          "type": "string"
        },
        "summary": {
          "type": "string"
        },
        "applies_to": {
          "description": "all profiles, or only short.",
          "type": "string"
        },
        "write": {
          "description": "What to write, in a few plain steps.",
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "fields": {
          "$ref": "#/$defs/LayerFields"
        },
        "required": {
          "description": "Without these the layer is not complete. Each is something the format or a readiness check cannot do without.",
          "type": "array",
          "items": {
            "$ref": "#/$defs/FieldSpec"
          }
        },
        "optional": {
          "description": "Worth writing when the film needs it. Absent, nothing is blocked.",
          "type": "array",
          "items": {
            "$ref": "#/$defs/FieldSpec"
          }
        },
        "checks": {
          "description": "The validation and readiness codes that apply once the layer is written.",
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "guidance": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": [
        "id",
        "order",
        "title",
        "summary",
        "applies_to",
        "write",
        "fields",
        "required",
        "optional",
        "checks",
        "guidance"
      ],
      "additionalProperties": false
    },
    "LayerFields": {
      "type": "object",
      "description": "The members a layer writes: at plan level, on each scene, on each shot, on each location and on each shot's camera. Lists name JSON members.",
      "properties": {
        "plan": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "scene": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "shot": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "location": {
          "description": "Members of each locations[] element this layer writes.",
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "camera": {
          "description": "Members of each shot's camera this layer writes.",
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": [
        "plan",
        "scene",
        "shot",
        "location",
        "camera"
      ],
      "additionalProperties": false
    },
    "NextAction": {
      "type": "object",
      "description": "The one thing to do next. It always names a plan path, a finding or a command: paths are plan paths that exist or that the schema defines; tool is the command to run when the step needs one. After the step, call dpl draft next again.",
      "properties": {
        "kind": {
          "$ref": "#/$defs/NextActionKind"
        },
        "layer": {
          "description": "The layer the step belongs to.",
          "type": [
            "string",
            "null"
          ]
        },
        "scene": {
          "type": [
            "string",
            "null"
          ]
        },
        "shot": {
          "type": [
            "string",
            "null"
          ]
        },
        "finding": {
          "description": "The finding to resolve or the finding a fix is for (dpl.findings/1 id).",
          "type": [
            "string",
            "null"
          ]
        },
        "fix": {
          "description": "The suggestion to apply (its id on the finding).",
          "type": [
            "string",
            "null"
          ]
        },
        "instruction": {
          "description": "In words, what to do; ends with the call to make afterwards.",
          "type": "string"
        },
        "paths": {
          "description": "Plan paths the step writes or changes.",
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "tool": {
          "description": "The command to run for this step, when it needs one (dpl apply, dpl draft gate, dpl validate); otherwise the command to call after writing.",
          "type": "string"
        }
      },
      "required": [
        "kind",
        "instruction",
        "paths",
        "tool"
      ],
      "additionalProperties": false
    },
    "NextActionKind": {
      "type": "string",
      "description": "What kind of step the next action is.",
      "enum": [
        "fix_plan_error",
        "write_layer",
        "apply_fix",
        "resolve_finding",
        "run_gate"
      ]
    },
    "RecipeSummary": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "title": {
          "type": "string"
        },
        "use_when": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "title",
        "use_when"
      ],
      "additionalProperties": false
    }
  }
}
