FAILURE MAP
← Case archive

FA-97746 / Knitting and sewing pattern grading / Open access

Knitting needle size converter: tolerance edge · case 01

An 11 mm needle is reported as US 15.

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

ROOT CAUSE

No tolerance is applied, so any size maps to the nearest table entry.

VERIFIED REPAIR

Skip entries more than 0.5 mm away.

Unsuccessful approach: An exclusive tolerance rejects sizes exactly 0.5 mm away.

Case contract

Table US->mm: 0 2.0, 1 2.25, 2 2.75, 3 3.25, 4 3.5, 5 3.75, 6 4.0, 7 4.5, 8 5.0, 9 5.5, 10 6.0, 10.5 6.5, 11 8.0, 13 9.0, 15 10.0. "us->mm": trim, "10 1/2" means "10.5", exact match or "error: size". "mm->us": nearest size within 0.5 mm inclusive, ties to the larger mm, else "error: size". Other directions -> "error: direction".

Why this case matters

Patterns list needle sizes in US or metric and knitters convert between them.

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(value, direction):
    T = [('0', 2.0), ('1', 2.25), ('2', 2.75), ('3', 3.25), ('4', 3.5), ('5', 3.75), ('6', 4.0), ('7', 4.5),
         ('8', 5.0), ('9', 5.5), ('10', 6.0), ('10.5', 6.5), ('11', 8.0), ('13', 9.0), ('15', 10.0)]
    if direction == 'us->mm':
        v = str(value).strip().replace(' 1/2', '.5')
        for us, mm in T:
            if us == v:
                return mm
        return 'error: size'
    if direction == 'mm->us':
        x = Fraction(str(value))
        best = None
        for us, mm in T:
            d = abs(Fraction(str(mm)) - x)
            if d > 100:
                continue
            if best is None or d < best[0] or (d == best[0] and mm > best[2]):
                best = (d, us, mm)
        return best[1] if best else 'error: size'
    return 'error: direction' 
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['US 8', ['8', 'us->mm'], 5.0], ['half size', ['10 1/2', 'us->mm'], 6.5],
  ['tie between 9 and 10', [5.75, 'mm->us'], '10'],
  ['regression: tolerance edge', [7.25, 'mm->us'], 'error: size'],
  ['repair check: tolerance edge', [9.5, 'mm->us'], '15'], ['generated control 1', [11, 'us->mm'], 8.0],
  ['generated control 2', [3.3, 'mm->us'], '3'], ['generated control 3', [7.0, 'uk'], 'error: direction']],
 [['half size', ['10 1/2', 'us->mm'], 6.5], ['tie between 9 and 10', [5.75, 'mm->us'], '10'],
  ['edge of tolerance', [1.5, 'mm->us'], '0'],
  ['regression: tolerance edge', [10.6, 'mm->us'], 'error: size'],
  ['generated control 1', [11, 'us->mm'], 8.0], ['generated control 2', ['10.5', 'us->mm'], 6.5],
  ['generated control 3', [10.6, 'uk'], 'error: direction'],
  ['generated control 4', ['12', 'us->mm'], 'error: size']],
 [['tie between 9 and 10', [5.75, 'mm->us'], '10'], ['edge of tolerance', [1.5, 'mm->us'], '0'],
  ['no match', [11.0, 'mm->us'], 'error: size'], ['repair check: tolerance edge', [7.0, 'mm->us'], '10.5'],
  ['generated control 1', ['12', 'us->mm'], 'error: size'],
  ['generated control 2', ['10 1/2', 'us->mm'], 6.5], ['generated control 3', [3.625, 'mm->us'], '5'],
  ['generated control 4', [1.5, 'uk'], 'error: direction']],
 [['edge of tolerance', [1.5, 'mm->us'], '0'], ['no match', [11.0, 'mm->us'], 'error: size'],
  ['US 8', ['8', 'us->mm'], 5.0], ['regression: tolerance edge', [10.6, 'mm->us'], 'error: size'],
  ['repair check: tolerance edge', [7.0, 'mm->us'], '10.5'],
  ['generated control 1', [6.25, 'mm->us'], '10.5'], ['generated control 2', ['12', 'us->mm'], 'error: size'],
  ['generated control 3', [3.625, 'mm->us'], '5']],
 [['no match', [11.0, 'mm->us'], 'error: size'], ['US 8', ['8', 'us->mm'], 5.0],
  ['half size', ['10 1/2', 'us->mm'], 6.5], ['regression: tolerance edge', [10.6, 'mm->us'], 'error: size'],
  ['repair check: tolerance edge', [9.5, 'mm->us'], '15'],
  ['generated control 1', [5.75, 'uk'], 'error: direction'], ['generated control 2', ['15', 'us->mm'], 10.0],
  ['generated control 3', [10.6, 'uk'], 'error: direction']]]
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
US 85.05.0Passed
half size6.56.5Passed
tie between 9 and 101010Passed
regression: tolerance edge11error: sizeFailed
repair check: tolerance edge1515Passed
generated control 18.08.0Passed
generated control 233Passed
generated control 3error: directionerror: directionPassed

