{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/cueframe-ai/json-schema/cueframe-ai-checkpoint-list-response-schema.json",
  "title": "CheckpointListResponse",
  "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/CheckpointListResponse",
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/CheckpointResponse"
      }
    },
    "pagination": {
      "$ref": "#/$defs/PaginationMeta"
    }
  },
  "required": [
    "data",
    "pagination"
  ],
  "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
    },
    "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
    },
    "CheckpointStage": {
      "type": "string",
      "enum": [
        "content",
        "layout",
        "motion"
      ]
    },
    "PaginationMeta": {
      "type": "object",
      "properties": {
        "hasMore": {
          "type": "boolean"
        },
        "nextCursor": {
          "type": [
            "string",
            "null"
          ]
        },
        "prevCursor": {
          "type": [
            "string",
            "null"
          ]
        }
      },
      "required": [
        "hasMore",
        "nextCursor",
        "prevCursor"
      ],
      "additionalProperties": false,
      "description": "Cursor pagination metadata."
    }
  }
}