FAILURE MAP
← Case archive

FA-96851 / Recipe scaling and nutrition / Open access

Servings scaler: count half-up rounding · case 01

4.5 eggs becomes 4 eggs and 2.75 limes becomes 2 limes.

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

ROOT CAUSE

Countable rows truncate the scaled count instead of rounding half-up.

VERIFIED REPAIR

Round countable rows half-up: add one when the fractional part is at least 1/2.

Unsuccessful approach: A strict greater-than rounds exact halves down, so 4.5 eggs still becomes 4.

Case contract

Scale [name, qty, unit, kind] rows from base to target servings. Factor f=target/base (both must be positive, else an error string). Seasoning rows scale by 1+(f-1)*3/4 (damped); other rows by f. Unit "each" rounds half-up to an integer with a floor of 1. Other units round half-up to the nearest 1/8 and print as reduced kitchen fractions ("1 1/2", "3/4", "2"); a zero result prints "pinch".

Why this case matters

Home and commercial recipe scalers must keep countable items whole and print measurable fractions cooks can actually portion.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(items, base, target):
    if base <= 0 or target <= 0:
        return 'error: servings must be positive'
    f = Fraction(target, base)
    def fmt(e):
        if e == 0:
            return 'pinch'
        whole, rem = divmod(e, 8)
        if rem == 0:
            return str(whole)
        g = math.gcd(rem, 8)
        frac = '%d/%d' % (rem // g, 8 // g)
        return frac if whole == 0 else '%d %s' % (whole, frac)
    out = []
    for name, qty, unit, kind in items:
        q = Fraction(qty)
        if kind == 'seasoning':
            s = q * (1 + (f - 1) * Fraction(3, 4))
        else:
            s = q * f
        if unit == 'each':
            n = int(s)
            out.append([name, str(max(1, n)), unit])
        else:
            e = int(s * 8 + Fraction(1, 2))
            out.append([name, fmt(e), unit])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['identity scaling control', [[['egg', '2', 'each', 'base'], ['flour', '3/2', 'cup', 'base']], 4, 4],
   [['egg', '2', 'each'], ['flour', '1 1/2', 'cup']]],
  ['zero servings rejected', [[['egg', '2', 'each', 'base']], 0, 4], 'error: servings must be positive'],
  ['double batch with seasoning', [[['salt', '1', 'tsp', 'seasoning'], ['egg', '3', 'each', 'base']], 4, 8],
   [['salt', '1 3/4', 'tsp'], ['egg', '6', 'each']]],
  ['regression: count half-up rounding',
   [[['lime', '3', 'each', 'base'], ['butter', '1', 'tbsp', 'base'], ['salt', '9/4', 'tsp', 'seasoning'],
     ['cumin', '3/4', 'tsp', 'seasoning'], ['milk', '1', 'cup', 'base']],
    8, 12],
   [['lime', '5', 'each'], ['butter', '1 1/2', 'tbsp'], ['salt', '3 1/8', 'tsp'], ['cumin', '1', 'tsp'],
    ['milk', '1 1/2', 'cup']]],
  ['repair check: count half-up rounding',
   [[['cumin', '3/4', 'tsp', 'seasoning'], ['lime', '2', 'each', 'base'],
     ['pepper', '3/2', 'tsp', 'seasoning'], ['milk', '1/2', 'cup', 'base']],
    4, 7],
   [['cumin', '1 1/8', 'tsp'], ['lime', '4', 'each'], ['pepper', '2 3/8', 'tsp'], ['milk', '7/8', 'cup']]],
  ['generated control 1', [[['milk', '2', 'cup', 'base'], ['cumin', '1/4', 'tsp', 'seasoning']], 4, 5],
   [['milk', '2 1/2', 'cup'], ['cumin', '1/4', 'tsp']]],
  ['generated control 2', [[['flour', '3/4', 'cup', 'base'], ['salt', '5/2', 'tsp', 'seasoning']], 6, 12],
   [['flour', '1 1/2', 'cup'], ['salt', '4 3/8', 'tsp']]],
  ['generated control 3',
   [[['butter', '1/2', 'tbsp', 'base'], ['lime', '1/2', 'each', 'base'], ['flour', '1/8', 'cup', 'base'],
     ['garlic clove', '1', 'each', 'base']],
    5, 6],
   [['butter', '5/8', 'tbsp'], ['lime', '1', 'each'], ['flour', '1/8', 'cup'],
    ['garlic clove', '1', 'each']]]],
 [['zero servings rejected', [[['egg', '2', 'each', 'base']], 0, 4], 'error: servings must be positive'],
  ['double batch with seasoning', [[['salt', '1', 'tsp', 'seasoning'], ['egg', '3', 'each', 'base']], 4, 8],
   [['salt', '1 3/4', 'tsp'], ['egg', '6', 'each']]],
  ['tiny scale-down to pinch', [[['cumin', '1/8', 'tsp', 'base'], ['egg', '1', 'each', 'base']], 8, 1],
   [['cumin', 'pinch', 'tsp'], ['egg', '1', 'each']]],
  ['regression: count half-up rounding',
   [[['egg', '5', 'each', 'base'], ['lime', '4', 'each', 'base']], 6, 9],
   [['egg', '8', 'each'], ['lime', '6', 'each']]],
  ['repair check: count half-up rounding',
   [[['lime', '5', 'each', 'base'], ['pepper', '3/4', 'tsp', 'seasoning'], ['milk', '2/3', 'cup', 'base'],
     ['cumin', '2', 'tsp', 'seasoning']],
    2, 9],
   [['lime', '23', 'each'], ['pepper', '2 3/4', 'tsp'], ['milk', '3', 'cup'], ['cumin', '7 1/4', 'tsp']]],
  ['generated control 1',
   [[['pepper', '3/4', 'tsp', 'seasoning'], ['egg', '2', 'each', 'base'], ['lime', '1/2', 'each', 'base'],
     ['flour', '1/3', 'cup', 'base'], ['butter', '1/3', 'tbsp', 'base']],
    6, 1],
   [['pepper', '1/4', 'tsp'], ['egg', '1', 'each'], ['lime', '1', 'each'], ['flour', 'pinch', 'cup'],
    ['butter', 'pinch', 'tbsp']]],
  ['generated control 2',
   [[['salt', '1/2', 'tsp', 'seasoning'], ['pepper', '1/2', 'tsp', 'seasoning'],
     ['cumin', '3/2', 'tsp', 'seasoning']],
    3, 12],
   [['salt', '1 5/8', 'tsp'], ['pepper', '1 5/8', 'tsp'], ['cumin', '4 7/8', 'tsp']]],
  ['generated control 3',
   [[['cumin', '3/2', 'tsp', 'seasoning'], ['butter', '1/4', 'tbsp', 'base'], ['egg', '1', 'each', 'base']],
    5, 8],
   [['cumin', '2 1/8', 'tsp'], ['butter', '3/8', 'tbsp'], ['egg', '2', 'each']]]],
 [['double batch with seasoning', [[['salt', '1', 'tsp', 'seasoning'], ['egg', '3', 'each', 'base']], 4, 8],
   [['salt', '1 3/4', 'tsp'], ['egg', '6', 'each']]],
  ['tiny scale-down to pinch', [[['cumin', '1/8', 'tsp', 'base'], ['egg', '1', 'each', 'base']], 8, 1],
   [['cumin', 'pinch', 'tsp'], ['egg', '1', 'each']]],
  ['half egg rounds up', [[['egg', '3', 'each', 'base'], ['milk', '1/2', 'cup', 'base']], 4, 6],
   [['egg', '5', 'each'], ['milk', '3/4', 'cup']]],
  ['regression: count half-up rounding',
   [[['cumin', '1', 'tsp', 'seasoning'], ['pepper', '3', 'tsp', 'seasoning'], ['milk', '3/4', 'cup', 'base'],
     ['salt', '1', 'tsp', 'seasoning'], ['garlic clove', '3', 'each', 'base']],
    4, 9],
   [['cumin', '2', 'tsp'], ['pepper', '5 7/8', 'tsp'], ['milk', '1 3/4', 'cup'], ['salt', '2', 'tsp'],
    ['garlic clove', '7', 'each']]],
  ['repair check: count half-up rounding',
   [[['milk', '2/3', 'cup', 'base'], ['lime', '5', 'each', 'base'], ['egg', '1/2', 'each', 'base'],
     ['flour', '1/2', 'cup', 'base'], ['garlic clove', '1', 'each', 'base']],
    2, 3],
   [['milk', '1', 'cup'], ['lime', '8', 'each'], ['egg', '1', 'each'], ['flour', '3/4', 'cup'],
    ['garlic clove', '2', 'each']]],
  ['generated control 1',
   [[['flour', '1/2', 'cup', 'base'], ['pepper', '2/3', 'tsp', 'seasoning'],
     ['butter', '1/3', 'tbsp', 'base'], ['salt', '1/3', 'tsp', 'seasoning']],
    8, 7],
   [['flour', '1/2', 'cup'], ['pepper', '5/8', 'tsp'], ['butter', '1/4', 'tbsp'], ['salt', '1/4', 'tsp']]],
  ['generated control 2',
   [[['cumin', '1/3', 'tsp', 'seasoning'], ['milk', '3', 'cup', 'base'],
     ['pepper', '9/4', 'tsp', 'seasoning'], ['butter', '2/3', 'tbsp', 'base']],
    1, 9],
   [['cumin', '2 3/8', 'tsp'], ['milk', '27', 'cup'], ['pepper', '15 3/4', 'tsp'], ['butter', '6', 'tbsp']]],
  ['generated control 3',
   [[['garlic clove', '2', 'each', 'base'], ['pepper', '1/8', 'tsp', 'seasoning']], 4, 1],
   [['garlic clove', '1', 'each'], ['pepper', 'pinch', 'tsp']]]],
 [['tiny scale-down to pinch', [[['cumin', '1/8', 'tsp', 'base'], ['egg', '1', 'each', 'base']], 8, 1],
   [['cumin', 'pinch', 'tsp'], ['egg', '1', 'each']]],
  ['half egg rounds up', [[['egg', '3', 'each', 'base'], ['milk', '1/2', 'cup', 'base']], 4, 6],
   [['egg', '5', 'each'], ['milk', '3/4', 'cup']]],
  ['identity scaling control', [[['egg', '2', 'each', 'base'], ['flour', '3/2', 'cup', 'base']], 4, 4],
   [['egg', '2', 'each'], ['flour', '1 1/2', 'cup']]],
  ['regression: count half-up rounding',
   [[['butter', '1/4', 'tbsp', 'base'], ['garlic clove', '3', 'each', 'base'],
     ['egg', '1/2', 'each', 'base']],
    7, 6],
   [['butter', '1/4', 'tbsp'], ['garlic clove', '3', 'each'], ['egg', '1', 'each']]],
  ['repair check: count half-up rounding',
   [[['lime', '2', 'each', 'base'], ['butter', '3', 'tbsp', 'base'], ['garlic clove', '5', 'each', 'base'],
     ['salt', '3/2', 'tsp', 'seasoning']],
    2, 5],
   [['lime', '5', 'each'], ['butter', '7 1/2', 'tbsp'], ['garlic clove', '13', 'each'],
    ['salt', '3 1/4', 'tsp']]],
  ['generated control 1',
   [[['egg', '3', 'each', 'base'], ['cumin', '3/2', 'tsp', 'seasoning'], ['butter', '2/3', 'tbsp', 'base'],
     ['flour', '3', 'cup', 'base'], ['salt', '2', 'tsp', 'seasoning']],
    4, 11],
   [['egg', '8', 'each'], ['cumin', '3 1/2', 'tsp'], ['butter', '1 7/8', 'tbsp'], ['flour', '8 1/4', 'cup'],
    ['salt', '4 5/8', 'tsp']]],
  ['generated control 2',
   [[['cumin', '9/4', 'tsp', 'seasoning'], ['egg', '3', 'each', 'base'], ['butter', '1/3', 'tbsp', 'base'],
     ['flour', '1/2', 'cup', 'base']],
    8, 1],
   [['cumin', '3/4', 'tsp'], ['egg', '1', 'each'], ['butter', 'pinch', 'tbsp'], ['flour', '1/8', 'cup']]],
  ['generated control 3', [[['egg', '1', 'each', 'base'], ['milk', '1/4', 'cup', 'base']], 5, 2],
   [['egg', '1', 'each'], ['milk', '1/8', 'cup']]]],
 [['half egg rounds up', [[['egg', '3', 'each', 'base'], ['milk', '1/2', 'cup', 'base']], 4, 6],
   [['egg', '5', 'each'], ['milk', '3/4', 'cup']]],
  ['identity scaling control', [[['egg', '2', 'each', 'base'], ['flour', '3/2', 'cup', 'base']], 4, 4],
   [['egg', '2', 'each'], ['flour', '1 1/2', 'cup']]],
  ['zero servings rejected', [[['egg', '2', 'each', 'base']], 0, 4], 'error: servings must be positive'],
  ['regression: count half-up rounding',
   [[['cumin', '5/2', 'tsp', 'seasoning'], ['garlic clove', '2', 'each', 'base'],
     ['pepper', '1/3', 'tsp', 'seasoning'], ['butter', '2/3', 'tbsp', 'base']],
    8, 7],
   [['cumin', '2 1/4', 'tsp'], ['garlic clove', '2', 'each'], ['pepper', '1/4', 'tsp'],
    ['butter', '5/8', 'tbsp']]],
  ['repair check: count half-up rounding',
   [[['lime', '5', 'each', 'base'], ['egg', '4', 'each', 'base'], ['flour', '1', 'cup', 'base'],
     ['milk', '2/3', 'cup', 'base']],
    2, 3],
   [['lime', '8', 'each'], ['egg', '6', 'each'], ['flour', '1 1/2', 'cup'], ['milk', '1', 'cup']]],
  ['generated control 1',
   [[['pepper', '1/2', 'tsp', 'seasoning'], ['salt', '9/4', 'tsp', 'seasoning'],
     ['garlic clove', '5', 'each', 'base'], ['cumin', '1', 'tsp', 'seasoning'],
     ['flour', '2/3', 'cup', 'base']],
    5, 7],
   [['pepper', '5/8', 'tsp'], ['salt', '2 7/8', 'tsp'], ['garlic clove', '7', 'each'],
    ['cumin', '1 1/4', 'tsp'], ['flour', '7/8', 'cup']]],
  ['generated control 2',
   [[['flour', '3', 'cup', 'base'], ['salt', '5/2', 'tsp', 'seasoning'],
     ['pepper', '1/3', 'tsp', 'seasoning'], ['butter', '3/4', 'tbsp', 'base'], ['milk', '1', 'cup', 'base']],
    2, 6],
   [['flour', '9', 'cup'], ['salt', '6 1/4', 'tsp'], ['pepper', '7/8', 'tsp'], ['butter', '2 1/4', 'tbsp'],
    ['milk', '3', 'cup']]],
  ['generated control 3',
   [[['garlic clove', '4', 'each', 'base'], ['salt', '1/8', 'tsp', 'seasoning'],
     ['cumin', '3/4', 'tsp', 'seasoning'], ['lime', '5', 'each', 'base']],
    4, 4],
   [['garlic clove', '4', 'each'], ['salt', '1/8', 'tsp'], ['cumin', '3/4', 'tsp'], ['lime', '5', 'each']]]]]
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 fixtureActualExpectedOutcome
identity scaling control[['egg', '2', 'each'], ['flour', '1 1/2', 'cup']][['egg', '2', 'each'], ['flour', '1 1/2', 'cup']]Passed
zero servings rejectederror: servings must be positiveerror: servings must be positivePassed
double batch with seasoning[['salt', '1 3/4', 'tsp'], ['egg', '6', 'each']][['salt', '1 3/4', 'tsp'], ['egg', '6', 'each']]Passed
regression: count half-up rounding[['lime', '4', 'each'], ['butter', '1 1/2', 'tbsp'], ['salt', '3 1/8', 'tsp'], ['cumin', '1', 'tsp'], ['milk', '1 1/2', 'cup']][['lime', '5', 'each'], ['butter', '1 1/2', 'tbsp'], ['salt', '3 1/8', 'tsp'], ['cumin', '1', 'tsp'], ['milk', '1 1/2', 'cup']]Failed
repair check: count half-up rounding[['cumin', '1 1/8', 'tsp'], ['lime', '3', 'each'], ['pepper', '2 3/8', 'tsp'], ['milk', '7/8', 'cup']][['cumin', '1 1/8', 'tsp'], ['lime', '4', 'each'], ['pepper', '2 3/8', 'tsp'], ['milk', '7/8', 'cup']]Failed
generated control 1[['milk', '2 1/2', 'cup'], ['cumin', '1/4', 'tsp']][['milk', '2 1/2', 'cup'], ['cumin', '1/4', 'tsp']]Passed
generated control 2[['flour', '1 1/2', 'cup'], ['salt', '4 3/8', 'tsp']][['flour', '1 1/2', 'cup'], ['salt', '4 3/8', 'tsp']]Passed
generated control 3[['butter', '5/8', 'tbsp'], ['lime', '1', 'each'], ['flour', '1/8', 'cup'], ['garlic clove', '1', 'each']][['butter', '5/8', 'tbsp'], ['lime', '1', 'each'], ['flour', '1/8', 'cup'], ['garlic clove', '1', 'each']]Passed

