FA-60751 / Loyalty points ledgers / Open access
Tier multiplier in force at transaction time: history ordering · case 01
An out-of-order tier history makes later transactions use an older tier.
ROOT CAUSE
The history is scanned in stored order without sorting by effective day.
VERIFIED REPAIR
Sort the history by effective day before scanning.
Unsuccessful approach: Sorting by tier name orders tiers alphabetically, not by date.
Case contract
Input {tier_history:[[effective_day,tier]] (any order), txns:[[day,base]], mult:{tier:pct}}. Each transaction earns floor(base*pct/100) using the tier with the latest effective_day <= transaction day ("member" before any entry). Unknown tier names earn at 100%. Return {points, total}.
Why this case matters
Member point balances, statements and the program liability depend on this ledger rule.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
hist = x['tier_history']
out = []
for day, base in x['txns']:
tier = 'member'
for eff, t in hist:
if eff <= day:
tier = t
else:
break
pct = x['mult'].get(tier, 100)
out.append(base * pct // 100)
return {'points': out, 'total': sum(out)}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['tier changes midyear', {'tier_history': [[100, 'silver'], [200, 'gold']], 'txns': [[50, 1000], [150, 1001], [250, 1000]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [1000, 1251, 1500], 'total': 3751}], ['effective day', {'tier_history': [[100, 'silver'], [201, 'gold']], 'txns': [[100, 400], [201, 400]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [500, 600], 'total': 1100}], ['unsorted history', {'tier_history': [[300, 'platinum'], [100, 'gold']], 'txns': [[150, 101], [350, 100]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [151, 200], 'total': 351}], ['legacy tier', {'tier_history': [[10, 'diamond']], 'txns': [[20, 334]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [334], 'total': 334}], ['before any tier', {'tier_history': [[500, 'gold']], 'txns': [[1, 77], [499, 11]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [77, 11], 'total': 88}], ['downgrade', {'tier_history': [[10, 'gold'], [60, 'silver']], 'txns': [[59, 200], [61, 201]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [300, 251], 'total': 551}], ['late earns', {'tier_history': [[0, 'silver'], [30, 'platinum']], 'txns': [[15, 91]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [113], 'total': 113}]], [['tier changes midyear', {'tier_history': [[100, 'silver'], [200, 'gold']], 'txns': [[50, 1000], [150, 1002], [250, 1000]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [1000, 1252, 1500], 'total': 3752}], ['effective day', {'tier_history': [[100, 'silver'], [202, 'gold']], 'txns': [[100, 400], [202, 400]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [500, 600], 'total': 1100}], ['unsorted history', {'tier_history': [[300, 'platinum'], [100, 'gold']], 'txns': [[150, 102], [350, 100]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [153, 200], 'total': 353}], ['legacy tier', {'tier_history': [[10, 'diamond']], 'txns': [[20, 335]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [335], 'total': 335}], ['before any tier', {'tier_history': [[500, 'gold']], 'txns': [[1, 77], [499, 12]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [77, 12], 'total': 89}], ['downgrade', {'tier_history': [[10, 'gold'], [60, 'silver']], 'txns': [[59, 200], [61, 202]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [300, 252], 'total': 552}], ['late earns', {'tier_history': [[0, 'silver'], [30, 'platinum']], 'txns': [[15, 92]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [115], 'total': 115}]], [['tier changes midyear', {'tier_history': [[100, 'silver'], [200, 'gold']], 'txns': [[50, 1000], [150, 1003], [250, 1000]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [1000, 1253, 1500], 'total': 3753}], ['effective day', {'tier_history': [[100, 'silver'], [203, 'gold']], 'txns': [[100, 400], [203, 400]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [500, 600], 'total': 1100}], ['unsorted history', {'tier_history': [[300, 'platinum'], [100, 'gold']], 'txns': [[150, 103], [350, 100]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [154, 200], 'total': 354}], ['legacy tier', {'tier_history': [[10, 'diamond']], 'txns': [[20, 336]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [336], 'total': 336}], ['before any tier', {'tier_history': [[500, 'gold']], 'txns': [[1, 77], [499, 13]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [77, 13], 'total': 90}], ['downgrade', {'tier_history': [[10, 'gold'], [60, 'silver']], 'txns': [[59, 200], [61, 203]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [300, 253], 'total': 553}], ['late earns', {'tier_history': [[0, 'silver'], [30, 'platinum']], 'txns': [[15, 93]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [116], 'total': 116}]], [['tier changes midyear', {'tier_history': [[100, 'silver'], [200, 'gold']], 'txns': [[50, 1000], [150, 1004], [250, 1000]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [1000, 1255, 1500], 'total': 3755}], ['effective day', {'tier_history': [[100, 'silver'], [204, 'gold']], 'txns': [[100, 400], [204, 400]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [500, 600], 'total': 1100}], ['unsorted history', {'tier_history': [[300, 'platinum'], [100, 'gold']], 'txns': [[150, 104], [350, 100]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [156, 200], 'total': 356}], ['legacy tier', {'tier_history': [[10, 'diamond']], 'txns': [[20, 337]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [337], 'total': 337}], ['before any tier', {'tier_history': [[500, 'gold']], 'txns': [[1, 77], [499, 14]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [77, 14], 'total': 91}], ['downgrade', {'tier_history': [[10, 'gold'], [60, 'silver']], 'txns': [[59, 200], [61, 204]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [300, 255], 'total': 555}], ['late earns', {'tier_history': [[0, 'silver'], [30, 'platinum']], 'txns': [[15, 94]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [117], 'total': 117}]], [['tier changes midyear', {'tier_history': [[100, 'silver'], [200, 'gold']], 'txns': [[50, 1000], [150, 1005], [250, 1000]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [1000, 1256, 1500], 'total': 3756}], ['effective day', {'tier_history': [[100, 'silver'], [205, 'gold']], 'txns': [[100, 400], [205, 400]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [500, 600], 'total': 1100}], ['unsorted history', {'tier_history': [[300, 'platinum'], [100, 'gold']], 'txns': [[150, 105], [350, 100]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [157, 200], 'total': 357}], ['legacy tier', {'tier_history': [[10, 'diamond']], 'txns': [[20, 338]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [338], 'total': 338}], ['before any tier', {'tier_history': [[500, 'gold']], 'txns': [[1, 77], [499, 15]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [77, 15], 'total': 92}], ['downgrade', {'tier_history': [[10, 'gold'], [60, 'silver']], 'txns': [[59, 200], [61, 205]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [300, 256], 'total': 556}], ['late earns', {'tier_history': [[0, 'silver'], [30, 'platinum']], 'txns': [[15, 95]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [118], 'total': 118}]]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| tier changes midyear | {'points': [1000, 1251, 1500], 'total': 3751} | {'points': [1000, 1251, 1500], 'total': 3751} | Passed |
| effective day | {'points': [500, 600], 'total': 1100} | {'points': [500, 600], 'total': 1100} | Passed |
| unsorted history | {'points': [101, 150], 'total': 251} | {'points': [151, 200], 'total': 351} | Failed |
| legacy tier | {'points': [334], 'total': 334} | {'points': [334], 'total': 334} | Passed |
| before any tier | {'points': [77, 11], 'total': 88} | {'points': [77, 11], 'total': 88} | Passed |
| downgrade | {'points': [300, 251], 'total': 551} | {'points': [300, 251], 'total': 551} | Passed |
| late earns | {'points': [113], 'total': 113} | {'points': [113], 'total': 113} | Passed |
SHA-256 / 668ed0755ff46c726b43a62aef916e5904c3e1bf4dc2ada753705992a55e5cd7
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
hist = sorted(x['tier_history'], key=lambda h: h[1])
out = []
for day, base in x['txns']:
tier = 'member'
for eff, t in hist:
if eff <= day:
tier = t
else:
break
pct = x['mult'].get(tier, 100)
out.append(base * pct // 100)
return {'points': out, 'total': sum(out)}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['tier changes midyear', {'tier_history': [[100, 'silver'], [200, 'gold']], 'txns': [[50, 1000], [150, 1001], [250, 1000]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [1000, 1251, 1500], 'total': 3751}], ['effective day', {'tier_history': [[100, 'silver'], [201, 'gold']], 'txns': [[100, 400], [201, 400]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [500, 600], 'total': 1100}], ['unsorted history', {'tier_history': [[300, 'platinum'], [100, 'gold']], 'txns': [[150, 101], [350, 100]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [151, 200], 'total': 351}], ['legacy tier', {'tier_history': [[10, 'diamond']], 'txns': [[20, 334]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [334], 'total': 334}], ['before any tier', {'tier_history': [[500, 'gold']], 'txns': [[1, 77], [499, 11]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [77, 11], 'total': 88}], ['downgrade', {'tier_history': [[10, 'gold'], [60, 'silver']], 'txns': [[59, 200], [61, 201]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [300, 251], 'total': 551}], ['late earns', {'tier_history': [[0, 'silver'], [30, 'platinum']], 'txns': [[15, 91]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [113], 'total': 113}]], [['tier changes midyear', {'tier_history': [[100, 'silver'], [200, 'gold']], 'txns': [[50, 1000], [150, 1002], [250, 1000]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [1000, 1252, 1500], 'total': 3752}], ['effective day', {'tier_history': [[100, 'silver'], [202, 'gold']], 'txns': [[100, 400], [202, 400]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [500, 600], 'total': 1100}], ['unsorted history', {'tier_history': [[300, 'platinum'], [100, 'gold']], 'txns': [[150, 102], [350, 100]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [153, 200], 'total': 353}], ['legacy tier', {'tier_history': [[10, 'diamond']], 'txns': [[20, 335]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [335], 'total': 335}], ['before any tier', {'tier_history': [[500, 'gold']], 'txns': [[1, 77], [499, 12]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [77, 12], 'total': 89}], ['downgrade', {'tier_history': [[10, 'gold'], [60, 'silver']], 'txns': [[59, 200], [61, 202]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [300, 252], 'total': 552}], ['late earns', {'tier_history': [[0, 'silver'], [30, 'platinum']], 'txns': [[15, 92]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [115], 'total': 115}]], [['tier changes midyear', {'tier_history': [[100, 'silver'], [200, 'gold']], 'txns': [[50, 1000], [150, 1003], [250, 1000]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [1000, 1253, 1500], 'total': 3753}], ['effective day', {'tier_history': [[100, 'silver'], [203, 'gold']], 'txns': [[100, 400], [203, 400]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [500, 600], 'total': 1100}], ['unsorted history', {'tier_history': [[300, 'platinum'], [100, 'gold']], 'txns': [[150, 103], [350, 100]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [154, 200], 'total': 354}], ['legacy tier', {'tier_history': [[10, 'diamond']], 'txns': [[20, 336]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [336], 'total': 336}], ['before any tier', {'tier_history': [[500, 'gold']], 'txns': [[1, 77], [499, 13]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [77, 13], 'total': 90}], ['downgrade', {'tier_history': [[10, 'gold'], [60, 'silver']], 'txns': [[59, 200], [61, 203]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [300, 253], 'total': 553}], ['late earns', {'tier_history': [[0, 'silver'], [30, 'platinum']], 'txns': [[15, 93]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [116], 'total': 116}]], [['tier changes midyear', {'tier_history': [[100, 'silver'], [200, 'gold']], 'txns': [[50, 1000], [150, 1004], [250, 1000]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [1000, 1255, 1500], 'total': 3755}], ['effective day', {'tier_history': [[100, 'silver'], [204, 'gold']], 'txns': [[100, 400], [204, 400]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [500, 600], 'total': 1100}], ['unsorted history', {'tier_history': [[300, 'platinum'], [100, 'gold']], 'txns': [[150, 104], [350, 100]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [156, 200], 'total': 356}], ['legacy tier', {'tier_history': [[10, 'diamond']], 'txns': [[20, 337]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [337], 'total': 337}], ['before any tier', {'tier_history': [[500, 'gold']], 'txns': [[1, 77], [499, 14]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [77, 14], 'total': 91}], ['downgrade', {'tier_history': [[10, 'gold'], [60, 'silver']], 'txns': [[59, 200], [61, 204]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [300, 255], 'total': 555}], ['late earns', {'tier_history': [[0, 'silver'], [30, 'platinum']], 'txns': [[15, 94]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [117], 'total': 117}]], [['tier changes midyear', {'tier_history': [[100, 'silver'], [200, 'gold']], 'txns': [[50, 1000], [150, 1005], [250, 1000]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [1000, 1256, 1500], 'total': 3756}], ['effective day', {'tier_history': [[100, 'silver'], [205, 'gold']], 'txns': [[100, 400], [205, 400]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [500, 600], 'total': 1100}], ['unsorted history', {'tier_history': [[300, 'platinum'], [100, 'gold']], 'txns': [[150, 105], [350, 100]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [157, 200], 'total': 357}], ['legacy tier', {'tier_history': [[10, 'diamond']], 'txns': [[20, 338]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [338], 'total': 338}], ['before any tier', {'tier_history': [[500, 'gold']], 'txns': [[1, 77], [499, 15]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [77, 15], 'total': 92}], ['downgrade', {'tier_history': [[10, 'gold'], [60, 'silver']], 'txns': [[59, 200], [61, 205]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [300, 256], 'total': 556}], ['late earns', {'tier_history': [[0, 'silver'], [30, 'platinum']], 'txns': [[15, 95]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [118], 'total': 118}]]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| tier changes midyear | {'points': [1000, 1001, 1250], 'total': 3251} | {'points': [1000, 1251, 1500], 'total': 3751} | Failed |
| effective day | {'points': [400, 500], 'total': 900} | {'points': [500, 600], 'total': 1100} | Failed |
| unsorted history | {'points': [151, 200], 'total': 351} | {'points': [151, 200], 'total': 351} | Passed |
| legacy tier | {'points': [334], 'total': 334} | {'points': [334], 'total': 334} | Passed |
| before any tier | {'points': [77, 11], 'total': 88} | {'points': [77, 11], 'total': 88} | Passed |
| downgrade | {'points': [300, 251], 'total': 551} | {'points': [300, 251], 'total': 551} | Passed |
| late earns | {'points': [91], 'total': 91} | {'points': [113], 'total': 113} | Failed |
SHA-256 / 8fe79db15df30c051a7bd9856d85c26318f9d56cd8ac8adcf9c3bee970d9e259
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
hist = sorted(x['tier_history'])
out = []
for day, base in x['txns']:
tier = 'member'
for eff, t in hist:
if eff <= day:
tier = t
else:
break
pct = x['mult'].get(tier, 100)
out.append(base * pct // 100)
return {'points': out, 'total': sum(out)}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['tier changes midyear', {'tier_history': [[100, 'silver'], [200, 'gold']], 'txns': [[50, 1000], [150, 1001], [250, 1000]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [1000, 1251, 1500], 'total': 3751}], ['effective day', {'tier_history': [[100, 'silver'], [201, 'gold']], 'txns': [[100, 400], [201, 400]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [500, 600], 'total': 1100}], ['unsorted history', {'tier_history': [[300, 'platinum'], [100, 'gold']], 'txns': [[150, 101], [350, 100]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [151, 200], 'total': 351}], ['legacy tier', {'tier_history': [[10, 'diamond']], 'txns': [[20, 334]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [334], 'total': 334}], ['before any tier', {'tier_history': [[500, 'gold']], 'txns': [[1, 77], [499, 11]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [77, 11], 'total': 88}], ['downgrade', {'tier_history': [[10, 'gold'], [60, 'silver']], 'txns': [[59, 200], [61, 201]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [300, 251], 'total': 551}], ['late earns', {'tier_history': [[0, 'silver'], [30, 'platinum']], 'txns': [[15, 91]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [113], 'total': 113}]], [['tier changes midyear', {'tier_history': [[100, 'silver'], [200, 'gold']], 'txns': [[50, 1000], [150, 1002], [250, 1000]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [1000, 1252, 1500], 'total': 3752}], ['effective day', {'tier_history': [[100, 'silver'], [202, 'gold']], 'txns': [[100, 400], [202, 400]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [500, 600], 'total': 1100}], ['unsorted history', {'tier_history': [[300, 'platinum'], [100, 'gold']], 'txns': [[150, 102], [350, 100]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [153, 200], 'total': 353}], ['legacy tier', {'tier_history': [[10, 'diamond']], 'txns': [[20, 335]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [335], 'total': 335}], ['before any tier', {'tier_history': [[500, 'gold']], 'txns': [[1, 77], [499, 12]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [77, 12], 'total': 89}], ['downgrade', {'tier_history': [[10, 'gold'], [60, 'silver']], 'txns': [[59, 200], [61, 202]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [300, 252], 'total': 552}], ['late earns', {'tier_history': [[0, 'silver'], [30, 'platinum']], 'txns': [[15, 92]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [115], 'total': 115}]], [['tier changes midyear', {'tier_history': [[100, 'silver'], [200, 'gold']], 'txns': [[50, 1000], [150, 1003], [250, 1000]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [1000, 1253, 1500], 'total': 3753}], ['effective day', {'tier_history': [[100, 'silver'], [203, 'gold']], 'txns': [[100, 400], [203, 400]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [500, 600], 'total': 1100}], ['unsorted history', {'tier_history': [[300, 'platinum'], [100, 'gold']], 'txns': [[150, 103], [350, 100]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [154, 200], 'total': 354}], ['legacy tier', {'tier_history': [[10, 'diamond']], 'txns': [[20, 336]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [336], 'total': 336}], ['before any tier', {'tier_history': [[500, 'gold']], 'txns': [[1, 77], [499, 13]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [77, 13], 'total': 90}], ['downgrade', {'tier_history': [[10, 'gold'], [60, 'silver']], 'txns': [[59, 200], [61, 203]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [300, 253], 'total': 553}], ['late earns', {'tier_history': [[0, 'silver'], [30, 'platinum']], 'txns': [[15, 93]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [116], 'total': 116}]], [['tier changes midyear', {'tier_history': [[100, 'silver'], [200, 'gold']], 'txns': [[50, 1000], [150, 1004], [250, 1000]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [1000, 1255, 1500], 'total': 3755}], ['effective day', {'tier_history': [[100, 'silver'], [204, 'gold']], 'txns': [[100, 400], [204, 400]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [500, 600], 'total': 1100}], ['unsorted history', {'tier_history': [[300, 'platinum'], [100, 'gold']], 'txns': [[150, 104], [350, 100]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [156, 200], 'total': 356}], ['legacy tier', {'tier_history': [[10, 'diamond']], 'txns': [[20, 337]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [337], 'total': 337}], ['before any tier', {'tier_history': [[500, 'gold']], 'txns': [[1, 77], [499, 14]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [77, 14], 'total': 91}], ['downgrade', {'tier_history': [[10, 'gold'], [60, 'silver']], 'txns': [[59, 200], [61, 204]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [300, 255], 'total': 555}], ['late earns', {'tier_history': [[0, 'silver'], [30, 'platinum']], 'txns': [[15, 94]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [117], 'total': 117}]], [['tier changes midyear', {'tier_history': [[100, 'silver'], [200, 'gold']], 'txns': [[50, 1000], [150, 1005], [250, 1000]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [1000, 1256, 1500], 'total': 3756}], ['effective day', {'tier_history': [[100, 'silver'], [205, 'gold']], 'txns': [[100, 400], [205, 400]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [500, 600], 'total': 1100}], ['unsorted history', {'tier_history': [[300, 'platinum'], [100, 'gold']], 'txns': [[150, 105], [350, 100]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [157, 200], 'total': 357}], ['legacy tier', {'tier_history': [[10, 'diamond']], 'txns': [[20, 338]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [338], 'total': 338}], ['before any tier', {'tier_history': [[500, 'gold']], 'txns': [[1, 77], [499, 15]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [77, 15], 'total': 92}], ['downgrade', {'tier_history': [[10, 'gold'], [60, 'silver']], 'txns': [[59, 200], [61, 205]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [300, 256], 'total': 556}], ['late earns', {'tier_history': [[0, 'silver'], [30, 'platinum']], 'txns': [[15, 95]], 'mult': {'member': 100, 'silver': 125, 'gold': 150, 'platinum': 200}}, {'points': [118], 'total': 118}]]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| tier changes midyear | {'points': [1000, 1251, 1500], 'total': 3751} | {'points': [1000, 1251, 1500], 'total': 3751} | Passed |
| effective day | {'points': [500, 600], 'total': 1100} | {'points': [500, 600], 'total': 1100} | Passed |
| unsorted history | {'points': [151, 200], 'total': 351} | {'points': [151, 200], 'total': 351} | Passed |
| legacy tier | {'points': [334], 'total': 334} | {'points': [334], 'total': 334} | Passed |
| before any tier | {'points': [77, 11], 'total': 88} | {'points': [77, 11], 'total': 88} | Passed |
| downgrade | {'points': [300, 251], 'total': 551} | {'points': [300, 251], 'total': 551} | Passed |
| late earns | {'points': [113], 'total': 113} | {'points': [113], 'total': 113} | Passed |
SHA-256 / a6aa004133bf274de7fb5e95d2650e5d09e58efe89ca92bbd37e211aad14dda3
Verification & scope
Stipulated bounded loyalty-program model with explicit toy rules; not any real program terms. 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.
Observations recorded using Python 3.12.14 at 2026-09-29T14:46:48.595393+00:00.
Case digest / 28b02f14c81e131e80c4dea01ec620934740f973121630021b5cf88b47abba86