{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://storage.googleapis.com/maestro-schemas/artifact-manifest/v1.schema.json",
  "title": "ArtifactManifest (v1)",
  "description": "The set of artifacts produced for a single Maestro flow run. Owned and emitted by Orchestra; written as manifest.json in the run's artifact root and consumed verbatim by the CLI and the cloud worker.",
  "type": "object",
  "additionalProperties": true,
  "properties": {
    "$schema": {
      "type": "string",
      "description": "Stable HTTPS URL identifying this schema (published to the public maestro-schemas GCS bucket), so the manifest stays self-describing wherever it is moved, copied, or uploaded. The vN path is the only version signal; there is no separate schemaVersion field."
    },
    "entries": {
      "type": "array",
      "description": "One element per artifact, or per homogeneous collection of artifacts. Omitted when empty.",
      "items": { "$ref": "#/$defs/ArtifactEntry" }
    }
  },
  "$defs": {
    "ArtifactEntry": {
      "type": "object",
      "description": "One artifact, or one homogeneous collection of artifacts.",
      "required": ["kind", "relativePath"],
      "additionalProperties": true,
      "properties": {
        "kind": {
          "description": "What this artifact is, semantically.",
          "$ref": "#/$defs/ArtifactKind"
        },
        "format": {
          "description": "Member format when the entry is homogeneous; omitted for a mixed collection.",
          "$ref": "#/$defs/ArtifactFormat"
        },
        "relativePath": {
          "type": "string",
          "description": "Path relative to the run root (the dir holding manifest.json), which is itself the zippable artifact bundle. Everything core makes sits directly under it: commands.json, logs/maestro.log (plus device logs and crash/ANR on worker/cloud), takeScreenshot/, startRecording/, the failure screenshot, the per-step screenshots/ folder, and screen-recording.mp4. A directory when count is set, otherwise a single file."
        },
        "count": {
          "type": "integer",
          "description": "Omitted for a single file; set to the member count for a collection living under relativePath."
        },
        "sizeBytes": {
          "type": "integer",
          "description": "Size of the file in bytes; omitted when unknown or for a collection."
        },
        "metadata": {
          "type": "object",
          "description": "Free-form string key/value pairs qualifying the artifact. metadata.source identifies the log origin for DEVICE_LOG: simulator | xctest | emulator. Omitted when empty.",
          "additionalProperties": { "type": "string" }
        }
      }
    },
    "ArtifactKind": {
      "type": "string",
      "description": "What an artifact is, semantically. Superset across local + cloud; each environment emits the subset it produces. Wire form is the enum name in SCREAMING_SNAKE_CASE.",
      "oneOf": [
        {
          "const": "SCREENSHOT",
          "description": "A step PNG screenshot in the run-root screenshots/ folder. With captureStepScreenshots on (worker), one per executed command; otherwise only the failed command's. The failed step's file is identified via commands.json (the FAILED command's artifacts entry)."
        },
        {
          "const": "TAKE_SCREENSHOT",
          "description": "Output of the takeScreenshot command, under the run-root takeScreenshot/ folder."
        },
        {
          "const": "SCREEN_RECORDING",
          "description": "The whole-run MP4 recording at the run-root screen-recording.mp4. Flag-gated; emitted by the worker, not the local CLI."
        },
        {
          "const": "START_SCREEN_RECORDING",
          "description": "Output of the startRecording command, under the run-root startRecording/ folder."
        },
        {
          "const": "SCREEN_HIERARCHY",
          "description": "The view hierarchy, captured per step as its own JSON artifact (run-root screen-hierarchy/ folder, one step-<N>.json per executed command) and referenced from that command's COMMAND_METADATA artifacts list. This is the only home of the hierarchy; it is no longer inlined in commands.json."
        },
        {
          "const": "COMMAND_METADATA",
          "description": "commands.json: per-command execution metadata (status, timing, evaluated command) plus a typed artifacts list ({type, path} objects, run-root-relative) referencing the files each command produced. The view hierarchy is NOT inline here: it is a separate SCREEN_HIERARCHY artifact, one per executed command, referenced from that command's artifacts list."
        },
        {
          "const": "MAESTRO_LOG",
          "description": "maestro.log: the scoped capture of maestro.* logger output for this flow run."
        },
        {
          "const": "DEVICE_LOG",
          "description": "Raw device-side log output. metadata.source identifies the origin: simulator, xctest, or emulator."
        },
        {
          "const": "CRASH_REPORT",
          "description": "An app crash report collected from the device."
        },
        {
          "const": "ANR_REPORT",
          "description": "An Android 'Application Not Responding' report collected from the device."
        },
        {
          "const": "AI_ANALYSIS",
          "description": "Reserved for AI-generated analysis of the run. Not emitted yet."
        }
      ]
    },
    "ArtifactFormat": {
      "type": "string",
      "description": "Concrete on-disk format of an artifact's bytes. ZIP is a download view, not a kind, and so is absent here.",
      "enum": ["PNG", "MP4", "JSON", "TXT", "HTML"]
    }
  }
}