SHA-256 / 3f37d8e90d3d69a619ee220fd0a954b09a4eb1cd319b65a170c5fb2efe3f660f

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(items, base, target):
    if base <= 0 or target <= 0:
        return 'error: servings must be positive'
    f = Fraction(target, base)
    def fmt(e):
        if e == 0:
            return 'pinch'
        whole, rem = divmod(e, 8)
        if rem == 0:
            return str(whole)
        g = math.gcd(rem, 8)
        frac = '%d/%d' % (rem // g, 8 // g)
        return frac if whole == 0 else '%d %s' % (whole, frac)
    out = []
    for name, qty, unit, kind in items:
        q = Fraction(qty)
        if kind == 'seasoning':
            s = q * (1 + (f - 1) * Fraction(3, 4))
        else:
            s = q * f
        if unit == 'each':
            n = int(s) + (1 if s - int(s) > Fraction(1, 2) else 0)
            out.append([name, str(max(1, n)), unit])
        else:
            e = int(s * 8 + Fraction(1, 2))
            out.append([name, fmt(e), unit])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['identity scaling control', [[['egg', '2', 'each', 'base'], ['flour', '3/2', 'cup', 'base']], 4, 4],
   [['egg', '2', 'each'], ['flour', '1 1/2', 'cup']]],
  ['zero servings rejected', [[['egg', '2', 'each', 'base']], 0, 4], 'error: servings must be positive'],
  ['double batch with seasoning', [[['salt', '1', 'tsp', 'seasoning'], ['egg', '3', 'each', 'base']], 4, 8],
   [['salt', '1 3/4', 'tsp'], ['egg', '6', 'each']]],
  ['regression: count half-up rounding',
   [[['lime', '3', 'each', 'base'], ['butter', '1', 'tbsp', 'base'], ['salt', '9/4', 'tsp', 'seasoning'],
     ['cumin', '3/4', 'tsp', 'seasoning'], ['milk', '1', 'cup', 'base']],
    8, 12],
   [['lime', '5', 'each'], ['butter', '1 1/2', 'tbsp'], ['salt', '3 1/8', 'tsp'], ['cumin', '1', 'tsp'],
    ['milk', '1 1/2', 'cup']]],
  ['repair check: count half-up rounding',
   [[['cumin', '3/4', 'tsp', 'seasoning'], ['lime', '2', 'each', 'base'],
     ['pepper', '3/2', 'tsp', 'seasoning'], ['milk', '1/2', 'cup', 'base']],
    4, 7],
   [['cumin', '1 1/8', 'tsp'], ['lime', '4', 'each'], ['pepper', '2 3/8', 'tsp'], ['milk', '7/8', 'cup']]],
  ['generated control 1', [[['milk', '2', 'cup', 'base'], ['cumin', '1/4', 'tsp', 'seasoning']], 4, 5],
   [['milk', '2 1/2', 'cup'], ['cumin', '1/4', 'tsp']]],
  ['generated control 2', [[['flour', '3/4', 'cup', 'base'], ['salt', '5/2', 'tsp', 'seasoning']], 6, 12],
   [['flour', '1 1/2', 'cup'], ['salt', '4 3/8', 'tsp']]],
  ['generated control 3',
   [[['butter', '1/2', 'tbsp', 'base'], ['lime', '1/2', 'each', 'base'], ['flour', '1/8', 'cup', 'base'],
     ['garlic clove', '1', 'each', 'base']],
    5, 6],
   [['butter', '5/8', 'tbsp'], ['lime', '1', 'each'], ['flour', '1/8', 'cup'],
    ['garlic clove', '1', 'each']]]],
 [['zero servings rejected', [[['egg', '2', 'each', 'base']], 0, 4], 'error: servings must be positive'],
  ['double batch with seasoning', [[['salt', '1', 'tsp', 'seasoning'], ['egg', '3', 'each', 'base']], 4, 8],
   [['salt', '1 3/4', 'tsp'], ['egg', '6', 'each']]],
  ['tiny scale-down to pinch', [[['cumin', '1/8', 'tsp', 'base'], ['egg', '1', 'each', 'base']], 8, 1],
   [['cumin', 'pinch', 'tsp'], ['egg', '1', 'each']]],
  ['regression: count half-up rounding',
   [[['egg', '5', 'each', 'base'], ['lime', '4', 'each', 'base']], 6, 9],
   [['egg', '8', 'each'], ['lime', '6', 'each']]],
  ['repair check: count half-up rounding',
   [[['lime', '5', 'each', 'base'], ['pepper', '3/4', 'tsp', 'seasoning'], ['milk', '2/3', 'cup', 'base'],
     ['cumin', '2', 'tsp', 'seasoning']],
    2, 9],
   [['lime', '23', 'each'], ['pepper', '2 3/4', 'tsp'], ['milk', '3', 'cup'], ['cumin', '7 1/4', 'tsp']]],
  ['generated control 1',
   [[['pepper', '3/4', 'tsp', 'seasoning'], ['egg', '2', 'each', 'base'], ['lime', '1/2', 'each', 'base'],
     ['flour', '1/3', 'cup', 'base'], ['butter', '1/3', 'tbsp', 'base']],
    6, 1],
   [['pepper', '1/4', 'tsp'], ['egg', '1', 'each'], ['lime', '1', 'each'], ['flour', 'pinch', 'cup'],
    ['butter', 'pinch', 'tbsp']]],
  ['generated control 2',
   [[['salt', '1/2', 'tsp', 'seasoning'], ['pepper', '1/2', 'tsp', 'seasoning'],
     ['cumin', '3/2', 'tsp', 'seasoning']],
    3, 12],
   [['salt', '1 5/8', 'tsp'], ['pepper', '1 5/8', 'tsp'], ['cumin', '4 7/8', 'tsp']]],
  ['generated control 3',
   [[['cumin', '3/2', 'tsp', 'seasoning'], ['butter', '1/4', 'tbsp', 'base'], ['egg', '1', 'each', 'base']],
    5, 8],
   [['cumin', '2 1/8', 'tsp'], ['butter', '3/8', 'tbsp'], ['egg', '2', 'each']]]],
 [['double batch with seasoning', [[['salt', '1', 'tsp', 'seasoning'], ['egg', '3', 'each', 'base']], 4, 8],
   [['salt', '1 3/4', 'tsp'], ['egg', '6', 'each']]],
  ['tiny scale-down to pinch', [[['cumin', '1/8', 'tsp', 'base'], ['egg', '1', 'each', 'base']], 8, 1],
   [['cumin', 'pinch', 'tsp'], ['egg', '1', 'each']]],
  ['half egg rounds up', [[['egg', '3', 'each', 'base'], ['milk', '1/2', 'cup', 'base']], 4, 6],
   [['egg', '5', 'each'], ['milk', '3/4', 'cup']]],
  ['regression: count half-up rounding',
   [[['cumin', '1', 'tsp', 'seasoning'], ['pepper', '3', 'tsp', 'seasoning'], ['milk', '3/4', 'cup', 'base'],
     ['salt', '1', 'tsp', 'seasoning'], ['garlic clove', '3', 'each', 'base']],
    4, 9],
   [['cumin', '2', 'tsp'], ['pepper', '5 7/8', 'tsp'], ['milk', '1 3/4', 'cup'], ['salt', '2', 'tsp'],
    ['garlic clove', '7', 'each']]],
  ['repair check: count half-up rounding',
   [[['milk', '2/3', 'cup', 'base'], ['lime', '5', 'each', 'base'], ['egg', '1/2', 'each', 'base'],
     ['flour', '1/2', 'cup', 'base'], ['garlic clove', '1', 'each', 'base']],
    2, 3],
   [['milk', '1', 'cup'], ['lime', '8', 'each'], ['egg', '1', 'each'], ['flour', '3/4', 'cup'],
    ['garlic clove', '2', 'each']]],
  ['generated control 1',
   [[['flour', '1/2', 'cup', 'base'], ['pepper', '2/3', 'tsp', 'seasoning'],
     ['butter', '1/3', 'tbsp', 'base'], ['salt', '1/3', 'tsp', 'seasoning']],
    8, 7],
   [['flour', '1/2', 'cup'], ['pepper', '5/8', 'tsp'], ['butter', '1/4', 'tbsp'], ['salt', '1/4', 'tsp']]],
  ['generated control 2',
   [[['cumin', '1/3', 'tsp', 'seasoning'], ['milk', '3', 'cup', 'base'],
     ['pepper', '9/4', 'tsp', 'seasoning'], ['butter', '2/3', 'tbsp', 'base']],
    1, 9],
   [['cumin', '2 3/8', 'tsp'], ['milk', '27', 'cup'], ['pepper', '15 3/4', 'tsp'], ['butter', '6', 'tbsp']]],
  ['generated control 3',
   [[['garlic clove', '2', 'each', 'base'], ['pepper', '1/8', 'tsp', 'seasoning']], 4, 1],
   [['garlic clove', '1', 'each'], ['pepper', 'pinch', 'tsp']]]],
 [['tiny scale-down to pinch', [[['cumin', '1/8', 'tsp', 'base'], ['egg', '1', 'each', 'base']], 8, 1],
   [['cumin', 'pinch', 'tsp'], ['egg', '1', 'each']]],
  ['half egg rounds up', [[['egg', '3', 'each', 'base'], ['milk', '1/2', 'cup', 'base']], 4, 6],
   [['egg', '5', 'each'], ['milk', '3/4', 'cup']]],
  ['identity scaling control', [[['egg', '2', 'each', 'base'], ['flour', '3/2', 'cup', 'base']], 4, 4],
   [['egg', '2', 'each'], ['flour', '1 1/2', 'cup']]],
  ['regression: count half-up rounding',
   [[['butter', '1/4', 'tbsp', 'base'], ['garlic clove', '3', 'each', 'base'],
     ['egg', '1/2', 'each', 'base']],
    7, 6],
   [['butter', '1/4', 'tbsp'], ['garlic clove', '3', 'each'], ['egg', '1', 'each']]],
  ['repair check: count half-up rounding',
   [[['lime', '2', 'each', 'base'], ['butter', '3', 'tbsp', 'base'], ['garlic clove', '5', 'each', 'base'],
     ['salt', '3/2', 'tsp', 'seasoning']],
    2, 5],
   [['lime', '5', 'each'], ['butter', '7 1/2', 'tbsp'], ['garlic clove', '13', 'each'],
    ['salt', '3 1/4', 'tsp']]],
  ['generated control 1',
   [[['egg', '3', 'each', 'base'], ['cumin', '3/2', 'tsp', 'seasoning'], ['butter', '2/3', 'tbsp', 'base'],
     ['flour', '3', 'cup', 'base'], ['salt', '2', 'tsp', 'seasoning']],
    4, 11],
   [['egg', '8', 'each'], ['cumin', '3 1/2', 'tsp'], ['butter', '1 7/8', 'tbsp'], ['flour', '8 1/4', 'cup'],
    ['salt', '4 5/8', 'tsp']]],
  ['generated control 2',
   [[['cumin', '9/4', 'tsp', 'seasoning'], ['egg', '3', 'each', 'base'], ['butter', '1/3', 'tbsp', 'base'],
     ['flour', '1/2', 'cup', 'base']],
    8, 1],
   [['cumin', '3/4', 'tsp'], ['egg', '1', 'each'], ['butter', 'pinch', 'tbsp'], ['flour', '1/8', 'cup']]],
  ['generated control 3', [[['egg', '1', 'each', 'base'], ['milk', '1/4', 'cup', 'base']], 5, 2],
   [['egg', '1', 'each'], ['milk', '1/8', 'cup']]]],
 [['half egg rounds up', [[['egg', '3', 'each', 'base'], ['milk', '1/2', 'cup', 'base']], 4, 6],
   [['egg', '5', 'each'], ['milk', '3/4', 'cup']]],
  ['identity scaling control', [[['egg', '2', 'each', 'base'], ['flour', '3/2', 'cup', 'base']], 4, 4],
   [['egg', '2', 'each'], ['flour', '1 1/2', 'cup']]],
  ['zero servings rejected', [[['egg', '2', 'each', 'base']], 0, 4], 'error: servings must be positive'],
  ['regression: count half-up rounding',
   [[['cumin', '5/2', 'tsp', 'seasoning'], ['garlic clove', '2', 'each', 'base'],
     ['pepper', '1/3', 'tsp', 'seasoning'], ['butter', '2/3', 'tbsp', 'base']],
    8, 7],
   [['cumin', '2 1/4', 'tsp'], ['garlic clove', '2', 'each'], ['pepper', '1/4', 'tsp'],
    ['butter', '5/8', 'tbsp']]],
  ['repair check: count half-up rounding',
   [[['lime', '5', 'each', 'base'], ['egg', '4', 'each', 'base'], ['flour', '1', 'cup', 'base'],
     ['milk', '2/3', 'cup', 'base']],
    2, 3],
   [['lime', '8', 'each'], ['egg', '6', 'each'], ['flour', '1 1/2', 'cup'], ['milk', '1', 'cup']]],
  ['generated control 1',
   [[['pepper', '1/2', 'tsp', 'seasoning'], ['salt', '9/4', 'tsp', 'seasoning'],
     ['garlic clove', '5', 'each', 'base'], ['cumin', '1', 'tsp', 'seasoning'],
     ['flour', '2/3', 'cup', 'base']],
    5, 7],
   [['pepper', '5/8', 'tsp'], ['salt', '2 7/8', 'tsp'], ['garlic clove', '7', 'each'],
    ['cumin', '1 1/4', 'tsp'], ['flour', '7/8', 'cup']]],
  ['generated control 2',
   [[['flour', '3', 'cup', 'base'], ['salt', '5/2', 'tsp', 'seasoning'],
     ['pepper', '1/3', 'tsp', 'seasoning'], ['butter', '3/4', 'tbsp', 'base'], ['milk', '1', 'cup', 'base']],
    2, 6],
   [['flour', '9', 'cup'], ['salt', '6 1/4', 'tsp'], ['pepper', '7/8', 'tsp'], ['butter', '2 1/4', 'tbsp'],
    ['milk', '3', 'cup']]],
  ['generated control 3',
   [[['garlic clove', '4', 'each', 'base'], ['salt', '1/8', 'tsp', 'seasoning'],
     ['cumin', '3/4', 'tsp', 'seasoning'], ['lime', '5', 'each', 'base']],
    4, 4],
   [['garlic clove', '4', 'each'], ['salt', '1/8', 'tsp'], ['cumin', '3/4', 'tsp'], ['lime', '5', 'each']]]]]
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 fixtureActualExpectedOutcome
identity scaling control[['egg', '2', 'each'], ['flour', '1 1/2', 'cup']][['egg', '2', 'each'], ['flour', '1 1/2', 'cup']]Passed
zero servings rejectederror: servings must be positiveerror: servings must be positivePassed
double batch with seasoning[['salt', '1 3/4', 'tsp'], ['egg', '6', 'each']][['salt', '1 3/4', 'tsp'], ['egg', '6', 'each']]Passed
regression: count half-up rounding[['lime', '4', 'each'], ['butter', '1 1/2', 'tbsp'], ['salt', '3 1/8', 'tsp'], ['cumin', '1', 'tsp'], ['milk', '1 1/2', 'cup']][['lime', '5', 'each'], ['butter', '1 1/2', 'tbsp'], ['salt', '3 1/8', 'tsp'], ['cumin', '1', 'tsp'], ['milk', '1 1/2', 'cup']]Failed
repair check: count half-up rounding[['cumin', '1 1/8', 'tsp'], ['lime', '3', 'each'], ['pepper', '2 3/8', 'tsp'], ['milk', '7/8', 'cup']][['cumin', '1 1/8', 'tsp'], ['lime', '4', 'each'], ['pepper', '2 3/8', 'tsp'], ['milk', '7/8', 'cup']]Failed
generated control 1[['milk', '2 1/2', 'cup'], ['cumin', '1/4', 'tsp']][['milk', '2 1/2', 'cup'], ['cumin', '1/4', 'tsp']]Passed
generated control 2[['flour', '1 1/2', 'cup'], ['salt', '4 3/8', 'tsp']][['flour', '1 1/2', 'cup'], ['salt', '4 3/8', 'tsp']]Passed
generated control 3[['butter', '5/8', 'tbsp'], ['lime', '1', 'each'], ['flour', '1/8', 'cup'], ['garlic clove', '1', 'each']][['butter', '5/8', 'tbsp'], ['lime', '1', 'each'], ['flour', '1/8', 'cup'], ['garlic clove', '1', 'each']]Passed

