{"kind": "SchemaBundle", "version": "0.2.0", "sha256": "f51dcc1b2c014786d5c428fa809023c08fbdf805e186b871e19089ff2d03bea4", "schemas": {"https://cookwala.ai/v1/schemas/advice.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/advice.schema.json", "title": "Cookwala Advice (reasoning requests and responses)", "x-cookwala-status": "experimental", "description": "Questions a robot, appliance, agent or person asks the Cookwala reasoner (what can I cook, how do I fix this mistake, how do we split the work, how do I store it, what should I cook for N people), and the structured, safety-checked answers. Served statelessly by the index (POST /v1/advise/{intent}) and with full kitchen context by a hub (POST /cookwala/v1/advise/{intent}). Use $defs AdviceRequest and AdviceResponse.", "$defs": {"Intent": {"enum": ["ask", "cook_from", "substitute", "recover", "repurpose", "adapt_equipment", "team_plan", "store", "feed", "rescale", "retime", "leftovers", "diagnose", "texture_modify", "diet_merge", "nutrition_target", "shopping_optimize", "custom", "relief_allocate", "personalize"]}, "IngredientInput": {"type": "object", "properties": {"ingredientId": {"$ref": "common.schema.json#/$defs/VocabId"}, "name": {"type": "string", "description": "Free text when the id is unknown; the reasoner resolves it."}, "qty": {"$ref": "common.schema.json#/$defs/Quantity"}, "state": {"type": "string", "description": "e.g. raw, cooked, frozen, overripe, stale."}, "expires": {"type": "string", "format": "date"}, "mustUse": {"type": "boolean"}}, "anyOf": [{"required": ["ingredientId"]}, {"required": ["name"]}], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "DinerGroup": {"type": "object", "required": ["count"], "properties": {"count": {"type": "integer", "minimum": 1}, "ageGroup": {"enum": ["infant", "child", "teen", "adult", "senior"]}, "allergies": {"type": "array", "items": {"type": "string"}}, "dietary": {"type": "array", "items": {"type": "string"}}, "iddsiLevel": {"type": "integer", "minimum": 0, "maximum": 7, "description": "IDDSI texture level for swallowing needs."}, "appetite": {"enum": ["light", "normal", "hearty"]}, "medical": {"type": "array", "items": {"type": "string"}, "description": "e.g. low_sodium, diabetic, renal (used only for filtering, never stored)."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Constraints": {"type": "object", "properties": {"serveAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "startEarliest": {"$ref": "common.schema.json#/$defs/DateTime"}, "timeAvailable": {"$ref": "common.schema.json#/$defs/Duration"}, "maxActiveTime": {"$ref": "common.schema.json#/$defs/Duration"}, "budget": {"$ref": "common.schema.json#/$defs/Money"}, "cuisines": {"type": "array", "items": {"type": "string"}}, "courses": {"type": "array", "items": {"type": "string"}}, "dietary": {"type": "array", "items": {"type": "string"}}, "excludeAllergens": {"type": "array", "items": {"type": "string"}}, "avoidIngredients": {"type": "array", "items": {"type": "string"}}, "useFirst": {"type": "array", "items": {"type": "string"}, "description": "Inventory item ids or ingredient ids to prioritise (expiring)."}, "equipmentUnavailable": {"type": "array", "items": {"type": "string"}}, "skill": {"enum": ["none", "basic", "intermediate", "advanced"]}, "authenticity": {"enum": ["strict", "flexible", "creative"]}, "minLevel": {"enum": ["V0", "V1", "V2", "V3"]}, "supervision": {"enum": ["unattended", "presence", "hands_on"]}, "nutrition": {"type": "object", "properties": {"kcalPerServing": {"$ref": "common.schema.json#/$defs/Range"}, "proteinGMin": {"type": "number"}, "sodiumMgMax": {"type": "number"}, "sugarGMax": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "energy": {"enum": ["any", "low", "no_oven", "no_power"]}, "noise": {"enum": ["any", "quiet"]}, "minimizeWaste": {"type": "boolean"}, "holdMax": {"$ref": "common.schema.json#/$defs/Duration", "description": "Longest acceptable time between done and served."}, "servingStyle": {"enum": ["plated", "family", "buffet", "packed", "delivery"]}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Context": {"type": "object", "description": "What the asker knows about its kitchen. A hub fills this automatically; robots asking the index directly send what they have.", "properties": {"kitchenId": {"type": "string"}, "lang": {"type": "string"}, "country": {"type": "string", "pattern": "^[A-Z]{2}$"}, "altitudeM": {"type": "number", "description": "Affects boiling point, baking and pressure-cooking times."}, "policyPacks": {"type": "array", "items": {"type": "string"}}, "inventory": {"$ref": "inventory.schema.json"}, "actors": {"type": "array", "items": {"$ref": "capabilities.schema.json"}}, "humansAvailable": {"type": "integer", "minimum": 0}, "session": {"type": "object", "properties": {"sessionId": {"type": "string"}, "recipeId": {"type": "string"}, "revision": {"type": "integer"}, "nodeId": {"type": "string"}, "taskId": {"type": "string"}, "completedNodes": {"type": "array", "items": {"type": "string"}}, "telemetry": {"type": "object"}, "startedAt": {"$ref": "common.schema.json#/$defs/DateTime"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "diners": {"type": "array", "items": {"$ref": "#/$defs/DinerGroup"}}, "constraints": {"$ref": "#/$defs/Constraints"}, "mode": {"$ref": "profile.schema.json#/$defs/OperatingMode"}, "profiles": {"type": "array", "items": {"$ref": "common.schema.json#/$defs/GlobalRef"}, "description": "Client, kitchen, cookware, robot and organization profiles to apply (resolved by the hub; private profiles never leave it)."}, "catalogs": {"type": "array", "items": {"type": "string"}, "description": "Recipe catalogs to search, in priority order (public, private, local)."}, "extensions": {"type": "array", "items": {"type": "string"}, "description": "Extension ids to apply to this request (filters, rankers, advisors)."}, "members": {"type": "array", "items": {"$ref": "profile.schema.json#/$defs/PersonNutrition"}, "description": "Only when asking a local hub/advisor; the public index rejects requests containing person data."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Incident": {"type": "object", "required": ["type"], "properties": {"type": {"$ref": "common.schema.json#/$defs/VocabId", "description": "From vocab/incidents (cw.incident.*), e.g. cw.incident.too_salty, cw.incident.scorched_bottom, cw.incident.emulsion_broke, cw.incident.time_temp_abuse."}, "description": {"type": "string"}, "recipeId": {"type": "string"}, "nodeId": {"type": "string"}, "ingredientRef": {"type": "string"}, "observations": {"type": "object", "description": "Measurements and cues, e.g. {\"saltAddedG\": 20, \"saltExpectedG\": 8, \"minutesBetween5and57C\": 150, \"coreTempC\": 48, \"smell\": \"acrid\", \"visual\": [\"black_flecks\"]}.", "additionalProperties": true}, "noticedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "elapsedSince": {"$ref": "common.schema.json#/$defs/Duration"}, "servedAlready": {"type": "boolean"}, "media": {"type": "array", "items": {"type": "string"}, "description": "Local references to photos/frames (kept local unless the user opts in)."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Query": {"type": "object", "description": "Intent-specific parameters. See the per-intent definitions below.", "additionalProperties": true}, "CookFromQuery": {"type": "object", "required": ["ingredients"], "properties": {"ingredients": {"type": "array", "items": {"$ref": "#/$defs/IngredientInput"}}, "useInventory": {"type": "boolean", "default": true}, "pantryStaplesAssumed": {"type": "boolean", "default": true, "description": "Assume salt, pepper, oil, water, common spices."}, "allowMissing": {"type": "integer", "minimum": 0, "default": 2}, "allowSubstitutions": {"type": "boolean", "default": true}, "allowShopping": {"type": "boolean", "default": false}, "servings": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "SubstituteQuery": {"type": "object", "required": ["recipeId"], "properties": {"recipeId": {"type": "string"}, "ingredientRef": {"type": "string"}, "equipmentRef": {"type": "string"}, "reason": {"enum": ["missing", "allergy", "dietary", "cost", "preference", "spoiled", "not_enough"]}, "qtyAvailable": {"$ref": "common.schema.json#/$defs/Quantity"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "RecoverQuery": {"type": "object", "required": ["incident"], "properties": {"incident": {"$ref": "#/$defs/Incident"}, "goal": {"enum": ["save_this_dish", "any_good_meal", "safest", "fastest"], "default": "save_this_dish"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "RepurposeQuery": {"type": "object", "required": ["intermediate"], "properties": {"intermediate": {"type": "object", "properties": {"fromRecipeId": {"type": "string"}, "fromNodeId": {"type": "string"}, "description": {"type": "string"}, "ingredients": {"type": "array", "items": {"$ref": "#/$defs/IngredientInput"}}, "state": {"type": "object", "description": "e.g. {\"cooked\": true, \"texture\": \"mushy\", \"flavorIssues\": [\"too_salty\"]}."}, "qty": {"$ref": "common.schema.json#/$defs/Quantity"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "incident": {"$ref": "#/$defs/Incident"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "AdaptEquipmentQuery": {"type": "object", "required": ["recipeId", "missingEquipment"], "properties": {"recipeId": {"type": "string"}, "missingEquipment": {"type": "array", "items": {"type": "string"}}, "availableEquipment": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "TeamPlanQuery": {"type": "object", "required": ["recipes"], "properties": {"recipes": {"type": "array", "items": {"type": "object", "required": ["recipeId"], "properties": {"recipeId": {"type": "string"}, "servings": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "requester": {"type": "string", "description": "Actor id of the robot asking (it gets the coordinator role if no hub)."}, "helpers": {"type": "array", "items": {"type": "string"}, "description": "Actor ids that offered help (from cookwala.team.bid)."}, "objective": {"enum": ["on_time", "min_makespan", "min_hold", "min_energy", "balanced", "min_human_work"], "default": "on_time"}, "allowSplitTasks": {"type": "boolean", "default": true, "description": "Split divisible work (chopping 2 kg onions) across actors."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "StoreQuery": {"type": "object", "properties": {"recipeId": {"type": "string"}, "description": {"type": "string"}, "qty": {"$ref": "common.schema.json#/$defs/Quantity"}, "servings": {"type": "number"}, "duration": {"$ref": "common.schema.json#/$defs/Duration", "description": "How long it must keep, e.g. P3D."}, "notCookedYet": {"type": "boolean", "description": "True: also advise how to cook it for storage (cook-for-storage changes)."}, "storageAvailable": {"type": "array", "items": {"enum": ["fridge", "freezer", "pantry", "cooler_with_ice", "none"]}}, "containersAvailable": {"type": "array", "items": {"type": "string"}}, "reheatAvailable": {"type": "array", "items": {"enum": ["microwave", "oven", "hob", "steamer", "none"]}}, "transport": {"type": "boolean", "description": "Food will travel (lunch boxes, delivery)."}}, "anyOf": [{"required": ["recipeId"]}, {"required": ["description"]}], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "FeedQuery": {"type": "object", "required": ["people"], "properties": {"people": {"type": "integer", "minimum": 1}, "meals": {"type": "integer", "minimum": 1, "default": 1, "description": "Number of meals to cover (e.g. 9 for three days × three meals)."}, "mealTypes": {"type": "array", "items": {"enum": ["breakfast", "lunch", "dinner", "snack", "iftar", "suhoor"]}}, "dishCount": {"type": "integer", "minimum": 1, "description": "Variety per meal."}, "includeStorage": {"type": "boolean", "description": "Plan make-ahead + storage for later meals."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "RescaleQuery": {"type": "object", "required": ["recipeId"], "properties": {"recipeId": {"type": "string"}, "targetServings": {"type": "number"}, "targetMass": {"$ref": "common.schema.json#/$defs/Quantity"}, "limitingIngredient": {"$ref": "#/$defs/IngredientInput", "description": "Scale to what I have of this."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "RetimeQuery": {"type": "object", "properties": {"sessionId": {"type": "string"}, "newServeAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "runningLate": {"$ref": "common.schema.json#/$defs/Duration"}, "guestsLate": {"$ref": "common.schema.json#/$defs/Duration"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "DiagnoseQuery": {"type": "object", "required": ["anomalies"], "properties": {"sessionId": {"type": "string"}, "taskId": {"type": "string"}, "anomalies": {"type": "array", "items": {"type": "object", "properties": {"sensor": {"type": "string"}, "expected": {}, "observed": {}, "since": {"$ref": "common.schema.json#/$defs/Duration"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "AdviceRequest": {"type": "object", "required": ["cookwala", "intent"], "properties": {"cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "id": {"type": "string"}, "intent": {"$ref": "#/$defs/Intent"}, "text": {"type": "string", "description": "Natural-language question (required for intent=ask; optional extra context otherwise)."}, "asker": {"$ref": "common.schema.json#/$defs/Actor"}, "context": {"$ref": "#/$defs/Context"}, "query": {"$ref": "#/$defs/Query"}, "maxOptions": {"type": "integer", "minimum": 1, "maximum": 20, "default": 5}, "explain": {"type": "boolean", "default": true}, "answersTo": {"type": "object", "description": "Answers to questions from a previous needs_input response: {questionId: value}.", "additionalProperties": true}, "previousResponseId": {"type": "string"}, "customIntent": {"type": "string", "description": "For intent=custom: an extension-defined intent (x-namespace.name)."}}, "allOf": [{"if": {"properties": {"intent": {"const": "ask"}}}, "then": {"required": ["text"]}}, {"if": {"properties": {"intent": {"const": "cook_from"}}}, "then": {"properties": {"query": {"$ref": "#/$defs/CookFromQuery"}}, "required": ["query"]}}, {"if": {"properties": {"intent": {"const": "substitute"}}}, "then": {"properties": {"query": {"$ref": "#/$defs/SubstituteQuery"}}, "required": ["query"]}}, {"if": {"properties": {"intent": {"const": "recover"}}}, "then": {"properties": {"query": {"$ref": "#/$defs/RecoverQuery"}}, "required": ["query"]}}, {"if": {"properties": {"intent": {"const": "repurpose"}}}, "then": {"properties": {"query": {"$ref": "#/$defs/RepurposeQuery"}}, "required": ["query"]}}, {"if": {"properties": {"intent": {"const": "adapt_equipment"}}}, "then": {"properties": {"query": {"$ref": "#/$defs/AdaptEquipmentQuery"}}, "required": ["query"]}}, {"if": {"properties": {"intent": {"const": "team_plan"}}}, "then": {"properties": {"query": {"$ref": "#/$defs/TeamPlanQuery"}}, "required": ["query"]}}, {"if": {"properties": {"intent": {"const": "store"}}}, "then": {"properties": {"query": {"$ref": "#/$defs/StoreQuery"}}, "required": ["query"]}}, {"if": {"properties": {"intent": {"const": "feed"}}}, "then": {"properties": {"query": {"$ref": "#/$defs/FeedQuery"}}, "required": ["query"]}}, {"if": {"properties": {"intent": {"const": "rescale"}}}, "then": {"properties": {"query": {"$ref": "#/$defs/RescaleQuery"}}, "required": ["query"]}}, {"if": {"properties": {"intent": {"const": "retime"}}}, "then": {"properties": {"query": {"$ref": "#/$defs/RetimeQuery"}}, "required": ["query"]}}, {"if": {"properties": {"intent": {"const": "diagnose"}}}, "then": {"properties": {"query": {"$ref": "#/$defs/DiagnoseQuery"}}, "required": ["query"]}}, {"if": {"properties": {"intent": {"const": "custom"}}}, "then": {"required": ["customIntent"]}}, {"if": {"properties": {"intent": {"const": "relief_allocate"}}}, "then": {"required": ["query"], "properties": {"query": {"type": "object", "required": ["needs"], "properties": {"needs": {"type": "array", "items": {"type": "string"}}, "pledges": {"type": "array", "items": {"type": "string"}}, "programs": {"type": "array", "items": {"type": "string"}}, "horizon": {"$ref": "common.schema.json#/$defs/Duration"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}}}, {"if": {"properties": {"intent": {"const": "personalize"}}}, "then": {"properties": {"query": {"$ref": "#/$defs/PersonalizeQuery"}}, "required": ["query"]}}], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "SafetyVerdict": {"type": "object", "required": ["verdict"], "properties": {"verdict": {"enum": ["safe", "safe_with_conditions", "unsafe_discard", "unknown_ask_human", "not_applicable"]}, "reasons": {"type": "array", "items": {"type": "string"}}, "rulesApplied": {"type": "array", "items": {"type": "string"}, "description": "Policy-pack rule ids and knowledge ids (e.g. cw.safety.tcs_4h, us.fda-food-code-2022/3-501.19)."}, "conditions": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "PatchOp": {"type": "object", "required": ["op"], "properties": {"op": {"enum": ["add_node", "replace_node", "remove_node", "insert_before", "insert_after", "update_params", "set_until", "add_ingredient", "scale_ingredient", "replace_ingredient", "remove_ingredient", "scale_all", "split_batch", "merge_batches", "discard_output", "add_hazard", "add_ccp", "set_supervision", "note"]}, "target": {"type": "string", "description": "Node id, ingredient ref or intermediate ref."}, "node": {"$ref": "recipe.schema.json#/$defs/Node"}, "ingredient": {"$ref": "recipe.schema.json#/$defs/Ingredient"}, "params": {"type": "object"}, "factor": {"anyOf": [{"type": "number", "exclusiveMinimum": 0}, {"type": "string", "pattern": "^\\{[A-Za-z_.]+\\}$", "description": "Template placeholder, only in playbooks; resolved before a patch is applied."}]}, "until": {"$ref": "common.schema.json#/$defs/Condition"}, "text": {"$ref": "common.schema.json#/$defs/LangMap"}}, "description": "One semantic change. In knowledge playbooks, string values may contain {placeholders} (e.g. {nodeId}, {salt_ratio}) that the reasoner resolves from the incident, answers and recipe.", "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "RecipePatch": {"type": "object", "description": "A semantic, validated change to a recipe's process graph (not raw JSON Patch), applied by the hub to the running session.", "required": ["base", "ops"], "properties": {"base": {"type": "object", "required": ["recipeId"], "properties": {"recipeId": {"type": "string"}, "revision": {"type": "integer"}, "hash": {"$ref": "common.schema.json#/$defs/Hash"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "ops": {"type": "array", "items": {"$ref": "#/$defs/PatchOp"}}, "resumeAt": {"type": "string", "description": "Node id to continue from after the patch."}, "redo": {"type": "array", "items": {"type": "string"}, "description": "Completed nodes whose outputs are invalidated and must be redone."}, "validated": {"type": "boolean", "description": "Patched graph passed schema + semantic validation + policy."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "PlannedTask": {"type": "object", "required": ["ref", "start", "end"], "properties": {"ref": {"type": "string", "description": "recipeId#nodeId, or recipeId#nodeId/part-k for split tasks."}, "op": {"type": "string"}, "start": {"$ref": "common.schema.json#/$defs/Duration", "description": "Offset from plan start."}, "end": {"$ref": "common.schema.json#/$defs/Duration"}, "resources": {"type": "array", "items": {"type": "string"}}, "handoffTo": {"type": "string"}, "attention": {"type": "string"}, "instructions": {"$ref": "common.schema.json#/$defs/LangMap"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "TeamPlan": {"type": "object", "required": ["assignments", "makespan"], "properties": {"assignments": {"type": "array", "items": {"type": "object", "required": ["actorId", "tasks"], "properties": {"actorId": {"type": "string"}, "role": {"type": "string"}, "tasks": {"type": "array", "items": {"$ref": "#/$defs/PlannedTask"}}, "utilization": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "makespan": {"$ref": "common.schema.json#/$defs/Duration"}, "startAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "serveAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "criticalPath": {"type": "array", "items": {"type": "string"}}, "handoffs": {"type": "array", "items": {"type": "object", "properties": {"from": {"type": "string"}, "to": {"type": "string"}, "item": {"type": "string"}, "at": {"$ref": "common.schema.json#/$defs/Duration"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "leases": {"type": "array", "items": {"type": "object", "properties": {"resource": {"type": "string"}, "holder": {"type": "string"}, "from": {"type": "string"}, "until": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "humanTasks": {"type": "array", "items": {"type": "string"}}, "slack": {"$ref": "common.schema.json#/$defs/Duration"}, "solver": {"type": "object", "properties": {"name": {"type": "string"}, "status": {"enum": ["optimal", "feasible", "infeasible", "timeout"]}, "objective": {"type": "string"}, "seconds": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "assumptions": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "StoragePlan": {"type": "object", "required": ["feasible"], "properties": {"feasible": {"type": "boolean"}, "method": {"enum": ["fridge", "freezer", "fridge_then_freezer", "freezer_then_fridge_thaw", "pantry_shelf_stable", "hot_hold", "not_storable"]}, "keepsFor": {"$ref": "common.schema.json#/$defs/Duration"}, "qualityBestWithin": {"$ref": "common.schema.json#/$defs/Duration"}, "cooling": {"type": "object", "properties": {"method": {"type": "string"}, "maxDepthCm": {"type": "number"}, "stages": {"type": "array", "items": {"type": "object", "properties": {"fromC": {"type": "number"}, "toC": {"type": "number"}, "within": {"$ref": "common.schema.json#/$defs/Duration"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "portioning": {"type": "object", "properties": {"portions": {"type": "integer"}, "massPerPortionG": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "containers": {"type": "array", "items": {"type": "object", "properties": {"type": {"type": "string"}, "material": {"type": "string"}, "sizeMl": {"type": "number"}, "count": {"type": "integer"}, "fillMaxPct": {"type": "number"}, "headspaceMm": {"type": "number"}, "airtight": {"type": "boolean"}, "freezerSafe": {"type": "boolean"}, "microwaveSafe": {"type": "boolean"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "separateComponents": {"type": "array", "items": {"type": "string"}, "description": "Store apart (sauce, crispy toppings, dressing, garnish)."}, "cookForStorage": {"$ref": "#/$defs/RecipePatch", "description": "Changes when cooking specifically for storage (undercook pasta, hold back garnish...)."}, "label": {"type": "array", "items": {"type": "string"}, "description": "What to write on the label: name, date cooked, use-by, allergens, reheat instructions."}, "thaw": {"type": "string"}, "reheat": {"type": "object", "properties": {"method": {"type": "string"}, "minCoreC": {"type": "number"}, "onlyOnce": {"type": "boolean"}, "notes": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "discardIf": {"type": "array", "items": {"type": "string"}}, "alternatives": {"type": "array", "items": {"type": "object", "properties": {"method": {"type": "string"}, "keepsFor": {"type": "string"}, "tradeoffs": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "ProductionPlan": {"type": "object", "properties": {"menu": {"type": "array", "items": {"type": "object", "properties": {"recipeId": {"type": "string"}, "servings": {"type": "number"}, "scale": {"type": "number"}, "batches": {"type": "integer"}, "meal": {"type": "string"}, "cookDay": {"type": "integer"}, "serveDay": {"type": "integer"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "schedule": {"$ref": "#/$defs/TeamPlan"}, "shopping": {"$ref": "order.schema.json"}, "storage": {"type": "array", "items": {"$ref": "#/$defs/StoragePlan"}}, "equipmentLoad": {"type": "array", "items": {"type": "object", "properties": {"resource": {"type": "string"}, "utilization": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "costTotal": {"$ref": "common.schema.json#/$defs/Money"}, "perPerson": {"type": "object"}, "constraintsMet": {"type": "array", "items": {"type": "string"}}, "constraintsRelaxed": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Option": {"type": "object", "required": ["id", "kind", "title", "confidence", "safety"], "properties": {"id": {"type": "string"}, "rank": {"type": "integer"}, "kind": {"enum": ["recipe", "recipe_with_changes", "patch_and_resume", "repurpose", "discard_and_restart", "discard", "substitution", "equipment_adaptation", "team_plan", "storage_plan", "production_plan", "timing_plan", "shopping", "ask_human", "allocation", "portion_plan"]}, "title": {"$ref": "common.schema.json#/$defs/LangMap"}, "summary": {"$ref": "common.schema.json#/$defs/LangMap"}, "recipeIds": {"type": "array", "items": {"type": "string"}}, "patch": {"$ref": "#/$defs/RecipePatch"}, "teamPlan": {"$ref": "#/$defs/TeamPlan"}, "storagePlan": {"$ref": "#/$defs/StoragePlan"}, "productionPlan": {"$ref": "#/$defs/ProductionPlan"}, "orderIntent": {"$ref": "order.schema.json"}, "coverage": {"type": "object", "description": "For cook_from: how the recipe matches what's available.", "properties": {"have": {"type": "array", "items": {"type": "string"}}, "missing": {"type": "array", "items": {"type": "string"}}, "substituted": {"type": "array", "items": {"type": "object", "properties": {"from": {"type": "string"}, "to": {"type": "string"}, "ratio": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "usesFirst": {"type": "array", "items": {"type": "string"}}, "automation": {"type": "number", "minimum": 0, "maximum": 1}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "impact": {"type": "object", "properties": {"extraTime": {"$ref": "common.schema.json#/$defs/Duration"}, "extraCost": {"$ref": "common.schema.json#/$defs/Money"}, "quality": {"enum": ["better", "none", "minor", "noticeable", "major"]}, "servingsChange": {"type": "number"}, "notes": {"$ref": "common.schema.json#/$defs/LangMap"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "requires": {"type": "object", "properties": {"ingredients": {"type": "array", "items": {"type": "string"}}, "equipment": {"type": "array", "items": {"type": "string"}}, "actors": {"type": "array", "items": {"type": "string"}}, "human": {"type": "boolean"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "safety": {"$ref": "#/$defs/SafetyVerdict"}, "confidence": {"type": "number", "minimum": 0, "maximum": 1}, "evidence": {"type": "array", "items": {"type": "object", "required": ["kind", "ref"], "properties": {"kind": {"enum": ["playbook", "rule", "recipe", "simulation", "solver", "field_reports", "llm", "reference"]}, "ref": {"type": "string"}, "detail": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "explanation": {"$ref": "common.schema.json#/$defs/LangMap"}, "allocation": {"$ref": "relief.schema.json#/$defs/Allocation"}, "portionPlan": {"$ref": "#/$defs/PortionPlan"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Question": {"type": "object", "required": ["id", "text", "answerType"], "properties": {"id": {"type": "string"}, "text": {"$ref": "common.schema.json#/$defs/LangMap"}, "answerType": {"enum": ["boolean", "number", "choice", "text", "measurement", "photo"]}, "choices": {"type": "array", "items": {"type": "string"}}, "sensor": {"type": "string", "description": "A robot can answer by measuring this sensor instead of asking a human."}, "why": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "AdviceResponse": {"type": "object", "required": ["cookwala", "requestId", "intent", "status", "safety", "options"], "properties": {"cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "requestId": {"type": "string"}, "responseId": {"type": "string"}, "intent": {"$ref": "#/$defs/Intent"}, "resolvedIntent": {"$ref": "#/$defs/Intent", "description": "For intent=ask: what the question was understood as."}, "resolvedQuery": {"$ref": "#/$defs/Query"}, "status": {"enum": ["answered", "needs_input", "partial", "refused", "unsupported"]}, "safety": {"$ref": "#/$defs/SafetyVerdict", "description": "Overall verdict. If unsafe_discard, no option may keep the unsafe food."}, "options": {"type": "array", "items": {"$ref": "#/$defs/Option"}}, "questions": {"type": "array", "items": {"$ref": "#/$defs/Question"}}, "warnings": {"type": "array", "items": {"$ref": "common.schema.json#/$defs/LangMap"}}, "engine": {"type": "object", "properties": {"version": {"type": "string"}, "components": {"type": "array", "items": {"type": "string"}}, "llm": {"type": "object", "properties": {"used": {"type": "boolean"}, "model": {"type": "string"}, "role": {"enum": ["parse", "propose", "explain", "none"]}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "checks": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "generatedAt": {"$ref": "common.schema.json#/$defs/DateTime"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "PortionPlan": {"type": "object", "description": "Right amount for each person from a dish or menu, so everyone meets their targets and nothing is wasted.", "properties": {"recipeId": {"type": "string"}, "totalCookedG": {"type": "number"}, "people": {"type": "array", "items": {"type": "object", "required": ["personId", "grams"], "properties": {"personId": {"type": "string"}, "grams": {"type": "number"}, "components": {"type": "object", "additionalProperties": {"type": "number"}, "description": "Grams per component (e.g. rice 120, stew 220)."}, "nutrition": {"type": "object", "properties": {"kcal": {"type": "number"}, "proteinG": {"type": "number"}, "carbsG": {"type": "number"}, "fatG": {"type": "number"}, "fiberG": {"type": "number"}, "sodiumMg": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "dayProgress": {"type": "object", "description": "Share of the person's daily targets covered after this meal (0..1 per nutrient).", "additionalProperties": {"type": "number"}}, "modifications": {"type": "array", "items": {"type": "string"}, "description": "e.g. 'serve before adding salt', 'IDDSI 5 minced', 'no sauce'."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "cookQuantityFactor": {"type": "number", "description": "Scale to cook so total portions + planned leftovers are exact."}, "plannedLeftovers": {"type": "object", "properties": {"grams": {"type": "number"}, "use": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "wasteEstimateG": {"type": "number"}, "cost": {"type": "object", "properties": {"total": {"$ref": "common.schema.json#/$defs/Money"}, "perPerson": {"type": "object", "additionalProperties": {"$ref": "common.schema.json#/$defs/Money"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "PersonalizeQuery": {"type": "object", "properties": {"personIds": {"type": "array", "items": {"type": "string"}, "description": "Members of the client profile (resolved locally by the hub)."}, "recipeIds": {"type": "array", "items": {"type": "string"}, "description": "Portion these dishes; omit to get a meal plan."}, "days": {"type": "integer", "minimum": 1}, "mealTypes": {"type": "array", "items": {"type": "string"}}, "optimize": {"type": "array", "items": {"enum": ["nutrition_fit", "cost", "waste", "organic", "local", "variety", "prep_time", "energy"]}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}}, "https://cookwala.ai/v1/schemas/capabilities.schema.json": {"$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}, "https://cookwala.ai/v1/schemas/catalog.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/catalog.schema.json", "title": "Cookwala Catalog (index) documents", "x-cookwala-status": "core", "description": "Static documents served by any Cookwala index (the reference index at cookwala.ai or a mirror). Use the $defs by name: Discovery (/.well-known/cookwala.json), Manifest (/v1/manifest.json), IndexEntry (items of /v1/index/{lang}/{page}.json), Changes (/v1/changes/{sinceVersion}.json), Vocabulary (/v1/vocab/{name}.json).", "$defs": {"Discovery": {"type": "object", "required": ["cookwala", "name", "versions", "keys", "endpoints", "terms"], "properties": {"cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "name": {"type": "string"}, "operator": {"type": "string"}, "versions": {"type": "array", "items": {"type": "string"}}, "keys": {"type": "array", "items": {"$ref": "common.schema.json#/$defs/KeyRecord"}, "description": "Public keys of the catalog, with validity and revocation. Verifiers cache them for offline use."}, "endpoints": {"type": "object", "properties": {"manifest": {"type": "string"}, "recipe": {"type": "string"}, "index": {"type": "string"}, "changes": {"type": "string"}, "dump": {"type": "string"}, "vocab": {"type": "string"}, "policies": {"type": "string"}, "schemas": {"type": "string"}, "rest": {"type": "string"}, "graphql": {"type": "string"}, "openapi": {"type": "string"}, "mcp": {"type": "string"}, "a2a": {"type": "string"}, "reports": {"type": "string"}, "coreApi": {"type": "string", "description": "Core API description (api/core.openapi.yaml)."}, "recalls": {"type": "string", "description": "Recall feed (GET, ?since=)."}, "incidents": {"type": "string", "description": "Anonymous incident reports (POST)."}, "schemaBundle": {"type": "string", "description": "All schemas in one file for offline validation."}, "conformance": {"type": "string", "description": "Conformance vectors."}, "safetyLimits": {"type": "string", "description": "Default safety-limits pack."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "mirrors": {"type": "array", "items": {"type": "string"}}, "contact": {"type": "string"}, "terms": {"type": "string"}, "license": {"type": "string"}, "roles": {"type": "array", "items": {"enum": ["catalog", "hub", "provider", "registry", "advisor", "marketplace", "mirror"]}}, "visibility": {"enum": ["public", "private", "unlisted"]}, "auth": {"type": "object", "description": "For private catalogs.", "properties": {"schemes": {"type": "array", "items": {"enum": ["none", "oauth2", "api_key", "mtls", "did_auth"]}}, "tokenUrl": {"type": "string"}, "docs": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "federation": {"type": "object", "properties": {"trusts": {"type": "array", "items": {"type": "object", "properties": {"catalog": {"type": "string"}, "keys": {"type": "array", "items": {"type": "string"}}, "priority": {"type": "integer"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "registry": {"type": "string"}, "feeds": {"type": "object", "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "description": "Signed feeds this node publishes. Readers verify every item against its ISSUER's KeyRecord, never the relaying node's (RFC-0006).", "properties": {"recalls": {"type": "string", "format": "uri"}, "incidents": {"type": "string", "format": "uri"}, "registry": {"type": "string", "format": "uri"}, "keys": {"type": "string", "format": "uri"}}}, "peers": {"type": "array", "items": {"type": "string", "format": "uri"}, "description": "Catalogs or registries this node suggests; a hub may ignore them."}, "relays": {"type": "boolean", "description": "True if this node republishes other issuers' signed items unchanged, with x-relay provenance."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "extensions": {"type": "array", "items": {"type": "string"}, "description": "Extension manifests this server supports/serves."}, "provider": {"type": "string", "description": "URL of the operator's market Provider document."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Manifest": {"type": "object", "required": ["cookwala", "version", "generatedAt", "counts", "shards"], "properties": {"cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "version": {"type": "string"}, "generatedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "counts": {"type": "object", "properties": {"recipes": {"type": "integer"}, "byLevel": {"type": "object"}, "countries": {"type": "integer"}, "languages": {"type": "integer"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "languages": {"type": "array", "items": {"type": "string"}}, "shards": {"type": "array", "items": {"type": "object", "required": ["path", "hash"], "properties": {"path": {"type": "string"}, "hash": {"$ref": "common.schema.json#/$defs/Hash"}, "bytes": {"type": "integer"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "signature": {"$ref": "common.schema.json#/$defs/Signature"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "IndexEntry": {"type": "object", "required": ["id", "title", "hash", "level"], "properties": {"id": {"type": "string"}, "revision": {"type": "integer"}, "hash": {"$ref": "common.schema.json#/$defs/Hash"}, "title": {"type": "string"}, "cuisine": {"type": "array", "items": {"type": "string"}}, "course": {"type": "string"}, "tags": {"type": "array", "items": {"type": "string"}}, "level": {"enum": ["V0", "V1", "V2", "V3"]}, "totalTimeS": {"type": "integer"}, "activeTimeS": {"type": "integer"}, "servings": {"type": "number"}, "allergens": {"type": "array", "items": {"type": "string"}}, "dietary": {"type": "array", "items": {"type": "string"}}, "ops": {"type": "array", "items": {"type": "string"}}, "equipment": {"type": "array", "items": {"type": "string"}}, "sensors": {"type": "array", "items": {"type": "string"}}, "maxTempC": {"type": "number"}, "supervision": {"type": "string"}, "kcal": {"type": "number"}, "thumb": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Changes": {"type": "object", "required": ["from", "to", "upserted", "removed"], "properties": {"from": {"type": "string"}, "to": {"type": "string"}, "upserted": {"type": "array", "items": {"type": "object", "properties": {"id": {"type": "string"}, "hash": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "removed": {"type": "array", "items": {"type": "object", "properties": {"id": {"type": "string"}, "reason": {"enum": ["withdrawn", "safety_recall", "rights", "duplicate"]}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "recalls": {"type": "array", "items": {"type": "object", "properties": {"id": {"type": "string"}, "severity": {"type": "string"}, "message": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "description": "Devices must stop executing recalled revisions."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Vocabulary": {"type": "object", "required": ["name", "version", "entries"], "properties": {"name": {"enum": ["ingredients", "ops", "equipment", "sensors", "hazards", "units", "classes", "incidents", "modes", "roles", "facets"]}, "version": {"type": "string"}, "entries": {"type": "array", "items": {"type": "object", "required": ["id", "label"], "properties": {"id": {"$ref": "common.schema.json#/$defs/VocabId"}, "label": {"$ref": "common.schema.json#/$defs/LangMap"}, "definition": {"type": "string"}, "classes": {"type": "array", "items": {"type": "string"}}, "paramsSchema": {"type": "object", "description": "ops only: JSON Schema for node.params."}, "sensors": {"type": "array", "items": {"type": "string"}, "description": "ops only: sensors usable in until conditions."}, "allergens": {"type": "array", "items": {"type": "string"}}, "density": {"type": "number", "description": "ingredients: g/ml for volume conversion."}, "links": {"type": "object", "properties": {"wikidata": {"type": "string"}, "foodon": {"type": "string"}, "usdaFdc": {"type": "string"}, "ieee1872": {"type": "string"}, "matter": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "deprecated": {"type": "boolean"}, "replacedBy": {"type": "string"}, "envelope": {"type": "object", "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "description": "ops only: the physical meaning of the operation. Executors must keep the medium inside tempC (and pressureKPa) unless the recipe sets a narrower target inside it; conformance vectors in testMethod check this.", "properties": {"medium": {"enum": ["water", "oil", "air", "steam", "pan_surface", "product", "ambient", "pressure", "radiant", "none"]}, "tempC": {"type": "object", "required": ["min", "max"], "unevaluatedProperties": false, "properties": {"min": {"type": "number"}, "max": {"type": "number"}}}, "pressureKPa": {"type": "object", "required": ["min", "max"], "unevaluatedProperties": false, "properties": {"min": {"type": "number"}, "max": {"type": "number"}}}, "agitation": {"enum": ["none", "occasional", "frequent", "continuous"]}, "lid": {"enum": ["on", "off", "any"]}, "sensorLadder": {"type": "array", "items": {"type": "string", "pattern": "^(cw\\.sense\\.[a-z0-9_]+|x-[a-z0-9-]+\\.[a-z0-9_.-]+|model|time|human)$"}, "description": "Ways to verify the step, best first. model = a logged estimate; time = nominal time only; human = a person confirms. If the ladder has no entry the executor can satisfy, the step must not run."}, "attention": {"enum": ["none", "periodic", "monitor", "continuous"]}, "unattended": {"type": "boolean"}, "hazards": {"type": "array", "items": {"type": "string"}}, "note": {"type": "string"}, "testMethod": {"type": "string"}}}, "convert": {"type": "object", "required": ["to", "factor"], "unevaluatedProperties": false, "properties": {"to": {"type": "string"}, "factor": {"type": "number", "exclusiveMinimum": 0}}, "description": "units only: exact conversion to a base unit."}, "surfaceTempC": {"type": "object", "required": ["min", "max"], "unevaluatedProperties": false, "properties": {"min": {"type": "number"}, "max": {"type": "number"}}, "description": "heat levels only."}, "family": {"type": "string", "pattern": "^[a-z_.]+$", "description": "facets only: facet family (self, mandate, household.people, household.pets, household.culture, household.tastes, household.health, household.behavior, household.economics, space, space.environment, devices, resources, commerce, service, history)."}, "privacy": {"enum": ["public", "household", "sensitive", "secret"], "description": "facets only: default privacy class. Implementations may raise it, never lower it (RFC-0001)."}, "travel": {"enum": ["never", "derived", "consented"], "description": "facets only: whether the raw fact may leave the home: never; only as a derived constraint; or as a selective disclosure after explicit consent."}, "derivesTo": {"type": "array", "items": {"type": "string", "pattern": "^[a-z_]+$"}, "description": "facets only: DerivedConstraint types this facet may produce (household.schema.json)."}, "sources": {"type": "array", "items": {"enum": ["declared", "observed", "reported", "inferred"]}, "description": "facets only: who may assert this fact."}, "valueHint": {"type": "string", "maxLength": 200, "description": "facets only: shape of the value in plain words."}, "safetyUse": {"enum": ["allowed", "never"], "description": "facets only: whether a safety decision may rely on this fact. Inferred facts are never allowed."}, "executable": {"type": "boolean", "default": true, "description": "false: never runs on a device; a capabilities document that declares the operation is ignored and a dry run assigns the step to a person or refuses (cw.op.legacy_step, RFC-0009)."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "RegistryEntry": {"type": "object", "required": ["kind", "url"], "description": "Item in a registry (/v1/registry.json): anyone can list a catalog, recipe collection, extension, flow, provider, knowledge pack, policy or rule pack hosted anywhere. Modelled on the MCP Registry: verified namespaces, pinned versions, integrity hashes and a lifecycle status (docs/REGISTRY.md).", "properties": {"kind": {"enum": ["advisor", "benchmark", "catalog", "device", "extension", "flow", "hub", "kitchen", "knowledge", "policy_pack", "program", "provider", "recipe_collection", "rule_pack", "safety_limits"]}, "id": {"type": "string"}, "url": {"type": "string"}, "name": {"type": "string", "pattern": "^[a-z0-9.-]+/[a-z0-9._-]+$", "minLength": 3, "maxLength": 200, "description": "<namespace>/<name>. The namespace is a reverse-DNS domain the publisher proved control of (org.fifi-cooking/egyptian-home) or a code-host account (io.github.amado2k5/recipes)."}, "description": {"type": "string", "minLength": 1, "maxLength": 100, "description": "One clear sentence, 100 characters at most."}, "tags": {"type": "array", "items": {"type": "string"}}, "verified": {"type": "boolean"}, "conformance": {"type": "array", "items": {"type": "string"}}, "addedAt": {"type": "string"}, "version": {"type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+(-[0-9A-Za-z.-]+)?$", "description": "An exact version. Ranges (^1.2, ~1.2, >=1, 1.x) are rejected."}, "status": {"enum": ["active", "deprecated", "recalled", "deleted"], "description": "recalled entries also appear in the recall feed; deleted entries stay listed as tombstones so ids are never reused."}, "verification": {"type": "object", "required": ["method", "verifiedAt"], "unevaluatedProperties": false, "properties": {"method": {"enum": ["dns_txt", "http_well_known", "github_oidc", "gitlab_oidc", "signature"]}, "verifiedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "by": {"type": "string", "description": "Registry that verified it."}}}, "repository": {"type": "object", "unevaluatedProperties": false, "properties": {"url": {"type": "string", "format": "uri"}, "source": {"enum": ["github", "gitlab", "codeberg", "other"]}, "id": {"type": "string", "description": "Stable id from the code host; changes if the repository is deleted and recreated (resurrection attacks)."}, "subfolder": {"type": "string"}}}, "sha256": {"type": "string", "pattern": "^[a-f0-9]{64}$", "description": "Hash of the published artifact; clients verify before use."}, "icons": {"type": "array", "items": {"type": "object", "required": ["src"], "unevaluatedProperties": false, "properties": {"src": {"type": "string", "format": "uri", "pattern": "^https://"}, "mimeType": {"enum": ["image/png", "image/jpeg", "image/svg+xml", "image/webp"]}, "sizes": {"type": "array", "items": {"type": "string", "pattern": "^([0-9]+x[0-9]+|any)$"}}, "theme": {"enum": ["light", "dark"]}}}}, "publishedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "coreVersion": {"type": "string", "description": "Cookwala Core version this entry targets."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "DirectoryEntry": {"type": "object", "required": ["kind", "id", "name", "roles", "country", "status", "addedAt"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "description": "An organization that takes part in Cookwala, listed at its own request in a directory (/v1/directory.json). Never a person. Listing means the organization asked to be listed and its namespace was checked; it does not mean endorsement, certification or partnership (RFC-0002).", "properties": {"kind": {"const": "DirectoryEntry"}, "id": {"type": "string", "pattern": "^(did:web:[a-z0-9.-]+|org:[a-z0-9-]+\\.[a-z0-9.-]+|gln:[0-9]{13})$"}, "name": {"type": "string", "minLength": 1, "maxLength": 120}, "description": {"type": "string", "maxLength": 200}, "roles": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"enum": ["device_maker", "appliance_maker", "agent_builder", "catalog", "registry", "hub_vendor", "food_bank", "community_kitchen", "school_program", "relief_program", "farm_or_cooperative", "grocer_or_retailer", "restaurant_or_food_service", "recipe_publisher", "certifier", "research_lab", "health_body", "government", "insurer", "translator_community", "other"]}}, "country": {"type": "string", "pattern": "^[A-Z]{2}$"}, "url": {"type": "string", "format": "uri", "pattern": "^https://"}, "contact": {"type": "string", "maxLength": 200, "description": "A role address or page, never a person's name or number."}, "conformance": {"type": "array", "items": {"$ref": "common.schema.json#/$defs/Hash"}, "description": "Hashes of published ConformanceReport documents (conformance.schema.json)."}, "humanitarianLevels": {"type": "array", "uniqueItems": true, "items": {"enum": ["H0", "H1", "H2", "H3"]}}, "verification": {"type": "object", "required": ["method", "verifiedAt", "by"], "unevaluatedProperties": false, "properties": {"method": {"enum": ["dns_txt", "well_known", "code_host_oidc", "vouched_by_program", "none"]}, "verifiedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "by": {"type": "string", "description": "Registry or program that checked it."}}}, "status": {"enum": ["active", "inactive", "deleted"]}, "addedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "updatedAt": {"$ref": "common.schema.json#/$defs/DateTime"}}}, "CommunityNamespaceFile": {"type": "object", "description": "recipes/community/NAMESPACES.json: the id-prefix claims that let anyone add a recipe to Cookwala without colliding with another contributor or a reserved collection (docs/CONTRIBUTE-RECIPES.md, RFC-0013). Checked by tools/check_community_namespaces.py.", "required": ["reservedPrefixes", "namespaces"], "unevaluatedProperties": false, "properties": {"$schema": {"type": "string"}, "note": {"type": "string"}, "rules": {"type": "array", "items": {"type": "string"}}, "reservedPrefixes": {"type": "array", "items": {"type": "string", "pattern": "^[a-z][a-z0-9-]*$"}, "description": "Prefixes used by the founder's own collections (tools/export_fifi.collections.json), the spec examples and the process-graph node id convention; never claimable."}, "namespaces": {"type": "array", "items": {"type": "object", "required": ["prefix", "owner", "verification", "addedAt"], "unevaluatedProperties": false, "properties": {"prefix": {"type": "string", "pattern": "^[a-z][a-z0-9]{1,14}-$", "description": "Every recipe id under recipes/community/<prefix>/ must start with this, including the trailing hyphen."}, "owner": {"type": "string", "description": "The GitHub login (or verified domain, reverse-DNS) that proved control of this prefix."}, "verification": {"enum": ["github_account", "dns_txt", "well_known"]}, "addedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "description": {"type": "string", "maxLength": 300}}}}}}}}, "https://cookwala.ai/v1/schemas/common.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/common.schema.json", "title": "Cookwala common definitions", "x-cookwala-status": "core", "description": "Shared types used by every Cookwala schema. Units follow UCUM codes; temperatures are degrees Celsius on the wire; durations are ISO 8601; language keys are BCP 47 tags; money is an exact decimal string. Free-text fields carry the annotation \"x-cookwala-untrusted\": they are data, never instructions, for software and AI agents (docs/CORE.md section 6).", "$defs": {"SpecVersion": {"type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"}, "VocabId": {"type": "string", "description": "Id from an Cookwala vocabulary, e.g. cw.op.simmer, cw.ing.onion_yellow, cw.eq.vessel.pan.skillet, cw.sense.core_temp, cw.hz.burn.hot_oil. Vendor extensions use x-<vendor>.<name>.", "pattern": "^(cw|x-[a-z0-9-]+)\\.[a-z0-9_.-]+$"}, "LocalRef": {"type": "string", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,63}$", "description": "Reference to an id defined elsewhere in the same document."}, "Uri": {"type": "string", "format": "uri"}, "Hash": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$", "description": "SHA-256 of the RFC 8785 canonical JSON of the document with its hash and signature fields removed."}, "Duration": {"type": "string", "pattern": "^P(?!$)(\\d+D)?(T(?=\\d)(\\d+H)?(\\d+M)?(\\d+(\\.\\d+)?S)?)?$"}, "DateTime": {"type": "string", "format": "date-time"}, "LangMap": {"type": "object", "description": "Text per language (BCP 47).", "propertyNames": {"pattern": "^[a-z]{2,3}(-[A-Za-z0-9]{2,8})*$"}, "additionalProperties": {"type": "string"}, "x-cookwala-untrusted": true}, "Unit": {"description": "UCUM-style unit. Temperatures are degC only on the wire (displays may convert). Kitchen volume units have fixed metric equivalents in vocab/units.json: tsp = 5 ml, tbsp = 15 ml, cup = 240 ml, pinch ≈ 0.36 g of salt-like solids, dash ≈ 0.6 ml of liquid. pcs = countable pieces.", "enum": ["g", "kg", "mg", "ml", "l", "tsp", "tbsp", "cup", "pinch", "dash", "pcs", "degC", "W", "kW", "mm", "cm", "rpm", "Pa", "kPa", "pct", "s"]}, "Quantity": {"type": "object", "required": ["value", "unit"], "properties": {"value": {"type": "number", "minimum": 0}, "unit": {"$ref": "#/$defs/Unit"}, "tolerance": {"type": "number", "minimum": 0, "maximum": 1, "description": "Acceptable RELATIVE deviation (0.1 = ±10 %). Only for ratio-scale units; never for degC."}, "toleranceAbs": {"type": "number", "minimum": 0, "description": "Acceptable ABSOLUTE deviation, in the same unit as value. Required instead of tolerance for degC."}, "pieces": {"type": "number", "minimum": 0, "description": "Human count when value is a mass (e.g. 1 onion)."}, "massPerPiece": {"$ref": "#/$defs/Quantity"}, "densityGPerMl": {"type": "number", "exclusiveMinimum": 0, "description": "Density used to convert between volume and mass for this quantity. Overrides the ingredient vocabulary density."}}, "allOf": [{"if": {"required": ["tolerance"]}, "then": {"properties": {"unit": {"$ref": "#/$defs/RatioUnit"}}}}, {"not": {"required": ["tolerance", "toleranceAbs"]}}], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Range": {"type": "object", "properties": {"min": {"type": "number"}, "max": {"type": "number"}, "unit": {"$ref": "#/$defs/Unit"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Target": {"type": "object", "required": ["sensor", "value", "unit"], "properties": {"sensor": {"$ref": "#/$defs/VocabId"}, "value": {"type": "number"}, "unit": {"$ref": "#/$defs/Unit"}, "tolerance": {"type": "number", "minimum": 0, "description": "ABSOLUTE tolerance, in the same unit as value (e.g. 2 for ±2 °C)."}, "target": {"type": "string", "description": "What the sensor measures, e.g. egg_yolk, thickest_part."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Comparison": {"type": "object", "description": "A single sensor or vision check.", "properties": {"sensor": {"$ref": "#/$defs/VocabId"}, "vision": {"$ref": "#/$defs/VocabId"}, "target": {"type": "string"}, "gte": {"$ref": "#/$defs/NumberOrParam"}, "lte": {"$ref": "#/$defs/NumberOrParam"}, "eq": {}, "between": {"type": "array", "items": {"$ref": "#/$defs/NumberOrParam"}, "minItems": 2, "maxItems": 2}, "unit": {"$ref": "#/$defs/Unit"}, "holdFor": {"$ref": "#/$defs/Duration", "description": "Condition must hold continuously this long (e.g. 63 °C for 15 s)."}, "confidence": {"type": "number", "minimum": 0, "maximum": 1, "description": "Minimum classifier confidence for vision cues."}, "optional": {"type": "boolean", "description": "Use if the device has this sensor; otherwise rely on the rest of the condition."}, "humanConfirm": {"type": "boolean", "description": "A human may confirm this cue instead of a sensor."}}, "oneOf": [{"required": ["sensor"]}, {"required": ["vision"]}], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Condition": {"type": "object", "description": "End condition for a step: boolean tree of checks plus a time window. Satisfied when the tree is true AND minTime has elapsed; maxTime triggers onTimeout.", "properties": {"all": {"type": "array", "items": {"$ref": "#/$defs/ConditionOrCheck"}}, "any": {"type": "array", "items": {"$ref": "#/$defs/ConditionOrCheck"}}, "not": {"$ref": "#/$defs/ConditionOrCheck"}, "minTime": {"$ref": "#/$defs/Duration"}, "maxTime": {"$ref": "#/$defs/Duration"}, "nominalTime": {"$ref": "#/$defs/Duration", "description": "Typical duration for planning and timers."}, "onSensorMissing": {"enum": ["estimate", "time", "human", "refuse"], "description": "What an executor does when it lacks a sensor this condition needs. estimate = model-based estimate (must be logged); time = rely on nominalTime/minTime only; human = ask a person to confirm; refuse = the step must not run. Default: estimate if the op envelope allows it, else human. Steps guarding a critical control point default to refuse."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "ConditionOrCheck": {"anyOf": [{"$ref": "#/$defs/Condition"}, {"$ref": "#/$defs/Comparison"}]}, "FailureAction": {"enum": ["retry", "extend", "ask_human", "handoff_human", "skip_optional", "abort_safe"]}, "Severity": {"enum": ["info", "low", "medium", "high", "critical"]}, "Signature": {"type": "object", "required": ["alg", "kid", "sig", "signedAt"], "properties": {"alg": {"enum": ["EdDSA", "ES256"], "description": "EdDSA (Ed25519) is mandatory to implement; ES256 is allowed for hardware keys that only support P-256. New algorithms are added by minor version."}, "kid": {"type": "string", "description": "Key id: <actor DID or catalog URL>#<key name>, resolvable to a KeyRecord."}, "sig": {"type": "string", "pattern": "^[A-Za-z0-9_-]+$", "description": "Base64url signature over the RFC 8785 canonical JSON of the signing header {alg, hash, kid, kind, signedAt}, where hash is the document hash (RFC-0012; docs/CORE.md section 5)."}, "signedAt": {"$ref": "#/$defs/DateTime", "description": "When the signature was made. Covered by the signature, so revocation and validity windows can be checked against it."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Actor": {"type": "object", "required": ["kind", "id"], "properties": {"kind": {"enum": ["human", "robot", "appliance", "agent", "hub", "service", "sensor"]}, "id": {"type": "string", "description": "Stable id within a kitchen, e.g. robot:neo-1, appliance:oven-main, human:primary."}, "name": {"type": "string"}, "vendor": {"type": "string"}, "model": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Money": {"type": "object", "required": ["amount", "currency"], "properties": {"amount": {"$ref": "#/$defs/Decimal"}, "currency": {"type": "string", "pattern": "^[A-Z]{3}$"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Meta": {"type": "object", "description": "Who owns a document, where it lives and who may see it. Any Cookwala document may carry meta.", "properties": {"owner": {"type": "string", "description": "Person, org or device id (e.g. did:web:acme.example, github:amado2k5, cookwala.ai)."}, "catalog": {"type": "string", "description": "Base URL of the catalog that publishes it (public, private or local)."}, "visibility": {"enum": ["public", "unlisted", "shared", "private", "local_only"]}, "sharedWith": {"type": "array", "items": {"type": "string"}}, "sensitive": {"type": "boolean", "description": "Contains personal or health data: never send to an index, never log in reports."}, "createdAt": {"$ref": "#/$defs/DateTime"}, "updatedAt": {"$ref": "#/$defs/DateTime"}, "derivedFrom": {"type": "array", "items": {"type": "string"}, "description": "Global refs of documents this one forks or extends."}, "extensions": {"type": "array", "items": {"type": "string"}, "description": "Extension ids whose x- fields appear in this document."}, "tags": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "GlobalRef": {"type": "string", "description": "Global reference to a document in any catalog: '<catalog base URL>#<id>' or 'cw:<authority>:<id>' (authority = catalog domain or x-namespace). Bare ids refer to the current catalog.", "pattern": "^(https?://[^#\\s]+#[A-Za-z0-9._:-]+|cw:[a-z0-9.-]+:[A-Za-z0-9._:-]+|[A-Za-z0-9._-]+)$"}, "EnergyEstimate": {"type": "object", "description": "Estimated energy for a step or plan; values are estimates for planning, not measurements.", "properties": {"source": {"enum": ["electric_induction", "electric_resistive", "natural_gas", "propane", "charcoal", "wood", "solar_cooker", "battery", "any"]}, "kWh": {"type": "number", "minimum": 0}, "gasMJ": {"type": "number", "minimum": 0}, "peakW": {"type": "number", "minimum": 0}, "robotWh": {"type": "number", "minimum": 0, "description": "Robot battery energy for manipulation/motion."}, "waterL": {"type": "number", "minimum": 0}, "co2eKg": {"type": "number", "minimum": 0}, "basis": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "RatioUnit": {"description": "Units on a ratio scale (zero means none), where a relative tolerance makes sense. degC is an interval scale and never takes a relative tolerance.", "enum": ["g", "kg", "mg", "ml", "l", "tsp", "tbsp", "cup", "pinch", "dash", "pcs", "W", "kW", "mm", "cm", "rpm", "Pa", "kPa", "pct", "s"]}, "Decimal": {"type": "string", "pattern": "^-?[0-9]{1,15}(\\.[0-9]{1,6})?$", "description": "Exact decimal as a string; never a binary float."}, "KeyRecord": {"type": "object", "required": ["kid", "alg", "publicKey", "validFrom"], "description": "A public key bound to an actor. Published in /.well-known/cookwala.json (catalogs), a did:web document (organizations, people) or the device capabilities document (robots, appliances). Verifiers cache records for offline use.", "properties": {"kid": {"type": "string"}, "alg": {"enum": ["EdDSA", "ES256"]}, "publicKey": {"type": "string", "pattern": "^[A-Za-z0-9_-]+$", "description": "Base64url raw public key."}, "actor": {"type": "string", "description": "Actor or organization the key belongs to."}, "validFrom": {"$ref": "#/$defs/DateTime"}, "validTo": {"$ref": "#/$defs/DateTime"}, "revokedAt": {"$ref": "#/$defs/DateTime", "description": "Signatures with signedAt after this time are invalid."}, "revocationReason": {"enum": ["compromised", "superseded", "retired"]}, "hardwareBacked": {"type": "boolean"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Disclosure": {"type": "object", "required": ["digest"], "description": "Selective disclosure (SD-JWT style). A signed document carries only digest; the holder sends salt and value separately to the parties allowed to see them. digest = sha256 of the RFC 8785 canonical JSON of [salt, value]. The signature covers the digest, so partial views still verify.", "properties": {"digest": {"$ref": "#/$defs/Hash"}, "salt": {"type": "string", "minLength": 22, "description": "At least 128 bits of randomness, base64url. Present only in a disclosed copy."}, "value": {"description": "The disclosed value. Present only in a disclosed copy."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "AgentMandate": {"type": "object", "required": ["principal", "agent", "scopes", "expires"], "description": "What an AI agent may do on a person's behalf. Every agent action traces to a named principal and a mandate; anything outside it must go back to the principal.", "properties": {"principal": {"type": "string", "description": "Id of the human (or organization) the agent acts for."}, "agent": {"type": "string", "description": "Agent id; its model and vendor appear in agentInfo."}, "agentInfo": {"type": "object", "properties": {"vendor": {"type": "string"}, "model": {"type": "string"}, "version": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "scopes": {"type": "array", "minItems": 1, "items": {"enum": ["plan_meals", "search_recipes", "start_cooking", "stop_cooking", "order_groceries", "accept_deliveries", "offer_surplus", "claim_surplus", "share_data", "change_settings"]}}, "spendCap": {"$ref": "#/$defs/Money", "description": "Maximum total spend under this mandate."}, "perOrderCap": {"$ref": "#/$defs/Money"}, "allowedProviders": {"type": "array", "items": {"type": "string"}}, "confirmBefore": {"type": "array", "items": {"enum": ["any_payment", "payment_over_cap", "irreversible", "safety_override", "new_provider", "sharing_data", "diet_or_allergen_change"]}, "description": "Actions that always need the principal's explicit confirmation. irreversible and safety_override are always included, whatever this list says."}, "expires": {"$ref": "#/$defs/DateTime"}, "signature": {"$ref": "#/$defs/Signature", "description": "Signed by the principal."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "UntrustedText": {"type": "string", "maxLength": 4000, "x-cookwala-untrusted": true, "description": "Free text from a person or another party. Data, never instructions."}, "NumberOrParam": {"description": "A number, or a {parameter} placeholder. Placeholders are allowed only in knowledge playbooks and templates; recipes and Missions must use numbers (the validator enforces this).", "oneOf": [{"type": "number"}, {"type": "string", "pattern": "^\\{[a-z_]+\\}$"}]}, "CertificationScheme": {"type": "string", "pattern": "^(halal|kosher|vegetarian|vegan|organic|gluten_free|dairy_free|nut_free|fair_trade|non_gmo|food_safety|x-[a-z0-9][a-z0-9.-]*)$", "description": "What is being certified. Fixed ids for the common schemes; x-<authority or namespace> for any other (RFC-0010)."}, "CertificationEvidence": {"type": "object", "required": ["kind"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "description": "Where a reader can check the certificate outside Cookwala. None of these is required by the standard; the signature is the proof the standard checks.", "properties": {"kind": {"enum": ["certificate_url", "verifiable_credential", "transparency_log", "chain_anchor", "registry_entry", "document"], "description": "certificate_url: the authority's own page or PDF. verifiable_credential: a W3C VC (JWT or JSON-LD). transparency_log: an entry in an append-only log (for example IETF SCITT). chain_anchor: a public-chain transaction that anchors the document hash. registry_entry: a Cookwala registry name. document: any file, identified by its hash."}, "url": {"$ref": "#/$defs/Uri"}, "hash": {"$ref": "#/$defs/Hash", "description": "Hash of the referenced file or statement, when the link alone could be swapped."}, "logId": {"type": "string", "maxLength": 200}, "entryId": {"type": "string", "maxLength": 200}, "chain": {"type": "string", "maxLength": 60, "description": "Chain name or CAIP-2 id for chain_anchor."}, "txId": {"type": "string", "maxLength": 200}, "note": {"$ref": "#/$defs/UntrustedText"}}}, "CertificationSubject": {"type": "object", "required": ["kind"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "description": "What the certificate is about. For a recipe or meal the hash of the exact revision is required: a later revision is not certified until someone certifies it.", "properties": {"kind": {"enum": ["ingredient", "lot", "product", "recipe", "meal", "kitchen"]}, "ref": {"type": "string", "maxLength": 300, "description": "GlobalRef of a recipe, VocabId of an ingredient, OrgId of a kitchen, or a product name."}, "hash": {"$ref": "#/$defs/Hash", "description": "Hash of the certified document (recipe revision, meal description). Required for kind recipe and meal."}, "revision": {"type": "integer", "minimum": 1}, "gtin": {"type": "string", "pattern": "^[0-9]{8,14}$"}, "lot": {"type": "string", "maxLength": 120, "description": "Batch or lot number for kind lot."}, "name": {"$ref": "#/$defs/LangMap"}}, "if": {"properties": {"kind": {"enum": ["recipe", "meal"]}}}, "then": {"required": ["hash"]}}, "CertificationAuthority": {"type": "object", "required": ["id"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "properties": {"id": {"type": "string", "maxLength": 300, "description": "did:web or https URL of the certifying body; its KeyRecords are published there (did:web document or /.well-known/cookwala.json)."}, "name": {"type": "string", "maxLength": 200}, "accreditation": {"type": "string", "maxLength": 300, "description": "Who accredits the authority, if anyone (free text; not verified by the standard)."}}}, "Certification": {"type": "object", "required": ["cookwala", "kind", "id", "scheme", "subject", "authority", "status", "issuedAt", "hash", "signature"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "description": "A signed, detached attestation that an ingredient, lot, product, recipe revision, meal or kitchen meets a scheme (halal, kosher, vegetarian, organic, ...). Issued by a certifying authority under its own key; several authorities may certify the same subject; an authority re-certifies by issuing a new document that supersedes its earlier one. Verifiers check the signature against the authority's KeyRecord, the subject hash against the document they hold, the validity window and the status (RFC-0010). Contains no personal data.", "properties": {"cookwala": {"$ref": "#/$defs/SpecVersion"}, "kind": {"const": "Certification"}, "id": {"type": "string", "maxLength": 200}, "scheme": {"$ref": "#/$defs/CertificationScheme"}, "standard": {"type": "string", "maxLength": 200, "description": "The named standard or ruleset applied, for example \"OIC/SMIIC 1:2019\", \"OU\", \"cw.ruleset.halal.v1\", \"EU 2018/848\"."}, "subject": {"$ref": "#/$defs/CertificationSubject"}, "authority": {"$ref": "#/$defs/CertificationAuthority"}, "status": {"enum": ["valid", "suspended", "revoked"]}, "issuedAt": {"$ref": "#/$defs/DateTime"}, "validFrom": {"$ref": "#/$defs/DateTime"}, "validUntil": {"$ref": "#/$defs/DateTime"}, "revokedAt": {"$ref": "#/$defs/DateTime"}, "revocationReason": {"type": "string", "maxLength": 300}, "supersedes": {"type": "string", "maxLength": 200, "description": "id of this authority's earlier certification of the same subject and scheme that this one replaces (re-certification). The newest valid document of an authority wins."}, "certificateId": {"type": "string", "maxLength": 120, "description": "The authority's own certificate number."}, "scope": {"$ref": "#/$defs/UntrustedText", "description": "What exactly is covered, for example \"the beef only\" or \"as served, not the optional yogurt\"."}, "conditions": {"$ref": "#/$defs/UntrustedText"}, "evidence": {"type": "array", "items": {"$ref": "#/$defs/CertificationEvidence"}}, "hash": {"$ref": "#/$defs/Hash"}, "signature": {"$ref": "#/$defs/Signature", "description": "The authority's signature over the hash (CORE.md section 5). kid resolves to a KeyRecord published by authority.id."}}}, "CertificationRef": {"type": "object", "required": ["id", "scheme", "authority", "hash"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "description": "A pointer to a Certification document a reader should fetch and verify; never proof by itself.", "properties": {"id": {"type": "string", "maxLength": 200}, "scheme": {"$ref": "#/$defs/CertificationScheme"}, "authority": {"type": "string", "maxLength": 300, "description": "authority.id of the certification."}, "hash": {"$ref": "#/$defs/Hash", "description": "Hash of the Certification document."}, "url": {"$ref": "#/$defs/Uri"}, "validUntil": {"$ref": "#/$defs/DateTime"}}}}}, "https://cookwala.ai/v1/schemas/conformance.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/conformance.schema.json", "title": "Cookwala conformance reports and profile vectors", "x-cookwala-status": "profile-draft", "description": "RFC-0008. A ConformanceReport is the signed record behind any claim of conformance: which class, which vectors, which tool, on what, when, checked by whom. ProfileVector is the vector format for profile suites in conformance/profiles/, so Core's ConformanceVector enum stays frozen.", "$defs": {"Version": {"type": "string", "pattern": "^0\\.1\\.[0-9]+$"}, "ConformanceReport": {"type": "object", "required": ["profile", "kind", "id", "core", "claim", "subject", "suites", "vectorsHash", "tool", "date", "status", "signature"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "description": "A claim of conformance that anyone can reproduce. A report that fails any vector of a class may not claim that class.", "properties": {"profile": {"$ref": "#/$defs/Version"}, "kind": {"const": "ConformanceReport"}, "id": {"type": "string", "pattern": "^[a-z0-9][a-z0-9._:-]{2,95}$"}, "core": {"type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$", "description": "Core version the vectors belong to."}, "claim": {"type": "string", "pattern": "^(recipe_publisher|executor|catalog|agent|verifier|humanitarian:H[0-3]|household|registry|fleet|supply)$", "description": "Core conformance class (docs/CORE.md section 1) or profile claim."}, "subject": {"type": "object", "required": ["name"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "properties": {"name": {"type": "string", "maxLength": 120, "description": "Product, device model or software name."}, "vendor": {"type": "string", "maxLength": 120}, "version": {"type": "string", "maxLength": 60, "description": "Firmware or software version."}, "capabilitiesHash": {"$ref": "common.schema.json#/$defs/Hash"}}}, "suites": {"type": "array", "minItems": 1, "items": {"type": "object", "required": ["suite", "total", "passed"], "unevaluatedProperties": false, "properties": {"suite": {"type": "string", "pattern": "^[a-z0-9_/-]+$", "description": "Vector file stem, e.g. hash, envelope, profiles/disclosure_policy."}, "total": {"type": "integer", "minimum": 0}, "passed": {"type": "integer", "minimum": 0}, "failed": {"type": "array", "items": {"type": "string"}, "description": "Ids of failed vectors."}}}}, "vectorsHash": {"$ref": "common.schema.json#/$defs/Hash", "description": "sha256 of the RFC 8785 canonical JSON of the sorted list of (suite, vector id, expected) used."}, "tool": {"type": "object", "required": ["name", "version"], "unevaluatedProperties": false, "properties": {"name": {"type": "string", "maxLength": 80}, "version": {"type": "string", "maxLength": 60}, "commit": {"type": "string", "pattern": "^[0-9a-f]{7,40}$"}}}, "date": {"type": "string", "format": "date"}, "status": {"enum": ["self_declared", "verified", "certified"], "description": "self_declared: published by the maker. verified: reproduced by a registry operator. certified: an independent certifier with hardware and safety-case checks."}, "verifier": {"type": "string", "maxLength": 120, "description": "Organization that verified or certified; required when status is not self_declared."}, "notes": {"$ref": "common.schema.json#/$defs/UntrustedText"}, "hash": {"$ref": "common.schema.json#/$defs/Hash"}, "signature": {"$ref": "common.schema.json#/$defs/Signature", "description": "Required for every status. Self-declared: the maker's key. Verified: the registry operator counter-signs. Certified: the certifier's key. Over the report's hash (CORE.md section 5)."}}, "if": {"properties": {"status": {"enum": ["verified", "certified"]}}}, "then": {"required": ["verifier"]}}, "ProfileVector": {"type": "object", "required": ["id", "kind", "description", "input", "expected"], "unevaluatedProperties": false, "description": "A test vector for a profile suite. kind is any lower-case token the runner knows (disclosure_policy, registry_name, registry_version, sms_parse, signal_policy, signature...).", "properties": {"id": {"type": "string", "pattern": "^[a-z0-9][a-z0-9._-]{1,95}$"}, "kind": {"type": "string", "pattern": "^[a-z][a-z0-9_]{1,40}$"}, "profile": {"type": "string", "maxLength": 40, "description": "Profile the vector belongs to, e.g. household, registry, humanitarian."}, "rfc": {"type": "string", "pattern": "^[0-9]{4}$"}, "description": {"type": "string"}, "input": {}, "expected": {}}}}}, "https://cookwala.ai/v1/schemas/core.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/core.schema.json", "title": "Cookwala Core", "x-cookwala-status": "core", "description": "The small, stable core of Cookwala (docs/CORE.md): how a device is asked to cook a recipe, how it reports status, how it logs what happened, the safety limits it enforces locally whatever anyone says, recalls of unsafe recipes or extensions, anonymous incident reports, and conformance test vectors. Everything outside this file, recipe.schema.json, capabilities.schema.json and common.schema.json is an optional profile.", "$defs": {"CoreVersion": {"type": "string", "pattern": "^0\\.2\\.[0-9]+$", "description": "Core version. A reader accepts any patch of its minor version, rejects other minors with error unsupported_version, and ignores x- fields it does not know."}, "Id": {"type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{2,127}$"}, "ExecuteRequest": {"type": "object", "required": ["core", "kind", "id", "recipe", "recipeHash", "requestedBy", "idempotencyKey"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "description": "Ask a device or hub to cook a recipe. The executor refuses (state refused) rather than guessing when it cannot meet a step's envelope, sensor ladder or safety limits.", "properties": {"core": {"$ref": "#/$defs/CoreVersion"}, "kind": {"const": "ExecuteRequest"}, "id": {"$ref": "#/$defs/Id"}, "recipe": {"$ref": "common.schema.json#/$defs/GlobalRef"}, "recipeHash": {"$ref": "common.schema.json#/$defs/Hash", "description": "The executor must cook exactly this revision; a mismatch is refused."}, "servings": {"type": "number", "exclusiveMinimum": 0}, "serveBy": {"$ref": "common.schema.json#/$defs/DateTime"}, "requestedBy": {"type": "string", "description": "Id of the human, or of the agent acting under mandate."}, "mandate": {"$ref": "common.schema.json#/$defs/AgentMandate", "description": "Required when an AI agent sends the request; must include the start_cooking scope."}, "allergenBlocks": {"type": "array", "items": {"type": "string"}, "description": "Allergens that must not be present for these diners. Matched against the recipe and the inventory; any match refuses the request."}, "operatingMode": {"type": "string", "description": "Id of an operating mode (profile.schema.json), e.g. energy saver."}, "idempotencyKey": {"type": "string", "minLength": 8, "maxLength": 128, "description": "Repeating a request with the same key returns the original execution."}}}, "RefusalReason": {"enum": ["unsupported_version", "recipe_hash_mismatch", "recipe_recalled", "missing_equipment", "missing_capability", "missing_sensor_no_fallback", "envelope_out_of_range", "safety_limit", "allergen_block", "not_authorized", "mandate_scope", "needs_human_present", "busy"]}, "ExecutionState": {"enum": ["accepted", "refused", "preparing", "running", "paused", "needs_human", "stopping", "stopped", "completed", "failed"], "description": "Legal transitions: accepted→preparing|refused|stopped; preparing→running|needs_human|stopping|failed; running→paused|needs_human|stopping|completed|failed; paused→running|stopping; needs_human→running|stopping|failed; stopping→stopped. refused, stopped, completed and failed are final."}, "ExecutionStatus": {"type": "object", "required": ["core", "kind", "id", "request", "state", "seq", "updatedAt"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "properties": {"core": {"$ref": "#/$defs/CoreVersion"}, "kind": {"const": "ExecutionStatus"}, "id": {"$ref": "#/$defs/Id"}, "request": {"$ref": "#/$defs/Id"}, "state": {"$ref": "#/$defs/ExecutionState"}, "seq": {"type": "integer", "minimum": 0, "description": "Increments on every change; events carry the same sequence."}, "updatedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "step": {"type": "object", "unevaluatedProperties": false, "properties": {"node": {"type": "string"}, "op": {"$ref": "common.schema.json#/$defs/VocabId"}, "startedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "progress": {"type": "number", "minimum": 0, "maximum": 1}, "verifiedBy": {"$ref": "#/$defs/VerifiedBy"}, "readings": {"type": "array", "items": {"$ref": "#/$defs/Reading"}}}}, "eta": {"$ref": "common.schema.json#/$defs/DateTime"}, "refusal": {"type": "object", "required": ["reason"], "unevaluatedProperties": false, "properties": {"reason": {"$ref": "#/$defs/RefusalReason"}, "node": {"type": "string"}, "detail": {"type": "string", "maxLength": 500}}}, "humanNeeded": {"type": "object", "unevaluatedProperties": false, "properties": {"why": {"type": "string", "maxLength": 300}, "byWhen": {"$ref": "common.schema.json#/$defs/DateTime"}}}}}, "StopRequest": {"type": "object", "required": ["core", "kind", "execution", "requestedBy"], "unevaluatedProperties": false, "description": "Ask an executor to stop safely. Stopping never needs authorization beyond reaching the executor; a local stop on the device always works without the network.", "properties": {"core": {"$ref": "#/$defs/CoreVersion"}, "kind": {"const": "StopRequest"}, "execution": {"$ref": "#/$defs/Id"}, "requestedBy": {"type": "string"}, "reason": {"type": "string", "maxLength": 300}}}, "VerifiedBy": {"enum": ["sensor", "model", "time", "human"], "description": "Which rung of the operation's sensor ladder confirmed the step."}, "Reading": {"type": "object", "required": ["sensor", "value", "unit"], "unevaluatedProperties": false, "properties": {"sensor": {"$ref": "common.schema.json#/$defs/VocabId"}, "value": {"type": "number"}, "unit": {"$ref": "common.schema.json#/$defs/Unit"}, "at": {"$ref": "common.schema.json#/$defs/DateTime"}, "estimated": {"type": "boolean", "description": "true when the value comes from a model, not a sensor."}}}, "ExecutionLog": {"type": "object", "required": ["core", "kind", "id", "recipe", "recipeHash", "device", "startedAt", "outcome", "steps", "consent", "privacy"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "description": "What happened when a recipe was cooked. The record behind the cooking benchmark and the open dataset. Contains no personal data; shared beyond the device only with the consent given in consent.dataset.", "properties": {"core": {"$ref": "#/$defs/CoreVersion"}, "kind": {"const": "ExecutionLog"}, "id": {"$ref": "#/$defs/Id"}, "recipe": {"$ref": "common.schema.json#/$defs/GlobalRef"}, "recipeHash": {"$ref": "common.schema.json#/$defs/Hash"}, "device": {"type": "object", "required": ["vendor", "model"], "unevaluatedProperties": false, "properties": {"vendor": {"type": "string"}, "model": {"type": "string"}, "firmware": {"type": "string"}, "capabilitiesHash": {"$ref": "common.schema.json#/$defs/Hash"}, "safetyLimits": {"type": "string", "description": "Id@version of the SafetyLimits pack in force."}}}, "startedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "endedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "outcome": {"enum": ["served", "partial", "aborted_safe", "refused", "failed"]}, "servings": {"type": "number", "minimum": 0}, "steps": {"type": "array", "items": {"type": "object", "required": ["node", "op", "verifiedBy", "envelopeOk"], "unevaluatedProperties": false, "properties": {"node": {"type": "string"}, "op": {"$ref": "common.schema.json#/$defs/VocabId"}, "startedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "endedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "verifiedBy": {"$ref": "#/$defs/VerifiedBy"}, "envelopeOk": {"type": "boolean", "description": "The medium stayed inside the op envelope (and the recipe target, if narrower) for the whole step."}, "summary": {"type": "array", "items": {"type": "object", "required": ["sensor", "unit"], "unevaluatedProperties": false, "properties": {"sensor": {"$ref": "common.schema.json#/$defs/VocabId"}, "unit": {"$ref": "common.schema.json#/$defs/Unit"}, "min": {"type": "number"}, "max": {"type": "number"}, "end": {"type": "number"}, "estimated": {"type": "boolean"}}}}, "deviation": {"type": "object", "required": ["kind"], "unevaluatedProperties": false, "properties": {"kind": {"enum": ["substitution", "extended_time", "shortened_time", "temperature_excursion", "skipped_optional", "human_took_over", "other"]}, "detail": {"type": "string", "maxLength": 300}}}}}}, "safetyEvents": {"type": "array", "items": {"type": "object", "required": ["at", "limit", "action"], "unevaluatedProperties": false, "properties": {"at": {"$ref": "common.schema.json#/$defs/DateTime"}, "limit": {"type": "string", "description": "SafetyLimit id that fired."}, "action": {"$ref": "#/$defs/LimitAction"}, "node": {"type": "string"}}}}, "humanInterventions": {"type": "array", "items": {"type": "object", "required": ["kind"], "unevaluatedProperties": false, "properties": {"at": {"$ref": "common.schema.json#/$defs/DateTime"}, "kind": {"enum": ["confirm", "assist", "take_over", "stop", "refill", "other"]}, "minutes": {"type": "number", "minimum": 0}}}}, "energyKwh": {"type": "number", "minimum": 0}, "wasteG": {"type": "number", "minimum": 0}, "rating": {"type": "object", "unevaluatedProperties": false, "properties": {"score": {"type": "integer", "minimum": 1, "maximum": 5}, "comment": {"$ref": "common.schema.json#/$defs/UntrustedText"}}}, "consent": {"type": "object", "required": ["dataset"], "unevaluatedProperties": false, "description": "Opt-in only. Default none: the log stays on the device or hub.", "properties": {"dataset": {"enum": ["none", "research_only", "open"]}, "grantedBy": {"type": "string", "description": "Opaque id of the household account; never a name."}, "grantedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "withdrawable": {"const": true}}}, "privacy": {"type": "object", "required": ["personalData"], "unevaluatedProperties": false, "properties": {"personalData": {"const": "none"}, "timePrecision": {"enum": ["minute", "hour", "day"], "description": "Times may be coarsened before sharing; day is the default for open datasets."}}}, "signature": {"$ref": "common.schema.json#/$defs/Signature"}}}, "LimitAction": {"enum": ["refuse_start", "cut_heat", "stop_motion", "stop_all", "ask_human", "alert"]}, "SafetyLimit": {"type": "object", "required": ["id", "kind", "action", "source"], "unevaluatedProperties": false, "properties": {"id": {"type": "string", "pattern": "^[a-z0-9._-]+$"}, "kind": {"enum": ["max_temp", "min_core_temp", "time_temp", "allergen_block", "unattended", "pressure", "smoke_or_fire", "stop", "untrusted_input"]}, "appliesTo": {"type": "object", "unevaluatedProperties": false, "properties": {"medium": {"type": "string"}, "ops": {"type": "array", "items": {"$ref": "common.schema.json#/$defs/VocabId"}}, "foodClass": {"type": "string"}}}, "min": {"type": "number"}, "max": {"type": "number"}, "unit": {"enum": ["degC", "kPa", "s", "min", "h"]}, "holdFor": {"$ref": "common.schema.json#/$defs/Duration"}, "action": {"$ref": "#/$defs/LimitAction"}, "message": {"type": "string", "maxLength": 200}, "source": {"type": "string", "maxLength": 200}}}, "SafetyLimits": {"type": "object", "required": ["core", "kind", "id", "version", "limits", "disclaimer"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "description": "Limits an executor enforces on the device itself. No recipe, agent, remote message, extension or operating mode can raise or disable them; only the device maker (and, more strictly, local law) can change them. A stricter limit always wins over a looser one.", "properties": {"core": {"$ref": "#/$defs/CoreVersion"}, "kind": {"const": "SafetyLimits"}, "id": {"type": "string"}, "version": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "status": {"enum": ["draft", "reviewed", "adopted"]}, "reviewedBy": {"type": "array", "items": {"type": "string"}}, "limits": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/SafetyLimit"}}, "disclaimer": {"type": "string"}}}, "Recall": {"type": "object", "required": ["core", "kind", "id", "issuedAt", "issuer", "targets", "severity", "reason", "action", "signature"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "description": "Withdraws a recipe revision, an extension or a rule pack. Catalogs publish recalls in a feed (GET /v1/recalls); executors check the feed when online and refuse recalled revisions within the window the action names.", "properties": {"core": {"$ref": "#/$defs/CoreVersion"}, "kind": {"const": "Recall"}, "id": {"$ref": "#/$defs/Id"}, "issuedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "issuer": {"type": "string", "description": "Catalog or authority issuing the recall; its key must be trusted by the executor."}, "targets": {"type": "array", "minItems": 1, "items": {"type": "object", "required": ["ref"], "unevaluatedProperties": false, "properties": {"ref": {"$ref": "common.schema.json#/$defs/GlobalRef"}, "hash": {"$ref": "common.schema.json#/$defs/Hash"}, "allRevisions": {"type": "boolean"}}}}, "severity": {"$ref": "common.schema.json#/$defs/Severity"}, "reason": {"enum": ["food_safety", "allergen", "device_safety", "security", "legal", "quality"]}, "action": {"enum": ["block", "block_and_stop_running", "warn"]}, "replacement": {"$ref": "common.schema.json#/$defs/GlobalRef"}, "detail": {"type": "string", "maxLength": 1000}, "signature": {"$ref": "common.schema.json#/$defs/Signature"}}}, "IncidentReport": {"type": "object", "required": ["core", "kind", "id", "date", "category", "severity", "description"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "description": "Anonymous near-miss or incident report, modelled on aviation's confidential reporting. No names, addresses, account ids or exact times; dates only.", "properties": {"core": {"$ref": "#/$defs/CoreVersion"}, "kind": {"const": "IncidentReport"}, "id": {"$ref": "#/$defs/Id"}, "date": {"type": "string", "format": "date"}, "category": {"type": "string", "description": "Id from vocab/incidents.json."}, "severity": {"$ref": "common.schema.json#/$defs/Severity"}, "outcome": {"enum": ["near_miss", "minor_injury", "injury", "property_damage", "illness_suspected", "none"]}, "op": {"$ref": "common.schema.json#/$defs/VocabId"}, "deviceModel": {"type": "string"}, "recipe": {"$ref": "common.schema.json#/$defs/GlobalRef"}, "safetyLimitsFired": {"type": "array", "items": {"type": "string"}}, "description": {"$ref": "common.schema.json#/$defs/UntrustedText"}, "contributingFactors": {"type": "array", "items": {"enum": ["sensor_missing", "sensor_fault", "envelope_unclear", "recipe_error", "agent_instruction", "human_override", "network", "power", "other"]}}}}, "ConformanceVector": {"type": "object", "required": ["id", "kind", "description", "input", "expected"], "unevaluatedProperties": false, "properties": {"id": {"type": "string"}, "kind": {"enum": ["hash", "signature", "disclosure", "envelope", "units", "execution_transition", "mission_transition", "ledger", "dryrun"]}, "description": {"type": "string"}, "input": {}, "expected": {}}}}}, "https://cookwala.ai/v1/schemas/event.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/event.schema.json", "title": "Cookwala Event", "x-cookwala-status": "core", "description": "Every message on the kitchen event bus (MQTT, WebSocket, SSE, webhooks) is a CloudEvents 1.0 JSON event with a type from the cookwala catalog below. Safety events have priority and must be delivered to every participant.", "type": "object", "required": ["specversion", "id", "source", "type", "time", "data"], "properties": {"specversion": {"const": "1.0"}, "id": {"type": "string"}, "source": {"type": "string", "description": "URI of the emitter, e.g. cookwala://kitchen-123/robot/neo-1."}, "type": {"$ref": "#/$defs/EventType"}, "subject": {"type": "string", "description": "Session/task/device id the event is about."}, "time": {"$ref": "common.schema.json#/$defs/DateTime"}, "datacontenttype": {"const": "application/json"}, "dataschema": {"type": "string"}, "cookwalapriority": {"enum": ["safety", "high", "normal", "low"], "description": "CloudEvents extension attribute."}, "cookwalakitchen": {"type": "string", "description": "CloudEvents extension attribute: kitchen id."}, "cookwalasession": {"type": "string"}, "cookwalasig": {"type": "string", "description": "Optional detached signature for safety-critical events."}, "data": {"type": "object"}, "cookwalaseq": {"type": "integer", "minimum": 0, "description": "CloudEvents extension: sequence number per subject (execution, session or Mission). Consumers use it to order events and detect gaps; id is the deduplication key (delivery is at least once)."}, "cookwalalatency": {"enum": ["local_safety", "realtime", "interactive", "background"], "description": "CloudEvents extension: latency class. local_safety events only REPORT what a device already did locally; no safety function may depend on receiving them."}}, "allOf": [{"if": {"properties": {"type": {"pattern": "^cookwala\\.safety\\."}}}, "then": {"properties": {"cookwalapriority": {"const": "safety"}, "data": {"$ref": "#/$defs/SafetyData"}}, "required": ["cookwalapriority"]}}, {"if": {"properties": {"type": {"pattern": "^cookwala\\.task\\."}}}, "then": {"properties": {"data": {"$ref": "#/$defs/TaskData"}}}}, {"if": {"properties": {"type": {"pattern": "^cookwala\\.telemetry\\."}}}, "then": {"properties": {"data": {"$ref": "#/$defs/TelemetryData"}}}}, {"if": {"properties": {"type": {"pattern": "^cookwala\\.inventory\\."}}}, "then": {"properties": {"data": {"$ref": "#/$defs/InventoryData"}}}}, {"if": {"properties": {"type": {"pattern": "^cookwala\\.notify\\."}}}, "then": {"properties": {"data": {"$ref": "#/$defs/NotifyData"}}}}, {"if": {"properties": {"type": {"pattern": "^cookwala\\.team\\."}}}, "then": {"properties": {"data": {"$ref": "#/$defs/TeamData"}}}}], "$defs": {"EventType": {"anyOf": [{"enum": ["cookwala.session.created", "cookwala.session.planned", "cookwala.session.state_changed", "cookwala.session.completed", "cookwala.session.aborted", "cookwala.policy.evaluated", "cookwala.policy.acknowledged", "cookwala.task.assigned", "cookwala.task.started", "cookwala.task.progress", "cookwala.task.condition_met", "cookwala.task.input_required", "cookwala.task.completed", "cookwala.task.failed", "cookwala.task.reassigned", "cookwala.lease.requested", "cookwala.lease.granted", "cookwala.lease.released", "cookwala.lease.revoked", "cookwala.handoff.proposed", "cookwala.handoff.ready", "cookwala.handoff.acknowledged", "cookwala.handoff.completed", "cookwala.handoff.refused", "cookwala.ccp.recorded", "cookwala.ccp.failed", "cookwala.telemetry.reading", "cookwala.device.online", "cookwala.device.offline", "cookwala.device.fault", "cookwala.device.capabilities_changed", "cookwala.inventory.changed", "cookwala.inventory.low", "cookwala.inventory.expiring", "cookwala.inventory.reserved", "cookwala.order.intent_created", "cookwala.order.approval_required", "cookwala.order.placed", "cookwala.order.status", "cookwala.order.delivered", "cookwala.notify.request", "cookwala.notify.delivered", "cookwala.notify.acknowledged", "cookwala.human.presence", "cookwala.human.confirmation", "cookwala.human.override", "cookwala.safety.estop", "cookwala.safety.smoke", "cookwala.safety.co", "cookwala.safety.gas_leak", "cookwala.safety.fire", "cookwala.safety.overtemp", "cookwala.safety.boilover", "cookwala.safety.spill", "cookwala.safety.intrusion_zone", "cookwala.safety.child_or_pet_in_zone", "cookwala.safety.unattended_heat", "cookwala.safety.water_leak", "cookwala.safety.power_loss", "cookwala.safety.cleared", "cookwala.team.cfp", "cookwala.team.bid", "cookwala.team.award", "cookwala.team.decline", "cookwala.team.plan", "cookwala.team.replan", "cookwala.advice.requested", "cookwala.advice.answered", "cookwala.advice.applied", "cookwala.mode.changed", "cookwala.device.battery", "cookwala.market.quote_requested", "cookwala.market.quote", "cookwala.market.offer_changed", "cookwala.flow.started", "cookwala.flow.step", "cookwala.flow.completed", "cookwala.flow.failed", "cookwala.relief.need_opened", "cookwala.relief.need_updated", "cookwala.relief.pledge_offered", "cookwala.relief.allocated", "cookwala.relief.dispatched", "cookwala.relief.delivered", "cookwala.relief.impact", "cookwala.relief.surplus_available", "cookwala.mission.assessment", "cookwala.mission.conflict", "cookwala.mission.reconciled", "cookwala.mission.budget_threshold", "cookwala.mission.degradation", "cookwala.mission.adaptation", "cookwala.mission.decision", "cookwala.mission.closed", "cookwala.device.heartbeat", "cookwala.execution.accepted", "cookwala.execution.refused", "cookwala.execution.state_changed", "cookwala.execution.step", "cookwala.execution.completed", "cookwala.safety.limit_fired", "cookwala.recall.published"]}, {"type": "string", "pattern": "^x-[a-z0-9-]+\\.[a-z0-9_.]+$", "description": "Extension event types."}]}, "SafetyData": {"type": "object", "required": ["level", "action"], "properties": {"level": {"enum": ["warning", "alarm", "emergency"]}, "action": {"enum": ["none", "pause_all", "heat_off_all", "abort_session", "evacuate"], "description": "Required response from every participant."}, "zone": {"type": "string"}, "reading": {"type": "object"}, "detectedBy": {"$ref": "common.schema.json#/$defs/Actor"}, "expected": {"type": "boolean", "description": "True when the hub matched it to recipe safety.environment.smokeExpected; never suppresses alarms, only adds context for humans."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "TaskData": {"type": "object", "required": ["taskId", "state"], "properties": {"taskId": {"type": "string"}, "nodeId": {"type": "string"}, "recipeId": {"type": "string"}, "state": {"$ref": "session.schema.json#/$defs/TaskState"}, "assignee": {"$ref": "common.schema.json#/$defs/Actor"}, "progress": {"type": "number"}, "message": {"$ref": "common.schema.json#/$defs/LangMap"}, "reason": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "TelemetryData": {"type": "object", "required": ["readings"], "properties": {"taskId": {"type": "string"}, "readings": {"type": "array", "items": {"type": "object", "required": ["sensor", "value"], "properties": {"sensor": {"type": "string"}, "value": {}, "unit": {"type": "string"}, "target": {"type": "string"}, "confidence": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "InventoryData": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "inventory.schema.json#/$defs/Item"}}, "storage": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "NotifyData": {"type": "object", "required": ["audience", "urgency", "message"], "properties": {"audience": {"type": "array", "items": {"type": "string", "description": "Actor ids or roles: human:primary, role:household, role:emergency_contact."}}, "urgency": {"enum": ["info", "action_needed", "time_critical", "emergency"]}, "message": {"$ref": "common.schema.json#/$defs/LangMap"}, "actions": {"type": "array", "items": {"type": "object", "properties": {"id": {"type": "string"}, "label": {"$ref": "common.schema.json#/$defs/LangMap"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "channels": {"type": "array", "items": {"type": "string"}}, "expiresAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "relatesTo": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "TeamData": {"type": "object", "description": "Contract-net style teaming: a robot (or the hub) issues a call for proposals for tasks; helpers bid with capability, ETA, battery and cost; the hub awards.", "properties": {"cfpId": {"type": "string"}, "sessionId": {"type": "string"}, "tasks": {"type": "array", "items": {"type": "string"}}, "from": {"type": "string"}, "bid": {"type": "object", "properties": {"actorId": {"type": "string"}, "canDo": {"type": "array", "items": {"type": "string"}}, "etaS": {"type": "number"}, "durationS": {"type": "number"}, "batteryAfterPct": {"type": "number"}, "energyWh": {"type": "number"}, "confidence": {"type": "number"}, "constraints": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "award": {"type": "object", "properties": {"actorId": {"type": "string"}, "tasks": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "deadline": {"$ref": "common.schema.json#/$defs/DateTime"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "https://cookwala.ai/v1/schemas/extension.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/extension.schema.json", "title": "Cookwala Extension Manifest", "x-cookwala-status": "experimental", "description": "Declares an extension anyone can build and host anywhere: new fields (x- namespace), vocabularies, knowledge packs, policy packs, filters, rankers, advisors, planners' cost terms, AI models, agents, tools, device adapters, flows, UI cards, or marketplace connectors. Hubs and indexes load extensions the operator trusts. Core safety checks always run after every extension and cannot be disabled or loosened by one.", "type": "object", "required": ["cookwala", "id", "name", "version", "publisher", "provides", "permissions"], "properties": {"cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "id": {"type": "string", "pattern": "^x-[a-z0-9-]+(\\.[a-z0-9-]+)*$", "description": "Namespace owned by the publisher, e.g. x-acme or x-acme.halal-plus. Fields it adds are prefixed with this id."}, "name": {"type": "string"}, "version": {"type": "string"}, "description": {"$ref": "common.schema.json#/$defs/LangMap"}, "publisher": {"type": "object", "required": ["name"], "properties": {"name": {"type": "string"}, "url": {"type": "string"}, "contact": {"type": "string"}, "did": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "license": {"type": "string"}, "compat": {"type": "object", "properties": {"cookwala": {"type": "string", "description": "SemVer range, e.g. ^0.1 || ^1."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "provides": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/Contribution"}}, "permissions": {"type": "object", "description": "What data and actions the extension needs. The operator grants or denies each; sensitive data is never granted by default.", "properties": {"read": {"type": "array", "items": {"enum": ["recipes", "catalog", "inventory", "session", "telemetry", "profiles.client", "profiles.client.sensitive", "profiles.kitchen", "profiles.cookware", "profiles.robot", "orders", "events", "mode"]}}, "write": {"type": "array", "items": {"enum": ["advice", "inventory", "orders.intent", "notify", "session.patch_proposal", "catalog.private", "events.custom"]}}, "network": {"type": "array", "items": {"type": "string"}, "description": "Hosts the extension may call (empty = offline only)."}, "actuate": {"type": "boolean", "const": false, "description": "Extensions never actuate devices directly; they propose, the hub decides."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "runtime": {"type": "object", "description": "How it runs. Pure data contributions need no runtime.", "properties": {"kind": {"enum": ["data", "wasm", "http", "mcp", "a2a", "container"]}, "entry": {"type": "string", "description": "WASM component URL/path, HTTP base URL, MCP endpoint, AgentCard URL or OCI image."}, "timeoutMs": {"type": "integer", "minimum": 1}, "offline": {"type": "boolean"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "pricing": {"$ref": "market.schema.json#/$defs/Pricing"}, "integrity": {"type": "object", "properties": {"hash": {"$ref": "common.schema.json#/$defs/Hash"}, "signature": {"$ref": "common.schema.json#/$defs/Signature"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "meta": {"$ref": "common.schema.json#/$defs/Meta"}}, "patternProperties": {"^x-": {}}, "$defs": {"Hook": {"enum": ["reasoner.parse", "reasoner.retrieve", "reasoner.filter", "reasoner.generate", "reasoner.verify", "reasoner.rank", "reasoner.explain", "planner.cost_terms", "planner.constraints", "planner.post_plan", "policy.evaluate", "session.before_start", "session.on_event", "session.after_complete", "catalog.ingest", "catalog.enrich", "catalog.search_filter", "catalog.search_rank", "inventory.ingest", "order.route", "notify.deliver", "sense.classify"]}, "Contribution": {"type": "object", "required": ["type"], "properties": {"type": {"enum": ["fields", "vocabulary", "knowledge", "policy_pack", "playbooks", "recipes", "filter", "ranker", "advisor", "intent", "planner_terms", "model", "sensor_classifier", "agent", "tool", "adapter", "flow", "ui_card", "market_connector", "profile_kind", "mode_preset"]}, "id": {"type": "string"}, "hooks": {"type": "array", "items": {"$ref": "#/$defs/Hook"}}, "schema": {"type": "string", "description": "For 'fields': JSON Schema (URL) of the x- fields and which documents they attach to."}, "attachesTo": {"type": "array", "items": {"enum": ["recipe", "node", "ingredient", "capabilities", "policy", "session", "inventory", "order", "profile", "advice_request", "advice_response", "offer", "event"]}}, "intent": {"type": "string", "description": "For 'intent': new advisor intent name, e.g. x-acme.wine_free_pairing; request/response schemas below."}, "requestSchema": {"type": "string"}, "responseSchema": {"type": "string"}, "model": {"type": "object", "description": "For 'model' / 'sensor_classifier': bring-your-own AI.", "properties": {"roles": {"type": "array", "items": {"enum": ["parse", "propose", "explain", "translate", "vision_cue", "embed", "rerank"]}}, "cues": {"type": "array", "items": {"type": "string"}, "description": "cw.sense.* vision cues it can classify."}, "accuracy": {"type": "object", "additionalProperties": {"type": "number"}, "description": "Declared accuracy per cue/task on the Cookwala benchmark."}, "local": {"type": "boolean"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "flow": {"type": "string", "description": "URL of a flow document (flow.schema.json)."}, "data": {"type": "string", "description": "URL of the contributed data (vocabulary, knowledge pack, policy pack, recipes catalog)."}, "priority": {"type": "integer", "description": "Order among extensions at the same hook (lower first)."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "unevaluatedProperties": false}, "https://cookwala.ai/v1/schemas/fleet.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/fleet.schema.json", "title": "Cookwala Kitchens and Production Runs (fleets)", "x-cookwala-status": "experimental", "description": "RFC-0005. A Kitchen is an organization's kitchen (restaurant, community, school, disaster, care home, central production or robot kitchen) with stations and devices. A ProductionRun is many batches of recipes for a serve window, with assignments per step to a device, a person or either, the critical control points to record, and the Core execution logs it produced. A run that serves a program emits a Humanitarian Distribution. Staff appear as counts by role, never names. Fleet dispatch (Open-RMF, vendor fleet managers) is outside this profile.", "$defs": {"Version": {"type": "string", "pattern": "^0\\.1\\.[0-9]+$"}, "Id": {"type": "string", "pattern": "^[a-z0-9][a-z0-9._:-]{2,95}$"}, "OrgId": {"type": "string", "pattern": "^(did:web:[a-z0-9.-]+|gln:[0-9]{13}|org:[a-z0-9-]+\\.[a-z0-9.-]+)$"}, "Station": {"type": "object", "required": ["id", "kind"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "properties": {"id": {"$ref": "#/$defs/Id"}, "kind": {"enum": ["prep", "hob", "oven", "fryer", "grill", "steam", "kettle", "robot_cell", "plating", "packing", "hot_hold", "cooling", "cold_store", "wash"]}, "heatSources": {"type": "array", "items": {"enum": ["gas", "electric", "induction", "steam", "charcoal", "solar", "none"]}}, "devices": {"type": "array", "items": {"type": "string", "maxLength": 200}, "description": "Capability document references (URL or id) of robots and appliances at this station."}, "capacityPerHour": {"type": "integer", "minimum": 0, "description": "Portions per hour this station can process."}, "sensors": {"type": "array", "items": {"$ref": "common.schema.json#/$defs/VocabId"}}}}, "Kitchen": {"type": "object", "required": ["profile", "kind", "id", "organization", "type", "stations", "capacityMealsPerHour", "rulePacks"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "properties": {"profile": {"$ref": "#/$defs/Version"}, "kind": {"const": "Kitchen"}, "id": {"$ref": "#/$defs/Id"}, "organization": {"$ref": "#/$defs/OrgId"}, "name": {"type": "string", "maxLength": 120}, "type": {"enum": ["restaurant", "community", "school", "disaster", "care_home", "central_production", "robot", "caterer", "food_factory"]}, "site": {"type": "object", "required": ["country"], "unevaluatedProperties": false, "properties": {"country": {"type": "string", "pattern": "^[A-Z]{2}$"}, "admin1": {"type": "string", "maxLength": 80}, "pcode": {"type": "string", "maxLength": 20}, "altitudeM": {"type": "number"}}}, "stations": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/Station"}}, "capacityMealsPerHour": {"type": "integer", "minimum": 0}, "hotHold": {"type": "object", "unevaluatedProperties": false, "properties": {"units": {"type": "integer", "minimum": 0}, "minTempC": {"type": "number"}}}, "cooling": {"type": "object", "unevaluatedProperties": false, "properties": {"blastChiller": {"type": "boolean"}, "iceBath": {"type": "boolean"}, "coldStoreKg": {"type": "number", "minimum": 0}}}, "rulePacks": {"type": "array", "items": {"type": "string", "pattern": "^[a-z0-9._-]+@[0-9]+\\.[0-9]+\\.[0-9]+$"}, "description": "Humanitarian rule packs in force, id@version."}, "safetyLimits": {"type": "string", "description": "SafetyLimits pack id@version enforced by the kitchen's devices."}, "staff": {"type": "array", "items": {"type": "object", "required": ["role", "count"], "unevaluatedProperties": false, "properties": {"role": {"enum": ["head_cook", "cook", "assistant", "volunteer", "robot_technician", "food_safety_lead", "server", "driver"]}, "count": {"type": "integer", "minimum": 0}}}, "description": "Counts by role, never names."}, "operatingHours": {"type": "array", "items": {"type": "object", "required": ["days", "from", "to"], "unevaluatedProperties": false, "properties": {"days": {"type": "string", "maxLength": 40}, "from": {"type": "string", "pattern": "^[0-2][0-9]:[0-5][0-9]$"}, "to": {"type": "string", "pattern": "^[0-2][0-9]:[0-5][0-9]$"}}}}, "meta": {"$ref": "common.schema.json#/$defs/Meta"}}}, "Assignment": {"type": "object", "required": ["recipe", "node", "station", "actor"], "unevaluatedProperties": false, "properties": {"recipe": {"$ref": "common.schema.json#/$defs/GlobalRef"}, "node": {"type": "string", "maxLength": 40, "description": "Recipe node id."}, "station": {"$ref": "#/$defs/Id"}, "actor": {"enum": ["device", "person", "either"]}, "device": {"type": "string", "maxLength": 200}, "role": {"enum": ["head_cook", "cook", "assistant", "volunteer", "robot_technician", "food_safety_lead", "server"]}, "plannedStart": {"$ref": "common.schema.json#/$defs/DateTime"}, "plannedEnd": {"$ref": "common.schema.json#/$defs/DateTime"}}}, "CcpRecord": {"type": "object", "required": ["id", "kind", "limit", "unit"], "unevaluatedProperties": false, "properties": {"id": {"$ref": "#/$defs/Id"}, "kind": {"enum": ["cook_core_temp", "hot_hold_temp", "cooling_stage_1", "cooling_stage_2", "reheat_core_temp", "chilled_storage_temp", "allergen_segregation"]}, "recipe": {"$ref": "common.schema.json#/$defs/GlobalRef"}, "batch": {"type": "integer", "minimum": 1}, "limit": {"type": "number"}, "unit": {"enum": ["degC", "min", "h"]}, "observed": {"type": "number"}, "at": {"$ref": "common.schema.json#/$defs/DateTime"}, "method": {"enum": ["probe", "device_log", "logger", "visual", "not_measured"]}, "pass": {"type": "boolean"}, "action": {"type": "string", "maxLength": 200, "description": "Corrective action when the record fails."}}}, "ProductionRun": {"type": "object", "required": ["profile", "kind", "id", "kitchen", "serveWindow", "recipes", "state"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "properties": {"profile": {"$ref": "#/$defs/Version"}, "kind": {"const": "ProductionRun"}, "id": {"$ref": "#/$defs/Id"}, "kitchen": {"$ref": "#/$defs/Id"}, "program": {"type": "string", "maxLength": 96, "description": "Humanitarian Program or Distribution id when the run serves a program."}, "purpose": {"enum": ["service", "school_meals", "community_meals", "disaster_response", "care_home_meals", "event", "donation", "retail"]}, "serveWindow": {"type": "object", "required": ["from", "to"], "unevaluatedProperties": false, "properties": {"from": {"$ref": "common.schema.json#/$defs/DateTime"}, "to": {"$ref": "common.schema.json#/$defs/DateTime"}}}, "recipes": {"type": "array", "minItems": 1, "items": {"type": "object", "required": ["recipe", "recipeHash", "batches", "servingsPerBatch"], "unevaluatedProperties": false, "properties": {"recipe": {"$ref": "common.schema.json#/$defs/GlobalRef"}, "recipeHash": {"$ref": "common.schema.json#/$defs/Hash"}, "batches": {"type": "integer", "minimum": 1}, "servingsPerBatch": {"type": "number", "exclusiveMinimum": 0}, "scale": {"type": "number", "exclusiveMinimum": 0, "description": "Scale factor per batch relative to the recipe yield; must respect yield.scaling."}}}}, "dietRules": {"type": "array", "items": {"type": "string", "maxLength": 40}, "description": "Diet rules in force for this run (e.g. halal, vegetarian)."}, "allergenBlocks": {"type": "array", "items": {"type": "string", "maxLength": 40}}, "assignments": {"type": "array", "items": {"$ref": "#/$defs/Assignment"}}, "ccps": {"type": "array", "items": {"$ref": "#/$defs/CcpRecord"}}, "executions": {"type": "array", "items": {"type": "object", "required": ["device", "executionId"], "unevaluatedProperties": false, "properties": {"device": {"type": "string", "maxLength": 200}, "executionId": {"type": "string", "maxLength": 96}, "logHash": {"$ref": "common.schema.json#/$defs/Hash"}, "outcome": {"enum": ["served", "partial", "aborted_safe", "refused", "failed"]}}}, "description": "Core executions (ExecutionLog) that device steps produced."}, "state": {"enum": ["planned", "in_progress", "completed", "aborted"]}, "outcome": {"type": "object", "unevaluatedProperties": false, "properties": {"mealsProduced": {"type": "integer", "minimum": 0}, "mealsServed": {"type": "integer", "minimum": 0}, "kgWaste": {"type": "number", "minimum": 0}, "kgRescuedUsed": {"type": "number", "minimum": 0}, "ccpFailures": {"type": "integer", "minimum": 0}, "safetyIncidents": {"type": "integer", "minimum": 0}, "findings": {"type": "array", "items": {"type": "string", "pattern": "^[a-z0-9._-]+$"}}, "distribution": {"type": "string", "maxLength": 96, "description": "Humanitarian Distribution id emitted for this run."}, "energyKwh": {"type": "number", "minimum": 0}, "gasM3": {"type": "number", "minimum": 0}, "cost": {"type": "object", "unevaluatedProperties": false, "properties": {"food": {"$ref": "common.schema.json#/$defs/Money"}, "energy": {"$ref": "common.schema.json#/$defs/Money"}, "staff": {"$ref": "common.schema.json#/$defs/Money"}}}}}, "note": {"$ref": "common.schema.json#/$defs/UntrustedText"}, "meta": {"$ref": "common.schema.json#/$defs/Meta"}}}, "StationLease": {"type": "object", "required": ["kind", "id", "kitchen", "station", "holder", "from", "to"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "description": "Exclusive use of a station by a device or a role for a time. Two robots cannot hold the same hob.", "properties": {"kind": {"const": "StationLease"}, "id": {"$ref": "#/$defs/Id"}, "kitchen": {"$ref": "#/$defs/Id"}, "run": {"$ref": "#/$defs/Id"}, "station": {"$ref": "#/$defs/Id"}, "holder": {"type": "string", "maxLength": 200, "description": "Device id or staff role."}, "from": {"$ref": "common.schema.json#/$defs/DateTime"}, "to": {"$ref": "common.schema.json#/$defs/DateTime"}, "releasedAt": {"$ref": "common.schema.json#/$defs/DateTime"}}}}}, "https://cookwala.ai/v1/schemas/flow.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/flow.schema.json", "title": "Cookwala Flow", "x-cookwala-status": "experimental", "description": "A declarative, shareable workflow that strings Cookwala capabilities together: triggers (events, schedules, questions), steps (advise, plan, session, order, notify, wait for human, call an agent/tool/extension), branches and loops. Examples: 'every Sunday plan a week of halal meals under a budget, ask me to approve groceries, batch-cook Monday', 'when the fridge reports expiring items, suggest a dinner that uses them', 'restaurant: on order received, schedule robots and hold times'. Flows run inside a hub (or any compatible flow runner) and never bypass approvals or safety.", "type": "object", "required": ["cookwala", "id", "name", "version", "triggers", "steps"], "properties": {"cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "id": {"type": "string"}, "name": {"type": "string"}, "version": {"type": "string"}, "description": {"$ref": "common.schema.json#/$defs/LangMap"}, "inputs": {"type": "object", "description": "JSON Schema of parameters the user sets when installing (budget, people, cuisines...)."}, "mode": {"$ref": "profile.schema.json#/$defs/OperatingMode"}, "triggers": {"type": "array", "minItems": 1, "items": {"type": "object", "required": ["type"], "properties": {"type": {"enum": ["schedule", "event", "ask", "manual", "webhook"]}, "cron": {"type": "string"}, "timezone": {"type": "string"}, "eventTypes": {"type": "array", "items": {"type": "string"}}, "filter": {"type": "object", "description": "Expression over the event (policy expression language)."}, "phrases": {"$ref": "common.schema.json#/$defs/LangMap", "description": "For ask: example utterances that start this flow."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "steps": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/Step"}}, "onError": {"enum": ["stop", "notify_and_stop", "skip", "ask_human"], "default": "notify_and_stop"}, "meta": {"$ref": "common.schema.json#/$defs/Meta"}}, "patternProperties": {"^x-": {}}, "$defs": {"Step": {"type": "object", "required": ["id", "do"], "properties": {"id": {"type": "string"}, "do": {"enum": ["advise", "plan_session", "start_session", "confirm_with_human", "order_intent", "approve_with_human", "notify", "wait", "wait_for_event", "branch", "foreach", "set", "call_tool", "call_agent", "call_extension", "store_profile", "publish_recipe", "end"]}, "with": {"type": "object", "description": "Arguments; values may reference earlier outputs with {{steps.<id>.output...}} and inputs with {{inputs.<name>}}."}, "if": {"type": "object", "description": "Run only when this expression is true."}, "branches": {"type": "array", "items": {"type": "object", "properties": {"when": {"type": "object"}, "goto": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "items": {"type": "string"}, "steps": {"type": "array", "items": {"$ref": "#/$defs/Step"}}, "timeout": {"$ref": "common.schema.json#/$defs/Duration"}, "output": {"type": "string", "description": "Name to store the result under."}, "next": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "unevaluatedProperties": false}, "https://cookwala.ai/v1/schemas/household.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/household.schema.json", "title": "Cookwala Household Context Profile", "x-cookwala-status": "profile-draft", "description": "RFC-0001. The full picture of a home stays at home. A HouseholdContext is local-only and sensitive; providers and agents receive only DerivedConstraints. Facet types, their privacy classes and their travel rules come from vocab/facets.json. Raw facets never leave the device; inferred facets are never used for safety decisions; no behavioural score of any person exists; everything is erasable.", "$defs": {"Version": {"type": "string", "pattern": "^0\\.1\\.[0-9]+$"}, "Id": {"type": "string", "pattern": "^[a-z0-9][a-z0-9._:-]{2,95}$"}, "FacetId": {"type": "string", "pattern": "^(cw|x-[a-z0-9-]+)\\.facet\\.[a-z0-9_.]+$"}, "RecipientRole": {"enum": ["grocer", "delivery", "planner", "device_maker", "program", "dataset", "insurer", "other_robot"]}, "ConstraintType": {"enum": ["delivery_window", "access_point", "no_movement_zone", "quiet_hours", "avoid_ingredient", "allergen_block", "diet_rule", "serve_window", "budget_cap", "heat_sources", "equipment_available", "texture_level", "portion_count", "presence_required", "caution_level", "robot_runtime_minutes", "serving_form", "labeling_required", "cuisine_preference", "spice_level", "packaging_preference", "pet_safe_storage", "child_safe_zones", "device_fault_summary"]}, "Facet": {"type": "object", "required": ["facet", "subject", "value", "source", "observedAt", "privacy"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "description": "One typed fact about the home. The same shape as a Mission facet; the type must exist in vocab/facets.json.", "properties": {"id": {"$ref": "#/$defs/Id"}, "facet": {"$ref": "#/$defs/FacetId"}, "subject": {"type": "string", "maxLength": 120, "description": "What the fact is about: a device id, a zone, a role such as 'adult_member_2'. Never a legal name."}, "value": {}, "summary": {"$ref": "common.schema.json#/$defs/UntrustedText"}, "source": {"type": "object", "required": ["kind"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "properties": {"kind": {"enum": ["declared", "observed", "reported", "inferred"]}, "actor": {"type": "string", "maxLength": 120}, "evidence": {"type": "array", "items": {"type": "string", "maxLength": 200}, "description": "Local references (frames, logs) kept on the device."}}}, "observedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "validFor": {"$ref": "common.schema.json#/$defs/Duration"}, "confidence": {"type": "number", "minimum": 0, "maximum": 1}, "privacy": {"enum": ["public", "household", "sensitive", "secret"], "description": "May be raised above the registry default, never lowered below it."}, "consent": {"type": "array", "items": {"$ref": "#/$defs/Id"}, "description": "ConsentGrant ids that cover this facet."}}}, "ConsentGrant": {"type": "object", "required": ["id", "grantedBy", "scope", "recipientRole", "purpose", "grantedAt", "withdrawable"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "description": "Permission for facets with travel 'consented' to leave the home as selective disclosures. Granted by a role, never a named person.", "properties": {"id": {"$ref": "#/$defs/Id"}, "grantedBy": {"enum": ["owner", "adult_member", "guardian", "organization"], "description": "A role. Children cannot grant consent."}, "scope": {"type": "object", "unevaluatedProperties": false, "properties": {"facets": {"type": "array", "items": {"$ref": "#/$defs/FacetId"}}, "families": {"type": "array", "items": {"type": "string", "pattern": "^[a-z_.]+$"}}}, "minProperties": 1}, "recipientRole": {"$ref": "#/$defs/RecipientRole"}, "recipient": {"type": "string", "maxLength": 200, "description": "Specific organization (did:web) when the grant is not for a whole role."}, "purpose": {"type": "string", "maxLength": 200}, "grantedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "expiresAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "withdrawnAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "withdrawable": {"const": true}}}, "DerivedConstraint": {"type": "object", "required": ["kind", "type", "value", "recipientRole", "derivedFrom", "issuedAt"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "description": "The only household-originated object a provider or agent ever receives. Names the facet TYPES it came from, never their values.", "properties": {"kind": {"const": "DerivedConstraint"}, "type": {"$ref": "#/$defs/ConstraintType"}, "value": {}, "recipientRole": {"$ref": "#/$defs/RecipientRole"}, "derivedFrom": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/FacetId"}}, "issuedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "validFrom": {"$ref": "common.schema.json#/$defs/DateTime"}, "validTo": {"$ref": "common.schema.json#/$defs/DateTime"}, "disclosure": {"$ref": "common.schema.json#/$defs/Disclosure", "description": "Present only for 'consented' facets sent as a selective disclosure."}}}, "LocalIncident": {"type": "object", "required": ["id", "date", "category", "involved", "resolved"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "description": "The household's own memory of what went wrong and what was learnt. Never exported. The public, anonymous record is core.schema.json IncidentReport.", "properties": {"id": {"$ref": "#/$defs/Id"}, "date": {"type": "string", "format": "date"}, "category": {"$ref": "common.schema.json#/$defs/VocabId", "description": "From vocab/incidents.json."}, "involved": {"type": "array", "minItems": 1, "items": {"enum": ["robot", "other_robot", "appliance", "utensil", "alarm", "adult", "child", "pet", "visitor", "worker", "provider", "network", "power"]}}, "note": {"$ref": "common.schema.json#/$defs/UntrustedText"}, "lesson": {"$ref": "common.schema.json#/$defs/UntrustedText"}, "escalatedTo": {"enum": ["none", "household", "maker_support", "emergency_services"]}, "resolved": {"type": "boolean"}}}, "HouseholdContext": {"type": "object", "required": ["profile", "kind", "id", "holder", "meta", "facets", "consents", "retention"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "description": "Local-only document held by the home's hub or robot. meta.visibility MUST be local_only and meta.sensitive MUST be true.", "properties": {"profile": {"$ref": "#/$defs/Version"}, "kind": {"const": "HouseholdContext"}, "id": {"$ref": "#/$defs/Id"}, "holder": {"type": "string", "maxLength": 120, "description": "Device or hub id that holds the document."}, "meta": {"type": "object", "required": ["visibility", "sensitive"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "properties": {"visibility": {"const": "local_only"}, "sensitive": {"const": true}, "createdAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "updatedAt": {"$ref": "common.schema.json#/$defs/DateTime"}}}, "facets": {"type": "array", "items": {"$ref": "#/$defs/Facet"}}, "consents": {"type": "array", "items": {"$ref": "#/$defs/ConsentGrant"}}, "incidents": {"type": "array", "items": {"$ref": "#/$defs/LocalIncident"}}, "retention": {"type": "object", "required": ["erasureWindowDays"], "unevaluatedProperties": false, "properties": {"facetsDays": {"type": "integer", "minimum": 1, "maximum": 3650, "description": "Observed facets older than this are dropped unless re-observed."}, "incidentsDays": {"type": "integer", "minimum": 1, "maximum": 3650}, "erasureWindowDays": {"type": "integer", "minimum": 1, "maximum": 30, "description": "An erasure request completes within this many days. Default 7."}}}, "erasures": {"type": "array", "items": {"type": "object", "required": ["requestedAt", "scope", "completedAt"], "unevaluatedProperties": false, "properties": {"requestedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "scope": {"enum": ["all", "facets", "incidents", "family", "facet"]}, "target": {"type": "string", "maxLength": 120}, "completedAt": {"$ref": "common.schema.json#/$defs/DateTime"}}}, "description": "Local log that erasure happened, kept without the erased content."}}}, "RecipientRoles": {"type": "object", "required": ["profile", "kind", "roles"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "description": "Which DerivedConstraint types each recipient role may receive. Closed list in 0.1 (RFC-0001 open question 1).", "properties": {"profile": {"$ref": "#/$defs/Version"}, "kind": {"const": "RecipientRoles"}, "roles": {"type": "object", "unevaluatedProperties": false, "properties": {"grocer": {"$ref": "#/$defs/ConstraintTypeList"}, "delivery": {"$ref": "#/$defs/ConstraintTypeList"}, "planner": {"$ref": "#/$defs/ConstraintTypeList"}, "device_maker": {"$ref": "#/$defs/ConstraintTypeList"}, "program": {"$ref": "#/$defs/ConstraintTypeList"}, "dataset": {"$ref": "#/$defs/ConstraintTypeList"}, "insurer": {"$ref": "#/$defs/ConstraintTypeList"}, "other_robot": {"$ref": "#/$defs/ConstraintTypeList"}}}}}, "ConstraintTypeList": {"type": "array", "uniqueItems": true, "items": {"$ref": "#/$defs/ConstraintType"}}}}, "https://cookwala.ai/v1/schemas/humanitarian.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/humanitarian.schema.json", "title": "Cookwala Humanitarian Profile", "x-cookwala-status": "profile-draft", "description": "A minimal, strict, personal-data-free subset of Cookwala for food banks, community kitchens, school-meal and relief programs: surplus offers, claims, custody handovers with cold-chain checks, aggregate distributions, and machine-readable nutrition and food-safety rule packs. Works without robots. Version 0.2 (RFC-0003, RFC-0004) adds item origin and harvest date, food classes, program types, review records and the ImpactSummary. See docs/HUMANITARIAN-PROFILE.md. Unlike the core schemas, every object here rejects unknown properties except x- extensions, temperatures are degrees Celsius only, tolerances are absolute, and money is a decimal string.", "$defs": {"Version": {"type": "string", "pattern": "^0\\.(1|2)\\.[0-9]+$", "description": "Humanitarian Profile version. 0.2 is additive over 0.1; readers accept both during the transition."}, "Id": {"type": "string", "pattern": "^[a-z0-9][a-z0-9._:-]{2,95}$"}, "OrgId": {"type": "string", "pattern": "^(did:web:[a-z0-9.-]+|gln:[0-9]{13}|org:[a-z0-9-]+\\.[a-z0-9.-]+)$", "description": "An ORGANIZATION, never a person: a did:web domain, a GS1 Global Location Number, or a registry-scoped id."}, "Role": {"enum": ["donor", "food_bank", "community_kitchen", "school", "relief_program", "transporter", "cold_storage", "platform", "farm", "caterer", "robot_kitchen"]}, "DateTime": {"type": "string", "format": "date-time", "pattern": "(Z|[+-][0-9]{2}:[0-9]{2})$", "description": "RFC 3339 with an explicit offset."}, "Date": {"type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"}, "Kg": {"type": "number", "minimum": 0, "maximum": 1000000, "description": "Mass in kilograms. The profile uses kg only."}, "TempC": {"type": "number", "minimum": -60, "maximum": 300, "description": "Degrees Celsius. The profile uses Celsius only; displays may convert."}, "Decimal": {"type": "string", "pattern": "^-?[0-9]{1,15}(\\.[0-9]{1,6})?$", "description": "Exact decimal, never a binary float."}, "Money": {"type": "object", "required": ["amount", "currency"], "unevaluatedProperties": false, "properties": {"amount": {"$ref": "#/$defs/Decimal"}, "currency": {"type": "string", "pattern": "^[A-Z]{3}$"}}}, "Extensions": {"patternProperties": {"^x-[a-z0-9-]+$": {}}}, "Note": {"type": "string", "maxLength": 280, "description": "Operational note. MUST NOT contain names, phone numbers, ids or health details of any person."}, "Site": {"type": "object", "required": ["country", "admin1"], "unevaluatedProperties": false, "description": "An organization's premises or an administrative area. Never a household or a person's location.", "properties": {"country": {"type": "string", "pattern": "^[A-Z]{2}$"}, "admin1": {"type": "string", "maxLength": 80}, "admin2": {"type": "string", "maxLength": 80}, "pcode": {"type": "string", "maxLength": 20, "description": "OCHA common operational dataset P-code."}, "gln": {"type": "string", "pattern": "^[0-9]{13}$"}, "siteName": {"type": "string", "maxLength": 80, "description": "Name of the organization's site, e.g. 'North warehouse'."}, "lat": {"type": "number", "minimum": -90, "maximum": 90}, "lon": {"type": "number", "minimum": -180, "maximum": 180}}, "$ref": "#/$defs/Extensions"}, "Storage": {"enum": ["ambient", "chilled", "frozen", "hot_held"]}, "DateMark": {"type": "object", "required": ["kind", "date"], "unevaluatedProperties": false, "properties": {"kind": {"enum": ["use_by", "best_before", "cooked_on", "none"]}, "date": {"$ref": "#/$defs/Date"}}}, "Item": {"type": "object", "required": ["name", "kg", "storage"], "unevaluatedProperties": false, "properties": {"lineId": {"type": "string", "pattern": "^[a-z0-9-]{1,32}$"}, "name": {"type": "string", "maxLength": 80}, "ingredientId": {"type": "string", "pattern": "^(cw|x-[a-z0-9-]+)\\.[a-z0-9_.-]+$"}, "gtin": {"type": "string", "pattern": "^[0-9]{8,14}$"}, "kg": {"$ref": "#/$defs/Kg"}, "units": {"type": "integer", "minimum": 0}, "storage": {"$ref": "#/$defs/Storage"}, "dateMark": {"$ref": "#/$defs/DateMark"}, "allergens": {"type": "array", "uniqueItems": true, "items": {"enum": ["cereals_gluten", "crustaceans", "eggs", "fish", "peanuts", "soybeans", "milk", "tree_nuts", "sesame", "mustard", "celery", "lupin", "molluscs", "sulphites", "unknown"]}, "description": "Declared allergens. 'unknown' means unlabelled and triggers rule-pack checks."}, "cooked": {"type": "boolean", "description": "Ready-to-eat cooked food (higher risk)."}, "cookedAt": {"$ref": "#/$defs/DateTime"}, "origin": {"$ref": "#/$defs/Origin"}, "harvestedAt": {"$ref": "#/$defs/Date", "description": "Harvest date for farm produce."}, "foodClasses": {"type": "array", "uniqueItems": true, "items": {"$ref": "#/$defs/FoodClass"}}, "certifications": {"type": "array", "items": {"$ref": "common.schema.json#/$defs/CertificationRef"}, "description": "Certifications of the item or lot (halal, kosher, organic...), by hash; verified against the authority's key, never trusted from the message (RFC-0010)."}}, "$ref": "#/$defs/Extensions"}, "TempReading": {"type": "object", "required": ["at", "tempC", "method"], "unevaluatedProperties": false, "properties": {"at": {"$ref": "#/$defs/DateTime"}, "tempC": {"$ref": "#/$defs/TempC"}, "method": {"enum": ["probe", "infrared", "logger", "fridge_display", "not_measured"]}, "lineId": {"type": "string", "pattern": "^[a-z0-9-]{1,32}$"}}}, "OfferState": {"enum": ["offered", "claimed", "collected", "delivered", "distributed", "expired", "withdrawn", "rejected"], "description": "Legal transitions are listed in docs/HUMANITARIAN-PROFILE.md section 5; anything else MUST be refused with 409."}, "RejectReason": {"enum": ["temp_out_of_range", "past_use_by", "packaging_damaged", "allergen_unlabelled", "quantity_mismatch", "pests_or_contamination", "no_capacity", "no_transport", "arrived_late", "other"]}, "Offer": {"type": "object", "required": ["profile", "kind", "id", "donor", "items", "window", "site", "state"], "unevaluatedProperties": false, "description": "A donor offers surplus food for collection.", "properties": {"profile": {"$ref": "#/$defs/Version"}, "kind": {"const": "Offer"}, "id": {"$ref": "#/$defs/Id"}, "donor": {"$ref": "#/$defs/OrgId"}, "items": {"type": "array", "minItems": 1, "maxItems": 200, "items": {"$ref": "#/$defs/Item"}}, "window": {"type": "object", "required": ["from", "to"], "unevaluatedProperties": false, "properties": {"from": {"$ref": "#/$defs/DateTime"}, "to": {"$ref": "#/$defs/DateTime"}}}, "site": {"$ref": "#/$defs/Site"}, "readings": {"type": "array", "items": {"$ref": "#/$defs/TempReading"}, "description": "Storage temperatures at the donor when offered."}, "needs": {"type": "array", "uniqueItems": true, "items": {"enum": ["refrigerated_vehicle", "pallet_jack", "volunteers", "same_day"]}}, "donationProtection": {"type": "string", "maxLength": 80, "description": "Applicable donor-liability law, e.g. 'US Bill Emerson Act'."}, "state": {"$ref": "#/$defs/OfferState"}, "version": {"type": "integer", "minimum": 1, "description": "Incremented on every change; used with If-Match."}, "note": {"$ref": "#/$defs/Note"}, "createdAt": {"$ref": "#/$defs/DateTime", "description": "When the offer was created; with Claim.claimedAt it gives time to claim."}}, "$ref": "#/$defs/Extensions"}, "Claim": {"type": "object", "required": ["profile", "kind", "id", "offer", "claimant", "lines", "pickupBy"], "unevaluatedProperties": false, "description": "A receiving organization claims all or part of an offer.", "properties": {"profile": {"$ref": "#/$defs/Version"}, "kind": {"const": "Claim"}, "id": {"$ref": "#/$defs/Id"}, "offer": {"$ref": "#/$defs/Id"}, "claimant": {"$ref": "#/$defs/OrgId"}, "claimantRole": {"$ref": "#/$defs/Role"}, "lines": {"type": "array", "minItems": 1, "items": {"type": "object", "required": ["lineId", "kg"], "unevaluatedProperties": false, "properties": {"lineId": {"type": "string", "pattern": "^[a-z0-9-]{1,32}$"}, "kg": {"$ref": "#/$defs/Kg"}}}}, "pickupBy": {"$ref": "#/$defs/DateTime"}, "transporter": {"$ref": "#/$defs/OrgId"}, "vehicle": {"enum": ["refrigerated", "insulated", "ambient", "on_foot_or_bike"]}, "note": {"$ref": "#/$defs/Note"}, "claimedAt": {"$ref": "#/$defs/DateTime"}}, "$ref": "#/$defs/Extensions"}, "Handover": {"type": "object", "required": ["profile", "kind", "id", "offer", "from", "to", "at", "readings", "lines", "outcome"], "unevaluatedProperties": false, "description": "A custody transfer with a cold-chain check. One per leg (donor → transporter → food bank → kitchen).", "properties": {"profile": {"$ref": "#/$defs/Version"}, "kind": {"const": "Handover"}, "id": {"$ref": "#/$defs/Id"}, "offer": {"$ref": "#/$defs/Id"}, "claim": {"$ref": "#/$defs/Id"}, "from": {"$ref": "#/$defs/OrgId"}, "to": {"$ref": "#/$defs/OrgId"}, "at": {"$ref": "#/$defs/DateTime"}, "site": {"$ref": "#/$defs/Site"}, "readings": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/TempReading"}}, "lines": {"type": "array", "minItems": 1, "items": {"type": "object", "required": ["lineId", "kgAccepted"], "unevaluatedProperties": false, "properties": {"lineId": {"type": "string", "pattern": "^[a-z0-9-]{1,32}$"}, "kgAccepted": {"$ref": "#/$defs/Kg"}, "kgRejected": {"$ref": "#/$defs/Kg"}, "reason": {"$ref": "#/$defs/RejectReason"}}}}, "outcome": {"enum": ["accepted", "partly_accepted", "rejected"]}, "checkedBy": {"enum": ["trained_staff", "volunteer", "driver", "automated_logger"], "description": "A role, never a name."}, "rulePack": {"type": "string", "description": "Id@version of the rule pack applied."}, "findings": {"type": "array", "items": {"type": "string", "pattern": "^[a-z0-9._-]+$"}, "description": "Ids of rules that warned or blocked."}, "note": {"$ref": "#/$defs/Note"}, "leg": {"type": "integer", "minimum": 1, "description": "1 for the first custody transfer from the donor; kilograms rescued are counted on leg 1 only."}, "audienceGroups": {"type": "array", "uniqueItems": true, "items": {"$ref": "#/$defs/AudienceGroup"}, "description": "Who the receiving program serves, so care rules apply at handover."}}, "$ref": "#/$defs/Extensions"}, "Distribution": {"type": "object", "required": ["profile", "kind", "id", "org", "site", "date", "meals"], "unevaluatedProperties": false, "description": "AGGREGATE record of food served or handed out at a site on a day. No individual or household records exist in this profile.", "properties": {"profile": {"$ref": "#/$defs/Version"}, "kind": {"const": "Distribution"}, "id": {"$ref": "#/$defs/Id"}, "org": {"$ref": "#/$defs/OrgId"}, "orgRole": {"$ref": "#/$defs/Role"}, "site": {"$ref": "#/$defs/Site"}, "date": {"$ref": "#/$defs/Date"}, "form": {"enum": ["hot_meals", "food_parcels", "school_meals", "mixed"]}, "meals": {"type": "integer", "minimum": 0}, "people": {"type": "object", "unevaluatedProperties": false, "description": "Counts by HXL-style groups. Any group under 10 MUST be reported as the string '<10' (small-cell suppression).", "properties": {"total": {"$ref": "#/$defs/Count"}, "children": {"$ref": "#/$defs/Count"}, "adults": {"$ref": "#/$defs/Count"}, "elderly": {"$ref": "#/$defs/Count", "deprecated": true, "description": "Deprecated in 0.2; write older_adults. Kept so 0.1 documents still validate."}, "older_adults": {"$ref": "#/$defs/Count"}, "female": {"$ref": "#/$defs/Count"}, "male": {"$ref": "#/$defs/Count"}}}, "kgUsed": {"$ref": "#/$defs/Kg"}, "kgRescuedUsed": {"$ref": "#/$defs/Kg"}, "offers": {"type": "array", "items": {"$ref": "#/$defs/Id"}}, "menu": {"type": "object", "unevaluatedProperties": false, "properties": {"recipes": {"type": "array", "items": {"type": "string", "maxLength": 120}}, "perPersonDay": {"$ref": "#/$defs/Nutrients"}, "perMeal": {"$ref": "#/$defs/Nutrients"}, "foodClasses": {"type": "array", "uniqueItems": true, "items": {"$ref": "#/$defs/FoodClass"}, "description": "Food classes present in the menu, for food_class rules."}}}, "cost": {"type": "object", "unevaluatedProperties": false, "properties": {"food": {"$ref": "#/$defs/Money"}, "transport": {"$ref": "#/$defs/Money"}, "staff": {"$ref": "#/$defs/Money"}, "energy": {"$ref": "#/$defs/Money"}}}, "volunteerMinutes": {"type": "integer", "minimum": 0}, "rulePack": {"type": "string"}, "findings": {"type": "array", "items": {"type": "string", "pattern": "^[a-z0-9._-]+$"}}, "safetyIncidents": {"type": "integer", "minimum": 0, "description": "Suspected foodborne illness reports or recalls linked to this distribution (counts only)."}, "note": {"$ref": "#/$defs/Note"}, "audienceGroups": {"type": "array", "uniqueItems": true, "items": {"$ref": "#/$defs/AudienceGroup"}, "description": "Who the distribution serves, so care rules apply."}}, "$ref": "#/$defs/Extensions"}, "Count": {"oneOf": [{"type": "integer", "minimum": 10}, {"const": "<10"}]}, "Nutrients": {"type": "object", "unevaluatedProperties": false, "properties": {"energyKcal": {"type": "number", "minimum": 0}, "proteinG": {"type": "number", "minimum": 0}, "fatG": {"type": "number", "minimum": 0}, "saturatedFatG": {"type": "number", "minimum": 0}, "transFatG": {"type": "number", "minimum": 0}, "freeSugarsG": {"type": "number", "minimum": 0}, "sodiumMg": {"type": "number", "minimum": 0}, "fruitVegG": {"type": "number", "minimum": 0}, "fibreG": {"type": "number", "minimum": 0}}}, "Rule": {"type": "object", "required": ["id", "kind", "applies", "check", "severity", "source"], "unevaluatedProperties": false, "properties": {"id": {"type": "string", "pattern": "^[a-z0-9._-]+$"}, "kind": {"enum": ["nutrient", "energy_share", "temperature", "time", "date_mark", "allergen", "food_class"]}, "applies": {"enum": ["menu_per_person_day", "menu_per_meal", "item_chilled", "item_frozen", "item_hot_held", "item_cooked", "item_any"]}, "check": {"type": "object", "unevaluatedProperties": false, "properties": {"nutrient": {"enum": ["energyKcal", "proteinG", "fatG", "saturatedFatG", "transFatG", "freeSugarsG", "sodiumMg", "fruitVegG", "fibreG"]}, "min": {"type": "number"}, "max": {"type": "number"}, "unit": {"enum": ["mg", "g", "kcal", "pct_energy", "degC", "hours", "days"]}, "dateKind": {"enum": ["use_by", "best_before"]}, "allergen": {"const": "unknown"}, "foodClass": {"$ref": "#/$defs/FoodClass"}}}, "severity": {"enum": ["block", "warn"], "description": "block: the receiver should not accept or serve; warn: allowed, recorded as a finding."}, "audience": {"type": "string", "maxLength": 80, "description": "Population the rule is meant for, e.g. 'adults', 'children 2-15 (adjust by energy)'."}, "message": {"type": "string", "maxLength": 200}, "source": {"type": "string", "maxLength": 200}, "audienceGroup": {"$ref": "#/$defs/AudienceGroup", "description": "Machine-readable population the rule is for; a program applies rules whose audienceGroup matches its audienceGroups or is 'all'."}}}, "RulePack": {"type": "object", "required": ["profile", "kind", "id", "version", "title", "status", "rules", "disclaimer"], "unevaluatedProperties": false, "description": "Machine-readable nutrition and food-safety rules a program applies to handovers and menus. Packs are versioned and replaceable by local authorities' rules.", "properties": {"profile": {"$ref": "#/$defs/Version"}, "kind": {"const": "RulePack"}, "id": {"$ref": "#/$defs/Id"}, "version": {"type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"}, "title": {"type": "string", "maxLength": 120}, "status": {"enum": ["draft", "reviewed", "adopted", "retired"]}, "reviewedBy": {"type": "array", "items": {"type": "string", "maxLength": 120}}, "jurisdiction": {"type": "string", "maxLength": 80}, "rules": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/Rule"}}, "disclaimer": {"type": "string", "maxLength": 600}, "reviews": {"type": "array", "items": {"type": "object", "required": ["role", "date", "outcome"], "unevaluatedProperties": false, "properties": {"role": {"type": "string", "maxLength": 80, "description": "A profession, e.g. registered dietitian, food-safety officer. Never a person's name."}, "organization": {"type": "string", "maxLength": 120}, "date": {"$ref": "#/$defs/Date"}, "scope": {"type": "string", "maxLength": 200, "description": "Which rules were reviewed."}, "outcome": {"enum": ["approved", "approved_with_changes", "rejected"]}, "notes": {"$ref": "#/$defs/Note"}}}, "description": "Who reviewed this pack (RFC-0004). status may be 'reviewed' only with at least one approved outcome."}, "extends": {"type": "string", "maxLength": 120, "description": "id@version of a pack this one tightens."}}}, "Manifest": {"type": "object", "required": ["profile", "kind", "org", "levels", "contact"], "unevaluatedProperties": false, "description": "Published at /.well-known/cookwala-humanitarian.json by a participating system or organization.", "properties": {"profile": {"$ref": "#/$defs/Version"}, "kind": {"const": "Manifest"}, "org": {"$ref": "#/$defs/OrgId"}, "roles": {"type": "array", "items": {"$ref": "#/$defs/Role"}}, "levels": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"enum": ["H0", "H1", "H2", "H3"]}}, "rulePacks": {"type": "array", "items": {"type": "string"}}, "endpoints": {"type": "object", "unevaluatedProperties": false, "properties": {"api": {"type": "string", "format": "uri"}, "sms": {"type": "string", "maxLength": 20}, "csvTemplates": {"type": "string", "format": "uri"}}}, "auditLog": {"enum": ["none", "hash_only"], "description": "hash_only: document hashes appended by one sequencer per program, checkpoints witnessed by a partner."}, "dataProtection": {"type": "object", "required": ["personalData"], "unevaluatedProperties": false, "properties": {"personalData": {"const": "none"}, "retentionDays": {"type": "integer", "minimum": 1}, "hosting": {"type": "string", "maxLength": 120}}}, "contact": {"type": "string", "format": "email"}, "programTypes": {"type": "array", "uniqueItems": true, "items": {"enum": ["food_bank", "school_meals", "community_kitchen", "disaster_kitchen", "robot_kitchen", "surplus_rescue"]}}}}, "FoodClass": {"enum": ["raw_egg", "undercooked_egg", "raw_meat", "raw_fish", "unpasteurized_dairy", "soft_cheese", "raw_sprouts", "high_mercury_fish", "honey", "whole_nuts", "hard_candy", "alcohol", "caffeine_high", "deli_meat_cold", "leafy_greens_raw", "cut_melon", "cooked_rice", "none"], "description": "Food classes that care rules refer to (RFC-0004)."}, "AudienceGroup": {"enum": ["all", "children_under_5", "children", "pregnant", "older_adults", "immunocompromised"]}, "Origin": {"enum": ["farm", "processor", "wholesale", "retail", "food_service", "kitchen"], "description": "Where the item comes from. A farm is a donor like any other: an organization, never a person."}, "Measure": {"type": "object", "required": ["value", "method"], "unevaluatedProperties": false, "properties": {"value": {"oneOf": [{"type": "number"}, {"const": "<10"}, {"type": "null"}]}, "unit": {"type": "string", "maxLength": 20}, "method": {"enum": ["measured", "modelled", "assumed", "not_recorded"]}, "source": {"type": "string", "maxLength": 200, "description": "Which documents or model produced it."}, "n": {"type": "integer", "minimum": 0, "description": "Number of documents behind the value."}}}, "ImpactSummary": {"type": "object", "required": ["profile", "kind", "id", "org", "period", "measures"], "unevaluatedProperties": false, "description": "RFC-0003. The measures that prove impact, computed from Handovers, Claims and Distributions, each with its method. People counts under 10 are '<10'. Never typed by hand when the documents exist.", "properties": {"profile": {"$ref": "#/$defs/Version"}, "kind": {"const": "ImpactSummary"}, "id": {"$ref": "#/$defs/Id"}, "org": {"$ref": "#/$defs/OrgId"}, "programType": {"enum": ["food_bank", "school_meals", "community_kitchen", "disaster_kitchen", "robot_kitchen", "surplus_rescue"]}, "site": {"$ref": "#/$defs/Site"}, "period": {"type": "object", "required": ["from", "to"], "unevaluatedProperties": false, "properties": {"from": {"$ref": "#/$defs/Date"}, "to": {"$ref": "#/$defs/Date"}}}, "measures": {"type": "object", "required": ["kgRescued", "mealsServed", "safetyIncidents"], "unevaluatedProperties": false, "properties": {"kgRescued": {"$ref": "#/$defs/Measure"}, "kgRejected": {"$ref": "#/$defs/Measure"}, "mealsServed": {"$ref": "#/$defs/Measure"}, "peopleReached": {"$ref": "#/$defs/Measure"}, "nutritionPassRate": {"$ref": "#/$defs/Measure"}, "costPerMeal": {"$ref": "#/$defs/Measure"}, "timeToClaimMinutesMedian": {"$ref": "#/$defs/Measure"}, "claimRate": {"$ref": "#/$defs/Measure"}, "safetyBlockFindings": {"$ref": "#/$defs/Measure"}, "safetyIncidents": {"$ref": "#/$defs/Measure"}, "volunteerMinutesPer100Kg": {"$ref": "#/$defs/Measure"}}}, "documents": {"type": "object", "unevaluatedProperties": false, "properties": {"offers": {"type": "integer", "minimum": 0}, "claims": {"type": "integer", "minimum": 0}, "handovers": {"type": "integer", "minimum": 0}, "distributions": {"type": "integer", "minimum": 0}}}, "whatWentWrong": {"type": "array", "items": {"$ref": "#/$defs/Note"}, "description": "Required on published summaries: problems recorded in the period, or 'nothing recorded yet'."}, "unknowns": {"type": "array", "items": {"$ref": "#/$defs/Note"}, "description": "What the documents cannot tell."}, "rulePack": {"type": "string"}, "signature": {"$ref": "common.schema.json#/$defs/Signature"}, "counterSignature": {"$ref": "common.schema.json#/$defs/Signature", "description": "A partner organization's signature over the same hash (recommended for published summaries)."}}, "$ref": "#/$defs/Extensions"}}}, "https://cookwala.ai/v1/schemas/inventory.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/inventory.schema.json", "title": "Cookwala Inventory", "x-cookwala-status": "experimental", "description": "What food is in the kitchen (fridge, freezer, pantry, robot dispensers). Matter covers fridge state but not contents, so Cookwala defines it. Published by smart fridges, pantry scales, receipt scanners or humans; read by planners to decide what can be cooked and what to order.", "type": "object", "required": ["cookwala", "kitchenId", "updatedAt", "items"], "properties": {"cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "kitchenId": {"type": "string"}, "updatedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "storages": {"type": "array", "items": {"type": "object", "required": ["id", "kind"], "properties": {"id": {"type": "string"}, "kind": {"enum": ["fridge", "freezer", "pantry", "spice_rack", "dispenser", "counter", "cellar"]}, "tempC": {"type": "number"}, "actor": {"$ref": "common.schema.json#/$defs/Actor"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "items": {"type": "array", "items": {"$ref": "#/$defs/Item"}}, "meta": {"$ref": "common.schema.json#/$defs/Meta"}}, "$defs": {"Item": {"type": "object", "required": ["id", "ingredientId", "qty"], "properties": {"id": {"type": "string"}, "ingredientId": {"$ref": "common.schema.json#/$defs/VocabId"}, "label": {"type": "string"}, "gtin": {"type": "string"}, "qty": {"$ref": "common.schema.json#/$defs/Quantity"}, "storage": {"type": "string"}, "openedAt": {"type": "string", "format": "date"}, "expires": {"type": "string", "format": "date"}, "useWithinDaysAfterOpening": {"type": "number"}, "confidence": {"type": "number", "minimum": 0, "maximum": 1, "description": "How sure the detector is (camera inventories are approximate)."}, "detectedBy": {"enum": ["camera", "weight", "rfid", "barcode", "receipt", "manual", "order"]}, "dietary": {"type": "array", "items": {"type": "string"}, "description": "e.g. halal_certified, kosher, organic."}, "allergens": {"type": "array", "items": {"type": "string"}}, "reservedBy": {"type": "string", "description": "Session id holding this item for a planned cook."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "patternProperties": {"^x-": {}}, "unevaluatedProperties": false}, "https://cookwala.ai/v1/schemas/knowledge.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/knowledge.schema.json", "title": "Cookwala Knowledge Packs", "x-cookwala-status": "experimental", "description": "Culinary and food-safety knowledge the reasoner uses beyond recipes: recovery playbooks, ingredient functional roles, substitution rules, transformations (repurposing intermediates), storage profiles and energy models. Anyone can publish a knowledge pack (public or private); packs are merged by priority, and safety rules can only be tightened by lower-priority packs, never loosened.", "type": "object", "required": ["cookwala", "id", "version", "kind", "entries"], "properties": {"cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "id": {"type": "string"}, "version": {"type": "string"}, "kind": {"enum": ["playbooks", "roles", "substitutions", "transformations", "storage", "energy", "incidents", "pairings", "scaling", "nutrition"]}, "title": {"$ref": "common.schema.json#/$defs/LangMap"}, "reviewStatus": {"enum": ["draft", "community_reviewed", "expert_reviewed"]}, "sources": {"type": "array", "items": {"type": "object", "properties": {"title": {"type": "string"}, "url": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "disclaimer": {"type": "string"}, "meta": {"$ref": "common.schema.json#/$defs/Meta"}, "entries": {"type": "array"}}, "patternProperties": {"^x-": {}}, "allOf": [{"if": {"properties": {"kind": {"const": "playbooks"}}}, "then": {"properties": {"entries": {"items": {"$ref": "#/$defs/Playbook"}}}}}, {"if": {"properties": {"kind": {"const": "roles"}}}, "then": {"properties": {"entries": {"items": {"$ref": "#/$defs/RoleEntry"}}}}}, {"if": {"properties": {"kind": {"const": "substitutions"}}}, "then": {"properties": {"entries": {"items": {"$ref": "#/$defs/Substitution"}}}}}, {"if": {"properties": {"kind": {"const": "transformations"}}}, "then": {"properties": {"entries": {"items": {"$ref": "#/$defs/Transformation"}}}}}, {"if": {"properties": {"kind": {"const": "storage"}}}, "then": {"properties": {"entries": {"items": {"$ref": "#/$defs/StorageProfile"}}}}}, {"if": {"properties": {"kind": {"const": "energy"}}}, "then": {"properties": {"entries": {"items": {"$ref": "#/$defs/EnergyModel"}}}}}], "$defs": {"Cond": {"type": "object", "description": "Condition over the incident/context (same expression language as policy packs: all/any/not/path comparisons).", "additionalProperties": true}, "Playbook": {"type": "object", "required": ["id", "incidentTypes", "title", "options"], "properties": {"id": {"type": "string", "pattern": "^(cw|x-[a-z0-9-]+)\\.pb\\.[a-z0-9_.]+$"}, "incidentTypes": {"type": "array", "items": {"type": "string"}}, "title": {"$ref": "common.schema.json#/$defs/LangMap"}, "appliesTo": {"type": "object", "properties": {"ops": {"type": "array", "items": {"type": "string"}}, "ingredientClasses": {"type": "array", "items": {"type": "string"}}, "dishTags": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "safetyGate": {"type": "array", "description": "Evaluated first. The first matching rule with verdict unsafe_discard ends the playbook: only discard/restart/repurpose-other-food options remain.", "items": {"type": "object", "required": ["when", "verdict", "message"], "properties": {"when": {"$ref": "#/$defs/Cond"}, "verdict": {"enum": ["unsafe_discard", "unknown_ask_human", "safe_with_conditions"]}, "message": {"$ref": "common.schema.json#/$defs/LangMap"}, "ruleRef": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "diagnostics": {"type": "array", "items": {"$ref": "advice.schema.json#/$defs/Question"}}, "options": {"type": "array", "minItems": 1, "items": {"type": "object", "required": ["id", "title", "kind"], "properties": {"id": {"type": "string"}, "kind": {"enum": ["patch_and_resume", "repurpose", "discard_and_restart", "discard", "ask_human", "substitution"]}, "title": {"$ref": "common.schema.json#/$defs/LangMap"}, "when": {"$ref": "#/$defs/Cond"}, "actions": {"type": "array", "items": {"$ref": "advice.schema.json#/$defs/PatchOp"}, "description": "Patch templates; {placeholders} resolved from the incident and recipe."}, "resume": {"enum": ["same_node", "next_node", "restart_node", "restart_from_input", "none"]}, "impact": {"type": "object", "properties": {"extraTimeMin": {"type": "number"}, "quality": {"type": "string"}, "notes": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "priority": {"type": "integer"}, "notes": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "prevention": {"type": "array", "items": {"type": "string"}, "description": "What executors should do to avoid it next time (fed back into recipes)."}, "references": {"type": "array", "items": {"type": "object", "properties": {"title": {"type": "string"}, "url": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "RoleEntry": {"type": "object", "required": ["subject", "roles"], "properties": {"subject": {"type": "string", "description": "Ingredient id or class (cw.ing.* / cw.ing.class.*)."}, "roles": {"type": "array", "items": {"type": "object", "required": ["role"], "properties": {"role": {"enum": ["salt", "acid", "sweetener", "fat", "umami", "bitter", "heat_spice", "aromatic_base", "herb_fresh", "spice_warm", "binder", "leavener_chemical", "leavener_biological", "thickener_starch", "thickener_protein", "gelling", "emulsifier", "protein_main", "bulk_starch", "liquid_base", "stock", "color", "crunch", "moisture", "preservative", "garnish"]}, "strength": {"type": "number", "minimum": 0, "maximum": 1}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "saltPct": {"type": "number", "description": "Approximate salt (NaCl) by mass, for salt balancing."}, "acidity": {"type": "string"}, "notes": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Substitution": {"type": "object", "required": ["from", "to", "ratio"], "properties": {"from": {"type": "string"}, "to": {"type": "array", "items": {"type": "object", "required": ["ingredientId", "ratio"], "properties": {"ingredientId": {"type": "string"}, "ratio": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "minItems": 1}, "ratio": {"type": "number", "description": "Overall mass ratio to of from (1 = same mass)."}, "goodFor": {"type": "array", "items": {"type": "string"}, "description": "Contexts/ops where it works (baking, braise, raw, frying...)."}, "badFor": {"type": "array", "items": {"type": "string"}}, "quality": {"enum": ["same", "minor_loss", "noticeable_loss"]}, "reasons": {"type": "array", "items": {"enum": ["missing", "allergy", "dietary", "cost", "preference", "budget", "ration"]}}, "adjust": {"type": "array", "items": {"$ref": "advice.schema.json#/$defs/PatchOp"}, "description": "Follow-up adjustments (e.g. reduce other liquid)."}, "notes": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Transformation": {"type": "object", "required": ["id", "from", "to"], "properties": {"id": {"type": "string"}, "from": {"type": "object", "description": "Intermediate state pattern: {\"class\": \"cooked_rice\", \"issues\": [\"mushy\"]}.", "additionalProperties": true}, "to": {"type": "array", "items": {"type": "object", "properties": {"dishTag": {"type": "string"}, "recipeId": {"$ref": "common.schema.json#/$defs/GlobalRef"}, "title": {"$ref": "common.schema.json#/$defs/LangMap"}, "needs": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "safety": {"type": "string", "description": "Safety condition that must already hold (e.g. 'rice was cooled to 5 °C within 2 h')."}, "notes": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "StorageProfile": {"type": "object", "required": ["id", "foodClasses"], "properties": {"id": {"type": "string"}, "foodClasses": {"type": "array", "items": {"type": "string"}}, "fridgeDays": {"type": "object", "properties": {"min": {"type": "number"}, "max": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "freezerMonths": {"type": "object", "properties": {"min": {"type": "number"}, "max": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "freezeQuality": {"enum": ["good", "fair", "poor"]}, "roomTempMaxHours": {"type": "number"}, "cooling": {"type": "string"}, "reheatMinC": {"type": "number"}, "containers": {"type": "array", "items": {"type": "string"}}, "cookForStorage": {"type": "array", "items": {"type": "string"}}, "notes": {"type": "array", "items": {"type": "string"}}, "sources": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "EnergyModel": {"type": "object", "required": ["id", "source"], "properties": {"id": {"type": "string"}, "source": {"type": "string"}, "efficiency": {"$ref": "common.schema.json#/$defs/Range", "description": "Approximate fraction of input energy reaching the food."}, "notes": {"type": "array", "items": {"type": "string"}}, "tips": {"type": "array", "items": {"type": "string"}}, "sources": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "unevaluatedProperties": false}, "https://cookwala.ai/v1/schemas/legacy/fifi-data-v1.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/legacy/fifi-data-v1.schema.json", "title": "fifi.cooking public data API (existing, pre-Cookwala)", "description": "Documents the static JSON the site already publishes under /data/ (generated by scripts/generate-public-index.ts and scripts/generate-tv-index.ts). Cookwala keeps these endpoints unchanged and adds /v1/ alongside them. Use the $defs by name: RecipeFile (/data/recipes/{id}.json), IndexPage (/data/index/{page}.json), SearchMap (/data/search/{lang}.json), IngredientList (/data/ingredients/{lang}.json), Manifest (/data/manifest.json). The TV slice is specified separately in scripts/tv-api.schema.json.", "$defs": {"IngredientCategory": {"enum": ["meat_poultry", "seafood", "vegetable", "dairy_fat", "grain_starch", "spice_seasoning", "sweet_fruit", "liquid", "other"]}, "Collection": {"enum": ["archive", "chefteta", "osool", "abdennour", "abuhaty", "world"], "description": "'world' is added by the World Cuisines project."}, "MasterIngredient": {"type": "object", "required": ["id", "name", "standardAmount", "category"], "properties": {"id": {"type": "string", "pattern": "^[a-z0-9-]+-i[0-9]+$"}, "name": {"type": "string", "description": "Arabic display name."}, "nameEn": {"type": "string"}, "standardAmount": {"type": "string", "description": "Free-text amount in Arabic, e.g. '3 أكواب'. Not machine-parsed today; Cookwala adds SI quantities."}, "category": {"$ref": "#/$defs/IngredientCategory"}, "sourceVariations": {"type": "object"}, "isMerged": {"type": "boolean"}, "originalOccurrencesCount": {"type": "integer"}}}, "UniqueInstruction": {"type": "object", "required": ["stepNumber", "text"], "properties": {"stepNumber": {"type": "integer", "minimum": 1}, "text": {"type": "string"}, "phase": {"enum": ["prep", "cook", "finish", "alternative"]}, "importance": {"enum": ["core", "tip", "variation"]}, "isAlternative": {"type": "boolean"}, "sourceDocs": {"type": "array"}}}, "Source": {"type": "object", "required": ["name", "url"], "properties": {"name": {"type": "string"}, "url": {"type": "string"}, "collection": {"$ref": "#/$defs/Collection"}, "citation": {"type": "string"}}}, "Recipe": {"type": "object", "required": ["id", "title", "chapter", "chapterNumber", "category", "masterIngredients", "uniqueInstructions"], "properties": {"id": {"type": "string", "description": "Stable site id, e.g. meat-01, add-001, osool-433, ec-124, fah-234, w-ma-001."}, "title": {"type": "string", "description": "Arabic title (site base language)."}, "titleEn": {"type": "string"}, "chapter": {"type": "string"}, "chapterNumber": {"type": "integer"}, "category": {"type": "string"}, "cookingMethod": {"type": "string"}, "prepTime": {"type": "string", "description": "Free text, e.g. '15 دقيقة'."}, "cookTime": {"type": "string"}, "servings": {"type": "string"}, "difficulty": {"enum": ["easy", "medium", "hard"]}, "masterIngredients": {"type": "array", "items": {"$ref": "#/$defs/MasterIngredient"}}, "uniqueInstructions": {"type": "array", "items": {"$ref": "#/$defs/UniqueInstruction"}}, "culturalNotes": {"type": "string"}, "source": {"$ref": "#/$defs/Source"}, "englishOnly": {"type": "boolean"}, "overlapAnalysis": {"type": "object"}, "rawDocVersions": {"type": "object"}}}, "Estimate": {"type": "object", "description": "Per-serving nutrition and whole-recipe USD cost (src/data/recipeEstimates.ts).", "required": ["servings", "kcal", "protein", "fat", "carbs", "cost"], "properties": {"servings": {"type": "number"}, "kcal": {"type": "integer"}, "protein": {"type": "integer"}, "fat": {"type": "integer"}, "carbs": {"type": "integer"}, "fiber": {"type": "integer"}, "sugar": {"type": "integer"}, "cost": {"type": "object", "propertyNames": {"enum": ["protein", "dairyEggs", "produce", "grains", "fats", "sweeteners", "specialty", "spices"]}, "additionalProperties": {"type": "number"}}}}, "RecipeTranslation": {"type": "object", "properties": {"title": {"type": "string"}, "chapter": {"type": "string"}, "category": {"type": "string"}, "cookingMethod": {"type": "string"}, "prepTime": {"type": "string"}, "cookTime": {"type": "string"}, "servings": {"type": "string"}, "culturalNotes": {"type": "string"}, "ingredients": {"type": "object", "additionalProperties": {"type": "object", "properties": {"name": {"type": "string"}, "standardAmount": {"type": "string"}}}}, "instructions": {"type": "object", "description": "Keyed by stepNumber as a string.", "additionalProperties": {"type": "string"}}}}, "RecipeFile": {"type": "object", "description": "GET /data/recipes/{id}.json", "required": ["recipe"], "properties": {"recipe": {"$ref": "#/$defs/Recipe"}, "estimate": {"$ref": "#/$defs/Estimate"}, "translations": {"type": "object", "description": "Keyed by language code (24 site languages).", "additionalProperties": {"$ref": "#/$defs/RecipeTranslation"}}}}, "IndexCard": {"type": "object", "required": ["id", "title", "chapterNumber", "collection"], "properties": {"id": {"type": "string"}, "title": {"type": "string"}, "titleEn": {"type": "string"}, "chapter": {"type": "string"}, "chapterNumber": {"type": "integer"}, "category": {"type": "string"}, "cookingMethod": {"type": "string"}, "prepTime": {"type": "string"}, "cookTime": {"type": "string"}, "servings": {"type": "string"}, "imageUrl": {"type": "string"}, "collection": {"$ref": "#/$defs/Collection"}, "arabicOnly": {"type": "boolean"}, "englishOnly": {"type": "boolean"}, "ingredientCount": {"type": "integer"}, "stepCount": {"type": "integer"}, "overlapPercentage": {"type": "integer"}, "previewIngredients": {"type": "array", "items": {"type": "object", "properties": {"id": {"type": "string"}, "name": {"type": "string"}, "nameEn": {"type": "string"}}}}}}, "IndexPage": {"description": "GET /data/index/{page}.json (100 cards per page)", "type": "array", "items": {"$ref": "#/$defs/IndexCard"}}, "SearchMap": {"description": "GET /data/search/{lang}.json: recipe id → normalized searchable text", "type": "object", "additionalProperties": {"type": "string"}}, "IngredientList": {"description": "GET /data/ingredients/{lang}.json", "type": "array", "items": {"type": "object", "properties": {"id": {"type": "string"}, "name": {"type": "string"}, "nameEn": {"type": "string"}, "localizedName": {"type": "string"}, "sourceRecipeId": {"type": "string"}, "category": {"$ref": "#/$defs/IngredientCategory"}, "recipesCount": {"type": "integer"}, "recipeTitles": {"type": "array", "items": {"type": "object", "properties": {"id": {"type": "string"}, "title": {"type": "string"}, "standardAmount": {"type": "string"}}}}}}}, "Manifest": {"description": "GET /data/manifest.json", "type": "object", "required": ["version", "pageSize", "pageCount", "total"], "properties": {"version": {"type": "string", "description": "Content hash; append ?v=<version> to other requests."}, "pageSize": {"type": "integer"}, "pageCount": {"type": "integer"}, "total": {"type": "integer"}, "stats": {"type": "object", "description": "Per-language database statistics."}}}}}, "https://cookwala.ai/v1/schemas/market.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/market.schema.json", "title": "Cookwala Market (providers, offers, quotes)", "x-cookwala-status": "experimental", "description": "Lets grocers, ingredient suppliers, restaurants, meal-kit makers, robot and cookware makers, chefs and recipe publishers, certifiers, repairers, energy and delivery services, and extension/AI vendors publish who they are and what they offer, so kitchens, robots and agents can discover them through the protocol. Cookwala defines discovery and description only: price negotiation, checkout and payment go through the provider's own systems or open commerce protocols (UCP, ACP, AP2). No payment credentials ever travel in Cookwala documents. Use $defs Provider, Offer, OfferFeed, QuoteRequest, Quote.", "$defs": {"Role": {"enum": ["grocer", "ingredient_supplier", "farm", "butcher", "fishmonger", "bakery", "restaurant", "cloud_kitchen", "caterer", "meal_kit", "robot_maker", "appliance_maker", "cookware_maker", "robot_rental", "robot_operator", "repair_service", "recipe_publisher", "chef", "nutritionist", "cooking_school", "certifier", "food_safety_auditor", "lab", "delivery", "energy_provider", "extension_vendor", "ai_model_vendor", "hub_vendor", "catalog_host", "marketplace_operator", "other", "food_bank", "humanitarian_org", "community_kitchen", "school_feeding_program", "donor", "volunteer_group", "government_agency", "logistics"]}, "Credential": {"type": "object", "required": ["type", "issuer"], "description": "A claim such as halal/kosher/organic certification, food business license or safety certification, ideally as a W3C Verifiable Credential.", "properties": {"type": {"type": "string", "description": "e.g. halal_certified, kosher_certified, organic, food_business_license, iso_22000, haccp, iec_60335, iso_13482, cookwala_conformance:executor."}, "issuer": {"type": "string"}, "subject": {"type": "string"}, "validFrom": {"type": "string", "format": "date"}, "validUntil": {"type": "string", "format": "date"}, "vc": {"type": "string", "description": "URL of a W3C Verifiable Credential (JWT or JSON-LD) proving the claim."}, "verified": {"type": "boolean", "description": "Set by the index/hub after checking the VC; never trusted from the provider itself."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Area": {"type": "object", "properties": {"countries": {"type": "array", "items": {"type": "string"}}, "postalCodes": {"type": "array", "items": {"type": "string"}}, "radiusKm": {"type": "number"}, "center": {"type": "object", "properties": {"lat": {"type": "number"}, "lon": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "online": {"type": "boolean"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Pricing": {"type": "object", "properties": {"model": {"enum": ["free", "one_time", "per_unit", "per_use", "subscription", "quote", "donation"]}, "price": {"$ref": "common.schema.json#/$defs/Money"}, "unit": {"type": "string"}, "period": {"type": "string"}, "validUntil": {"$ref": "common.schema.json#/$defs/DateTime"}, "taxIncluded": {"type": "boolean"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Provider": {"type": "object", "required": ["cookwala", "id", "name", "roles"], "properties": {"cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "id": {"type": "string", "description": "Stable id, ideally a domain or DID (did:web:grocer.example)."}, "name": {"type": "string"}, "roles": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/Role"}}, "description": {"$ref": "common.schema.json#/$defs/LangMap"}, "url": {"type": "string"}, "contact": {"type": "string"}, "area": {"$ref": "#/$defs/Area"}, "credentials": {"type": "array", "items": {"$ref": "#/$defs/Credential"}}, "endpoints": {"type": "object", "description": "How to reach the provider's own systems.", "properties": {"offers": {"type": "string", "description": "OfferFeed URL."}, "ucp": {"type": "string"}, "acp": {"type": "string"}, "a2a": {"type": "string"}, "mcp": {"type": "string"}, "catalog": {"type": "string", "description": "Cookwala recipe catalog the provider publishes (chefs, meal kits, restaurants)."}, "quotes": {"type": "string"}, "support": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "standards": {"type": "array", "items": {"type": "string"}, "description": "Other standards they follow (GS1, schema.org/Product, Matter, UCP...), to help bridging."}, "meta": {"$ref": "common.schema.json#/$defs/Meta"}}, "patternProperties": {"^x-": {}}, "unevaluatedProperties": false}, "Offer": {"type": "object", "required": ["id", "provider", "type", "title"], "properties": {"id": {"type": "string"}, "provider": {"type": "string"}, "type": {"enum": ["ingredient", "grocery_bundle", "meal_kit", "ready_meal", "recipe_pack", "cooking_class", "robot", "robot_rental", "robot_service", "appliance", "cookware", "spare_part", "repair", "extension", "ai_model", "hub", "catalog_hosting", "certification", "audit", "delivery", "energy_plan", "other", "surplus_food", "donated_meal", "sponsored_meal", "kitchen_capacity", "volunteer_service", "cold_storage"]}, "title": {"$ref": "common.schema.json#/$defs/LangMap"}, "description": {"$ref": "common.schema.json#/$defs/LangMap"}, "ingredientId": {"type": "string", "description": "For ingredients: the cw.ing id this product fulfils."}, "gtin": {"type": "string"}, "pack": {"$ref": "common.schema.json#/$defs/Quantity"}, "recipeIds": {"type": "array", "items": {"$ref": "common.schema.json#/$defs/GlobalRef"}, "description": "Meal kits, ready meals and recipe packs map to Cookwala recipes, so a kitchen can choose cook-it-yourself vs buy-it-ready."}, "deviceClasses": {"type": "array", "items": {"type": "string"}, "description": "For robots/appliances/cookware: classes and the capability manifest they ship with."}, "capabilities": {"type": "string", "description": "URL of the product's capability manifest (robots/appliances)."}, "cookware": {"$ref": "profile.schema.json#/$defs/CookwareItem"}, "dietary": {"type": "array", "items": {"type": "string"}}, "allergens": {"type": "array", "items": {"type": "string"}}, "credentials": {"type": "array", "items": {"$ref": "#/$defs/Credential"}}, "pricing": {"$ref": "#/$defs/Pricing"}, "availability": {"type": "object", "properties": {"inStock": {"type": "boolean"}, "qty": {"type": "number"}, "leadTime": {"$ref": "common.schema.json#/$defs/Duration"}, "slots": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "area": {"$ref": "#/$defs/Area"}, "fulfillment": {"type": "array", "items": {"enum": ["delivery", "pickup", "robot_receive", "digital", "on_site"]}}, "sustainability": {"type": "object", "properties": {"co2eKg": {"type": "number"}, "local": {"type": "boolean"}, "packaging": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "license": {"type": "string", "description": "For recipe packs/extensions/models: usage license (may be proprietary)."}, "sponsored": {"type": "boolean", "description": "Must be true when placement was paid; indexes must disclose it."}, "checkout": {"type": "object", "properties": {"protocol": {"enum": ["ucp", "acp", "provider_site", "quote", "free"]}, "url": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "meta": {"$ref": "common.schema.json#/$defs/Meta"}}, "patternProperties": {"^x-": {}}, "unevaluatedProperties": false}, "OfferFeed": {"type": "object", "required": ["cookwala", "provider", "updatedAt", "offers"], "properties": {"cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "provider": {"$ref": "#/$defs/Provider"}, "updatedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "offers": {"type": "array", "items": {"$ref": "#/$defs/Offer"}}, "next": {"type": "string"}, "signature": {"$ref": "common.schema.json#/$defs/Signature"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "QuoteRequest": {"type": "object", "required": ["cookwala", "id", "need"], "description": "A kitchen/agent asks providers for prices without revealing personal data (e.g. catering for 80 people, halal lamb 5 kg, robot rental for an event).", "properties": {"cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "id": {"type": "string"}, "need": {"type": "object", "properties": {"offerTypes": {"type": "array", "items": {"type": "string"}}, "lines": {"type": "array", "items": {"type": "object", "properties": {"ingredientId": {"type": "string"}, "recipeId": {"type": "string"}, "qty": {"$ref": "common.schema.json#/$defs/Quantity"}, "servings": {"type": "number"}, "constraints": {"type": "object"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "by": {"$ref": "common.schema.json#/$defs/DateTime"}, "area": {"$ref": "#/$defs/Area"}, "budget": {"$ref": "common.schema.json#/$defs/Money"}, "credentialsRequired": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "replyTo": {"type": "string"}, "expires": {"$ref": "common.schema.json#/$defs/DateTime"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Quote": {"type": "object", "required": ["cookwala", "requestId", "provider", "lines", "total"], "properties": {"cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "requestId": {"type": "string"}, "provider": {"type": "string"}, "lines": {"type": "array", "items": {"type": "object", "properties": {"offerId": {"type": "string"}, "qty": {"type": "number"}, "price": {"$ref": "common.schema.json#/$defs/Money"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "total": {"$ref": "common.schema.json#/$defs/Money"}, "validUntil": {"$ref": "common.schema.json#/$defs/DateTime"}, "checkout": {"type": "object", "properties": {"protocol": {"type": "string"}, "url": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "signature": {"$ref": "common.schema.json#/$defs/Signature"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}}, "https://cookwala.ai/v1/schemas/mission.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/mission.schema.json", "title": "Cookwala Mission", "x-cookwala-status": "experimental", "description": "The shared, signed, living document of the Cookwala Protocol (docs/PROTOCOL.md): intent, mandate, context facets, credentials, routing, requirements with criticality, fallbacks (PACE), decision rights, escalation, contributions with commitment lifecycle, the bound plan, execution, outcome and a hash-chained ledger. Decision governance is described in docs/DECISIONS.md.", "type": "object", "required": ["cookwala", "id", "header", "intent", "mandate", "requirements", "decisionRights", "state", "ledger"], "properties": {"cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "id": {"type": "string", "description": "Stable URI-able id (e.g. cw:mission:<uuid>)."}, "header": {"type": "object", "required": ["type", "createdAt", "holder"], "properties": {"type": {"enum": ["home_meal", "meal_plan", "event", "restaurant_service", "production_run", "school_meals", "relief_kitchen", "packed_meals", "delivery", "custom"]}, "createdAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "holder": {"type": "string", "description": "DID of the party that owns the Mission (usually the robot acting for the household); only the holder accepts contributions and closes the Mission."}, "owner": {"type": "string", "description": "DID of the human/organization the holder acts for."}, "jurisdiction": {"type": "string"}, "parent": {"type": "string", "description": "Parent Mission (e.g. a relief program Mission)."}, "deadline": {"$ref": "common.schema.json#/$defs/DateTime"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "intent": {"type": "object", "required": ["summary"], "properties": {"summary": {"$ref": "common.schema.json#/$defs/LangMap"}, "goals": {"type": "array", "items": {"type": "string"}}, "commandersIntent": {"$ref": "common.schema.json#/$defs/LangMap", "description": "What matters most if the plan breaks (e.g. 'a safe, warm halal dinner for 5 by 19:30; cost matters more than variety')."}, "priorities": {"type": "array", "items": {"enum": ["human_safety", "animal_safety", "food_safety", "property", "mandate", "time", "quality", "cost", "waste", "energy"]}, "description": "Order after the fixed safety prefix; the first three are always first."}, "advice": {"$ref": "advice.schema.json#/$defs/AdviceRequest", "description": "Structured request when the intent maps to a reasoner intent."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "mandate": {"type": "object", "description": "What the holder may do and decide.", "properties": {"tasks": {"type": "array", "items": {"enum": ["cook", "prep", "clean_dishes", "clean_floor", "fetch_supplies", "open_door_for_delivery", "receive_delivery", "take_out_trash", "set_table", "serve_to_table", "serve_to_room", "pack_food", "order_groceries", "garden_pick", "remind_people", "care_for_pets_food"]}}, "zones": {"type": "array", "items": {"type": "string"}}, "stairs": {"type": "boolean"}, "hardNos": {"type": "array", "items": {"type": "string"}}, "caution": {"enum": ["extra_slow", "normal", "relaxed"]}, "autonomyLevel": {"enum": ["CA0", "CA1", "CA2", "CA3", "CA4", "CA5"]}, "spendingLimit": {"$ref": "common.schema.json#/$defs/Money"}, "mayAddParties": {"type": "array", "items": {"type": "string"}, "description": "Providers/people the holder may bring into the flow."}, "authority": {"type": "array", "items": {"type": "object", "required": ["who", "level"], "properties": {"who": {"type": "string"}, "level": {"type": "integer", "minimum": 0, "maximum": 10}, "scopes": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "description": "Whose instructions win (higher level wins within scope)."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "context": {"type": "object", "properties": {"facets": {"type": "array", "items": {"$ref": "#/$defs/Facet"}}, "profiles": {"type": "array", "items": {"$ref": "common.schema.json#/$defs/GlobalRef"}}, "mode": {"$ref": "profile.schema.json#/$defs/OperatingMode"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "credentials": {"type": "array", "items": {"type": "object", "required": ["type", "vc"], "properties": {"type": {"type": "string"}, "vc": {"type": "string"}, "selective": {"type": "boolean"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "routing": {"type": "object", "properties": {"topology": {"enum": ["direct", "chain", "orchestrated", "swarm", "hybrid"]}, "orchestrator": {"type": "string"}, "providers": {"type": "array", "items": {"$ref": "#/$defs/ProviderSlot"}}, "maxHops": {"type": "integer", "minimum": 1}, "budget": {"$ref": "common.schema.json#/$defs/Money"}, "groups": {"type": "array", "description": "Provider groups that share capabilities (consortia, ensembles, partner networks).", "items": {"type": "object", "required": ["id", "members"], "properties": {"id": {"type": "string"}, "members": {"type": "array", "items": {"type": "string"}}, "sharedCapabilities": {"type": "array", "items": {"type": "string"}}, "mode": {"enum": ["each_independent", "group_consensus", "leader_with_reviewers"], "description": "Each member answers independently, the group returns one agreed answer, or a leader answers and others review."}, "leader": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "requirements": {"type": "array", "items": {"$ref": "#/$defs/Requirement"}}, "readiness": {"type": "object", "description": "Definition of ready: execution may start only when every listed requirement is satisfied (or resolved by an allowed fallback) and the safety kernel passes.", "properties": {"requires": {"type": "array", "items": {"type": "string"}}, "minConfidence": {"type": "number"}, "deadline": {"$ref": "common.schema.json#/$defs/DateTime"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "decisionRights": {"type": "array", "items": {"$ref": "#/$defs/DecisionRight"}}, "escalation": {"type": "array", "items": {"$ref": "#/$defs/EscalationStep"}}, "contributions": {"type": "array", "items": {"$ref": "#/$defs/Contribution"}}, "decisions": {"type": "array", "items": {"$ref": "#/$defs/Decision"}}, "plan": {"type": "object", "properties": {"recipes": {"type": "array", "items": {"type": "object", "properties": {"recipe": {"$ref": "common.schema.json#/$defs/GlobalRef"}, "hash": {"$ref": "common.schema.json#/$defs/Hash"}, "servings": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "session": {"$ref": "session.schema.json", "description": "Bound plan (R4): tasks, leases, handoffs."}, "contingencies": {"type": "array", "items": {"type": "object", "properties": {"on": {"type": "string"}, "do": {"type": "string"}, "playbook": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "invariants": {"type": "array", "items": {"type": "string"}}, "monitors": {"type": "array", "items": {"type": "object", "properties": {"who": {"type": "string"}, "signal": {"type": "string"}, "everyS": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "execution": {"type": "object", "properties": {"progress": {"type": "number", "minimum": 0, "maximum": 1}, "log": {"type": "array", "items": {"type": "object", "properties": {"at": {"$ref": "common.schema.json#/$defs/DateTime"}, "by": {"type": "string"}, "kind": {"enum": ["progress", "deviation", "interruption", "decision", "comment", "lesson", "issue"]}, "text": {"type": "string"}, "ref": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "outcome": {"type": "object", "properties": {"result": {"enum": ["success", "success_degraded", "partial", "failed", "aborted_safety", "aborted_by_human", "cancelled"]}, "requirementsMet": {"type": "array", "items": {"type": "string"}}, "requirementsDropped": {"type": "array", "items": {"type": "string"}}, "consumedPct": {"type": "number"}, "wasteG": {"type": "number"}, "costActual": {"$ref": "common.schema.json#/$defs/Money"}, "feedback": {"type": "array", "items": {"type": "string"}}, "lessons": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "state": {"enum": ["draft", "open", "enriching", "ready", "committed", "executing", "paused", "degraded", "closing", "closed", "failed", "cancelled"]}, "closure": {"$ref": "#/$defs/Closure"}, "ledger": {"type": "array", "items": {"$ref": "#/$defs/LedgerEntry"}}, "meta": {"$ref": "common.schema.json#/$defs/Meta"}, "budgets": {"type": "array", "items": {"$ref": "#/$defs/Budget"}, "description": "Guardrails for cost, time, energy, retries, hops, data disclosure, human attention. Tracked live from contributions, meters and execution; thresholds trigger actions automatically."}, "meters": {"type": "array", "items": {"$ref": "#/$defs/MeterEntry"}, "description": "Accruals against budgets (each also recorded in the ledger)."}, "roles": {"type": "array", "items": {"type": "object", "required": ["role", "who"], "properties": {"role": {"enum": ["holder", "owner", "budget_controller", "orchestrator", "arbiter", "provider", "monitor", "approver", "safety_kernel", "auditor", "executor"]}, "who": {"type": "string"}, "scope": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "description": "Who plays which role in this Mission (see docs/DECISIONS.md)."}, "degradations": {"type": "array", "items": {"$ref": "#/$defs/Degradation"}, "description": "What is not working fully right now (robot, environment, devices, connectivity). Declared by the holder or observed by monitors."}, "adaptations": {"type": "array", "items": {"$ref": "#/$defs/Adaptation"}, "description": "How the plan is adjusted to the degradations, by whom, with which accepted deviations from the normal dish."}, "assessments": {"type": "array", "items": {"$ref": "#/$defs/Assessment"}}, "reconcileRules": {"type": "array", "items": {"$ref": "#/$defs/ReconcileRule"}}, "reconciliations": {"type": "array", "items": {"$ref": "#/$defs/Reconciliation"}}, "eventLog": {"type": "object", "required": ["headSeq", "head"], "unevaluatedProperties": false, "description": "Where the authoritative event log lives and which head this projection was derived from.", "properties": {"uri": {"type": "string", "format": "uri"}, "sequencer": {"type": "string"}, "headSeq": {"type": "integer", "minimum": 0}, "head": {"$ref": "common.schema.json#/$defs/Hash"}, "mode": {"enum": ["full", "hash_only"]}}}, "checkpoints": {"type": "array", "items": {"$ref": "#/$defs/Checkpoint"}}}, "patternProperties": {"^x-": {}}, "$defs": {"Facet": {"type": "object", "required": ["facet", "subject", "value", "source", "observedAt", "privacy"], "properties": {"facet": {"$ref": "common.schema.json#/$defs/VocabId"}, "subject": {"type": "string"}, "value": {}, "summary": {"type": "string"}, "source": {"type": "object", "required": ["kind"], "properties": {"kind": {"enum": ["declared", "observed", "reported", "inferred"]}, "actor": {"type": "string"}, "evidence": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "observedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "validFor": {"$ref": "common.schema.json#/$defs/Duration"}, "confidence": {"type": "number", "minimum": 0, "maximum": 1}, "privacy": {"enum": ["public", "household", "sensitive", "secret"]}, "consent": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "ProviderSlot": {"type": "object", "required": ["role", "candidates"], "description": "A role in the flow with ordered candidates (primary → alternates), what each may see and do.", "properties": {"role": {"type": "string", "description": "e.g. planner, grocer, delivery, monitor, arbiter:substitution, nutrition, orchestrator."}, "candidates": {"type": "array", "items": {"type": "object", "required": ["provider"], "properties": {"provider": {"type": "string"}, "tier": {"type": "string"}, "pace": {"enum": ["primary", "alternate", "contingency", "emergency"]}, "endpoint": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "view": {"type": "array", "items": {"type": "string"}, "description": "Facet types disclosed to this role."}, "capabilityToken": {"type": "string", "description": "Delegated, attenuated authorization (UCAN/ZCAP-style)."}, "mayForward": {"type": "boolean"}, "timeoutS": {"type": "number"}, "hedge": {"type": "boolean", "description": "Ask alternates in parallel when latency matters; first valid answer wins."}, "capabilities": {"type": "array", "items": {"type": "string"}, "description": "Capability tags this role covers, e.g. estimate:robot_energy, estimate:duration, assess:criticality. Several roles/providers may share a tag; their outputs become competing assessments."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Criticality": {"enum": ["critical", "required", "preferred", "optional"], "description": "critical: must be met exactly, never traded, failure blocks the Mission (allergen-free, halal, CCPs, child safety). required: must be met, but approved alternatives (plan B/C) are allowed. preferred: degrade gracefully; record the loss. optional: drop silently if unavailable; log only."}, "Requirement": {"type": "object", "required": ["id", "what", "criticality"], "properties": {"id": {"type": "string"}, "what": {"type": "string", "description": "e.g. ingredient:eggs, dietary:halal, allergen_free:peanuts, serve_by:19:30, budget<=40USD, dish_identity, delivery:groceries, device:oven."}, "criticality": {"$ref": "#/$defs/Criticality"}, "source": {"type": "string", "description": "Who set it: owner, recipe identity, policy pack, clinician, mode."}, "fallbacks": {"$ref": "#/$defs/Pace"}, "decidedBy": {"type": "string", "description": "Decision class governing changes to it (see decisionRights)."}, "status": {"enum": ["open", "satisfied", "satisfied_by_fallback", "dropped", "violated", "blocked"]}, "satisfiedBy": {"type": "string", "description": "Contribution or decision id."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Pace": {"type": "object", "description": "Primary, Alternate, Contingency, Emergency (military PACE planning): ordered plan A/B/C/D for one requirement, step or the whole Mission.", "properties": {"primary": {"$ref": "#/$defs/Fallback"}, "alternate": {"$ref": "#/$defs/Fallback"}, "contingency": {"$ref": "#/$defs/Fallback"}, "emergency": {"$ref": "#/$defs/Fallback"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Fallback": {"type": "object", "properties": {"action": {"type": "string", "description": "e.g. substitute:cw.ing.turmeric, provider:did:web:grocer-b, method:pressure_cook, dish:w-ma-012, order:ready_meal, drop, delay:PT30M, ask:owner."}, "trigger": {"type": "string", "description": "When to switch: timeout, unavailable, failed_check, budget_exceeded, quality_below."}, "impact": {"type": "object", "properties": {"quality": {"type": "string"}, "extraCost": {"$ref": "common.schema.json#/$defs/Money"}, "extraTime": {"$ref": "common.schema.json#/$defs/Duration"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "needsApproval": {"type": "string", "description": "Decision class or actor that must approve before switching."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "DecisionRight": {"type": "object", "required": ["class", "decider"], "description": "Who may decide what. Evaluated top-down; the first matching rule applies. Safety-class decisions can never be granted solely to a remote provider.", "properties": {"class": {"enum": ["substitute_ingredient", "drop_optional", "drop_preferred", "change_method", "change_dish", "change_provider", "spend_more", "delay", "reschedule", "discard_food", "salvage", "serve_degraded", "abort_mission", "contact_emergency", "share_more_data", "accept_offer", "criticality_assessment", "custom", "budget_increase", "deadline_extension", "reduce_scope", "accept_deviation", "lower_autonomy", "request_assist", "recharge_plan", "handoff_task", "reconcile"]}, "decider": {"enum": ["holder", "arbiter", "orchestrator", "provider", "quorum", "household_human", "named_human", "safety_kernel"]}, "who": {"type": "array", "items": {"type": "string"}, "description": "Specific DIDs/roles (e.g. arbiter providers, 'parent')."}, "limits": {"type": "object", "description": "Thresholds under which the decider may act alone, e.g. {\"extraCost\": {\"amount\": 3, \"currency\": \"USD\"}, \"quality\": \"minor\", \"delay\": \"PT15M\"}.", "additionalProperties": true}, "quorum": {"type": "object", "properties": {"of": {"type": "integer"}, "need": {"type": "integer"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "beyondLimits": {"type": "string", "description": "Decision class/actor to escalate to when limits are exceeded."}, "timeout": {"$ref": "common.schema.json#/$defs/Duration"}, "onTimeout": {"enum": ["take_default", "take_safest", "escalate", "abort"]}, "default": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "EscalationStep": {"type": "object", "required": ["level", "to"], "properties": {"level": {"type": "integer", "minimum": 0}, "to": {"type": "string", "description": "holder | arbiter:<class> | orchestrator | household:<person/role> | maker_support | service_provider | emergency_services."}, "when": {"type": "array", "items": {"type": "string"}}, "channel": {"type": "array", "items": {"type": "string"}}, "waitFor": {"$ref": "common.schema.json#/$defs/Duration"}, "then": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Contribution": {"type": "object", "required": ["id", "by", "role", "kind", "status", "createdAt"], "description": "What a provider adds. Lifecycle: offered → accepted/rejected (by holder) → committed (binding, with SLA) → in_progress → fulfilled | partially_fulfilled | failed | withdrawn | superseded | compensated.", "properties": {"id": {"type": "string"}, "by": {"type": "string"}, "role": {"type": "string"}, "kind": {"enum": ["facet", "advice", "plan", "quote", "offer", "order", "delivery", "monitor", "decision", "approval", "review", "custom", "assessment"]}, "satisfies": {"type": "array", "items": {"type": "string"}, "description": "Requirement ids."}, "body": {"description": "Typed payload (AdviceResponse, TeamPlan, Quote, OrderIntent...)."}, "bodySchema": {"type": "string"}, "binding": {"enum": ["informational", "advisory", "binding_offer", "commitment"]}, "sla": {"type": "object", "properties": {"deliverBy": {"$ref": "common.schema.json#/$defs/DateTime"}, "availability": {"type": "string"}, "penalty": {"type": "string"}, "insurer": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "status": {"enum": ["offered", "accepted", "rejected", "committed", "in_progress", "fulfilled", "partially_fulfilled", "failed", "withdrawn", "superseded", "compensated"]}, "failure": {"$ref": "#/$defs/Failure"}, "compensation": {"type": "string", "description": "Action that undoes/offsets this contribution if the Mission changes (cancel order, release slot, refund) — saga pattern."}, "idempotencyKey": {"type": "string"}, "createdAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "hash": {"$ref": "common.schema.json#/$defs/Hash"}, "signature": {"$ref": "common.schema.json#/$defs/Signature"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Failure": {"type": "object", "required": ["code", "retryable"], "properties": {"code": {"enum": ["timeout", "unavailable", "out_of_stock", "capability_mismatch", "policy_denied", "safety_denied", "budget_exceeded", "invalid_input", "insufficient_context", "conflict", "internal_error", "rate_limited", "subscription_inactive", "custom"]}, "retryable": {"type": "boolean"}, "retryAfter": {"$ref": "common.schema.json#/$defs/Duration"}, "partial": {"description": "Whatever could still be provided."}, "needs": {"type": "array", "items": {"type": "string"}, "description": "Missing facets/permissions that would let it succeed."}, "suggest": {"type": "array", "items": {"type": "string"}, "description": "Suggested alternates/fallbacks."}, "message": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Decision": {"type": "object", "required": ["id", "class", "by", "choice", "at"], "properties": {"id": {"type": "string"}, "class": {"type": "string"}, "about": {"type": "array", "items": {"type": "string"}, "description": "Requirement/contribution/task ids."}, "by": {"type": "string"}, "basis": {"enum": ["decision_right", "quorum", "fallback_rule", "default_on_timeout", "safety_kernel", "human"]}, "options": {"type": "array", "items": {"type": "string"}}, "choice": {"type": "string"}, "rationale": {"type": "string"}, "confidence": {"type": "number"}, "votes": {"type": "array", "items": {"type": "object", "properties": {"by": {"type": "string"}, "choice": {"type": "string"}, "confidence": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "verifiedBy": {"type": "string", "description": "Usually the holder's safety kernel."}, "at": {"$ref": "common.schema.json#/$defs/DateTime"}, "signature": {"$ref": "common.schema.json#/$defs/Signature"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Closure": {"type": "object", "description": "How the Mission ends: every committed contribution is fulfilled, failed-and-compensated or released; the holder signs the final receipt; settlements are recorded.", "properties": {"closedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "byHolder": {"$ref": "common.schema.json#/$defs/Signature"}, "participants": {"type": "array", "items": {"type": "object", "properties": {"who": {"type": "string"}, "contributions": {"type": "array", "items": {"type": "string"}}, "final": {"enum": ["fulfilled", "partially_fulfilled", "failed", "compensated", "released"]}, "settlement": {"type": "string"}, "rating": {"type": "integer", "minimum": 1, "maximum": 5}, "signature": {"$ref": "common.schema.json#/$defs/Signature"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "ledgerHead": {"$ref": "common.schema.json#/$defs/Hash"}, "anchoredAt": {"type": "string", "description": "Transparency log / blockchain anchoring reference, if any."}, "calibration": {"type": "array", "description": "Predicted vs actual per assessment; updates provider calibration and reputation.", "items": {"type": "object", "properties": {"assessment": {"type": "string"}, "by": {"type": "string"}, "predicted": {}, "actual": {}, "withinInterval": {"type": "boolean"}, "error": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "LedgerEntry": {"type": "object", "required": ["seq", "at", "actor", "action", "prev"], "description": "Append-only, hash-chained, signed. Modeled on EPCIS event dimensions (what, when, where, why, who). Deprecated in favour of MissionEvent (same fields plus hash); kept for 0.1 documents.", "properties": {"seq": {"type": "integer", "minimum": 0}, "at": {"$ref": "common.schema.json#/$defs/DateTime"}, "actor": {"type": "string"}, "action": {"enum": ["created", "facet_added", "view_granted", "contribution_offered", "contribution_accepted", "contribution_rejected", "committed", "progress", "fulfilled", "failed", "withdrawn", "compensated", "decision", "escalated", "approved", "state_changed", "closed", "custom", "assessment", "reconciled"]}, "ref": {"type": "string"}, "why": {"type": "string"}, "where": {"type": "string"}, "contentHash": {"$ref": "common.schema.json#/$defs/Hash"}, "prev": {"type": "string", "description": "Hash of the previous entry ('genesis' for seq 0)."}, "signature": {"$ref": "common.schema.json#/$defs/Signature"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Budget": {"type": "object", "required": ["id", "kind", "limit", "controller"], "properties": {"id": {"type": "string"}, "kind": {"enum": ["cost", "time", "energy", "gas", "water", "robot_battery", "retries", "provider_calls", "hops", "data_disclosure", "human_attention", "waste", "custom"]}, "scope": {"type": "string", "description": "Whole mission, a requirement, a step, a provider role or a provider (e.g. 'mission', 'role:grocer', 'step:n7')."}, "unit": {"type": "string", "description": "Currency code, ISO 8601 duration ('time'), kWh, MJ, L, pct, count, minutes."}, "limit": {"description": "Hard limit (number, Money or Duration/DateTime for time)."}, "plan": {"description": "Planned/baseline amount (from the bound plan)."}, "thresholds": {"type": "array", "items": {"type": "object", "required": ["at", "action"], "properties": {"at": {"type": "number", "description": "Fraction of limit (0.8 = 80%) or of forecast overrun."}, "on": {"enum": ["actual", "forecast"], "default": "forecast", "description": "Trigger on spent-so-far or on estimate-at-completion."}, "action": {"enum": ["log", "notify", "require_approval", "switch_fallback", "cheaper_mode", "reduce_scope", "pause", "escalate", "abort"]}, "to": {"type": "string", "description": "Who is notified/asked (decision class, role or person)."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "controller": {"type": "string", "description": "Who tracks and enforces it: holder (default), orchestrator (delegated), or budget_controller provider. The holder's kernel enforces hard limits regardless."}, "status": {"type": "object", "properties": {"spent": {"description": "Actual so far."}, "committed": {"description": "Committed but not yet spent (e.g. accepted orders)."}, "forecastAtCompletion": {"description": "Estimate at completion (spent + committed + remaining plan)."}, "variance": {"type": "number", "description": "(forecast - plan) / plan."}, "state": {"enum": ["ok", "warning", "over_soft", "over_hard", "frozen"]}, "updatedAt": {"$ref": "common.schema.json#/$defs/DateTime"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "carryOver": {"type": "boolean", "description": "Unspent amount returns to a parent budget (meal plan, week)."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "MeterEntry": {"type": "object", "required": ["budget", "amount", "at", "by"], "properties": {"budget": {"type": "string"}, "amount": {"description": "Number, Money or Duration."}, "kind": {"enum": ["spent", "committed", "released", "forecast_change"]}, "ref": {"type": "string", "description": "Contribution/task/decision causing it."}, "at": {"$ref": "common.schema.json#/$defs/DateTime"}, "by": {"type": "string"}, "signature": {"$ref": "common.schema.json#/$defs/Signature"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Degradation": {"type": "object", "required": ["id", "area", "severity"], "properties": {"id": {"type": "string"}, "area": {"enum": ["vision", "low_light", "glare", "depth_sensing", "touch_force", "gripper", "arm_reach", "mobility", "temperature_sensing", "smell_sensing", "audio", "speech", "compute", "network", "battery", "calibration", "tool_missing", "appliance_fault", "space_constraint", "human_unavailable", "custom"]}, "subject": {"type": "string", "description": "Robot/device/zone affected."}, "severity": {"enum": ["minor", "moderate", "severe", "blocking"]}, "detail": {"type": "string"}, "measured": {"type": "object", "additionalProperties": true, "description": "e.g. {\"visionConfidence\": 0.55, \"lux\": 40, \"gripForceMaxN\": 6}."}, "since": {"$ref": "common.schema.json#/$defs/DateTime"}, "expectedUntil": {"$ref": "common.schema.json#/$defs/DateTime"}, "affects": {"type": "array", "items": {"type": "string"}, "description": "Ops, sensors or cues affected (cw.op.cut, cw.sense.translucent...)."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Adaptation": {"type": "object", "required": ["id", "for", "strategy", "by"], "properties": {"id": {"type": "string"}, "for": {"type": "array", "items": {"type": "string"}, "description": "Degradation ids."}, "strategy": {"enum": ["fix_environment", "substitute_sensing", "borrow_perception", "reassign_task", "human_assist", "remote_assist", "simplify_method", "change_equipment", "widen_safety_margin", "slow_down", "shrink_batch", "change_recipe", "use_preprepared_ingredient", "lower_autonomy", "defer"]}, "by": {"type": "string", "description": "Who proposed/provides it: holder, planner, arbiter, maker extension, another robot, smart-home device, human, teleoperation service."}, "actions": {"type": "array", "items": {"type": "string"}, "description": "e.g. 'turn on hood light (Matter On/Off)', 'use probe cw.sense.core_temp instead of vision cue', 'arm-1 camera streams view of pan', 'coarse chop 20 mm instead of 10 mm'."}, "patch": {"$ref": "advice.schema.json#/$defs/RecipePatch"}, "deviation": {"type": "object", "description": "How the result will differ from the normal dish.", "properties": {"identityPreserved": {"type": "boolean", "description": "Must be true unless a change_dish decision approved otherwise."}, "sensory": {"type": "array", "items": {"type": "string"}, "description": "e.g. 'onions less browned', 'coarser texture', 'slightly overcooked eggs (firm yolks)'."}, "quality": {"enum": ["none", "minor", "noticeable", "major"]}, "nutritionDelta": {"type": "object", "additionalProperties": {"type": "number"}}, "extraTime": {"$ref": "common.schema.json#/$defs/Duration"}, "extraCost": {"$ref": "common.schema.json#/$defs/Money"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "safety": {"type": "string", "description": "Why safety is unchanged or stricter (never looser)."}, "approvedBy": {"type": "string", "description": "Decision id (serve_degraded / change_method) or actor."}, "status": {"enum": ["proposed", "approved", "active", "rejected", "ended"]}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Distribution": {"type": "object", "description": "Uncertainty of an estimate.", "properties": {"p10": {"type": "number"}, "p50": {"type": "number"}, "p90": {"type": "number"}, "mean": {"type": "number"}, "sd": {"type": "number"}, "min": {"type": "number"}, "max": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Assessment": {"type": "object", "required": ["id", "topic", "by", "value", "method", "confidence", "at"], "description": "An opinion, estimate or judgment by a provider (or the robot) on a topic. Multiple providers may assess the same topic; they may agree, refine or disagree.", "properties": {"id": {"type": "string"}, "topic": {"type": "string", "description": "e.g. estimate.robot_energy_pct, estimate.robot_energy_wh, estimate.duration, estimate.cost, estimate.appliance_energy_kwh, assess.safety, assess.criticality, assess.feasibility, assess.doneness, assess.spoilage."}, "subject": {"type": "string", "description": "What it is about: mission, recipe, plan, task, item."}, "by": {"type": "string"}, "group": {"type": "string"}, "value": {"description": "Point value (number/string/object)."}, "unit": {"type": "string"}, "distribution": {"$ref": "#/$defs/Distribution"}, "method": {"enum": ["physics_model", "simulation", "historical_stats", "ml_model", "llm_judgment", "measurement", "vendor_spec", "expert_rule", "human_judgment"]}, "evidence": {"type": "array", "items": {"type": "object", "properties": {"kind": {"enum": ["facet", "media", "telemetry", "history", "spec", "benchmark", "report"]}, "ref": {"type": "string"}, "note": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "assumptions": {"type": "array", "items": {"type": "string"}}, "inputsHash": {"$ref": "common.schema.json#/$defs/Hash", "description": "Hash of the inputs/view it saw, so disagreements caused by different inputs are visible."}, "confidence": {"type": "number", "minimum": 0, "maximum": 1}, "respondsTo": {"type": "string", "description": "Assessment id it reacts to."}, "stance": {"enum": ["independent", "agree", "refine", "disagree"]}, "reason": {"type": "string"}, "calibration": {"type": "object", "description": "Provider's historical accuracy on this topic (claimed; verified by the reconciler from closure data).", "properties": {"n": {"type": "integer"}, "intervalCoverage": {"type": "number"}, "meanAbsError": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "at": {"$ref": "common.schema.json#/$defs/DateTime"}, "signature": {"$ref": "common.schema.json#/$defs/Signature"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "ReconcileRule": {"type": "object", "required": ["topic", "reconciler", "strategy"], "properties": {"topic": {"type": "string", "description": "Topic or prefix (estimate.robot_energy*)."}, "reconciler": {"type": "string", "description": "holder (default), a chosen agent/orchestrator DID, a quorum, or a household human."}, "strategy": {"enum": ["conservative", "calibration_weighted", "evidence_priority", "bayesian_fusion", "median", "quorum", "debate_then_decide", "ask_human"]}, "safetyBias": {"enum": ["worst_case", "p90", "p50"], "description": "For safety/feasibility topics take the cautious quantile (e.g. energy need at p90)."}, "conflictThreshold": {"type": "number", "description": "Relative spread above which assessments count as conflicting (e.g. 0.25)."}, "evidenceOrder": {"type": "array", "items": {"type": "string"}, "description": "Precedence when evidence quality differs, e.g. [measurement, historical_stats, physics_model, vendor_spec, llm_judgment]."}, "maxRounds": {"type": "integer", "description": "Rebuttal/clarification rounds before deciding."}, "timeout": {"$ref": "common.schema.json#/$defs/Duration"}, "onTimeout": {"enum": ["take_conservative", "take_latest", "escalate"]}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Reconciliation": {"type": "object", "required": ["id", "topic", "assessments", "reconciler", "strategy", "result", "at"], "properties": {"id": {"type": "string"}, "topic": {"type": "string"}, "assessments": {"type": "array", "items": {"type": "string"}}, "conflict": {"type": "object", "properties": {"detected": {"type": "boolean"}, "spread": {"type": "number"}, "causes": {"type": "array", "items": {"enum": ["different_inputs", "different_methods", "different_assumptions", "stale_evidence", "model_error", "unknown"]}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "rounds": {"type": "array", "items": {"type": "object", "properties": {"asked": {"type": "array", "items": {"type": "string"}}, "question": {"type": "string"}, "newEvidence": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "description": "Requests for more evidence/rebuttals (e.g. robot measured battery; provider re-estimated)."}, "reconciler": {"type": "string"}, "strategy": {"type": "string"}, "weights": {"type": "object", "additionalProperties": {"type": "number"}}, "result": {"type": "object", "properties": {"value": {}, "unit": {"type": "string"}, "distribution": {"$ref": "#/$defs/Distribution"}, "decisionValue": {"description": "The value used for decisions after safety bias."}, "dissent": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "consequences": {"type": "array", "items": {"type": "string"}, "description": "Decision/plan-change ids triggered (charge first, handoff midway, notify owner...)."}, "at": {"$ref": "common.schema.json#/$defs/DateTime"}, "signature": {"$ref": "common.schema.json#/$defs/Signature"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "MissionEvent": {"type": "object", "required": ["mission", "seq", "at", "actor", "type", "prev", "hash"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "description": "One entry of the Mission event log. The log is the source of truth; the Mission document is a projection derived by replaying it (tools/mission_reducer.py). One sequencer per Mission (normally the holder's hub) assigns seq and prev, so the chain never forks; other parties submit proposals and receive the sequenced event back.", "properties": {"mission": {"type": "string"}, "seq": {"type": "integer", "minimum": 0}, "at": {"$ref": "common.schema.json#/$defs/DateTime"}, "actor": {"type": "string"}, "type": {"enum": ["created", "facet_added", "view_granted", "contribution_offered", "contribution_accepted", "contribution_rejected", "committed", "progress", "fulfilled", "failed", "withdrawn", "compensated", "decision", "escalated", "approved", "state_changed", "closed", "custom", "assessment", "reconciled"]}, "transition": {"type": "object", "unevaluatedProperties": false, "properties": {"from": {"$ref": "#/properties/state"}, "to": {"$ref": "#/properties/state"}}, "description": "For state_changed: checked against profiles/mission/transitions.json."}, "payload": {"type": "object", "description": "Type-specific body. Personal content may be replaced by a Disclosure digest."}, "payloadDigest": {"$ref": "common.schema.json#/$defs/Hash", "description": "Hash-only mode: the payload is stored off-log in erasable storage and only its hash is kept here."}, "prev": {"type": "string", "pattern": "^(genesis|sha256:[0-9a-f]{64})$"}, "hash": {"$ref": "common.schema.json#/$defs/Hash", "description": "sha256 of the RFC 8785 canonical JSON of this event without hash and signature."}, "signature": {"$ref": "common.schema.json#/$defs/Signature"}, "proposedBy": {"$ref": "common.schema.json#/$defs/Signature", "description": "When the actor is not the sequencer: the actor's signature over the proposal."}}}, "Checkpoint": {"type": "object", "required": ["mission", "seq", "head", "at", "sequencer", "signature"], "unevaluatedProperties": false, "description": "A signed statement of the log head, counter-signed by witnesses (another party in the Mission or an external transparency service, e.g. IETF SCITT). A sequencer that rewrites history after a witnessed checkpoint is detectable.", "properties": {"mission": {"type": "string"}, "seq": {"type": "integer", "minimum": 0}, "head": {"$ref": "common.schema.json#/$defs/Hash"}, "at": {"$ref": "common.schema.json#/$defs/DateTime"}, "sequencer": {"type": "string"}, "signature": {"$ref": "common.schema.json#/$defs/Signature"}, "witnesses": {"type": "array", "items": {"type": "object", "required": ["actor", "signature"], "unevaluatedProperties": false, "properties": {"actor": {"type": "string"}, "at": {"$ref": "common.schema.json#/$defs/DateTime"}, "signature": {"$ref": "common.schema.json#/$defs/Signature"}, "receipt": {"type": "string", "description": "Transparency-service receipt, if any."}}}}}}}, "unevaluatedProperties": false}, "https://cookwala.ai/v1/schemas/order.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/order.schema.json", "title": "Cookwala Order Intent", "x-cookwala-status": "experimental", "description": "A shopping list or ready-meal order derived from a plan and the inventory. Cookwala never carries payment credentials. An adapter turns an OrderIntent into a UCP / ACP checkout (grocery or delivery merchant); payment authorization stays with the merchant and AP2-style user mandates. Orders are never placed without an approval record unless the user set a standing budget rule.", "type": "object", "required": ["cookwala", "id", "kitchenId", "kind", "lines", "approval", "state"], "properties": {"cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "id": {"type": "string"}, "kitchenId": {"type": "string"}, "sessionId": {"type": "string"}, "kind": {"enum": ["groceries", "ready_meal", "meal_kit"]}, "lines": {"type": "array", "minItems": 1, "items": {"type": "object", "required": ["ingredientId", "qty"], "properties": {"ingredientId": {"$ref": "common.schema.json#/$defs/VocabId"}, "qty": {"$ref": "common.schema.json#/$defs/Quantity"}, "forRecipes": {"type": "array", "items": {"type": "string"}}, "constraints": {"type": "object", "properties": {"dietary": {"type": "array", "items": {"type": "string"}, "description": "e.g. halal_certified for meat."}, "excludeAllergens": {"type": "array", "items": {"type": "string"}}, "preferredGtin": {"type": "array", "items": {"type": "string"}}, "substitutionAllowed": {"enum": ["no", "same_ingredient_any_brand", "ask"]}, "maxUnitPrice": {"$ref": "common.schema.json#/$defs/Money"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "recipeId": {"type": "string", "description": "For ready_meal: the dish to order from a restaurant/delivery merchant."}, "deliverBy": {"$ref": "common.schema.json#/$defs/DateTime"}, "budget": {"$ref": "common.schema.json#/$defs/Money"}, "merchantHints": {"type": "array", "items": {"type": "object", "properties": {"protocol": {"enum": ["ucp", "acp", "vendor_api", "manual"]}, "merchant": {"type": "string"}, "endpoint": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "approval": {"type": "object", "required": ["mode"], "properties": {"mode": {"enum": ["ask_every_time", "standing_rule", "approved"]}, "rule": {"type": "object", "properties": {"maxTotal": {"$ref": "common.schema.json#/$defs/Money"}, "merchants": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "approvedBy": {"$ref": "common.schema.json#/$defs/Actor"}, "approvedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "mandateRef": {"type": "string", "description": "Reference to the payment-protocol mandate (e.g. AP2), never the credential itself."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "state": {"enum": ["draft", "awaiting_approval", "approved", "placed", "partially_fulfilled", "delivered", "canceled", "failed"]}, "externalOrderRef": {"type": "string"}, "delivery": {"type": "object", "properties": {"eta": {"$ref": "common.schema.json#/$defs/DateTime"}, "handoff": {"enum": ["door", "locker", "robot_receive", "concierge"], "description": "robot_receive: a home robot may receive and put away items (cold chain first)."}, "coldChainRequired": {"type": "boolean"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "meta": {"$ref": "common.schema.json#/$defs/Meta"}}, "patternProperties": {"^x-": {}}, "unevaluatedProperties": false}, "https://cookwala.ai/v1/schemas/policy.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/policy.schema.json", "title": "Cookwala Policy Pack", "x-cookwala-status": "experimental", "description": "Machine-checkable local rules (food safety, allergen disclosure, dietary, venue, appliance/robot operation). Evaluated by a hub or device against a recipe + session + capability set. Informational and best-effort: packs cite their legal sources and are not legal advice.", "type": "object", "required": ["cookwala", "id", "version", "kind", "title", "rules", "sources", "effective", "disclaimer"], "properties": {"cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "id": {"type": "string", "pattern": "^[a-z0-9]+(\\.[a-z0-9-]+)+$", "description": "e.g. us.fda-food-code-2022, eu.reg-852-2004, sa.sfda, dietary.halal, venue.school, household.default, robot.unattended-default."}, "version": {"type": "string"}, "kind": {"enum": ["jurisdiction", "dietary", "venue", "household", "device", "organization"]}, "jurisdiction": {"type": "array", "items": {"type": "string", "description": "ISO 3166-1/2 codes, e.g. US, US-CA, EU, SA, AE, EG."}}, "title": {"$ref": "common.schema.json#/$defs/LangMap"}, "extends": {"type": "array", "items": {"type": "string"}}, "rules": {"type": "array", "items": {"$ref": "#/$defs/Rule"}}, "sources": {"type": "array", "minItems": 1, "items": {"type": "object", "required": ["title", "url"], "properties": {"title": {"type": "string"}, "url": {"type": "string"}, "section": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "effective": {"type": "string", "format": "date"}, "reviewedBy": {"type": "string"}, "reviewStatus": {"enum": ["draft", "community_reviewed", "expert_reviewed"]}, "disclaimer": {"type": "string"}, "signature": {"$ref": "common.schema.json#/$defs/Signature"}, "meta": {"$ref": "common.schema.json#/$defs/Meta"}}, "$defs": {"Rule": {"type": "object", "required": ["id", "effect", "when", "message"], "properties": {"id": {"type": "string"}, "effect": {"enum": ["deny", "require", "warn", "inform", "adjust"]}, "scope": {"enum": ["recipe", "node", "ingredient", "session", "device", "inventory", "order"]}, "when": {"$ref": "#/$defs/Expr", "description": "Rule applies when this is true."}, "then": {"$ref": "#/$defs/Expr", "description": "For require: this must also be true, else the rule fails."}, "adjust": {"type": "object", "description": "For adjust: values to tighten (never loosen), e.g. {\"ccp.minCoreC\": 74}."}, "message": {"$ref": "common.schema.json#/$defs/LangMap"}, "severity": {"$ref": "common.schema.json#/$defs/Severity"}, "overridable": {"enum": ["no", "by_user", "by_operator"], "default": "no"}, "source": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Expr": {"description": "A small, side-effect-free expression language over JSON paths. Paths start at the evaluation context: recipe, node, ingredient, session, device, policyContext (venue, ageGroups, time, location).", "oneOf": [{"type": "object", "required": ["all"], "properties": {"all": {"type": "array", "items": {"$ref": "#/$defs/Expr"}}}}, {"type": "object", "required": ["any"], "properties": {"any": {"type": "array", "items": {"$ref": "#/$defs/Expr"}}}}, {"type": "object", "required": ["not"], "properties": {"not": {"$ref": "#/$defs/Expr"}}}, {"type": "object", "required": ["path"], "properties": {"path": {"type": "string", "description": "JSONPath-like, e.g. recipe.ingredients[*].ingredientId, node.op, session.supervision, device.safety.presenceDetection."}, "eq": {}, "ne": {}, "in": {"type": "array"}, "contains": {}, "containsAny": {"type": "array"}, "gte": {"type": "number"}, "lte": {"type": "number"}, "exists": {"type": "boolean"}, "inClass": {"type": "string", "description": "Ingredient/op belongs to a vocabulary class, e.g. cw.ing.class.pork."}}}]}}, "patternProperties": {"^x-": {}}, "unevaluatedProperties": false}, "https://cookwala.ai/v1/schemas/profile.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/profile.schema.json", "title": "Cookwala Profiles and Operating Modes", "x-cookwala-status": "experimental", "description": "Setup information about everything in the cooking lifecycle (clients/households, diners, kitchens, cookware, robots, organizations) and the Operating Mode that tells planners and advisors how to trade off energy, battery, ingredients, budget, time and quality. Profiles are owned by whoever creates them and can be private (local only), shared, or public, hosted in any catalog. Fields marked sensitive must never leave the owner's hub.", "type": "object", "required": ["cookwala", "id", "kind"], "properties": {"cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "id": {"type": "string"}, "kind": {"enum": ["client", "kitchen", "cookware", "robot", "organization", "mode"]}, "name": {"type": "string"}, "meta": {"$ref": "common.schema.json#/$defs/Meta"}}, "patternProperties": {"^x-": {}}, "allOf": [{"if": {"properties": {"kind": {"const": "client"}}}, "then": {"$ref": "#/$defs/ClientProfile"}}, {"if": {"properties": {"kind": {"const": "kitchen"}}}, "then": {"$ref": "#/$defs/KitchenProfile"}}, {"if": {"properties": {"kind": {"const": "cookware"}}}, "then": {"$ref": "#/$defs/CookwareProfile"}}, {"if": {"properties": {"kind": {"const": "robot"}}}, "then": {"$ref": "#/$defs/RobotProfile"}}, {"if": {"properties": {"kind": {"const": "organization"}}}, "then": {"$ref": "#/$defs/OrganizationProfile"}}, {"if": {"properties": {"kind": {"const": "mode"}}}, "then": {"properties": {"mode": {"$ref": "#/$defs/OperatingMode"}}, "required": ["mode"]}}], "$defs": {"BatteryState": {"type": "object", "properties": {"actorId": {"type": "string"}, "level": {"enum": ["full", "high", "medium", "low", "critical"], "description": "Coarse level; planners map it to work they may assign."}, "pct": {"type": "number", "minimum": 0, "maximum": 100}, "remainingWh": {"type": "number", "minimum": 0}, "charging": {"type": "boolean"}, "chargeW": {"type": "number"}, "minReservePct": {"type": "number", "minimum": 0, "maximum": 100, "description": "Never plan below this (needed to reach the dock and stay safe)."}, "canDockMidSession": {"type": "boolean"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "EnergySource": {"type": "object", "required": ["source"], "properties": {"source": {"enum": ["electric_induction", "electric_resistive", "natural_gas", "propane", "charcoal", "wood", "solar_cooker", "battery"]}, "appliances": {"type": "array", "items": {"type": "string"}}, "available": {"type": "boolean", "default": true}, "maxW": {"type": "number"}, "efficiency": {"type": "number", "minimum": 0, "maximum": 1, "description": "Heat-to-pot efficiency if known; otherwise the reasoner uses knowledge/energy.json defaults."}, "price": {"type": "object", "properties": {"perKWh": {"$ref": "common.schema.json#/$defs/Money"}, "perMJ": {"$ref": "common.schema.json#/$defs/Money"}, "timeOfUse": {"type": "array", "items": {"type": "object", "properties": {"from": {"type": "string", "pattern": "^[0-2][0-9]:[0-5][0-9]$"}, "to": {"type": "string"}, "perKWh": {"$ref": "common.schema.json#/$defs/Money"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "co2eKgPerKWh": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "OperatingMode": {"type": "object", "description": "How to cook right now. Set per hub, per session, or per request; the most specific wins. Planners turn it into objective weights and hard limits.", "properties": {"preset": {"enum": ["normal", "eco", "budget", "fast", "quiet", "off_grid", "week_saver", "feast", "outage", "battery_saver", "relief"], "description": "A named bundle of the settings below; explicit fields override the preset."}, "energy": {"type": "object", "properties": {"sources": {"type": "array", "items": {"$ref": "#/$defs/EnergySource"}}, "prefer": {"type": "array", "items": {"type": "string"}, "description": "Preferred sources in order, e.g. [\"electric_induction\", \"natural_gas\"]."}, "avoid": {"type": "array", "items": {"type": "string"}}, "goal": {"enum": ["normal", "min_energy", "min_cost", "min_carbon", "off_grid"]}, "peakLimitW": {"type": "number", "description": "Household breaker / generator / solar-inverter limit across simultaneous appliances."}, "budgetKWh": {"type": "number"}, "gridOutage": {"type": "boolean"}, "gasAvailable": {"type": "boolean"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "robots": {"type": "array", "items": {"$ref": "#/$defs/BatteryState"}}, "conserve": {"type": "object", "properties": {"energy": {"enum": ["off", "some", "max"]}, "water": {"enum": ["off", "some", "max"]}, "cleanup": {"enum": ["off", "some", "max"], "description": "Fewer pots and tools."}, "ingredients": {"type": "object", "description": "Make what's on hand last.", "properties": {"horizon": {"$ref": "common.schema.json#/$defs/Duration", "description": "e.g. P7D to make inventory last a week."}, "strategy": {"enum": ["normal", "ration", "stretch", "use_expiring_first", "no_waste"]}, "protect": {"type": "array", "items": {"type": "string"}, "description": "Ingredient ids to keep for later in the horizon."}, "mealsPerDay": {"type": "integer", "minimum": 1}, "minKcalPerPersonDay": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "budget": {"type": "object", "properties": {"mode": {"enum": ["very_low", "low", "moderate", "open"]}, "amount": {"$ref": "common.schema.json#/$defs/Money"}, "period": {"enum": ["meal", "day", "week", "month", "event"]}, "includeEnergyCost": {"type": "boolean", "default": true}, "allowShopping": {"type": "boolean"}, "preferPantry": {"type": "boolean"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "time": {"enum": ["fastest", "balanced", "relaxed"]}, "quality": {"enum": ["best", "balanced", "economy"]}, "noise": {"enum": ["any", "quiet"]}, "weights": {"type": "object", "description": "Advanced: explicit objective weights (0..1) when presets aren't enough.", "properties": {"time": {"type": "number"}, "cost": {"type": "number"}, "energy": {"type": "number"}, "carbon": {"type": "number"}, "battery": {"type": "number"}, "waste": {"type": "number"}, "quality": {"type": "number"}, "humanEffort": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "relief": {"type": "object", "description": "Mass-feeding / no-ability-to-pay mode: maximize people fed per resource while meeting ration standards and safety.", "properties": {"program": {"type": "string"}, "ration": {"$ref": "relief.schema.json#/$defs/RationStandard"}, "objective": {"enum": ["max_people_fed", "max_nutrition_per_cost", "min_waste", "equity_first"]}, "lowTech": {"type": "boolean", "description": "Plan for no robots/appliances: guided human steps, fuel-efficient methods, minimal water."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "ClientProfile": {"type": "object", "properties": {"diners": {"type": "array", "items": {"$ref": "advice.schema.json#/$defs/DinerGroup"}}, "preferences": {"type": "object", "properties": {"cuisines": {"type": "array", "items": {"type": "string"}}, "dislikes": {"type": "array", "items": {"type": "string"}}, "spice": {"enum": ["none", "mild", "medium", "hot"]}, "portion": {"enum": ["small", "normal", "large"]}, "favorites": {"type": "array", "items": {"$ref": "common.schema.json#/$defs/GlobalRef"}}, "sourcing": {"type": "object", "properties": {"organic": {"enum": ["no_preference", "prefer", "require"]}, "local": {"enum": ["no_preference", "prefer", "require"]}, "seasonal": {"type": "boolean"}, "certifications": {"type": "array", "items": {"type": "string"}, "description": "Required verified credentials, e.g. organic, halal_certified."}, "maxPremiumPct": {"type": "number", "description": "Max extra cost accepted for preferred sourcing."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "dietary": {"type": "array", "items": {"type": "string"}}, "allergies": {"type": "array", "items": {"type": "string"}}, "policyPacks": {"type": "array", "items": {"type": "string"}}, "defaultMode": {"$ref": "#/$defs/OperatingMode"}, "schedule": {"type": "object", "properties": {"mealTimes": {"type": "object", "additionalProperties": {"type": "string"}}, "fasting": {"type": "array", "items": {"type": "object", "properties": {"name": {"type": "string"}, "from": {"type": "string"}, "to": {"type": "string"}, "rule": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "locale": {"type": "object", "properties": {"lang": {"type": "string"}, "country": {"type": "string"}, "units": {"enum": ["metric", "us", "imperial"]}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "consent": {"type": "object", "properties": {"shareReports": {"type": "boolean"}, "shareMedia": {"type": "boolean"}, "useCloudAdvice": {"type": "boolean"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "members": {"type": "array", "items": {"$ref": "#/$defs/PersonNutrition"}, "description": "Per-person nutrition profiles (sensitive, local-only)."}}, "description": "Kind-specific fields; the profile root (which applies this through allOf) rejects unknown fields."}, "KitchenProfile": {"type": "object", "properties": {"energy": {"type": "array", "items": {"$ref": "#/$defs/EnergySource"}}, "appliances": {"type": "array", "items": {"type": "string", "description": "Actor ids or capabilities URLs."}}, "zones": {"type": "array", "items": {"type": "object", "properties": {"id": {"type": "string"}, "kind": {"type": "string"}, "areaCm2": {"type": "number"}, "reachableBy": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "storage": {"type": "object", "properties": {"fridgeL": {"type": "number"}, "freezerL": {"type": "number"}, "pantryL": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "altitudeM": {"type": "number"}, "water": {"type": "object", "properties": {"potable": {"type": "boolean"}, "hardness": {"enum": ["soft", "medium", "hard"]}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "ventilation": {"enum": ["none", "window", "hood", "commercial"]}, "accessibility": {"type": "array", "items": {"type": "string"}}}, "description": "Kind-specific fields; the profile root (which applies this through allOf) rejects unknown fields."}, "CookwareItem": {"type": "object", "required": ["id", "class"], "properties": {"id": {"type": "string"}, "class": {"$ref": "common.schema.json#/$defs/VocabId"}, "name": {"type": "string"}, "count": {"type": "integer", "minimum": 1}, "capacityMl": {"type": "number"}, "diameterMm": {"type": "number"}, "depthMm": {"type": "number"}, "material": {"enum": ["stainless", "cast_iron", "carbon_steel", "aluminium", "copper", "nonstick", "enamel", "ceramic", "glass", "clay", "silicone", "plastic", "wood", "other"]}, "lid": {"type": "boolean"}, "inductionCompatible": {"type": "boolean"}, "ovenSafeMaxC": {"type": "number"}, "microwaveSafe": {"type": "boolean"}, "freezerSafe": {"type": "boolean"}, "airtight": {"type": "boolean"}, "foodGrade": {"type": "boolean"}, "dishwasherSafe": {"type": "boolean"}, "handle": {"enum": ["long", "two_loop", "none", "robot_adapter"], "description": "Affects robot grasping."}, "massKg": {"type": "number"}, "location": {"type": "string"}, "dietaryDedicated": {"type": "array", "items": {"type": "string"}, "description": "e.g. halal_only, allergen_free (cross-contact control)."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "CookwareProfile": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/$defs/CookwareItem"}}}, "required": ["items"], "description": "Kind-specific fields; the profile root (which applies this through allOf) rejects unknown fields."}, "RobotProfile": {"type": "object", "properties": {"capabilities": {"description": "Inline manifest or URL.", "anyOf": [{"type": "string"}, {"$ref": "capabilities.schema.json"}]}, "battery": {"type": "object", "properties": {"capacityWh": {"type": "number"}, "chargeW": {"type": "number"}, "drawW": {"type": "object", "description": "Typical draw by activity, e.g. {\"idle\": 40, \"walk\": 250, \"stir\": 120, \"lift\": 300}.", "additionalProperties": {"type": "number"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "home": {"type": "object", "properties": {"dock": {"type": "string"}, "zones": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "maintenance": {"type": "object", "properties": {"lastCleaned": {"type": "string"}, "foodContactParts": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "description": "Kind-specific fields; the profile root (which applies this through allOf) rejects unknown fields."}, "OrganizationProfile": {"type": "object", "properties": {"type": {"enum": ["household", "restaurant", "cloud_kitchen", "school", "hospital", "care_home", "charity_kitchen", "caterer", "military", "disaster_relief", "other", "food_bank", "humanitarian_org", "community_kitchen", "school_feeding_program", "government_agency"]}, "licenses": {"type": "array", "items": {"type": "string"}}, "policyPacks": {"type": "array", "items": {"type": "string"}}, "catalogs": {"type": "array", "items": {"type": "string"}, "description": "Catalogs this organization publishes or trusts."}}, "description": "Kind-specific fields; the profile root (which applies this through allOf) rejects unknown fields."}, "NutritionTargets": {"type": "object", "description": "Daily targets for one person. Computed by the nutrition engine from the person's data and reference values, or set by a clinician (clinician values always win).", "properties": {"kcal": {"$ref": "common.schema.json#/$defs/Range"}, "proteinG": {"$ref": "common.schema.json#/$defs/Range"}, "carbsG": {"$ref": "common.schema.json#/$defs/Range"}, "fatG": {"$ref": "common.schema.json#/$defs/Range"}, "fiberGMin": {"type": "number"}, "sodiumMgMax": {"type": "number"}, "freeSugarsGMax": {"type": "number"}, "satFatGMax": {"type": "number"}, "potassiumMg": {"$ref": "common.schema.json#/$defs/Range"}, "phosphorusMgMax": {"type": "number"}, "carbsPerMealGMax": {"type": "number", "description": "e.g. carbohydrate budgeting for diabetes, if set by a clinician."}, "micronutrients": {"type": "object", "additionalProperties": {"$ref": "common.schema.json#/$defs/Range"}, "description": "e.g. iron_mg, calcium_mg, vitamin_d_ug, folate_ug."}, "source": {"enum": ["computed", "clinician", "program_standard", "user_set"]}, "basis": {"type": "array", "items": {"type": "string"}, "description": "References used, e.g. mifflin_st_jeor, who_sodium_2023, dri_tables."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "PersonNutrition": {"type": "object", "description": "One person's health and nutrition data. Always sensitive and local-only; never sent to an index or a provider. Cookwala is not a medical service: for medical diets, targets should come from a clinician.", "required": ["id"], "properties": {"id": {"type": "string"}, "alias": {"type": "string", "description": "Display name chosen by the household (e.g. 'Grandpa')."}, "ageYears": {"type": "number", "minimum": 0}, "sex": {"enum": ["female", "male", "unspecified"], "description": "Biological sex used only for reference-value equations; 'unspecified' uses averaged values."}, "heightCm": {"type": "number"}, "weightKg": {"type": "number"}, "activity": {"enum": ["sedentary", "light", "moderate", "active", "very_active"]}, "lifeStage": {"type": "array", "items": {"enum": ["infant", "child", "adolescent", "adult", "older_adult", "pregnant_t1", "pregnant_t2", "pregnant_t3", "lactating"]}}, "goals": {"type": "array", "items": {"enum": ["maintain", "lose_weight", "gain_weight", "build_muscle", "lower_sodium", "lower_sugar", "more_fiber", "heart_health", "gut_health", "athletic"]}}, "conditions": {"type": "array", "items": {"type": "string"}, "description": "e.g. type2_diabetes, hypertension, ckd_stage3, celiac, ibs_low_fodmap, gout, anemia (filters and clinician-set targets only)."}, "allergies": {"type": "array", "items": {"type": "string"}}, "intolerances": {"type": "array", "items": {"type": "string"}}, "dietary": {"type": "array", "items": {"type": "string"}}, "iddsiLevel": {"type": "integer", "minimum": 0, "maximum": 7}, "medicationsInteractions": {"type": "array", "items": {"type": "string"}, "description": "Food-drug interaction flags set by a clinician (e.g. vitamin_k_consistent for warfarin, grapefruit_avoid)."}, "targets": {"$ref": "#/$defs/NutritionTargets"}, "clinician": {"type": "object", "properties": {"name": {"type": "string"}, "reviewedAt": {"type": "string", "format": "date"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "appetite": {"enum": ["light", "normal", "hearty"]}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "unevaluatedProperties": false}, "https://cookwala.ai/v1/schemas/recipe.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/recipe.schema.json", "title": "Cookwala Recipe", "x-cookwala-status": "core", "description": "A recipe a machine can plan, check against local policy, execute and verify. Media type application/vnd.cookwala+json; file extension .cookwala.json. Layers: L0 semantics (dish, yield, ingredients, equipment, nutrition, cost, text), L1 process graph, L2 bindings, L3 safety. L4 policies live in policy.schema.json documents.", "type": "object", "required": ["cookwala", "id", "revision", "verification", "dish", "yield", "ingredients", "equipment", "process", "safety", "text", "license"], "properties": {"$schema": {"type": "string"}, "@context": {"description": "Optional JSON-LD context (https://cookwala.ai/v1/context.jsonld) mapping Cookwala terms to schema.org, FoodOn, Wikidata and IEEE 1872.1."}, "cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "id": {"type": "string", "pattern": "^[a-z0-9][a-z0-9-]{1,63}$", "description": "Same as the site recipe id (e.g. fah-234, w-ma-001)."}, "revision": {"type": "integer", "minimum": 1}, "updated": {"type": "string", "format": "date"}, "hash": {"$ref": "common.schema.json#/$defs/Hash"}, "signature": {"$ref": "common.schema.json#/$defs/Signature"}, "legacy": {"type": "object", "description": "Links back to the existing fifi.cooking representations.", "properties": {"dataUrl": {"type": "string", "description": "/data/recipes/{id}.json"}, "pageUrl": {"type": "string"}, "schemaOrg": {"type": "string", "description": "URL of the schema.org Recipe JSON-LD."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "verification": {"$ref": "#/$defs/Verification"}, "dish": {"$ref": "#/$defs/Dish"}, "yield": {"$ref": "#/$defs/Yield"}, "ingredients": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/Ingredient"}}, "equipment": {"type": "array", "items": {"$ref": "#/$defs/Equipment"}}, "process": {"$ref": "#/$defs/Process"}, "safety": {"$ref": "#/$defs/Safety"}, "requires": {"$ref": "#/$defs/Requirements"}, "nutrition": {"$ref": "#/$defs/Nutrition"}, "cost": {"$ref": "#/$defs/Cost"}, "storage": {"$ref": "#/$defs/Storage"}, "text": {"type": "object", "description": "Human-readable text per language. Machines must not rely on it for control.", "propertyNames": {"pattern": "^[a-z]{2,3}(-[A-Za-z0-9]{2,8})*$"}, "additionalProperties": {"$ref": "#/$defs/Text"}}, "bindings": {"type": "object", "description": "Optional device-class hints, keyed by x-<namespace>. Unknown keys must be ignored.", "propertyNames": {"pattern": "^x-[a-z0-9.-]+$"}}, "source": {"type": "object", "required": ["name", "url"], "properties": {"name": {"type": "string"}, "url": {"type": "string"}, "citation": {"type": "string"}, "collection": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "license": {"type": "string", "description": "SPDX id, e.g. CC-BY-4.0."}, "textSidecars": {"type": "object", "description": "Other languages are served as sidecar files to keep the core document small: {\"languages\": [...], \"url\": \"/v1/recipes/{id}/text/{lang}.json\"}. Each sidecar validates against #/$defs/Text.", "properties": {"languages": {"type": "array", "items": {"type": "string"}}, "url": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "meta": {"$ref": "common.schema.json#/$defs/Meta"}, "identity": {"type": "object", "description": "What makes this dish itself: elements that must not change (or it becomes another dish) vs elements that may flex. Planners and substitution engines must keep the essentials.", "properties": {"essential": {"type": "array", "items": {"type": "string"}, "description": "Ingredient refs, ops or states that define the dish (e.g. eggs poached in spiced tomato-pepper sauce)."}, "flexible": {"type": "array", "items": {"type": "string"}}, "neverAdd": {"type": "array", "items": {"type": "string"}, "description": "Additions that break authenticity or the dish's dietary character."}, "family": {"type": "array", "items": {"type": "string"}, "description": "Related dishes/variants (for repurposing and suggestions)."}, "culturalNotes": {"$ref": "common.schema.json#/$defs/LangMap"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "sensory": {"type": "array", "items": {"$ref": "#/$defs/SensoryTarget"}, "description": "Sensory targets per stage and for the finished dish."}, "formula": {"type": "object", "description": "Scalable proportions: quantities as ratios to a base, with role and flex range. Lets planners scale, ration, budget and substitute without breaking the dish.", "properties": {"base": {"type": "string", "description": "Ingredient ref used as 1.0 (e.g. tomato)."}, "ratios": {"type": "array", "items": {"type": "object", "required": ["ref", "ratio"], "properties": {"ref": {"type": "string"}, "ratio": {"type": "number"}, "min": {"type": "number"}, "max": {"type": "number"}, "role": {"type": "string"}, "scaling": {"enum": ["linear", "sublinear", "fixed", "to_taste"]}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "perServing": {"type": "object", "description": "Base-ingredient grams per serving at reference portion.", "properties": {"baseG": {"type": "number"}, "cookedG": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "prep": {"type": "object", "description": "Mise en place for the environment: what must be true or done before cooking starts (tools found and clean, surfaces cleared, space, ingredients staged, pre-tasks like soaking).", "properties": {"tools": {"type": "array", "items": {"type": "object", "properties": {"ref": {"type": "string"}, "clean": {"type": "boolean"}, "dry": {"type": "boolean"}, "stageAt": {"type": "string", "description": "Zone, e.g. counter-left."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "surfaces": {"type": "array", "items": {"type": "object", "properties": {"zone": {"type": "string"}, "clearAreaCm2": {"type": "number"}, "sanitized": {"type": "boolean"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "stageIngredients": {"type": "boolean", "default": true}, "advanceTasks": {"type": "array", "items": {"type": "object", "properties": {"task": {"type": "string"}, "lead": {"$ref": "common.schema.json#/$defs/Duration"}, "node": {"$ref": "#/$defs/Node"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "description": "Soak, thaw, marinate, preheat: scheduled ahead by planners."}, "clearFirst": {"type": "array", "items": {"type": "string"}, "description": "e.g. sink, hob, counter-left (planner adds tidy/wash/dry tasks if occupied)."}, "estimatedPrepTime": {"$ref": "common.schema.json#/$defs/Duration"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "service": {"type": "object", "description": "How the dish is served and eaten.", "properties": {"servingTempC": {"$ref": "common.schema.json#/$defs/Range"}, "maxHoldBeforeServe": {"$ref": "common.schema.json#/$defs/Duration"}, "plating": {"$ref": "common.schema.json#/$defs/LangMap"}, "vessel": {"type": "array", "items": {"type": "string"}, "description": "Serving vessel classes (shared pan, bowl, plate, lunchbox)."}, "accompaniments": {"type": "array", "items": {"type": "object", "properties": {"item": {"type": "string"}, "recipeId": {"$ref": "common.schema.json#/$defs/GlobalRef"}, "optional": {"type": "boolean"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "tableware": {"type": "array", "items": {"type": "string"}, "description": "e.g. spoon, bread for scooping, fork, chopsticks."}, "eatingStyle": {"type": "array", "items": {"enum": ["utensils", "by_hand", "bread_scoop", "chopsticks", "shared_platter", "individual"]}}, "portioning": {"type": "object", "properties": {"unit": {"type": "string"}, "divisible": {"type": "boolean"}, "perPersonMin": {"type": "number"}, "perPersonMax": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "packable": {"type": "object", "properties": {"lunchbox": {"type": "boolean"}, "travelMax": {"$ref": "common.schema.json#/$defs/Duration"}, "notes": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "acceptance": {"type": "array", "items": {"$ref": "#/$defs/FoodState"}, "description": "Final acceptance checks (the recipe's 'tests'): the dish is done and right when these hold."}, "layers": {"type": "object", "description": "Which knowledge layers this document carries (WHO-SMART-style): R1 narrative, R2 dish spec, R3 executable IR. R4 bound plans live in Missions.", "properties": {"r1": {"type": "boolean"}, "r2": {"type": "boolean"}, "r3": {"type": "boolean"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "additionalProperties": false, "$defs": {"Verification": {"type": "object", "required": ["level"], "properties": {"level": {"enum": ["V0", "V1", "V2", "V3"], "description": "V0 described · V1 structured · V2 simulated + reviewed · V3 field-verified."}, "evidence": {"type": "object", "properties": {"simulatorRuns": {"type": "integer", "minimum": 0}, "humanReviews": {"type": "integer", "minimum": 0}, "fieldReports": {"type": "integer", "minimum": 0}, "deviceClasses": {"type": "array", "items": {"type": "string"}}, "incidents": {"type": "integer", "minimum": 0}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "reviewedBy": {"type": "string"}, "generatedBy": {"type": "string", "description": "Tool/model that produced the process graph, for audit."}, "notes": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Dish": {"type": "object", "required": ["names"], "properties": {"names": {"$ref": "common.schema.json#/$defs/LangMap"}, "localName": {"type": "string"}, "cuisine": {"type": "array", "items": {"type": "string", "pattern": "^[A-Z]{2}$"}, "description": "ISO 3166-1 alpha-2 countries."}, "course": {"enum": ["breakfast", "starter", "soup", "salad", "main", "side", "bread", "dessert", "snack", "drink", "sauce", "condiment", "baby", "other"]}, "tags": {"type": "array", "items": {"type": "string"}}, "difficulty": {"enum": ["easy", "medium", "hard"]}, "wikidata": {"type": "string", "pattern": "^Q[0-9]+$"}, "images": {"type": "array", "items": {"type": "object", "required": ["url"], "properties": {"url": {"type": "string"}, "role": {"enum": ["banner", "thumb", "step", "reference_done"]}, "width": {"type": "integer"}, "height": {"type": "integer"}, "node": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Yield": {"type": "object", "required": ["servings"], "properties": {"servings": {"type": "number", "exclusiveMinimum": 0}, "totalMass": {"$ref": "common.schema.json#/$defs/Quantity"}, "scaling": {"type": "object", "properties": {"minScale": {"type": "number", "exclusiveMinimum": 0}, "maxScale": {"type": "number", "exclusiveMinimum": 0}, "timeExponent": {"type": "number", "description": "How cooking time scales with mass (0 = constant, 0.66 typical for roasts)."}, "note": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Prep": {"type": "object", "properties": {"op": {"type": "string"}, "shape": {"enum": ["whole", "halve", "quarter", "slice", "dice", "brunoise", "julienne", "chop", "chop_fine", "mince", "grate", "crush", "puree", "cube", "strip", "wedge", "ring", "peel_only", "zest", "juice"]}, "size": {"$ref": "common.schema.json#/$defs/Quantity"}, "remove": {"type": "array", "items": {"type": "string"}}, "soak": {"type": "object", "properties": {"liquid": {"type": "string"}, "duration": {"$ref": "common.schema.json#/$defs/Duration"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Ingredient": {"type": "object", "required": ["ref", "ingredientId", "qty"], "properties": {"ref": {"$ref": "common.schema.json#/$defs/LocalRef"}, "ingredientId": {"$ref": "common.schema.json#/$defs/VocabId"}, "legacyId": {"type": "string", "description": "masterIngredients[].id in the site data."}, "qty": {"$ref": "common.schema.json#/$defs/Quantity"}, "display": {"$ref": "common.schema.json#/$defs/LangMap"}, "prep": {"$ref": "#/$defs/Prep"}, "startTemp": {"enum": ["frozen", "fridge", "room", "warm", "hot"]}, "scaling": {"enum": ["linear", "sublinear", "fixed"], "default": "linear"}, "toTaste": {"type": "boolean"}, "optional": {"type": "boolean"}, "substitutions": {"type": "array", "description": "Equivalents that keep the dish the same. Never used to bypass dietary rules.", "items": {"type": "object", "required": ["ingredientId", "qty"], "properties": {"ingredientId": {"$ref": "common.schema.json#/$defs/VocabId"}, "qty": {"$ref": "common.schema.json#/$defs/Quantity"}, "note": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "gtin": {"type": "array", "items": {"type": "string", "pattern": "^[0-9]{8,14}$"}, "description": "Optional example GS1 product codes for ordering."}, "allergens": {"type": "array", "items": {"type": "string"}, "description": "Computed from the vocabulary; repeated here for offline use."}, "economy": {"type": "object", "description": "Budget/ration hints.", "properties": {"costClass": {"enum": ["cheap", "moderate", "expensive"]}, "stretchable": {"type": "boolean", "description": "Can be reduced or bulked out without changing the dish's identity."}, "minRatio": {"type": "number", "description": "Lowest fraction of qty that still gives an acceptable dish."}, "bulkWith": {"type": "array", "items": {"type": "string"}, "description": "Ingredient ids that can extend it (e.g. lentils for minced meat)."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "certifications": {"type": "array", "items": {"$ref": "common.schema.json#/$defs/CertificationRef"}, "description": "Certifications of this ingredient, lot or product (RFC-0010)."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Equipment": {"type": "object", "required": ["ref", "class"], "properties": {"ref": {"$ref": "common.schema.json#/$defs/LocalRef"}, "class": {"$ref": "common.schema.json#/$defs/VocabId"}, "optional": {"type": "boolean"}, "constraints": {"type": "object", "properties": {"diameterMm": {"$ref": "common.schema.json#/$defs/Range"}, "capacityMl": {"$ref": "common.schema.json#/$defs/Range"}, "powerW": {"$ref": "common.schema.json#/$defs/Range"}, "maxTempC": {"type": "number"}, "lid": {"type": "boolean"}, "material": {"type": "array", "items": {"type": "string"}}, "inductionCompatible": {"type": "boolean"}, "ovenSafe": {"type": "boolean"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Node": {"type": "object", "required": ["id", "op"], "properties": {"id": {"$ref": "common.schema.json#/$defs/LocalRef"}, "op": {"$ref": "common.schema.json#/$defs/VocabId"}, "inputs": {"type": "array", "items": {"$ref": "common.schema.json#/$defs/LocalRef"}, "description": "Ingredient refs or outputs of earlier nodes."}, "output": {"$ref": "common.schema.json#/$defs/LocalRef"}, "into": {"$ref": "common.schema.json#/$defs/LocalRef", "description": "Container/intermediate the inputs are added to."}, "equipment": {"type": "array", "items": {"$ref": "common.schema.json#/$defs/LocalRef"}}, "params": {"type": "object", "description": "Validated against the op's param schema in vocab/ops."}, "until": {"$ref": "common.schema.json#/$defs/Condition"}, "onTimeout": {"$ref": "common.schema.json#/$defs/FailureAction"}, "onFail": {"$ref": "common.schema.json#/$defs/FailureAction"}, "retry": {"type": "object", "properties": {"max": {"type": "integer", "minimum": 0}, "extendBy": {"$ref": "common.schema.json#/$defs/Duration"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "attention": {"enum": ["none", "periodic", "monitor", "continuous"], "description": "How closely the executor must watch this step."}, "assignment": {"type": "object", "description": "Who may do this step. A hub assigns concrete actors at plan time.", "properties": {"allowed": {"type": "array", "items": {"enum": ["human", "robot", "appliance", "any"]}}, "preferred": {"enum": ["human", "robot", "appliance"]}, "reason": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "humanOptional": {"type": "boolean", "description": "A human may do or confirm this step (e.g. tasting)."}, "timing": {"type": "object", "properties": {"startAfter": {"$ref": "common.schema.json#/$defs/Duration"}, "nextWithin": {"$ref": "common.schema.json#/$defs/Duration", "description": "Following dependent node must start within this time."}, "notBefore": {"type": "string", "description": "Relative anchor, e.g. serve-PT30M."}, "canPause": {"type": "boolean"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "hazards": {"type": "array", "items": {"$ref": "common.schema.json#/$defs/LocalRef"}}, "ccp": {"$ref": "common.schema.json#/$defs/LocalRef"}, "optional": {"type": "boolean"}, "variants": {"type": "array", "items": {"type": "object", "required": ["id"], "properties": {"id": {"type": "string"}, "label": {"$ref": "common.schema.json#/$defs/LangMap"}, "params": {"type": "object"}, "until": {"$ref": "common.schema.json#/$defs/ConditionOrCheck"}, "maxTime": {"$ref": "common.schema.json#/$defs/Duration"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "skill": {"type": "string", "description": "Optional reference to a learned skill/policy id for robots that have one (vendor namespace)."}, "notes": {"$ref": "common.schema.json#/$defs/LangMap"}, "sourceSteps": {"type": "array", "items": {"type": "integer", "minimum": 1}, "description": "Original step numbers (fifi.cooking uniqueInstructions.stepNumber) this node was derived from, for traceability and translation reuse."}, "energy": {"$ref": "common.schema.json#/$defs/EnergyEstimate"}, "alternatives": {"type": "array", "description": "Other ways to do this step (different heat source, equipment, or effort) with their trade-offs, used by planners for energy/budget/battery modes and missing equipment.", "items": {"type": "object", "required": ["id", "op"], "properties": {"id": {"type": "string"}, "op": {"$ref": "common.schema.json#/$defs/VocabId"}, "equipment": {"type": "array", "items": {"type": "string"}}, "params": {"type": "object"}, "until": {"$ref": "common.schema.json#/$defs/Condition"}, "energy": {"$ref": "common.schema.json#/$defs/EnergyEstimate"}, "timeFactor": {"type": "number", "description": "Duration relative to the main method (0.4 = 60% faster)."}, "quality": {"enum": ["better", "same", "minor_loss", "noticeable_loss"]}, "when": {"type": "array", "items": {"type": "string"}, "description": "Mode tags where this is preferred: energy_saver, battery_low, budget_low, no_oven, gas_only, quiet, fast."}, "label": {"$ref": "common.schema.json#/$defs/LangMap"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "pre": {"type": "array", "items": {"$ref": "#/$defs/FoodState"}, "description": "Food/equipment states required before this node may start."}, "post": {"type": "array", "items": {"$ref": "#/$defs/FoodState"}, "description": "States this node produces (planner effects; verified at completion)."}, "pause": {"type": "object", "description": "Interruption handling.", "properties": {"pausable": {"type": "boolean"}, "safeState": {"type": "array", "items": {"type": "string"}, "description": "e.g. heat_off, heat_hold_low, lid_on, knife_down, cover_food, move_from_edge."}, "maxPause": {"$ref": "common.schema.json#/$defs/Duration", "description": "Longest pause before the node's output quality or safety is affected."}, "onExceeded": {"enum": ["resume_with_extension", "reheat_then_resume", "restart_node", "salvage", "discard"]}, "resumeCheck": {"type": "array", "items": {"$ref": "#/$defs/FoodState"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "failureModes": {"type": "array", "items": {"type": "object", "required": ["incident"], "properties": {"incident": {"type": "string", "description": "cw.incident.* id."}, "likelihood": {"enum": ["low", "medium", "high"]}, "detect": {"type": "array", "items": {"$ref": "common.schema.json#/$defs/ConditionOrCheck"}}, "prevent": {"type": "array", "items": {"type": "string"}}, "playbook": {"type": "string", "description": "cw.pb.* id to run."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "description": "Known ways this step goes wrong, how to spot them early, and which playbook recovers."}, "affordances": {"type": "object", "description": "What an executor needs physically (robots match capabilities against this).", "properties": {"grasp": {"type": "array", "items": {"type": "string"}}, "forceN": {"$ref": "common.schema.json#/$defs/Range"}, "precisionMm": {"type": "number"}, "tools": {"type": "array", "items": {"type": "string"}}, "twoHanded": {"type": "boolean"}, "liftKg": {"type": "number"}, "hygiene": {"type": "array", "items": {"type": "string"}, "description": "e.g. clean_gloves, wash_after_raw_meat, allergen_clean."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "space": {"type": "object", "properties": {"zone": {"type": "string"}, "areaCm2": {"type": "number"}, "keepClearOfChildren": {"type": "boolean"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Process": {"type": "object", "required": ["nodes"], "properties": {"nodes": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/Node"}}, "edges": {"oneOf": [{"const": "implicit-from-inputs"}, {"type": "array", "items": {"type": "object", "required": ["from", "to"], "properties": {"from": {"type": "string"}, "to": {"type": "string"}, "type": {"enum": ["finish_to_start", "start_to_start", "finish_to_finish"]}, "lag": {"$ref": "common.schema.json#/$defs/Duration"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}]}, "parallelGroups": {"type": "array", "items": {"type": "array", "items": {"type": "string"}}}, "activeTime": {"$ref": "common.schema.json#/$defs/Duration"}, "totalTime": {"$ref": "common.schema.json#/$defs/Duration"}, "makeAhead": {"type": "array", "items": {"type": "object", "properties": {"until": {"type": "string"}, "maxAdvance": {"$ref": "common.schema.json#/$defs/Duration"}, "storage": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Hazard": {"type": "object", "required": ["id", "type", "severity"], "properties": {"id": {"$ref": "common.schema.json#/$defs/LocalRef"}, "type": {"$ref": "common.schema.json#/$defs/VocabId"}, "severity": {"$ref": "common.schema.json#/$defs/Severity"}, "mitigation": {"type": "array", "items": {"type": "string"}}, "limits": {"type": "object", "description": "Hard envelope, e.g. {\"oilTempMaxC\": 200, \"maxFillPct\": 50}."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "CCP": {"type": "object", "required": ["id", "hazard", "node", "criticalLimit", "monitoring", "corrective"], "properties": {"id": {"$ref": "common.schema.json#/$defs/LocalRef"}, "hazard": {"type": "string", "description": "e.g. pathogen.salmonella, pathogen.clostridium_perfringens (cooling), toxin.bacillus_cereus (rice)."}, "node": {"$ref": "common.schema.json#/$defs/LocalRef"}, "criticalLimit": {"oneOf": [{"type": "string"}, {"type": "object"}]}, "limit": {"$ref": "common.schema.json#/$defs/ConditionOrCheck", "description": "Machine-checkable form of the critical limit."}, "monitoring": {"type": "array", "items": {"type": "string"}}, "corrective": {"type": "string"}, "record": {"type": "boolean", "default": true, "description": "Executor must log readings to the session record."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Safety": {"type": "object", "required": ["hazards", "allergens", "supervision", "abort"], "properties": {"hazards": {"type": "array", "items": {"$ref": "#/$defs/Hazard"}}, "ccps": {"type": "array", "items": {"$ref": "#/$defs/CCP"}}, "allergens": {"type": "object", "properties": {"eu14": {"type": "array", "items": {"enum": ["cereals_gluten", "crustaceans", "eggs", "fish", "peanuts", "soybeans", "milk", "nuts", "celery", "mustard", "sesame", "sulphites", "lupin", "molluscs"]}}, "us9": {"type": "array", "items": {"enum": ["milk", "eggs", "fish", "crustacean_shellfish", "tree_nuts", "peanuts", "wheat", "soybeans", "sesame"]}}, "mayContain": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "dietary": {"type": "array", "items": {"type": "object", "required": ["claim", "basis"], "properties": {"claim": {"enum": ["halal", "kosher", "vegetarian", "vegan", "gluten_free", "dairy_free", "nut_free", "low_sodium", "diabetic_friendly", "pregnancy_safe", "infant_safe"]}, "basis": {"enum": ["ingredients", "certified"]}, "ruleset": {"type": "string"}, "certificate": {"type": "string", "description": "Deprecated in 0.2.1: write certifications[] (RFC-0010). Kept for 0.2 readers."}, "note": {"type": "string"}, "certifications": {"type": "array", "items": {"$ref": "common.schema.json#/$defs/CertificationRef"}, "description": "Certifications known to the publisher when this revision was signed. Later ones are published as detached Certification documents whose subject.hash is this revision's hash (RFC-0010)."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "supervision": {"type": "object", "required": ["default"], "properties": {"default": {"enum": ["unattended_ok", "presence_required", "hands_on_required"]}, "reasons": {"type": "object", "additionalProperties": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "abort": {"type": "object", "required": ["steps"], "properties": {"steps": {"type": "array", "items": {"enum": ["heat_off", "lid_on", "vent_on", "move_pan_to_cool_zone_if_capable", "retract_arm", "stop_motion", "unlock_doors", "alert_user", "alert_emergency_contact", "call_emergency_services_if_fire"]}}, "neverLeave": {"type": "array", "items": {"type": "string"}, "description": "Nodes during which the executor must not leave the cooking zone unattended."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "environment": {"type": "object", "properties": {"ventilation": {"enum": ["none", "recommended", "required"]}, "openFlame": {"type": "boolean"}, "smokeExpected": {"type": "boolean", "description": "Lets smoke alarms/hubs distinguish expected searing smoke from fire (never disables alarms)."}, "childrenPetsKeepAway": {"type": "boolean"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Requirements": {"type": "object", "description": "Derived summary for fast capability matching.", "properties": {"ops": {"type": "array", "items": {"type": "string"}}, "equipment": {"type": "array", "items": {"type": "string"}}, "sensors": {"type": "array", "items": {"type": "string"}}, "maxTempC": {"type": "number"}, "minHumanSkill": {"enum": ["none", "basic", "intermediate", "advanced"]}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Nutrition": {"type": "object", "properties": {"perServing": {"type": "object", "properties": {"kcal": {"type": "number"}, "protein": {"type": "number"}, "fat": {"type": "number"}, "carbs": {"type": "number"}, "fiber": {"type": "number"}, "sugar": {"type": "number"}, "sodiumMg": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "basis": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Cost": {"type": "object", "properties": {"currency": {"type": "string"}, "priceYear": {"type": "integer"}, "region": {"type": "string"}, "total": {"type": "number"}, "buckets": {"type": "object", "additionalProperties": {"type": "number"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Storage": {"type": "object", "properties": {"fridgeDays": {"type": "number"}, "freezerDays": {"type": "number"}, "reheat": {"type": "object", "properties": {"minCoreC": {"type": "number"}, "method": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "coolingRequired": {"type": "boolean", "description": "If true, leftover cooling is a CCP (see policy packs)."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Text": {"type": "object", "properties": {"title": {"type": "string"}, "intro": {"type": "string"}, "culturalNotes": {"type": "string"}, "steps": {"type": "object", "description": "Node id → human instruction.", "additionalProperties": {"type": "string"}}, "tips": {"type": "array", "items": {"type": "string"}}, "legacySteps": {"type": "array", "items": {"type": "string"}, "description": "Original human steps in order, as published on the source site."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "FoodState": {"type": "object", "description": "A named state of an ingredient or intermediate, checkable by sensors, vision or a human. Used as node pre/post conditions (planning) and as checkpoints.", "properties": {"of": {"type": "string", "description": "Ingredient ref or intermediate output."}, "state": {"type": "string", "description": "e.g. diced_10mm, translucent, golden, reduced_30pct, al_dente, set, rested, cooled_below_5C."}, "checks": {"type": "array", "items": {"$ref": "common.schema.json#/$defs/ConditionOrCheck"}}, "reference": {"type": "array", "items": {"type": "string"}, "description": "Reference images/clips/sounds of this state for vision/audio models."}, "description": {"$ref": "common.schema.json#/$defs/LangMap"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "SensoryTarget": {"type": "object", "properties": {"stage": {"type": "string", "description": "Node id or 'final'."}, "color": {"type": "string"}, "texture": {"type": "string"}, "aroma": {"type": "string"}, "sound": {"type": "string"}, "taste": {"type": "object", "properties": {"salt": {"type": "number", "minimum": 0, "maximum": 5}, "sour": {"type": "number", "minimum": 0, "maximum": 5}, "sweet": {"type": "number", "minimum": 0, "maximum": 5}, "bitter": {"type": "number", "minimum": 0, "maximum": 5}, "umami": {"type": "number", "minimum": 0, "maximum": 5}, "heat": {"type": "number", "minimum": 0, "maximum": 5}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "servingTempC": {"$ref": "common.schema.json#/$defs/Range"}, "description": {"$ref": "common.schema.json#/$defs/LangMap"}, "references": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "patternProperties": {"^x-": {"description": "Extension fields (see docs/EXTENSIBILITY.md). Unknown x- fields must be preserved and ignored."}}}, "https://cookwala.ai/v1/schemas/relief.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/relief.schema.json", "title": "Cookwala Relief (feeding programs, needs, pledges, allocations, impact)", "x-cookwala-status": "experimental", "description": "The humanitarian layer of Cookwala: lets food organizations, food banks, community kitchens, schools, governments, donors, grocers, restaurants and robot operators coordinate a global, federated 'assembly line' that feeds people, including those who cannot pay. Needs are aggregated (never individual beneficiaries); supply arrives as pledges (food, surplus, kitchen and robot capacity, transport, volunteers, funds expressed as meals); an allocator matches them; kitchens run normal Cookwala sessions; impact is reported openly. Use $defs Program, Need, Pledge, Allocation, ImpactReport. Fields carry optional HXL hashtags for interoperability with humanitarian data systems.", "$defs": {"Hxl": {"type": "string", "pattern": "^#[a-z_]+(\\+[a-z_]+)*$", "description": "Humanitarian Exchange Language tag, e.g. #adm1+name, #affected+f+children."}, "Place": {"type": "object", "properties": {"country": {"type": "string", "pattern": "^[A-Z]{2}$"}, "admin1": {"type": "string"}, "admin2": {"type": "string"}, "pcode": {"type": "string", "description": "OCHA place code when available."}, "site": {"type": "string", "description": "Camp, school, kitchen or distribution point id."}, "lat": {"type": "number"}, "lon": {"type": "number"}, "radiusKm": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "RationStandard": {"type": "object", "description": "Nutrition and ration rules for a program. Defaults follow widely used humanitarian minimums (e.g. Sphere: about 2,100 kcal per person per day for general food rations); programs set their own.", "properties": {"kcalPerPersonDay": {"type": "number"}, "proteinPctEnergy": {"$ref": "common.schema.json#/$defs/Range"}, "fatPctEnergy": {"$ref": "common.schema.json#/$defs/Range"}, "micronutrients": {"type": "array", "items": {"type": "string"}, "description": "e.g. iron, vitamin_a, iodine (fortified foods)."}, "groups": {"type": "array", "items": {"type": "object", "properties": {"group": {"enum": ["infant_6_23m", "child", "adolescent", "adult", "pregnant_lactating", "elderly", "malnourished_mam", "malnourished_sam"]}, "kcalPerDay": {"type": "number"}, "notes": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "standardRef": {"type": "string", "description": "e.g. sphere-2018, wfp-school-meals, national guideline id."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Program": {"type": "object", "required": ["cookwala", "id", "name", "operator", "type", "area"], "properties": {"cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "id": {"type": "string"}, "name": {"type": "string"}, "operator": {"type": "string", "description": "Provider id of the organization running it."}, "partners": {"type": "array", "items": {"type": "string"}}, "type": {"enum": ["emergency_relief", "school_meals", "community_kitchen", "food_bank", "soup_kitchen", "elderly_meals", "refugee_camp", "disaster_response", "surplus_rescue", "pay_it_forward", "other"]}, "area": {"type": "array", "items": {"$ref": "#/$defs/Place"}}, "period": {"type": "object", "properties": {"from": {"type": "string", "format": "date"}, "to": {"type": "string", "format": "date"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "rations": {"$ref": "#/$defs/RationStandard"}, "policyPacks": {"type": "array", "items": {"type": "string"}, "description": "Food safety + dietary (e.g. dietary.halal) + humanitarian.sphere."}, "kitchens": {"type": "array", "items": {"type": "string"}, "description": "Hub/catalog URLs of participating kitchens."}, "catalogs": {"type": "array", "items": {"type": "string"}, "description": "Recipe catalogs used: local, culturally appropriate, from local ingredients."}, "accepts": {"type": "array", "items": {"enum": ["food", "surplus_food", "cooked_meals", "kitchen_capacity", "robot_capacity", "transport", "volunteers", "cold_storage", "funds", "fuel", "equipment"]}}, "contact": {"type": "string"}, "transparency": {"type": "object", "properties": {"impactFeed": {"type": "string"}, "iati": {"type": "string", "description": "IATI activity identifier when reporting aid flows."}, "hdx": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "meta": {"$ref": "common.schema.json#/$defs/Meta"}}, "patternProperties": {"^x-": {}}, "unevaluatedProperties": false}, "Need": {"type": "object", "required": ["cookwala", "id", "program", "place", "window", "people"], "description": "Aggregated demand at a place and time. No names, no individual data.", "properties": {"cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "id": {"type": "string"}, "program": {"type": "string"}, "place": {"$ref": "#/$defs/Place"}, "window": {"type": "object", "required": ["from", "to"], "properties": {"from": {"$ref": "common.schema.json#/$defs/DateTime"}, "to": {"$ref": "common.schema.json#/$defs/DateTime"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "people": {"type": "integer", "minimum": 1, "x-hxl": "#affected"}, "groups": {"type": "array", "items": {"type": "object", "properties": {"group": {"type": "string"}, "count": {"type": "integer"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "mealsPerDay": {"type": "integer", "minimum": 1}, "form": {"enum": ["hot_meals", "packed_meals", "dry_rations", "mixed"]}, "dietary": {"type": "array", "items": {"type": "string"}}, "allergensToAvoid": {"type": "array", "items": {"type": "string"}}, "constraints": {"type": "object", "description": "Cooking/serving constraints at the site: no fuel, no water, no refrigeration, no utensils, access window.", "additionalProperties": true}, "priority": {"enum": ["critical", "high", "normal"], "description": "Set by the program using its own vulnerability criteria."}, "status": {"enum": ["open", "partially_covered", "covered", "closed"]}, "meta": {"$ref": "common.schema.json#/$defs/Meta"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Pledge": {"type": "object", "required": ["cookwala", "id", "from", "kind", "available"], "description": "Something a participant commits to give: food, surplus, cooking or robot capacity, transport, cold storage, volunteers, fuel, equipment or funds expressed as meals.", "properties": {"cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "id": {"type": "string"}, "from": {"type": "string", "description": "Provider id (grocer, restaurant, farm, donor, robot operator, kitchen...)."}, "kind": {"enum": ["food", "surplus_food", "cooked_meals", "kitchen_capacity", "robot_capacity", "transport", "cold_storage", "volunteers", "funds", "fuel", "equipment"]}, "items": {"type": "array", "items": {"type": "object", "properties": {"ingredientId": {"type": "string"}, "recipeId": {"type": "string"}, "qty": {"$ref": "common.schema.json#/$defs/Quantity"}, "servings": {"type": "number"}, "useBy": {"$ref": "common.schema.json#/$defs/DateTime"}, "storage": {"enum": ["ambient", "chilled", "frozen", "hot_held"]}, "dietary": {"type": "array", "items": {"type": "string"}}, "allergens": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "capacity": {"type": "object", "description": "For kitchen/robot/transport/storage/volunteer pledges.", "properties": {"mealsPerHour": {"type": "number"}, "hours": {"type": "array", "items": {"type": "string"}}, "kitchen": {"type": "string"}, "vehicles": {"type": "integer"}, "coldStorageL": {"type": "number"}, "people": {"type": "integer"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "funds": {"type": "object", "properties": {"meals": {"type": "integer", "description": "Funds expressed as number of meals sponsored."}, "amount": {"$ref": "common.schema.json#/$defs/Money"}, "channel": {"type": "string", "description": "The program's own donation channel; Cookwala never handles payments."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "available": {"type": "object", "required": ["from", "to"], "properties": {"from": {"$ref": "common.schema.json#/$defs/DateTime"}, "to": {"$ref": "common.schema.json#/$defs/DateTime"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "place": {"$ref": "#/$defs/Place"}, "conditions": {"type": "array", "items": {"type": "string"}}, "foodSafety": {"type": "object", "description": "Required for surplus/cooked food: when cooked, how held, temperatures logged.", "properties": {"cookedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "holding": {"type": "string"}, "tempLog": {"type": "string"}, "ccpRecords": {"type": "boolean"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "anonymous": {"type": "boolean"}, "meta": {"$ref": "common.schema.json#/$defs/Meta"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Allocation": {"type": "object", "required": ["cookwala", "id", "need", "assignments"], "description": "The allocator's plan for covering a need from pledges: which supply goes to which kitchen, what gets cooked (production plans), how it moves, and what remains uncovered.", "properties": {"cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "id": {"type": "string"}, "need": {"type": "string"}, "assignments": {"type": "array", "items": {"type": "object", "properties": {"pledge": {"type": "string"}, "to": {"type": "string"}, "items": {"type": "array"}, "pickupAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "deliverBy": {"$ref": "common.schema.json#/$defs/DateTime"}, "transport": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "production": {"type": "array", "items": {"$ref": "advice.schema.json#/$defs/ProductionPlan"}}, "coverage": {"type": "object", "properties": {"meals": {"type": "integer"}, "kcalPerPersonDay": {"type": "number"}, "pct": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "gaps": {"type": "array", "items": {"type": "object", "properties": {"what": {"type": "string"}, "qty": {"type": "number"}, "unit": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "solver": {"type": "object", "properties": {"name": {"type": "string"}, "status": {"type": "string"}, "objective": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "approvedBy": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "ImpactReport": {"type": "object", "required": ["cookwala", "program", "period", "meals"], "description": "Open, aggregated impact data. No personal data.", "properties": {"cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "program": {"type": "string"}, "place": {"$ref": "#/$defs/Place"}, "period": {"type": "object", "properties": {"from": {"type": "string", "format": "date"}, "to": {"type": "string", "format": "date"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "meals": {"type": "integer", "minimum": 0, "x-hxl": "#output+meals"}, "peopleReached": {"type": "integer", "minimum": 0, "x-hxl": "#reached"}, "kcalPerPersonDayAvg": {"type": "number"}, "costPerMeal": {"$ref": "common.schema.json#/$defs/Money"}, "surplusRescuedKg": {"type": "number"}, "wasteKg": {"type": "number"}, "energyKWhPerMeal": {"type": "number"}, "robotShare": {"type": "number", "minimum": 0, "maximum": 1, "description": "Share of cooking steps performed by robots."}, "foodSafetyIncidents": {"type": "integer"}, "gapsUnmet": {"type": "integer"}, "hxl": {"type": "object", "additionalProperties": {"$ref": "#/$defs/Hxl"}, "description": "Field → HXL tag mapping for export."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}}, "https://cookwala.ai/v1/schemas/report.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/report.schema.json", "title": "Cookwala Execution Report", "x-cookwala-status": "experimental", "description": "Anonymous, opt-in report a hub or device sends to the index after a session (POST /v1/reports). Drives verification levels (V3) and recipe fixes. No personal data, no images unless the user opts in, no location finer than country.", "type": "object", "required": ["cookwala", "reportId", "recipeId", "recipeHash", "outcome", "deviceClasses", "submittedAt"], "properties": {"cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "reportId": {"type": "string", "format": "uuid"}, "recipeId": {"type": "string"}, "recipeHash": {"$ref": "common.schema.json#/$defs/Hash"}, "scale": {"type": "number"}, "mode": {"enum": ["guided", "assisted", "autonomous"]}, "outcome": {"enum": ["success", "success_with_interventions", "failed", "aborted_safety", "aborted_user"]}, "deviceClasses": {"type": "array", "items": {"type": "string", "description": "Coarse class + vendor, e.g. x-posha.countertop, humanoid.generic, oven.matter."}}, "country": {"type": "string", "pattern": "^[A-Z]{2}$"}, "nodes": {"type": "array", "items": {"type": "object", "required": ["nodeId", "result"], "properties": {"nodeId": {"type": "string"}, "result": {"enum": ["ok", "retried", "extended", "human_took_over", "skipped", "failed"]}, "durationS": {"type": "number"}, "conditionFired": {"type": "string"}, "assigneeKind": {"enum": ["human", "robot", "appliance"]}, "note": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "ccps": {"type": "array", "items": {"type": "object", "properties": {"ccpId": {"type": "string"}, "passed": {"type": "boolean"}, "value": {"type": "number"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "safetyEvents": {"type": "array", "items": {"type": "string"}}, "rating": {"type": "integer", "minimum": 1, "maximum": 5}, "submittedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "signature": {"$ref": "common.schema.json#/$defs/Signature"}, "meta": {"$ref": "common.schema.json#/$defs/Meta"}}, "patternProperties": {"^x-": {}}, "unevaluatedProperties": false}, "https://cookwala.ai/v1/schemas/session.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/session.schema.json", "title": "Cookwala Cook Session", "x-cookwala-status": "experimental", "description": "One execution of one or more recipes in one kitchen, coordinated by a Cookwala Hub. It holds the plan (who does what, when, with which resources), live task states, resource leases, handoffs, CCP records and policy decisions. Task states match the A2A task lifecycle so agents can follow along.", "type": "object", "required": ["cookwala", "id", "kitchenId", "state", "recipes", "participants", "plan", "policy"], "properties": {"cookwala": {"$ref": "common.schema.json#/$defs/SpecVersion"}, "id": {"type": "string"}, "kitchenId": {"type": "string"}, "createdBy": {"$ref": "common.schema.json#/$defs/Actor"}, "createdAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "state": {"$ref": "#/$defs/SessionState"}, "serveAt": {"$ref": "common.schema.json#/$defs/DateTime", "description": "Target time the food should be ready; the planner schedules backwards."}, "mode": {"enum": ["guided", "assisted", "autonomous"], "description": "guided: humans do the steps with prompts; assisted: mixed team; autonomous: machines do everything allowed."}, "supervision": {"enum": ["unattended", "presence", "hands_on"]}, "recipes": {"type": "array", "minItems": 1, "items": {"type": "object", "required": ["recipeId", "hash"], "properties": {"recipeId": {"type": "string"}, "revision": {"type": "integer"}, "hash": {"$ref": "common.schema.json#/$defs/Hash"}, "scale": {"type": "number", "exclusiveMinimum": 0}, "servings": {"type": "number"}, "variants": {"type": "object", "additionalProperties": {"type": "string"}, "description": "nodeId → chosen variant id."}, "exclusions": {"type": "array", "items": {"type": "string"}, "description": "Optional ingredients the diner chose to skip."}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "diners": {"type": "array", "description": "Optional, privacy-minimal diner profile used only for policy evaluation.", "items": {"type": "object", "properties": {"ageGroup": {"enum": ["infant", "child", "adult", "senior"]}, "allergies": {"type": "array", "items": {"type": "string"}}, "dietary": {"type": "array", "items": {"type": "string"}}, "pregnant": {"type": "boolean"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "participants": {"type": "array", "items": {"type": "object", "required": ["actor", "roles"], "properties": {"actor": {"$ref": "common.schema.json#/$defs/Actor"}, "roles": {"type": "array", "items": {"type": "string"}}, "capabilitiesUrl": {"type": "string"}, "status": {"enum": ["available", "busy", "offline", "fault", "paused"]}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "plan": {"type": "object", "required": ["tasks"], "properties": {"generatedBy": {"type": "string"}, "estimatedStart": {"$ref": "common.schema.json#/$defs/DateTime"}, "estimatedEnd": {"$ref": "common.schema.json#/$defs/DateTime"}, "tasks": {"type": "array", "items": {"$ref": "#/$defs/Task"}}, "unassignable": {"type": "array", "items": {"type": "object", "properties": {"nodeId": {"type": "string"}, "reason": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "leases": {"type": "array", "items": {"$ref": "#/$defs/Lease"}}, "handoffs": {"type": "array", "items": {"$ref": "#/$defs/Handoff"}}, "ccpRecords": {"type": "array", "items": {"type": "object", "required": ["ccpId", "taskId", "at", "reading", "passed"], "properties": {"ccpId": {"type": "string"}, "taskId": {"type": "string"}, "at": {"$ref": "common.schema.json#/$defs/DateTime"}, "reading": {"type": "object"}, "passed": {"type": "boolean"}, "by": {"$ref": "common.schema.json#/$defs/Actor"}, "corrective": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "policy": {"type": "object", "required": ["packs", "decision"], "properties": {"packs": {"type": "array", "items": {"type": "string"}}, "decision": {"enum": ["allow", "allow_with_warnings", "deny"]}, "results": {"type": "array", "items": {"type": "object", "properties": {"pack": {"type": "string"}, "rule": {"type": "string"}, "effect": {"type": "string"}, "passed": {"type": "boolean"}, "message": {"type": "string"}, "overriddenBy": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "acknowledgedBy": {"$ref": "common.schema.json#/$defs/Actor"}, "acknowledgedAt": {"$ref": "common.schema.json#/$defs/DateTime"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "shoppingList": {"type": "string", "description": "Id of an order.schema.json OrderIntent generated for missing ingredients."}, "abort": {"type": "object", "properties": {"reason": {"type": "string"}, "by": {"$ref": "common.schema.json#/$defs/Actor"}, "at": {"$ref": "common.schema.json#/$defs/DateTime"}, "stepsExecuted": {"type": "array", "items": {"type": "string"}}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "meta": {"$ref": "common.schema.json#/$defs/Meta"}, "operatingMode": {"$ref": "profile.schema.json#/$defs/OperatingMode"}}, "$defs": {"SessionState": {"enum": ["draft", "planned", "awaiting_ingredients", "awaiting_confirmation", "running", "paused", "completed", "aborted", "failed"]}, "TaskState": {"description": "Matches A2A task states plus 'scheduled' and 'blocked'.", "enum": ["scheduled", "blocked", "submitted", "working", "input_required", "auth_required", "completed", "failed", "canceled", "rejected"]}, "Task": {"type": "object", "required": ["id", "recipeId", "nodeId", "assignee", "state"], "properties": {"id": {"type": "string"}, "recipeId": {"type": "string"}, "nodeId": {"type": "string"}, "op": {"type": "string"}, "assignee": {"$ref": "common.schema.json#/$defs/Actor"}, "fallback": {"type": "array", "items": {"$ref": "common.schema.json#/$defs/Actor"}, "description": "Who takes over on failure, in order (usually ends with a human)."}, "state": {"$ref": "#/$defs/TaskState"}, "dependsOn": {"type": "array", "items": {"type": "string"}}, "leases": {"type": "array", "items": {"type": "string"}}, "scheduledStart": {"$ref": "common.schema.json#/$defs/DateTime"}, "startedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "endedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "params": {"type": "object", "description": "Resolved params after scaling and policy adjustments."}, "progress": {"type": "number", "minimum": 0, "maximum": 1}, "telemetry": {"type": "object", "description": "Latest readings, e.g. {\"cw.sense.core_temp\": 61.5}."}, "conditionStatus": {"type": "object", "description": "Which until-checks are satisfied."}, "attempts": {"type": "integer"}, "message": {"$ref": "common.schema.json#/$defs/LangMap", "description": "What to show/say to humans for this task."}, "a2aTaskId": {"type": "string"}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Lease": {"type": "object", "description": "Exclusive or shared hold on a physical resource, so two actors never use the same burner, pan or counter zone at once (modelled on Open-RMF resource scheduling).", "required": ["id", "resource", "holder", "mode", "from", "until"], "properties": {"id": {"type": "string"}, "resource": {"type": "string", "description": "e.g. appliance:hob-1/zone-2, vessel:pan-28, zone:counter-left, appliance:oven-main/cavity-1, robot:neo-1/arm-right."}, "holder": {"type": "string", "description": "Task id or actor id."}, "mode": {"enum": ["exclusive", "shared_read"]}, "from": {"$ref": "common.schema.json#/$defs/DateTime"}, "until": {"$ref": "common.schema.json#/$defs/DateTime"}, "state": {"enum": ["requested", "granted", "released", "expired", "revoked"]}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}, "Handoff": {"type": "object", "description": "Transfer of an intermediate or a task between actors (robot→human, appliance→robot, robot→robot).", "required": ["id", "from", "to", "item", "state"], "properties": {"id": {"type": "string"}, "from": {"$ref": "common.schema.json#/$defs/Actor"}, "to": {"$ref": "common.schema.json#/$defs/Actor"}, "item": {"type": "string", "description": "Intermediate ref (e.g. sauce) or task id."}, "location": {"type": "string"}, "hazards": {"type": "array", "items": {"type": "string"}, "description": "e.g. hot_vessel; the receiver must acknowledge."}, "state": {"enum": ["proposed", "ready", "acknowledged", "completed", "refused", "timed_out"]}, "requiresAck": {"type": "boolean", "default": true}}, "unevaluatedProperties": false, "patternProperties": {"^x-": {}}}}, "patternProperties": {"^x-": {}}, "unevaluatedProperties": false}, "https://cookwala.ai/v1/schemas/supply.schema.json": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://cookwala.ai/v1/schemas/supply.schema.json", "title": "Cookwala supply signals (experimental)", "x-cookwala-status": "experimental", "description": "RFC-0007. Aggregated, delayed, class-level demand and supply signals so farms, cooperatives, programs and stores can plan with less waste. No prices, no products or brands, no region finer than admin1 without at least 100 sources, at least 20 contributing sources, at least 7 days of delay. Gated on competition-law review before any production use. Surplus rescue itself uses the Humanitarian Profile (a farm is a donor).", "$defs": {"Version": {"type": "string", "pattern": "^0\\.1\\.[0-9]+$"}, "OrgId": {"type": "string", "pattern": "^(did:web:[a-z0-9.-]+|gln:[0-9]{13}|org:[a-z0-9-]+\\.[a-z0-9.-]+)$"}, "Region": {"type": "object", "required": ["country", "admin1"], "unevaluatedProperties": false, "properties": {"country": {"type": "string", "pattern": "^[A-Z]{2}$"}, "admin1": {"type": "string", "maxLength": 80}, "admin2": {"type": "string", "maxLength": 80, "description": "Allowed only with at least 100 contributing sources."}, "pcode": {"type": "string", "maxLength": 20}}}, "Period": {"type": "object", "required": ["weekStart"], "unevaluatedProperties": false, "properties": {"weekStart": {"type": "string", "format": "date", "description": "Monday of the ISO week."}}}, "QuantityRange": {"type": "object", "required": ["low", "high", "method"], "unevaluatedProperties": false, "properties": {"low": {"type": "number", "minimum": 0}, "high": {"type": "number", "minimum": 0}, "method": {"enum": ["measured", "modelled", "assumed"]}}}, "DemandSignal": {"type": "object", "required": ["profile", "kind", "id", "publisher", "region", "period", "ingredientClass", "quantityKg", "contributingSources", "delayDays", "basis", "prices", "publishedAt"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "properties": {"profile": {"$ref": "#/$defs/Version"}, "kind": {"const": "DemandSignal"}, "id": {"type": "string", "pattern": "^[a-z0-9][a-z0-9._:-]{2,95}$"}, "publisher": {"$ref": "#/$defs/OrgId"}, "region": {"$ref": "#/$defs/Region"}, "period": {"$ref": "#/$defs/Period"}, "ingredientClass": {"type": "string", "pattern": "^(cw\\.ing\\.class\\.[a-z0-9_]+|x-[a-z0-9-]+\\.[a-z0-9_.]+)$", "description": "A class (legume, leafy vegetable, poultry), never a product or brand."}, "quantityKg": {"$ref": "#/$defs/QuantityRange"}, "contributingSources": {"type": "integer", "minimum": 20, "description": "Kitchens, programs or households whose plans were aggregated. At least 20."}, "delayDays": {"type": "integer", "minimum": 7, "description": "Days between the end of the period and publication. At least 7."}, "basis": {"enum": ["planned_meals", "distributions", "orders", "production_runs"]}, "prices": {"const": "none"}, "publishedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "signature": {"$ref": "common.schema.json#/$defs/Signature"}}}, "SupplySignal": {"type": "object", "required": ["profile", "kind", "id", "publisher", "region", "period", "ingredientClass", "availability", "openToAll", "publishedAt"], "unevaluatedProperties": false, "patternProperties": {"^x-": {}}, "properties": {"profile": {"$ref": "#/$defs/Version"}, "kind": {"const": "SupplySignal"}, "id": {"type": "string", "pattern": "^[a-z0-9][a-z0-9._:-]{2,95}$"}, "publisher": {"$ref": "#/$defs/OrgId", "description": "A cooperative, program or market operator, never a single person."}, "region": {"$ref": "#/$defs/Region"}, "period": {"$ref": "#/$defs/Period"}, "ingredientClass": {"type": "string", "pattern": "^(cw\\.ing\\.class\\.[a-z0-9_]+|x-[a-z0-9-]+\\.[a-z0-9_.]+)$"}, "availability": {"enum": ["glut", "normal", "short"]}, "quantityKg": {"$ref": "#/$defs/QuantityRange"}, "harvestWindow": {"type": "object", "required": ["from", "to"], "unevaluatedProperties": false, "properties": {"from": {"type": "string", "format": "date"}, "to": {"type": "string", "format": "date"}}}, "openToAll": {"const": true, "description": "Published signals are public, free and identical for every reader."}, "publishedAt": {"$ref": "common.schema.json#/$defs/DateTime"}, "signature": {"$ref": "common.schema.json#/$defs/Signature"}}}}}}}
