{
 "$schema": "https://json-schema.org/draft/2020-12/schema",
 "$id": "https://cookwala.ai/v1/schemas/capabilities.schema.json",
 "title": "Cookwala Capability Manifest",
 "x-cookwala-status": "core",
 "description": "Published by every participant in a Cookwala kitchen (robot, appliance, sensor, hub, agent, service) so a hub can match recipe steps to who can do them. Served by the device at /.well-known/cookwala-device.json, registered with the hub (POST /devices), or provided by the vendor's cloud. Self-declared; the hub treats safety claims as claims.",
 "type": "object",
 "required": [
  "cookwala",
  "actor",
  "roles",
  "capabilities",
  "safety",
  "interfaces"
 ],
 "properties": {
  "cookwala": {
   "$ref": "common.schema.json#/$defs/SpecVersion"
  },
  "actor": {
   "$ref": "common.schema.json#/$defs/Actor"
  },
  "firmware": {
   "type": "string"
  },
  "roles": {
   "type": "array",
   "minItems": 1,
   "items": {
    "enum": [
     "executor",
     "appliance",
     "sensor",
     "inventory",
     "orderer",
     "notifier",
     "safety_monitor",
     "planner",
     "hub",
     "display",
     "voice"
    ]
   }
  },
  "location": {
   "type": "object",
   "properties": {
    "kitchenId": {
     "type": "string"
    },
    "zone": {
     "type": "string",
     "description": "e.g. counter-left, hob, sink, fridge."
    },
    "mobile": {
     "type": "boolean"
    }
   },
   "unevaluatedProperties": false,
   "patternProperties": {
    "^x-": {}
   }
  },
  "capabilities": {
   "type": "object",
   "properties": {
    "ops": {
     "type": "array",
     "description": "Operations this actor can perform, with parameter ranges.",
     "items": {
      "type": "object",
      "required": [
       "op"
      ],
      "properties": {
       "op": {
        "$ref": "common.schema.json#/$defs/VocabId",
        "not": {
         "const": "cw.op.legacy_step"
        },
        "description": "An executable operation id. cw.op.legacy_step (V0 import, executable: false) may not be declared (RFC-0009)."
       },
       "params": {
        "type": "object",
        "description": "Per-parameter supported ranges/enums, e.g. {\"heat\": [\"low\",\"medium\",\"high\"], \"targetC\": {\"min\": 30, \"max\": 250}}."
       },
       "maxMassG": {
        "type": "number"
       },
       "ingredientClasses": {
        "type": "array",
        "items": {
         "type": "string"
        },
        "description": "Limits, e.g. cut only for cw.ing.class.vegetable_firm."
       },
       "reliability": {
        "type": "number",
        "minimum": 0,
        "maximum": 1,
        "description": "Self-reported success rate."
       },
       "needsHumanFor": {
        "type": "array",
        "items": {
         "type": "string"
        }
       },
       "skill": {
        "type": "string"
       }
      },
      "unevaluatedProperties": false,
      "patternProperties": {
       "^x-": {}
      }
     }
    },
    "heat": {
     "type": "array",
     "items": {
      "type": "object",
      "required": [
       "id",
       "class"
      ],
      "properties": {
       "id": {
        "type": "string"
       },
       "class": {
        "$ref": "common.schema.json#/$defs/VocabId"
       },
       "maxTempC": {
        "type": "number"
       },
       "powerW": {
        "type": "number"
       },
       "modes": {
        "type": "array",
        "items": {
         "type": "string"
        }
       },
       "closedLoopTemp": {
        "type": "boolean"
       },
       "remoteStartAllowed": {
        "type": "boolean",
        "description": "Whether local regulation/vendor allows remote start."
       }
      },
      "unevaluatedProperties": false,
      "patternProperties": {
       "^x-": {}
      }
     }
    },
    "vessels": {
     "type": "array",
     "items": {
      "type": "object",
      "properties": {
       "class": {
        "type": "string"
       },
       "capacityMl": {
        "type": "number"
       },
       "diameterMm": {
        "type": "number"
       },
       "material": {
        "type": "string"
       },
       "count": {
        "type": "integer"
       }
      },
      "unevaluatedProperties": false,
      "patternProperties": {
       "^x-": {}
      }
     }
    },
    "sensors": {
     "type": "array",
     "items": {
      "type": "object",
      "required": [
       "sensor"
      ],
      "properties": {
       "sensor": {
        "$ref": "common.schema.json#/$defs/VocabId"
       },
       "accuracy": {
        "type": "number",
        "description": "Stated accuracy in the sensor's unit (for temperatures: ± °C). Used by plausibility checks between sensors on the same medium (RFC-0011)."
       },
       "unit": {
        "$ref": "common.schema.json#/$defs/Unit"
       },
       "rateHz": {
        "type": "number"
       },
       "visionCues": {
        "type": "array",
        "items": {
         "type": "string"
        }
       },
       "state": {
        "enum": [
         "ok",
         "degraded",
         "fault",
         "unknown"
        ],
        "description": "Self-reported health. Only ok (or absent) counts as a sensor rung; degraded, fault and unknown fall to the next rung of the ladder (RFC-0011)."
       },
       "calibration": {
        "type": "object",
        "unevaluatedProperties": false,
        "patternProperties": {
         "^x-": {}
        },
        "description": "Last calibration of this sensor. A sensor whose validUntil has passed does not count as a sensor rung (RFC-0011).",
        "properties": {
         "lastAt": {
          "$ref": "common.schema.json#/$defs/DateTime"
         },
         "validUntil": {
          "$ref": "common.schema.json#/$defs/DateTime"
         },
         "by": {
          "type": "string",
          "maxLength": 200,
          "description": "Who calibrated: the maker, a service, a lab."
         },
         "method": {
          "type": "string",
          "maxLength": 200,
          "description": "For example ice point and boiling point, reference thermometer, factory."
         },
         "certificate": {
          "type": "string",
          "maxLength": 300,
          "description": "Reference or URL of the calibration certificate."
         }
        }
       }
      },
      "unevaluatedProperties": false,
      "patternProperties": {
       "^x-": {}
      }
     }
    },
    "dispensers": {
     "type": "array",
     "items": {
      "type": "object",
      "properties": {
       "slot": {
        "type": "string"
       },
       "kind": {
        "enum": [
         "solid",
         "liquid",
         "spice",
         "oil",
         "water"
        ]
       },
       "capacityG": {
        "type": "number"
       },
       "accuracyG": {
        "type": "number"
       }
      },
      "unevaluatedProperties": false,
      "patternProperties": {
       "^x-": {}
      }
     }
    },
    "manipulation": {
     "type": "object",
     "properties": {
      "arms": {
       "type": "integer"
      },
      "payloadKg": {
       "type": "number"
      },
      "reachMm": {
       "type": "number"
      },
      "toolChanger": {
       "type": "boolean"
      },
      "canOpen": {
       "type": "array",
       "items": {
        "enum": [
         "fridge",
         "oven",
         "drawer",
         "cupboard",
         "jar",
         "can",
         "packet"
        ]
       }
      }
     },
     "unevaluatedProperties": false,
     "patternProperties": {
      "^x-": {}
     }
    },
    "inventory": {
     "type": "object",
     "properties": {
      "tracks": {
       "type": "array",
       "items": {
        "enum": [
         "presence",
         "quantity",
         "expiry",
         "temperature",
         "door_state"
        ]
       }
      },
      "method": {
       "type": "array",
       "items": {
        "enum": [
         "camera",
         "weight",
         "rfid",
         "barcode",
         "receipt",
         "manual"
        ]
       }
      }
     },
     "unevaluatedProperties": false,
     "patternProperties": {
      "^x-": {}
     }
    },
    "notify": {
     "type": "object",
     "properties": {
      "channels": {
       "type": "array",
       "items": {
        "enum": [
         "screen",
         "speaker",
         "push",
         "sms",
         "email",
         "matter",
         "webhook",
         "light",
         "haptic"
        ]
       }
      }
     },
     "unevaluatedProperties": false,
     "patternProperties": {
      "^x-": {}
     }
    },
    "languages": {
     "type": "array",
     "items": {
      "type": "string"
     }
    }
   },
   "unevaluatedProperties": false,
   "patternProperties": {
    "^x-": {}
   }
  },
  "safety": {
   "type": "object",
   "required": [
    "certifications",
    "presenceDetection",
    "emergencyStop"
   ],
   "properties": {
    "certifications": {
     "type": "array",
     "items": {
      "type": "object",
      "required": [
       "standard"
      ],
      "properties": {
       "standard": {
        "type": "string",
        "description": "e.g. IEC 60335-1, IEC 60335-2-6, ISO 13482:2026, ISO 10218-1, ISO/TS 15066, ETSI EN 303 645, GB/T (cooking machines), UL 858."
       },
       "body": {
        "type": "string"
       },
       "certificate": {
        "type": "string"
       },
       "selfDeclared": {
        "type": "boolean"
       }
      },
      "unevaluatedProperties": false,
      "patternProperties": {
       "^x-": {}
      }
     }
    },
    "presenceDetection": {
     "type": "boolean",
     "description": "Can detect humans, children or pets in its work zone."
    },
    "emergencyStop": {
     "enum": [
      "physical",
      "remote",
      "both",
      "none"
     ]
    },
    "unattendedOps": {
     "type": "array",
     "items": {
      "type": "string"
     },
     "description": "Ops the maker certifies for unattended use."
    },
    "policyPacks": {
     "type": "array",
     "items": {
      "type": "string"
     },
     "description": "Policy packs the device enforces itself."
    },
    "minVerificationLevel": {
     "type": "object",
     "properties": {
      "presence_required": {
       "enum": [
        "V1",
        "V2",
        "V3"
       ]
      },
      "unattended": {
       "enum": [
        "V2",
        "V3"
       ]
      }
     },
     "unevaluatedProperties": false,
     "patternProperties": {
      "^x-": {}
     }
    }
   },
   "unevaluatedProperties": false,
   "patternProperties": {
    "^x-": {}
   }
  },
  "interfaces": {
   "type": "object",
   "description": "How the hub reaches this actor.",
   "properties": {
    "cookwalaHttp": {
     "type": "string",
     "description": "Base URL of the actor's Cookwala executor API."
    },
    "mqtt": {
     "type": "object",
     "properties": {
      "topicPrefix": {
       "type": "string"
      }
     },
     "unevaluatedProperties": false,
     "patternProperties": {
      "^x-": {}
     }
    },
    "matter": {
     "type": "object",
     "properties": {
      "nodeId": {
       "type": "string"
      },
      "endpoints": {
       "type": "array",
       "items": {
        "type": "object",
        "properties": {
         "endpoint": {
          "type": "integer"
         },
         "deviceType": {
          "type": "string"
         }
        },
        "unevaluatedProperties": false,
        "patternProperties": {
         "^x-": {}
        }
       }
      }
     },
     "unevaluatedProperties": false,
     "patternProperties": {
      "^x-": {}
     }
    },
    "ros2": {
     "type": "object",
     "properties": {
      "namespace": {
       "type": "string"
      },
      "actionServer": {
       "type": "string"
      }
     },
     "unevaluatedProperties": false,
     "patternProperties": {
      "^x-": {}
     }
    },
    "a2a": {
     "type": "string",
     "description": "AgentCard URL (/.well-known/agent-card.json)."
    },
    "mcp": {
     "type": "string"
    },
    "homeAssistant": {
     "type": "string",
     "description": "Entity id prefix if bridged through Home Assistant."
    },
    "vendorCloud": {
     "type": "string"
    }
   },
   "unevaluatedProperties": false,
   "patternProperties": {
    "^x-": {}
   }
  },
  "signature": {
   "$ref": "common.schema.json#/$defs/Signature"
  },
  "meta": {
   "$ref": "common.schema.json#/$defs/Meta"
  },
  "currentLimitations": {
   "type": "array",
   "items": {
    "$ref": "mission.schema.json#/$defs/Degradation"
   },
   "description": "Live degradations (low light, weak grip, sensor fault...) so planners adapt before assigning tasks."
  }
 },
 "patternProperties": {
  "^x-": {}
 },
 "unevaluatedProperties": false
}
