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.
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| US 8 | 5.0 | 5.0 | Passed |
| half size | 6.5 | 6.5 | Passed |
| tie between 9 and 10 | 10 | 10 | Passed |
| regression: tolerance edge | 11 | error: size | Failed |
| repair check: tolerance edge | 15 | 15 | Passed |
| generated control 1 | 8.0 | 8.0 | Passed |
| generated control 2 | 3 | 3 | Passed |
| generated control 3 | error: direction | error: direction | Passed |
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| US 8 | 5.0 | 5.0 | Passed |
| half size | 6.5 | 6.5 | Passed |
| tie between 9 and 10 | 10 | 10 | Passed |
| regression: tolerance edge | error: size | error: size | Passed |
| repair check: tolerance edge | error: size | 15 | Failed |
| generated control 1 | 8.0 | 8.0 | Passed |
| generated control 2 | 3 | 3 | Passed |
| generated control 3 | error: direction | error: direction | Passed |
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| US 8 | 5.0 | 5.0 | Passed |
| half size | 6.5 | 6.5 | Passed |
| tie between 9 and 10 | 10 | 10 | Passed |
| regression: tolerance edge | error: size | error: size | Passed |
| repair check: tolerance edge | 15 | 15 | Passed |
| generated control 1 | 8.0 | 8.0 | Passed |
| generated control 2 | 3 | 3 | Passed |
| generated control 3 | error: direction | error: direction | Passed |
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