{"abstract":"Evaluation reasons point at the rule after the one that actually matched.","category":"Feature flag rollout bucketing","checks":8,"contract":"An off flag serves its off variation (reason OFF). Otherwise individual targets (checked by sorted variation name) win with reason TARGET, then rules in order, then the fallthrough. A rule matches only when the user has its attribute: op in = membership, startsWith = case-sensitive string prefix, lt = numeric less-than any value; negate inverts a present attribute result. Return [variation, reason, zero-based rule index or -1].","evaluation_group":"w2-feature-flag-rollout-bucketing-targeting-precedence","failed_approach":"Counting only rules whose attribute is present renumbers rules after a skipped one.","family":"w2-feature-flag-rollout-bucketing-targeting-precedence-rule-index","id":"FA-73906","implementations":{"attempt":{"sha256":"a323e88e79e77bd7e51969738de22ba04cdf1f79da207a257edddc33694e5caf","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(flag, user):\n    if not flag.get('on'):\n        return [flag.get('off'), 'OFF', -1]\n    key = user.get('key')\n    for variation in sorted(flag.get('targets', {})):\n        if key in flag['targets'][variation]:\n            return [variation, 'TARGET', -1]\n    seen = -1\n    for index, rule in enumerate(flag.get('rules', [])):\n        if rule['attr'] not in user:\n            continue\n        seen += 1\n        value = user[rule['attr']]\n        if rule['op'] == 'in':\n            hit = value in rule['values']\n        elif rule['op'] == 'startsWith':\n            hit = isinstance(value, str) and any(value.startswith(v) for v in rule['values'])\n        else:\n            hit = isinstance(value, (int, float)) and not isinstance(value, bool) and any(value < v for v in rule['values'])\n        if rule.get('negate'):\n            hit = not hit\n        if hit:\n            return [rule['variation'], 'RULE', seen]\n    return [flag.get('fallthrough'), 'FALLTHROUGH', -1]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('individual target beats a matching rule',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': ['k1']},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['US'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k1', 'country': 'US'}],\n   ['v1', 'TARGET', -1]),\n  ('negated rule does not match a missing attribute',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k2'}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('off flag serves off variation',\n   [{'on': False, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []}, {'key': 'k1'}],\n   ['v1', 'OFF', -1]),\n  ('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('targeting sample 1',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': []},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['a', 'Ann'],\n                'negate': False,\n                'variation': 'v2'},\n               {'attr': 'age', 'op': 'lt', 'values': [21, 18], 'negate': False, 'variation': 'v0'},\n               {'attr': 'age', 'op': 'lt', 'values': [18, 30], 'negate': True, 'variation': 'v2'},\n               {'attr': 'email',\n                'op': 'startsWith',\n                'values': ['a', 'Ann'],\n                'negate': False,\n                'variation': 'v2'}]},\n    {'key': 'k2', 'country': 'DE', 'age': 20, 'plan': 'team'}],\n   ['v0', 'RULE', 1]),\n  ('targeting sample 2',\n   [{'on': True, 'off': 'v1', 'fallthrough': 'v0', 'targets': {'v2': []}, 'rules': []},\n    {'key': 'k6', 'age': 40, 'plan': 'pro'}],\n   ['v0', 'FALLTHROUGH', -1])],\n [('negated rule does not match a missing attribute',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k2'}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('off flag serves off variation',\n   [{'on': False, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []}, {'key': 'k1'}],\n   ['v1', 'OFF', -1]),\n  ('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('targeting sample 6',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [18, 65], 'negate': False, 'variation': 'v1'},\n               {'attr': 'plan', 'op': 'in', 'values': ['DE', 'free'], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k5', 'country': 'DE', 'plan': 'team'}],\n   ['v2', 'RULE', 1]),\n  ('targeting sample 7',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['FR', 'free'], 'negate': True, 'variation': 'v1'},\n               {'attr': 'plan', 'op': 'in', 'values': ['FR', 'US'], 'negate': False, 'variation': 'v0'}]},\n    {'key': 'k6', 'country': 'JP', 'email': 'annie', 'age': 17, 'plan': 'free'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('targeting sample 13',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v0',\n     'targets': {'v1': ['k3'], 'v2': ['k4']},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['DE', 'free'], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k5', 'country': 'US', 'email': 'qa-1@z.io', 'plan': 'team'}],\n   ['v2', 'RULE', 0])],\n [('off flag serves off variation',\n   [{'on': False, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []}, {'key': 'k1'}],\n   ['v1', 'OFF', -1]),\n  ('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('targeting sample 11',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v3',\n     'targets': {'v3': ['k2'], 'v2': ['k4', 'k2']},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['qa-', 'a'],\n                'negate': False,\n                'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE', 'FR'], 'negate': True, 'variation': 'v3'},\n               {'attr': 'email',\n                'op': 'startsWith',\n                'values': ['qa-', 'a'],\n                'negate': False,\n                'variation': 'v1'}]},\n    {'key': 'k6', 'email': 'annie', 'age': 40, 'plan': 'free'}],\n   ['v1', 'RULE', 0]),\n  ('targeting sample 23',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v1': ['k5', 'k3'], 'v2': []},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['ann', 'qa-'],\n                'negate': False,\n                'variation': 'v2'},\n               {'attr': 'plan', 'op': 'in', 'values': ['pro', 'DE'], 'negate': False, 'variation': 'v3'}]},\n    {'key': 'k2', 'age': 17, 'plan': 'pro'}],\n   ['v3', 'RULE', 1]),\n  ('targeting sample 35',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': [], 'v3': ['k3', 'k4']},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['ann', 'qa-'],\n                'negate': False,\n                'variation': 'v2'},\n               {'attr': 'age', 'op': 'lt', 'values': [65, 18], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k1', 'email': 'Ann@x.io', 'age': 70}],\n   ['v2', 'RULE', 1])],\n [('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('no rule matches uses fallthrough',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {'v1': ['k9']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [18], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 40}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('targeting sample 1',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': []},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['a', 'Ann'],\n                'negate': False,\n                'variation': 'v2'},\n               {'attr': 'age', 'op': 'lt', 'values': [21, 18], 'negate': False, 'variation': 'v0'},\n               {'attr': 'age', 'op': 'lt', 'values': [18, 30], 'negate': True, 'variation': 'v2'},\n               {'attr': 'email',\n                'op': 'startsWith',\n                'values': ['a', 'Ann'],\n                'negate': False,\n                'variation': 'v2'}]},\n    {'key': 'k2', 'country': 'DE', 'age': 20, 'plan': 'team'}],\n   ['v0', 'RULE', 1]),\n  ('targeting sample 16',\n   [{'on': True, 'off': 'v0', 'fallthrough': 'v2', 'targets': {}, 'rules': []},\n    {'key': 'k5', 'age': 40, 'plan': 'free'}],\n   ['v2', 'FALLTHROUGH', -1]),\n  ('targeting sample 17',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['ann', 'a'],\n                'negate': True,\n                'variation': 'v0'},\n               {'attr': 'plan', 'op': 'lt', 'values': [30, 18], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k6', 'country': 'JP', 'email': 'ann@x.io', 'plan': 'team'}],\n   ['v3', 'FALLTHROUGH', -1])],\n [('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('no rule matches uses fallthrough',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {'v1': ['k9']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [18], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 40}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('prefix operand order matters',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['annie@corp'],\n                'negate': False,\n                'variation': 'v1'}]},\n    {'key': 'k2', 'email': 'annie'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('targeting sample 14',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan',\n                'op': 'startsWith',\n                'values': ['bob', 'ann'],\n                'negate': False,\n                'variation': 'v3'},\n               {'attr': 'email',\n                'op': 'startsWith',\n                'values': ['bob', 'a'],\n                'negate': True,\n                'variation': 'v2'},\n               {'attr': 'email',\n                'op': 'startsWith',\n                'values': ['bob', 'a'],\n                'negate': False,\n                'variation': 'v3'}]},\n    {'key': 'k5', 'email': 'qa-1@z.io'}],\n   ['v2', 'RULE', 1]),\n  ('targeting sample 21',\n   [{'on': True, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []},\n    {'key': 'k3', 'email': 'qa-1@z.io', 'plan': 'free'}],\n   ['v2', 'FALLTHROUGH', -1]),\n  ('targeting sample 22',\n   [{'on': False, 'off': 'v0', 'fallthrough': 'v2', 'targets': {'v1': [], 'v3': ['k3']}, 'rules': []},\n    {'key': 'k6', 'country': 'DE', 'email': 'Ann@x.io', 'plan': 'team'}],\n   ['v0', 'OFF', -1])]]\nfor label, args, expected in fixtures[N - 1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"broken":{"sha256":"0e1ec2543579903018896064554553bc60687fadb68a5b1ec35fc44392af2829","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(flag, user):\n    if not flag.get('on'):\n        return [flag.get('off'), 'OFF', -1]\n    key = user.get('key')\n    for variation in sorted(flag.get('targets', {})):\n        if key in flag['targets'][variation]:\n            return [variation, 'TARGET', -1]\n    for index, rule in enumerate(flag.get('rules', [])):\n        if rule['attr'] not in user:\n            continue\n        value = user[rule['attr']]\n        if rule['op'] == 'in':\n            hit = value in rule['values']\n        elif rule['op'] == 'startsWith':\n            hit = isinstance(value, str) and any(value.startswith(v) for v in rule['values'])\n        else:\n            hit = isinstance(value, (int, float)) and not isinstance(value, bool) and any(value < v for v in rule['values'])\n        if rule.get('negate'):\n            hit = not hit\n        if hit:\n            return [rule['variation'], 'RULE', index + 1]\n    return [flag.get('fallthrough'), 'FALLTHROUGH', -1]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('individual target beats a matching rule',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': ['k1']},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['US'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k1', 'country': 'US'}],\n   ['v1', 'TARGET', -1]),\n  ('negated rule does not match a missing attribute',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k2'}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('off flag serves off variation',\n   [{'on': False, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []}, {'key': 'k1'}],\n   ['v1', 'OFF', -1]),\n  ('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('targeting sample 1',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': []},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['a', 'Ann'],\n                'negate': False,\n                'variation': 'v2'},\n               {'attr': 'age', 'op': 'lt', 'values': [21, 18], 'negate': False, 'variation': 'v0'},\n               {'attr': 'age', 'op': 'lt', 'values': [18, 30], 'negate': True, 'variation': 'v2'},\n               {'attr': 'email',\n                'op': 'startsWith',\n                'values': ['a', 'Ann'],\n                'negate': False,\n                'variation': 'v2'}]},\n    {'key': 'k2', 'country': 'DE', 'age': 20, 'plan': 'team'}],\n   ['v0', 'RULE', 1]),\n  ('targeting sample 2',\n   [{'on': True, 'off': 'v1', 'fallthrough': 'v0', 'targets': {'v2': []}, 'rules': []},\n    {'key': 'k6', 'age': 40, 'plan': 'pro'}],\n   ['v0', 'FALLTHROUGH', -1])],\n [('negated rule does not match a missing attribute',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k2'}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('off flag serves off variation',\n   [{'on': False, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []}, {'key': 'k1'}],\n   ['v1', 'OFF', -1]),\n  ('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('targeting sample 6',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [18, 65], 'negate': False, 'variation': 'v1'},\n               {'attr': 'plan', 'op': 'in', 'values': ['DE', 'free'], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k5', 'country': 'DE', 'plan': 'team'}],\n   ['v2', 'RULE', 1]),\n  ('targeting sample 7',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['FR', 'free'], 'negate': True, 'variation': 'v1'},\n               {'attr': 'plan', 'op': 'in', 'values': ['FR', 'US'], 'negate': False, 'variation': 'v0'}]},\n    {'key': 'k6', 'country': 'JP', 'email': 'annie', 'age': 17, 'plan': 'free'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('targeting sample 13',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v0',\n     'targets': {'v1': ['k3'], 'v2': ['k4']},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['DE', 'free'], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k5', 'country': 'US', 'email': 'qa-1@z.io', 'plan': 'team'}],\n   ['v2', 'RULE', 0])],\n [('off flag serves off variation',\n   [{'on': False, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []}, {'key': 'k1'}],\n   ['v1', 'OFF', -1]),\n  ('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('targeting sample 11',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v3',\n     'targets': {'v3': ['k2'], 'v2': ['k4', 'k2']},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['qa-', 'a'],\n                'negate': False,\n                'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE', 'FR'], 'negate': True, 'variation': 'v3'},\n               {'attr': 'email',\n                'op': 'startsWith',\n                'values': ['qa-', 'a'],\n                'negate': False,\n                'variation': 'v1'}]},\n    {'key': 'k6', 'email': 'annie', 'age': 40, 'plan': 'free'}],\n   ['v1', 'RULE', 0]),\n  ('targeting sample 23',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v1': ['k5', 'k3'], 'v2': []},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['ann', 'qa-'],\n                'negate': False,\n                'variation': 'v2'},\n               {'attr': 'plan', 'op': 'in', 'values': ['pro', 'DE'], 'negate': False, 'variation': 'v3'}]},\n    {'key': 'k2', 'age': 17, 'plan': 'pro'}],\n   ['v3', 'RULE', 1]),\n  ('targeting sample 35',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': [], 'v3': ['k3', 'k4']},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['ann', 'qa-'],\n                'negate': False,\n                'variation': 'v2'},\n               {'attr': 'age', 'op': 'lt', 'values': [65, 18], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k1', 'email': 'Ann@x.io', 'age': 70}],\n   ['v2', 'RULE', 1])],\n [('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('no rule matches uses fallthrough',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {'v1': ['k9']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [18], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 40}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('targeting sample 1',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': []},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['a', 'Ann'],\n                'negate': False,\n                'variation': 'v2'},\n               {'attr': 'age', 'op': 'lt', 'values': [21, 18], 'negate': False, 'variation': 'v0'},\n               {'attr': 'age', 'op': 'lt', 'values': [18, 30], 'negate': True, 'variation': 'v2'},\n               {'attr': 'email',\n                'op': 'startsWith',\n                'values': ['a', 'Ann'],\n                'negate': False,\n                'variation': 'v2'}]},\n    {'key': 'k2', 'country': 'DE', 'age': 20, 'plan': 'team'}],\n   ['v0', 'RULE', 1]),\n  ('targeting sample 16',\n   [{'on': True, 'off': 'v0', 'fallthrough': 'v2', 'targets': {}, 'rules': []},\n    {'key': 'k5', 'age': 40, 'plan': 'free'}],\n   ['v2', 'FALLTHROUGH', -1]),\n  ('targeting sample 17',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['ann', 'a'],\n                'negate': True,\n                'variation': 'v0'},\n               {'attr': 'plan', 'op': 'lt', 'values': [30, 18], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k6', 'country': 'JP', 'email': 'ann@x.io', 'plan': 'team'}],\n   ['v3', 'FALLTHROUGH', -1])],\n [('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('no rule matches uses fallthrough',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {'v1': ['k9']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [18], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 40}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('prefix operand order matters',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['annie@corp'],\n                'negate': False,\n                'variation': 'v1'}]},\n    {'key': 'k2', 'email': 'annie'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('targeting sample 14',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan',\n                'op': 'startsWith',\n                'values': ['bob', 'ann'],\n                'negate': False,\n                'variation': 'v3'},\n               {'attr': 'email',\n                'op': 'startsWith',\n                'values': ['bob', 'a'],\n                'negate': True,\n                'variation': 'v2'},\n               {'attr': 'email',\n                'op': 'startsWith',\n                'values': ['bob', 'a'],\n                'negate': False,\n                'variation': 'v3'}]},\n    {'key': 'k5', 'email': 'qa-1@z.io'}],\n   ['v2', 'RULE', 1]),\n  ('targeting sample 21',\n   [{'on': True, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []},\n    {'key': 'k3', 'email': 'qa-1@z.io', 'plan': 'free'}],\n   ['v2', 'FALLTHROUGH', -1]),\n  ('targeting sample 22',\n   [{'on': False, 'off': 'v0', 'fallthrough': 'v2', 'targets': {'v1': [], 'v3': ['k3']}, 'rules': []},\n    {'key': 'k6', 'country': 'DE', 'email': 'Ann@x.io', 'plan': 'team'}],\n   ['v0', 'OFF', -1])]]\nfor label, args, expected in fixtures[N - 1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"fixed":{"sha256":"022c664cbd29db6a049b71689d57e874976d3778c1e7fa08be79fd690569fdfd","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(flag, user):\n    if not flag.get('on'):\n        return [flag.get('off'), 'OFF', -1]\n    key = user.get('key')\n    for variation in sorted(flag.get('targets', {})):\n        if key in flag['targets'][variation]:\n            return [variation, 'TARGET', -1]\n    for index, rule in enumerate(flag.get('rules', [])):\n        if rule['attr'] not in user:\n            continue\n        value = user[rule['attr']]\n        if rule['op'] == 'in':\n            hit = value in rule['values']\n        elif rule['op'] == 'startsWith':\n            hit = isinstance(value, str) and any(value.startswith(v) for v in rule['values'])\n        else:\n            hit = isinstance(value, (int, float)) and not isinstance(value, bool) and any(value < v for v in rule['values'])\n        if rule.get('negate'):\n            hit = not hit\n        if hit:\n            return [rule['variation'], 'RULE', index]\n    return [flag.get('fallthrough'), 'FALLTHROUGH', -1]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('individual target beats a matching rule',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': ['k1']},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['US'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k1', 'country': 'US'}],\n   ['v1', 'TARGET', -1]),\n  ('negated rule does not match a missing attribute',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k2'}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('off flag serves off variation',\n   [{'on': False, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []}, {'key': 'k1'}],\n   ['v1', 'OFF', -1]),\n  ('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('targeting sample 1',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': []},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['a', 'Ann'],\n                'negate': False,\n                'variation': 'v2'},\n               {'attr': 'age', 'op': 'lt', 'values': [21, 18], 'negate': False, 'variation': 'v0'},\n               {'attr': 'age', 'op': 'lt', 'values': [18, 30], 'negate': True, 'variation': 'v2'},\n               {'attr': 'email',\n                'op': 'startsWith',\n                'values': ['a', 'Ann'],\n                'negate': False,\n                'variation': 'v2'}]},\n    {'key': 'k2', 'country': 'DE', 'age': 20, 'plan': 'team'}],\n   ['v0', 'RULE', 1]),\n  ('targeting sample 2',\n   [{'on': True, 'off': 'v1', 'fallthrough': 'v0', 'targets': {'v2': []}, 'rules': []},\n    {'key': 'k6', 'age': 40, 'plan': 'pro'}],\n   ['v0', 'FALLTHROUGH', -1])],\n [('negated rule does not match a missing attribute',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k2'}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('off flag serves off variation',\n   [{'on': False, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []}, {'key': 'k1'}],\n   ['v1', 'OFF', -1]),\n  ('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('targeting sample 6',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [18, 65], 'negate': False, 'variation': 'v1'},\n               {'attr': 'plan', 'op': 'in', 'values': ['DE', 'free'], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k5', 'country': 'DE', 'plan': 'team'}],\n   ['v2', 'RULE', 1]),\n  ('targeting sample 7',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['FR', 'free'], 'negate': True, 'variation': 'v1'},\n               {'attr': 'plan', 'op': 'in', 'values': ['FR', 'US'], 'negate': False, 'variation': 'v0'}]},\n    {'key': 'k6', 'country': 'JP', 'email': 'annie', 'age': 17, 'plan': 'free'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('targeting sample 13',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v0',\n     'targets': {'v1': ['k3'], 'v2': ['k4']},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['DE', 'free'], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k5', 'country': 'US', 'email': 'qa-1@z.io', 'plan': 'team'}],\n   ['v2', 'RULE', 0])],\n [('off flag serves off variation',\n   [{'on': False, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []}, {'key': 'k1'}],\n   ['v1', 'OFF', -1]),\n  ('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('targeting sample 11',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v3',\n     'targets': {'v3': ['k2'], 'v2': ['k4', 'k2']},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['qa-', 'a'],\n                'negate': False,\n                'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE', 'FR'], 'negate': True, 'variation': 'v3'},\n               {'attr': 'email',\n                'op': 'startsWith',\n                'values': ['qa-', 'a'],\n                'negate': False,\n                'variation': 'v1'}]},\n    {'key': 'k6', 'email': 'annie', 'age': 40, 'plan': 'free'}],\n   ['v1', 'RULE', 0]),\n  ('targeting sample 23',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v1': ['k5', 'k3'], 'v2': []},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['ann', 'qa-'],\n                'negate': False,\n                'variation': 'v2'},\n               {'attr': 'plan', 'op': 'in', 'values': ['pro', 'DE'], 'negate': False, 'variation': 'v3'}]},\n    {'key': 'k2', 'age': 17, 'plan': 'pro'}],\n   ['v3', 'RULE', 1]),\n  ('targeting sample 35',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': [], 'v3': ['k3', 'k4']},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['ann', 'qa-'],\n                'negate': False,\n                'variation': 'v2'},\n               {'attr': 'age', 'op': 'lt', 'values': [65, 18], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k1', 'email': 'Ann@x.io', 'age': 70}],\n   ['v2', 'RULE', 1])],\n [('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('no rule matches uses fallthrough',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {'v1': ['k9']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [18], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 40}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('targeting sample 1',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': []},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['a', 'Ann'],\n                'negate': False,\n                'variation': 'v2'},\n               {'attr': 'age', 'op': 'lt', 'values': [21, 18], 'negate': False, 'variation': 'v0'},\n               {'attr': 'age', 'op': 'lt', 'values': [18, 30], 'negate': True, 'variation': 'v2'},\n               {'attr': 'email',\n                'op': 'startsWith',\n                'values': ['a', 'Ann'],\n                'negate': False,\n                'variation': 'v2'}]},\n    {'key': 'k2', 'country': 'DE', 'age': 20, 'plan': 'team'}],\n   ['v0', 'RULE', 1]),\n  ('targeting sample 16',\n   [{'on': True, 'off': 'v0', 'fallthrough': 'v2', 'targets': {}, 'rules': []},\n    {'key': 'k5', 'age': 40, 'plan': 'free'}],\n   ['v2', 'FALLTHROUGH', -1]),\n  ('targeting sample 17',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['ann', 'a'],\n                'negate': True,\n                'variation': 'v0'},\n               {'attr': 'plan', 'op': 'lt', 'values': [30, 18], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k6', 'country': 'JP', 'email': 'ann@x.io', 'plan': 'team'}],\n   ['v3', 'FALLTHROUGH', -1])],\n [('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('no rule matches uses fallthrough',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {'v1': ['k9']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [18], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 40}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('prefix operand order matters',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['annie@corp'],\n                'negate': False,\n                'variation': 'v1'}]},\n    {'key': 'k2', 'email': 'annie'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('targeting sample 14',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan',\n                'op': 'startsWith',\n                'values': ['bob', 'ann'],\n                'negate': False,\n                'variation': 'v3'},\n               {'attr': 'email',\n                'op': 'startsWith',\n                'values': ['bob', 'a'],\n                'negate': True,\n                'variation': 'v2'},\n               {'attr': 'email',\n                'op': 'startsWith',\n                'values': ['bob', 'a'],\n                'negate': False,\n                'variation': 'v3'}]},\n    {'key': 'k5', 'email': 'qa-1@z.io'}],\n   ['v2', 'RULE', 1]),\n  ('targeting sample 21',\n   [{'on': True, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []},\n    {'key': 'k3', 'email': 'qa-1@z.io', 'plan': 'free'}],\n   ['v2', 'FALLTHROUGH', -1]),\n  ('targeting sample 22',\n   [{'on': False, 'off': 'v0', 'fallthrough': 'v2', 'targets': {'v1': [], 'v3': ['k3']}, 'rules': []},\n    {'key': 'k6', 'country': 'DE', 'email': 'Ann@x.io', 'plan': 'team'}],\n   ['v0', 'OFF', -1])]]\nfor label, args, expected in fixtures[N - 1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"}},"limitations":"A deterministic toy flag-evaluation model with a stipulated contract; it does not reproduce any vendor SDK byte for byte. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.","method":"Deterministic executable model with adversarial boundary fixtures.","provenance":{"created_by":"Failure Map","dependencies":"Python standard library","family":"w2-feature-flag-rollout-bucketing-targeting-precedence-rule-index","generated_at":"2026-09-29T14:48:51.876723+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Evaluation order decides whether QA allowlists, segment rules and defaults behave predictably.","repair":"Report the zero-based enumerate index of the matching rule.","root_cause":"The reason reports index + 1 although the contract uses zero-based rule positions.","sha256":"a03590c58fd2bd14698bccd9ff4b4dea2119a1f4507939d52ec2bea95da79d11","title":"Flag targeting precedence: Matched rule index is reported one-based · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":40.656,"exit_code":1,"observations":[{"actual":["v1","TARGET",-1],"check":"individual target beats a matching rule","expected":["v1","TARGET",-1],"passed":true},{"actual":["v3","FALLTHROUGH",-1],"check":"negated rule does not match a missing attribute","expected":["v3","FALLTHROUGH",-1],"passed":true},{"actual":["v1","OFF",-1],"check":"off flag serves off variation","expected":["v1","OFF",-1],"passed":true},{"actual":["v2","RULE",1],"check":"second rule reports index one","expected":["v2","RULE",1],"passed":true},{"actual":["v0","FALLTHROUGH",-1],"check":"prefix match is case sensitive","expected":["v0","FALLTHROUGH",-1],"passed":true},{"actual":["v2","RULE",0],"check":"rule index skips rules on absent attributes","expected":["v2","RULE",1],"passed":false},{"actual":["v0","RULE",0],"check":"targeting sample 1","expected":["v0","RULE",1],"passed":false},{"actual":["v0","FALLTHROUGH",-1],"check":"targeting sample 2","expected":["v0","FALLTHROUGH",-1],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"individual target beats a matching rule\", \"actual\": [\"v1\", \"TARGET\", -1], \"expected\": [\"v1\", \"TARGET\", -1], \"passed\": true}, {\"check\": \"negated rule does not match a missing attribute\", \"actual\": [\"v3\", \"FALLTHROUGH\", -1], \"expected\": [\"v3\", \"FALLTHROUGH\", -1], \"passed\": true}, {\"check\": \"off flag serves off variation\", \"actual\": [\"v1\", \"OFF\", -1], \"expected\": [\"v1\", \"OFF\", -1], \"passed\": true}, {\"check\": \"second rule reports index one\", \"actual\": [\"v2\", \"RULE\", 1], \"expected\": [\"v2\", \"RULE\", 1], \"passed\": true}, {\"check\": \"prefix match is case sensitive\", \"actual\": [\"v0\", \"FALLTHROUGH\", -1], \"expected\": [\"v0\", \"FALLTHROUGH\", -1], \"passed\": true}, {\"check\": \"rule index skips rules on absent attributes\", \"actual\": [\"v2\", \"RULE\", 0], \"expected\": [\"v2\", \"RULE\", 1], \"passed\": false}, {\"check\": \"targeting sample 1\", \"actual\": [\"v0\", \"RULE\", 0], \"expected\": [\"v0\", \"RULE\", 1], \"passed\": false}, {\"check\": \"targeting sample 2\", \"actual\": [\"v0\", \"FALLTHROUGH\", -1], \"expected\": [\"v0\", \"FALLTHROUGH\", -1], \"passed\": true}], \"passed\": false}\n"},"broken":{"elapsed_ms":40.055,"exit_code":1,"observations":[{"actual":["v1","TARGET",-1],"check":"individual target beats a matching rule","expected":["v1","TARGET",-1],"passed":true},{"actual":["v3","FALLTHROUGH",-1],"check":"negated rule does not match a missing attribute","expected":["v3","FALLTHROUGH",-1],"passed":true},{"actual":["v1","OFF",-1],"check":"off flag serves off variation","expected":["v1","OFF",-1],"passed":true},{"actual":["v2","RULE",2],"check":"second rule reports index one","expected":["v2","RULE",1],"passed":false},{"actual":["v0","FALLTHROUGH",-1],"check":"prefix match is case sensitive","expected":["v0","FALLTHROUGH",-1],"passed":true},{"actual":["v2","RULE",2],"check":"rule index skips rules on absent attributes","expected":["v2","RULE",1],"passed":false},{"actual":["v0","RULE",2],"check":"targeting sample 1","expected":["v0","RULE",1],"passed":false},{"actual":["v0","FALLTHROUGH",-1],"check":"targeting sample 2","expected":["v0","FALLTHROUGH",-1],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"individual target beats a matching rule\", \"actual\": [\"v1\", \"TARGET\", -1], \"expected\": [\"v1\", \"TARGET\", -1], \"passed\": true}, {\"check\": \"negated rule does not match a missing attribute\", \"actual\": [\"v3\", \"FALLTHROUGH\", -1], \"expected\": [\"v3\", \"FALLTHROUGH\", -1], \"passed\": true}, {\"check\": \"off flag serves off variation\", \"actual\": [\"v1\", \"OFF\", -1], \"expected\": [\"v1\", \"OFF\", -1], \"passed\": true}, {\"check\": \"second rule reports index one\", \"actual\": [\"v2\", \"RULE\", 2], \"expected\": [\"v2\", \"RULE\", 1], \"passed\": false}, {\"check\": \"prefix match is case sensitive\", \"actual\": [\"v0\", \"FALLTHROUGH\", -1], \"expected\": [\"v0\", \"FALLTHROUGH\", -1], \"passed\": true}, {\"check\": \"rule index skips rules on absent attributes\", \"actual\": [\"v2\", \"RULE\", 2], \"expected\": [\"v2\", \"RULE\", 1], \"passed\": false}, {\"check\": \"targeting sample 1\", \"actual\": [\"v0\", \"RULE\", 2], \"expected\": [\"v0\", \"RULE\", 1], \"passed\": false}, {\"check\": \"targeting sample 2\", \"actual\": [\"v0\", \"FALLTHROUGH\", -1], \"expected\": [\"v0\", \"FALLTHROUGH\", -1], \"passed\": true}], \"passed\": false}\n"},"fixed":{"elapsed_ms":40.375,"exit_code":0,"observations":[{"actual":["v1","TARGET",-1],"check":"individual target beats a matching rule","expected":["v1","TARGET",-1],"passed":true},{"actual":["v3","FALLTHROUGH",-1],"check":"negated rule does not match a missing attribute","expected":["v3","FALLTHROUGH",-1],"passed":true},{"actual":["v1","OFF",-1],"check":"off flag serves off variation","expected":["v1","OFF",-1],"passed":true},{"actual":["v2","RULE",1],"check":"second rule reports index one","expected":["v2","RULE",1],"passed":true},{"actual":["v0","FALLTHROUGH",-1],"check":"prefix match is case sensitive","expected":["v0","FALLTHROUGH",-1],"passed":true},{"actual":["v2","RULE",1],"check":"rule index skips rules on absent attributes","expected":["v2","RULE",1],"passed":true},{"actual":["v0","RULE",1],"check":"targeting sample 1","expected":["v0","RULE",1],"passed":true},{"actual":["v0","FALLTHROUGH",-1],"check":"targeting sample 2","expected":["v0","FALLTHROUGH",-1],"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"individual target beats a matching rule\", \"actual\": [\"v1\", \"TARGET\", -1], \"expected\": [\"v1\", \"TARGET\", -1], \"passed\": true}, {\"check\": \"negated rule does not match a missing attribute\", \"actual\": [\"v3\", \"FALLTHROUGH\", -1], \"expected\": [\"v3\", \"FALLTHROUGH\", -1], \"passed\": true}, {\"check\": \"off flag serves off variation\", \"actual\": [\"v1\", \"OFF\", -1], \"expected\": [\"v1\", \"OFF\", -1], \"passed\": true}, {\"check\": \"second rule reports index one\", \"actual\": [\"v2\", \"RULE\", 1], \"expected\": [\"v2\", \"RULE\", 1], \"passed\": true}, {\"check\": \"prefix match is case sensitive\", \"actual\": [\"v0\", \"FALLTHROUGH\", -1], \"expected\": [\"v0\", \"FALLTHROUGH\", -1], \"passed\": true}, {\"check\": \"rule index skips rules on absent attributes\", \"actual\": [\"v2\", \"RULE\", 1], \"expected\": [\"v2\", \"RULE\", 1], \"passed\": true}, {\"check\": \"targeting sample 1\", \"actual\": [\"v0\", \"RULE\", 1], \"expected\": [\"v0\", \"RULE\", 1], \"passed\": true}, {\"check\": \"targeting sample 2\", \"actual\": [\"v0\", \"FALLTHROUGH\", -1], \"expected\": [\"v0\", \"FALLTHROUGH\", -1], \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}