{
 "$schema": "https://cookwala.ai/v1/schemas/recipe.schema.json",
 "cookwala": "0.2.0",
 "id": "example-koshari",
 "revision": 1,
 "updated": "2026-10-04",
 "verification": {
  "level": "V1",
  "evidence": {
   "simulatorRuns": 0,
   "humanReviews": 1,
   "fieldReports": 0
  },
  "reviewedBy": "cookwala.ai editorial (structure only)",
  "notes": "Example recipe written to exercise the standard: structured steps, end conditions, hazards and critical control points. Not simulated and not field-verified; values are typical home-cooking values, not measurements."
 },
 "dish": {
  "names": {
   "en": "Koshari",
   "ar": "كشري"
  },
  "cuisine": [
   "EG"
  ],
  "course": "main",
  "tags": [
   "koshari",
   "street-food",
   "vegan",
   "rice",
   "lentils",
   "pasta",
   "deep-fry"
  ]
 },
 "yield": {
  "servings": 6,
  "totalMass": {
   "value": 3200,
   "unit": "g"
  },
  "scaling": {
   "minScale": 0.5,
   "maxScale": 2,
   "note": "Frying oil volume does not scale; fry in more batches."
  }
 },
 "ingredients": [
  {
   "ref": "rice",
   "ingredientId": "cw.ing.rice_short",
   "qty": {
    "value": 300,
    "unit": "g",
    "tolerance": 0.1
   },
   "display": {
    "en": "300 g short-grain rice",
    "ar": "300 جم أرز مصري"
   }
  },
  {
   "ref": "vermicelli",
   "ingredientId": "cw.ing.vermicelli_wheat",
   "qty": {
    "value": 50,
    "unit": "g",
    "tolerance": 0.2
   },
   "display": {
    "en": "50 g vermicelli",
    "ar": "50 جم شعرية"
   }
  },
  {
   "ref": "oil",
   "ingredientId": "cw.ing.vegetable_oil",
   "qty": {
    "value": 30,
    "unit": "ml",
    "tolerance": 0.3
   },
   "display": {
    "en": "2 tbsp oil",
    "ar": "2 ملعقة كبيرة زيت"
   }
  },
  {
   "ref": "water_rice",
   "ingredientId": "cw.ing.water",
   "qty": {
    "value": 550,
    "unit": "ml",
    "tolerance": 0.1
   },
   "display": {
    "en": "550 ml hot water",
    "ar": "550 مل ماء ساخن"
   }
  },
  {
   "ref": "lentils",
   "ingredientId": "cw.ing.lentils_brown",
   "qty": {
    "value": 200,
    "unit": "g",
    "tolerance": 0.1
   },
   "display": {
    "en": "200 g brown lentils",
    "ar": "200 جم عدس أسود"
   }
  },
  {
   "ref": "water_lentils",
   "ingredientId": "cw.ing.water",
   "qty": {
    "value": 800,
    "unit": "ml",
    "tolerance": 0.1
   },
   "display": {
    "en": "800 ml water",
    "ar": "800 مل ماء"
   }
  },
  {
   "ref": "macaroni",
   "ingredientId": "cw.ing.pasta_short",
   "qty": {
    "value": 200,
    "unit": "g",
    "tolerance": 0.1
   },
   "display": {
    "en": "200 g small macaroni",
    "ar": "200 جم مكرونة صغيرة"
   }
  },
  {
   "ref": "water_pasta",
   "ingredientId": "cw.ing.water",
   "qty": {
    "value": 1500,
    "unit": "ml",
    "tolerance": 0.2
   },
   "display": {
    "en": "1.5 l water",
    "ar": "1.5 لتر ماء"
   }
  },
  {
   "ref": "chickpeas",
   "ingredientId": "cw.ing.chickpeas_cooked",
   "qty": {
    "value": 200,
    "unit": "g",
    "tolerance": 0.2
   },
   "display": {
    "en": "200 g cooked chickpeas",
    "ar": "200 جم حمص مسلوق"
   }
  },
  {
   "ref": "onions_fry",
   "ingredientId": "cw.ing.onion_yellow",
   "qty": {
    "value": 400,
    "unit": "g",
    "tolerance": 0.2
   },
   "display": {
    "en": "3 onions, sliced thin",
    "ar": "3 بصلات مقطعة شرائح رفيعة"
   }
  },
  {
   "ref": "flour",
   "ingredientId": "cw.ing.wheat_flour",
   "qty": {
    "value": 20,
    "unit": "g",
    "tolerance": 0.3
   },
   "display": {
    "en": "2 tbsp flour",
    "ar": "2 ملعقة كبيرة دقيق"
   }
  },
  {
   "ref": "frying_oil",
   "ingredientId": "cw.ing.vegetable_oil",
   "qty": {
    "value": 500,
    "unit": "ml",
    "tolerance": 0.2
   },
   "display": {
    "en": "500 ml oil for frying",
    "ar": "500 مل زيت للقلي"
   },
   "scaling": "fixed"
  },
  {
   "ref": "tomato",
   "ingredientId": "cw.ing.tomato_passata",
   "qty": {
    "value": 600,
    "unit": "g",
    "tolerance": 0.1
   },
   "display": {
    "en": "600 g tomato passata",
    "ar": "600 جم عصير طماطم"
   }
  },
  {
   "ref": "garlic",
   "ingredientId": "cw.ing.garlic",
   "qty": {
    "value": 9,
    "unit": "g",
    "tolerance": 0.3
   },
   "display": {
    "en": "3 garlic cloves",
    "ar": "3 فصوص ثوم"
   }
  },
  {
   "ref": "vinegar",
   "ingredientId": "cw.ing.vinegar_white",
   "qty": {
    "value": 30,
    "unit": "ml",
    "tolerance": 0.3
   },
   "display": {
    "en": "2 tbsp white vinegar",
    "ar": "2 ملعقة كبيرة خل"
   }
  },
  {
   "ref": "cumin",
   "ingredientId": "cw.ing.cumin_ground",
   "qty": {
    "value": 2,
    "unit": "g",
    "tolerance": 0.3
   },
   "display": {
    "en": "1 tsp cumin, for the sauce",
    "ar": "ملعقة صغيرة كمون للصلصة"
   },
   "scaling": "sublinear"
  },
  {
   "ref": "coriander",
   "ingredientId": "cw.ing.coriander_ground",
   "qty": {
    "value": 3,
    "unit": "g",
    "tolerance": 0.3
   },
   "display": {
    "en": "1½ tsp ground coriander",
    "ar": "1½ ملعقة صغيرة كسبرة"
   },
   "scaling": "sublinear"
  },
  {
   "ref": "chili",
   "ingredientId": "cw.ing.chili_flakes",
   "qty": {
    "value": 1,
    "unit": "g",
    "tolerance": 0.5
   },
   "display": {
    "en": "½ tsp chili flakes, to taste",
    "ar": "نصف ملعقة صغيرة شطة حسب الرغبة"
   },
   "scaling": "sublinear",
   "optional": true
  },
  {
   "ref": "salt",
   "ingredientId": "cw.ing.salt",
   "qty": {
    "value": 4,
    "unit": "g",
    "tolerance": 0.3
   },
   "display": {
    "en": "1 tsp salt, for the pasta water",
    "ar": "ملعقة صغيرة ملح لماء المكرونة"
   },
   "scaling": "sublinear",
   "toTaste": true
  },
  {
   "ref": "garlic_daqqa",
   "ingredientId": "cw.ing.garlic",
   "qty": {
    "value": 6,
    "unit": "g",
    "tolerance": 0.3
   },
   "display": {
    "en": "2 garlic cloves for the daqqa",
    "ar": "فصان ثوم للدقة"
   }
  },
  {
   "ref": "vinegar_daqqa",
   "ingredientId": "cw.ing.vinegar_white",
   "qty": {
    "value": 60,
    "unit": "ml",
    "tolerance": 0.3
   },
   "display": {
    "en": "60 ml vinegar for the daqqa",
    "ar": "60 مل خل للدقة"
   }
  },
  {
   "ref": "water_daqqa",
   "ingredientId": "cw.ing.water",
   "qty": {
    "value": 60,
    "unit": "ml",
    "tolerance": 0.3
   },
   "display": {
    "en": "60 ml water for the daqqa",
    "ar": "60 مل ماء للدقة"
   }
  },
  {
   "ref": "salt_rice",
   "ingredientId": "cw.ing.salt",
   "qty": {
    "value": 4,
    "unit": "g",
    "tolerance": 0.3
   },
   "display": {
    "en": "1 tsp salt, for the rice",
    "ar": "ملعقة صغيرة ملح للأرز"
   },
   "scaling": "sublinear",
   "toTaste": true
  },
  {
   "ref": "salt_sauce",
   "ingredientId": "cw.ing.salt",
   "qty": {
    "value": 4,
    "unit": "g",
    "tolerance": 0.3
   },
   "display": {
    "en": "1 tsp salt, for the sauce",
    "ar": "ملعقة صغيرة ملح للصلصة"
   },
   "scaling": "sublinear",
   "toTaste": true
  },
  {
   "ref": "cumin_daqqa",
   "ingredientId": "cw.ing.cumin_ground",
   "qty": {
    "value": 2,
    "unit": "g",
    "tolerance": 0.3
   },
   "display": {
    "en": "1 tsp cumin, for the daqqa",
    "ar": "ملعقة صغيرة كمون للدقة"
   },
   "scaling": "sublinear"
  },
  {
   "ref": "oil_spice",
   "ingredientId": "cw.ing.vegetable_oil",
   "qty": {
    "value": 15,
    "unit": "ml",
    "tolerance": 0.3
   },
   "display": {
    "en": "1 tbsp of the hot frying oil",
    "ar": "ملعقة كبيرة من زيت القلي الساخن"
   }
  }
 ],
 "equipment": [
  {
   "ref": "pot_rice",
   "class": "cw.eq.vessel.pot.sauce",
   "constraints": {
    "capacityMl": {
     "min": 2500
    },
    "lid": true
   }
  },
  {
   "ref": "pot_lentils",
   "class": "cw.eq.vessel.pot.sauce",
   "constraints": {
    "capacityMl": {
     "min": 2000
    },
    "lid": true
   }
  },
  {
   "ref": "pot_pasta",
   "class": "cw.eq.vessel.pot.stock",
   "constraints": {
    "capacityMl": {
     "min": 3000
    }
   }
  },
  {
   "ref": "pot_sauce",
   "class": "cw.eq.vessel.pot.sauce",
   "constraints": {
    "capacityMl": {
     "min": 1500
    }
   }
  },
  {
   "ref": "fryer",
   "class": "cw.eq.vessel.pot.fryer",
   "constraints": {
    "capacityMl": {
     "min": 2000
    }
   }
  },
  {
   "ref": "hob",
   "class": "cw.eq.heat.hob",
   "constraints": {
    "powerW": {
     "min": 2000
    }
   }
  },
  {
   "ref": "knife",
   "class": "cw.eq.tool.knife.chef"
  },
  {
   "ref": "board",
   "class": "cw.eq.tool.cutting_board"
  },
  {
   "ref": "colander",
   "class": "cw.eq.tool.colander"
  },
  {
   "ref": "skimmer",
   "class": "cw.eq.tool.skimmer"
  },
  {
   "ref": "bowl",
   "class": "cw.eq.tool.bowl.mixing"
  },
  {
   "ref": "oil_probe",
   "class": "cw.eq.sensor.probe"
  },
  {
   "ref": "spoon",
   "class": "cw.eq.tool.spoon.wooden"
  }
 ],
 "process": {
  "nodes": [
   {
    "id": "n1",
    "op": "cw.op.boil",
    "inputs": [
     "lentils",
     "water_lentils"
    ],
    "output": "lentils_boiling",
    "equipment": [
     "pot_lentils",
     "hob"
    ],
    "params": {
     "heat": "high",
     "lid": "off",
     "target": {
      "sensor": "cw.sense.liquid_temp",
      "value": 100,
      "unit": "degC",
      "tolerance": 2
     }
    },
    "until": {
     "any": [
      {
       "sensor": "cw.sense.liquid_temp",
       "gte": 98
      },
      {
       "vision": "cw.sense.boil_detect"
      }
     ],
     "minTime": "PT5M",
     "maxTime": "PT12M"
    },
    "onTimeout": "extend",
    "hazards": [
     "hz_boilover",
     "hz_steam"
    ],
    "attention": "monitor"
   },
   {
    "id": "n2",
    "op": "cw.op.simmer",
    "inputs": [
     "lentils_boiling"
    ],
    "output": "lentils_cooked",
    "params": {
     "heat": "low",
     "lid": "ajar",
     "target": {
      "sensor": "cw.sense.liquid_temp",
      "value": 92,
      "unit": "degC",
      "tolerance": 4
     }
    },
    "until": {
     "all": [
      {
       "vision": "cw.sense.lentils_tender_whole"
      }
     ],
     "minTime": "PT20M",
     "maxTime": "PT30M"
    },
    "onTimeout": "ask_human",
    "hazards": [
     "hz_steam"
    ],
    "attention": "periodic"
   },
   {
    "id": "n3",
    "op": "cw.op.drain",
    "inputs": [
     "lentils_cooked"
    ],
    "output": "lentils_drained",
    "equipment": [
     "colander"
    ],
    "params": {
     "keepLiquid": false
    },
    "hazards": [
     "hz_hot_liquid"
    ]
   },
   {
    "id": "n4",
    "op": "cw.op.boil",
    "inputs": [
     "water_pasta",
     "salt"
    ],
    "output": "water_salted_boiling",
    "equipment": [
     "pot_pasta",
     "hob"
    ],
    "params": {
     "heat": "high",
     "lid": "off",
     "target": {
      "sensor": "cw.sense.liquid_temp",
      "value": 100,
      "unit": "degC",
      "tolerance": 2
     }
    },
    "until": {
     "any": [
      {
       "sensor": "cw.sense.liquid_temp",
       "gte": 98
      },
      {
       "vision": "cw.sense.boil_detect"
      }
     ],
     "minTime": "PT6M",
     "maxTime": "PT15M"
    },
    "onTimeout": "extend",
    "hazards": [
     "hz_boilover",
     "hz_steam"
    ],
    "attention": "monitor"
   },
   {
    "id": "n5",
    "op": "cw.op.boil",
    "inputs": [
     "water_salted_boiling",
     "macaroni"
    ],
    "output": "pasta_cooked",
    "params": {
     "heat": "high",
     "lid": "off",
     "stir": {
      "intervalS": 90
     },
     "target": {
      "sensor": "cw.sense.liquid_temp",
      "value": 100,
      "unit": "degC",
      "tolerance": 2
     }
    },
    "until": {
     "all": [
      {
       "vision": "cw.sense.pasta_al_dente"
      }
     ],
     "minTime": "PT8M",
     "maxTime": "PT11M"
    },
    "onTimeout": "ask_human",
    "hazards": [
     "hz_boilover",
     "hz_steam"
    ],
    "attention": "monitor"
   },
   {
    "id": "n6",
    "op": "cw.op.drain",
    "inputs": [
     "pasta_cooked"
    ],
    "output": "pasta_drained",
    "equipment": [
     "colander"
    ],
    "params": {
     "keepLiquid": false
    },
    "hazards": [
     "hz_hot_liquid"
    ]
   },
   {
    "id": "n7",
    "op": "cw.op.heat",
    "inputs": [
     "oil"
    ],
    "output": "hot_oil",
    "equipment": [
     "pot_rice",
     "hob"
    ],
    "params": {
     "heat": "medium",
     "target": {
      "sensor": "cw.sense.pan_surface_temp",
      "value": 165,
      "unit": "degC",
      "tolerance": 15
     }
    },
    "until": {
     "any": [
      {
       "sensor": "cw.sense.pan_surface_temp",
       "gte": 150
      },
      {
       "vision": "cw.sense.oil_shimmer"
      }
     ],
     "minTime": "PT1M",
     "maxTime": "PT3M"
    },
    "onTimeout": "extend",
    "hazards": [
     "hz_oil"
    ],
    "attention": "continuous"
   },
   {
    "id": "n8",
    "op": "cw.op.toast",
    "inputs": [
     "hot_oil",
     "vermicelli"
    ],
    "output": "vermicelli_golden",
    "params": {
     "heat": "medium",
     "stir": {
      "intervalS": 15
     },
     "target": {
      "sensor": "cw.sense.pan_surface_temp",
      "value": 165,
      "unit": "degC",
      "tolerance": 20
     }
    },
    "until": {
     "all": [
      {
       "vision": "cw.sense.color_golden",
       "target": "vermicelli"
      }
     ],
     "minTime": "PT2M",
     "maxTime": "PT4M"
    },
    "onTimeout": "ask_human",
    "hazards": [
     "hz_oil",
     "hz_scorch"
    ],
    "attention": "continuous"
   },
   {
    "id": "n9",
    "op": "cw.op.boil",
    "inputs": [
     "vermicelli_golden",
     "rice",
     "water_rice",
     "salt_rice"
    ],
    "output": "rice_boiling",
    "params": {
     "heat": "high",
     "lid": "off",
     "target": {
      "sensor": "cw.sense.liquid_temp",
      "value": 100,
      "unit": "degC",
      "tolerance": 2
     }
    },
    "until": {
     "any": [
      {
       "sensor": "cw.sense.liquid_temp",
       "gte": 98
      },
      {
       "vision": "cw.sense.boil_detect"
      }
     ],
     "minTime": "PT2M",
     "maxTime": "PT8M"
    },
    "onTimeout": "extend",
    "hazards": [
     "hz_steam"
    ],
    "attention": "monitor"
   },
   {
    "id": "n10",
    "op": "cw.op.simmer",
    "inputs": [
     "rice_boiling"
    ],
    "output": "rice_cooked",
    "params": {
     "heat": "very_low",
     "lid": "on",
     "target": {
      "sensor": "cw.sense.liquid_temp",
      "value": 94,
      "unit": "degC",
      "tolerance": 2
     }
    },
    "until": {
     "all": [
      {
       "vision": "cw.sense.liquid_absorbed"
      }
     ],
     "minTime": "PT12M",
     "maxTime": "PT16M"
    },
    "onTimeout": "ask_human",
    "hazards": [
     "hz_scorch"
    ],
    "attention": "periodic"
   },
   {
    "id": "n11",
    "op": "cw.op.cut",
    "inputs": [
     "onions_fry"
    ],
    "output": "onions_sliced",
    "equipment": [
     "knife",
     "board"
    ],
    "params": {
     "shape": "slice",
     "size": {
      "value": 2,
      "unit": "mm"
     }
    },
    "hazards": [
     "hz_knife"
    ]
   },
   {
    "id": "n12",
    "op": "cw.op.mix",
    "inputs": [
     "onions_sliced",
     "flour"
    ],
    "output": "onions_floured",
    "equipment": [
     "bowl"
    ],
    "params": {
     "speed": "gentle",
     "untilEven": true
    },
    "hazards": [
     "hz_allergen_gluten"
    ]
   },
   {
    "id": "n13",
    "op": "cw.op.heat",
    "inputs": [
     "frying_oil"
    ],
    "output": "frying_oil_hot",
    "equipment": [
     "fryer",
     "hob",
     "oil_probe"
    ],
    "params": {
     "heat": "medium_high",
     "target": {
      "sensor": "cw.sense.oil_temp",
      "value": 175,
      "unit": "degC",
      "tolerance": 10
     }
    },
    "until": {
     "all": [
      {
       "sensor": "cw.sense.oil_temp",
       "gte": 170
      }
     ],
     "minTime": "PT4M",
     "maxTime": "PT10M"
    },
    "onTimeout": "extend",
    "hazards": [
     "hz_deep_oil"
    ],
    "attention": "continuous",
    "notes": {
     "en": "Oil no more than half way up the pot. An oil thermometer is required; without one this step is refused."
    }
   },
   {
    "id": "n14",
    "op": "cw.op.deep_fry",
    "inputs": [
     "frying_oil_hot",
     "onions_floured"
    ],
    "output": "onions_crisp",
    "equipment": [
     "fryer",
     "hob",
     "oil_probe",
     "skimmer"
    ],
    "params": {
     "heat": "medium_high",
     "oilTempC": 175,
     "batchMaxG": 130,
     "target": {
      "sensor": "cw.sense.oil_temp",
      "value": 175,
      "unit": "degC",
      "tolerance": 10
     },
     "stir": {
      "intervalS": 20,
      "style": "gentle"
     }
    },
    "until": {
     "all": [
      {
       "vision": "cw.sense.color_golden_brown",
       "target": "onions_floured"
      }
     ],
     "minTime": "PT5M",
     "maxTime": "PT9M"
    },
    "onTimeout": "ask_human",
    "hazards": [
     "hz_deep_oil",
     "hz_splatter"
    ],
    "attention": "continuous",
    "notes": {
     "en": "Fry in batches; lift out when deep golden, before they darken. Drain on paper."
    }
   },
   {
    "id": "n15",
    "op": "cw.op.crush",
    "inputs": [
     "garlic"
    ],
    "output": "garlic_crushed",
    "params": {
     "texture": "paste"
    }
   },
   {
    "id": "n16",
    "op": "cw.op.saute",
    "inputs": [
     "oil_spice",
     "garlic_crushed",
     "cumin",
     "coriander",
     "chili"
    ],
    "output": "spice_base",
    "equipment": [
     "pot_sauce",
     "hob"
    ],
    "params": {
     "heat": "medium_low",
     "stir": {
      "intervalS": 10
     },
     "target": {
      "sensor": "cw.sense.pan_surface_temp",
      "value": 155,
      "unit": "degC",
      "tolerance": 10
     }
    },
    "until": {
     "all": [
      {
       "vision": "cw.sense.fragrant_no_browning"
      }
     ],
     "minTime": "PT30S",
     "maxTime": "PT60S"
    },
    "onTimeout": "extend",
    "hazards": [
     "hz_oil"
    ],
    "attention": "continuous",
    "notes": {
     "en": "Use a spoonful of the hot frying oil."
    }
   },
   {
    "id": "n17",
    "op": "cw.op.simmer",
    "inputs": [
     "spice_base",
     "tomato",
     "vinegar",
     "salt_sauce"
    ],
    "output": "sauce",
    "params": {
     "heat": "medium_low",
     "lid": "off",
     "target": {
      "sensor": "cw.sense.liquid_temp",
      "value": 92,
      "unit": "degC",
      "tolerance": 4
     },
     "stir": {
      "intervalS": 120
     }
    },
    "until": {
     "any": [
      {
       "vision": "cw.sense.sauce_coats_spoon"
      },
      {
       "sensor": "cw.sense.mass_loss_ratio",
       "gte": 0.15
      }
     ],
     "minTime": "PT12M",
     "maxTime": "PT20M"
    },
    "onTimeout": "extend",
    "hazards": [
     "hz_splatter",
     "hz_steam"
    ],
    "attention": "periodic"
   },
   {
    "id": "n18",
    "op": "cw.op.mix",
    "inputs": [
     "garlic_daqqa",
     "vinegar_daqqa",
     "water_daqqa",
     "cumin_daqqa"
    ],
    "output": "daqqa",
    "equipment": [
     "bowl"
    ],
    "params": {
     "untilEven": true
    },
    "notes": {
     "en": "Crush the garlic into the vinegar and water; a pinch of cumin and salt."
    }
   },
   {
    "id": "n19",
    "op": "cw.op.layer",
    "inputs": [
     "rice_cooked",
     "lentils_drained",
     "pasta_drained",
     "chickpeas",
     "sauce",
     "onions_crisp"
    ],
    "output": "koshari",
    "params": {
     "order": [
      "rice_cooked",
      "lentils_drained",
      "pasta_drained",
      "chickpeas",
      "sauce",
      "onions_crisp"
     ]
    }
   },
   {
    "id": "n20",
    "op": "cw.op.serve",
    "inputs": [
     "koshari",
     "daqqa"
    ],
    "params": {
     "serveWithin": "PT30M",
     "keepHot": {
      "gte": 60,
      "unit": "degC"
     }
    }
   }
  ],
  "edges": "implicit-from-inputs",
  "parallelGroups": [
   [
    "n1",
    "n4",
    "n7",
    "n11"
   ],
   [
    "n2",
    "n5",
    "n9"
   ],
   [
    "n15",
    "n18"
   ]
  ]
 },
 "safety": {
  "hazards": [
   {
    "id": "hz_knife",
    "type": "cw.hz.cut.knife",
    "severity": "medium",
    "mitigation": [
     "keep_human_clear_of_blade",
     "stable_board"
    ]
   },
   {
    "id": "hz_oil",
    "type": "cw.hz.burn.hot_oil",
    "severity": "high",
    "mitigation": [
     "oil_temp_max_200C",
     "lid_ready",
     "no_water_contact"
    ]
   },
   {
    "id": "hz_deep_oil",
    "type": "cw.hz.fire.oil",
    "severity": "critical",
    "mitigation": [
     "oil_temp_sensor_required",
     "fill_max_50pct",
     "dry_food_before_frying",
     "lid_and_extinguisher_within_reach"
    ],
    "limits": {
     "oilTempMaxC": 190,
     "maxFillPct": 50
    }
   },
   {
    "id": "hz_splatter",
    "type": "cw.hz.splatter",
    "severity": "low",
    "mitigation": [
     "partial_lid"
    ]
   },
   {
    "id": "hz_steam",
    "type": "cw.hz.burn.steam",
    "severity": "medium",
    "mitigation": [
     "lift_lid_away_from_user"
    ]
   },
   {
    "id": "hz_scorch",
    "type": "cw.hz.scorch",
    "severity": "low",
    "mitigation": [
     "stir_bottom",
     "lowest_heat_for_lid_on_steps"
    ]
   },
   {
    "id": "hz_boilover",
    "type": "cw.hz.boilover",
    "severity": "medium",
    "mitigation": [
     "pot_max_fill_66pct",
     "reduce_heat_at_boil"
    ]
   },
   {
    "id": "hz_hot_liquid",
    "type": "cw.hz.burn.hot_liquid",
    "severity": "high",
    "mitigation": [
     "blend_below_rim",
     "immersion_blender_fully_submerged",
     "move_pot_off_heat"
    ]
   },
   {
    "id": "hz_allergen_gluten",
    "type": "cw.hz.allergen.cross_contact",
    "severity": "medium",
    "mitigation": [
     "clean_surfaces_after_flour"
    ]
   }
  ],
  "ccps": [
   {
    "id": "ccp_hot_oil",
    "hazard": "fire.oil",
    "node": "n14",
    "criticalLimit": "oil temperature between 160 °C and 190 °C, measured; never above 190 °C; pot at most half full",
    "limit": {
     "sensor": "cw.sense.oil_temp",
     "lte": 190
    },
    "monitoring": [
     "cw.sense.oil_temp"
    ],
    "corrective": "heat off immediately above 190 °C; lid on; never water"
   },
   {
    "id": "ccp_rice_time",
    "hazard": "toxin.bacillus_cereus",
    "node": "n20",
    "criticalLimit": "serve within 30 minutes or cool leftovers from 60 °C to 21 °C within 2 h and refrigerate within 4 h",
    "monitoring": [
     "time",
     "cw.sense.core_temp"
    ],
    "corrective": "discard rice and pasta left at room temperature for more than 2 h"
   }
  ],
  "allergens": {
   "eu14": [
    "cereals_gluten"
   ],
   "us9": [
    "wheat"
   ],
   "mayContain": []
  },
  "dietary": [
   {
    "claim": "halal",
    "basis": "ingredients",
    "ruleset": "cw.ruleset.halal.v1"
   },
   {
    "claim": "vegan",
    "basis": "ingredients"
   },
   {
    "claim": "nut_free",
    "basis": "ingredients"
   }
  ],
  "supervision": {
   "default": "hands_on_required",
   "reasons": {
    "n13": "deep-frying oil",
    "n14": "deep-frying oil",
    "n8": "burns in seconds",
    "n3": "hot liquid",
    "n6": "hot liquid"
   }
  },
  "abort": {
   "steps": [
    "heat_off",
    "lid_on",
    "move_pan_to_cool_zone_if_capable",
    "alert_user",
    "call_emergency_services_if_fire"
   ],
   "neverLeave": [
    "n7",
    "n8",
    "n13",
    "n14",
    "n16"
   ]
  }
 },
 "nutrition": {
  "perServing": {
   "kcal": 620,
   "protein": 20,
   "fat": 16,
   "carbs": 100,
   "fiber": 12,
   "sugar": 9,
   "sodiumMg": 780
  },
  "basis": "Typical composition tables, estimate per serving; not measured"
 },
 "storage": {
  "fridgeDays": 2,
  "freezerDays": 30,
  "reheat": {
   "minCoreC": 75,
   "method": "reheat components separately; onions stay crisp at room temperature for a day"
  },
  "coolingRequired": true
 },
 "text": {
  "en": {
   "title": "Koshari",
   "intro": "Cairo's street food: rice, lentils, pasta and chickpeas under spiced tomato sauce and crisp fried onions, with garlic vinegar on the side. The fried onions need an oil thermometer; a device without one refuses that step.",
   "steps": {
    "n1": "Bring the lentils and water to the boil.",
    "n2": "Simmer until tender but whole (20 to 30 minutes).",
    "n3": "Drain the lentils.",
    "n4": "Bring the salted pasta water to the boil.",
    "n5": "Cook the macaroni until al dente, stirring now and then.",
    "n6": "Drain the pasta.",
    "n7": "Heat the oil in the rice pot.",
    "n8": "Toast the vermicelli, stirring constantly, until golden.",
    "n9": "Add the rice, hot water and salt; bring to the boil.",
    "n10": "Lowest heat, lid on, until the water is absorbed (12 to 16 minutes).",
    "n11": "Slice the onions very thin.",
    "n12": "Toss the onions with the flour.",
    "n13": "Heat the frying oil to 175 °C, measured with a thermometer. The pot must be no more than half full.",
    "n14": "Deep-fry the onions in batches at 175 °C until deep golden brown (5 to 9 minutes a batch). Lift out with the skimmer and drain.",
    "n15": "Crush the garlic.",
    "n16": "Fry the garlic, cumin, coriander and chili in a spoon of hot oil for under a minute, until fragrant.",
    "n17": "Add the passata, vinegar and salt; simmer until the sauce thickens and coats a spoon (12 to 20 minutes).",
    "n18": "Make the daqqa: crushed garlic in vinegar and water with a pinch of cumin and salt.",
    "n19": "Layer rice, lentils, pasta and chickpeas; spoon sauce over; top with crisp onions.",
    "n20": "Serve hot with the daqqa and extra sauce on the side."
   }
  },
  "ar": {
   "title": "كشري",
   "intro": "أكلة شوارع القاهرة: أرز وعدس ومكرونة وحمص تحت صلصة طماطم متبلة وبصل مقرمش، مع الدقة بجانبها. البصل المقلي يحتاج ترمومتر زيت؛ والجهاز الذي لا يملكه يرفض هذه الخطوة.",
   "steps": {
    "n1": "اتركي العدس والماء حتى يغليا.",
    "n2": "اطهيه على نار هادئة حتى يلين ويبقى كاملًا (20 إلى 30 دقيقة).",
    "n3": "صفّي العدس.",
    "n4": "اتركي ماء المكرونة المملح حتى يغلي.",
    "n5": "اسلقي المكرونة حتى تنضج مع التقليب من حين لآخر.",
    "n6": "صفّي المكرونة.",
    "n7": "سخّني الزيت في حلة الأرز.",
    "n8": "حمّري الشعرية مع التقليب المستمر حتى تصبح ذهبية.",
    "n9": "أضيفي الأرز والماء الساخن والملح واتركيه يغلي.",
    "n10": "أقل نار، والغطاء محكم، حتى يتشرب الماء (12 إلى 16 دقيقة).",
    "n11": "قطّعي البصل شرائح رفيعة جدًا.",
    "n12": "قلّبي البصل مع الدقيق.",
    "n13": "سخّني زيت القلي إلى 175 درجة بالترمومتر. لا يتجاوز الزيت نصف الحلة.",
    "n14": "اقلي البصل على دفعات عند 175 درجة حتى يصبح ذهبيًا داكنًا (5 إلى 9 دقائق للدفعة). ارفعيه بالمصفاة وصفّيه.",
    "n15": "اهرسي الثوم.",
    "n16": "شوّحي الثوم والكمون والكسبرة والشطة في ملعقة من الزيت الساخن أقل من دقيقة حتى تفوح الرائحة.",
    "n17": "أضيفي عصير الطماطم والخل والملح واتركيه يطهو على نار هادئة حتى يثقل ويغلّف الملعقة (12 إلى 20 دقيقة).",
    "n18": "جهّزي الدقة: ثوم مهروس في الخل والماء مع رشة كمون وملح.",
    "n19": "رصّي الأرز ثم العدس ثم المكرونة ثم الحمص، واسكبي الصلصة، وزيّني بالبصل المقرمش.",
    "n20": "قدّميه ساخنًا مع الدقة وصلصة إضافية."
   }
  }
 },
 "source": {
  "name": "cookwala.ai",
  "url": "https://cookwala.ai/",
  "citation": "Cookwala example recipe, written for the standard"
 },
 "license": "CC-BY-4.0",
 "layers": {
  "r1": true,
  "r2": false,
  "r3": true
 },
 "identity": {
  "essential": [
   "rice",
   "lentils",
   "macaroni",
   "tomato",
   "onions_fry",
   "daqqa"
  ],
  "flexible": [
   "chickpeas",
   "chili",
   "vermicelli"
  ],
  "neverAdd": [
   "meat"
  ],
  "culturalNotes": {
   "en": "Everything is cooked separately and assembled at the table or in the bowl; the crisp onions are what make it koshari."
  }
 },
 "hash": "sha256:f7fc3745af51465fb7a849faa5b5927eeaa44030a703318bb293381fef8b3f45"
}
