{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://sashite.dev/schemas/pmn/1.0.0/schema.json",
  "title": "Portable Move Notation (PMN) v1.0.0",
  "description": "Rule-agnostic JSON format for mechanical decomposition of moves using CELL coordinates, HAND \"*\", and QPI piece identifiers.",
  "type": "array",

  "oneOf": [
    { "description": "Pass move (voluntary turn conclusion without any action).", "maxItems": 0 },
    { "description": "Non-empty action sequence (≥2 elements).", "minItems": 2 }
  ],

  "$comment": "Non-empty arrays represent a flat, left-to-right sequence of atomic actions grouped as [source, destination, piece?]. The total length must be a multiple of 3, or a multiple of 3 plus 2 (final action without explicit piece). Enforcement of this grouping, hand→hand prohibition, and no-effect actions MUST be handled at application level per PMN spec.",

  "items": { "$ref": "#/$defs/element" },

  "$defs": {
    "cell": {
      "description": "CELL coordinate token (multi-dimensional friendly). Keep this permissive; exact grammar is in CELL spec.",
      "type": "string",
      "pattern": "^[a-z]+(?:[0-9]+[A-Z]+[a-z]+)*[0-9]*[A-Z]*$"
    },
    "hand": {
      "description": "HAND (reserve) location.",
      "type": "string",
      "pattern": "^\\*$"
    },
    "location": {
      "description": "Either a CELL coordinate or HAND \"*\".",
      "type": "string",
      "oneOf": [
        { "$ref": "#/$defs/cell" },
        { "$ref": "#/$defs/hand" }
      ]
    },
    "qpi": {
      "description": "QPI (Qualified Piece Identifier): <style>:<piece>, with optional leading +/− on the piece and optional trailing prime for variants. Case-style consistency is enforced at application level.",
      "type": "string",
      "pattern": "^[A-Za-z]:[+-]?[A-Za-z](?:'|[a-z])?$"
    },
    "element": {
      "description": "An element of the flat PMN array. Position determines its role (source, destination, or optional piece).",
      "type": "string",
      "minLength": 1
    }
  },

  "allOf": [
    {
      "$comment": "Structural guard: every element must be a plausible LOCATION or QPI token. Role-specific checks (e.g., that positions 0,1,3,4,... are locations and 2,5,8,... are QPI) are application-level due to JSON Schema limitations for repeating triplets.",
      "items": {
        "anyOf": [
          { "$ref": "#/$defs/location" },
          { "$ref": "#/$defs/qpi" }
        ]
      }
    }
  ],

  "examples": [
    [],

    ["e2", "e4"],
    ["e2", "e4", "C:P"],

    ["e7", "e8", "C:Q"],

    ["*", "e4", "S:P"],
    ["b2", "*", "s:l"],

    ["a1", "*", "S:L", "b2", "a1", "S:S"],

    ["e1", "g1"],
    ["e1", "g1", "C:K", "h1", "f1", "C:R"],

    ["e5", "f6"],
    ["e5", "f6", "C:P", "f5", "*", "c:p"],

    ["e4", "e4", "C:+P"]
  ],

  "x-counterExamples": [
    {
      "description": "Single element (incomplete)",
      "value": ["e2"]
    },
    {
      "description": "Hand-to-hand displacement is prohibited by protocol (semantic rule).",
      "note": "Must be rejected by application-level validation.",
      "value": ["*", "*", "S:P"]
    },
    {
      "description": "Same-location without state change (no-effect action) is prohibited (semantic rule).",
      "note": "Use [] to pass the turn.",
      "value": ["a1", "a1"]
    },
    {
      "description": "Length 4 does not fit grouping rule (3k or 3k+2).",
      "value": ["e2", "e4", "C:P", "f3"]
    }
  ]
}
