{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/slideforge-dev/json-schema/slideforge-dev-sandbox-render-request-schema.json",
  "title": "SandboxRenderRequest",
  "x-generated": "2026-10-31",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/slideforge-dev-openapi.json#/components/schemas/SandboxRenderRequest",
  "properties": {
    "code": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 64000
        },
        {
          "type": "null"
        }
      ],
      "title": "Code",
      "description": "Python code defining build(prs) or build(prs, slide). Required if job_id not provided. Max 64 KB — well above any real slide; the Jev screen (A2) screens the whole thing, so an unbounded field would let a padded payload slip past a prefix screen."
    },
    "job_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Job Id",
      "description": "Previous render_code job ID — loads its code for patching with replacements."
    },
    "replacements": {
      "anyOf": [
        {
          "items": {
            "$ref": "#/$defs/Replacement"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "title": "Replacements",
      "description": "String replacements to apply to the loaded code. Requires job_id."
    },
    "theme_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Theme Id",
      "description": "Theme ID for chrome + colors"
    },
    "logo_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Logo Id",
      "description": "Uploaded logo (upload_asset purpose=logo): the account's logo inside the code — add_logo(slide) draws it in the theme's logo box."
    },
    "chrome": {
      "anyOf": [
        {
          "type": "object"
        },
        {
          "type": "null"
        }
      ],
      "title": "Chrome",
      "description": "Chrome overlays: title, subtitle, footer, etc."
    },
    "headline": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Headline",
      "description": "Slide title (chrome-rendered; use build(prs, slide))"
    },
    "context": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Context",
      "description": "Subtitle line under the title (chrome-rendered)"
    },
    "takeaway": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Takeaway",
      "description": "Bottom takeaway band (chrome-rendered)"
    },
    "source_note": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Source Note",
      "description": "Source citation in the footer zone (chrome-rendered)"
    },
    "notes": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Notes",
      "description": "Speaker notes for the presenter; never drawn on the slide. Wins over notes the code wrote."
    },
    "name": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Name",
      "description": "Human-readable job name"
    },
    "include_preview": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Include Preview",
      "description": "Embed preview inline: none, small (256px), default (768px), full. Default: none."
    },
    "verify": {
      "type": "string",
      "title": "Verify",
      "description": "Verification tier: off | lint (default — static geometry linter + composer content validators, no LLM) | lint+vlm (adds the VLM second-look, ~+8s) | full.",
      "default": "lint"
    },
    "dry_run": {
      "type": "boolean",
      "title": "Dry Run",
      "description": "If true: run the verify tier and return status (validated if clean, invalid if errors) + warnings/errors with cost:0 and NO PPTX — a free pre-commit check. Fix errors, then render for real.",
      "default": false
    },
    "quality_profile": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Quality Profile",
      "description": "Readiness thresholds the layout block is judged against: executive | technical (default) | appendix."
    },
    "fail_on_vlm": {
      "anyOf": [
        {
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "title": "Fail On Vlm",
      "description": "VLM finding categories that BLOCK (escalate to errors, render free per usable-or-free): substring match on the finding, e.g. ['contrast', 'clipping']. A high-confidence `overlap` and any `content_missing` already block by default. Requires verify=lint+vlm."
    },
    "content": {
      "anyOf": [
        {
          "type": "object"
        },
        {
          "type": "null"
        }
      ],
      "title": "Content",
      "description": "Typed business facts (ADR 2026-07-14): available read-only as CONTENT inside the code; the renderer verifies every leaf rendered verbatim and emits fidelity + provenance. Keys named 'id' are references, not display content."
    },
    "code_profile": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Code Profile",
      "description": "widgets_only = compose via add_widget + approved helpers + CONTENT/theme only; raw python-pptx (slide.shapes.*, add_text_box/add_box, add_slide) is rejected. Omit or 'native' for full access. Response echoes code_profile.applied + violations."
    }
  },
  "type": "object",
  "$defs": {
    "Replacement": {
      "properties": {
        "old": {
          "type": "string",
          "title": "Old",
          "description": "Exact string to find in the code"
        },
        "new": {
          "type": "string",
          "title": "New",
          "description": "String to replace it with"
        }
      },
      "type": "object",
      "required": [
        "old",
        "new"
      ],
      "title": "Replacement"
    }
  }
}