SHA-256 / 6cf55069cd75521e9caf172e703dece2cd5eb3116d1673d8f25e621b03f95d4e

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(value, direction):
    T = [('0', 2.0), ('1', 2.25), ('2', 2.75), ('3', 3.25), ('4', 3.5), ('5', 3.75), ('6', 4.0), ('7', 4.5),
         ('8', 5.0), ('9', 5.5), ('10', 6.0), ('10.5', 6.5), ('11', 8.0), ('13', 9.0), ('15', 10.0)]
    if direction == 'us->mm':
        v = str(value).strip().replace(' 1/2', '.5')
        for us, mm in T:
            if us == v:
                return mm
        return 'error: size'
    if direction == 'mm->us':
        x = Fraction(str(value))
        best = None
        for us, mm in T:
            d = abs(Fraction(str(mm)) - x)
            if d >= Fraction(1, 2):
                continue
            if best is None or d < best[0] or (d == best[0] and mm > best[2]):
                best = (d, us, mm)
        return best[1] if best else 'error: size'
    return 'error: direction' 
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['US 8', ['8', 'us->mm'], 5.0], ['half size', ['10 1/2', 'us->mm'], 6.5],
  ['tie between 9 and 10', [5.75, 'mm->us'], '10'],
  ['regression: tolerance edge', [7.25, 'mm->us'], 'error: size'],
  ['repair check: tolerance edge', [9.5, 'mm->us'], '15'], ['generated control 1', [11, 'us->mm'], 8.0],
  ['generated control 2', [3.3, 'mm->us'], '3'], ['generated control 3', [7.0, 'uk'], 'error: direction']],
 [['half size', ['10 1/2', 'us->mm'], 6.5], ['tie between 9 and 10', [5.75, 'mm->us'], '10'],
  ['edge of tolerance', [1.5, 'mm->us'], '0'],
  ['regression: tolerance edge', [10.6, 'mm->us'], 'error: size'],
  ['generated control 1', [11, 'us->mm'], 8.0], ['generated control 2', ['10.5', 'us->mm'], 6.5],
  ['generated control 3', [10.6, 'uk'], 'error: direction'],
  ['generated control 4', ['12', 'us->mm'], 'error: size']],
 [['tie between 9 and 10', [5.75, 'mm->us'], '10'], ['edge of tolerance', [1.5, 'mm->us'], '0'],
  ['no match', [11.0, 'mm->us'], 'error: size'], ['repair check: tolerance edge', [7.0, 'mm->us'], '10.5'],
  ['generated control 1', ['12', 'us->mm'], 'error: size'],
  ['generated control 2', ['10 1/2', 'us->mm'], 6.5], ['generated control 3', [3.625, 'mm->us'], '5'],
  ['generated control 4', [1.5, 'uk'], 'error: direction']],
 [['edge of tolerance', [1.5, 'mm->us'], '0'], ['no match', [11.0, 'mm->us'], 'error: size'],
  ['US 8', ['8', 'us->mm'], 5.0], ['regression: tolerance edge', [10.6, 'mm->us'], 'error: size'],
  ['repair check: tolerance edge', [7.0, 'mm->us'], '10.5'],
  ['generated control 1', [6.25, 'mm->us'], '10.5'], ['generated control 2', ['12', 'us->mm'], 'error: size'],
  ['generated control 3', [3.625, 'mm->us'], '5']],
 [['no match', [11.0, 'mm->us'], 'error: size'], ['US 8', ['8', 'us->mm'], 5.0],
  ['half size', ['10 1/2', 'us->mm'], 6.5], ['regression: tolerance edge', [10.6, 'mm->us'], 'error: size'],
  ['repair check: tolerance edge', [9.5, 'mm->us'], '15'],
  ['generated control 1', [5.75, 'uk'], 'error: direction'], ['generated control 2', ['15', 'us->mm'], 10.0],
  ['generated control 3', [10.6, 'uk'], 'error: direction']]]
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
US 85.05.0Passed
half size6.56.5Passed
tie between 9 and 101010Passed
regression: tolerance edgeerror: sizeerror: sizePassed
repair check: tolerance edgeerror: size15Failed
generated control 18.08.0Passed
generated control 233Passed
generated control 3error: directionerror: directionPassed

