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

Validate a recipe, see an invalid one fail, and publish its hash

A publisher validates against the recipe schema (the one kind the hub checks in full), sees what a non-recipe gets back, and computes the hash that executors compare with ExecuteRequest.recipeHash.

الفئة: recipe publisher · الهدف: صحة أفضل للناس · المستوى: beginner

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

الخطوات

  1. Fetch koshari from the hub. getRecipe

  2. Validate it as a recipe: no errors. validate

  3. A document that is not a recipe fails with thirteen errors, one per required property plus the unknown field. validate

  4. The recipe's hash: an executor refuses a request whose recipeHash differs (recipe_hash_mismatch, scenario 097). hash

النتيجة

You can validate and hash before you publish, and put the hash in a registry entry. Next: 100 verifies a recall that travelled through a mirror.

سطر الأوامر

cookwala validate
cookwala hash examples/koshari.cookwala.json

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

الحالة: ok

[1] 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"…
[2] validate: {"ok": true, "errors": []}
[3] validate: {"ok": false, "errors": [": 'cookwala' is a required property", ": 'id' is a required property", ": 'revision' is a required property", ": 'verification' is a required property", ": 'dish' is a required property", ": 'yield' is a required property", ": 'ingredients' is a required property", ": 'equipment' is a required property", ": 'process' is a required property", ": 'safety' is a required property", ": 'text' is a required property", ": 'license' is a required property", ": 'nonsense' does not match any of the regexes: '^x-'"]}
[4] hash: {"hash": "sha256:f7fc3745af51465fb7a849faa5b5927eeaa44030a703318bb293381fef8b3f45"}

الكود

التشغيل: python scenarios/out/099-publisher-validates-and-hashes-a-recipe/python.py

# Scenario 099: Validate a recipe, see an invalid one fail, and publish its hash
# A publisher validates against the recipe schema (the one kind the hub checks in full), sees what a non-recipe gets back, and computes the hash that executors compare with ExecuteRequest.recipeHash.
# 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: Fetch koshari from the hub.
recipe = c.get_recipe("koshari")
assert pick(recipe, "id") == "example-koshari", pick(recipe, "id")
print("ok", "id", "=", "example-koshari")
assert pick(recipe, "cookwala") == "0.2.0", pick(recipe, "cookwala")
print("ok", "cookwala", "=", "0.2.0")

# Step 2: Validate it as a recipe: no errors.
valid = c.validate("recipe", recipe)
assert pick(valid, "ok") == True, pick(valid, "ok")
print("ok", "ok", "=", True)
assert pick(valid, "errors.length") == 0, pick(valid, "errors.length")
print("ok", "errors.length", "=", 0)

# Step 3: A document that is not a recipe fails with thirteen errors, one per required property plus the unknown field.
invalid = c.validate("recipe", {"nonsense": 1})
assert pick(invalid, "ok") == False, pick(invalid, "ok")
print("ok", "ok", "=", False)
assert pick(invalid, "errors.length") == 13, pick(invalid, "errors.length")
print("ok", "errors.length", "=", 13)

# Step 4: The recipe's hash: an executor refuses a request whose recipeHash differs (recipe_hash_mismatch, scenario 097).
h = c.hash(recipe)
assert pick(h, "hash") == "sha256:f7fc3745af51465fb7a849faa5b5927eeaa44030a703318bb293381fef8b3f45", pick(h, "hash")
print("ok", "hash", "=", "sha256:f7fc3745af51465fb7a849faa5b5927eeaa44030a703318bb293381fef8b3f45")

print("scenario complete")

scenarios/099-publisher-validates-and-hashes-a-recipe.json

السابق: 098 التالي: 100