SHA-256 / 08b2cf97f6040272f914a95f62886e9e66aa3a64c79de452531c36dadf9265ca

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(items, base, target):
    if base <= 0 or target <= 0:
        return 'error: servings must be positive'
    f = Fraction(target, base)
    def fmt(e):
        if e == 0:
            return 'pinch'
        whole, rem = divmod(e, 8)
        if rem == 0:
            return str(whole)
        g = math.gcd(rem, 8)
        frac = '%d/%d' % (rem // g, 8 // g)
        return frac if whole == 0 else '%d %s' % (whole, frac)
    out = []
    for name, qty, unit, kind in items:
        q = Fraction(qty)
        if kind == 'seasoning':
            s = q * (1 + (f - 1) * Fraction(3, 4))
        else:
            s = q * f
        if unit == 'each':
            n = int(s) + (1 if s - int(s) >= Fraction(1, 2) else 0)
            out.append([name, str(max(1, n)), unit])
        else:
            e = int(s * 8 + Fraction(1, 2))
            out.append([name, fmt(e), unit])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['identity scaling control', [[['egg', '2', 'each', 'base'], ['flour', '3/2', 'cup', 'base']], 4, 4],
   [['egg', '2', 'each'], ['flour', '1 1/2', 'cup']]],
  ['zero servings rejected', [[['egg', '2', 'each', 'base']], 0, 4], 'error: servings must be positive'],
  ['double batch with seasoning', [[['salt', '1', 'tsp', 'seasoning'], ['egg', '3', 'each', 'base']], 4, 8],
   [['salt', '1 3/4', 'tsp'], ['egg', '6', 'each']]],
  ['regression: count half-up rounding',
   [[['lime', '3', 'each', 'base'], ['butter', '1', 'tbsp', 'base'], ['salt', '9/4', 'tsp', 'seasoning'],
     ['cumin', '3/4', 'tsp', 'seasoning'], ['milk', '1', 'cup', 'base']],
    8, 12],
   [['lime', '5', 'each'], ['butter', '1 1/2', 'tbsp'], ['salt', '3 1/8', 'tsp'], ['cumin', '1', 'tsp'],
    ['milk', '1 1/2', 'cup']]],
  ['repair check: count half-up rounding',
   [[['cumin', '3/4', 'tsp', 'seasoning'], ['lime', '2', 'each', 'base'],
     ['pepper', '3/2', 'tsp', 'seasoning'], ['milk', '1/2', 'cup', 'base']],
    4, 7],
   [['cumin', '1 1/8', 'tsp'], ['lime', '4', 'each'], ['pepper', '2 3/8', 'tsp'], ['milk', '7/8', 'cup']]],
  ['generated control 1', [[['milk', '2', 'cup', 'base'], ['cumin', '1/4', 'tsp', 'seasoning']], 4, 5],
   [['milk', '2 1/2', 'cup'], ['cumin', '1/4', 'tsp']]],
  ['generated control 2', [[['flour', '3/4', 'cup', 'base'], ['salt', '5/2', 'tsp', 'seasoning']], 6, 12],
   [['flour', '1 1/2', 'cup'], ['salt', '4 3/8', 'tsp']]],
  ['generated control 3',
   [[['butter', '1/2', 'tbsp', 'base'], ['lime', '1/2', 'each', 'base'], ['flour', '1/8', 'cup', 'base'],
     ['garlic clove', '1', 'each', 'base']],
    5, 6],
   [['butter', '5/8', 'tbsp'], ['lime', '1', 'each'], ['flour', '1/8', 'cup'],
    ['garlic clove', '1', 'each']]]],
 [['zero servings rejected', [[['egg', '2', 'each', 'base']], 0, 4], 'error: servings must be positive'],
  ['double batch with seasoning', [[['salt', '1', 'tsp', 'seasoning'], ['egg', '3', 'each', 'base']], 4, 8],
   [['salt', '1 3/4', 'tsp'], ['egg', '6', 'each']]],
  ['tiny scale-down to pinch', [[['cumin', '1/8', 'tsp', 'base'], ['egg', '1', 'each', 'base']], 8, 1],
   [['cumin', 'pinch', 'tsp'], ['egg', '1', 'each']]],
  ['regression: count half-up rounding',
   [[['egg', '5', 'each', 'base'], ['lime', '4', 'each', 'base']], 6, 9],
   [['egg', '8', 'each'], ['lime', '6', 'each']]],
  ['repair check: count half-up rounding',
   [[['lime', '5', 'each', 'base'], ['pepper', '3/4', 'tsp', 'seasoning'], ['milk', '2/3', 'cup', 'base'],
     ['cumin', '2', 'tsp', 'seasoning']],
    2, 9],
   [['lime', '23', 'each'], ['pepper', '2 3/4', 'tsp'], ['milk', '3', 'cup'], ['cumin', '7 1/4', 'tsp']]],
  ['generated control 1',
   [[['pepper', '3/4', 'tsp', 'seasoning'], ['egg', '2', 'each', 'base'], ['lime', '1/2', 'each', 'base'],
     ['flour', '1/3', 'cup', 'base'], ['butter', '1/3', 'tbsp', 'base']],
    6, 1],
   [['pepper', '1/4', 'tsp'], ['egg', '1', 'each'], ['lime', '1', 'each'], ['flour', 'pinch', 'cup'],
    ['butter', 'pinch', 'tbsp']]],
  ['generated control 2',
   [[['salt', '1/2', 'tsp', 'seasoning'], ['pepper', '1/2', 'tsp', 'seasoning'],
     ['cumin', '3/2', 'tsp', 'seasoning']],
    3, 12],
   [['salt', '1 5/8', 'tsp'], ['pepper', '1 5/8', 'tsp'], ['cumin', '4 7/8', 'tsp']]],
  ['generated control 3',
   [[['cumin', '3/2', 'tsp', 'seasoning'], ['butter', '1/4', 'tbsp', 'base'], ['egg', '1', 'each', 'base']],
    5, 8],
   [['cumin', '2 1/8', 'tsp'], ['butter', '3/8', 'tbsp'], ['egg', '2', 'each']]]],
 [['double batch with seasoning', [[['salt', '1', 'tsp', 'seasoning'], ['egg', '3', 'each', 'base']], 4, 8],
   [['salt', '1 3/4', 'tsp'], ['egg', '6', 'each']]],
  ['tiny scale-down to pinch', [[['cumin', '1/8', 'tsp', 'base'], ['egg', '1', 'each', 'base']], 8, 1],
   [['cumin', 'pinch', 'tsp'], ['egg', '1', 'each']]],
  ['half egg rounds up', [[['egg', '3', 'each', 'base'], ['milk', '1/2', 'cup', 'base']], 4, 6],
   [['egg', '5', 'each'], ['milk', '3/4', 'cup']]],
  ['regression: count half-up rounding',
   [[['cumin', '1', 'tsp', 'seasoning'], ['pepper', '3', 'tsp', 'seasoning'], ['milk', '3/4', 'cup', 'base'],
     ['salt', '1', 'tsp', 'seasoning'], ['garlic clove', '3', 'each', 'base']],
    4, 9],
   [['cumin', '2', 'tsp'], ['pepper', '5 7/8', 'tsp'], ['milk', '1 3/4', 'cup'], ['salt', '2', 'tsp'],
    ['garlic clove', '7', 'each']]],
  ['repair check: count half-up rounding',
   [[['milk', '2/3', 'cup', 'base'], ['lime', '5', 'each', 'base'], ['egg', '1/2', 'each', 'base'],
     ['flour', '1/2', 'cup', 'base'], ['garlic clove', '1', 'each', 'base']],
    2, 3],
   [['milk', '1', 'cup'], ['lime', '8', 'each'], ['egg', '1', 'each'], ['flour', '3/4', 'cup'],
    ['garlic clove', '2', 'each']]],
  ['generated control 1',
   [[['flour', '1/2', 'cup', 'base'], ['pepper', '2/3', 'tsp', 'seasoning'],
     ['butter', '1/3', 'tbsp', 'base'], ['salt', '1/3', 'tsp', 'seasoning']],
    8, 7],
   [['flour', '1/2', 'cup'], ['pepper', '5/8', 'tsp'], ['butter', '1/4', 'tbsp'], ['salt', '1/4', 'tsp']]],
  ['generated control 2',
   [[['cumin', '1/3', 'tsp', 'seasoning'], ['milk', '3', 'cup', 'base'],
     ['pepper', '9/4', 'tsp', 'seasoning'], ['butter', '2/3', 'tbsp', 'base']],
    1, 9],
   [['cumin', '2 3/8', 'tsp'], ['milk', '27', 'cup'], ['pepper', '15 3/4', 'tsp'], ['butter', '6', 'tbsp']]],
  ['generated control 3',
   [[['garlic clove', '2', 'each', 'base'], ['pepper', '1/8', 'tsp', 'seasoning']], 4, 1],
   [['garlic clove', '1', 'each'], ['pepper', 'pinch', 'tsp']]]],
 [['tiny scale-down to pinch', [[['cumin', '1/8', 'tsp', 'base'], ['egg', '1', 'each', 'base']], 8, 1],
   [['cumin', 'pinch', 'tsp'], ['egg', '1', 'each']]],
  ['half egg rounds up', [[['egg', '3', 'each', 'base'], ['milk', '1/2', 'cup', 'base']], 4, 6],
   [['egg', '5', 'each'], ['milk', '3/4', 'cup']]],
  ['identity scaling control', [[['egg', '2', 'each', 'base'], ['flour', '3/2', 'cup', 'base']], 4, 4],
   [['egg', '2', 'each'], ['flour', '1 1/2', 'cup']]],
  ['regression: count half-up rounding',
   [[['butter', '1/4', 'tbsp', 'base'], ['garlic clove', '3', 'each', 'base'],
     ['egg', '1/2', 'each', 'base']],
    7, 6],
   [['butter', '1/4', 'tbsp'], ['garlic clove', '3', 'each'], ['egg', '1', 'each']]],
  ['repair check: count half-up rounding',
   [[['lime', '2', 'each', 'base'], ['butter', '3', 'tbsp', 'base'], ['garlic clove', '5', 'each', 'base'],
     ['salt', '3/2', 'tsp', 'seasoning']],
    2, 5],
   [['lime', '5', 'each'], ['butter', '7 1/2', 'tbsp'], ['garlic clove', '13', 'each'],
    ['salt', '3 1/4', 'tsp']]],
  ['generated control 1',
   [[['egg', '3', 'each', 'base'], ['cumin', '3/2', 'tsp', 'seasoning'], ['butter', '2/3', 'tbsp', 'base'],
     ['flour', '3', 'cup', 'base'], ['salt', '2', 'tsp', 'seasoning']],
    4, 11],
   [['egg', '8', 'each'], ['cumin', '3 1/2', 'tsp'], ['butter', '1 7/8', 'tbsp'], ['flour', '8 1/4', 'cup'],
    ['salt', '4 5/8', 'tsp']]],
  ['generated control 2',
   [[['cumin', '9/4', 'tsp', 'seasoning'], ['egg', '3', 'each', 'base'], ['butter', '1/3', 'tbsp', 'base'],
     ['flour', '1/2', 'cup', 'base']],
    8, 1],
   [['cumin', '3/4', 'tsp'], ['egg', '1', 'each'], ['butter', 'pinch', 'tbsp'], ['flour', '1/8', 'cup']]],
  ['generated control 3', [[['egg', '1', 'each', 'base'], ['milk', '1/4', 'cup', 'base']], 5, 2],
   [['egg', '1', 'each'], ['milk', '1/8', 'cup']]]],
 [['half egg rounds up', [[['egg', '3', 'each', 'base'], ['milk', '1/2', 'cup', 'base']], 4, 6],
   [['egg', '5', 'each'], ['milk', '3/4', 'cup']]],
  ['identity scaling control', [[['egg', '2', 'each', 'base'], ['flour', '3/2', 'cup', 'base']], 4, 4],
   [['egg', '2', 'each'], ['flour', '1 1/2', 'cup']]],
  ['zero servings rejected', [[['egg', '2', 'each', 'base']], 0, 4], 'error: servings must be positive'],
  ['regression: count half-up rounding',
   [[['cumin', '5/2', 'tsp', 'seasoning'], ['garlic clove', '2', 'each', 'base'],
     ['pepper', '1/3', 'tsp', 'seasoning'], ['butter', '2/3', 'tbsp', 'base']],
    8, 7],
   [['cumin', '2 1/4', 'tsp'], ['garlic clove', '2', 'each'], ['pepper', '1/4', 'tsp'],
    ['butter', '5/8', 'tbsp']]],
  ['repair check: count half-up rounding',
   [[['lime', '5', 'each', 'base'], ['egg', '4', 'each', 'base'], ['flour', '1', 'cup', 'base'],
     ['milk', '2/3', 'cup', 'base']],
    2, 3],
   [['lime', '8', 'each'], ['egg', '6', 'each'], ['flour', '1 1/2', 'cup'], ['milk', '1', 'cup']]],
  ['generated control 1',
   [[['pepper', '1/2', 'tsp', 'seasoning'], ['salt', '9/4', 'tsp', 'seasoning'],
     ['garlic clove', '5', 'each', 'base'], ['cumin', '1', 'tsp', 'seasoning'],
     ['flour', '2/3', 'cup', 'base']],
    5, 7],
   [['pepper', '5/8', 'tsp'], ['salt', '2 7/8', 'tsp'], ['garlic clove', '7', 'each'],
    ['cumin', '1 1/4', 'tsp'], ['flour', '7/8', 'cup']]],
  ['generated control 2',
   [[['flour', '3', 'cup', 'base'], ['salt', '5/2', 'tsp', 'seasoning'],
     ['pepper', '1/3', 'tsp', 'seasoning'], ['butter', '3/4', 'tbsp', 'base'], ['milk', '1', 'cup', 'base']],
    2, 6],
   [['flour', '9', 'cup'], ['salt', '6 1/4', 'tsp'], ['pepper', '7/8', 'tsp'], ['butter', '2 1/4', 'tbsp'],
    ['milk', '3', 'cup']]],
  ['generated control 3',
   [[['garlic clove', '4', 'each', 'base'], ['salt', '1/8', 'tsp', 'seasoning'],
     ['cumin', '3/4', 'tsp', 'seasoning'], ['lime', '5', 'each', 'base']],
    4, 4],
   [['garlic clove', '4', 'each'], ['salt', '1/8', 'tsp'], ['cumin', '3/4', 'tsp'], ['lime', '5', 'each']]]]]
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 fixtureActualExpectedOutcome
identity scaling control[['egg', '2', 'each'], ['flour', '1 1/2', 'cup']][['egg', '2', 'each'], ['flour', '1 1/2', 'cup']]Passed
zero servings rejectederror: servings must be positiveerror: servings must be positivePassed
double batch with seasoning[['salt', '1 3/4', 'tsp'], ['egg', '6', 'each']][['salt', '1 3/4', 'tsp'], ['egg', '6', 'each']]Passed
regression: count half-up rounding[['lime', '5', 'each'], ['butter', '1 1/2', 'tbsp'], ['salt', '3 1/8', 'tsp'], ['cumin', '1', 'tsp'], ['milk', '1 1/2', 'cup']][['lime', '5', 'each'], ['butter', '1 1/2', 'tbsp'], ['salt', '3 1/8', 'tsp'], ['cumin', '1', 'tsp'], ['milk', '1 1/2', 'cup']]Passed
repair check: count half-up rounding[['cumin', '1 1/8', 'tsp'], ['lime', '4', 'each'], ['pepper', '2 3/8', 'tsp'], ['milk', '7/8', 'cup']][['cumin', '1 1/8', 'tsp'], ['lime', '4', 'each'], ['pepper', '2 3/8', 'tsp'], ['milk', '7/8', 'cup']]Passed
generated control 1[['milk', '2 1/2', 'cup'], ['cumin', '1/4', 'tsp']][['milk', '2 1/2', 'cup'], ['cumin', '1/4', 'tsp']]Passed
generated control 2[['flour', '1 1/2', 'cup'], ['salt', '4 3/8', 'tsp']][['flour', '1 1/2', 'cup'], ['salt', '4 3/8', 'tsp']]Passed
generated control 3[['butter', '5/8', 'tbsp'], ['lime', '1', 'each'], ['flour', '1/8', 'cup'], ['garlic clove', '1', 'each']][['butter', '5/8', 'tbsp'], ['lime', '1', 'each'], ['flour', '1/8', 'cup'], ['garlic clove', '1', 'each']]Passed

SHA-256 / cbc06b60d1b5bbdc1c2b35c2eb2ac4ae9dd6dc99e376c1eca30ee558031b33b1

Verification & scope

A deterministic toy contract stated in full here; it is a bounded teaching model, not an authoritative reference or standards implementation. 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:52:26.461596+00:00.

Case digest / 21297c8c0f1b4f8efe386fb15811c6ed4d056ef7c06b6522c7ecf75287db7e53