{
  "schema_version": "1.0",
  "nodes": [
    {
      "id": "shoot",
      "type": "input/bundle_manifest",
      "label": "Photo shoot",
      "parameters": {
        "validation": "warn",
        "verifyChecksum": "always",
        "allowExternalUrls": false,
        "manifest": "__SHOOT__"
      }
    },
    {
      "id": "assets",
      "type": "utility/extract",
      "label": "Photos",
      "parameters": {
        "path": "assets",
        "expected_type": "json",
        "on_missing": "fail"
      }
    },
    {
      "id": "photos",
      "type": "enumerate/json",
      "label": "One photo at a time",
      "parameters": {
        "jsonConfig": {
          "arrayPath": "(root)",
          "properties": [
            {
              "sourcePath": "id",
              "outputPort": "photo_id",
              "outputType": "text",
              "selected": true,
              "label": "Photo"
            },
            {
              "sourcePath": "metadata.space",
              "outputPort": "space",
              "outputType": "text",
              "selected": true,
              "label": "Space"
            },
            {
              "sourcePath": "storageRef",
              "outputPort": "photo",
              "outputType": "image",
              "selected": true,
              "label": "Image"
            }
          ]
        },
        "emptyBehavior": "fail"
      }
    },
    {
      "id": "measure",
      "type": "media/technical_info",
      "label": "Measure",
      "parameters": {
        "check_id": "social-resolution",
        "policy": {
          "schema": "madoo.media-policy/v1",
          "policyId": "social-video-source",
          "allowedMediaKinds": [
            "image"
          ],
          "minimumWidth": 1200,
          "minimumHeight": 675
        }
      }
    },
    {
      "id": "gate",
      "type": "utility/quality_gate",
      "label": "Big enough",
      "parameters": {
        "mode": "route",
        "profile": "all_must_pass"
      }
    },
    {
      "id": "look",
      "type": "ai/image_analysis",
      "label": "Judge the photo",
      "parameters": {
        "system_prompt": "You are the photo editor of a hotel group. Judge one photograph for a social media campaign. Answer with one JSON object with exactly these keys: sharp: true only if the main subject is in focus and free of motion blur; exposure: \"good\", \"too_dark\" or \"too_bright\"; publishable: true only if sharp is true and exposure is \"good\" and the photo would look professional on the hotel's channels; reason: one sentence explaining the verdict; caption: a short, warm English caption for the post, at most 90 characters, no hashtags, no emojis; motion: one sentence for a video model describing a gentle, realistic camera and scene motion for a 4-second clip of this photo (a slow push-in, curtains moving, light on the water), with nothing added that is not in the photo.",
        "prompt": "Judge this photograph.",
        "response_format": "json_object",
        "temperature": 0.2,
        "max_tokens": 700
      }
    },
    {
      "id": "check",
      "type": "utility/json_schema_validate",
      "label": "Verdict is complete",
      "parameters": {
        "schema_source": "inline",
        "schema_definition": "{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"title\": \"Photo judgement\",\n  \"type\": \"object\",\n  \"required\": [\n    \"sharp\",\n    \"exposure\",\n    \"publishable\",\n    \"reason\",\n    \"caption\",\n    \"motion\"\n  ],\n  \"properties\": {\n    \"sharp\": {\n      \"type\": \"boolean\"\n    },\n    \"exposure\": {\n      \"enum\": [\n        \"good\",\n        \"too_dark\",\n        \"too_bright\"\n      ]\n    },\n    \"publishable\": {\n      \"type\": \"boolean\"\n    },\n    \"reason\": {\n      \"type\": \"string\",\n      \"minLength\": 10,\n      \"maxLength\": 200\n    },\n    \"caption\": {\n      \"type\": \"string\",\n      \"minLength\": 10,\n      \"maxLength\": 90\n    },\n    \"motion\": {\n      \"type\": \"string\",\n      \"minLength\": 20,\n      \"maxLength\": 300\n    }\n  },\n  \"additionalProperties\": false\n}",
        "mode": "route",
        "max_errors": 10
      }
    },
    {
      "id": "publishable",
      "type": "utility/extract",
      "label": "Publishable?",
      "parameters": {
        "path": "publishable",
        "expected_type": "boolean",
        "on_missing": "fail"
      }
    },
    {
      "id": "reason",
      "type": "utility/extract",
      "label": "Why",
      "parameters": {
        "path": "reason",
        "expected_type": "text",
        "on_missing": "fail"
      }
    },
    {
      "id": "caption",
      "type": "utility/extract",
      "label": "Caption",
      "parameters": {
        "path": "caption",
        "expected_type": "text",
        "on_missing": "fail"
      }
    },
    {
      "id": "motion",
      "type": "utility/extract",
      "label": "Motion",
      "parameters": {
        "path": "motion",
        "expected_type": "text",
        "on_missing": "fail"
      }
    },
    {
      "id": "keep",
      "type": "utility/filter",
      "label": "Only publishable photos",
      "parameters": {
        "invert": false
      }
    },
    {
      "id": "clip",
      "type": "ai/image_to_video",
      "label": "Social clip",
      "parameters": {
        "duration": "4",
        "resolution": "720p",
        "aspect_ratio": "16:9",
        "generate_audio": false,
        "negative_prompt": "people, text, logos, distortion, warping, flicker"
      }
    },
    {
      "id": "campaign",
      "type": "aggregate/json",
      "label": "Campaign",
      "parameters": {
        "emptyBehavior": "empty",
        "jsonAggregateConfig": {
          "prettyPrint": true,
          "outputName": "campaign",
          "columns": [
            {
              "name": "photo",
              "inputPort": "photo_id",
              "type": "text"
            },
            {
              "name": "space",
              "inputPort": "space",
              "type": "text"
            },
            {
              "name": "caption",
              "inputPort": "caption",
              "type": "text"
            },
            {
              "name": "clip",
              "inputPort": "clip",
              "type": "video",
              "whenAbsent": "skip_row"
            }
          ]
        }
      }
    },
    {
      "id": "report",
      "type": "aggregate/json",
      "label": "Screening report",
      "parameters": {
        "jsonAggregateConfig": {
          "prettyPrint": true,
          "outputName": "screening",
          "columns": [
            {
              "name": "photo",
              "inputPort": "photo_id",
              "type": "text"
            },
            {
              "name": "width",
              "inputPort": "width",
              "type": "number"
            },
            {
              "name": "big_enough",
              "inputPort": "big_enough",
              "type": "boolean"
            },
            {
              "name": "publishable",
              "inputPort": "publishable",
              "type": "boolean"
            },
            {
              "name": "reason",
              "inputPort": "reason",
              "type": "text"
            }
          ]
        }
      }
    },
    {
      "id": "out_clips",
      "type": "output/video",
      "label": "Clips",
      "parameters": {
        "output_name": "clips"
      }
    },
    {
      "id": "out_campaign",
      "type": "output/json",
      "label": "Campaign",
      "parameters": {
        "output_name": "campaign"
      }
    },
    {
      "id": "out_report",
      "type": "output/json",
      "label": "Screening report",
      "parameters": {
        "output_name": "screening_report"
      }
    },
    {
      "id": "out_issues",
      "type": "output/json",
      "label": "Bundle issues",
      "parameters": {
        "output_name": "bundle_issues"
      }
    }
  ],
  "connections": [
    {
      "from_node": "shoot",
      "from_output": "bundle",
      "to_node": "assets",
      "to_input": "json"
    },
    {
      "from_node": "assets",
      "from_output": "value",
      "to_node": "photos",
      "to_input": "json"
    },
    {
      "from_node": "shoot",
      "from_output": "issues",
      "to_node": "out_issues",
      "to_input": "json"
    },
    {
      "from_node": "photos",
      "from_output": "photo",
      "to_node": "measure",
      "to_input": "media"
    },
    {
      "from_node": "measure",
      "from_output": "quality_check",
      "to_node": "gate",
      "to_input": "checks_0"
    },
    {
      "from_node": "photos",
      "from_output": "photo",
      "to_node": "gate",
      "to_input": "value"
    },
    {
      "from_node": "gate",
      "from_output": "value",
      "to_node": "look",
      "to_input": "images"
    },
    {
      "from_node": "look",
      "from_output": "json",
      "to_node": "check",
      "to_input": "document"
    },
    {
      "from_node": "check",
      "from_output": "normalized_json",
      "to_node": "publishable",
      "to_input": "json"
    },
    {
      "from_node": "check",
      "from_output": "normalized_json",
      "to_node": "reason",
      "to_input": "json"
    },
    {
      "from_node": "check",
      "from_output": "normalized_json",
      "to_node": "caption",
      "to_input": "json"
    },
    {
      "from_node": "check",
      "from_output": "normalized_json",
      "to_node": "motion",
      "to_input": "json"
    },
    {
      "from_node": "publishable",
      "from_output": "value",
      "to_node": "keep",
      "to_input": "condition"
    },
    {
      "from_node": "gate",
      "from_output": "value",
      "to_node": "keep",
      "to_input": "value"
    },
    {
      "from_node": "keep",
      "from_output": "value",
      "to_node": "clip",
      "to_input": "image"
    },
    {
      "from_node": "motion",
      "from_output": "value",
      "to_node": "clip",
      "to_input": "prompt"
    },
    {
      "from_node": "photos",
      "from_output": "photo_id",
      "to_node": "campaign",
      "to_input": "photo_id"
    },
    {
      "from_node": "photos",
      "from_output": "space",
      "to_node": "campaign",
      "to_input": "space"
    },
    {
      "from_node": "caption",
      "from_output": "value",
      "to_node": "campaign",
      "to_input": "caption"
    },
    {
      "from_node": "clip",
      "from_output": "video",
      "to_node": "campaign",
      "to_input": "clip"
    },
    {
      "from_node": "photos",
      "from_output": "photo_id",
      "to_node": "report",
      "to_input": "photo_id"
    },
    {
      "from_node": "measure",
      "from_output": "width",
      "to_node": "report",
      "to_input": "width"
    },
    {
      "from_node": "gate",
      "from_output": "passed",
      "to_node": "report",
      "to_input": "big_enough"
    },
    {
      "from_node": "publishable",
      "from_output": "value",
      "to_node": "report",
      "to_input": "publishable"
    },
    {
      "from_node": "reason",
      "from_output": "value",
      "to_node": "report",
      "to_input": "reason"
    },
    {
      "from_node": "clip",
      "from_output": "video",
      "to_node": "out_clips",
      "to_input": "video"
    },
    {
      "from_node": "campaign",
      "from_output": "result",
      "to_node": "out_campaign",
      "to_input": "json"
    },
    {
      "from_node": "report",
      "from_output": "result",
      "to_node": "out_report",
      "to_input": "json"
    }
  ]
}
