Cookwala / حزمة التطوير والسيناريوهات / 034

The fryer robot plans koshari with every heat step verified by a sensor

With estimates forbidden, a robot that has a pan thermometer, a liquid thermometer and an oil thermometer still plans all twenty steps of koshari, none by estimate and none by a person. Then check the recipe's own frying target against the envelope.

الفئة: robot maker · الهدف: المساعدة في إنهاء الجوع, روبوتات في خدمة الناس · المستوى: beginner

اقرأ أولًا: /docs/CORE/ /docs/QUICKSTART/

الخطوات

  1. Estimates forbidden: boiling by liquid thermometer, heating by pan thermometer, deep frying by oil thermometer. dryRun

  2. The recipe asks for oil at 175 plus or minus 10 degC and limits each batch to 130 g. getRecipe

  3. A trace that holds the recipe target passes the envelope and the target. checkEnvelope

  4. Twenty steps, the deep fry by the device.

النتيجة

You have the sensor list a koshari robot needs to run with no estimates and no person doing a step, and the target it must hold. Next: scenario 022 shows the limit above that target.

سطر الأوامر

cookwala dryrun examples/koshari.cookwala.json --device examples/capabilities/demo-fryer-robot.json --human-present --no-model
curl -s http://localhost:7878/v1/tools/recipes/koshari
printf '[{"t": 0, "tempC": 160}, {"t": 30, "tempC": 172}, {"t": 60, "tempC": 176}, {"t": 90, "tempC": 174}]' > trace.json && cookwala envelope cw.op.deep_fry trace.json --target 175 --tolerance 10

المخرجات المسجلة

الحالة: ok

[1] dryRun: {"state": "accepted", "plan": [{"node": "n1", "op": "cw.op.boil", "by": "device", "verifiedBy": "sensor", "rung": "cw.sense.liquid_temp"}, {"node": "n2", "op": "cw.op.simmer", "by": "device", "verifiedBy": "sensor", "rung": "cw.sense.liquid_temp"}, {"node": "n3", "op": "cw.op.drain", "by": "device", "verifiedBy": "time", "rung": "time"}, {"node": "n4", "op": "cw.op.boil", "by": "device", "verifiedBy": "sensor", "rung": "cw.sense.liquid_temp"}, {"node": "n5", "op": "cw.op.boil", "by": "device", "verifiedBy": "sensor", "rung": "cw.sense.liquid_temp"}, {"node": "n6", "op": "cw.op.drain", "by": "d…
[2] getRecipe: {"$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"…
[3] checkEnvelope: {"envelopeOk": true, "targetOk": true, "reason": "ok"}

الكود

التشغيل: python scenarios/out/034-fryer-robot-without-estimates/python.py

# Scenario 034: The fryer robot plans koshari with every heat step verified by a sensor
# With estimates forbidden, a robot that has a pan thermometer, a liquid thermometer and an oil thermometer still plans all twenty steps of koshari, none by estimate and none by a person. Then check the recipe's own frying target against the envelope.
# Run a hub first: python hub/cookwala_hub.py --recipes examples
import json, os
from cookwala.client import CookwalaClient, CookwalaProblem

def load(path):
    with open(path, encoding="utf-8") as f:
        return json.load(f)

def pick(obj, path):
    for part in path.replace("]", "").replace("[", ".").split("."):
        obj = obj[int(part)] if part.isdigit() else (len(obj) if part == "length" else obj.get(part))
    return obj

c = CookwalaClient(os.environ.get("COOKWALA_HUB", "http://localhost:7878"))


# Step 1: Estimates forbidden: boiling by liquid thermometer, heating by pan thermometer, deep frying by oil thermometer.
plan = c.dry_run(recipe_id="koshari", device_id="demo-fryer-robot", human_present=True, allow_model=False)
assert pick(plan, "state") == "accepted", pick(plan, "state")
print("ok", "state", "=", "accepted")
assert pick(plan, "plan.length") == 20, pick(plan, "plan.length")
print("ok", "plan.length", "=", 20)
assert pick(plan, "plan[0].rung") == "cw.sense.liquid_temp", pick(plan, "plan[0].rung")
print("ok", "plan[0].rung", "=", "cw.sense.liquid_temp")
assert pick(plan, "plan[6].rung") == "cw.sense.pan_surface_temp", pick(plan, "plan[6].rung")
print("ok", "plan[6].rung", "=", "cw.sense.pan_surface_temp")
assert pick(plan, "plan[13].rung") == "cw.sense.oil_temp", pick(plan, "plan[13].rung")
print("ok", "plan[13].rung", "=", "cw.sense.oil_temp")
assert pick(plan, "plan[10].rung") == "cw.sense.vision", pick(plan, "plan[10].rung")
print("ok", "plan[10].rung", "=", "cw.sense.vision")

# Step 2: The recipe asks for oil at 175 plus or minus 10 degC and limits each batch to 130 g.
koshari = c.get_recipe("koshari")
assert pick(koshari, "process.nodes[13].op") == "cw.op.deep_fry", pick(koshari, "process.nodes[13].op")
print("ok", "process.nodes[13].op", "=", "cw.op.deep_fry")
assert pick(koshari, "process.nodes[13].params.target.value") == 175, pick(koshari, "process.nodes[13].params.target.value")
print("ok", "process.nodes[13].params.target.value", "=", 175)
assert pick(koshari, "process.nodes[13].params.target.tolerance") == 10, pick(koshari, "process.nodes[13].params.target.tolerance")
print("ok", "process.nodes[13].params.target.tolerance", "=", 10)
assert pick(koshari, "process.nodes[13].params.batchMaxG") == 130, pick(koshari, "process.nodes[13].params.batchMaxG")
print("ok", "process.nodes[13].params.batchMaxG", "=", 130)

# Step 3: A trace that holds the recipe target passes the envelope and the target.
trace = c.check_envelope("cw.op.deep_fry", [{"t": 0, "tempC": 160}, {"t": 60, "tempC": 172}, {"t": 120, "tempC": 176}, {"t": 180, "tempC": 174}], {"value": 175, "tolerance": 10})
assert pick(trace, "envelopeOk") == True, pick(trace, "envelopeOk")
print("ok", "envelopeOk", "=", True)
assert pick(trace, "targetOk") == True, pick(trace, "targetOk")
print("ok", "targetOk", "=", True)
assert pick(trace, "reason") == "ok", pick(trace, "reason")
print("ok", "reason", "=", "ok")

# Step 4: Twenty steps, the deep fry by the device.
assert pick(plan, "plan[13].by") == "device", pick(plan, "plan[13].by")
print("ok", "plan[13].by", "=", "device")
assert pick(plan, "plan[13].verifiedBy") == "sensor", pick(plan, "plan[13].verifiedBy")
print("ok", "plan[13].verifiedBy", "=", "sensor")

print("scenario complete")

scenarios/034-fryer-robot-without-estimates.json

السابق: 033 التالي: 035