{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "anyOf": [
    {
      "additionalProperties": false,
      "$id": "resource",
      "type": "object",
      "required": [
        "format",
        "id",
        "title",
        "creator",
        "type",
        "node"
      ],
      "properties": {
        "$schema": {
          "type": "string"
        },
        "format": {
          "description": "Format version of this file.",
          "const": 1,
          "type": "number"
        },
        "id": {
          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
          "maxLength": 80,
          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
          "type": "string"
        },
        "title": {
          "minLength": 1,
          "maxLength": 40,
          "type": "string"
        },
        "creator": {
          "pattern": "^[a-z0-9_-]+$",
          "maxLength": 39,
          "description": "GitHub handle, lowercase.",
          "type": "string"
        },
        "description": {
          "minLength": 1,
          "maxLength": 240,
          "type": "string"
        },
        "ai_tools": {
          "maxItems": 8,
          "description": "AI tools used to make this file or its art. Required when any were used.",
          "type": "array",
          "items": {
            "minLength": 1,
            "maxLength": 60,
            "type": "string"
          }
        },
        "items": {
          "maxItems": 40,
          "type": "array",
          "items": {
            "additionalProperties": false,
            "type": "object",
            "required": [
              "id",
              "name",
              "kind",
              "rarity",
              "sprite"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              },
              "kind": {
                "anyOf": [
                  {
                    "const": "material",
                    "type": "string"
                  },
                  {
                    "const": "food",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "fragment",
                    "type": "string"
                  },
                  {
                    "const": "treasure",
                    "type": "string"
                  }
                ]
              },
              "rarity": {
                "description": "Declared rarity. The check compares it with the rarity computed from the data.",
                "anyOf": [
                  {
                    "const": "common",
                    "type": "string"
                  },
                  {
                    "const": "uncommon",
                    "type": "string"
                  },
                  {
                    "const": "rare",
                    "type": "string"
                  },
                  {
                    "const": "legendary",
                    "type": "string"
                  }
                ]
              },
              "class": {
                "description": "A base class (plant, wood, fibre, ...) or the id of a class an extension declares under one of them.",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  },
                  {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                ]
              },
              "family": {
                "pattern": "^[a-z0-9_-]+$",
                "maxLength": 24,
                "description": "A group inside the class, for example \"berry\" for every berry. Open: any lowercase word.",
                "type": "string"
              },
              "tags": {
                "maxItems": 8,
                "uniqueItems": true,
                "description": "Open words that describe it, for example \"sweet\" or \"night\".",
                "type": "array",
                "items": {
                  "pattern": "^[a-z0-9_-]+$",
                  "maxLength": 24,
                  "description": "A lowercase word.",
                  "type": "string"
                }
              },
              "tier": {
                "minimum": 1,
                "maximum": 20,
                "description": "How advanced it is, from 1. The rarity says how often it appears; the tier says how far up the ladder it is. A tool has the tier of its \"tool\".",
                "type": "integer"
              },
              "sprite": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
                "maxLength": 120,
                "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
                "type": "string"
              },
              "food": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "satiety"
                ],
                "properties": {
                  "satiety": {
                    "minimum": 0,
                    "maximum": 100,
                    "description": "Health points restored when eaten (the meter holds 100 at the start). 0 for a food that only hurts.",
                    "type": "integer"
                  },
                  "hurt": {
                    "minimum": 1,
                    "maximum": 100,
                    "description": "Health points it takes when eaten, at any hour: a bad fruit or a raw herb (G30).",
                    "type": "integer"
                  }
                }
              },
              "tool": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "kind",
                  "tier"
                ],
                "properties": {
                  "kind": {
                    "anyOf": [
                      {
                        "const": "basket",
                        "type": "string"
                      },
                      {
                        "const": "trowel",
                        "type": "string"
                      },
                      {
                        "const": "axe",
                        "type": "string"
                      },
                      {
                        "const": "staff",
                        "type": "string"
                      }
                    ]
                  },
                  "tier": {
                    "minimum": 1,
                    "maximum": 5,
                    "description": "Better tools work faster. The calculator clamps the total.",
                    "type": "integer"
                  },
                  "uses": {
                    "minimum": 1,
                    "maximum": 1000,
                    "description": "The tool wears out after this many uses. Left out, the tool lasts (DECISIONS.md, 2026-10-09: the crafting economy).",
                    "type": "integer"
                  }
                }
              },
              "fragment": {
                "additionalProperties": false,
                "description": "A found scrap that teaches a recipe.",
                "type": "object",
                "required": [
                  "unlocks"
                ],
                "properties": {
                  "unlocks": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                }
              },
              "wear": {
                "additionalProperties": false,
                "description": "Something the character wears (DECISIONS.md, 2026-10-09: the upgrade). A worn item stays in the bag.",
                "type": "object",
                "required": [
                  "slot"
                ],
                "properties": {
                  "slot": {
                    "description": "Where it is worn: head, top, legs (trousers), outfit (takes the top and the legs), feet, jewelry (two places) or hand (a tool).",
                    "anyOf": [
                      {
                        "const": "head",
                        "type": "string"
                      },
                      {
                        "const": "top",
                        "type": "string"
                      },
                      {
                        "const": "legs",
                        "type": "string"
                      },
                      {
                        "const": "outfit",
                        "type": "string"
                      },
                      {
                        "const": "feet",
                        "type": "string"
                      },
                      {
                        "const": "jewelry",
                        "type": "string"
                      },
                      {
                        "const": "hand",
                        "type": "string"
                      }
                    ]
                  },
                  "look": {
                    "description": "A look: worn on the look layer over the work clothes. It shows and counts for nothing, so it has no effects and no set.",
                    "type": "boolean"
                  },
                  "effects": {
                    "minItems": 1,
                    "maxItems": 2,
                    "description": "Small bonuses while it is worn on the work layer. Two at most, each effect once.",
                    "type": "array",
                    "items": {
                      "additionalProperties": false,
                      "type": "object",
                      "required": [
                        "effect",
                        "value"
                      ],
                      "properties": {
                        "effect": {
                          "description": "What a worn item helps: gathering, digging or crafting speed, the craft chance, or rare finds.",
                          "anyOf": [
                            {
                              "const": "gather_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "dig_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_chance_pct",
                              "type": "string"
                            },
                            {
                              "const": "rare_find_pct",
                              "type": "string"
                            }
                          ]
                        },
                        "value": {
                          "minimum": 1,
                          "maximum": 100,
                          "description": "Percent, at most the cap of the item's tier (params.wear_effect_max_pct).",
                          "type": "integer"
                        }
                      }
                    }
                  },
                  "set": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "A set of one creator: when every piece of it is worn, their effects grow by params.wear_set_bonus_pct.",
                    "type": "string"
                  }
                }
              },
              "premium_later": {
                "description": "Marks a look that may also be sold for premium currency once stage 6 brings it. Only a look item with no effect may carry it, and it stays obtainable in the game (DECISIONS.md, 2026-10-09).",
                "type": "boolean"
              }
            }
          }
        },
        "classes": {
          "maxItems": 10,
          "description": "Classes of your own, each under one base class.",
          "type": "array",
          "items": {
            "additionalProperties": false,
            "description": "A class of your own, declared under one base class. Every rule written for the base class holds for it.",
            "type": "object",
            "required": [
              "id",
              "name",
              "base"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "base": {
                "description": "plant (leaves, herbs, berries, fruit, roots, mushrooms), wood, fibre (reeds, grass, thread, cloth), stone, clay (clay, sand, pottery, brick), mineral (crystals, gems, salt, ore), metal (waits for its discovery), animal (feathers, wool, hide, bone), meal (cooked food), tool, garment (worn clothes), jewelry, relic (old things from the ruins).",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  }
                ]
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              }
            }
          }
        },
        "type": {
          "const": "resource",
          "type": "string"
        },
        "node": {
          "additionalProperties": false,
          "type": "object",
          "required": [
            "output",
            "yield",
            "active_ms",
            "respawn_ms",
            "count",
            "sprite",
            "level",
            "place"
          ],
          "properties": {
            "output": {
              "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
              "maxLength": 80,
              "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
              "type": "string"
            },
            "yield": {
              "minimum": 1,
              "maximum": 20,
              "description": "Units gathered per execution at perfect timing.",
              "type": "integer"
            },
            "active_ms": {
              "minimum": 0,
              "maximum": 3600000,
              "description": "Time the player is busy gathering once.",
              "type": "integer"
            },
            "respawn_ms": {
              "minimum": 0,
              "maximum": 3600000,
              "description": "Time before the same plant gives again. Waiting is never paid.",
              "type": "integer"
            },
            "count": {
              "minimum": 1,
              "maximum": 12,
              "description": "How many of these nodes the slot holds.",
              "type": "integer"
            },
            "sprite": {
              "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
              "maxLength": 120,
              "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
              "type": "string"
            },
            "sprite_empty": {
              "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
              "maxLength": 120,
              "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
              "type": "string"
            },
            "growth": {
              "minItems": 1,
              "maxItems": 3,
              "description": "Young stages of a node that grows back, from the youngest up (after `sprite_empty`, before `sprite`). The client shows the stage by how much of the respawn time has passed. Needs `sprite_empty`.",
              "type": "array",
              "items": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
                "maxLength": 120,
                "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
                "type": "string"
              }
            },
            "solid": {
              "description": "The node blocks the way, ready or not, as a tree does: a stump stays in the way until the tree is grown again. Left out: the player walks through it.",
              "type": "boolean"
            },
            "tool": {
              "anyOf": [
                {
                  "const": "basket",
                  "type": "string"
                },
                {
                  "const": "trowel",
                  "type": "string"
                },
                {
                  "const": "axe",
                  "type": "string"
                },
                {
                  "const": "staff",
                  "type": "string"
                }
              ]
            },
            "level": {
              "minimum": 1,
              "maximum": 20,
              "description": "Level required, in the profession the node trains: felling when the tool is an axe, foraging otherwise.",
              "type": "integer"
            },
            "game": {
              "description": "The minigame played when gathering: \"timing\" (stop a marker in the middle, the default), \"strike\" (three timed hammer strikes, for stone), \"pick\" (press only for the ripe ones, for plants) or \"snap\" (press fast, for wood).",
              "anyOf": [
                {
                  "const": "timing",
                  "type": "string"
                },
                {
                  "const": "strike",
                  "type": "string"
                },
                {
                  "const": "pick",
                  "type": "string"
                },
                {
                  "const": "snap",
                  "type": "string"
                }
              ]
            },
            "hours": {
              "description": "Hours of the in-game day when it can be gathered, [from, to).",
              "type": "array",
              "items": [
                {
                  "minimum": 0,
                  "maximum": 23,
                  "type": "integer"
                },
                {
                  "minimum": 1,
                  "maximum": 24,
                  "type": "integer"
                }
              ],
              "additionalItems": false,
              "minItems": 2,
              "maxItems": 2
            },
            "place": {
              "additionalProperties": false,
              "description": "An empty resource slot of the map (`count` nodes inside it), and optionally single-node slots scattered over the map.",
              "type": "object",
              "required": [
                "slot"
              ],
              "properties": {
                "slot": {
                  "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                  "maxLength": 80,
                  "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                  "type": "string"
                },
                "scatter": {
                  "minItems": 1,
                  "uniqueItems": true,
                  "description": "More resource slots that each hold exactly one of these nodes: a tree or a log standing where the map already shows one. They add supply only: `count`, the value and the opening's log floor follow the main slot.",
                  "type": "array",
                  "items": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    },
    {
      "additionalProperties": false,
      "$id": "treasure",
      "type": "object",
      "required": [
        "format",
        "id",
        "title",
        "creator",
        "type",
        "dig"
      ],
      "properties": {
        "$schema": {
          "type": "string"
        },
        "format": {
          "description": "Format version of this file.",
          "const": 1,
          "type": "number"
        },
        "id": {
          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
          "maxLength": 80,
          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
          "type": "string"
        },
        "title": {
          "minLength": 1,
          "maxLength": 40,
          "type": "string"
        },
        "creator": {
          "pattern": "^[a-z0-9_-]+$",
          "maxLength": 39,
          "description": "GitHub handle, lowercase.",
          "type": "string"
        },
        "description": {
          "minLength": 1,
          "maxLength": 240,
          "type": "string"
        },
        "ai_tools": {
          "maxItems": 8,
          "description": "AI tools used to make this file or its art. Required when any were used.",
          "type": "array",
          "items": {
            "minLength": 1,
            "maxLength": 60,
            "type": "string"
          }
        },
        "items": {
          "maxItems": 40,
          "type": "array",
          "items": {
            "additionalProperties": false,
            "type": "object",
            "required": [
              "id",
              "name",
              "kind",
              "rarity",
              "sprite"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              },
              "kind": {
                "anyOf": [
                  {
                    "const": "material",
                    "type": "string"
                  },
                  {
                    "const": "food",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "fragment",
                    "type": "string"
                  },
                  {
                    "const": "treasure",
                    "type": "string"
                  }
                ]
              },
              "rarity": {
                "description": "Declared rarity. The check compares it with the rarity computed from the data.",
                "anyOf": [
                  {
                    "const": "common",
                    "type": "string"
                  },
                  {
                    "const": "uncommon",
                    "type": "string"
                  },
                  {
                    "const": "rare",
                    "type": "string"
                  },
                  {
                    "const": "legendary",
                    "type": "string"
                  }
                ]
              },
              "class": {
                "description": "A base class (plant, wood, fibre, ...) or the id of a class an extension declares under one of them.",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  },
                  {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                ]
              },
              "family": {
                "pattern": "^[a-z0-9_-]+$",
                "maxLength": 24,
                "description": "A group inside the class, for example \"berry\" for every berry. Open: any lowercase word.",
                "type": "string"
              },
              "tags": {
                "maxItems": 8,
                "uniqueItems": true,
                "description": "Open words that describe it, for example \"sweet\" or \"night\".",
                "type": "array",
                "items": {
                  "pattern": "^[a-z0-9_-]+$",
                  "maxLength": 24,
                  "description": "A lowercase word.",
                  "type": "string"
                }
              },
              "tier": {
                "minimum": 1,
                "maximum": 20,
                "description": "How advanced it is, from 1. The rarity says how often it appears; the tier says how far up the ladder it is. A tool has the tier of its \"tool\".",
                "type": "integer"
              },
              "sprite": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
                "maxLength": 120,
                "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
                "type": "string"
              },
              "food": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "satiety"
                ],
                "properties": {
                  "satiety": {
                    "minimum": 0,
                    "maximum": 100,
                    "description": "Health points restored when eaten (the meter holds 100 at the start). 0 for a food that only hurts.",
                    "type": "integer"
                  },
                  "hurt": {
                    "minimum": 1,
                    "maximum": 100,
                    "description": "Health points it takes when eaten, at any hour: a bad fruit or a raw herb (G30).",
                    "type": "integer"
                  }
                }
              },
              "tool": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "kind",
                  "tier"
                ],
                "properties": {
                  "kind": {
                    "anyOf": [
                      {
                        "const": "basket",
                        "type": "string"
                      },
                      {
                        "const": "trowel",
                        "type": "string"
                      },
                      {
                        "const": "axe",
                        "type": "string"
                      },
                      {
                        "const": "staff",
                        "type": "string"
                      }
                    ]
                  },
                  "tier": {
                    "minimum": 1,
                    "maximum": 5,
                    "description": "Better tools work faster. The calculator clamps the total.",
                    "type": "integer"
                  },
                  "uses": {
                    "minimum": 1,
                    "maximum": 1000,
                    "description": "The tool wears out after this many uses. Left out, the tool lasts (DECISIONS.md, 2026-10-09: the crafting economy).",
                    "type": "integer"
                  }
                }
              },
              "fragment": {
                "additionalProperties": false,
                "description": "A found scrap that teaches a recipe.",
                "type": "object",
                "required": [
                  "unlocks"
                ],
                "properties": {
                  "unlocks": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                }
              },
              "wear": {
                "additionalProperties": false,
                "description": "Something the character wears (DECISIONS.md, 2026-10-09: the upgrade). A worn item stays in the bag.",
                "type": "object",
                "required": [
                  "slot"
                ],
                "properties": {
                  "slot": {
                    "description": "Where it is worn: head, top, legs (trousers), outfit (takes the top and the legs), feet, jewelry (two places) or hand (a tool).",
                    "anyOf": [
                      {
                        "const": "head",
                        "type": "string"
                      },
                      {
                        "const": "top",
                        "type": "string"
                      },
                      {
                        "const": "legs",
                        "type": "string"
                      },
                      {
                        "const": "outfit",
                        "type": "string"
                      },
                      {
                        "const": "feet",
                        "type": "string"
                      },
                      {
                        "const": "jewelry",
                        "type": "string"
                      },
                      {
                        "const": "hand",
                        "type": "string"
                      }
                    ]
                  },
                  "look": {
                    "description": "A look: worn on the look layer over the work clothes. It shows and counts for nothing, so it has no effects and no set.",
                    "type": "boolean"
                  },
                  "effects": {
                    "minItems": 1,
                    "maxItems": 2,
                    "description": "Small bonuses while it is worn on the work layer. Two at most, each effect once.",
                    "type": "array",
                    "items": {
                      "additionalProperties": false,
                      "type": "object",
                      "required": [
                        "effect",
                        "value"
                      ],
                      "properties": {
                        "effect": {
                          "description": "What a worn item helps: gathering, digging or crafting speed, the craft chance, or rare finds.",
                          "anyOf": [
                            {
                              "const": "gather_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "dig_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_chance_pct",
                              "type": "string"
                            },
                            {
                              "const": "rare_find_pct",
                              "type": "string"
                            }
                          ]
                        },
                        "value": {
                          "minimum": 1,
                          "maximum": 100,
                          "description": "Percent, at most the cap of the item's tier (params.wear_effect_max_pct).",
                          "type": "integer"
                        }
                      }
                    }
                  },
                  "set": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "A set of one creator: when every piece of it is worn, their effects grow by params.wear_set_bonus_pct.",
                    "type": "string"
                  }
                }
              },
              "premium_later": {
                "description": "Marks a look that may also be sold for premium currency once stage 6 brings it. Only a look item with no effect may carry it, and it stays obtainable in the game (DECISIONS.md, 2026-10-09).",
                "type": "boolean"
              }
            }
          }
        },
        "classes": {
          "maxItems": 10,
          "description": "Classes of your own, each under one base class.",
          "type": "array",
          "items": {
            "additionalProperties": false,
            "description": "A class of your own, declared under one base class. Every rule written for the base class holds for it.",
            "type": "object",
            "required": [
              "id",
              "name",
              "base"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "base": {
                "description": "plant (leaves, herbs, berries, fruit, roots, mushrooms), wood, fibre (reeds, grass, thread, cloth), stone, clay (clay, sand, pottery, brick), mineral (crystals, gems, salt, ore), metal (waits for its discovery), animal (feathers, wool, hide, bone), meal (cooked food), tool, garment (worn clothes), jewelry, relic (old things from the ruins).",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  }
                ]
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              }
            }
          }
        },
        "type": {
          "const": "treasure",
          "type": "string"
        },
        "dig": {
          "additionalProperties": false,
          "type": "object",
          "required": [
            "hint",
            "active_ms",
            "respawn_ms",
            "count",
            "level",
            "finds",
            "place"
          ],
          "properties": {
            "hint": {
              "minLength": 1,
              "maxLength": 240,
              "type": "string"
            },
            "active_ms": {
              "minimum": 0,
              "maximum": 3600000,
              "description": "Time the player is busy digging once.",
              "type": "integer"
            },
            "respawn_ms": {
              "minimum": 0,
              "maximum": 3600000,
              "description": "Time before the spot can be dug again.",
              "type": "integer"
            },
            "count": {
              "minimum": 1,
              "maximum": 8,
              "type": "integer"
            },
            "tool": {
              "anyOf": [
                {
                  "const": "basket",
                  "type": "string"
                },
                {
                  "const": "trowel",
                  "type": "string"
                },
                {
                  "const": "axe",
                  "type": "string"
                },
                {
                  "const": "staff",
                  "type": "string"
                }
              ],
              "description": "The tool the dig asks for and wears. Left out: the find is picked up by hand, with no timing window and no tool worn."
            },
            "level": {
              "minimum": 1,
              "maximum": 20,
              "description": "Digging level required.",
              "type": "integer"
            },
            "finds": {
              "minItems": 1,
              "maxItems": 8,
              "type": "array",
              "items": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "item",
                  "chance_pct",
                  "share_pct"
                ],
                "properties": {
                  "item": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  },
                  "chance_pct": {
                    "minimum": 1,
                    "maximum": 100,
                    "description": "Chance of this find per dig, at perfect timing. Chances of one spot sum to at most 100.",
                    "type": "integer"
                  },
                  "share_pct": {
                    "minimum": 1,
                    "maximum": 100,
                    "description": "Part of the dig cost this find carries. Shares sum to 100.",
                    "type": "integer"
                  }
                }
              }
            },
            "place": {
              "additionalProperties": false,
              "description": "An empty slot from the ruins map. Only one extension is active per slot.",
              "type": "object",
              "required": [
                "slot"
              ],
              "properties": {
                "slot": {
                  "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                  "maxLength": 80,
                  "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                  "type": "string"
                }
              }
            },
            "starter": {
              "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
              "maxLength": 80,
              "description": "A start's own spot: only a character of this starter sees it and digs it, once, and it always gives its one find. A gift of the start, so it prices nothing (it is no source in the value table).",
              "type": "string"
            }
          }
        }
      }
    },
    {
      "additionalProperties": false,
      "$id": "recipe",
      "type": "object",
      "required": [
        "format",
        "id",
        "title",
        "creator",
        "type",
        "recipe"
      ],
      "properties": {
        "$schema": {
          "type": "string"
        },
        "format": {
          "description": "Format version of this file.",
          "const": 1,
          "type": "number"
        },
        "id": {
          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
          "maxLength": 80,
          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
          "type": "string"
        },
        "title": {
          "minLength": 1,
          "maxLength": 40,
          "type": "string"
        },
        "creator": {
          "pattern": "^[a-z0-9_-]+$",
          "maxLength": 39,
          "description": "GitHub handle, lowercase.",
          "type": "string"
        },
        "description": {
          "minLength": 1,
          "maxLength": 240,
          "type": "string"
        },
        "ai_tools": {
          "maxItems": 8,
          "description": "AI tools used to make this file or its art. Required when any were used.",
          "type": "array",
          "items": {
            "minLength": 1,
            "maxLength": 60,
            "type": "string"
          }
        },
        "items": {
          "maxItems": 40,
          "type": "array",
          "items": {
            "additionalProperties": false,
            "type": "object",
            "required": [
              "id",
              "name",
              "kind",
              "rarity",
              "sprite"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              },
              "kind": {
                "anyOf": [
                  {
                    "const": "material",
                    "type": "string"
                  },
                  {
                    "const": "food",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "fragment",
                    "type": "string"
                  },
                  {
                    "const": "treasure",
                    "type": "string"
                  }
                ]
              },
              "rarity": {
                "description": "Declared rarity. The check compares it with the rarity computed from the data.",
                "anyOf": [
                  {
                    "const": "common",
                    "type": "string"
                  },
                  {
                    "const": "uncommon",
                    "type": "string"
                  },
                  {
                    "const": "rare",
                    "type": "string"
                  },
                  {
                    "const": "legendary",
                    "type": "string"
                  }
                ]
              },
              "class": {
                "description": "A base class (plant, wood, fibre, ...) or the id of a class an extension declares under one of them.",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  },
                  {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                ]
              },
              "family": {
                "pattern": "^[a-z0-9_-]+$",
                "maxLength": 24,
                "description": "A group inside the class, for example \"berry\" for every berry. Open: any lowercase word.",
                "type": "string"
              },
              "tags": {
                "maxItems": 8,
                "uniqueItems": true,
                "description": "Open words that describe it, for example \"sweet\" or \"night\".",
                "type": "array",
                "items": {
                  "pattern": "^[a-z0-9_-]+$",
                  "maxLength": 24,
                  "description": "A lowercase word.",
                  "type": "string"
                }
              },
              "tier": {
                "minimum": 1,
                "maximum": 20,
                "description": "How advanced it is, from 1. The rarity says how often it appears; the tier says how far up the ladder it is. A tool has the tier of its \"tool\".",
                "type": "integer"
              },
              "sprite": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
                "maxLength": 120,
                "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
                "type": "string"
              },
              "food": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "satiety"
                ],
                "properties": {
                  "satiety": {
                    "minimum": 0,
                    "maximum": 100,
                    "description": "Health points restored when eaten (the meter holds 100 at the start). 0 for a food that only hurts.",
                    "type": "integer"
                  },
                  "hurt": {
                    "minimum": 1,
                    "maximum": 100,
                    "description": "Health points it takes when eaten, at any hour: a bad fruit or a raw herb (G30).",
                    "type": "integer"
                  }
                }
              },
              "tool": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "kind",
                  "tier"
                ],
                "properties": {
                  "kind": {
                    "anyOf": [
                      {
                        "const": "basket",
                        "type": "string"
                      },
                      {
                        "const": "trowel",
                        "type": "string"
                      },
                      {
                        "const": "axe",
                        "type": "string"
                      },
                      {
                        "const": "staff",
                        "type": "string"
                      }
                    ]
                  },
                  "tier": {
                    "minimum": 1,
                    "maximum": 5,
                    "description": "Better tools work faster. The calculator clamps the total.",
                    "type": "integer"
                  },
                  "uses": {
                    "minimum": 1,
                    "maximum": 1000,
                    "description": "The tool wears out after this many uses. Left out, the tool lasts (DECISIONS.md, 2026-10-09: the crafting economy).",
                    "type": "integer"
                  }
                }
              },
              "fragment": {
                "additionalProperties": false,
                "description": "A found scrap that teaches a recipe.",
                "type": "object",
                "required": [
                  "unlocks"
                ],
                "properties": {
                  "unlocks": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                }
              },
              "wear": {
                "additionalProperties": false,
                "description": "Something the character wears (DECISIONS.md, 2026-10-09: the upgrade). A worn item stays in the bag.",
                "type": "object",
                "required": [
                  "slot"
                ],
                "properties": {
                  "slot": {
                    "description": "Where it is worn: head, top, legs (trousers), outfit (takes the top and the legs), feet, jewelry (two places) or hand (a tool).",
                    "anyOf": [
                      {
                        "const": "head",
                        "type": "string"
                      },
                      {
                        "const": "top",
                        "type": "string"
                      },
                      {
                        "const": "legs",
                        "type": "string"
                      },
                      {
                        "const": "outfit",
                        "type": "string"
                      },
                      {
                        "const": "feet",
                        "type": "string"
                      },
                      {
                        "const": "jewelry",
                        "type": "string"
                      },
                      {
                        "const": "hand",
                        "type": "string"
                      }
                    ]
                  },
                  "look": {
                    "description": "A look: worn on the look layer over the work clothes. It shows and counts for nothing, so it has no effects and no set.",
                    "type": "boolean"
                  },
                  "effects": {
                    "minItems": 1,
                    "maxItems": 2,
                    "description": "Small bonuses while it is worn on the work layer. Two at most, each effect once.",
                    "type": "array",
                    "items": {
                      "additionalProperties": false,
                      "type": "object",
                      "required": [
                        "effect",
                        "value"
                      ],
                      "properties": {
                        "effect": {
                          "description": "What a worn item helps: gathering, digging or crafting speed, the craft chance, or rare finds.",
                          "anyOf": [
                            {
                              "const": "gather_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "dig_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_chance_pct",
                              "type": "string"
                            },
                            {
                              "const": "rare_find_pct",
                              "type": "string"
                            }
                          ]
                        },
                        "value": {
                          "minimum": 1,
                          "maximum": 100,
                          "description": "Percent, at most the cap of the item's tier (params.wear_effect_max_pct).",
                          "type": "integer"
                        }
                      }
                    }
                  },
                  "set": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "A set of one creator: when every piece of it is worn, their effects grow by params.wear_set_bonus_pct.",
                    "type": "string"
                  }
                }
              },
              "premium_later": {
                "description": "Marks a look that may also be sold for premium currency once stage 6 brings it. Only a look item with no effect may carry it, and it stays obtainable in the game (DECISIONS.md, 2026-10-09).",
                "type": "boolean"
              }
            }
          }
        },
        "classes": {
          "maxItems": 10,
          "description": "Classes of your own, each under one base class.",
          "type": "array",
          "items": {
            "additionalProperties": false,
            "description": "A class of your own, declared under one base class. Every rule written for the base class holds for it.",
            "type": "object",
            "required": [
              "id",
              "name",
              "base"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "base": {
                "description": "plant (leaves, herbs, berries, fruit, roots, mushrooms), wood, fibre (reeds, grass, thread, cloth), stone, clay (clay, sand, pottery, brick), mineral (crystals, gems, salt, ore), metal (waits for its discovery), animal (feathers, wool, hide, bone), meal (cooked food), tool, garment (worn clothes), jewelry, relic (old things from the ruins).",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  }
                ]
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              }
            }
          }
        },
        "type": {
          "const": "recipe",
          "type": "string"
        },
        "recipe": {
          "additionalProperties": false,
          "type": "object",
          "required": [
            "station",
            "active_ms",
            "level",
            "inputs",
            "outputs",
            "known"
          ],
          "properties": {
            "station": {
              "anyOf": [
                {
                  "const": "fire",
                  "type": "string"
                },
                {
                  "const": "workshop",
                  "type": "string"
                }
              ]
            },
            "active_ms": {
              "minimum": 0,
              "maximum": 3600000,
              "description": "Time the player is busy making it once.",
              "type": "integer"
            },
            "level": {
              "minimum": 1,
              "maximum": 20,
              "description": "Level required in the profession that gates the recipe. It sits inside the level band of the recipe's tier.",
              "type": "integer"
            },
            "profession": {
              "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
              "maxLength": 80,
              "description": "The profession that gates this recipe and that it trains. Left out: the profession that works its station.",
              "type": "string"
            },
            "inputs": {
              "minItems": 1,
              "maxItems": 6,
              "type": "array",
              "items": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "item",
                  "qty"
                ],
                "properties": {
                  "item": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  },
                  "qty": {
                    "minimum": 1,
                    "maximum": 999,
                    "type": "integer"
                  }
                }
              }
            },
            "outputs": {
              "minItems": 1,
              "maxItems": 4,
              "type": "array",
              "items": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "item",
                  "qty",
                  "share_pct"
                ],
                "properties": {
                  "item": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  },
                  "qty": {
                    "minimum": 1,
                    "maximum": 999,
                    "description": "Units produced per execution at perfect timing.",
                    "type": "integer"
                  },
                  "share_pct": {
                    "minimum": 1,
                    "maximum": 100,
                    "description": "Part of the activity cost this output carries. Shares of one activity sum to 100.",
                    "type": "integer"
                  }
                }
              }
            },
            "miss": {
              "additionalProperties": false,
              "description": "What a missed craft leaves (G40): part of the inputs and nothing else, worth less than a success. Left out: the default share of the inputs. When the share leaves nothing, one unit of the most valuable input comes back.",
              "type": "object",
              "properties": {
                "keep_pct": {
                  "minimum": 0,
                  "maximum": 90,
                  "description": "Part of each input a miss keeps, rounded down, at most 90 percent. Left out: params.craft_miss_keep_pct.",
                  "type": "integer"
                }
              }
            },
            "known": {
              "description": "\"start\": every player knows it. \"found\": learned from a recipe scrap found by digging, or from a quest.",
              "anyOf": [
                {
                  "const": "start",
                  "type": "string"
                },
                {
                  "const": "found",
                  "type": "string"
                }
              ]
            }
          }
        }
      }
    },
    {
      "additionalProperties": false,
      "$id": "template",
      "type": "object",
      "required": [
        "format",
        "id",
        "title",
        "creator",
        "type",
        "template"
      ],
      "properties": {
        "$schema": {
          "type": "string"
        },
        "format": {
          "description": "Format version of this file.",
          "const": 1,
          "type": "number"
        },
        "id": {
          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
          "maxLength": 80,
          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
          "type": "string"
        },
        "title": {
          "minLength": 1,
          "maxLength": 40,
          "type": "string"
        },
        "creator": {
          "pattern": "^[a-z0-9_-]+$",
          "maxLength": 39,
          "description": "GitHub handle, lowercase.",
          "type": "string"
        },
        "description": {
          "minLength": 1,
          "maxLength": 240,
          "type": "string"
        },
        "ai_tools": {
          "maxItems": 8,
          "description": "AI tools used to make this file or its art. Required when any were used.",
          "type": "array",
          "items": {
            "minLength": 1,
            "maxLength": 60,
            "type": "string"
          }
        },
        "items": {
          "maxItems": 40,
          "type": "array",
          "items": {
            "additionalProperties": false,
            "type": "object",
            "required": [
              "id",
              "name",
              "kind",
              "rarity",
              "sprite"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              },
              "kind": {
                "anyOf": [
                  {
                    "const": "material",
                    "type": "string"
                  },
                  {
                    "const": "food",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "fragment",
                    "type": "string"
                  },
                  {
                    "const": "treasure",
                    "type": "string"
                  }
                ]
              },
              "rarity": {
                "description": "Declared rarity. The check compares it with the rarity computed from the data.",
                "anyOf": [
                  {
                    "const": "common",
                    "type": "string"
                  },
                  {
                    "const": "uncommon",
                    "type": "string"
                  },
                  {
                    "const": "rare",
                    "type": "string"
                  },
                  {
                    "const": "legendary",
                    "type": "string"
                  }
                ]
              },
              "class": {
                "description": "A base class (plant, wood, fibre, ...) or the id of a class an extension declares under one of them.",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  },
                  {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                ]
              },
              "family": {
                "pattern": "^[a-z0-9_-]+$",
                "maxLength": 24,
                "description": "A group inside the class, for example \"berry\" for every berry. Open: any lowercase word.",
                "type": "string"
              },
              "tags": {
                "maxItems": 8,
                "uniqueItems": true,
                "description": "Open words that describe it, for example \"sweet\" or \"night\".",
                "type": "array",
                "items": {
                  "pattern": "^[a-z0-9_-]+$",
                  "maxLength": 24,
                  "description": "A lowercase word.",
                  "type": "string"
                }
              },
              "tier": {
                "minimum": 1,
                "maximum": 20,
                "description": "How advanced it is, from 1. The rarity says how often it appears; the tier says how far up the ladder it is. A tool has the tier of its \"tool\".",
                "type": "integer"
              },
              "sprite": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
                "maxLength": 120,
                "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
                "type": "string"
              },
              "food": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "satiety"
                ],
                "properties": {
                  "satiety": {
                    "minimum": 0,
                    "maximum": 100,
                    "description": "Health points restored when eaten (the meter holds 100 at the start). 0 for a food that only hurts.",
                    "type": "integer"
                  },
                  "hurt": {
                    "minimum": 1,
                    "maximum": 100,
                    "description": "Health points it takes when eaten, at any hour: a bad fruit or a raw herb (G30).",
                    "type": "integer"
                  }
                }
              },
              "tool": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "kind",
                  "tier"
                ],
                "properties": {
                  "kind": {
                    "anyOf": [
                      {
                        "const": "basket",
                        "type": "string"
                      },
                      {
                        "const": "trowel",
                        "type": "string"
                      },
                      {
                        "const": "axe",
                        "type": "string"
                      },
                      {
                        "const": "staff",
                        "type": "string"
                      }
                    ]
                  },
                  "tier": {
                    "minimum": 1,
                    "maximum": 5,
                    "description": "Better tools work faster. The calculator clamps the total.",
                    "type": "integer"
                  },
                  "uses": {
                    "minimum": 1,
                    "maximum": 1000,
                    "description": "The tool wears out after this many uses. Left out, the tool lasts (DECISIONS.md, 2026-10-09: the crafting economy).",
                    "type": "integer"
                  }
                }
              },
              "fragment": {
                "additionalProperties": false,
                "description": "A found scrap that teaches a recipe.",
                "type": "object",
                "required": [
                  "unlocks"
                ],
                "properties": {
                  "unlocks": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                }
              },
              "wear": {
                "additionalProperties": false,
                "description": "Something the character wears (DECISIONS.md, 2026-10-09: the upgrade). A worn item stays in the bag.",
                "type": "object",
                "required": [
                  "slot"
                ],
                "properties": {
                  "slot": {
                    "description": "Where it is worn: head, top, legs (trousers), outfit (takes the top and the legs), feet, jewelry (two places) or hand (a tool).",
                    "anyOf": [
                      {
                        "const": "head",
                        "type": "string"
                      },
                      {
                        "const": "top",
                        "type": "string"
                      },
                      {
                        "const": "legs",
                        "type": "string"
                      },
                      {
                        "const": "outfit",
                        "type": "string"
                      },
                      {
                        "const": "feet",
                        "type": "string"
                      },
                      {
                        "const": "jewelry",
                        "type": "string"
                      },
                      {
                        "const": "hand",
                        "type": "string"
                      }
                    ]
                  },
                  "look": {
                    "description": "A look: worn on the look layer over the work clothes. It shows and counts for nothing, so it has no effects and no set.",
                    "type": "boolean"
                  },
                  "effects": {
                    "minItems": 1,
                    "maxItems": 2,
                    "description": "Small bonuses while it is worn on the work layer. Two at most, each effect once.",
                    "type": "array",
                    "items": {
                      "additionalProperties": false,
                      "type": "object",
                      "required": [
                        "effect",
                        "value"
                      ],
                      "properties": {
                        "effect": {
                          "description": "What a worn item helps: gathering, digging or crafting speed, the craft chance, or rare finds.",
                          "anyOf": [
                            {
                              "const": "gather_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "dig_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_chance_pct",
                              "type": "string"
                            },
                            {
                              "const": "rare_find_pct",
                              "type": "string"
                            }
                          ]
                        },
                        "value": {
                          "minimum": 1,
                          "maximum": 100,
                          "description": "Percent, at most the cap of the item's tier (params.wear_effect_max_pct).",
                          "type": "integer"
                        }
                      }
                    }
                  },
                  "set": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "A set of one creator: when every piece of it is worn, their effects grow by params.wear_set_bonus_pct.",
                    "type": "string"
                  }
                }
              },
              "premium_later": {
                "description": "Marks a look that may also be sold for premium currency once stage 6 brings it. Only a look item with no effect may carry it, and it stays obtainable in the game (DECISIONS.md, 2026-10-09).",
                "type": "boolean"
              }
            }
          }
        },
        "classes": {
          "maxItems": 10,
          "description": "Classes of your own, each under one base class.",
          "type": "array",
          "items": {
            "additionalProperties": false,
            "description": "A class of your own, declared under one base class. Every rule written for the base class holds for it.",
            "type": "object",
            "required": [
              "id",
              "name",
              "base"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "base": {
                "description": "plant (leaves, herbs, berries, fruit, roots, mushrooms), wood, fibre (reeds, grass, thread, cloth), stone, clay (clay, sand, pottery, brick), mineral (crystals, gems, salt, ore), metal (waits for its discovery), animal (feathers, wool, hide, bone), meal (cooked food), tool, garment (worn clothes), jewelry, relic (old things from the ruins).",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  }
                ]
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              }
            }
          }
        },
        "type": {
          "const": "template",
          "type": "string"
        },
        "template": {
          "additionalProperties": false,
          "description": "A recipe template: the assembler turns it into one recipe for every combination of items that fit its class inputs, in a fixed order and never more than params.template_max_recipes. Every recipe it makes is known from the start.",
          "type": "object",
          "required": [
            "station",
            "active_ms",
            "level",
            "inputs",
            "outputs"
          ],
          "properties": {
            "station": {
              "anyOf": [
                {
                  "const": "fire",
                  "type": "string"
                },
                {
                  "const": "workshop",
                  "type": "string"
                }
              ]
            },
            "active_ms": {
              "minimum": 0,
              "maximum": 3600000,
              "description": "Time the player is busy making it once.",
              "type": "integer"
            },
            "level": {
              "minimum": 1,
              "maximum": 20,
              "description": "Level required in the profession that gates the recipe. It sits inside the level band of the recipe's tier.",
              "type": "integer"
            },
            "profession": {
              "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
              "maxLength": 80,
              "description": "The profession that gates this recipe and that it trains. Left out: the profession that works its station.",
              "type": "string"
            },
            "inputs": {
              "minItems": 1,
              "maxItems": 6,
              "description": "Items by id, or by class and lowest tier. At least one input names a class.",
              "type": "array",
              "items": {
                "anyOf": [
                  {
                    "additionalProperties": false,
                    "type": "object",
                    "required": [
                      "item",
                      "qty"
                    ],
                    "properties": {
                      "item": {
                        "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                        "maxLength": 80,
                        "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                        "type": "string"
                      },
                      "qty": {
                        "minimum": 1,
                        "maximum": 999,
                        "type": "integer"
                      }
                    }
                  },
                  {
                    "additionalProperties": false,
                    "description": "Any item of this class (and family, when named) at this tier or above. A base class also takes every class declared under it.",
                    "type": "object",
                    "required": [
                      "class",
                      "min_tier",
                      "qty"
                    ],
                    "properties": {
                      "class": {
                        "description": "A base class (plant, wood, fibre, ...) or the id of a class an extension declares under one of them.",
                        "anyOf": [
                          {
                            "const": "plant",
                            "type": "string"
                          },
                          {
                            "const": "wood",
                            "type": "string"
                          },
                          {
                            "const": "fibre",
                            "type": "string"
                          },
                          {
                            "const": "stone",
                            "type": "string"
                          },
                          {
                            "const": "clay",
                            "type": "string"
                          },
                          {
                            "const": "mineral",
                            "type": "string"
                          },
                          {
                            "const": "metal",
                            "type": "string"
                          },
                          {
                            "const": "animal",
                            "type": "string"
                          },
                          {
                            "const": "meal",
                            "type": "string"
                          },
                          {
                            "const": "tool",
                            "type": "string"
                          },
                          {
                            "const": "garment",
                            "type": "string"
                          },
                          {
                            "const": "jewelry",
                            "type": "string"
                          },
                          {
                            "const": "relic",
                            "type": "string"
                          },
                          {
                            "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                            "maxLength": 80,
                            "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                            "type": "string"
                          }
                        ]
                      },
                      "family": {
                        "pattern": "^[a-z0-9_-]+$",
                        "maxLength": 24,
                        "description": "Only items of this family.",
                        "type": "string"
                      },
                      "min_tier": {
                        "minimum": 1,
                        "maximum": 20,
                        "description": "The lowest tier that fits.",
                        "type": "integer"
                      },
                      "qty": {
                        "minimum": 1,
                        "maximum": 999,
                        "type": "integer"
                      }
                    }
                  }
                ]
              }
            },
            "outputs": {
              "minItems": 1,
              "maxItems": 4,
              "type": "array",
              "items": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "item",
                  "qty",
                  "share_pct"
                ],
                "properties": {
                  "item": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  },
                  "qty": {
                    "minimum": 1,
                    "maximum": 999,
                    "description": "Units produced per execution at perfect timing.",
                    "type": "integer"
                  },
                  "share_pct": {
                    "minimum": 1,
                    "maximum": 100,
                    "description": "Part of the activity cost this output carries. Shares of one activity sum to 100.",
                    "type": "integer"
                  }
                }
              }
            },
            "miss": {
              "additionalProperties": false,
              "description": "What a missed craft leaves (G40): part of the inputs and nothing else, worth less than a success. Left out: the default share of the inputs. When the share leaves nothing, one unit of the most valuable input comes back.",
              "type": "object",
              "properties": {
                "keep_pct": {
                  "minimum": 0,
                  "maximum": 90,
                  "description": "Part of each input a miss keeps, rounded down, at most 90 percent. Left out: params.craft_miss_keep_pct.",
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    {
      "additionalProperties": false,
      "$id": "npc",
      "type": "object",
      "required": [
        "format",
        "id",
        "title",
        "creator",
        "type",
        "npc"
      ],
      "properties": {
        "$schema": {
          "type": "string"
        },
        "format": {
          "description": "Format version of this file.",
          "const": 1,
          "type": "number"
        },
        "id": {
          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
          "maxLength": 80,
          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
          "type": "string"
        },
        "title": {
          "minLength": 1,
          "maxLength": 40,
          "type": "string"
        },
        "creator": {
          "pattern": "^[a-z0-9_-]+$",
          "maxLength": 39,
          "description": "GitHub handle, lowercase.",
          "type": "string"
        },
        "description": {
          "minLength": 1,
          "maxLength": 240,
          "type": "string"
        },
        "ai_tools": {
          "maxItems": 8,
          "description": "AI tools used to make this file or its art. Required when any were used.",
          "type": "array",
          "items": {
            "minLength": 1,
            "maxLength": 60,
            "type": "string"
          }
        },
        "items": {
          "maxItems": 40,
          "type": "array",
          "items": {
            "additionalProperties": false,
            "type": "object",
            "required": [
              "id",
              "name",
              "kind",
              "rarity",
              "sprite"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              },
              "kind": {
                "anyOf": [
                  {
                    "const": "material",
                    "type": "string"
                  },
                  {
                    "const": "food",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "fragment",
                    "type": "string"
                  },
                  {
                    "const": "treasure",
                    "type": "string"
                  }
                ]
              },
              "rarity": {
                "description": "Declared rarity. The check compares it with the rarity computed from the data.",
                "anyOf": [
                  {
                    "const": "common",
                    "type": "string"
                  },
                  {
                    "const": "uncommon",
                    "type": "string"
                  },
                  {
                    "const": "rare",
                    "type": "string"
                  },
                  {
                    "const": "legendary",
                    "type": "string"
                  }
                ]
              },
              "class": {
                "description": "A base class (plant, wood, fibre, ...) or the id of a class an extension declares under one of them.",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  },
                  {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                ]
              },
              "family": {
                "pattern": "^[a-z0-9_-]+$",
                "maxLength": 24,
                "description": "A group inside the class, for example \"berry\" for every berry. Open: any lowercase word.",
                "type": "string"
              },
              "tags": {
                "maxItems": 8,
                "uniqueItems": true,
                "description": "Open words that describe it, for example \"sweet\" or \"night\".",
                "type": "array",
                "items": {
                  "pattern": "^[a-z0-9_-]+$",
                  "maxLength": 24,
                  "description": "A lowercase word.",
                  "type": "string"
                }
              },
              "tier": {
                "minimum": 1,
                "maximum": 20,
                "description": "How advanced it is, from 1. The rarity says how often it appears; the tier says how far up the ladder it is. A tool has the tier of its \"tool\".",
                "type": "integer"
              },
              "sprite": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
                "maxLength": 120,
                "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
                "type": "string"
              },
              "food": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "satiety"
                ],
                "properties": {
                  "satiety": {
                    "minimum": 0,
                    "maximum": 100,
                    "description": "Health points restored when eaten (the meter holds 100 at the start). 0 for a food that only hurts.",
                    "type": "integer"
                  },
                  "hurt": {
                    "minimum": 1,
                    "maximum": 100,
                    "description": "Health points it takes when eaten, at any hour: a bad fruit or a raw herb (G30).",
                    "type": "integer"
                  }
                }
              },
              "tool": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "kind",
                  "tier"
                ],
                "properties": {
                  "kind": {
                    "anyOf": [
                      {
                        "const": "basket",
                        "type": "string"
                      },
                      {
                        "const": "trowel",
                        "type": "string"
                      },
                      {
                        "const": "axe",
                        "type": "string"
                      },
                      {
                        "const": "staff",
                        "type": "string"
                      }
                    ]
                  },
                  "tier": {
                    "minimum": 1,
                    "maximum": 5,
                    "description": "Better tools work faster. The calculator clamps the total.",
                    "type": "integer"
                  },
                  "uses": {
                    "minimum": 1,
                    "maximum": 1000,
                    "description": "The tool wears out after this many uses. Left out, the tool lasts (DECISIONS.md, 2026-10-09: the crafting economy).",
                    "type": "integer"
                  }
                }
              },
              "fragment": {
                "additionalProperties": false,
                "description": "A found scrap that teaches a recipe.",
                "type": "object",
                "required": [
                  "unlocks"
                ],
                "properties": {
                  "unlocks": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                }
              },
              "wear": {
                "additionalProperties": false,
                "description": "Something the character wears (DECISIONS.md, 2026-10-09: the upgrade). A worn item stays in the bag.",
                "type": "object",
                "required": [
                  "slot"
                ],
                "properties": {
                  "slot": {
                    "description": "Where it is worn: head, top, legs (trousers), outfit (takes the top and the legs), feet, jewelry (two places) or hand (a tool).",
                    "anyOf": [
                      {
                        "const": "head",
                        "type": "string"
                      },
                      {
                        "const": "top",
                        "type": "string"
                      },
                      {
                        "const": "legs",
                        "type": "string"
                      },
                      {
                        "const": "outfit",
                        "type": "string"
                      },
                      {
                        "const": "feet",
                        "type": "string"
                      },
                      {
                        "const": "jewelry",
                        "type": "string"
                      },
                      {
                        "const": "hand",
                        "type": "string"
                      }
                    ]
                  },
                  "look": {
                    "description": "A look: worn on the look layer over the work clothes. It shows and counts for nothing, so it has no effects and no set.",
                    "type": "boolean"
                  },
                  "effects": {
                    "minItems": 1,
                    "maxItems": 2,
                    "description": "Small bonuses while it is worn on the work layer. Two at most, each effect once.",
                    "type": "array",
                    "items": {
                      "additionalProperties": false,
                      "type": "object",
                      "required": [
                        "effect",
                        "value"
                      ],
                      "properties": {
                        "effect": {
                          "description": "What a worn item helps: gathering, digging or crafting speed, the craft chance, or rare finds.",
                          "anyOf": [
                            {
                              "const": "gather_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "dig_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_chance_pct",
                              "type": "string"
                            },
                            {
                              "const": "rare_find_pct",
                              "type": "string"
                            }
                          ]
                        },
                        "value": {
                          "minimum": 1,
                          "maximum": 100,
                          "description": "Percent, at most the cap of the item's tier (params.wear_effect_max_pct).",
                          "type": "integer"
                        }
                      }
                    }
                  },
                  "set": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "A set of one creator: when every piece of it is worn, their effects grow by params.wear_set_bonus_pct.",
                    "type": "string"
                  }
                }
              },
              "premium_later": {
                "description": "Marks a look that may also be sold for premium currency once stage 6 brings it. Only a look item with no effect may carry it, and it stays obtainable in the game (DECISIONS.md, 2026-10-09).",
                "type": "boolean"
              }
            }
          }
        },
        "classes": {
          "maxItems": 10,
          "description": "Classes of your own, each under one base class.",
          "type": "array",
          "items": {
            "additionalProperties": false,
            "description": "A class of your own, declared under one base class. Every rule written for the base class holds for it.",
            "type": "object",
            "required": [
              "id",
              "name",
              "base"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "base": {
                "description": "plant (leaves, herbs, berries, fruit, roots, mushrooms), wood, fibre (reeds, grass, thread, cloth), stone, clay (clay, sand, pottery, brick), mineral (crystals, gems, salt, ore), metal (waits for its discovery), animal (feathers, wool, hide, bone), meal (cooked food), tool, garment (worn clothes), jewelry, relic (old things from the ruins).",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  }
                ]
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              }
            }
          }
        },
        "type": {
          "const": "npc",
          "type": "string"
        },
        "npc": {
          "additionalProperties": false,
          "type": "object",
          "required": [
            "name",
            "sprite",
            "place",
            "dialogue"
          ],
          "properties": {
            "name": {
              "minLength": 1,
              "maxLength": 40,
              "type": "string"
            },
            "sprite": {
              "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
              "maxLength": 120,
              "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
              "type": "string"
            },
            "place": {
              "additionalProperties": false,
              "description": "An empty slot from the ruins map. Only one extension is active per slot.",
              "type": "object",
              "required": [
                "slot"
              ],
              "properties": {
                "slot": {
                  "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                  "maxLength": 80,
                  "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                  "type": "string"
                }
              }
            },
            "dialogue": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "stranger"
              ],
              "properties": {
                "stranger": {
                  "minItems": 1,
                  "maxItems": 6,
                  "type": "array",
                  "items": {
                    "minLength": 1,
                    "maxLength": 240,
                    "type": "string"
                  }
                },
                "acquaintance": {
                  "minItems": 1,
                  "maxItems": 6,
                  "type": "array",
                  "items": {
                    "minLength": 1,
                    "maxLength": 240,
                    "type": "string"
                  }
                },
                "friend": {
                  "minItems": 1,
                  "maxItems": 6,
                  "type": "array",
                  "items": {
                    "minLength": 1,
                    "maxLength": 240,
                    "type": "string"
                  }
                },
                "family": {
                  "minItems": 1,
                  "maxItems": 6,
                  "type": "array",
                  "items": {
                    "minLength": 1,
                    "maxLength": 240,
                    "type": "string"
                  }
                },
                "first": {
                  "minItems": 1,
                  "maxItems": 8,
                  "description": "Said the first time the player talks to them, before anything else.",
                  "type": "array",
                  "items": {
                    "minLength": 1,
                    "maxLength": 240,
                    "type": "string"
                  }
                }
              }
            },
            "remarks": {
              "maxItems": 16,
              "type": "array",
              "items": {
                "additionalProperties": false,
                "description": "A standing line that waits for a change in the world and is said once, in place of the standing line. Of the remarks that hold, the highest priority wins, then the one whose condition names the most, then the first in the file.",
                "type": "object",
                "required": [
                  "when",
                  "say"
                ],
                "properties": {
                  "when": {
                    "additionalProperties": false,
                    "minProperties": 1,
                    "description": "Holds when every condition it names holds.",
                    "type": "object",
                    "properties": {
                      "done": {
                        "minItems": 1,
                        "maxItems": 4,
                        "description": "Quests the player has finished.",
                        "type": "array",
                        "items": {
                          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                          "maxLength": 80,
                          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                          "type": "string"
                        }
                      },
                      "active": {
                        "minItems": 1,
                        "maxItems": 4,
                        "description": "Quests the player is on now.",
                        "type": "array",
                        "items": {
                          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                          "maxLength": 80,
                          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                          "type": "string"
                        }
                      },
                      "not_done": {
                        "minItems": 1,
                        "maxItems": 4,
                        "description": "Quests the player has not finished yet, on them or not.",
                        "type": "array",
                        "items": {
                          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                          "maxLength": 80,
                          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                          "type": "string"
                        }
                      },
                      "restored": {
                        "minItems": 1,
                        "maxItems": 4,
                        "description": "Places the player has mended.",
                        "type": "array",
                        "items": {
                          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                          "maxLength": 80,
                          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                          "type": "string"
                        }
                      },
                      "built": {
                        "minItems": 1,
                        "maxItems": 4,
                        "description": "Camp parts that stand, themselves or under an upgrade.",
                        "type": "array",
                        "items": {
                          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                          "maxLength": 80,
                          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                          "type": "string"
                        }
                      },
                      "has": {
                        "minItems": 1,
                        "maxItems": 4,
                        "description": "Items with at least one in the bag.",
                        "type": "array",
                        "items": {
                          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                          "maxLength": 80,
                          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                          "type": "string"
                        }
                      },
                      "visited": {
                        "minItems": 1,
                        "maxItems": 4,
                        "description": "Map slots the player has stood in.",
                        "type": "array",
                        "items": {
                          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                          "maxLength": 80,
                          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                          "type": "string"
                        }
                      },
                      "time": {
                        "description": "By day (05:00 to 20:00) or by night.",
                        "anyOf": [
                          {
                            "const": "day",
                            "type": "string"
                          },
                          {
                            "const": "night",
                            "type": "string"
                          }
                        ]
                      }
                    }
                  },
                  "say": {
                    "minItems": 1,
                    "maxItems": 2,
                    "description": "One box, two at most (G21).",
                    "type": "array",
                    "items": {
                      "minLength": 1,
                      "maxLength": 240,
                      "type": "string"
                    }
                  },
                  "priority": {
                    "minimum": 0,
                    "maximum": 9,
                    "description": "Higher is said first when more than one remark holds. Left out, 0.",
                    "type": "integer"
                  }
                }
              }
            },
            "topics": {
              "maxItems": 8,
              "description": "Things the player can ask about: always, or once the topic's `when` holds (G21). The menu shows four at most, the ones not yet asked first.",
              "type": "array",
              "items": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "ask",
                  "lines"
                ],
                "properties": {
                  "ask": {
                    "minLength": 1,
                    "maxLength": 40,
                    "description": "The question the player can pick, for example \"About the mist\".",
                    "type": "string"
                  },
                  "lines": {
                    "minItems": 1,
                    "maxItems": 6,
                    "type": "array",
                    "items": {
                      "minLength": 1,
                      "maxLength": 240,
                      "type": "string"
                    }
                  },
                  "when": {
                    "additionalProperties": false,
                    "minProperties": 1,
                    "description": "Holds when every condition it names holds.",
                    "type": "object",
                    "properties": {
                      "done": {
                        "minItems": 1,
                        "maxItems": 4,
                        "description": "Quests the player has finished.",
                        "type": "array",
                        "items": {
                          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                          "maxLength": 80,
                          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                          "type": "string"
                        }
                      },
                      "active": {
                        "minItems": 1,
                        "maxItems": 4,
                        "description": "Quests the player is on now.",
                        "type": "array",
                        "items": {
                          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                          "maxLength": 80,
                          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                          "type": "string"
                        }
                      },
                      "not_done": {
                        "minItems": 1,
                        "maxItems": 4,
                        "description": "Quests the player has not finished yet, on them or not.",
                        "type": "array",
                        "items": {
                          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                          "maxLength": 80,
                          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                          "type": "string"
                        }
                      },
                      "restored": {
                        "minItems": 1,
                        "maxItems": 4,
                        "description": "Places the player has mended.",
                        "type": "array",
                        "items": {
                          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                          "maxLength": 80,
                          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                          "type": "string"
                        }
                      },
                      "built": {
                        "minItems": 1,
                        "maxItems": 4,
                        "description": "Camp parts that stand, themselves or under an upgrade.",
                        "type": "array",
                        "items": {
                          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                          "maxLength": 80,
                          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                          "type": "string"
                        }
                      },
                      "has": {
                        "minItems": 1,
                        "maxItems": 4,
                        "description": "Items with at least one in the bag.",
                        "type": "array",
                        "items": {
                          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                          "maxLength": 80,
                          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                          "type": "string"
                        }
                      },
                      "visited": {
                        "minItems": 1,
                        "maxItems": 4,
                        "description": "Map slots the player has stood in.",
                        "type": "array",
                        "items": {
                          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                          "maxLength": 80,
                          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                          "type": "string"
                        }
                      },
                      "time": {
                        "description": "By day (05:00 to 20:00) or by night.",
                        "anyOf": [
                          {
                            "const": "day",
                            "type": "string"
                          },
                          {
                            "const": "night",
                            "type": "string"
                          }
                        ]
                      }
                    }
                  }
                }
              }
            },
            "shop": {
              "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
              "maxLength": 80,
              "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
              "type": "string"
            }
          }
        }
      }
    },
    {
      "additionalProperties": false,
      "$id": "quest",
      "type": "object",
      "required": [
        "format",
        "id",
        "title",
        "creator",
        "type",
        "quest"
      ],
      "properties": {
        "$schema": {
          "type": "string"
        },
        "format": {
          "description": "Format version of this file.",
          "const": 1,
          "type": "number"
        },
        "id": {
          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
          "maxLength": 80,
          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
          "type": "string"
        },
        "title": {
          "minLength": 1,
          "maxLength": 40,
          "type": "string"
        },
        "creator": {
          "pattern": "^[a-z0-9_-]+$",
          "maxLength": 39,
          "description": "GitHub handle, lowercase.",
          "type": "string"
        },
        "description": {
          "minLength": 1,
          "maxLength": 240,
          "type": "string"
        },
        "ai_tools": {
          "maxItems": 8,
          "description": "AI tools used to make this file or its art. Required when any were used.",
          "type": "array",
          "items": {
            "minLength": 1,
            "maxLength": 60,
            "type": "string"
          }
        },
        "items": {
          "maxItems": 40,
          "type": "array",
          "items": {
            "additionalProperties": false,
            "type": "object",
            "required": [
              "id",
              "name",
              "kind",
              "rarity",
              "sprite"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              },
              "kind": {
                "anyOf": [
                  {
                    "const": "material",
                    "type": "string"
                  },
                  {
                    "const": "food",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "fragment",
                    "type": "string"
                  },
                  {
                    "const": "treasure",
                    "type": "string"
                  }
                ]
              },
              "rarity": {
                "description": "Declared rarity. The check compares it with the rarity computed from the data.",
                "anyOf": [
                  {
                    "const": "common",
                    "type": "string"
                  },
                  {
                    "const": "uncommon",
                    "type": "string"
                  },
                  {
                    "const": "rare",
                    "type": "string"
                  },
                  {
                    "const": "legendary",
                    "type": "string"
                  }
                ]
              },
              "class": {
                "description": "A base class (plant, wood, fibre, ...) or the id of a class an extension declares under one of them.",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  },
                  {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                ]
              },
              "family": {
                "pattern": "^[a-z0-9_-]+$",
                "maxLength": 24,
                "description": "A group inside the class, for example \"berry\" for every berry. Open: any lowercase word.",
                "type": "string"
              },
              "tags": {
                "maxItems": 8,
                "uniqueItems": true,
                "description": "Open words that describe it, for example \"sweet\" or \"night\".",
                "type": "array",
                "items": {
                  "pattern": "^[a-z0-9_-]+$",
                  "maxLength": 24,
                  "description": "A lowercase word.",
                  "type": "string"
                }
              },
              "tier": {
                "minimum": 1,
                "maximum": 20,
                "description": "How advanced it is, from 1. The rarity says how often it appears; the tier says how far up the ladder it is. A tool has the tier of its \"tool\".",
                "type": "integer"
              },
              "sprite": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
                "maxLength": 120,
                "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
                "type": "string"
              },
              "food": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "satiety"
                ],
                "properties": {
                  "satiety": {
                    "minimum": 0,
                    "maximum": 100,
                    "description": "Health points restored when eaten (the meter holds 100 at the start). 0 for a food that only hurts.",
                    "type": "integer"
                  },
                  "hurt": {
                    "minimum": 1,
                    "maximum": 100,
                    "description": "Health points it takes when eaten, at any hour: a bad fruit or a raw herb (G30).",
                    "type": "integer"
                  }
                }
              },
              "tool": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "kind",
                  "tier"
                ],
                "properties": {
                  "kind": {
                    "anyOf": [
                      {
                        "const": "basket",
                        "type": "string"
                      },
                      {
                        "const": "trowel",
                        "type": "string"
                      },
                      {
                        "const": "axe",
                        "type": "string"
                      },
                      {
                        "const": "staff",
                        "type": "string"
                      }
                    ]
                  },
                  "tier": {
                    "minimum": 1,
                    "maximum": 5,
                    "description": "Better tools work faster. The calculator clamps the total.",
                    "type": "integer"
                  },
                  "uses": {
                    "minimum": 1,
                    "maximum": 1000,
                    "description": "The tool wears out after this many uses. Left out, the tool lasts (DECISIONS.md, 2026-10-09: the crafting economy).",
                    "type": "integer"
                  }
                }
              },
              "fragment": {
                "additionalProperties": false,
                "description": "A found scrap that teaches a recipe.",
                "type": "object",
                "required": [
                  "unlocks"
                ],
                "properties": {
                  "unlocks": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                }
              },
              "wear": {
                "additionalProperties": false,
                "description": "Something the character wears (DECISIONS.md, 2026-10-09: the upgrade). A worn item stays in the bag.",
                "type": "object",
                "required": [
                  "slot"
                ],
                "properties": {
                  "slot": {
                    "description": "Where it is worn: head, top, legs (trousers), outfit (takes the top and the legs), feet, jewelry (two places) or hand (a tool).",
                    "anyOf": [
                      {
                        "const": "head",
                        "type": "string"
                      },
                      {
                        "const": "top",
                        "type": "string"
                      },
                      {
                        "const": "legs",
                        "type": "string"
                      },
                      {
                        "const": "outfit",
                        "type": "string"
                      },
                      {
                        "const": "feet",
                        "type": "string"
                      },
                      {
                        "const": "jewelry",
                        "type": "string"
                      },
                      {
                        "const": "hand",
                        "type": "string"
                      }
                    ]
                  },
                  "look": {
                    "description": "A look: worn on the look layer over the work clothes. It shows and counts for nothing, so it has no effects and no set.",
                    "type": "boolean"
                  },
                  "effects": {
                    "minItems": 1,
                    "maxItems": 2,
                    "description": "Small bonuses while it is worn on the work layer. Two at most, each effect once.",
                    "type": "array",
                    "items": {
                      "additionalProperties": false,
                      "type": "object",
                      "required": [
                        "effect",
                        "value"
                      ],
                      "properties": {
                        "effect": {
                          "description": "What a worn item helps: gathering, digging or crafting speed, the craft chance, or rare finds.",
                          "anyOf": [
                            {
                              "const": "gather_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "dig_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_chance_pct",
                              "type": "string"
                            },
                            {
                              "const": "rare_find_pct",
                              "type": "string"
                            }
                          ]
                        },
                        "value": {
                          "minimum": 1,
                          "maximum": 100,
                          "description": "Percent, at most the cap of the item's tier (params.wear_effect_max_pct).",
                          "type": "integer"
                        }
                      }
                    }
                  },
                  "set": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "A set of one creator: when every piece of it is worn, their effects grow by params.wear_set_bonus_pct.",
                    "type": "string"
                  }
                }
              },
              "premium_later": {
                "description": "Marks a look that may also be sold for premium currency once stage 6 brings it. Only a look item with no effect may carry it, and it stays obtainable in the game (DECISIONS.md, 2026-10-09).",
                "type": "boolean"
              }
            }
          }
        },
        "classes": {
          "maxItems": 10,
          "description": "Classes of your own, each under one base class.",
          "type": "array",
          "items": {
            "additionalProperties": false,
            "description": "A class of your own, declared under one base class. Every rule written for the base class holds for it.",
            "type": "object",
            "required": [
              "id",
              "name",
              "base"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "base": {
                "description": "plant (leaves, herbs, berries, fruit, roots, mushrooms), wood, fibre (reeds, grass, thread, cloth), stone, clay (clay, sand, pottery, brick), mineral (crystals, gems, salt, ore), metal (waits for its discovery), animal (feathers, wool, hide, bone), meal (cooked food), tool, garment (worn clothes), jewelry, relic (old things from the ruins).",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  }
                ]
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              }
            }
          }
        },
        "type": {
          "const": "quest",
          "type": "string"
        },
        "quest": {
          "additionalProperties": false,
          "type": "object",
          "required": [
            "summary",
            "steps",
            "reward"
          ],
          "properties": {
            "giver": {
              "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
              "maxLength": 80,
              "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
              "type": "string"
            },
            "starter": {
              "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
              "maxLength": 80,
              "description": "Offered to a character of this starter only: a start's own first task. Left out: every character.",
              "type": "string"
            },
            "type": {
              "description": "The kind of question the quest asks: one of the thirteen in docs/design/GAME_RULES.md section 3. Two quests of one type never follow each other in a chain (G17). Optional in the schema so an old file still reads; the check refuses a quest without one since the core content declared it (GRUNT P-3, 8.10).",
              "anyOf": [
                {
                  "const": "investigation",
                  "type": "string"
                },
                {
                  "const": "discovery",
                  "type": "string"
                },
                {
                  "const": "fetch_twist",
                  "type": "string"
                },
                {
                  "const": "dilemma",
                  "type": "string"
                },
                {
                  "const": "skill",
                  "type": "string"
                },
                {
                  "const": "collection",
                  "type": "string"
                },
                {
                  "const": "tending",
                  "type": "string"
                },
                {
                  "const": "riddle",
                  "type": "string"
                },
                {
                  "const": "mastery",
                  "type": "string"
                },
                {
                  "const": "gamble",
                  "type": "string"
                },
                {
                  "const": "persuasion",
                  "type": "string"
                },
                {
                  "const": "errand",
                  "type": "string"
                },
                {
                  "const": "maze",
                  "type": "string"
                }
              ]
            },
            "summary": {
              "minLength": 1,
              "maxLength": 240,
              "type": "string"
            },
            "steps": {
              "minItems": 1,
              "maxItems": 6,
              "type": "array",
              "items": {
                "anyOf": [
                  {
                    "additionalProperties": false,
                    "type": "object",
                    "required": [
                      "kind",
                      "item",
                      "qty"
                    ],
                    "properties": {
                      "kind": {
                        "const": "bring",
                        "type": "string"
                      },
                      "item": {
                        "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                        "maxLength": 80,
                        "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                        "type": "string"
                      },
                      "qty": {
                        "minimum": 1,
                        "maximum": 99,
                        "type": "integer"
                      }
                    }
                  },
                  {
                    "additionalProperties": false,
                    "type": "object",
                    "required": [
                      "kind",
                      "recipe"
                    ],
                    "properties": {
                      "kind": {
                        "const": "make",
                        "type": "string"
                      },
                      "recipe": {
                        "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                        "maxLength": 80,
                        "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                        "type": "string"
                      }
                    }
                  },
                  {
                    "additionalProperties": false,
                    "type": "object",
                    "required": [
                      "kind",
                      "restore"
                    ],
                    "properties": {
                      "kind": {
                        "const": "restore",
                        "type": "string"
                      },
                      "restore": {
                        "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                        "maxLength": 80,
                        "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                        "type": "string"
                      }
                    }
                  },
                  {
                    "additionalProperties": false,
                    "type": "object",
                    "required": [
                      "kind",
                      "camp"
                    ],
                    "properties": {
                      "kind": {
                        "const": "build",
                        "type": "string"
                      },
                      "camp": {
                        "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                        "maxLength": 80,
                        "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                        "type": "string"
                      }
                    }
                  },
                  {
                    "additionalProperties": false,
                    "type": "object",
                    "required": [
                      "kind",
                      "slot"
                    ],
                    "properties": {
                      "kind": {
                        "const": "visit",
                        "type": "string"
                      },
                      "slot": {
                        "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                        "maxLength": 80,
                        "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                        "type": "string"
                      }
                    }
                  },
                  {
                    "additionalProperties": false,
                    "description": "Bring one of an item that is found, not farmed: only digging gives it, or one timed plant (a resource with hours) that nothing else gives, makes or sells. The journal shows the clue, not a count, until the item is in the bag.",
                    "type": "object",
                    "required": [
                      "kind",
                      "item",
                      "clue"
                    ],
                    "properties": {
                      "kind": {
                        "const": "find",
                        "type": "string"
                      },
                      "item": {
                        "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                        "maxLength": 80,
                        "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                        "type": "string"
                      },
                      "clue": {
                        "minLength": 1,
                        "maxLength": 240,
                        "description": "What the journal shows for this step: something to notice or work out. Never the answer, never a count.",
                        "type": "string"
                      }
                    }
                  },
                  {
                    "additionalProperties": false,
                    "description": "A catch and a reveal (G6): the journal shows the clue, the world holds the answer.",
                    "type": "object",
                    "required": [
                      "kind",
                      "clue",
                      "props",
                      "answer"
                    ],
                    "properties": {
                      "kind": {
                        "const": "riddle",
                        "type": "string"
                      },
                      "clue": {
                        "minLength": 1,
                        "maxLength": 240,
                        "description": "What the journal shows for this step: something to notice or work out. Never the answer, never a count.",
                        "type": "string"
                      },
                      "props": {
                        "minItems": 1,
                        "maxItems": 4,
                        "description": "Ids of the map props the riddle reads: the inscriptions it pays for (G8).",
                        "type": "array",
                        "items": {
                          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                          "maxLength": 80,
                          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                          "type": "string"
                        }
                      },
                      "answer": {
                        "description": "What solves the riddle. The kernel completes the step on that event and on nothing else.",
                        "anyOf": [
                          {
                            "additionalProperties": false,
                            "description": "Solved by digging at this dig spot, whatever comes up.",
                            "type": "object",
                            "required": [
                              "kind",
                              "treasure"
                            ],
                            "properties": {
                              "kind": {
                                "const": "dig",
                                "type": "string"
                              },
                              "treasure": {
                                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                                "maxLength": 80,
                                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                                "type": "string"
                              }
                            }
                          },
                          {
                            "additionalProperties": false,
                            "description": "Solved by standing in this slot by day (05:00 to 20:00) or by night.",
                            "type": "object",
                            "required": [
                              "kind",
                              "slot",
                              "at"
                            ],
                            "properties": {
                              "kind": {
                                "const": "visit",
                                "type": "string"
                              },
                              "slot": {
                                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                                "maxLength": 80,
                                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                                "type": "string"
                              },
                              "at": {
                                "anyOf": [
                                  {
                                    "const": "day",
                                    "type": "string"
                                  },
                                  {
                                    "const": "night",
                                    "type": "string"
                                  }
                                ]
                              }
                            }
                          }
                        ]
                      }
                    }
                  }
                ]
              }
            },
            "requires": {
              "maxItems": 4,
              "type": "array",
              "items": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              }
            },
            "talk": {
              "additionalProperties": false,
              "description": "What the giver says, in the giver's voice. \"{name}\" in a line is the player's name.",
              "type": "object",
              "properties": {
                "offer": {
                  "minItems": 1,
                  "maxItems": 3,
                  "description": "The giver asks. Left out, the summary.",
                  "type": "array",
                  "items": {
                    "minLength": 1,
                    "maxLength": 240,
                    "type": "string"
                  }
                },
                "waiting": {
                  "minItems": 1,
                  "maxItems": 2,
                  "description": "The giver, while the player is on it. Left out, the summary.",
                  "type": "array",
                  "items": {
                    "minLength": 1,
                    "maxLength": 240,
                    "type": "string"
                  }
                },
                "done": {
                  "minItems": 1,
                  "maxItems": 3,
                  "description": "The giver, when the player hands it in.",
                  "type": "array",
                  "items": {
                    "minLength": 1,
                    "maxLength": 240,
                    "type": "string"
                  }
                }
              }
            },
            "reward": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "rep"
              ],
              "properties": {
                "rep": {
                  "minimum": 0,
                  "maximum": 100,
                  "description": "Reputation with the giver. Never traded, so it can be generous.",
                  "type": "integer"
                },
                "gold_mg": {
                  "minimum": 1,
                  "maximum": 10000000,
                  "type": "integer"
                },
                "items": {
                  "maxItems": 4,
                  "type": "array",
                  "items": {
                    "additionalProperties": false,
                    "type": "object",
                    "required": [
                      "item",
                      "qty"
                    ],
                    "properties": {
                      "item": {
                        "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                        "maxLength": 80,
                        "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                        "type": "string"
                      },
                      "qty": {
                        "minimum": 1,
                        "maximum": 999,
                        "type": "integer"
                      },
                      "instead": {
                        "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                        "maxLength": 80,
                        "description": "What a start whose kit holds the item gets in its place: something that kit lacks.",
                        "type": "string"
                      }
                    }
                  }
                },
                "recipes": {
                  "maxItems": 4,
                  "type": "array",
                  "items": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                },
                "opens": {
                  "maxItems": 2,
                  "description": "Ids of restores the quest opens when it is done: a place reward, the way a restore opens by hand.",
                  "type": "array",
                  "items": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    },
    {
      "additionalProperties": false,
      "$id": "restore",
      "type": "object",
      "required": [
        "format",
        "id",
        "title",
        "creator",
        "type",
        "restore"
      ],
      "properties": {
        "$schema": {
          "type": "string"
        },
        "format": {
          "description": "Format version of this file.",
          "const": 1,
          "type": "number"
        },
        "id": {
          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
          "maxLength": 80,
          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
          "type": "string"
        },
        "title": {
          "minLength": 1,
          "maxLength": 40,
          "type": "string"
        },
        "creator": {
          "pattern": "^[a-z0-9_-]+$",
          "maxLength": 39,
          "description": "GitHub handle, lowercase.",
          "type": "string"
        },
        "description": {
          "minLength": 1,
          "maxLength": 240,
          "type": "string"
        },
        "ai_tools": {
          "maxItems": 8,
          "description": "AI tools used to make this file or its art. Required when any were used.",
          "type": "array",
          "items": {
            "minLength": 1,
            "maxLength": 60,
            "type": "string"
          }
        },
        "items": {
          "maxItems": 40,
          "type": "array",
          "items": {
            "additionalProperties": false,
            "type": "object",
            "required": [
              "id",
              "name",
              "kind",
              "rarity",
              "sprite"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              },
              "kind": {
                "anyOf": [
                  {
                    "const": "material",
                    "type": "string"
                  },
                  {
                    "const": "food",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "fragment",
                    "type": "string"
                  },
                  {
                    "const": "treasure",
                    "type": "string"
                  }
                ]
              },
              "rarity": {
                "description": "Declared rarity. The check compares it with the rarity computed from the data.",
                "anyOf": [
                  {
                    "const": "common",
                    "type": "string"
                  },
                  {
                    "const": "uncommon",
                    "type": "string"
                  },
                  {
                    "const": "rare",
                    "type": "string"
                  },
                  {
                    "const": "legendary",
                    "type": "string"
                  }
                ]
              },
              "class": {
                "description": "A base class (plant, wood, fibre, ...) or the id of a class an extension declares under one of them.",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  },
                  {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                ]
              },
              "family": {
                "pattern": "^[a-z0-9_-]+$",
                "maxLength": 24,
                "description": "A group inside the class, for example \"berry\" for every berry. Open: any lowercase word.",
                "type": "string"
              },
              "tags": {
                "maxItems": 8,
                "uniqueItems": true,
                "description": "Open words that describe it, for example \"sweet\" or \"night\".",
                "type": "array",
                "items": {
                  "pattern": "^[a-z0-9_-]+$",
                  "maxLength": 24,
                  "description": "A lowercase word.",
                  "type": "string"
                }
              },
              "tier": {
                "minimum": 1,
                "maximum": 20,
                "description": "How advanced it is, from 1. The rarity says how often it appears; the tier says how far up the ladder it is. A tool has the tier of its \"tool\".",
                "type": "integer"
              },
              "sprite": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
                "maxLength": 120,
                "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
                "type": "string"
              },
              "food": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "satiety"
                ],
                "properties": {
                  "satiety": {
                    "minimum": 0,
                    "maximum": 100,
                    "description": "Health points restored when eaten (the meter holds 100 at the start). 0 for a food that only hurts.",
                    "type": "integer"
                  },
                  "hurt": {
                    "minimum": 1,
                    "maximum": 100,
                    "description": "Health points it takes when eaten, at any hour: a bad fruit or a raw herb (G30).",
                    "type": "integer"
                  }
                }
              },
              "tool": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "kind",
                  "tier"
                ],
                "properties": {
                  "kind": {
                    "anyOf": [
                      {
                        "const": "basket",
                        "type": "string"
                      },
                      {
                        "const": "trowel",
                        "type": "string"
                      },
                      {
                        "const": "axe",
                        "type": "string"
                      },
                      {
                        "const": "staff",
                        "type": "string"
                      }
                    ]
                  },
                  "tier": {
                    "minimum": 1,
                    "maximum": 5,
                    "description": "Better tools work faster. The calculator clamps the total.",
                    "type": "integer"
                  },
                  "uses": {
                    "minimum": 1,
                    "maximum": 1000,
                    "description": "The tool wears out after this many uses. Left out, the tool lasts (DECISIONS.md, 2026-10-09: the crafting economy).",
                    "type": "integer"
                  }
                }
              },
              "fragment": {
                "additionalProperties": false,
                "description": "A found scrap that teaches a recipe.",
                "type": "object",
                "required": [
                  "unlocks"
                ],
                "properties": {
                  "unlocks": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                }
              },
              "wear": {
                "additionalProperties": false,
                "description": "Something the character wears (DECISIONS.md, 2026-10-09: the upgrade). A worn item stays in the bag.",
                "type": "object",
                "required": [
                  "slot"
                ],
                "properties": {
                  "slot": {
                    "description": "Where it is worn: head, top, legs (trousers), outfit (takes the top and the legs), feet, jewelry (two places) or hand (a tool).",
                    "anyOf": [
                      {
                        "const": "head",
                        "type": "string"
                      },
                      {
                        "const": "top",
                        "type": "string"
                      },
                      {
                        "const": "legs",
                        "type": "string"
                      },
                      {
                        "const": "outfit",
                        "type": "string"
                      },
                      {
                        "const": "feet",
                        "type": "string"
                      },
                      {
                        "const": "jewelry",
                        "type": "string"
                      },
                      {
                        "const": "hand",
                        "type": "string"
                      }
                    ]
                  },
                  "look": {
                    "description": "A look: worn on the look layer over the work clothes. It shows and counts for nothing, so it has no effects and no set.",
                    "type": "boolean"
                  },
                  "effects": {
                    "minItems": 1,
                    "maxItems": 2,
                    "description": "Small bonuses while it is worn on the work layer. Two at most, each effect once.",
                    "type": "array",
                    "items": {
                      "additionalProperties": false,
                      "type": "object",
                      "required": [
                        "effect",
                        "value"
                      ],
                      "properties": {
                        "effect": {
                          "description": "What a worn item helps: gathering, digging or crafting speed, the craft chance, or rare finds.",
                          "anyOf": [
                            {
                              "const": "gather_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "dig_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_chance_pct",
                              "type": "string"
                            },
                            {
                              "const": "rare_find_pct",
                              "type": "string"
                            }
                          ]
                        },
                        "value": {
                          "minimum": 1,
                          "maximum": 100,
                          "description": "Percent, at most the cap of the item's tier (params.wear_effect_max_pct).",
                          "type": "integer"
                        }
                      }
                    }
                  },
                  "set": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "A set of one creator: when every piece of it is worn, their effects grow by params.wear_set_bonus_pct.",
                    "type": "string"
                  }
                }
              },
              "premium_later": {
                "description": "Marks a look that may also be sold for premium currency once stage 6 brings it. Only a look item with no effect may carry it, and it stays obtainable in the game (DECISIONS.md, 2026-10-09).",
                "type": "boolean"
              }
            }
          }
        },
        "classes": {
          "maxItems": 10,
          "description": "Classes of your own, each under one base class.",
          "type": "array",
          "items": {
            "additionalProperties": false,
            "description": "A class of your own, declared under one base class. Every rule written for the base class holds for it.",
            "type": "object",
            "required": [
              "id",
              "name",
              "base"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "base": {
                "description": "plant (leaves, herbs, berries, fruit, roots, mushrooms), wood, fibre (reeds, grass, thread, cloth), stone, clay (clay, sand, pottery, brick), mineral (crystals, gems, salt, ore), metal (waits for its discovery), animal (feathers, wool, hide, bone), meal (cooked food), tool, garment (worn clothes), jewelry, relic (old things from the ruins).",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  }
                ]
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              }
            }
          }
        },
        "type": {
          "const": "restore",
          "type": "string"
        },
        "restore": {
          "additionalProperties": false,
          "type": "object",
          "required": [
            "place",
            "before",
            "after",
            "inputs",
            "active_ms",
            "passable"
          ],
          "properties": {
            "place": {
              "additionalProperties": false,
              "description": "An empty slot from the ruins map. Only one extension is active per slot.",
              "type": "object",
              "required": [
                "slot"
              ],
              "properties": {
                "slot": {
                  "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                  "maxLength": 80,
                  "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                  "type": "string"
                }
              }
            },
            "before": {
              "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
              "maxLength": 120,
              "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
              "type": "string"
            },
            "after": {
              "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
              "maxLength": 120,
              "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
              "type": "string"
            },
            "inputs": {
              "maxItems": 6,
              "description": "What the player brings to restore it. Empty: it does not open by hand, only as a quest's reward.opens.",
              "type": "array",
              "items": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "item",
                  "qty"
                ],
                "properties": {
                  "item": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  },
                  "qty": {
                    "minimum": 1,
                    "maximum": 999,
                    "type": "integer"
                  }
                }
              }
            },
            "active_ms": {
              "minimum": 0,
              "maximum": 3600000,
              "description": "Time the player is busy restoring it.",
              "type": "integer"
            },
            "passable": {
              "description": "Whether the restored thing can be walked over (a bridge).",
              "type": "boolean"
            },
            "sign": {
              "minLength": 1,
              "maxLength": 40,
              "type": "string"
            },
            "done": {
              "minItems": 1,
              "maxItems": 2,
              "description": "The narrator, when the place is mended: what is there now, never what was (STORY.md S1). \"{name}\" is the player's name.",
              "type": "array",
              "items": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              }
            }
          }
        }
      }
    },
    {
      "additionalProperties": false,
      "$id": "camp",
      "type": "object",
      "required": [
        "format",
        "id",
        "title",
        "creator",
        "type",
        "camp"
      ],
      "properties": {
        "$schema": {
          "type": "string"
        },
        "format": {
          "description": "Format version of this file.",
          "const": 1,
          "type": "number"
        },
        "id": {
          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
          "maxLength": 80,
          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
          "type": "string"
        },
        "title": {
          "minLength": 1,
          "maxLength": 40,
          "type": "string"
        },
        "creator": {
          "pattern": "^[a-z0-9_-]+$",
          "maxLength": 39,
          "description": "GitHub handle, lowercase.",
          "type": "string"
        },
        "description": {
          "minLength": 1,
          "maxLength": 240,
          "type": "string"
        },
        "ai_tools": {
          "maxItems": 8,
          "description": "AI tools used to make this file or its art. Required when any were used.",
          "type": "array",
          "items": {
            "minLength": 1,
            "maxLength": 60,
            "type": "string"
          }
        },
        "items": {
          "maxItems": 40,
          "type": "array",
          "items": {
            "additionalProperties": false,
            "type": "object",
            "required": [
              "id",
              "name",
              "kind",
              "rarity",
              "sprite"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              },
              "kind": {
                "anyOf": [
                  {
                    "const": "material",
                    "type": "string"
                  },
                  {
                    "const": "food",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "fragment",
                    "type": "string"
                  },
                  {
                    "const": "treasure",
                    "type": "string"
                  }
                ]
              },
              "rarity": {
                "description": "Declared rarity. The check compares it with the rarity computed from the data.",
                "anyOf": [
                  {
                    "const": "common",
                    "type": "string"
                  },
                  {
                    "const": "uncommon",
                    "type": "string"
                  },
                  {
                    "const": "rare",
                    "type": "string"
                  },
                  {
                    "const": "legendary",
                    "type": "string"
                  }
                ]
              },
              "class": {
                "description": "A base class (plant, wood, fibre, ...) or the id of a class an extension declares under one of them.",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  },
                  {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                ]
              },
              "family": {
                "pattern": "^[a-z0-9_-]+$",
                "maxLength": 24,
                "description": "A group inside the class, for example \"berry\" for every berry. Open: any lowercase word.",
                "type": "string"
              },
              "tags": {
                "maxItems": 8,
                "uniqueItems": true,
                "description": "Open words that describe it, for example \"sweet\" or \"night\".",
                "type": "array",
                "items": {
                  "pattern": "^[a-z0-9_-]+$",
                  "maxLength": 24,
                  "description": "A lowercase word.",
                  "type": "string"
                }
              },
              "tier": {
                "minimum": 1,
                "maximum": 20,
                "description": "How advanced it is, from 1. The rarity says how often it appears; the tier says how far up the ladder it is. A tool has the tier of its \"tool\".",
                "type": "integer"
              },
              "sprite": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
                "maxLength": 120,
                "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
                "type": "string"
              },
              "food": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "satiety"
                ],
                "properties": {
                  "satiety": {
                    "minimum": 0,
                    "maximum": 100,
                    "description": "Health points restored when eaten (the meter holds 100 at the start). 0 for a food that only hurts.",
                    "type": "integer"
                  },
                  "hurt": {
                    "minimum": 1,
                    "maximum": 100,
                    "description": "Health points it takes when eaten, at any hour: a bad fruit or a raw herb (G30).",
                    "type": "integer"
                  }
                }
              },
              "tool": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "kind",
                  "tier"
                ],
                "properties": {
                  "kind": {
                    "anyOf": [
                      {
                        "const": "basket",
                        "type": "string"
                      },
                      {
                        "const": "trowel",
                        "type": "string"
                      },
                      {
                        "const": "axe",
                        "type": "string"
                      },
                      {
                        "const": "staff",
                        "type": "string"
                      }
                    ]
                  },
                  "tier": {
                    "minimum": 1,
                    "maximum": 5,
                    "description": "Better tools work faster. The calculator clamps the total.",
                    "type": "integer"
                  },
                  "uses": {
                    "minimum": 1,
                    "maximum": 1000,
                    "description": "The tool wears out after this many uses. Left out, the tool lasts (DECISIONS.md, 2026-10-09: the crafting economy).",
                    "type": "integer"
                  }
                }
              },
              "fragment": {
                "additionalProperties": false,
                "description": "A found scrap that teaches a recipe.",
                "type": "object",
                "required": [
                  "unlocks"
                ],
                "properties": {
                  "unlocks": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                }
              },
              "wear": {
                "additionalProperties": false,
                "description": "Something the character wears (DECISIONS.md, 2026-10-09: the upgrade). A worn item stays in the bag.",
                "type": "object",
                "required": [
                  "slot"
                ],
                "properties": {
                  "slot": {
                    "description": "Where it is worn: head, top, legs (trousers), outfit (takes the top and the legs), feet, jewelry (two places) or hand (a tool).",
                    "anyOf": [
                      {
                        "const": "head",
                        "type": "string"
                      },
                      {
                        "const": "top",
                        "type": "string"
                      },
                      {
                        "const": "legs",
                        "type": "string"
                      },
                      {
                        "const": "outfit",
                        "type": "string"
                      },
                      {
                        "const": "feet",
                        "type": "string"
                      },
                      {
                        "const": "jewelry",
                        "type": "string"
                      },
                      {
                        "const": "hand",
                        "type": "string"
                      }
                    ]
                  },
                  "look": {
                    "description": "A look: worn on the look layer over the work clothes. It shows and counts for nothing, so it has no effects and no set.",
                    "type": "boolean"
                  },
                  "effects": {
                    "minItems": 1,
                    "maxItems": 2,
                    "description": "Small bonuses while it is worn on the work layer. Two at most, each effect once.",
                    "type": "array",
                    "items": {
                      "additionalProperties": false,
                      "type": "object",
                      "required": [
                        "effect",
                        "value"
                      ],
                      "properties": {
                        "effect": {
                          "description": "What a worn item helps: gathering, digging or crafting speed, the craft chance, or rare finds.",
                          "anyOf": [
                            {
                              "const": "gather_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "dig_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_chance_pct",
                              "type": "string"
                            },
                            {
                              "const": "rare_find_pct",
                              "type": "string"
                            }
                          ]
                        },
                        "value": {
                          "minimum": 1,
                          "maximum": 100,
                          "description": "Percent, at most the cap of the item's tier (params.wear_effect_max_pct).",
                          "type": "integer"
                        }
                      }
                    }
                  },
                  "set": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "A set of one creator: when every piece of it is worn, their effects grow by params.wear_set_bonus_pct.",
                    "type": "string"
                  }
                }
              },
              "premium_later": {
                "description": "Marks a look that may also be sold for premium currency once stage 6 brings it. Only a look item with no effect may carry it, and it stays obtainable in the game (DECISIONS.md, 2026-10-09).",
                "type": "boolean"
              }
            }
          }
        },
        "classes": {
          "maxItems": 10,
          "description": "Classes of your own, each under one base class.",
          "type": "array",
          "items": {
            "additionalProperties": false,
            "description": "A class of your own, declared under one base class. Every rule written for the base class holds for it.",
            "type": "object",
            "required": [
              "id",
              "name",
              "base"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "base": {
                "description": "plant (leaves, herbs, berries, fruit, roots, mushrooms), wood, fibre (reeds, grass, thread, cloth), stone, clay (clay, sand, pottery, brick), mineral (crystals, gems, salt, ore), metal (waits for its discovery), animal (feathers, wool, hide, bone), meal (cooked food), tool, garment (worn clothes), jewelry, relic (old things from the ruins).",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  }
                ]
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              }
            }
          }
        },
        "type": {
          "const": "camp",
          "type": "string"
        },
        "camp": {
          "additionalProperties": false,
          "type": "object",
          "required": [
            "slot",
            "inputs",
            "active_ms",
            "sprite"
          ],
          "properties": {
            "slot": {
              "anyOf": [
                {
                  "const": "fire",
                  "type": "string"
                },
                {
                  "const": "storage",
                  "type": "string"
                },
                {
                  "const": "workshop",
                  "type": "string"
                },
                {
                  "const": "shelf",
                  "type": "string"
                }
              ]
            },
            "inputs": {
              "minItems": 1,
              "maxItems": 6,
              "type": "array",
              "items": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "item",
                  "qty"
                ],
                "properties": {
                  "item": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  },
                  "qty": {
                    "minimum": 1,
                    "maximum": 999,
                    "type": "integer"
                  }
                }
              }
            },
            "active_ms": {
              "minimum": 0,
              "maximum": 3600000,
              "description": "Time the player is busy building it.",
              "type": "integer"
            },
            "sprite": {
              "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
              "maxLength": 120,
              "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
              "type": "string"
            },
            "provides": {
              "anyOf": [
                {
                  "const": "fire",
                  "type": "string"
                },
                {
                  "const": "workshop",
                  "type": "string"
                }
              ]
            },
            "tier": {
              "minimum": 1,
              "maximum": 20,
              "description": "Tier of the station this part provides, 1 when left out. A recipe needs a station of at least its own tier.",
              "type": "integer"
            },
            "bag_bonus": {
              "minimum": 1,
              "maximum": 40,
              "type": "integer"
            },
            "upgrades": {
              "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
              "maxLength": 80,
              "description": "The camp part this one is built over, in the same slot: that part stands first, and this one replaces it. It gives at least what that part gave.",
              "type": "string"
            }
          }
        }
      }
    },
    {
      "additionalProperties": false,
      "$id": "starter",
      "type": "object",
      "required": [
        "format",
        "id",
        "title",
        "creator",
        "type",
        "starter"
      ],
      "properties": {
        "$schema": {
          "type": "string"
        },
        "format": {
          "description": "Format version of this file.",
          "const": 1,
          "type": "number"
        },
        "id": {
          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
          "maxLength": 80,
          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
          "type": "string"
        },
        "title": {
          "minLength": 1,
          "maxLength": 40,
          "type": "string"
        },
        "creator": {
          "pattern": "^[a-z0-9_-]+$",
          "maxLength": 39,
          "description": "GitHub handle, lowercase.",
          "type": "string"
        },
        "description": {
          "minLength": 1,
          "maxLength": 240,
          "type": "string"
        },
        "ai_tools": {
          "maxItems": 8,
          "description": "AI tools used to make this file or its art. Required when any were used.",
          "type": "array",
          "items": {
            "minLength": 1,
            "maxLength": 60,
            "type": "string"
          }
        },
        "items": {
          "maxItems": 40,
          "type": "array",
          "items": {
            "additionalProperties": false,
            "type": "object",
            "required": [
              "id",
              "name",
              "kind",
              "rarity",
              "sprite"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              },
              "kind": {
                "anyOf": [
                  {
                    "const": "material",
                    "type": "string"
                  },
                  {
                    "const": "food",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "fragment",
                    "type": "string"
                  },
                  {
                    "const": "treasure",
                    "type": "string"
                  }
                ]
              },
              "rarity": {
                "description": "Declared rarity. The check compares it with the rarity computed from the data.",
                "anyOf": [
                  {
                    "const": "common",
                    "type": "string"
                  },
                  {
                    "const": "uncommon",
                    "type": "string"
                  },
                  {
                    "const": "rare",
                    "type": "string"
                  },
                  {
                    "const": "legendary",
                    "type": "string"
                  }
                ]
              },
              "class": {
                "description": "A base class (plant, wood, fibre, ...) or the id of a class an extension declares under one of them.",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  },
                  {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                ]
              },
              "family": {
                "pattern": "^[a-z0-9_-]+$",
                "maxLength": 24,
                "description": "A group inside the class, for example \"berry\" for every berry. Open: any lowercase word.",
                "type": "string"
              },
              "tags": {
                "maxItems": 8,
                "uniqueItems": true,
                "description": "Open words that describe it, for example \"sweet\" or \"night\".",
                "type": "array",
                "items": {
                  "pattern": "^[a-z0-9_-]+$",
                  "maxLength": 24,
                  "description": "A lowercase word.",
                  "type": "string"
                }
              },
              "tier": {
                "minimum": 1,
                "maximum": 20,
                "description": "How advanced it is, from 1. The rarity says how often it appears; the tier says how far up the ladder it is. A tool has the tier of its \"tool\".",
                "type": "integer"
              },
              "sprite": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
                "maxLength": 120,
                "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
                "type": "string"
              },
              "food": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "satiety"
                ],
                "properties": {
                  "satiety": {
                    "minimum": 0,
                    "maximum": 100,
                    "description": "Health points restored when eaten (the meter holds 100 at the start). 0 for a food that only hurts.",
                    "type": "integer"
                  },
                  "hurt": {
                    "minimum": 1,
                    "maximum": 100,
                    "description": "Health points it takes when eaten, at any hour: a bad fruit or a raw herb (G30).",
                    "type": "integer"
                  }
                }
              },
              "tool": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "kind",
                  "tier"
                ],
                "properties": {
                  "kind": {
                    "anyOf": [
                      {
                        "const": "basket",
                        "type": "string"
                      },
                      {
                        "const": "trowel",
                        "type": "string"
                      },
                      {
                        "const": "axe",
                        "type": "string"
                      },
                      {
                        "const": "staff",
                        "type": "string"
                      }
                    ]
                  },
                  "tier": {
                    "minimum": 1,
                    "maximum": 5,
                    "description": "Better tools work faster. The calculator clamps the total.",
                    "type": "integer"
                  },
                  "uses": {
                    "minimum": 1,
                    "maximum": 1000,
                    "description": "The tool wears out after this many uses. Left out, the tool lasts (DECISIONS.md, 2026-10-09: the crafting economy).",
                    "type": "integer"
                  }
                }
              },
              "fragment": {
                "additionalProperties": false,
                "description": "A found scrap that teaches a recipe.",
                "type": "object",
                "required": [
                  "unlocks"
                ],
                "properties": {
                  "unlocks": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                }
              },
              "wear": {
                "additionalProperties": false,
                "description": "Something the character wears (DECISIONS.md, 2026-10-09: the upgrade). A worn item stays in the bag.",
                "type": "object",
                "required": [
                  "slot"
                ],
                "properties": {
                  "slot": {
                    "description": "Where it is worn: head, top, legs (trousers), outfit (takes the top and the legs), feet, jewelry (two places) or hand (a tool).",
                    "anyOf": [
                      {
                        "const": "head",
                        "type": "string"
                      },
                      {
                        "const": "top",
                        "type": "string"
                      },
                      {
                        "const": "legs",
                        "type": "string"
                      },
                      {
                        "const": "outfit",
                        "type": "string"
                      },
                      {
                        "const": "feet",
                        "type": "string"
                      },
                      {
                        "const": "jewelry",
                        "type": "string"
                      },
                      {
                        "const": "hand",
                        "type": "string"
                      }
                    ]
                  },
                  "look": {
                    "description": "A look: worn on the look layer over the work clothes. It shows and counts for nothing, so it has no effects and no set.",
                    "type": "boolean"
                  },
                  "effects": {
                    "minItems": 1,
                    "maxItems": 2,
                    "description": "Small bonuses while it is worn on the work layer. Two at most, each effect once.",
                    "type": "array",
                    "items": {
                      "additionalProperties": false,
                      "type": "object",
                      "required": [
                        "effect",
                        "value"
                      ],
                      "properties": {
                        "effect": {
                          "description": "What a worn item helps: gathering, digging or crafting speed, the craft chance, or rare finds.",
                          "anyOf": [
                            {
                              "const": "gather_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "dig_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_chance_pct",
                              "type": "string"
                            },
                            {
                              "const": "rare_find_pct",
                              "type": "string"
                            }
                          ]
                        },
                        "value": {
                          "minimum": 1,
                          "maximum": 100,
                          "description": "Percent, at most the cap of the item's tier (params.wear_effect_max_pct).",
                          "type": "integer"
                        }
                      }
                    }
                  },
                  "set": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "A set of one creator: when every piece of it is worn, their effects grow by params.wear_set_bonus_pct.",
                    "type": "string"
                  }
                }
              },
              "premium_later": {
                "description": "Marks a look that may also be sold for premium currency once stage 6 brings it. Only a look item with no effect may carry it, and it stays obtainable in the game (DECISIONS.md, 2026-10-09).",
                "type": "boolean"
              }
            }
          }
        },
        "classes": {
          "maxItems": 10,
          "description": "Classes of your own, each under one base class.",
          "type": "array",
          "items": {
            "additionalProperties": false,
            "description": "A class of your own, declared under one base class. Every rule written for the base class holds for it.",
            "type": "object",
            "required": [
              "id",
              "name",
              "base"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "base": {
                "description": "plant (leaves, herbs, berries, fruit, roots, mushrooms), wood, fibre (reeds, grass, thread, cloth), stone, clay (clay, sand, pottery, brick), mineral (crystals, gems, salt, ore), metal (waits for its discovery), animal (feathers, wool, hide, bone), meal (cooked food), tool, garment (worn clothes), jewelry, relic (old things from the ruins).",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  }
                ]
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              }
            }
          }
        },
        "type": {
          "const": "starter",
          "type": "string"
        },
        "starter": {
          "additionalProperties": false,
          "type": "object",
          "required": [
            "name",
            "summary",
            "attributes",
            "sprite"
          ],
          "properties": {
            "name": {
              "minLength": 1,
              "maxLength": 40,
              "type": "string"
            },
            "summary": {
              "minLength": 1,
              "maxLength": 240,
              "type": "string"
            },
            "attributes": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "carry",
                "senses",
                "agility",
                "luck",
                "stamina"
              ],
              "properties": {
                "carry": {
                  "minimum": 0,
                  "maximum": 5,
                  "type": "integer"
                },
                "senses": {
                  "minimum": 0,
                  "maximum": 5,
                  "type": "integer"
                },
                "agility": {
                  "minimum": 0,
                  "maximum": 5,
                  "type": "integer"
                },
                "luck": {
                  "minimum": 0,
                  "maximum": 5,
                  "type": "integer"
                },
                "stamina": {
                  "minimum": 0,
                  "maximum": 5,
                  "type": "integer"
                }
              }
            },
            "sprite": {
              "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
              "maxLength": 120,
              "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
              "type": "string"
            },
            "sprite_alt": {
              "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
              "maxLength": 120,
              "description": "Another look of the same character (for example a woman instead of a man), offered by one toggle on the character screen. Same sprite sizes and directions as `sprite`.",
              "type": "string"
            },
            "kit": {
              "maxItems": 6,
              "description": "What the character carries on the first morning: the tools of its first task, put in the bag when the character is chosen. A piece with a working \"wear\" slot is worn from the start.",
              "type": "array",
              "items": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "item",
                  "qty"
                ],
                "properties": {
                  "item": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  },
                  "qty": {
                    "minimum": 1,
                    "maximum": 999,
                    "type": "integer"
                  }
                }
              }
            },
            "wake": {
              "additionalProperties": false,
              "description": "The tile the character wakes on. Left out: the map's spawn.",
              "type": "object",
              "required": [
                "x",
                "y"
              ],
              "properties": {
                "x": {
                  "minimum": 0,
                  "maximum": 1023,
                  "type": "integer"
                },
                "y": {
                  "minimum": 0,
                  "maximum": 1023,
                  "type": "integer"
                }
              }
            },
            "intro": {
              "minItems": 1,
              "maxItems": 4,
              "description": "What the narrator says as the character wakes, one box a line. Left out: the game's own waking lines.",
              "type": "array",
              "items": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              }
            }
          }
        }
      }
    },
    {
      "additionalProperties": false,
      "type": "object",
      "required": [
        "format",
        "id",
        "title",
        "creator",
        "type"
      ],
      "properties": {
        "$schema": {
          "type": "string"
        },
        "format": {
          "description": "Format version of this file.",
          "const": 1,
          "type": "number"
        },
        "id": {
          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
          "maxLength": 80,
          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
          "type": "string"
        },
        "title": {
          "minLength": 1,
          "maxLength": 40,
          "type": "string"
        },
        "creator": {
          "pattern": "^[a-z0-9_-]+$",
          "maxLength": 39,
          "description": "GitHub handle, lowercase.",
          "type": "string"
        },
        "description": {
          "minLength": 1,
          "maxLength": 240,
          "type": "string"
        },
        "ai_tools": {
          "maxItems": 8,
          "description": "AI tools used to make this file or its art. Required when any were used.",
          "type": "array",
          "items": {
            "minLength": 1,
            "maxLength": 60,
            "type": "string"
          }
        },
        "items": {
          "maxItems": 40,
          "type": "array",
          "items": {
            "additionalProperties": false,
            "type": "object",
            "required": [
              "id",
              "name",
              "kind",
              "rarity",
              "sprite"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              },
              "kind": {
                "anyOf": [
                  {
                    "const": "material",
                    "type": "string"
                  },
                  {
                    "const": "food",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "fragment",
                    "type": "string"
                  },
                  {
                    "const": "treasure",
                    "type": "string"
                  }
                ]
              },
              "rarity": {
                "description": "Declared rarity. The check compares it with the rarity computed from the data.",
                "anyOf": [
                  {
                    "const": "common",
                    "type": "string"
                  },
                  {
                    "const": "uncommon",
                    "type": "string"
                  },
                  {
                    "const": "rare",
                    "type": "string"
                  },
                  {
                    "const": "legendary",
                    "type": "string"
                  }
                ]
              },
              "class": {
                "description": "A base class (plant, wood, fibre, ...) or the id of a class an extension declares under one of them.",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  },
                  {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                ]
              },
              "family": {
                "pattern": "^[a-z0-9_-]+$",
                "maxLength": 24,
                "description": "A group inside the class, for example \"berry\" for every berry. Open: any lowercase word.",
                "type": "string"
              },
              "tags": {
                "maxItems": 8,
                "uniqueItems": true,
                "description": "Open words that describe it, for example \"sweet\" or \"night\".",
                "type": "array",
                "items": {
                  "pattern": "^[a-z0-9_-]+$",
                  "maxLength": 24,
                  "description": "A lowercase word.",
                  "type": "string"
                }
              },
              "tier": {
                "minimum": 1,
                "maximum": 20,
                "description": "How advanced it is, from 1. The rarity says how often it appears; the tier says how far up the ladder it is. A tool has the tier of its \"tool\".",
                "type": "integer"
              },
              "sprite": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
                "maxLength": 120,
                "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
                "type": "string"
              },
              "food": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "satiety"
                ],
                "properties": {
                  "satiety": {
                    "minimum": 0,
                    "maximum": 100,
                    "description": "Health points restored when eaten (the meter holds 100 at the start). 0 for a food that only hurts.",
                    "type": "integer"
                  },
                  "hurt": {
                    "minimum": 1,
                    "maximum": 100,
                    "description": "Health points it takes when eaten, at any hour: a bad fruit or a raw herb (G30).",
                    "type": "integer"
                  }
                }
              },
              "tool": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "kind",
                  "tier"
                ],
                "properties": {
                  "kind": {
                    "anyOf": [
                      {
                        "const": "basket",
                        "type": "string"
                      },
                      {
                        "const": "trowel",
                        "type": "string"
                      },
                      {
                        "const": "axe",
                        "type": "string"
                      },
                      {
                        "const": "staff",
                        "type": "string"
                      }
                    ]
                  },
                  "tier": {
                    "minimum": 1,
                    "maximum": 5,
                    "description": "Better tools work faster. The calculator clamps the total.",
                    "type": "integer"
                  },
                  "uses": {
                    "minimum": 1,
                    "maximum": 1000,
                    "description": "The tool wears out after this many uses. Left out, the tool lasts (DECISIONS.md, 2026-10-09: the crafting economy).",
                    "type": "integer"
                  }
                }
              },
              "fragment": {
                "additionalProperties": false,
                "description": "A found scrap that teaches a recipe.",
                "type": "object",
                "required": [
                  "unlocks"
                ],
                "properties": {
                  "unlocks": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                }
              },
              "wear": {
                "additionalProperties": false,
                "description": "Something the character wears (DECISIONS.md, 2026-10-09: the upgrade). A worn item stays in the bag.",
                "type": "object",
                "required": [
                  "slot"
                ],
                "properties": {
                  "slot": {
                    "description": "Where it is worn: head, top, legs (trousers), outfit (takes the top and the legs), feet, jewelry (two places) or hand (a tool).",
                    "anyOf": [
                      {
                        "const": "head",
                        "type": "string"
                      },
                      {
                        "const": "top",
                        "type": "string"
                      },
                      {
                        "const": "legs",
                        "type": "string"
                      },
                      {
                        "const": "outfit",
                        "type": "string"
                      },
                      {
                        "const": "feet",
                        "type": "string"
                      },
                      {
                        "const": "jewelry",
                        "type": "string"
                      },
                      {
                        "const": "hand",
                        "type": "string"
                      }
                    ]
                  },
                  "look": {
                    "description": "A look: worn on the look layer over the work clothes. It shows and counts for nothing, so it has no effects and no set.",
                    "type": "boolean"
                  },
                  "effects": {
                    "minItems": 1,
                    "maxItems": 2,
                    "description": "Small bonuses while it is worn on the work layer. Two at most, each effect once.",
                    "type": "array",
                    "items": {
                      "additionalProperties": false,
                      "type": "object",
                      "required": [
                        "effect",
                        "value"
                      ],
                      "properties": {
                        "effect": {
                          "description": "What a worn item helps: gathering, digging or crafting speed, the craft chance, or rare finds.",
                          "anyOf": [
                            {
                              "const": "gather_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "dig_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_chance_pct",
                              "type": "string"
                            },
                            {
                              "const": "rare_find_pct",
                              "type": "string"
                            }
                          ]
                        },
                        "value": {
                          "minimum": 1,
                          "maximum": 100,
                          "description": "Percent, at most the cap of the item's tier (params.wear_effect_max_pct).",
                          "type": "integer"
                        }
                      }
                    }
                  },
                  "set": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "A set of one creator: when every piece of it is worn, their effects grow by params.wear_set_bonus_pct.",
                    "type": "string"
                  }
                }
              },
              "premium_later": {
                "description": "Marks a look that may also be sold for premium currency once stage 6 brings it. Only a look item with no effect may carry it, and it stays obtainable in the game (DECISIONS.md, 2026-10-09).",
                "type": "boolean"
              }
            }
          }
        },
        "classes": {
          "maxItems": 10,
          "description": "Classes of your own, each under one base class.",
          "type": "array",
          "items": {
            "additionalProperties": false,
            "description": "A class of your own, declared under one base class. Every rule written for the base class holds for it.",
            "type": "object",
            "required": [
              "id",
              "name",
              "base"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "base": {
                "description": "plant (leaves, herbs, berries, fruit, roots, mushrooms), wood, fibre (reeds, grass, thread, cloth), stone, clay (clay, sand, pottery, brick), mineral (crystals, gems, salt, ore), metal (waits for its discovery), animal (feathers, wool, hide, bone), meal (cooked food), tool, garment (worn clothes), jewelry, relic (old things from the ruins).",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  }
                ]
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              }
            }
          }
        },
        "type": {
          "const": "items",
          "type": "string"
        }
      }
    },
    {
      "additionalProperties": false,
      "$id": "creator",
      "type": "object",
      "required": [
        "format",
        "id",
        "title",
        "creator",
        "type",
        "profile"
      ],
      "properties": {
        "$schema": {
          "type": "string"
        },
        "format": {
          "description": "Format version of this file.",
          "const": 1,
          "type": "number"
        },
        "id": {
          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
          "maxLength": 80,
          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
          "type": "string"
        },
        "title": {
          "minLength": 1,
          "maxLength": 40,
          "type": "string"
        },
        "creator": {
          "pattern": "^[a-z0-9_-]+$",
          "maxLength": 39,
          "description": "GitHub handle, lowercase.",
          "type": "string"
        },
        "description": {
          "minLength": 1,
          "maxLength": 240,
          "type": "string"
        },
        "ai_tools": {
          "maxItems": 8,
          "description": "AI tools used to make this file or its art. Required when any were used.",
          "type": "array",
          "items": {
            "minLength": 1,
            "maxLength": 60,
            "type": "string"
          }
        },
        "items": {
          "maxItems": 40,
          "type": "array",
          "items": {
            "additionalProperties": false,
            "type": "object",
            "required": [
              "id",
              "name",
              "kind",
              "rarity",
              "sprite"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              },
              "kind": {
                "anyOf": [
                  {
                    "const": "material",
                    "type": "string"
                  },
                  {
                    "const": "food",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "fragment",
                    "type": "string"
                  },
                  {
                    "const": "treasure",
                    "type": "string"
                  }
                ]
              },
              "rarity": {
                "description": "Declared rarity. The check compares it with the rarity computed from the data.",
                "anyOf": [
                  {
                    "const": "common",
                    "type": "string"
                  },
                  {
                    "const": "uncommon",
                    "type": "string"
                  },
                  {
                    "const": "rare",
                    "type": "string"
                  },
                  {
                    "const": "legendary",
                    "type": "string"
                  }
                ]
              },
              "class": {
                "description": "A base class (plant, wood, fibre, ...) or the id of a class an extension declares under one of them.",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  },
                  {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                ]
              },
              "family": {
                "pattern": "^[a-z0-9_-]+$",
                "maxLength": 24,
                "description": "A group inside the class, for example \"berry\" for every berry. Open: any lowercase word.",
                "type": "string"
              },
              "tags": {
                "maxItems": 8,
                "uniqueItems": true,
                "description": "Open words that describe it, for example \"sweet\" or \"night\".",
                "type": "array",
                "items": {
                  "pattern": "^[a-z0-9_-]+$",
                  "maxLength": 24,
                  "description": "A lowercase word.",
                  "type": "string"
                }
              },
              "tier": {
                "minimum": 1,
                "maximum": 20,
                "description": "How advanced it is, from 1. The rarity says how often it appears; the tier says how far up the ladder it is. A tool has the tier of its \"tool\".",
                "type": "integer"
              },
              "sprite": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
                "maxLength": 120,
                "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
                "type": "string"
              },
              "food": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "satiety"
                ],
                "properties": {
                  "satiety": {
                    "minimum": 0,
                    "maximum": 100,
                    "description": "Health points restored when eaten (the meter holds 100 at the start). 0 for a food that only hurts.",
                    "type": "integer"
                  },
                  "hurt": {
                    "minimum": 1,
                    "maximum": 100,
                    "description": "Health points it takes when eaten, at any hour: a bad fruit or a raw herb (G30).",
                    "type": "integer"
                  }
                }
              },
              "tool": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "kind",
                  "tier"
                ],
                "properties": {
                  "kind": {
                    "anyOf": [
                      {
                        "const": "basket",
                        "type": "string"
                      },
                      {
                        "const": "trowel",
                        "type": "string"
                      },
                      {
                        "const": "axe",
                        "type": "string"
                      },
                      {
                        "const": "staff",
                        "type": "string"
                      }
                    ]
                  },
                  "tier": {
                    "minimum": 1,
                    "maximum": 5,
                    "description": "Better tools work faster. The calculator clamps the total.",
                    "type": "integer"
                  },
                  "uses": {
                    "minimum": 1,
                    "maximum": 1000,
                    "description": "The tool wears out after this many uses. Left out, the tool lasts (DECISIONS.md, 2026-10-09: the crafting economy).",
                    "type": "integer"
                  }
                }
              },
              "fragment": {
                "additionalProperties": false,
                "description": "A found scrap that teaches a recipe.",
                "type": "object",
                "required": [
                  "unlocks"
                ],
                "properties": {
                  "unlocks": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                }
              },
              "wear": {
                "additionalProperties": false,
                "description": "Something the character wears (DECISIONS.md, 2026-10-09: the upgrade). A worn item stays in the bag.",
                "type": "object",
                "required": [
                  "slot"
                ],
                "properties": {
                  "slot": {
                    "description": "Where it is worn: head, top, legs (trousers), outfit (takes the top and the legs), feet, jewelry (two places) or hand (a tool).",
                    "anyOf": [
                      {
                        "const": "head",
                        "type": "string"
                      },
                      {
                        "const": "top",
                        "type": "string"
                      },
                      {
                        "const": "legs",
                        "type": "string"
                      },
                      {
                        "const": "outfit",
                        "type": "string"
                      },
                      {
                        "const": "feet",
                        "type": "string"
                      },
                      {
                        "const": "jewelry",
                        "type": "string"
                      },
                      {
                        "const": "hand",
                        "type": "string"
                      }
                    ]
                  },
                  "look": {
                    "description": "A look: worn on the look layer over the work clothes. It shows and counts for nothing, so it has no effects and no set.",
                    "type": "boolean"
                  },
                  "effects": {
                    "minItems": 1,
                    "maxItems": 2,
                    "description": "Small bonuses while it is worn on the work layer. Two at most, each effect once.",
                    "type": "array",
                    "items": {
                      "additionalProperties": false,
                      "type": "object",
                      "required": [
                        "effect",
                        "value"
                      ],
                      "properties": {
                        "effect": {
                          "description": "What a worn item helps: gathering, digging or crafting speed, the craft chance, or rare finds.",
                          "anyOf": [
                            {
                              "const": "gather_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "dig_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_chance_pct",
                              "type": "string"
                            },
                            {
                              "const": "rare_find_pct",
                              "type": "string"
                            }
                          ]
                        },
                        "value": {
                          "minimum": 1,
                          "maximum": 100,
                          "description": "Percent, at most the cap of the item's tier (params.wear_effect_max_pct).",
                          "type": "integer"
                        }
                      }
                    }
                  },
                  "set": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "A set of one creator: when every piece of it is worn, their effects grow by params.wear_set_bonus_pct.",
                    "type": "string"
                  }
                }
              },
              "premium_later": {
                "description": "Marks a look that may also be sold for premium currency once stage 6 brings it. Only a look item with no effect may carry it, and it stays obtainable in the game (DECISIONS.md, 2026-10-09).",
                "type": "boolean"
              }
            }
          }
        },
        "classes": {
          "maxItems": 10,
          "description": "Classes of your own, each under one base class.",
          "type": "array",
          "items": {
            "additionalProperties": false,
            "description": "A class of your own, declared under one base class. Every rule written for the base class holds for it.",
            "type": "object",
            "required": [
              "id",
              "name",
              "base"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "base": {
                "description": "plant (leaves, herbs, berries, fruit, roots, mushrooms), wood, fibre (reeds, grass, thread, cloth), stone, clay (clay, sand, pottery, brick), mineral (crystals, gems, salt, ore), metal (waits for its discovery), animal (feathers, wool, hide, bone), meal (cooked food), tool, garment (worn clothes), jewelry, relic (old things from the ruins).",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  }
                ]
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              }
            }
          }
        },
        "type": {
          "const": "creator",
          "type": "string"
        },
        "profile": {
          "additionalProperties": false,
          "type": "object",
          "required": [
            "name"
          ],
          "properties": {
            "name": {
              "minLength": 1,
              "maxLength": 40,
              "type": "string",
              "description": "How the game names you on signs and in the credits."
            },
            "role": {
              "minLength": 1,
              "maxLength": 40,
              "description": "A few words under your name, for example \"Main developer\".",
              "type": "string"
            },
            "signature": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "text",
                "style"
              ],
              "properties": {
                "text": {
                  "minLength": 1,
                  "maxLength": 24,
                  "description": "The words of your signature, shown over your signs without a click.",
                  "type": "string"
                },
                "style": {
                  "description": "\"carved\" (into stone), \"painted\" (on wood), \"ink\", \"gold\" (leaf) or \"moss\".",
                  "anyOf": [
                    {
                      "const": "carved",
                      "type": "string"
                    },
                    {
                      "const": "painted",
                      "type": "string"
                    },
                    {
                      "const": "ink",
                      "type": "string"
                    },
                    {
                      "const": "gold",
                      "type": "string"
                    },
                    {
                      "const": "moss",
                      "type": "string"
                    }
                  ]
                },
                "glyph": {
                  "description": "A small mark beside the words.",
                  "anyOf": [
                    {
                      "const": "none",
                      "type": "string"
                    },
                    {
                      "const": "leaf",
                      "type": "string"
                    },
                    {
                      "const": "star",
                      "type": "string"
                    },
                    {
                      "const": "sun",
                      "type": "string"
                    },
                    {
                      "const": "flower",
                      "type": "string"
                    },
                    {
                      "const": "key",
                      "type": "string"
                    },
                    {
                      "const": "wave",
                      "type": "string"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    {
      "additionalProperties": false,
      "$id": "shop",
      "type": "object",
      "required": [
        "format",
        "id",
        "title",
        "creator",
        "type",
        "shop"
      ],
      "properties": {
        "$schema": {
          "type": "string"
        },
        "format": {
          "description": "Format version of this file.",
          "const": 1,
          "type": "number"
        },
        "id": {
          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
          "maxLength": 80,
          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
          "type": "string"
        },
        "title": {
          "minLength": 1,
          "maxLength": 40,
          "type": "string"
        },
        "creator": {
          "pattern": "^[a-z0-9_-]+$",
          "maxLength": 39,
          "description": "GitHub handle, lowercase.",
          "type": "string"
        },
        "description": {
          "minLength": 1,
          "maxLength": 240,
          "type": "string"
        },
        "ai_tools": {
          "maxItems": 8,
          "description": "AI tools used to make this file or its art. Required when any were used.",
          "type": "array",
          "items": {
            "minLength": 1,
            "maxLength": 60,
            "type": "string"
          }
        },
        "items": {
          "maxItems": 40,
          "type": "array",
          "items": {
            "additionalProperties": false,
            "type": "object",
            "required": [
              "id",
              "name",
              "kind",
              "rarity",
              "sprite"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              },
              "kind": {
                "anyOf": [
                  {
                    "const": "material",
                    "type": "string"
                  },
                  {
                    "const": "food",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "fragment",
                    "type": "string"
                  },
                  {
                    "const": "treasure",
                    "type": "string"
                  }
                ]
              },
              "rarity": {
                "description": "Declared rarity. The check compares it with the rarity computed from the data.",
                "anyOf": [
                  {
                    "const": "common",
                    "type": "string"
                  },
                  {
                    "const": "uncommon",
                    "type": "string"
                  },
                  {
                    "const": "rare",
                    "type": "string"
                  },
                  {
                    "const": "legendary",
                    "type": "string"
                  }
                ]
              },
              "class": {
                "description": "A base class (plant, wood, fibre, ...) or the id of a class an extension declares under one of them.",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  },
                  {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                ]
              },
              "family": {
                "pattern": "^[a-z0-9_-]+$",
                "maxLength": 24,
                "description": "A group inside the class, for example \"berry\" for every berry. Open: any lowercase word.",
                "type": "string"
              },
              "tags": {
                "maxItems": 8,
                "uniqueItems": true,
                "description": "Open words that describe it, for example \"sweet\" or \"night\".",
                "type": "array",
                "items": {
                  "pattern": "^[a-z0-9_-]+$",
                  "maxLength": 24,
                  "description": "A lowercase word.",
                  "type": "string"
                }
              },
              "tier": {
                "minimum": 1,
                "maximum": 20,
                "description": "How advanced it is, from 1. The rarity says how often it appears; the tier says how far up the ladder it is. A tool has the tier of its \"tool\".",
                "type": "integer"
              },
              "sprite": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
                "maxLength": 120,
                "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
                "type": "string"
              },
              "food": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "satiety"
                ],
                "properties": {
                  "satiety": {
                    "minimum": 0,
                    "maximum": 100,
                    "description": "Health points restored when eaten (the meter holds 100 at the start). 0 for a food that only hurts.",
                    "type": "integer"
                  },
                  "hurt": {
                    "minimum": 1,
                    "maximum": 100,
                    "description": "Health points it takes when eaten, at any hour: a bad fruit or a raw herb (G30).",
                    "type": "integer"
                  }
                }
              },
              "tool": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "kind",
                  "tier"
                ],
                "properties": {
                  "kind": {
                    "anyOf": [
                      {
                        "const": "basket",
                        "type": "string"
                      },
                      {
                        "const": "trowel",
                        "type": "string"
                      },
                      {
                        "const": "axe",
                        "type": "string"
                      },
                      {
                        "const": "staff",
                        "type": "string"
                      }
                    ]
                  },
                  "tier": {
                    "minimum": 1,
                    "maximum": 5,
                    "description": "Better tools work faster. The calculator clamps the total.",
                    "type": "integer"
                  },
                  "uses": {
                    "minimum": 1,
                    "maximum": 1000,
                    "description": "The tool wears out after this many uses. Left out, the tool lasts (DECISIONS.md, 2026-10-09: the crafting economy).",
                    "type": "integer"
                  }
                }
              },
              "fragment": {
                "additionalProperties": false,
                "description": "A found scrap that teaches a recipe.",
                "type": "object",
                "required": [
                  "unlocks"
                ],
                "properties": {
                  "unlocks": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                }
              },
              "wear": {
                "additionalProperties": false,
                "description": "Something the character wears (DECISIONS.md, 2026-10-09: the upgrade). A worn item stays in the bag.",
                "type": "object",
                "required": [
                  "slot"
                ],
                "properties": {
                  "slot": {
                    "description": "Where it is worn: head, top, legs (trousers), outfit (takes the top and the legs), feet, jewelry (two places) or hand (a tool).",
                    "anyOf": [
                      {
                        "const": "head",
                        "type": "string"
                      },
                      {
                        "const": "top",
                        "type": "string"
                      },
                      {
                        "const": "legs",
                        "type": "string"
                      },
                      {
                        "const": "outfit",
                        "type": "string"
                      },
                      {
                        "const": "feet",
                        "type": "string"
                      },
                      {
                        "const": "jewelry",
                        "type": "string"
                      },
                      {
                        "const": "hand",
                        "type": "string"
                      }
                    ]
                  },
                  "look": {
                    "description": "A look: worn on the look layer over the work clothes. It shows and counts for nothing, so it has no effects and no set.",
                    "type": "boolean"
                  },
                  "effects": {
                    "minItems": 1,
                    "maxItems": 2,
                    "description": "Small bonuses while it is worn on the work layer. Two at most, each effect once.",
                    "type": "array",
                    "items": {
                      "additionalProperties": false,
                      "type": "object",
                      "required": [
                        "effect",
                        "value"
                      ],
                      "properties": {
                        "effect": {
                          "description": "What a worn item helps: gathering, digging or crafting speed, the craft chance, or rare finds.",
                          "anyOf": [
                            {
                              "const": "gather_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "dig_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_chance_pct",
                              "type": "string"
                            },
                            {
                              "const": "rare_find_pct",
                              "type": "string"
                            }
                          ]
                        },
                        "value": {
                          "minimum": 1,
                          "maximum": 100,
                          "description": "Percent, at most the cap of the item's tier (params.wear_effect_max_pct).",
                          "type": "integer"
                        }
                      }
                    }
                  },
                  "set": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "A set of one creator: when every piece of it is worn, their effects grow by params.wear_set_bonus_pct.",
                    "type": "string"
                  }
                }
              },
              "premium_later": {
                "description": "Marks a look that may also be sold for premium currency once stage 6 brings it. Only a look item with no effect may carry it, and it stays obtainable in the game (DECISIONS.md, 2026-10-09).",
                "type": "boolean"
              }
            }
          }
        },
        "classes": {
          "maxItems": 10,
          "description": "Classes of your own, each under one base class.",
          "type": "array",
          "items": {
            "additionalProperties": false,
            "description": "A class of your own, declared under one base class. Every rule written for the base class holds for it.",
            "type": "object",
            "required": [
              "id",
              "name",
              "base"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "base": {
                "description": "plant (leaves, herbs, berries, fruit, roots, mushrooms), wood, fibre (reeds, grass, thread, cloth), stone, clay (clay, sand, pottery, brick), mineral (crystals, gems, salt, ore), metal (waits for its discovery), animal (feathers, wool, hide, bone), meal (cooked food), tool, garment (worn clothes), jewelry, relic (old things from the ruins).",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  }
                ]
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              }
            }
          }
        },
        "type": {
          "const": "shop",
          "type": "string"
        },
        "shop": {
          "additionalProperties": false,
          "type": "object",
          "required": [
            "sells",
            "buys"
          ],
          "properties": {
            "sells": {
              "maxItems": 40,
              "type": "array",
              "items": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "item",
                  "price_mg"
                ],
                "properties": {
                  "item": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  },
                  "price_mg": {
                    "minimum": 1,
                    "maximum": 100000000,
                    "description": "Price in milli-gold (1000 = 1 gold).",
                    "type": "integer"
                  }
                }
              }
            },
            "buys": {
              "description": "Whether the shop buys anything that has a value.",
              "type": "boolean"
            }
          }
        }
      }
    },
    {
      "additionalProperties": false,
      "$id": "profession",
      "type": "object",
      "required": [
        "format",
        "id",
        "title",
        "creator",
        "type",
        "profession"
      ],
      "properties": {
        "$schema": {
          "type": "string"
        },
        "format": {
          "description": "Format version of this file.",
          "const": 1,
          "type": "number"
        },
        "id": {
          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
          "maxLength": 80,
          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
          "type": "string"
        },
        "title": {
          "minLength": 1,
          "maxLength": 40,
          "type": "string"
        },
        "creator": {
          "pattern": "^[a-z0-9_-]+$",
          "maxLength": 39,
          "description": "GitHub handle, lowercase.",
          "type": "string"
        },
        "description": {
          "minLength": 1,
          "maxLength": 240,
          "type": "string"
        },
        "ai_tools": {
          "maxItems": 8,
          "description": "AI tools used to make this file or its art. Required when any were used.",
          "type": "array",
          "items": {
            "minLength": 1,
            "maxLength": 60,
            "type": "string"
          }
        },
        "items": {
          "maxItems": 40,
          "type": "array",
          "items": {
            "additionalProperties": false,
            "type": "object",
            "required": [
              "id",
              "name",
              "kind",
              "rarity",
              "sprite"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              },
              "kind": {
                "anyOf": [
                  {
                    "const": "material",
                    "type": "string"
                  },
                  {
                    "const": "food",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "fragment",
                    "type": "string"
                  },
                  {
                    "const": "treasure",
                    "type": "string"
                  }
                ]
              },
              "rarity": {
                "description": "Declared rarity. The check compares it with the rarity computed from the data.",
                "anyOf": [
                  {
                    "const": "common",
                    "type": "string"
                  },
                  {
                    "const": "uncommon",
                    "type": "string"
                  },
                  {
                    "const": "rare",
                    "type": "string"
                  },
                  {
                    "const": "legendary",
                    "type": "string"
                  }
                ]
              },
              "class": {
                "description": "A base class (plant, wood, fibre, ...) or the id of a class an extension declares under one of them.",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  },
                  {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                ]
              },
              "family": {
                "pattern": "^[a-z0-9_-]+$",
                "maxLength": 24,
                "description": "A group inside the class, for example \"berry\" for every berry. Open: any lowercase word.",
                "type": "string"
              },
              "tags": {
                "maxItems": 8,
                "uniqueItems": true,
                "description": "Open words that describe it, for example \"sweet\" or \"night\".",
                "type": "array",
                "items": {
                  "pattern": "^[a-z0-9_-]+$",
                  "maxLength": 24,
                  "description": "A lowercase word.",
                  "type": "string"
                }
              },
              "tier": {
                "minimum": 1,
                "maximum": 20,
                "description": "How advanced it is, from 1. The rarity says how often it appears; the tier says how far up the ladder it is. A tool has the tier of its \"tool\".",
                "type": "integer"
              },
              "sprite": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
                "maxLength": 120,
                "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
                "type": "string"
              },
              "food": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "satiety"
                ],
                "properties": {
                  "satiety": {
                    "minimum": 0,
                    "maximum": 100,
                    "description": "Health points restored when eaten (the meter holds 100 at the start). 0 for a food that only hurts.",
                    "type": "integer"
                  },
                  "hurt": {
                    "minimum": 1,
                    "maximum": 100,
                    "description": "Health points it takes when eaten, at any hour: a bad fruit or a raw herb (G30).",
                    "type": "integer"
                  }
                }
              },
              "tool": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "kind",
                  "tier"
                ],
                "properties": {
                  "kind": {
                    "anyOf": [
                      {
                        "const": "basket",
                        "type": "string"
                      },
                      {
                        "const": "trowel",
                        "type": "string"
                      },
                      {
                        "const": "axe",
                        "type": "string"
                      },
                      {
                        "const": "staff",
                        "type": "string"
                      }
                    ]
                  },
                  "tier": {
                    "minimum": 1,
                    "maximum": 5,
                    "description": "Better tools work faster. The calculator clamps the total.",
                    "type": "integer"
                  },
                  "uses": {
                    "minimum": 1,
                    "maximum": 1000,
                    "description": "The tool wears out after this many uses. Left out, the tool lasts (DECISIONS.md, 2026-10-09: the crafting economy).",
                    "type": "integer"
                  }
                }
              },
              "fragment": {
                "additionalProperties": false,
                "description": "A found scrap that teaches a recipe.",
                "type": "object",
                "required": [
                  "unlocks"
                ],
                "properties": {
                  "unlocks": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                }
              },
              "wear": {
                "additionalProperties": false,
                "description": "Something the character wears (DECISIONS.md, 2026-10-09: the upgrade). A worn item stays in the bag.",
                "type": "object",
                "required": [
                  "slot"
                ],
                "properties": {
                  "slot": {
                    "description": "Where it is worn: head, top, legs (trousers), outfit (takes the top and the legs), feet, jewelry (two places) or hand (a tool).",
                    "anyOf": [
                      {
                        "const": "head",
                        "type": "string"
                      },
                      {
                        "const": "top",
                        "type": "string"
                      },
                      {
                        "const": "legs",
                        "type": "string"
                      },
                      {
                        "const": "outfit",
                        "type": "string"
                      },
                      {
                        "const": "feet",
                        "type": "string"
                      },
                      {
                        "const": "jewelry",
                        "type": "string"
                      },
                      {
                        "const": "hand",
                        "type": "string"
                      }
                    ]
                  },
                  "look": {
                    "description": "A look: worn on the look layer over the work clothes. It shows and counts for nothing, so it has no effects and no set.",
                    "type": "boolean"
                  },
                  "effects": {
                    "minItems": 1,
                    "maxItems": 2,
                    "description": "Small bonuses while it is worn on the work layer. Two at most, each effect once.",
                    "type": "array",
                    "items": {
                      "additionalProperties": false,
                      "type": "object",
                      "required": [
                        "effect",
                        "value"
                      ],
                      "properties": {
                        "effect": {
                          "description": "What a worn item helps: gathering, digging or crafting speed, the craft chance, or rare finds.",
                          "anyOf": [
                            {
                              "const": "gather_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "dig_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_chance_pct",
                              "type": "string"
                            },
                            {
                              "const": "rare_find_pct",
                              "type": "string"
                            }
                          ]
                        },
                        "value": {
                          "minimum": 1,
                          "maximum": 100,
                          "description": "Percent, at most the cap of the item's tier (params.wear_effect_max_pct).",
                          "type": "integer"
                        }
                      }
                    }
                  },
                  "set": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "A set of one creator: when every piece of it is worn, their effects grow by params.wear_set_bonus_pct.",
                    "type": "string"
                  }
                }
              },
              "premium_later": {
                "description": "Marks a look that may also be sold for premium currency once stage 6 brings it. Only a look item with no effect may carry it, and it stays obtainable in the game (DECISIONS.md, 2026-10-09).",
                "type": "boolean"
              }
            }
          }
        },
        "classes": {
          "maxItems": 10,
          "description": "Classes of your own, each under one base class.",
          "type": "array",
          "items": {
            "additionalProperties": false,
            "description": "A class of your own, declared under one base class. Every rule written for the base class holds for it.",
            "type": "object",
            "required": [
              "id",
              "name",
              "base"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "base": {
                "description": "plant (leaves, herbs, berries, fruit, roots, mushrooms), wood, fibre (reeds, grass, thread, cloth), stone, clay (clay, sand, pottery, brick), mineral (crystals, gems, salt, ore), metal (waits for its discovery), animal (feathers, wool, hide, bone), meal (cooked food), tool, garment (worn clothes), jewelry, relic (old things from the ruins).",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  }
                ]
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              }
            }
          }
        },
        "type": {
          "const": "profession",
          "type": "string"
        },
        "profession": {
          "additionalProperties": false,
          "type": "object",
          "required": [
            "name",
            "verb",
            "xp_levels",
            "techniques"
          ],
          "properties": {
            "name": {
              "minLength": 1,
              "maxLength": 40,
              "type": "string"
            },
            "verb": {
              "anyOf": [
                {
                  "const": "gather",
                  "type": "string"
                },
                {
                  "const": "fell",
                  "type": "string"
                },
                {
                  "const": "dig",
                  "type": "string"
                },
                {
                  "const": "craft",
                  "type": "string"
                }
              ]
            },
            "stations": {
              "minItems": 1,
              "maxItems": 4,
              "uniqueItems": true,
              "description": "A craft profession only: the stations whose recipes it gates when a recipe names no profession. One profession per station.",
              "type": "array",
              "items": {
                "anyOf": [
                  {
                    "const": "fire",
                    "type": "string"
                  },
                  {
                    "const": "workshop",
                    "type": "string"
                  }
                ]
              }
            },
            "xp_levels": {
              "minItems": 1,
              "maxItems": 20,
              "description": "Total experience (active seconds) needed for level 2, 3, ...",
              "type": "array",
              "items": {
                "minimum": 1,
                "maximum": 10000000,
                "type": "integer"
              }
            },
            "techniques": {
              "maxItems": 10,
              "type": "array",
              "items": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "level",
                  "name",
                  "effect",
                  "value",
                  "text"
                ],
                "properties": {
                  "level": {
                    "minimum": 2,
                    "maximum": 20,
                    "type": "integer"
                  },
                  "name": {
                    "minLength": 1,
                    "maxLength": 40,
                    "type": "string"
                  },
                  "effect": {
                    "description": "What a technique does. A closed list: the kernel knows how to apply each one. A craft effect of a technique (craft_speed_pct, craft_chance_pct) helps the recipes of its own profession.",
                    "anyOf": [
                      {
                        "const": "see_ripe",
                        "type": "string"
                      },
                      {
                        "const": "timing_window_pct",
                        "type": "string"
                      },
                      {
                        "const": "second_hint",
                        "type": "string"
                      },
                      {
                        "const": "rare_find_pct",
                        "type": "string"
                      },
                      {
                        "const": "craft_speed_pct",
                        "type": "string"
                      },
                      {
                        "const": "meal_fill_pct",
                        "type": "string"
                      },
                      {
                        "const": "gather_speed_pct",
                        "type": "string"
                      },
                      {
                        "const": "dig_speed_pct",
                        "type": "string"
                      },
                      {
                        "const": "craft_chance_pct",
                        "type": "string"
                      }
                    ]
                  },
                  "value": {
                    "minimum": 0,
                    "maximum": 100,
                    "type": "integer"
                  },
                  "text": {
                    "minLength": 1,
                    "maxLength": 240,
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    },
    {
      "additionalProperties": false,
      "$id": "params",
      "type": "object",
      "required": [
        "format",
        "id",
        "title",
        "creator",
        "type",
        "params"
      ],
      "properties": {
        "$schema": {
          "type": "string"
        },
        "format": {
          "description": "Format version of this file.",
          "const": 1,
          "type": "number"
        },
        "id": {
          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
          "maxLength": 80,
          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
          "type": "string"
        },
        "title": {
          "minLength": 1,
          "maxLength": 40,
          "type": "string"
        },
        "creator": {
          "pattern": "^[a-z0-9_-]+$",
          "maxLength": 39,
          "description": "GitHub handle, lowercase.",
          "type": "string"
        },
        "description": {
          "minLength": 1,
          "maxLength": 240,
          "type": "string"
        },
        "ai_tools": {
          "maxItems": 8,
          "description": "AI tools used to make this file or its art. Required when any were used.",
          "type": "array",
          "items": {
            "minLength": 1,
            "maxLength": 60,
            "type": "string"
          }
        },
        "items": {
          "maxItems": 40,
          "type": "array",
          "items": {
            "additionalProperties": false,
            "type": "object",
            "required": [
              "id",
              "name",
              "kind",
              "rarity",
              "sprite"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              },
              "kind": {
                "anyOf": [
                  {
                    "const": "material",
                    "type": "string"
                  },
                  {
                    "const": "food",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "fragment",
                    "type": "string"
                  },
                  {
                    "const": "treasure",
                    "type": "string"
                  }
                ]
              },
              "rarity": {
                "description": "Declared rarity. The check compares it with the rarity computed from the data.",
                "anyOf": [
                  {
                    "const": "common",
                    "type": "string"
                  },
                  {
                    "const": "uncommon",
                    "type": "string"
                  },
                  {
                    "const": "rare",
                    "type": "string"
                  },
                  {
                    "const": "legendary",
                    "type": "string"
                  }
                ]
              },
              "class": {
                "description": "A base class (plant, wood, fibre, ...) or the id of a class an extension declares under one of them.",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  },
                  {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                ]
              },
              "family": {
                "pattern": "^[a-z0-9_-]+$",
                "maxLength": 24,
                "description": "A group inside the class, for example \"berry\" for every berry. Open: any lowercase word.",
                "type": "string"
              },
              "tags": {
                "maxItems": 8,
                "uniqueItems": true,
                "description": "Open words that describe it, for example \"sweet\" or \"night\".",
                "type": "array",
                "items": {
                  "pattern": "^[a-z0-9_-]+$",
                  "maxLength": 24,
                  "description": "A lowercase word.",
                  "type": "string"
                }
              },
              "tier": {
                "minimum": 1,
                "maximum": 20,
                "description": "How advanced it is, from 1. The rarity says how often it appears; the tier says how far up the ladder it is. A tool has the tier of its \"tool\".",
                "type": "integer"
              },
              "sprite": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
                "maxLength": 120,
                "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
                "type": "string"
              },
              "food": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "satiety"
                ],
                "properties": {
                  "satiety": {
                    "minimum": 0,
                    "maximum": 100,
                    "description": "Health points restored when eaten (the meter holds 100 at the start). 0 for a food that only hurts.",
                    "type": "integer"
                  },
                  "hurt": {
                    "minimum": 1,
                    "maximum": 100,
                    "description": "Health points it takes when eaten, at any hour: a bad fruit or a raw herb (G30).",
                    "type": "integer"
                  }
                }
              },
              "tool": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "kind",
                  "tier"
                ],
                "properties": {
                  "kind": {
                    "anyOf": [
                      {
                        "const": "basket",
                        "type": "string"
                      },
                      {
                        "const": "trowel",
                        "type": "string"
                      },
                      {
                        "const": "axe",
                        "type": "string"
                      },
                      {
                        "const": "staff",
                        "type": "string"
                      }
                    ]
                  },
                  "tier": {
                    "minimum": 1,
                    "maximum": 5,
                    "description": "Better tools work faster. The calculator clamps the total.",
                    "type": "integer"
                  },
                  "uses": {
                    "minimum": 1,
                    "maximum": 1000,
                    "description": "The tool wears out after this many uses. Left out, the tool lasts (DECISIONS.md, 2026-10-09: the crafting economy).",
                    "type": "integer"
                  }
                }
              },
              "fragment": {
                "additionalProperties": false,
                "description": "A found scrap that teaches a recipe.",
                "type": "object",
                "required": [
                  "unlocks"
                ],
                "properties": {
                  "unlocks": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                }
              },
              "wear": {
                "additionalProperties": false,
                "description": "Something the character wears (DECISIONS.md, 2026-10-09: the upgrade). A worn item stays in the bag.",
                "type": "object",
                "required": [
                  "slot"
                ],
                "properties": {
                  "slot": {
                    "description": "Where it is worn: head, top, legs (trousers), outfit (takes the top and the legs), feet, jewelry (two places) or hand (a tool).",
                    "anyOf": [
                      {
                        "const": "head",
                        "type": "string"
                      },
                      {
                        "const": "top",
                        "type": "string"
                      },
                      {
                        "const": "legs",
                        "type": "string"
                      },
                      {
                        "const": "outfit",
                        "type": "string"
                      },
                      {
                        "const": "feet",
                        "type": "string"
                      },
                      {
                        "const": "jewelry",
                        "type": "string"
                      },
                      {
                        "const": "hand",
                        "type": "string"
                      }
                    ]
                  },
                  "look": {
                    "description": "A look: worn on the look layer over the work clothes. It shows and counts for nothing, so it has no effects and no set.",
                    "type": "boolean"
                  },
                  "effects": {
                    "minItems": 1,
                    "maxItems": 2,
                    "description": "Small bonuses while it is worn on the work layer. Two at most, each effect once.",
                    "type": "array",
                    "items": {
                      "additionalProperties": false,
                      "type": "object",
                      "required": [
                        "effect",
                        "value"
                      ],
                      "properties": {
                        "effect": {
                          "description": "What a worn item helps: gathering, digging or crafting speed, the craft chance, or rare finds.",
                          "anyOf": [
                            {
                              "const": "gather_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "dig_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_chance_pct",
                              "type": "string"
                            },
                            {
                              "const": "rare_find_pct",
                              "type": "string"
                            }
                          ]
                        },
                        "value": {
                          "minimum": 1,
                          "maximum": 100,
                          "description": "Percent, at most the cap of the item's tier (params.wear_effect_max_pct).",
                          "type": "integer"
                        }
                      }
                    }
                  },
                  "set": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "A set of one creator: when every piece of it is worn, their effects grow by params.wear_set_bonus_pct.",
                    "type": "string"
                  }
                }
              },
              "premium_later": {
                "description": "Marks a look that may also be sold for premium currency once stage 6 brings it. Only a look item with no effect may carry it, and it stays obtainable in the game (DECISIONS.md, 2026-10-09).",
                "type": "boolean"
              }
            }
          }
        },
        "classes": {
          "maxItems": 10,
          "description": "Classes of your own, each under one base class.",
          "type": "array",
          "items": {
            "additionalProperties": false,
            "description": "A class of your own, declared under one base class. Every rule written for the base class holds for it.",
            "type": "object",
            "required": [
              "id",
              "name",
              "base"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "base": {
                "description": "plant (leaves, herbs, berries, fruit, roots, mushrooms), wood, fibre (reeds, grass, thread, cloth), stone, clay (clay, sand, pottery, brick), mineral (crystals, gems, salt, ore), metal (waits for its discovery), animal (feathers, wool, hide, bone), meal (cooked food), tool, garment (worn clothes), jewelry, relic (old things from the ruins).",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  }
                ]
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              }
            }
          }
        },
        "type": {
          "const": "params",
          "type": "string"
        },
        "params": {
          "additionalProperties": false,
          "type": "object",
          "required": [
            "k_permille",
            "k_craft_permille",
            "r_mg_per_value_ms",
            "t_min_ms",
            "max_action_ms",
            "effort_permille",
            "power_cap_permille",
            "rarity_budget_permille",
            "open_tiers",
            "tier_min_level",
            "template_max_recipes",
            "craft_chance_bp",
            "craft_level_step_bp",
            "craft_luck_max_permille",
            "craft_miss_keep_pct",
            "wear_effect_max_pct",
            "wear_set_bonus_pct",
            "rarity_bonus_ms",
            "drift_budget_permille",
            "satiety_cap",
            "satiety_drain_per_min",
            "day_length_ms",
            "walk_step_ms",
            "hp_low_pct",
            "hazard",
            "bag_base",
            "starting_gold_mg",
            "per_point"
          ],
          "properties": {
            "k_permille": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "value",
                "min",
                "max",
                "step"
              ],
              "properties": {
                "value": {
                  "type": "integer"
                },
                "min": {
                  "type": "integer"
                },
                "max": {
                  "type": "integer"
                },
                "step": {
                  "minimum": 0,
                  "description": "Largest change one decision may make.",
                  "type": "integer"
                }
              }
            },
            "k_craft_permille": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "value",
                "min",
                "max",
                "step"
              ],
              "properties": {
                "value": {
                  "type": "integer"
                },
                "min": {
                  "type": "integer"
                },
                "max": {
                  "type": "integer"
                },
                "step": {
                  "minimum": 0,
                  "description": "Largest change one decision may make.",
                  "type": "integer"
                }
              },
              "description": "What the trader pays for a made good, an item whose value comes from a recipe, per mille of r * V; k_permille holds for the rest. At least k_permille and always below 1000, so the trader never pays what the shop charges (DECISIONS.md, 2026-10-09: the crafting economy)."
            },
            "r_mg_per_value_ms": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "value",
                "min",
                "max",
                "step"
              ],
              "properties": {
                "value": {
                  "type": "integer"
                },
                "min": {
                  "type": "integer"
                },
                "max": {
                  "type": "integer"
                },
                "step": {
                  "minimum": 0,
                  "description": "Largest change one decision may make.",
                  "type": "integer"
                }
              }
            },
            "t_min_ms": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "value",
                "min",
                "max",
                "step"
              ],
              "properties": {
                "value": {
                  "type": "integer"
                },
                "min": {
                  "type": "integer"
                },
                "max": {
                  "type": "integer"
                },
                "step": {
                  "minimum": 0,
                  "description": "Largest change one decision may make.",
                  "type": "integer"
                }
              }
            },
            "max_action_ms": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "value",
                "min",
                "max",
                "step"
              ],
              "properties": {
                "value": {
                  "type": "integer"
                },
                "min": {
                  "type": "integer"
                },
                "max": {
                  "type": "integer"
                },
                "step": {
                  "minimum": 0,
                  "description": "Largest change one decision may make.",
                  "type": "integer"
                }
              }
            },
            "effort_permille": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "easy",
                "medium",
                "craft",
                "hard"
              ],
              "properties": {
                "easy": {
                  "additionalProperties": false,
                  "type": "object",
                  "required": [
                    "value",
                    "min",
                    "max",
                    "step"
                  ],
                  "properties": {
                    "value": {
                      "type": "integer"
                    },
                    "min": {
                      "type": "integer"
                    },
                    "max": {
                      "type": "integer"
                    },
                    "step": {
                      "minimum": 0,
                      "description": "Largest change one decision may make.",
                      "type": "integer"
                    }
                  }
                },
                "medium": {
                  "additionalProperties": false,
                  "type": "object",
                  "required": [
                    "value",
                    "min",
                    "max",
                    "step"
                  ],
                  "properties": {
                    "value": {
                      "type": "integer"
                    },
                    "min": {
                      "type": "integer"
                    },
                    "max": {
                      "type": "integer"
                    },
                    "step": {
                      "minimum": 0,
                      "description": "Largest change one decision may make.",
                      "type": "integer"
                    }
                  }
                },
                "craft": {
                  "additionalProperties": false,
                  "type": "object",
                  "required": [
                    "value",
                    "min",
                    "max",
                    "step"
                  ],
                  "properties": {
                    "value": {
                      "type": "integer"
                    },
                    "min": {
                      "type": "integer"
                    },
                    "max": {
                      "type": "integer"
                    },
                    "step": {
                      "minimum": 0,
                      "description": "Largest change one decision may make.",
                      "type": "integer"
                    }
                  }
                },
                "hard": {
                  "additionalProperties": false,
                  "type": "object",
                  "required": [
                    "value",
                    "min",
                    "max",
                    "step"
                  ],
                  "properties": {
                    "value": {
                      "type": "integer"
                    },
                    "min": {
                      "type": "integer"
                    },
                    "max": {
                      "type": "integer"
                    },
                    "step": {
                      "minimum": 0,
                      "description": "Largest change one decision may make.",
                      "type": "integer"
                    }
                  }
                }
              }
            },
            "power_cap_permille": {
              "minItems": 1,
              "maxItems": 40,
              "description": "P(level): the clamp on any rate multiplier, by character level (1-based).",
              "type": "array",
              "items": {
                "minimum": 1000,
                "maximum": 10000,
                "type": "integer"
              }
            },
            "rarity_budget_permille": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "value",
                "min",
                "max",
                "step"
              ],
              "properties": {
                "value": {
                  "type": "integer"
                },
                "min": {
                  "type": "integer"
                },
                "max": {
                  "type": "integer"
                },
                "step": {
                  "minimum": 0,
                  "description": "Largest change one decision may make.",
                  "type": "integer"
                }
              }
            },
            "open_tiers": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "value",
                "min",
                "max",
                "step"
              ],
              "properties": {
                "value": {
                  "type": "integer"
                },
                "min": {
                  "type": "integer"
                },
                "max": {
                  "type": "integer"
                },
                "step": {
                  "minimum": 0,
                  "description": "Largest change one decision may make.",
                  "type": "integer"
                }
              },
              "description": "The highest item tier the world has opened. A stage or a new town opens the next one."
            },
            "tier_min_level": {
              "minItems": 1,
              "maxItems": 20,
              "description": "The lowest level of each tier, from tier 1. A recipe of tier t needs a level from entry t up to one below entry t + 1 (up to 20 for the last), and a node that gives tier 3 or above needs at least entry t, or a slow respawn. Starts at 1 and rises with every tier; one entry for every open tier at least.",
              "type": "array",
              "items": {
                "minimum": 1,
                "maximum": 20,
                "type": "integer"
              }
            },
            "template_max_recipes": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "value",
                "min",
                "max",
                "step"
              ],
              "properties": {
                "value": {
                  "type": "integer"
                },
                "min": {
                  "type": "integer"
                },
                "max": {
                  "type": "integer"
                },
                "step": {
                  "minimum": 0,
                  "description": "Largest change one decision may make.",
                  "type": "integer"
                }
              },
              "description": "The most recipes one recipe template may make."
            },
            "craft_chance_bp": {
              "minItems": 1,
              "maxItems": 20,
              "description": "The chance a craft succeeds at exactly its level, in basis points, by the recipe's tier from tier 1; the last entry holds for the tiers above it. Never rises with the tier; 10000 is a sure craft.",
              "type": "array",
              "items": {
                "minimum": 1000,
                "maximum": 10000,
                "type": "integer"
              }
            },
            "craft_level_step_bp": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "value",
                "min",
                "max",
                "step"
              ],
              "properties": {
                "value": {
                  "type": "integer"
                },
                "min": {
                  "type": "integer"
                },
                "max": {
                  "type": "integer"
                },
                "step": {
                  "minimum": 0,
                  "description": "Largest change one decision may make.",
                  "type": "integer"
                }
              },
              "description": "What each level of the recipe's profession above the recipe's level adds to the craft chance, in basis points."
            },
            "craft_luck_max_permille": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "value",
                "min",
                "max",
                "step"
              ],
              "properties": {
                "value": {
                  "type": "integer"
                },
                "min": {
                  "type": "integer"
                },
                "max": {
                  "type": "integer"
                },
                "step": {
                  "minimum": 0,
                  "description": "Largest change one decision may make.",
                  "type": "integer"
                }
              },
              "description": "The largest part of the gap to a sure craft that luck and luck items close, in permille: skill decides, luck tilts (G40)."
            },
            "craft_miss_keep_pct": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "value",
                "min",
                "max",
                "step"
              ],
              "properties": {
                "value": {
                  "type": "integer"
                },
                "min": {
                  "type": "integer"
                },
                "max": {
                  "type": "integer"
                },
                "step": {
                  "minimum": 0,
                  "description": "Largest change one decision may make.",
                  "type": "integer"
                }
              },
              "description": "Part of each input a missed craft keeps when the recipe names no share, rounded down."
            },
            "wear_effect_max_pct": {
              "minItems": 1,
              "maxItems": 20,
              "description": "The largest value of one effect on a worn item, by the item's tier from tier 1; the last entry holds for the tiers above it. Never falls with the tier.",
              "type": "array",
              "items": {
                "minimum": 0,
                "maximum": 100,
                "type": "integer"
              }
            },
            "wear_set_bonus_pct": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "value",
                "min",
                "max",
                "step"
              ],
              "properties": {
                "value": {
                  "type": "integer"
                },
                "min": {
                  "type": "integer"
                },
                "max": {
                  "type": "integer"
                },
                "step": {
                  "minimum": 0,
                  "description": "Largest change one decision may make.",
                  "type": "integer"
                }
              },
              "description": "How much a full set adds to the effects of its pieces, in percent of their sum, rounded down."
            },
            "rarity_bonus_ms": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "common",
                "uncommon",
                "rare",
                "legendary"
              ],
              "properties": {
                "common": {
                  "type": "integer"
                },
                "uncommon": {
                  "type": "integer"
                },
                "rare": {
                  "type": "integer"
                },
                "legendary": {
                  "type": "integer"
                }
              }
            },
            "drift_budget_permille": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "value",
                "min",
                "max",
                "step"
              ],
              "properties": {
                "value": {
                  "type": "integer"
                },
                "min": {
                  "type": "integer"
                },
                "max": {
                  "type": "integer"
                },
                "step": {
                  "minimum": 0,
                  "description": "Largest change one decision may make.",
                  "type": "integer"
                }
              }
            },
            "satiety_cap": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "value",
                "min",
                "max",
                "step"
              ],
              "properties": {
                "value": {
                  "type": "integer"
                },
                "min": {
                  "type": "integer"
                },
                "max": {
                  "type": "integer"
                },
                "step": {
                  "minimum": 0,
                  "description": "Largest change one decision may make.",
                  "type": "integer"
                }
              }
            },
            "satiety_drain_per_min": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "value",
                "min",
                "max",
                "step"
              ],
              "properties": {
                "value": {
                  "type": "integer"
                },
                "min": {
                  "type": "integer"
                },
                "max": {
                  "type": "integer"
                },
                "step": {
                  "minimum": 0,
                  "description": "Largest change one decision may make.",
                  "type": "integer"
                }
              }
            },
            "day_length_ms": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "value",
                "min",
                "max",
                "step"
              ],
              "properties": {
                "value": {
                  "type": "integer"
                },
                "min": {
                  "type": "integer"
                },
                "max": {
                  "type": "integer"
                },
                "step": {
                  "minimum": 0,
                  "description": "Largest change one decision may make.",
                  "type": "integer"
                }
              }
            },
            "walk_step_ms": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "value",
                "min",
                "max",
                "step"
              ],
              "properties": {
                "value": {
                  "type": "integer"
                },
                "min": {
                  "type": "integer"
                },
                "max": {
                  "type": "integer"
                },
                "step": {
                  "minimum": 0,
                  "description": "Largest change one decision may make.",
                  "type": "integer"
                }
              },
              "description": "Milliseconds the player takes to walk one tile. The client walks at this pace; the kernel checks a position report against it (DECISIONS.md, 2026-10-10: health and hazards)."
            },
            "hp_low_pct": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "value",
                "min",
                "max",
                "step"
              ],
              "properties": {
                "value": {
                  "type": "integer"
                },
                "min": {
                  "type": "integer"
                },
                "max": {
                  "type": "integer"
                },
                "step": {
                  "minimum": 0,
                  "description": "Largest change one decision may make.",
                  "type": "integer"
                }
              },
              "description": "Work takes half as long again while health is at or below this share of its cap, in percent. 0 slows it only when health is empty (G32)."
            },
            "hazard": {
              "additionalProperties": false,
              "description": "How hard each kind of hazard hits (G30, G34). A hazard is a rule, not a roll.",
              "type": "object",
              "required": [
                "predator",
                "pit",
                "trap",
                "deep_water"
              ],
              "properties": {
                "predator": {
                  "additionalProperties": false,
                  "type": "object",
                  "required": [
                    "reach",
                    "catch_ms",
                    "bite_ms",
                    "bite_pct"
                  ],
                  "properties": {
                    "reach": {
                      "additionalProperties": false,
                      "type": "object",
                      "required": [
                        "value",
                        "min",
                        "max",
                        "step"
                      ],
                      "properties": {
                        "value": {
                          "type": "integer"
                        },
                        "min": {
                          "type": "integer"
                        },
                        "max": {
                          "type": "integer"
                        },
                        "step": {
                          "minimum": 0,
                          "description": "Largest change one decision may make.",
                          "type": "integer"
                        }
                      },
                      "description": "Tiles from its footprint within which a predator notices the player, unless the prop says otherwise."
                    },
                    "catch_ms": {
                      "additionalProperties": false,
                      "type": "object",
                      "required": [
                        "value",
                        "min",
                        "max",
                        "step"
                      ],
                      "properties": {
                        "value": {
                          "type": "integer"
                        },
                        "min": {
                          "type": "integer"
                        },
                        "max": {
                          "type": "integer"
                        },
                        "step": {
                          "minimum": 0,
                          "description": "Largest change one decision may make.",
                          "type": "integer"
                        }
                      },
                      "description": "From the start of a chase to the first bite."
                    },
                    "bite_ms": {
                      "additionalProperties": false,
                      "type": "object",
                      "required": [
                        "value",
                        "min",
                        "max",
                        "step"
                      ],
                      "properties": {
                        "value": {
                          "type": "integer"
                        },
                        "min": {
                          "type": "integer"
                        },
                        "max": {
                          "type": "integer"
                        },
                        "step": {
                          "minimum": 0,
                          "description": "Largest change one decision may make.",
                          "type": "integer"
                        }
                      },
                      "description": "Between one bite and the next."
                    },
                    "bite_pct": {
                      "additionalProperties": false,
                      "type": "object",
                      "required": [
                        "value",
                        "min",
                        "max",
                        "step"
                      ],
                      "properties": {
                        "value": {
                          "type": "integer"
                        },
                        "min": {
                          "type": "integer"
                        },
                        "max": {
                          "type": "integer"
                        },
                        "step": {
                          "minimum": 0,
                          "description": "Largest change one decision may make.",
                          "type": "integer"
                        }
                      },
                      "description": "What one bite takes, in percent of the health cap."
                    }
                  }
                },
                "pit": {
                  "additionalProperties": false,
                  "type": "object",
                  "required": [
                    "harm_pct"
                  ],
                  "properties": {
                    "harm_pct": {
                      "additionalProperties": false,
                      "type": "object",
                      "required": [
                        "value",
                        "min",
                        "max",
                        "step"
                      ],
                      "properties": {
                        "value": {
                          "type": "integer"
                        },
                        "min": {
                          "type": "integer"
                        },
                        "max": {
                          "type": "integer"
                        },
                        "step": {
                          "minimum": 0,
                          "description": "Largest change one decision may make.",
                          "type": "integer"
                        }
                      },
                      "description": "What stepping into a pit takes, in percent of the health cap."
                    }
                  }
                },
                "trap": {
                  "additionalProperties": false,
                  "type": "object",
                  "required": [
                    "harm_pct"
                  ],
                  "properties": {
                    "harm_pct": {
                      "additionalProperties": false,
                      "type": "object",
                      "required": [
                        "value",
                        "min",
                        "max",
                        "step"
                      ],
                      "properties": {
                        "value": {
                          "type": "integer"
                        },
                        "min": {
                          "type": "integer"
                        },
                        "max": {
                          "type": "integer"
                        },
                        "step": {
                          "minimum": 0,
                          "description": "Largest change one decision may make.",
                          "type": "integer"
                        }
                      },
                      "description": "What stepping on a trap takes, in percent of the health cap."
                    }
                  }
                },
                "deep_water": {
                  "additionalProperties": false,
                  "type": "object",
                  "required": [
                    "harm_pct"
                  ],
                  "properties": {
                    "harm_pct": {
                      "additionalProperties": false,
                      "type": "object",
                      "required": [
                        "value",
                        "min",
                        "max",
                        "step"
                      ],
                      "properties": {
                        "value": {
                          "type": "integer"
                        },
                        "min": {
                          "type": "integer"
                        },
                        "max": {
                          "type": "integer"
                        },
                        "step": {
                          "minimum": 0,
                          "description": "Largest change one decision may make.",
                          "type": "integer"
                        }
                      },
                      "description": "What stepping into deep water takes, in percent of the health cap."
                    }
                  }
                }
              }
            },
            "bag_base": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "value",
                "min",
                "max",
                "step"
              ],
              "properties": {
                "value": {
                  "type": "integer"
                },
                "min": {
                  "type": "integer"
                },
                "max": {
                  "type": "integer"
                },
                "step": {
                  "minimum": 0,
                  "description": "Largest change one decision may make.",
                  "type": "integer"
                }
              }
            },
            "starting_gold_mg": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "value",
                "min",
                "max",
                "step"
              ],
              "properties": {
                "value": {
                  "type": "integer"
                },
                "min": {
                  "type": "integer"
                },
                "max": {
                  "type": "integer"
                },
                "step": {
                  "minimum": 0,
                  "description": "Largest change one decision may make.",
                  "type": "integer"
                }
              }
            },
            "per_point": {
              "additionalProperties": false,
              "description": "What one point in an attribute adds: bag places (carry), tiles of dig-hint distance (senses), percent wider timing windows in every minigame (agility), permille on rare and legendary finds inside the power cap and on keeping one unit after a missed gather (luck), and fullness (stamina).",
              "type": "object",
              "required": [
                "carry",
                "senses",
                "agility_pct",
                "luck_permille",
                "stamina"
              ],
              "properties": {
                "carry": {
                  "additionalProperties": false,
                  "type": "object",
                  "required": [
                    "value",
                    "min",
                    "max",
                    "step"
                  ],
                  "properties": {
                    "value": {
                      "type": "integer"
                    },
                    "min": {
                      "type": "integer"
                    },
                    "max": {
                      "type": "integer"
                    },
                    "step": {
                      "minimum": 0,
                      "description": "Largest change one decision may make.",
                      "type": "integer"
                    }
                  }
                },
                "senses": {
                  "additionalProperties": false,
                  "type": "object",
                  "required": [
                    "value",
                    "min",
                    "max",
                    "step"
                  ],
                  "properties": {
                    "value": {
                      "type": "integer"
                    },
                    "min": {
                      "type": "integer"
                    },
                    "max": {
                      "type": "integer"
                    },
                    "step": {
                      "minimum": 0,
                      "description": "Largest change one decision may make.",
                      "type": "integer"
                    }
                  }
                },
                "agility_pct": {
                  "additionalProperties": false,
                  "type": "object",
                  "required": [
                    "value",
                    "min",
                    "max",
                    "step"
                  ],
                  "properties": {
                    "value": {
                      "type": "integer"
                    },
                    "min": {
                      "type": "integer"
                    },
                    "max": {
                      "type": "integer"
                    },
                    "step": {
                      "minimum": 0,
                      "description": "Largest change one decision may make.",
                      "type": "integer"
                    }
                  }
                },
                "luck_permille": {
                  "additionalProperties": false,
                  "type": "object",
                  "required": [
                    "value",
                    "min",
                    "max",
                    "step"
                  ],
                  "properties": {
                    "value": {
                      "type": "integer"
                    },
                    "min": {
                      "type": "integer"
                    },
                    "max": {
                      "type": "integer"
                    },
                    "step": {
                      "minimum": 0,
                      "description": "Largest change one decision may make.",
                      "type": "integer"
                    }
                  }
                },
                "stamina": {
                  "additionalProperties": false,
                  "type": "object",
                  "required": [
                    "value",
                    "min",
                    "max",
                    "step"
                  ],
                  "properties": {
                    "value": {
                      "type": "integer"
                    },
                    "min": {
                      "type": "integer"
                    },
                    "max": {
                      "type": "integer"
                    },
                    "step": {
                      "minimum": 0,
                      "description": "Largest change one decision may make.",
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    {
      "additionalProperties": false,
      "$id": "kit",
      "type": "object",
      "required": [
        "format",
        "id",
        "title",
        "creator",
        "type",
        "kit"
      ],
      "properties": {
        "$schema": {
          "type": "string"
        },
        "format": {
          "description": "Format version of this file.",
          "const": 1,
          "type": "number"
        },
        "id": {
          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
          "maxLength": 80,
          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
          "type": "string"
        },
        "title": {
          "minLength": 1,
          "maxLength": 40,
          "type": "string"
        },
        "creator": {
          "pattern": "^[a-z0-9_-]+$",
          "maxLength": 39,
          "description": "GitHub handle, lowercase.",
          "type": "string"
        },
        "description": {
          "minLength": 1,
          "maxLength": 240,
          "type": "string"
        },
        "ai_tools": {
          "maxItems": 8,
          "description": "AI tools used to make this file or its art. Required when any were used.",
          "type": "array",
          "items": {
            "minLength": 1,
            "maxLength": 60,
            "type": "string"
          }
        },
        "items": {
          "maxItems": 40,
          "type": "array",
          "items": {
            "additionalProperties": false,
            "type": "object",
            "required": [
              "id",
              "name",
              "kind",
              "rarity",
              "sprite"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              },
              "kind": {
                "anyOf": [
                  {
                    "const": "material",
                    "type": "string"
                  },
                  {
                    "const": "food",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "fragment",
                    "type": "string"
                  },
                  {
                    "const": "treasure",
                    "type": "string"
                  }
                ]
              },
              "rarity": {
                "description": "Declared rarity. The check compares it with the rarity computed from the data.",
                "anyOf": [
                  {
                    "const": "common",
                    "type": "string"
                  },
                  {
                    "const": "uncommon",
                    "type": "string"
                  },
                  {
                    "const": "rare",
                    "type": "string"
                  },
                  {
                    "const": "legendary",
                    "type": "string"
                  }
                ]
              },
              "class": {
                "description": "A base class (plant, wood, fibre, ...) or the id of a class an extension declares under one of them.",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  },
                  {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                ]
              },
              "family": {
                "pattern": "^[a-z0-9_-]+$",
                "maxLength": 24,
                "description": "A group inside the class, for example \"berry\" for every berry. Open: any lowercase word.",
                "type": "string"
              },
              "tags": {
                "maxItems": 8,
                "uniqueItems": true,
                "description": "Open words that describe it, for example \"sweet\" or \"night\".",
                "type": "array",
                "items": {
                  "pattern": "^[a-z0-9_-]+$",
                  "maxLength": 24,
                  "description": "A lowercase word.",
                  "type": "string"
                }
              },
              "tier": {
                "minimum": 1,
                "maximum": 20,
                "description": "How advanced it is, from 1. The rarity says how often it appears; the tier says how far up the ladder it is. A tool has the tier of its \"tool\".",
                "type": "integer"
              },
              "sprite": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
                "maxLength": 120,
                "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
                "type": "string"
              },
              "food": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "satiety"
                ],
                "properties": {
                  "satiety": {
                    "minimum": 0,
                    "maximum": 100,
                    "description": "Health points restored when eaten (the meter holds 100 at the start). 0 for a food that only hurts.",
                    "type": "integer"
                  },
                  "hurt": {
                    "minimum": 1,
                    "maximum": 100,
                    "description": "Health points it takes when eaten, at any hour: a bad fruit or a raw herb (G30).",
                    "type": "integer"
                  }
                }
              },
              "tool": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "kind",
                  "tier"
                ],
                "properties": {
                  "kind": {
                    "anyOf": [
                      {
                        "const": "basket",
                        "type": "string"
                      },
                      {
                        "const": "trowel",
                        "type": "string"
                      },
                      {
                        "const": "axe",
                        "type": "string"
                      },
                      {
                        "const": "staff",
                        "type": "string"
                      }
                    ]
                  },
                  "tier": {
                    "minimum": 1,
                    "maximum": 5,
                    "description": "Better tools work faster. The calculator clamps the total.",
                    "type": "integer"
                  },
                  "uses": {
                    "minimum": 1,
                    "maximum": 1000,
                    "description": "The tool wears out after this many uses. Left out, the tool lasts (DECISIONS.md, 2026-10-09: the crafting economy).",
                    "type": "integer"
                  }
                }
              },
              "fragment": {
                "additionalProperties": false,
                "description": "A found scrap that teaches a recipe.",
                "type": "object",
                "required": [
                  "unlocks"
                ],
                "properties": {
                  "unlocks": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                }
              },
              "wear": {
                "additionalProperties": false,
                "description": "Something the character wears (DECISIONS.md, 2026-10-09: the upgrade). A worn item stays in the bag.",
                "type": "object",
                "required": [
                  "slot"
                ],
                "properties": {
                  "slot": {
                    "description": "Where it is worn: head, top, legs (trousers), outfit (takes the top and the legs), feet, jewelry (two places) or hand (a tool).",
                    "anyOf": [
                      {
                        "const": "head",
                        "type": "string"
                      },
                      {
                        "const": "top",
                        "type": "string"
                      },
                      {
                        "const": "legs",
                        "type": "string"
                      },
                      {
                        "const": "outfit",
                        "type": "string"
                      },
                      {
                        "const": "feet",
                        "type": "string"
                      },
                      {
                        "const": "jewelry",
                        "type": "string"
                      },
                      {
                        "const": "hand",
                        "type": "string"
                      }
                    ]
                  },
                  "look": {
                    "description": "A look: worn on the look layer over the work clothes. It shows and counts for nothing, so it has no effects and no set.",
                    "type": "boolean"
                  },
                  "effects": {
                    "minItems": 1,
                    "maxItems": 2,
                    "description": "Small bonuses while it is worn on the work layer. Two at most, each effect once.",
                    "type": "array",
                    "items": {
                      "additionalProperties": false,
                      "type": "object",
                      "required": [
                        "effect",
                        "value"
                      ],
                      "properties": {
                        "effect": {
                          "description": "What a worn item helps: gathering, digging or crafting speed, the craft chance, or rare finds.",
                          "anyOf": [
                            {
                              "const": "gather_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "dig_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_chance_pct",
                              "type": "string"
                            },
                            {
                              "const": "rare_find_pct",
                              "type": "string"
                            }
                          ]
                        },
                        "value": {
                          "minimum": 1,
                          "maximum": 100,
                          "description": "Percent, at most the cap of the item's tier (params.wear_effect_max_pct).",
                          "type": "integer"
                        }
                      }
                    }
                  },
                  "set": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "A set of one creator: when every piece of it is worn, their effects grow by params.wear_set_bonus_pct.",
                    "type": "string"
                  }
                }
              },
              "premium_later": {
                "description": "Marks a look that may also be sold for premium currency once stage 6 brings it. Only a look item with no effect may carry it, and it stays obtainable in the game (DECISIONS.md, 2026-10-09).",
                "type": "boolean"
              }
            }
          }
        },
        "classes": {
          "maxItems": 10,
          "description": "Classes of your own, each under one base class.",
          "type": "array",
          "items": {
            "additionalProperties": false,
            "description": "A class of your own, declared under one base class. Every rule written for the base class holds for it.",
            "type": "object",
            "required": [
              "id",
              "name",
              "base"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "base": {
                "description": "plant (leaves, herbs, berries, fruit, roots, mushrooms), wood, fibre (reeds, grass, thread, cloth), stone, clay (clay, sand, pottery, brick), mineral (crystals, gems, salt, ore), metal (waits for its discovery), animal (feathers, wool, hide, bone), meal (cooked food), tool, garment (worn clothes), jewelry, relic (old things from the ruins).",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  }
                ]
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              }
            }
          }
        },
        "type": {
          "const": "kit",
          "type": "string"
        },
        "kit": {
          "additionalProperties": false,
          "type": "object",
          "required": [
            "sprites"
          ],
          "properties": {
            "palette": {
              "minItems": 2,
              "maxItems": 32,
              "description": "Only the core kit sets the palette. Every sprite of every kit must use these colors.",
              "type": "array",
              "items": {
                "pattern": "^#[0-9a-f]{6}$",
                "type": "string"
              }
            },
            "sprites": {
              "description": "Sprite name (group/name) to its PNG. Groups: tiles, items, chars, props, ui.",
              "type": "object",
              "patternProperties": {
                "^[a-z0-9_-]+/[a-z0-9_/-]+$": {
                  "additionalProperties": false,
                  "type": "object",
                  "required": [
                    "file",
                    "w",
                    "h"
                  ],
                  "properties": {
                    "file": {
                      "pattern": "^[a-z0-9_/-]+\\.png$",
                      "description": "PNG next to this file.",
                      "type": "string"
                    },
                    "w": {
                      "minimum": 8,
                      "maximum": 64,
                      "description": "Frame width in pixels. tiles/ and items/ are 16, chars/ are 16.",
                      "type": "integer"
                    },
                    "h": {
                      "minimum": 8,
                      "maximum": 64,
                      "description": "Frame height in pixels. tiles/ and items/ are 16, chars/ are 24.",
                      "type": "integer"
                    },
                    "frames": {
                      "minimum": 1,
                      "maximum": 16,
                      "description": "Animation frames laid side by side. Default 1.",
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    {
      "additionalProperties": false,
      "$id": "map",
      "type": "object",
      "required": [
        "format",
        "id",
        "title",
        "creator",
        "type",
        "map"
      ],
      "properties": {
        "$schema": {
          "type": "string"
        },
        "format": {
          "description": "Format version of this file.",
          "const": 1,
          "type": "number"
        },
        "id": {
          "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
          "maxLength": 80,
          "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
          "type": "string"
        },
        "title": {
          "minLength": 1,
          "maxLength": 40,
          "type": "string"
        },
        "creator": {
          "pattern": "^[a-z0-9_-]+$",
          "maxLength": 39,
          "description": "GitHub handle, lowercase.",
          "type": "string"
        },
        "description": {
          "minLength": 1,
          "maxLength": 240,
          "type": "string"
        },
        "ai_tools": {
          "maxItems": 8,
          "description": "AI tools used to make this file or its art. Required when any were used.",
          "type": "array",
          "items": {
            "minLength": 1,
            "maxLength": 60,
            "type": "string"
          }
        },
        "items": {
          "maxItems": 40,
          "type": "array",
          "items": {
            "additionalProperties": false,
            "type": "object",
            "required": [
              "id",
              "name",
              "kind",
              "rarity",
              "sprite"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              },
              "kind": {
                "anyOf": [
                  {
                    "const": "material",
                    "type": "string"
                  },
                  {
                    "const": "food",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "fragment",
                    "type": "string"
                  },
                  {
                    "const": "treasure",
                    "type": "string"
                  }
                ]
              },
              "rarity": {
                "description": "Declared rarity. The check compares it with the rarity computed from the data.",
                "anyOf": [
                  {
                    "const": "common",
                    "type": "string"
                  },
                  {
                    "const": "uncommon",
                    "type": "string"
                  },
                  {
                    "const": "rare",
                    "type": "string"
                  },
                  {
                    "const": "legendary",
                    "type": "string"
                  }
                ]
              },
              "class": {
                "description": "A base class (plant, wood, fibre, ...) or the id of a class an extension declares under one of them.",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  },
                  {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                ]
              },
              "family": {
                "pattern": "^[a-z0-9_-]+$",
                "maxLength": 24,
                "description": "A group inside the class, for example \"berry\" for every berry. Open: any lowercase word.",
                "type": "string"
              },
              "tags": {
                "maxItems": 8,
                "uniqueItems": true,
                "description": "Open words that describe it, for example \"sweet\" or \"night\".",
                "type": "array",
                "items": {
                  "pattern": "^[a-z0-9_-]+$",
                  "maxLength": 24,
                  "description": "A lowercase word.",
                  "type": "string"
                }
              },
              "tier": {
                "minimum": 1,
                "maximum": 20,
                "description": "How advanced it is, from 1. The rarity says how often it appears; the tier says how far up the ladder it is. A tool has the tier of its \"tool\".",
                "type": "integer"
              },
              "sprite": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
                "maxLength": 120,
                "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
                "type": "string"
              },
              "food": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "satiety"
                ],
                "properties": {
                  "satiety": {
                    "minimum": 0,
                    "maximum": 100,
                    "description": "Health points restored when eaten (the meter holds 100 at the start). 0 for a food that only hurts.",
                    "type": "integer"
                  },
                  "hurt": {
                    "minimum": 1,
                    "maximum": 100,
                    "description": "Health points it takes when eaten, at any hour: a bad fruit or a raw herb (G30).",
                    "type": "integer"
                  }
                }
              },
              "tool": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "kind",
                  "tier"
                ],
                "properties": {
                  "kind": {
                    "anyOf": [
                      {
                        "const": "basket",
                        "type": "string"
                      },
                      {
                        "const": "trowel",
                        "type": "string"
                      },
                      {
                        "const": "axe",
                        "type": "string"
                      },
                      {
                        "const": "staff",
                        "type": "string"
                      }
                    ]
                  },
                  "tier": {
                    "minimum": 1,
                    "maximum": 5,
                    "description": "Better tools work faster. The calculator clamps the total.",
                    "type": "integer"
                  },
                  "uses": {
                    "minimum": 1,
                    "maximum": 1000,
                    "description": "The tool wears out after this many uses. Left out, the tool lasts (DECISIONS.md, 2026-10-09: the crafting economy).",
                    "type": "integer"
                  }
                }
              },
              "fragment": {
                "additionalProperties": false,
                "description": "A found scrap that teaches a recipe.",
                "type": "object",
                "required": [
                  "unlocks"
                ],
                "properties": {
                  "unlocks": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  }
                }
              },
              "wear": {
                "additionalProperties": false,
                "description": "Something the character wears (DECISIONS.md, 2026-10-09: the upgrade). A worn item stays in the bag.",
                "type": "object",
                "required": [
                  "slot"
                ],
                "properties": {
                  "slot": {
                    "description": "Where it is worn: head, top, legs (trousers), outfit (takes the top and the legs), feet, jewelry (two places) or hand (a tool).",
                    "anyOf": [
                      {
                        "const": "head",
                        "type": "string"
                      },
                      {
                        "const": "top",
                        "type": "string"
                      },
                      {
                        "const": "legs",
                        "type": "string"
                      },
                      {
                        "const": "outfit",
                        "type": "string"
                      },
                      {
                        "const": "feet",
                        "type": "string"
                      },
                      {
                        "const": "jewelry",
                        "type": "string"
                      },
                      {
                        "const": "hand",
                        "type": "string"
                      }
                    ]
                  },
                  "look": {
                    "description": "A look: worn on the look layer over the work clothes. It shows and counts for nothing, so it has no effects and no set.",
                    "type": "boolean"
                  },
                  "effects": {
                    "minItems": 1,
                    "maxItems": 2,
                    "description": "Small bonuses while it is worn on the work layer. Two at most, each effect once.",
                    "type": "array",
                    "items": {
                      "additionalProperties": false,
                      "type": "object",
                      "required": [
                        "effect",
                        "value"
                      ],
                      "properties": {
                        "effect": {
                          "description": "What a worn item helps: gathering, digging or crafting speed, the craft chance, or rare finds.",
                          "anyOf": [
                            {
                              "const": "gather_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "dig_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_speed_pct",
                              "type": "string"
                            },
                            {
                              "const": "craft_chance_pct",
                              "type": "string"
                            },
                            {
                              "const": "rare_find_pct",
                              "type": "string"
                            }
                          ]
                        },
                        "value": {
                          "minimum": 1,
                          "maximum": 100,
                          "description": "Percent, at most the cap of the item's tier (params.wear_effect_max_pct).",
                          "type": "integer"
                        }
                      }
                    }
                  },
                  "set": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "A set of one creator: when every piece of it is worn, their effects grow by params.wear_set_bonus_pct.",
                    "type": "string"
                  }
                }
              },
              "premium_later": {
                "description": "Marks a look that may also be sold for premium currency once stage 6 brings it. Only a look item with no effect may carry it, and it stays obtainable in the game (DECISIONS.md, 2026-10-09).",
                "type": "boolean"
              }
            }
          }
        },
        "classes": {
          "maxItems": 10,
          "description": "Classes of your own, each under one base class.",
          "type": "array",
          "items": {
            "additionalProperties": false,
            "description": "A class of your own, declared under one base class. Every rule written for the base class holds for it.",
            "type": "object",
            "required": [
              "id",
              "name",
              "base"
            ],
            "properties": {
              "id": {
                "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                "maxLength": 80,
                "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                "type": "string"
              },
              "name": {
                "minLength": 1,
                "maxLength": 40,
                "type": "string"
              },
              "base": {
                "description": "plant (leaves, herbs, berries, fruit, roots, mushrooms), wood, fibre (reeds, grass, thread, cloth), stone, clay (clay, sand, pottery, brick), mineral (crystals, gems, salt, ore), metal (waits for its discovery), animal (feathers, wool, hide, bone), meal (cooked food), tool, garment (worn clothes), jewelry, relic (old things from the ruins).",
                "anyOf": [
                  {
                    "const": "plant",
                    "type": "string"
                  },
                  {
                    "const": "wood",
                    "type": "string"
                  },
                  {
                    "const": "fibre",
                    "type": "string"
                  },
                  {
                    "const": "stone",
                    "type": "string"
                  },
                  {
                    "const": "clay",
                    "type": "string"
                  },
                  {
                    "const": "mineral",
                    "type": "string"
                  },
                  {
                    "const": "metal",
                    "type": "string"
                  },
                  {
                    "const": "animal",
                    "type": "string"
                  },
                  {
                    "const": "meal",
                    "type": "string"
                  },
                  {
                    "const": "tool",
                    "type": "string"
                  },
                  {
                    "const": "garment",
                    "type": "string"
                  },
                  {
                    "const": "jewelry",
                    "type": "string"
                  },
                  {
                    "const": "relic",
                    "type": "string"
                  }
                ]
              },
              "description": {
                "minLength": 1,
                "maxLength": 240,
                "type": "string"
              }
            }
          }
        },
        "type": {
          "const": "map",
          "type": "string"
        },
        "map": {
          "additionalProperties": false,
          "type": "object",
          "required": [
            "width",
            "height",
            "legend",
            "ground",
            "props",
            "spawn",
            "slots"
          ],
          "properties": {
            "width": {
              "minimum": 8,
              "maximum": 1024,
              "type": "integer"
            },
            "height": {
              "minimum": 8,
              "maximum": 1024,
              "type": "integer"
            },
            "legend": {
              "type": "object",
              "patternProperties": {
                "^.$": {
                  "additionalProperties": false,
                  "type": "object",
                  "required": [
                    "sprite",
                    "solid",
                    "tag"
                  ],
                  "properties": {
                    "sprite": {
                      "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
                      "maxLength": 120,
                      "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
                      "type": "string"
                    },
                    "solid": {
                      "type": "boolean"
                    },
                    "tag": {
                      "anyOf": [
                        {
                          "const": "grove",
                          "type": "string"
                        },
                        {
                          "const": "meadow",
                          "type": "string"
                        },
                        {
                          "const": "riverbank",
                          "type": "string"
                        },
                        {
                          "const": "ruin",
                          "type": "string"
                        },
                        {
                          "const": "town",
                          "type": "string"
                        },
                        {
                          "const": "water",
                          "type": "string"
                        },
                        {
                          "const": "path",
                          "type": "string"
                        },
                        {
                          "const": "interior",
                          "type": "string"
                        }
                      ]
                    }
                  }
                }
              }
            },
            "ground": {
              "minItems": 8,
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "props": {
              "type": "array",
              "items": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "sprite",
                  "x",
                  "y",
                  "w",
                  "h",
                  "solid"
                ],
                "properties": {
                  "id": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "description": "Names the prop so a quest riddle can cite it. Unique on the map.",
                    "type": "string"
                  },
                  "sprite": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+:[a-z0-9_/-]+$",
                    "maxLength": 120,
                    "description": "A frame of an art kit: \"<kit id>:<frame name>\", for example \"core/base-kit:items/berry\".",
                    "type": "string"
                  },
                  "x": {
                    "minimum": 0,
                    "maximum": 1023,
                    "description": "Left tile of the footprint.",
                    "type": "integer"
                  },
                  "y": {
                    "minimum": 0,
                    "maximum": 1023,
                    "description": "Top tile of the footprint.",
                    "type": "integer"
                  },
                  "w": {
                    "minimum": 1,
                    "maximum": 8,
                    "description": "Footprint width in tiles. The sprite is drawn bottom-centered on it.",
                    "type": "integer"
                  },
                  "h": {
                    "minimum": 1,
                    "maximum": 8,
                    "description": "Footprint height in tiles.",
                    "type": "integer"
                  },
                  "solid": {
                    "type": "boolean"
                  },
                  "sign": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Makes the prop a readable sign that names whoever filled this slot, or says it awaits restoration.",
                    "type": "string"
                  },
                  "note": {
                    "minLength": 1,
                    "maxLength": 240,
                    "type": "string",
                    "description": "A line shown when the player looks at this prop, for example an old inscription."
                  },
                  "hazard": {
                    "additionalProperties": false,
                    "description": "Makes the prop a hazard (G30-G35). It needs an id.",
                    "type": "object",
                    "required": [
                      "kind",
                      "window"
                    ],
                    "properties": {
                      "kind": {
                        "description": "A predator hunts the player in its reach and bites until the player stands somewhere safe; a pit, a trap or deep water hurts once each time the player steps onto its footprint.",
                        "anyOf": [
                          {
                            "const": "predator",
                            "type": "string"
                          },
                          {
                            "const": "pit",
                            "type": "string"
                          },
                          {
                            "const": "trap",
                            "type": "string"
                          },
                          {
                            "const": "deep_water",
                            "type": "string"
                          }
                        ]
                      },
                      "window": {
                        "minItems": 1,
                        "uniqueItems": true,
                        "description": "When it acts (G30). Outside its window it is harmless and shows.",
                        "type": "array",
                        "items": {
                          "const": "night",
                          "type": "string"
                        }
                      },
                      "reach": {
                        "minimum": 1,
                        "maximum": 12,
                        "description": "A predator only: how many tiles from its footprint it notices the player. The params hold the default.",
                        "type": "integer"
                      }
                    }
                  }
                }
              }
            },
            "spawn": {
              "additionalProperties": false,
              "type": "object",
              "required": [
                "x",
                "y"
              ],
              "properties": {
                "x": {
                  "minimum": 0,
                  "maximum": 1023,
                  "type": "integer"
                },
                "y": {
                  "minimum": 0,
                  "maximum": 1023,
                  "type": "integer"
                }
              }
            },
            "slots": {
              "type": "array",
              "items": {
                "additionalProperties": false,
                "type": "object",
                "required": [
                  "id",
                  "kind",
                  "x",
                  "y",
                  "w",
                  "h"
                ],
                "properties": {
                  "id": {
                    "pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$",
                    "maxLength": 80,
                    "description": "Stable id \"creator/name\": lowercase letters, digits, \"_\" and \"-\". Never reused once merged.",
                    "type": "string"
                  },
                  "kind": {
                    "anyOf": [
                      {
                        "const": "resource",
                        "type": "string"
                      },
                      {
                        "const": "ruin",
                        "type": "string"
                      },
                      {
                        "const": "npc",
                        "type": "string"
                      },
                      {
                        "const": "building",
                        "type": "string"
                      },
                      {
                        "const": "restore",
                        "type": "string"
                      },
                      {
                        "const": "camp",
                        "type": "string"
                      },
                      {
                        "const": "area",
                        "type": "string"
                      }
                    ]
                  },
                  "x": {
                    "minimum": 0,
                    "maximum": 1023,
                    "type": "integer"
                  },
                  "y": {
                    "minimum": 0,
                    "maximum": 1023,
                    "type": "integer"
                  },
                  "w": {
                    "minimum": 1,
                    "maximum": 64,
                    "type": "integer"
                  },
                  "h": {
                    "minimum": 1,
                    "maximum": 64,
                    "type": "integer"
                  },
                  "tag": {
                    "anyOf": [
                      {
                        "const": "grove",
                        "type": "string"
                      },
                      {
                        "const": "meadow",
                        "type": "string"
                      },
                      {
                        "const": "riverbank",
                        "type": "string"
                      },
                      {
                        "const": "ruin",
                        "type": "string"
                      },
                      {
                        "const": "town",
                        "type": "string"
                      },
                      {
                        "const": "water",
                        "type": "string"
                      },
                      {
                        "const": "path",
                        "type": "string"
                      },
                      {
                        "const": "interior",
                        "type": "string"
                      }
                    ]
                  },
                  "label": {
                    "minLength": 1,
                    "maxLength": 40,
                    "type": "string"
                  },
                  "safe": {
                    "description": "A safe area (G30): no hazard acts inside it at any hour, a chase ends when the player stands in it, and what the player carries in is theirs. The cobbles of the town and the camp once a part stands are safe without this.",
                    "type": "boolean"
                  }
                }
              }
            }
          }
        }
      }
    }
  ],
  "$id": "https://github.com/Bobikobi/GAME/schema/json/extension.schema.json"
}
