{"record":{"id":"6c8696520d8f95c3","repo":"affaan-m/ECC","slug":"effect-recipe-must-declare-its-seeded-rng-algorithm","errorCode":null,"errorMessage":"effect recipe must declare its seeded RNG algorithm","messagePattern":"effect recipe must declare its seeded RNG algorithm","errorType":"validation","errorClass":"ContractError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/tasteforge/contract.py","lineNumber":185,"sourceCode":"        if not all(isinstance(signature[axis], list) for axis in _SIGNATURE_AXES):\n            raise ContractError(f\"genre {spec.get('number')} signature axes must be lists\")\n        if not all(signature[axis] for axis in _SIGNATURE_AXES):\n            raise ContractError(f\"genre {spec.get('number')} has an empty signature axis, including avoid\")\n\n\ndef validate_effect_recipe(\n    recipe: dict[str, Any], *, reference_durations: dict[str, float] | None = None\n) -> None:\n    \"\"\"Require a seeded aperiodic schedule and anchors on subject-aware effects.\"\"\"\n    if (recipe.get(\"dry_run\") is not True\n            or type(recipe.get(\"provider_calls\")) is not int\n            or recipe.get(\"provider_calls\") != 0\n            or recipe.get(\"provider_execution\") is not False):\n        raise ContractError(\"effect recipe crosses the dry-run provider boundary\")\n    if not isinstance(recipe.get(\"seed\"), int) or isinstance(recipe.get(\"seed\"), bool):\n        raise ContractError(\"effect recipe must have an integer seed\")\n    if recipe.get(\"rng_algorithm\") != \"python.random.Random/v1\":\n        raise ContractError(\"effect recipe must declare its seeded RNG algorithm\")\n    events = recipe.get(\"events\")\n    if not isinstance(events, list) or len(events) < 3:\n        raise ContractError(\"effect recipe needs at least three scheduled events\")\n    timeline = recipe.get(\"timeline_duration\")\n    if not _is_finite_real(timeline):\n        raise ContractError(\"effect recipe must declare a finite positive timeline duration\")\n    timeline = cast(float, timeline)\n    if float(timeline) <= 0:\n        raise ContractError(\"effect recipe must declare a finite positive timeline duration\")\n    for event in events:\n        start = event.get(\"time\")\n        duration = event.get(\"duration\")\n        if (not _is_finite_real(start) or not _is_finite_real(duration)\n                or float(start) < 0 or float(duration) <= 0):\n            raise ContractError(\"effect event start and duration must be finite positive timeline values\")\n        start = cast(float, start)\n        duration = cast(float, duration)\n        if float(start) + float(duration) > float(timeline) + 1e-9:","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/tasteforge/contract.py#L167-L203","documentation":"To keep schedules reproducible across runs and Python versions, the recipe must explicitly declare its RNG by setting rng_algorithm to the exact sentinel 'python.random.Random/v1'. Any other value (or a missing key) is rejected because the validator cannot guarantee the seed will be interpreted the same way.","triggerScenarios":"validate_effect_recipe called with a recipe missing 'rng_algorithm', or with values like 'random', 'secrets', 'numpy', or a different version tag such as 'python.random.Random/v2'.","commonSituations":"Recipes generated by older tool versions before the algorithm tag was introduced; switching RNG libraries; hand-edited recipes that omitted the field; typos in the algorithm string.","solutions":["Set recipe['rng_algorithm'] = 'python.random.Random/v1' exactly.","Regenerate the recipe with a current tasteforge generator that emits the algorithm tag.","Fix typos / version suffixes to match the accepted sentinel string."],"exampleFix":"# before\nrecipe[\"rng_algorithm\"] = \"random.Random\"\n# after\nrecipe[\"rng_algorithm\"] = \"python.random.Random/v1\"","handlingStrategy":"validation","validationCode":"if recipe.get(\"rng_algorithm\") != \"python.random.Random/v1\":\n    raise ValueError(\"recipe must declare rng_algorithm 'python.random.Random/v1'\")","typeGuard":"def declares_supported_rng(recipe: dict) -> bool:\n    return recipe.get(\"rng_algorithm\") == \"python.random.Random/v1\"","tryCatchPattern":"try:\n    validate_effect_recipe(recipe)\nexcept ContractError as exc:\n    if \"seeded RNG algorithm\" in str(exc):\n        recipe = {**recipe, \"rng_algorithm\": \"python.random.Random/v1\"}\n        validate_effect_recipe(recipe)\n    else:\n        raise","preventionTips":["Use a shared constant (RNG_ALGO = 'python.random.Random/v1') instead of literals.","Regenerate old recipes rather than hand-patching the algorithm tag.","Pin the generator version so emitted recipes always carry the tag."],"tags":["validation","rng","reproducibility"],"backgroundTag":"invalid-enum-value","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}