SHA-256 / 918c8503589615aa6bb3433e25160ad2cc0cea50501d51d65d0b5c53e75413d0

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(value, direction):
    T = [('0', 2.0), ('1', 2.25), ('2', 2.75), ('3', 3.25), ('4', 3.5), ('5', 3.75), ('6', 4.0), ('7', 4.5),
         ('8', 5.0), ('9', 5.5), ('10', 6.0), ('10.5', 6.5), ('11', 8.0), ('13', 9.0), ('15', 10.0)]
    if direction == 'us->mm':
        v = str(value).strip().replace(' 1/2', '.5')
        for us, mm in T:
            if us == v:
                return mm
        return 'error: size'
    if direction == 'mm->us':
        x = Fraction(str(value))
        best = None
        for us, mm in T:
            d = abs(Fraction(str(mm)) - x)
            if d > Fraction(1, 2):
                continue
            if best is None or d < best[0] or (d == best[0] and mm > best[2]):
                best = (d, us, mm)
        return best[1] if best else 'error: size'
    return 'error: direction' 
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['US 8', ['8', 'us->mm'], 5.0], ['half size', ['10 1/2', 'us->mm'], 6.5],
  ['tie between 9 and 10', [5.75, 'mm->us'], '10'],
  ['regression: tolerance edge', [7.25, 'mm->us'], 'error: size'],
  ['repair check: tolerance edge', [9.5, 'mm->us'], '15'], ['generated control 1', [11, 'us->mm'], 8.0],
  ['generated control 2', [3.3, 'mm->us'], '3'], ['generated control 3', [7.0, 'uk'], 'error: direction']],
 [['half size', ['10 1/2', 'us->mm'], 6.5], ['tie between 9 and 10', [5.75, 'mm->us'], '10'],
  ['edge of tolerance', [1.5, 'mm->us'], '0'],
  ['regression: tolerance edge', [10.6, 'mm->us'], 'error: size'],
  ['generated control 1', [11, 'us->mm'], 8.0], ['generated control 2', ['10.5', 'us->mm'], 6.5],
  ['generated control 3', [10.6, 'uk'], 'error: direction'],
  ['generated control 4', ['12', 'us->mm'], 'error: size']],
 [['tie between 9 and 10', [5.75, 'mm->us'], '10'], ['edge of tolerance', [1.5, 'mm->us'], '0'],
  ['no match', [11.0, 'mm->us'], 'error: size'], ['repair check: tolerance edge', [7.0, 'mm->us'], '10.5'],
  ['generated control 1', ['12', 'us->mm'], 'error: size'],
  ['generated control 2', ['10 1/2', 'us->mm'], 6.5], ['generated control 3', [3.625, 'mm->us'], '5'],
  ['generated control 4', [1.5, 'uk'], 'error: direction']],
 [['edge of tolerance', [1.5, 'mm->us'], '0'], ['no match', [11.0, 'mm->us'], 'error: size'],
  ['US 8', ['8', 'us->mm'], 5.0], ['regression: tolerance edge', [10.6, 'mm->us'], 'error: size'],
  ['repair check: tolerance edge', [7.0, 'mm->us'], '10.5'],
  ['generated control 1', [6.25, 'mm->us'], '10.5'], ['generated control 2', ['12', 'us->mm'], 'error: size'],
  ['generated control 3', [3.625, 'mm->us'], '5']],
 [['no match', [11.0, 'mm->us'], 'error: size'], ['US 8', ['8', 'us->mm'], 5.0],
  ['half size', ['10 1/2', 'us->mm'], 6.5], ['regression: tolerance edge', [10.6, 'mm->us'], 'error: size'],
  ['repair check: tolerance edge', [9.5, 'mm->us'], '15'],
  ['generated control 1', [5.75, 'uk'], 'error: direction'], ['generated control 2', ['15', 'us->mm'], 10.0],
  ['generated control 3', [10.6, 'uk'], 'error: direction']]]
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
US 85.05.0Passed
half size6.56.5Passed
tie between 9 and 101010Passed
regression: tolerance edgeerror: sizeerror: sizePassed
repair check: tolerance edge1515Passed
generated control 18.08.0Passed
generated control 233Passed
generated control 3error: directionerror: directionPassed

SHA-256 / 61d065402ca35ae1cf53a731c805c143ff38b548833b149339dcea0f658ad37f

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:35.134893+00:00.

Case digest / 5ed4e8d285764c344a09baa6e2057271a37b3ffcc8f01e79fc183e3e7754fac6