{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/dotsy-ai/json-schema/dotsy-ai-draft-status-response-schema.json",
  "title": "DraftStatusResponse",
  "x-generated": "2026-11-06",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/dotsy-ai-openapi.yml#/components/schemas/DraftStatusResponse",
  "type": "object",
  "properties": {
    "total": {
      "type": "integer",
      "description": "Staged changes in all three lists."
    },
    "content": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "modified",
              "new",
              "deleted"
            ]
          },
          "hash": {
            "type": "string",
            "description": "Fingerprint of the staged content (`deleted` for a deletion). Echo it in `reviewedSet` when you publish."
          }
        },
        "required": [
          "key",
          "status",
          "hash"
        ]
      },
      "description": "Content files that differ from the live site."
    },
    "routes": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "path": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "modified",
              "new",
              "deleted"
            ]
          },
          "hash": {
            "type": "string"
          }
        },
        "required": [
          "path",
          "status",
          "hash"
        ]
      },
      "description": "Routes that differ from the live site."
    },
    "menus": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "menu": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "modified",
              "new",
              "deleted"
            ]
          }
        },
        "required": [
          "id",
          "menu",
          "status"
        ]
      },
      "description": "Menu items that differ from the live site. Menus always publish together with the rest."
    },
    "fingerprint": {
      "type": "string",
      "description": "One opaque token for the whole staged state. If it is unchanged when you publish, nothing moved since you looked."
    },
    "indexState": {
      "type": "string",
      "enum": [
        "building"
      ],
      "description": "The staged-set index is being rebuilt, so the lists above may be a subset of what is staged."
    },
    "contentBytesIssues": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string"
          },
          "reason": {
            "type": "string",
            "enum": [
              "missing",
              "empty"
            ]
          }
        },
        "required": [
          "key",
          "reason"
        ]
      },
      "description": "Pages whose stored bytes are missing or empty. A publish would be refused (`content_bytes_missing`): re-write them first."
    },
    "draftLog": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "tool": {
            "type": "string"
          },
          "context": {
            "type": "string"
          },
          "at": {
            "type": "number",
            "description": "Unix ms."
          }
        },
        "required": [
          "tool",
          "context",
          "at"
        ]
      },
      "description": "The most recent draft edits an agent recorded (up to 20). Cleared when all drafts are discarded."
    },
    "verify": {
      "type": [
        "object",
        "null"
      ],
      "properties": {
        "at": {
          "type": "number",
          "description": "Unix ms when that check ran."
        },
        "scanned": {
          "type": "integer",
          "description": "Pages the check composed and scanned."
        },
        "errors": {
          "type": "integer"
        },
        "warnings": {
          "type": "integer"
        },
        "scope": {
          "type": "string",
          "enum": [
            "site",
            "paths"
          ],
          "description": "`site`: every route was checked. `paths`: only the pages the caller named, so a sample."
        },
        "heavyImages": {
          "type": "integer",
          "description": "Images the site's pages load that are too heavy or never shrunk (files with an image code: `perf_image_heavy`, `perf_image_old_format` or `perf_gif_heavy`; stylesheets, scripts and videos are not counted). Counted by a `site` run; a `paths` run keeps the last site run's count, and leaves it out when there was none. Absent on checks from before this field."
        },
        "brokenLinks": {
          "type": "integer",
          "description": "Distinct pages the site's links point at that don't exist (`link_broken_internal`). Counted by a `site` run; a `paths` run keeps the last site run's count. Absent when there was none, on checks from before this field, and after a run that could not read every route and page (`health.links.partial`)."
        },
        "healthWarnings": {
          "type": "integer",
          "description": "Warning-level health issues from the last `site` run (`health.warnings`: page issues plus file and site warnings, never infos). Every `site` run stores it; a `paths` run keeps the last site run's count. Absent when there was none and on checks from before this field. Not part of the SEO issue count."
        },
        "healthPartial": {
          "type": "boolean",
          "enum": [
            true
          ],
          "description": "True when that `site` run could not check everything (`health.partial` or `health.links.partial`), so `healthWarnings` may be low. A `paths` run keeps it with the count."
        },
        "stale": {
          "type": "boolean",
          "description": "True when the draft changed (content, routes or menus) after the check ran, so its result no longer describes it."
        }
      },
      "required": [
        "at",
        "scanned",
        "errors",
        "warnings",
        "scope",
        "stale"
      ],
      "description": "The last `verifySite` run. Present only with `?verify=1`; `null` when the site has never been verified."
    }
  },
  "required": [
    "total",
    "content",
    "routes",
    "menus",
    "fingerprint"
  ]
}