{"record":{"id":"e138702641504ab1","repo":"nextlevelbuilder/ui-ux-pro-max-skill","slug":"unknown-decision-rule-condition","errorCode":null,"errorMessage":"unknown decision-rule condition: {}","messagePattern":"unknown decision-rule condition: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/ui-ux-pro-max/scripts/reasoning_contract.py","lineNumber":77,"sourceCode":"    result = {}\n    for key, value in pairs:\n        if key in result:\n            raise ValueError(\"duplicate decision-rule key: {}\".format(key))\n        result[key] = value\n    return result\n\n\ndef parse_decision_rules(raw):\n    \"\"\"Parse the canonical condition -> action-array representation.\"\"\"\n    try:\n        rules = json.loads(raw or \"{}\", object_pairs_hook=_object_without_duplicates)\n    except json.JSONDecodeError as error:\n        raise ValueError(\"invalid decision-rule JSON: {}\".format(error)) from error\n    if not isinstance(rules, dict):\n        raise ValueError(\"decision rules must be a JSON object\")\n    for condition, actions in rules.items():\n        if condition not in ALLOWED_CONDITIONS:\n            raise ValueError(\"unknown decision-rule condition: {}\".format(condition))\n        if not isinstance(actions, list) or not actions:\n            raise ValueError(\"{} must map to a non-empty action array\".format(condition))\n        for action in actions:\n            _validate_action(action)\n        if len(actions) != len(set(actions)):\n            raise ValueError(\"{} contains duplicate actions\".format(condition))\n    return rules\n\n\ndef _validate_action(action):\n    if not isinstance(action, str) or \":\" not in action:\n        raise ValueError(\"action must use a known prefix: {}\".format(action))\n    prefix, value = action.split(\":\", 1)\n    if prefix not in ACTION_PREFIXES:\n        raise ValueError(\"unknown decision-rule action: {}\".format(action))\n    if prefix in TOKEN_ACTION_PREFIXES and not TOKEN_RE.fullmatch(value):\n        raise ValueError(\"invalid {} action value: {}\".format(prefix, value))\n    if prefix == \"pattern\" and not value.strip():","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/nextlevelbuilder/ui-ux-pro-max-skill/blob/a38d04c3d5c298c851dbe5e6ee1965ee3de42cb5/src/ui-ux-pro-max/scripts/reasoning_contract.py#L59-L95","documentation":"Each top-level key must be a condition in ALLOWED_CONDITIONS, which is exactly {\"must_have\"} plus the 36 if_* signal conditions defined in CONDITION_SIGNALS (if_booking, if_mobile, if_ux_focused, ...). Any other key — a typo, a renamed condition, or free-form text — raises this ValueError naming the offending condition.","triggerScenarios":"parse_decision_rules with keys like \"if-Mobile\" (hyphen/case mismatch), \"if_mobile_ui\" (suffix typo), \"always\" (not in the closed set), or a condition added to CONDITION_SIGNALS only in a newer version while the payload was authored against an older (or newer) vocabulary.","commonSituations":"Hand-authoring rules against the README's condition list and mistyping one; upgrading the toolkit so the condition vocabulary changed while stale rule payloads remain in data files.","solutions":["Check the failing key against the allowed list in the message's source file: ALLOWED_CONDITIONS in src/ui-ux-pro-max/scripts/reasoning_contract.py:45.","Fix typos and casing: conditions are lowercase snake_case starting with if_ (or exactly \"must_have\").","If a new condition is genuinely needed, add its signal words to CONDITION_SIGNALS in the same file — the allowed set is derived from it — and update tests.","Remove conditions that no longer exist in the vocabulary instead of keeping them for forward-compatibility; the grammar is closed by design."],"exampleFix":"// before\n{\"if-Mobile\": [\"mode:dark\"], \"always\": [\"style:minimal\"]}\n\n// after\n{\"if_mobile\": [\"mode:dark\"], \"must_have\": [\"style:minimal\"]}","handlingStrategy":"validation","validationCode":"from src.ui_ux_pro_max.scripts.reasoning_contract import ALLOWED_CONDITIONS\nunknown = set(json.loads(raw)) - ALLOWED_CONDITIONS\nif unknown:\n    raise ValueError(f\"unknown conditions {sorted(unknown)}; allowed: {sorted(ALLOWED_CONDITIONS)}\")","typeGuard":"def is_known_condition(key: str) -> bool:\n    return key in ALLOWED_CONDITIONS  # {\"must_have\", *CONDITION_SIGNALS}","tryCatchPattern":"try:\n    rules = rc.parse_decision_rules(raw)\nexcept ValueError as exc:\n    if 'unknown decision-rule condition' in str(exc):\n        bad = str(exc).rsplit(\":\", 1)[-1].strip()\n        raw = json.dumps({k: v for k, v in json.loads(raw).items() if k in rc.ALLOWED_CONDITIONS})\n        # dropped condition logged; re-parse remaining rules\n        rules = rc.parse_decision_rules(raw)","preventionTips":["Generate rule payloads from ALLOWED_CONDITIONS at runtime instead of hardcoding key names.","Re-run the contract tests in scripts/tests after any change to CONDITION_SIGNALS so stale payloads fail in CI, not production.","Note the vocabulary is versioned with the toolkit: re-validate stored rule blobs after upgrades."],"tags":["decision-rules","validation","closed-vocabulary","typo"],"backgroundTag":null,"analyzedSha":"a38d04c3d5c298c851dbe5e6ee1965ee3de42cb5","analyzedAt":"2026-08-14T18:51:02.321Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}