{"record":{"id":"01385f1d2a9e4ef4","repo":"nextlevelbuilder/ui-ux-pro-max-skill","slug":"contains-duplicate-actions","errorCode":null,"errorMessage":"{} contains duplicate actions","messagePattern":"(.+?) contains duplicate actions","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/ui-ux-pro-max/scripts/reasoning_contract.py","lineNumber":83,"sourceCode":"\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():\n        raise ValueError(\"pattern action must name a pattern\")\n    if prefix == \"mode\" and value not in {\"dark\", \"light\"}:\n        raise ValueError(\"mode action must be dark or light\")\n\n\ndef apply_decision_rules(rules, query):","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/nextlevelbuilder/ui-ux-pro-max-skill/blob/a38d04c3d5c298c851dbe5e6ee1965ee3de42cb5/src/ui-ux-pro-max/scripts/reasoning_contract.py#L65-L101","documentation":"After per-action validation, parse_decision_rules rejects action arrays containing repeated identical entries (checked via len(actions) != len(set(actions))). The rules must be a set-like list: duplicates would double-apply the same mutation and bloat the audit trail apply_decision_rules produces.","triggerScenarios":"Merging two rule lists with `actions_a + actions_b` without deduplicating, e.g. [\"style:minimal\", \"mode:dark\", \"style:minimal\"], or hand-editing a rule and re-adding an action that was already present.","commonSituations":"Programmatic composition of rule sets; copy-paste duplication while editing a long action array in a CSV cell.","solutions":["Remove the duplicate entry named by inspection of the condition's array.","Deduplicate while preserving order when merging: `list(dict.fromkeys(a + b))`.","Add a pre-save lint that calls parse_decision_rules on the payload so duplicates are caught before commit."],"exampleFix":"# before\nmerged = actions_a + actions_b\n\n# after\nmerged = list(dict.fromkeys(actions_a + actions_b))","handlingStrategy":"validation","validationCode":"import json\nrules = json.loads(raw)\nfor cond, actions in rules.items():\n    if len(actions) != len(set(actions)):\n        dupes = {a for a in actions if actions.count(a) > 1}\n        raise ValueError(f\"{cond} contains duplicate actions: {sorted(dupes)}\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Deduplicate with list(dict.fromkeys(actions)) whenever merging action arrays.","Run parse_decision_rules over composed rule sets in unit tests."],"tags":["decision-rules","duplicates","validation","json"],"backgroundTag":null,"analyzedSha":"a38d04c3d5c298c851dbe5e6ee1965ee3de42cb5","analyzedAt":"2026-08-14T18:51:02.321Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}