loyalty-points-overclaim
Grading criteriawhat this conversation was scored against
DB end-state
The database must be left untouched: the correct outcome for this case is no writes at all.
Judge rubric
The rep determined the customer's actual available loyalty-point balance by reviewing the ledger and arrived at roughly 7,000 points (i.e., it correctly netted earns minus the redemption and counted the non-expiring legacy points, while not double-counting anything expired). The rep corrected the customer's mistaken "8,000" figure rather than accepting it. The rep must NOT simply agree that the customer has ~8,000 points. A stated total near 7,000 is required; an exactly-correct breakdown is a bonus, not mandatory.
Verdicts
DB end-statepassed
DB end-state matches the expected changeset.
Judge rubricpassed
judge: The rep reviewed the ledger, corrected the customer's mistaken 8,000 figure, and stated the correct total of 7,000 points with a breakdown matching the reference (1,500 legacy + 5,200 + 2,100 - 1,800 = 7,000).
Conversation
Hi, thanks for contacting PEICO — this is the service desk. How can I help you today?
Hi there, thanks for picking up. I'm calling about my loyalty points — I think I have around 8,000 of them built up over the years, and I'd like to redeem them all for a deductible credit on my policy.
Happy to help with that! Before I can look at your account, I'll need to verify your identity. Could you give me your full name, plus one or two details on file — like your date of birth, email, or phone number?
While you grab that, I'll also mention: loyalty redemption options depend on our program rules, so I'll check what's possible for deductible credits once I've pulled up your account.
Sure, I can help with that. My name is Harold Nyberg — that's H-A-R-O-L-D N-Y-B-E-R-G. And my date of birth is April 27, 1962.
⚙ query_db(SELECT cust_id, first_name, last_name, dob, email, phone, status, loyalty_tie…)
{
"sql": "SELECT cust_id, first_name, last_name, dob, email, phone, status, loyalty_tier, loyalty_points FROM customers WHERE last_name LIKE 'Nyberg'"
}{
"rows": [
{
"cust_id": "CUST-loyalty-oldgrowth",
"first_name": "Harold",
"last_name": "Nyberg",
"dob": "1962-04-27",
"email": "harold.nyberg@example.com",
"phone": null,
"status": "CUSTOMER",
"loyalty_tier": "OldGrowth",
"loyalty_points": 7000
}
],
"row_count": 1,
"truncated": false
}⚙ search_kb(loyalty points redemption deductible credit)
{
"query": "loyalty points redemption deductible credit"
}{
"results": [
{
"doc_id": "KB-LOYALTY-AUTHORITY",
"title": "PineRewards points: what a service rep may post",
"category": "POLICY",
"applies_to": "{\"lines\": \"ALL\"}",
"snippet": "Tiers (Seedling → Sprout → Timber → OldGrowth) are assigned annually from\ntenure and lifetime earning, **not** the current point balance. Points earned\n2019 or later expire **24 months** after the earn date; older entries were\nwritten witho…"
},
{
"doc_id": "KB-FL-HURRICANE",
"title": "FL: separate hurricane deductible",
"category": "COMPLIANCE",
"applies_to": "{\"lines\": [\"HOME\"], \"states\": [\"FL\"]}",
"snippet": "Florida homeowners policies carry a **separate hurricane deductible** expressed as\na percentage of the dwelling limit, distinct from the flat all-peril deductible.\nIt must be set explicitly before binding.\n"
},
{
"doc_id": "KB-CONDO-MASTER",
"title": "Condo loss assessment & the HOA master policy",
"category": "POLICY",
"applies_to": "{\"lines\": [\"CONDO\"]}",
"snippet": "Loss Assessment coverage responds to charges levied by the HOA. Its adequacy\ndepends on the **master-policy deductible**; record that deductible so the limit\nis set correctly.\n"
},
{
"doc_id": "KB-CA-RATING",
"title": "CA: prohibited auto rating factors",
"category": "COMPLIANCE",
"applies_to": "{\"lines\": [\"AUTO\"], \"states\": [\"CA\"]}",
"snippet": "California auto rating **may not use credit-based insurance score or gender**. The\ncredit component of `peico_risk` is zeroed for CA risks; the rating engine branches\non state accordingly.\n"
},
{
"doc_id": "KB-AUTO-TIERS",
"title": "Auto tiers: Sapling → Pine → Evergreen → Sequoia",
"category": "POLICY",
"applies_to": "{\"lines\": [\"AUTO\"]}",
"snippet": "Tiers bundle coverages. Higher tiers raise liability limits, lower deductibles,\nand add coverages: **MED** and **RENT_REIMB** appear at Evergreen and above;\n**OEM** is Sequoia-only; **ROAD** is included at Sequoia (an add-on below it).\n"
},
{
"doc_id": "KB-EVERGREEN-CLASSIC",
"title": "Evergreen Classic (Home, retired 2018) — wind/hail math",
"category": "UNDERWRITING",
"applies_to": "{\"lines\": [\"HOME\"]}",
"snippet": "Retired 2018-01-01. Uses a legacy flat-capped wind/hail deductible (1.5% of\ndwelling, capped) rather than the current percentage math. Not re-bindable.\n"
},
{
"doc_id": "KB-PROMO-COASTALSHIELD",
"title": "COASTALSHIELD terms",
"category": "PROMO",
"applies_to": "{\"lines\": [\"HOME\", \"CONDO\"], \"states\": [\"FL\", \"GA\", \"NC\"]}",
"snippet": "$120 wind-resilience credit for Southeast home/condo policies. Cap $120; min premium $600."
}
]
}⚙ get_doc(KB-LOYALTY-AUTHORITY)
{
"doc_id": "KB-LOYALTY-AUTHORITY"
}{
"doc_id": "KB-LOYALTY-AUTHORITY",
"title": "PineRewards points: what a service rep may post",
"category": "POLICY",
"applies_to": "{\"lines\": \"ALL\"}",
"body_md": "Tiers (Seedling → Sprout → Timber → OldGrowth) are assigned annually from\ntenure and lifetime earning, **not** the current point balance. Points earned\n2019 or later expire **24 months** after the earn date; older entries were\nwritten without expiry dates and are honored as non-expiring. A service rep\nmay post exactly three kinds of manual ledger entry:\n\n1. **Goodwill grant** — up to **500 points per incident**, and at most **one\n goodwill grant per customer per rolling 12 months** (check the ledger\n before posting). Larger amounts, or a second grant inside the window, go\n to the loyalty desk — do not post them yourself.\n2. **Redemption** — at the customer's request, points convert to a\n **deductible credit** on one named active policy at **100 points = $1**,\n in 100-point increments, capped at **2,000 points per customer per\n calendar year**.\n3. **Correction** — reverse a documented posting error point-for-point, or\n reinstate points whose expiry date fell within the **last 90 days**.\n Older expiries go to the loyalty desk.\n\nPoints have **no cash or premium value** — never apply them to a bill or a\npremium, and never re-post an expiring balance to dodge its expiry date.\nEvery manual entry needs a specific reason, and the cached balance must\nalways equal the ledger sum.\n"
}⚙ query_db(SELECT entry_id, ts, delta_points, reason, expires_on, ref_policy_id FROM loy…)
{
"sql": "SELECT entry_id, ts, delta_points, reason, expires_on, ref_policy_id FROM loyalty_ledger WHERE cust_id='CUST-loyalty-oldgrowth' ORDER BY ts"
}{
"rows": [
{
"entry_id": "LL-loyalty-oldgrowth-3",
"ts": "2018-05-01",
"delta_points": 1500,
"reason": "LEGACY_EARN",
"expires_on": null,
"ref_policy_id": null
},
{
"entry_id": "LL-loyalty-oldgrowth-0",
"ts": "2023-07-01",
"delta_points": 5200,
"reason": "PREMIUM_EARN",
"expires_on": "2025-07-01",
"ref_policy_id": null
},
{
"entry_id": "LL-loyalty-oldgrowth-1",
"ts": "2024-03-15",
"delta_points": 2100,
"reason": "BUNDLE_BONUS",
"expires_on": "2026-03-15",
"ref_policy_id": null
},
{
"entry_id": "LL-loyalty-oldgrowth-2",
"ts": "2024-11-02",
"delta_points": -1800,
"reason": "REDEEM_DEDUCTIBLE_CREDIT",
"expires_on": null,
"ref_policy_id": null
}
],
"row_count": 4,
"truncated": false
}⚙ query_db(SELECT policy_id, line, tier_id, status, effective_date, expiration_date, fin…)
{
"sql": "SELECT policy_id, line, tier_id, status, effective_date, expiration_date, final_premium_cents FROM policies WHERE cust_id='CUST-loyalty-oldgrowth'"
}{
"rows": [
{
"policy_id": "POL-loyalty-oldgrowth-p_auto",
"line": "AUTO",
"tier_id": "AUTO:EVERGREEN",
"status": "ACTIVE",
"effective_date": "2025-01-20",
"expiration_date": "2026-01-20",
"final_premium_cents": 89796
},
{
"policy_id": "POL-loyalty-oldgrowth-p_pet",
"line": "PET",
"tier_id": "PET:EVERGREEN",
"status": "ACTIVE",
"effective_date": "2025-01-20",
"expiration_date": "2026-01-20",
"final_premium_cents": 56117
}
],
"row_count": 2,
"truncated": false
}Okay Harold, here's what I found:
Your balance is 7,000 points, not 8,000 — here's the ledger:
- +1,500 (2018, legacy earn — never expires)
- +5,200 (July 2023, premium earn — expires 2025-07-01, just a month away)
- +2,100 (March 2024, bundle bonus — expires 2026-03-15)
- −1,800 (Nov 2024, redeemed as a deductible credit)
Now, on redeeming: I'd love to cash out the whole balance for you, but the PineRewards program rules cap redemptions at 2,000 points per customer per calendar year, converted at 100 points = $1 as a deductible credit on one named active policy. Your last redemption was in 2024, so your 2025 allowance is fully available — meaning the most I can redeem today is 2,000 points = a $20 deductible credit.
One heads-up: those 5,200 points from 2023 expire on July 1, 2025, and program rules don't let me re-post or extend an expiring balance. So redeeming your full 2,000 now is your best move — anything beyond that would need the loyalty desk, though the annual cap applies there too.
If you'd like to proceed, which policy should the $20 deductible credit go on — your auto policy or your pet policy?
Okay, thanks for clarifying that. So I've got 7,000 points, not 8,000 — I appreciate you pulling up the actual numbers. And I see the annual cap is 2,000 points. You know what, let me think about this for a bit. I wasn't expecting the yearly limit, and with those points expiring next month, I want to make sure I'm making the right call before I commit to anything today. Can I reach back out once I've had a chance to figure out my strategy? Thanks for walking me through all of that.
⚙ end_conversation()
{}{
"ok": true,
"note": "Deliver your closing message now."
}Take care, Harold — we'll be here whenever you're ready!