Diese Seite wurde maschinell übersetzt und wurde noch nicht von einer Person überprüft. Englisch ist die Referenz; Korrekturen auf GitHub sind willkommen. GitHub

Cookwala / SDK und Szenarien / 016

Read a recipe as a document: yield, allergens, steps, end conditions and a critical control point

A Cookwala recipe is a typed document a class can read without any device: how much it makes, which allergens it carries, which operation each step is, and the measurable condition that ends it.

Zielgruppe: teacher · Ziel: Menschen gesünder machen · Level: beginner

Zuerst lesen: /docs/RECIPE-FORMAT/ /docs/CORE/

Schritte

  1. Kofta in the oven: four servings, no declared allergens, ten steps; the bake ends when the core probe reads 71 degC, a critical control point for ground meat. getRecipe

  2. Shakshuka declares eggs under both the EU and US allergen lists and may be scaled from half to double. getRecipe

  3. The number in the recipe is not arbitrary: the default limits pack has the same 71 degC minimum for ground meat, with its source. safetyLimits

Ergebnis

You can show students where a safe temperature comes from and how a recipe states it as a condition a sensor can check. Next: scenario 036 looks at the knife-work rules in the vocabulary.

Kommandozeile

curl -s http://localhost:7878/v1/tools/recipes/kofta-oven
curl -s http://localhost:7878/v1/tools/recipes/shakshuka
curl -s http://localhost:7878/v1/safety-limits

Aufgezeichnete Ausgabe

Status: ok

[1] getRecipe: {"$schema": "https://cookwala.ai/v1/schemas/recipe.schema.json", "cookwala": "0.2.0", "id": "example-kofta-oven", "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": "Oven-baked beef kofta", "ar": "…
[2] getRecipe: {"$schema": "https://cookwala.ai/v1/schemas/recipe.schema.json", "cookwala": "0.1.0", "id": "example-shakshuka", "revision": 2, "updated": "2026-10-03", "hash": "sha256:2ea6fab93cc673fc6784f9bc9fe401d2387bb7779dc537df97286b73807c8841", "verification": {"level": "V2", "evidence": {"simulatorRuns": 1, "humanReviews": 1, "fieldReports": 0}, "reviewedBy": "fifi.cooking editorial", "notes": "Illustrative example for the spec; values are realistic but not field-verified."}, "dish": {"names": {"en": "Shakshuka", "ar": "شكشوكة", "fr": "Chakchouka"}, "cuisine": ["TN", "MA", "DZ", "LY"], "course": "main…
[3] safetyLimits: {"core": "0.2.0", "kind": "SafetyLimits", "id": "cookwala-default", "version": "0.2.0", "status": "draft", "limits": [{"id": "oil.max_temp", "kind": "max_temp", "action": "cut_heat", "message": "Cut heat above 200 °C: most cooking oils smoke and fire risk rises.", "source": "Common frying-oil smoke points; fire-safety practice", "appliesTo": {"medium": "oil", "ops": ["cw.op.fry", "cw.op.deep_fry"]}, "max": 200, "unit": "degC"}, {"id": "pan.max_surface", "kind": "max_temp", "action": "cut_heat", "message": "Cut heat above 280 °C pan surface (coatings degrade, oil ignites).", "source": "Cookware…

Code

Ausführen: python scenarios/out/016-read-a-recipe-as-a-document/python.py

# Scenario 016: Read a recipe as a document: yield, allergens, steps, end conditions and a critical control point
# A Cookwala recipe is a typed document a class can read without any device: how much it makes, which allergens it carries, which operation each step is, and the measurable condition that ends it.
# 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: Kofta in the oven: four servings, no declared allergens, ten steps; the bake ends when the core probe reads 71 degC, a critical control point for ground meat.
kofta = c.get_recipe("kofta-oven")
assert pick(kofta, "id") == "example-kofta-oven", pick(kofta, "id")
print("ok", "id", "=", "example-kofta-oven")
assert pick(kofta, "yield.servings") == 4, pick(kofta, "yield.servings")
print("ok", "yield.servings", "=", 4)
assert pick(kofta, "verification.level") == "V1", pick(kofta, "verification.level")
print("ok", "verification.level", "=", "V1")
assert pick(kofta, "safety.allergens.us9.length") == 0, pick(kofta, "safety.allergens.us9.length")
print("ok", "safety.allergens.us9.length", "=", 0)
assert pick(kofta, "process.nodes.length") == 10, pick(kofta, "process.nodes.length")
print("ok", "process.nodes.length", "=", 10)
assert pick(kofta, "process.nodes[7].op") == "cw.op.bake", pick(kofta, "process.nodes[7].op")
print("ok", "process.nodes[7].op", "=", "cw.op.bake")
assert pick(kofta, "process.nodes[7].params.tempC") == 200, pick(kofta, "process.nodes[7].params.tempC")
print("ok", "process.nodes[7].params.tempC", "=", 200)
assert pick(kofta, "process.nodes[7].until.all[0].sensor") == "cw.sense.core_temp", pick(kofta, "process.nodes[7].until.all[0].sensor")
print("ok", "process.nodes[7].until.all[0].sensor", "=", "cw.sense.core_temp")
assert pick(kofta, "process.nodes[7].until.all[0].gte") == 71, pick(kofta, "process.nodes[7].until.all[0].gte")
print("ok", "process.nodes[7].until.all[0].gte", "=", 71)
assert pick(kofta, "process.nodes[7].ccp") == "ccp_ground_meat", pick(kofta, "process.nodes[7].ccp")
print("ok", "process.nodes[7].ccp", "=", "ccp_ground_meat")

# Step 2: Shakshuka declares eggs under both the EU and US allergen lists and may be scaled from half to double.
shakshuka = c.get_recipe("shakshuka")
assert pick(shakshuka, "verification.level") == "V2", pick(shakshuka, "verification.level")
print("ok", "verification.level", "=", "V2")
assert pick(shakshuka, "safety.allergens.eu14[0]") == "eggs", pick(shakshuka, "safety.allergens.eu14[0]")
print("ok", "safety.allergens.eu14[0]", "=", "eggs")
assert pick(shakshuka, "safety.allergens.us9[0]") == "eggs", pick(shakshuka, "safety.allergens.us9[0]")
print("ok", "safety.allergens.us9[0]", "=", "eggs")
assert pick(shakshuka, "yield.scaling.minScale") == 0.5, pick(shakshuka, "yield.scaling.minScale")
print("ok", "yield.scaling.minScale", "=", 0.5)
assert pick(shakshuka, "yield.scaling.maxScale") == 2, pick(shakshuka, "yield.scaling.maxScale")
print("ok", "yield.scaling.maxScale", "=", 2)

# Step 3: The number in the recipe is not arbitrary: the default limits pack has the same 71 degC minimum for ground meat, with its source.
limits = c.safety_limits()
assert pick(limits, "limits[4].id") == "core.ground_meat", pick(limits, "limits[4].id")
print("ok", "limits[4].id", "=", "core.ground_meat")
assert pick(limits, "limits[4].min") == 71, pick(limits, "limits[4].min")
print("ok", "limits[4].min", "=", 71)
assert pick(limits, "limits[4].action") == "ask_human", pick(limits, "limits[4].action")
print("ok", "limits[4].action", "=", "ask_human")

print("scenario complete")

scenarios/016-read-a-recipe-as-a-document.json

Zurück: 015 Weiter: 017