FAILURE MAP
← Case archive

FA-83961 / Sports scoring and tiebreakers / Open access

Cricket overs notation parsed as a decimal fraction · case 01

"43.4" overs is treated as 43.4 decimal overs, skewing net run rate.

Verified by executionVariant 1 · 9 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The overs string is converted with float() and multiplied by six, reading the ball digit as tenths.

VERIFIED REPAIR

Split the notation and count the digit after the point as balls.

Unsuccessful approach: Treating the ball digit as tenths of six balls (part * 6 // 10) still misweights partial overs.

Case contract

Tournament net run rate. Each match row is [runs_for, overs_faced, all_out_for, runs_against, overs_bowled, all_out_against]. Overs strings use cricket notation "O.B" where B is balls 0-5 ("43.4" = 43 overs 4 balls); a ball digit above 5 returns "invalid overs". When a side was all out its innings counts as the full quota of overs. NRR = total runs for / total overs faced - total runs against / total overs bowled, aggregated over all matches before dividing, formatted as "%+.3f" of the exact value. If either overs total is zero return "no overs".

Why this case matters

Group-stage standings use net run rate as the first tiebreaker after points.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
from fractions import Fraction
import math
N = 1
observations = []
def solve(matches, quota):
    def balls(text):
        whole, _, part = text.partition('.')
        part = int(part or 0)
        if part > 5:
            return None
        return round(float(text) * 6)
    rf = bf = ra = ba = 0
    for runs_for, faced, out_for, runs_against, bowled, out_against in matches:
        f = quota * 6 if out_for else balls(faced)
        g = quota * 6 if out_against else balls(bowled)
        if f is None or g is None:
            return 'invalid overs'
        rf += runs_for
        bf += f
        ra += runs_against
        ba += g
    if bf == 0 or ba == 0:
        return 'no overs'
    value = Fraction(rf * 6, bf) - Fraction(ra * 6, ba)
    return '%+.3f' % float(value)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
def run(args):
    try:
        return solve(*args)
    except Exception as exc:
        return 'raised ' + type(exc).__name__
cases = [[('control single match', ([[300, '50', False, 250, '50', False]], 50), '+1.000'),
  ('boundary partial over', ([[150, '20.3', False, 150, '25', False]], 50), '+1.317'),
  ('boundary all out uses quota', ([[120, '15.2', True, 121, '18.1', False]], 20), '-0.661'),
  ('boundary invalid ball digit', ([[100, '10.6', False, 90, '10', False]], 20), 'invalid overs'),
  ('control no overs', ([[0, '0', False, 0, '0', False]], 20), 'no overs'),
  ('control negative rate', ([[100, '20', False, 160, '20', False]], 20), '-3.000'),
  ('regression: overs notation', ([[332, '21.5', True, 294, '15.2', False]], 50), '-12.534'),
  ('variant scenario 1', ([[277, '13.1', True, 344, '5', True]], 20), '-3.350'),
  ('variant scenario 2',
   ([[290, '37.4', False, 163, '3.4', True], [227, '17.1', False, 84, '26.5', False]], 50),
   '+6.214')],
 [('control single match', ([[300, '50', False, 250, '50', False]], 50), '+1.000'),
  ('boundary partial over', ([[150, '20.3', False, 150, '25', False]], 50), '+1.317'),
  ('boundary all out uses quota', ([[120, '15.2', True, 121, '18.1', False]], 20), '-0.661'),
  ('boundary invalid ball digit', ([[100, '10.6', False, 90, '10', False]], 20), 'invalid overs'),
  ('control no overs', ([[0, '0', False, 0, '0', False]], 20), 'no overs'),
  ('control negative rate', ([[100, '20', False, 160, '20', False]], 20), '-3.000'),
  ('regression: overs notation',
   ([[334, '41.1', False, 189, '29.0', False],
     [228, '44.4', True, 194, '6.0', False],
     [213, '10.4', False, 157, '34.4', False],
     [323, '30.3', False, 228, '0.4', False]],
    20),
   '-0.190'),
  ('variant scenario 1', ([[0, '0', False, 0, '0', False]], 20), 'no overs'),
  ('variant scenario 2',
   ([[106, '30.1', False, 295, '38.1', False],
     [338, '47.3', False, 295, '10.4', True],
     [129, '47', True, 106, '50.4', False]],
    20),
   '-0.528')],
 [('control single match', ([[300, '50', False, 250, '50', False]], 50), '+1.000'),
  ('boundary partial over', ([[150, '20.3', False, 150, '25', False]], 50), '+1.317'),
  ('boundary all out uses quota', ([[120, '15.2', True, 121, '18.1', False]], 20), '-0.661'),
  ('boundary invalid ball digit', ([[100, '10.6', False, 90, '10', False]], 20), 'invalid overs'),
  ('control no overs', ([[0, '0', False, 0, '0', False]], 20), 'no overs'),
  ('control negative rate', ([[100, '20', False, 160, '20', False]], 20), '-3.000'),
  ('regression: overs notation',
   ([[124, '12.2', True, 200, '37.3', False],
     [249, '50.5', True, 118, '35.0', False],
     [276, '8.3', False, 220, '32', False],
     [301, '36.4', True, 141, '30.2', True]],
    20),
   '+8.415'),
  ('variant scenario 1',
   ([[194, '27', True, 107, '4.0', False],
     [275, '49.2', True, 248, '36', True],
     [184, '13.4', True, 319, '49.4', True]],
    50),
   '-2.127'),
  ('variant scenario 2',
   ([[160, '2.4', False, 141, '30.4', True], [311, '9.0', False, 308, '36.1', False]], 50),
   '+35.161')],
 [('control single match', ([[300, '50', False, 250, '50', False]], 50), '+1.000'),
  ('boundary partial over', ([[150, '20.3', False, 150, '25', False]], 50), '+1.317'),
  ('boundary all out uses quota', ([[120, '15.2', True, 121, '18.1', False]], 20), '-0.661'),
  ('boundary invalid ball digit', ([[100, '10.6', False, 90, '10', False]], 20), 'invalid overs'),
  ('control no overs', ([[0, '0', False, 0, '0', False]], 20), 'no overs'),
  ('control negative rate', ([[100, '20', False, 160, '20', False]], 20), '-3.000'),
  ('regression: overs notation',
   ([[234, '41.0', False, 232, '28.1', False],
     [337, '0', False, 86, '32.5', False],
     [282, '26.3', True, 240, '11.7', True],
     [209, '43.2', False, 101, '12', False]],
    20),
   '+3.093'),
  ('variant scenario 1',
   ([[100, '7.3', True, 230, '8.1', True],
     [255, '28', False, 125, '15.2', False],
     [105, '8.3', False, 323, '24.4', True],
     [191, '23.5', False, 223, '21.0', True],
     [291, '34.5', False, 104, '40.4', False],
     [100, '41.4', False, 344, '31.2', True]],
    20),
   '-3.275'),
  ('variant scenario 2',
   ([[221, '18.2', True, 95, '18.2', False],
     [205, '36.4', False, 287, '24.2', False],
     [180, '43.3', False, 224, '9.3', False]],
    20),
   '-5.567')],
 [('control single match', ([[300, '50', False, 250, '50', False]], 50), '+1.000'),
  ('boundary partial over', ([[150, '20.3', False, 150, '25', False]], 50), '+1.317'),
  ('boundary all out uses quota', ([[120, '15.2', True, 121, '18.1', False]], 20), '-0.661'),
  ('boundary invalid ball digit', ([[100, '10.6', False, 90, '10', False]], 20), 'invalid overs'),
  ('control no overs', ([[0, '0', False, 0, '0', False]], 20), 'no overs'),
  ('control negative rate', ([[100, '20', False, 160, '20', False]], 20), '-3.000'),
  ('regression: overs notation',
   ([[160, '1.1', False, 175, '22.4', False],
     [256, '46.1', True, 300, '0.4', False],
     [303, '43.0', False, 302, '16.3', False],
     [350, '13', False, 142, '28.4', True],
     [323, '39.4', True, 266, '42.2', False],
     [332, '36.1', False, 99, '5.1', False]],
    50),
   '-0.432'),
  ('variant scenario 1',
   ([[292, '42.1', False, 105, '16.2', False], [154, '36.5', False, 159, '19.5', False]], 50),
   '-1.654'),
  ('variant scenario 2', ([[0, '0', False, 0, '0', False]], 50), 'no overs')]]
for label, args, expected in cases[N - 1]:
    check(label, run(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 fixtureActualExpectedOutcome
control single match+1.000+1.000Passed
boundary partial over+1.377+1.317Failed
boundary all out uses quota-0.661-0.661Passed
boundary invalid ball digitinvalid oversinvalid oversPassed
control no oversno oversno oversPassed
control negative rate-3.000-3.000Passed
regression: overs notation-12.745-12.534Failed
variant scenario 1-3.350-3.350Passed
variant scenario 2+6.257+6.214Failed

SHA-256 / 10c9bd6e6c761d1d3ad803d8491afb5e70df4d1868be3244293b46816374bd07

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
from fractions import Fraction
import math
N = 1
observations = []
def solve(matches, quota):
    def balls(text):
        whole, _, part = text.partition('.')
        part = int(part or 0)
        if part > 5:
            return None
        return int(whole) * 6 + part * 6 // 10
    rf = bf = ra = ba = 0
    for runs_for, faced, out_for, runs_against, bowled, out_against in matches:
        f = quota * 6 if out_for else balls(faced)
        g = quota * 6 if out_against else balls(bowled)
        if f is None or g is None:
            return 'invalid overs'
        rf += runs_for
        bf += f
        ra += runs_against
        ba += g
    if bf == 0 or ba == 0:
        return 'no overs'
    value = Fraction(rf * 6, bf) - Fraction(ra * 6, ba)
    return '%+.3f' % float(value)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
def run(args):
    try:
        return solve(*args)
    except Exception as exc:
        return 'raised ' + type(exc).__name__
cases = [[('control single match', ([[300, '50', False, 250, '50', False]], 50), '+1.000'),
  ('boundary partial over', ([[150, '20.3', False, 150, '25', False]], 50), '+1.317'),
  ('boundary all out uses quota', ([[120, '15.2', True, 121, '18.1', False]], 20), '-0.661'),
  ('boundary invalid ball digit', ([[100, '10.6', False, 90, '10', False]], 20), 'invalid overs'),
  ('control no overs', ([[0, '0', False, 0, '0', False]], 20), 'no overs'),
  ('control negative rate', ([[100, '20', False, 160, '20', False]], 20), '-3.000'),
  ('regression: overs notation', ([[332, '21.5', True, 294, '15.2', False]], 50), '-12.534'),
  ('variant scenario 1', ([[277, '13.1', True, 344, '5', True]], 20), '-3.350'),
  ('variant scenario 2',
   ([[290, '37.4', False, 163, '3.4', True], [227, '17.1', False, 84, '26.5', False]], 50),
   '+6.214')],
 [('control single match', ([[300, '50', False, 250, '50', False]], 50), '+1.000'),
  ('boundary partial over', ([[150, '20.3', False, 150, '25', False]], 50), '+1.317'),
  ('boundary all out uses quota', ([[120, '15.2', True, 121, '18.1', False]], 20), '-0.661'),
  ('boundary invalid ball digit', ([[100, '10.6', False, 90, '10', False]], 20), 'invalid overs'),
  ('control no overs', ([[0, '0', False, 0, '0', False]], 20), 'no overs'),
  ('control negative rate', ([[100, '20', False, 160, '20', False]], 20), '-3.000'),
  ('regression: overs notation',
   ([[334, '41.1', False, 189, '29.0', False],
     [228, '44.4', True, 194, '6.0', False],
     [213, '10.4', False, 157, '34.4', False],
     [323, '30.3', False, 228, '0.4', False]],
    20),
   '-0.190'),
  ('variant scenario 1', ([[0, '0', False, 0, '0', False]], 20), 'no overs'),
  ('variant scenario 2',
   ([[106, '30.1', False, 295, '38.1', False],
     [338, '47.3', False, 295, '10.4', True],
     [129, '47', True, 106, '50.4', False]],
    20),
   '-0.528')],
 [('control single match', ([[300, '50', False, 250, '50', False]], 50), '+1.000'),
  ('boundary partial over', ([[150, '20.3', False, 150, '25', False]], 50), '+1.317'),
  ('boundary all out uses quota', ([[120, '15.2', True, 121, '18.1', False]], 20), '-0.661'),
  ('boundary invalid ball digit', ([[100, '10.6', False, 90, '10', False]], 20), 'invalid overs'),
  ('control no overs', ([[0, '0', False, 0, '0', False]], 20), 'no overs'),
  ('control negative rate', ([[100, '20', False, 160, '20', False]], 20), '-3.000'),
  ('regression: overs notation',
   ([[124, '12.2', True, 200, '37.3', False],
     [249, '50.5', True, 118, '35.0', False],
     [276, '8.3', False, 220, '32', False],
     [301, '36.4', True, 141, '30.2', True]],
    20),
   '+8.415'),
  ('variant scenario 1',
   ([[194, '27', True, 107, '4.0', False],
     [275, '49.2', True, 248, '36', True],
     [184, '13.4', True, 319, '49.4', True]],
    50),
   '-2.127'),
  ('variant scenario 2',
   ([[160, '2.4', False, 141, '30.4', True], [311, '9.0', False, 308, '36.1', False]], 50),
   '+35.161')],
 [('control single match', ([[300, '50', False, 250, '50', False]], 50), '+1.000'),
  ('boundary partial over', ([[150, '20.3', False, 150, '25', False]], 50), '+1.317'),
  ('boundary all out uses quota', ([[120, '15.2', True, 121, '18.1', False]], 20), '-0.661'),
  ('boundary invalid ball digit', ([[100, '10.6', False, 90, '10', False]], 20), 'invalid overs'),
  ('control no overs', ([[0, '0', False, 0, '0', False]], 20), 'no overs'),
  ('control negative rate', ([[100, '20', False, 160, '20', False]], 20), '-3.000'),
  ('regression: overs notation',
   ([[234, '41.0', False, 232, '28.1', False],
     [337, '0', False, 86, '32.5', False],
     [282, '26.3', True, 240, '11.7', True],
     [209, '43.2', False, 101, '12', False]],
    20),
   '+3.093'),
  ('variant scenario 1',
   ([[100, '7.3', True, 230, '8.1', True],
     [255, '28', False, 125, '15.2', False],
     [105, '8.3', False, 323, '24.4', True],
     [191, '23.5', False, 223, '21.0', True],
     [291, '34.5', False, 104, '40.4', False],
     [100, '41.4', False, 344, '31.2', True]],
    20),
   '-3.275'),
  ('variant scenario 2',
   ([[221, '18.2', True, 95, '18.2', False],
     [205, '36.4', False, 287, '24.2', False],
     [180, '43.3', False, 224, '9.3', False]],
    20),
   '-5.567')],
 [('control single match', ([[300, '50', False, 250, '50', False]], 50), '+1.000'),
  ('boundary partial over', ([[150, '20.3', False, 150, '25', False]], 50), '+1.317'),
  ('boundary all out uses quota', ([[120, '15.2', True, 121, '18.1', False]], 20), '-0.661'),
  ('boundary invalid ball digit', ([[100, '10.6', False, 90, '10', False]], 20), 'invalid overs'),
  ('control no overs', ([[0, '0', False, 0, '0', False]], 20), 'no overs'),
  ('control negative rate', ([[100, '20', False, 160, '20', False]], 20), '-3.000'),
  ('regression: overs notation',
   ([[160, '1.1', False, 175, '22.4', False],
     [256, '46.1', True, 300, '0.4', False],
     [303, '43.0', False, 302, '16.3', False],
     [350, '13', False, 142, '28.4', True],
     [323, '39.4', True, 266, '42.2', False],
     [332, '36.1', False, 99, '5.1', False]],
    50),
   '-0.432'),
  ('variant scenario 1',
   ([[292, '42.1', False, 105, '16.2', False], [154, '36.5', False, 159, '19.5', False]], 50),
   '-1.654'),
  ('variant scenario 2', ([[0, '0', False, 0, '0', False]], 50), 'no overs')]]
for label, args, expected in cases[N - 1]:
    check(label, run(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 fixtureActualExpectedOutcome
control single match+1.000+1.000Passed
boundary partial over+1.438+1.317Failed
boundary all out uses quota-0.722-0.661Failed
boundary invalid ball digitinvalid oversinvalid oversPassed
control no oversno oversno oversPassed
control negative rate-3.000-3.000Passed
regression: overs notation-12.745-12.534Failed
variant scenario 1-3.350-3.350Passed
variant scenario 2+6.287+6.214Failed

SHA-256 / 00be4c4d182f6c39334bbbb1c4443700fb0c3b4eff995542c333710fa84921a0

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
from fractions import Fraction
import math
N = 1
observations = []
def solve(matches, quota):
    def balls(text):
        whole, _, part = text.partition('.')
        part = int(part or 0)
        if part > 5:
            return None
        return int(whole) * 6 + part
    rf = bf = ra = ba = 0
    for runs_for, faced, out_for, runs_against, bowled, out_against in matches:
        f = quota * 6 if out_for else balls(faced)
        g = quota * 6 if out_against else balls(bowled)
        if f is None or g is None:
            return 'invalid overs'
        rf += runs_for
        bf += f
        ra += runs_against
        ba += g
    if bf == 0 or ba == 0:
        return 'no overs'
    value = Fraction(rf * 6, bf) - Fraction(ra * 6, ba)
    return '%+.3f' % float(value)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
def run(args):
    try:
        return solve(*args)
    except Exception as exc:
        return 'raised ' + type(exc).__name__
cases = [[('control single match', ([[300, '50', False, 250, '50', False]], 50), '+1.000'),
  ('boundary partial over', ([[150, '20.3', False, 150, '25', False]], 50), '+1.317'),
  ('boundary all out uses quota', ([[120, '15.2', True, 121, '18.1', False]], 20), '-0.661'),
  ('boundary invalid ball digit', ([[100, '10.6', False, 90, '10', False]], 20), 'invalid overs'),
  ('control no overs', ([[0, '0', False, 0, '0', False]], 20), 'no overs'),
  ('control negative rate', ([[100, '20', False, 160, '20', False]], 20), '-3.000'),
  ('regression: overs notation', ([[332, '21.5', True, 294, '15.2', False]], 50), '-12.534'),
  ('variant scenario 1', ([[277, '13.1', True, 344, '5', True]], 20), '-3.350'),
  ('variant scenario 2',
   ([[290, '37.4', False, 163, '3.4', True], [227, '17.1', False, 84, '26.5', False]], 50),
   '+6.214')],
 [('control single match', ([[300, '50', False, 250, '50', False]], 50), '+1.000'),
  ('boundary partial over', ([[150, '20.3', False, 150, '25', False]], 50), '+1.317'),
  ('boundary all out uses quota', ([[120, '15.2', True, 121, '18.1', False]], 20), '-0.661'),
  ('boundary invalid ball digit', ([[100, '10.6', False, 90, '10', False]], 20), 'invalid overs'),
  ('control no overs', ([[0, '0', False, 0, '0', False]], 20), 'no overs'),
  ('control negative rate', ([[100, '20', False, 160, '20', False]], 20), '-3.000'),
  ('regression: overs notation',
   ([[334, '41.1', False, 189, '29.0', False],
     [228, '44.4', True, 194, '6.0', False],
     [213, '10.4', False, 157, '34.4', False],
     [323, '30.3', False, 228, '0.4', False]],
    20),
   '-0.190'),
  ('variant scenario 1', ([[0, '0', False, 0, '0', False]], 20), 'no overs'),
  ('variant scenario 2',
   ([[106, '30.1', False, 295, '38.1', False],
     [338, '47.3', False, 295, '10.4', True],
     [129, '47', True, 106, '50.4', False]],
    20),
   '-0.528')],
 [('control single match', ([[300, '50', False, 250, '50', False]], 50), '+1.000'),
  ('boundary partial over', ([[150, '20.3', False, 150, '25', False]], 50), '+1.317'),
  ('boundary all out uses quota', ([[120, '15.2', True, 121, '18.1', False]], 20), '-0.661'),
  ('boundary invalid ball digit', ([[100, '10.6', False, 90, '10', False]], 20), 'invalid overs'),
  ('control no overs', ([[0, '0', False, 0, '0', False]], 20), 'no overs'),
  ('control negative rate', ([[100, '20', False, 160, '20', False]], 20), '-3.000'),
  ('regression: overs notation',
   ([[124, '12.2', True, 200, '37.3', False],
     [249, '50.5', True, 118, '35.0', False],
     [276, '8.3', False, 220, '32', False],
     [301, '36.4', True, 141, '30.2', True]],
    20),
   '+8.415'),
  ('variant scenario 1',
   ([[194, '27', True, 107, '4.0', False],
     [275, '49.2', True, 248, '36', True],
     [184, '13.4', True, 319, '49.4', True]],
    50),
   '-2.127'),
  ('variant scenario 2',
   ([[160, '2.4', False, 141, '30.4', True], [311, '9.0', False, 308, '36.1', False]], 50),
   '+35.161')],
 [('control single match', ([[300, '50', False, 250, '50', False]], 50), '+1.000'),
  ('boundary partial over', ([[150, '20.3', False, 150, '25', False]], 50), '+1.317'),
  ('boundary all out uses quota', ([[120, '15.2', True, 121, '18.1', False]], 20), '-0.661'),
  ('boundary invalid ball digit', ([[100, '10.6', False, 90, '10', False]], 20), 'invalid overs'),
  ('control no overs', ([[0, '0', False, 0, '0', False]], 20), 'no overs'),
  ('control negative rate', ([[100, '20', False, 160, '20', False]], 20), '-3.000'),
  ('regression: overs notation',
   ([[234, '41.0', False, 232, '28.1', False],
     [337, '0', False, 86, '32.5', False],
     [282, '26.3', True, 240, '11.7', True],
     [209, '43.2', False, 101, '12', False]],
    20),
   '+3.093'),
  ('variant scenario 1',
   ([[100, '7.3', True, 230, '8.1', True],
     [255, '28', False, 125, '15.2', False],
     [105, '8.3', False, 323, '24.4', True],
     [191, '23.5', False, 223, '21.0', True],
     [291, '34.5', False, 104, '40.4', False],
     [100, '41.4', False, 344, '31.2', True]],
    20),
   '-3.275'),
  ('variant scenario 2',
   ([[221, '18.2', True, 95, '18.2', False],
     [205, '36.4', False, 287, '24.2', False],
     [180, '43.3', False, 224, '9.3', False]],
    20),
   '-5.567')],
 [('control single match', ([[300, '50', False, 250, '50', False]], 50), '+1.000'),
  ('boundary partial over', ([[150, '20.3', False, 150, '25', False]], 50), '+1.317'),
  ('boundary all out uses quota', ([[120, '15.2', True, 121, '18.1', False]], 20), '-0.661'),
  ('boundary invalid ball digit', ([[100, '10.6', False, 90, '10', False]], 20), 'invalid overs'),
  ('control no overs', ([[0, '0', False, 0, '0', False]], 20), 'no overs'),
  ('control negative rate', ([[100, '20', False, 160, '20', False]], 20), '-3.000'),
  ('regression: overs notation',
   ([[160, '1.1', False, 175, '22.4', False],
     [256, '46.1', True, 300, '0.4', False],
     [303, '43.0', False, 302, '16.3', False],
     [350, '13', False, 142, '28.4', True],
     [323, '39.4', True, 266, '42.2', False],
     [332, '36.1', False, 99, '5.1', False]],
    50),
   '-0.432'),
  ('variant scenario 1',
   ([[292, '42.1', False, 105, '16.2', False], [154, '36.5', False, 159, '19.5', False]], 50),
   '-1.654'),
  ('variant scenario 2', ([[0, '0', False, 0, '0', False]], 50), 'no overs')]]
for label, args, expected in cases[N - 1]:
    check(label, run(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 fixtureActualExpectedOutcome
control single match+1.000+1.000Passed
boundary partial over+1.317+1.317Passed
boundary all out uses quota-0.661-0.661Passed
boundary invalid ball digitinvalid oversinvalid oversPassed
control no oversno oversno oversPassed
control negative rate-3.000-3.000Passed
regression: overs notation-12.534-12.534Passed
variant scenario 1-3.350-3.350Passed
variant scenario 2+6.214+6.214Passed

SHA-256 / 5997a5cc421c97d4ca357efa021c3d970def1f8e97bee051eed6917d35948b9c

Verification & scope

Stipulated, bounded toy contract stated in the contract field; not a claim of conformance with any governing body rulebook or operator house rules. 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:50:26.510258+00:00.

Case digest / dc50d8ba705106ab9d9d4c8da981e91abc42f02342d79cd63cb57e2a52bd32cc