{"record":{"id":"dea6d9c144efe79b","repo":"nextlevelbuilder/ui-ux-pro-max-skill","slug":"invalid-action-value","errorCode":null,"errorMessage":"invalid {} action value: {}","messagePattern":"invalid (.+?) action value: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/ui-ux-pro-max/scripts/reasoning_contract.py","lineNumber":94,"sourceCode":"        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):\n    \"\"\"Return deterministic mutations and an audit trail; never execute data.\"\"\"\n    normalized = str(query or \"\").casefold()\n    result = {\"activated\": [], \"style_ids\": [], \"constraints\": [],\n              \"pattern\": None, \"mode\": None}\n    for condition, actions in rules.items():\n        active = condition == \"must_have\" or any(\n            pattern.search(normalized)\n            for pattern in CONDITION_PATTERNS.get(condition, ()))\n        if not active:\n            continue\n        result[\"activated\"].append({\"condition\": condition, \"actions\": list(actions)})","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/nextlevelbuilder/ui-ux-pro-max-skill/blob/a38d04c3d5c298c851dbe5e6ee1965ee3de42cb5/src/ui-ux-pro-max/scripts/reasoning_contract.py#L76-L112","documentation":"For token-valued prefixes (TOKEN_ACTION_PREFIXES = {constraint, style}, reasoning_contract.py:47), the value after the colon must fully match TOKEN_RE = ^[a-z0-9]+(?:-[a-z0-9]+)*$ — lowercase kebab-case tokens only. Uppercase letters, underscores, spaces, leading/trailing hyphens, or slashes fail. The pattern: and mode: values are exempt (they have their own checks) which is why the message interpolates the specific prefix.","triggerScenarios":"_validate_action(\"style:Neo_Brutalism\"), \"constraint: no-large-images\" (space), \"constraint:ui/ux\" (slash), or \"style:-minimal\" (leading hyphen) — reached when parse_decision_rules iterates actions of any condition.","commonSituations":"Copying style IDs or constraint slugs from documentation that uses Title_Case or underscores; CSV cells preserving leading whitespace after a delimiter.","solutions":["Normalize the value to lowercase kebab-case: \"style:neo-brutalism\", \"constraint:no-large-images\".","Strip stray whitespace and leading/trailing hyphens before saving.","Cross-check style tokens against the actual style IDs in src/ui-ux-pro-max/data/styles.csv so the value also resolves at apply time."],"exampleFix":"// before\n{\"must_have\": [\"style:Neo_Brutalism\", \"constraint: no_large_images\"]}\n\n// after\n{\"must_have\": [\"style:neo-brutalism\", \"constraint:no-large-images\"]}","handlingStrategy":"validation","validationCode":"import re\nfrom src.ui_ux_pro_max.scripts.reasoning_contract import TOKEN_RE, TOKEN_ACTION_PREFIXES\nfor a in all_actions:\n    prefix, _, value = a.partition(\":\")\n    if prefix in TOKEN_ACTION_PREFIXES and not TOKEN_RE.fullmatch(value):\n        raise ValueError(f\"{a}: value must be lowercase kebab-case [a-z0-9-]; got {value!r}\")","typeGuard":"def is_kebab_token(value: str) -> bool:\n    return bool(re.fullmatch(r\"[a-z0-9]+(?:-[a-z0-9]+)*\", value))","tryCatchPattern":null,"preventionTips":["slugify values before composing rules: value.strip().lower().replace('_', '-').","Copy style/constraint tokens from styles.csv / canonical docs, not from prose."],"tags":["decision-rules","kebab-case","regex","validation"],"backgroundTag":null,"analyzedSha":"a38d04c3d5c298c851dbe5e6ee1965ee3de42cb5","analyzedAt":"2026-08-14T18:51:02.321Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}