{
  "description": "Allocation identity: `key` is the identifier, `name` is display-only. `contextualModel.coefficients` is keyed by allocation KEY. Every allocation in `policy_contextual_key` has a `name` that differs from its `key` (\"Treatment A\" vs \"treatment-a\") — an implementation that resolves coefficients by `name` finds nothing, falls back to `defaultAllocationScore` for EVERY arm, and degrades to a uniform softmax. These vectors are chosen so that uniform selection picks a different allocation than the correct distribution does, in all four cases. `policy_contextual_legacy` carries allocations with NO `key` at all (pre-key bundles) and coefficients keyed by name: the fallback `key ?? name` must keep resolving those, so it is a regression guard for the same change. THESE VALUES ARE HAND-DERIVED AND MUST NOT BE REGENERATED FROM AN IMPLEMENTATION — see test-vectors/README.md.",
  "bundle": "bundle_contextual_key_differs.json",
  "testCases": [
    {
      "name": "strong_treatment_a",
      "context": {
        "userId": "u-strong_treatment_a-0",
        "engagement_score": 6,
        "device_type": "mobile"
      },
      "expectedAssignments": {
        "ui.heroVariant": "hero_bold",
        "ui.ctaVariant": "cta_loud"
      },
      "expectedPolicies": {
        "policy_contextual_key": {
          "allocationName": "Treatment A",
          "allocationKey": "treatment-a",
          "scores": [0, 4, 0],
          "probabilities": [0.046963, 0.906074, 0.046963],
          "selectedIndex": 1,
          "seed": "ctx:u-strong_treatment_a-0:policy_contextual_key",
          "comment": "Control: 0 + 0*6 + mobile(0) = 0. Treatment A: 1.0 + 0.5*6 + mobile(0) = 4.0. Treatment B: 0 + 0*6 + mobile(0) = 0. Keying coefficients by name instead of key yields [0,0,0] -> uniform thirds -> selects Control."
        },
        "policy_contextual_legacy": {
          "allocationName": "cta_bold",
          "probabilities": [0.119203, 0.880797],
          "selectedIndex": 1
        }
      }
    },
    {
      "name": "mild_treatment_a",
      "context": {
        "userId": "u-mild_treatment_a-1",
        "engagement_score": 0,
        "device_type": "mobile"
      },
      "expectedAssignments": {
        "ui.heroVariant": "hero_bold",
        "ui.ctaVariant": "cta_loud"
      },
      "expectedPolicies": {
        "policy_contextual_key": {
          "allocationName": "Treatment A",
          "allocationKey": "treatment-a",
          "scores": [0, 1, 0],
          "probabilities": [0.211942, 0.576117, 0.211942],
          "selectedIndex": 1,
          "seed": "ctx:u-mild_treatment_a-1:policy_contextual_key",
          "comment": "Scores are the intercepts alone. A modest edge, so the floor never binds; name-keyed lookup gives uniform thirds -> selects Treatment B."
        },
        "policy_contextual_legacy": {
          "allocationName": "cta_bold",
          "probabilities": [0.119203, 0.880797],
          "selectedIndex": 1
        }
      }
    },
    {
      "name": "treatment_b_wins",
      "context": {
        "userId": "u-treatment_b_wins-1",
        "engagement_score": 0,
        "device_type": "desktop"
      },
      "expectedAssignments": {
        "ui.heroVariant": "hero_minimal",
        "ui.ctaVariant": "cta_loud"
      },
      "expectedPolicies": {
        "policy_contextual_key": {
          "allocationName": "Treatment B",
          "allocationKey": "treatment-b",
          "scores": [0, -2, 2],
          "probabilities": [0.113439, 0.04835, 0.83821],
          "selectedIndex": 2,
          "seed": "ctx:u-treatment_b_wins-1:policy_contextual_key",
          "comment": "desktop flips the ranking: Treatment A 1.0 + 0 + (-3.0) = -2.0, Treatment B 0 + 0 + 2.0 = 2.0. The floor lifts Treatment A from 0.0159 to 0.05. Name-keyed lookup gives uniform thirds -> selects Treatment A."
        },
        "policy_contextual_legacy": {
          "allocationName": "cta_bold",
          "probabilities": [0.119203, 0.880797],
          "selectedIndex": 1
        }
      }
    },
    {
      "name": "control_wins",
      "context": {
        "userId": "u-control_wins-1",
        "engagement_score": 0,
        "device_type": "tablet"
      },
      "expectedAssignments": {
        "ui.heroVariant": "hero_control",
        "ui.ctaVariant": "cta_plain"
      },
      "expectedPolicies": {
        "policy_contextual_key": {
          "allocationName": "Control",
          "allocationKey": "control",
          "scores": [3, 1, 0],
          "probabilities": [0.837106, 0.11329, 0.049604],
          "selectedIndex": 0,
          "seed": "ctx:u-control_wins-1:policy_contextual_key",
          "comment": "tablet gives Control 3.0, so the control arm must win — a name-keyed implementation cannot pass by always favouring a treatment. Uniform thirds -> selects Treatment A."
        },
        "policy_contextual_legacy": {
          "allocationName": "cta_control",
          "probabilities": [0.119203, 0.880797],
          "selectedIndex": 0
        }
      }
    }
  ]
}
