{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://dev.pow.box/agent/manifest.schema.json",
  "title": "POW!BOX game manifest",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "manifestVersion",
    "slug",
    "name",
    "creator",
    "orientation",
    "runtime",
    "entry",
    "scoreMode",
    "instruction",
    "objective",
    "controls",
    "permissions",
    "criticalAssets",
    "icon"
  ],
  "properties": {
    "manifestVersion": {
      "const": 1
    },
    "slug": {
      "type": "string",
      "pattern": "^[a-z0-9](?:[a-z0-9-]{1,30}[a-z0-9])?$",
      "description": "Stable game slug; not an access grant or a publishing permission."
    },
    "name": {
      "type": "string",
      "minLength": 2,
      "maxLength": 40
    },
    "creator": {
      "type": "string",
      "pattern": "^@[a-z0-9_]{2,24}$"
    },
    "description": {
      "type": "string",
      "maxLength": 240
    },
    "orientation": {
      "const": "portrait",
      "description": "Portrait games only."
    },
    "runtime": {
      "type": "string",
      "pattern": "^v[0-9]+$",
      "description": "Shared runtime version, currently v1."
    },
    "entry": {
      "type": "string",
      "pattern": "^game\\.js$",
      "description": "Built ESM entry relative to the game folder. The engine and SDK are externals supplied by the host."
    },
    "scoreMode": {
      "enum": [
        "highest",
        "lowest",
        "none"
      ]
    },
    "instruction": {
      "type": "string",
      "minLength": 8,
      "maxLength": 80,
      "description": "One sentence a player reads before pressing Play."
    },
    "objective": {
      "type": "string",
      "minLength": 4,
      "maxLength": 80,
      "description": "The first objective, e.g. 'Pass 10 gaps'."
    },
    "controls": {
      "type": "string",
      "minLength": 4,
      "maxLength": 80,
      "description": "Controls explained in one line."
    },
    "permissions": {
      "type": "array",
      "uniqueItems": true,
      "items": {
        "enum": [
          "save",
          "scores",
          "challenges",
          "share",
          "analytics"
        ]
      }
    },
    "criticalAssets": {
      "type": "array",
      "maxItems": 64,
      "items": {
        "type": "string",
        "pattern": "^assets/[A-Za-z0-9_./-]+$"
      },
      "description": "Paths under assets/ that must load before ready(). Everything else is lazy."
    },
    "icon": {
      "type": "string",
      "pattern": "^assets/[A-Za-z0-9_./-]+\\.(png|webp|svg)$"
    },
    "themeColor": {
      "type": "string",
      "pattern": "^#[0-9a-fA-F]{6}$"
    },
    "preview": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "webm",
        "mp4",
        "poster",
        "durationSeconds"
      ],
      "properties": {
        "webm": {
          "type": "string"
        },
        "mp4": {
          "type": "string"
        },
        "poster": {
          "type": "string"
        },
        "durationSeconds": {
          "type": "number",
          "minimum": 3,
          "maximum": 20
        },
        "capturedWith": {
          "type": "string",
          "description": "Set by the POW!BOX team."
        }
      },
      "description": "Added by the POW!BOX team during review; not creator-authored."
    },
    "balance": {
      "type": "object",
      "description": "Tunables the game can read at runtime through game.release.balance; changing them creates a new candidate.",
      "additionalProperties": {
        "type": [
          "number",
          "string",
          "boolean"
        ]
      }
    }
  }
}
