{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/cueframe-ai/json-schema/cueframe-ai-checkpoint-response-schema.json",
  "title": "CheckpointResponse",
  "x-generated": "2026-11-10",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/cueframe-ai-checkpoints-api-openapi.yml#/components/schemas/CheckpointResponse",
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "projectId": {
      "type": "string"
    },
    "composeJobId": {
      "type": "string"
    },
    "briefId": {
      "type": "string"
    },
    "kind": {
      "type": "string",
      "enum": [
        "gate",
        "score"
      ]
    },
    "stage": {
      "$ref": "#/$defs/CheckpointStage"
    },
    "version": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "status": {
      "type": "string",
      "enum": [
        "awaiting",
        "approved",
        "revised",
        "abandoned",
        "expired",
        "superseded"
      ]
    },
    "artifact": {
      "description": "The stage artifact under review: the locked ComposePlan at content; the composition wire shape at layout/motion; the judged composition snapshot on kind:'score'."
    },
    "stillUrls": {
      "description": "Presigned storyboard/eval stills — the packet's visual evidence (may be GC'd by the retention sweep after the job goes terminal; the decision record is immortal).",
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "criticVerdicts": {
      "description": "Per-criterion scores + critique from the design loop / judge, incl. lock_violation entries."
    },
    "quote": {
      "$ref": "#/$defs/CheckpointQuote"
    },
    "revisionCycle": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991,
      "description": "Revise cycles this gate has consumed. The brief quote states the included count (revisionCyclesIncluded); beyond it, resume(revise) is refused with a typed error."
    },
    "decision": {
      "description": "The recorded decision {decision, comments?, globalNote?, decidedAt} once resolved."
    },
    "reviewMode": {
      "description": "How this packet is decided (from the Brief's gates). 'hosted' = the review PAGE captures the decision; absent/'agent' = the decision flows back through the driving agent.",
      "type": "string",
      "enum": [
        "agent",
        "hosted"
      ]
    },
    "reviewUrl": {
      "description": "Hosted review-page URL (present when reviewMode is 'hosted') — a human decides from this link, no account or agent session; the recorded decision rides the SAME resume rail, and the agent learns of it via checkpoint webhooks / wait_job.",
      "type": "string"
    },
    "createdAt": {
      "type": "number"
    },
    "updatedAt": {
      "type": "number"
    }
  },
  "required": [
    "id",
    "projectId",
    "kind",
    "version",
    "status",
    "artifact",
    "revisionCycle",
    "createdAt",
    "updatedAt"
  ],
  "additionalProperties": false,
  "$defs": {
    "CheckpointQuote": {
      "type": "object",
      "properties": {
        "thisStepUsd": {
          "type": "number",
          "description": "What approving costs NEXT (the render at the final gate; $0 earlier)."
        },
        "jobSpendSoFarUsd": {
          "type": "number",
          "description": "What has SETTLED so far — $0 while the run is live (compose is charge-on-delivery on both rails), so abandoning at a gate charges nothing."
        },
        "estimatedJourneyTotalUsd": {
          "type": "number",
          "description": "The same journey number the Brief quoted."
        }
      },
      "required": [
        "thisStepUsd",
        "jobSpendSoFarUsd",
        "estimatedJourneyTotalUsd"
      ],
      "additionalProperties": false
    },
    "CheckpointStage": {
      "type": "string",
      "enum": [
        "content",
        "layout",
        "motion"
      ]
    }
  }
}