FA-97676 / Knitting and sewing pattern grading / Open access
Sleeve cap ease checker: armhole length · case 01
Every sleeve cap shows about 24 cm of ease.
ROOT CAUSE
Only the front armhole is subtracted.
VERIFIED REPAIR
Subtract front plus back armhole.
Unsuccessful approach: Doubling the front assumes a symmetric armhole, which the back often is not.
Case contract
Ease = cap - (front + back armhole). Allowed ease: woven 2.5-4.5, knit 0-1.5, leather 0-0.5 (inclusive; fabric trimmed, lower-case; other -> "error: fabric"). Verdict "too little", "too much" or "ok". Adjustment per side = (midpoint - ease)/2. Return [ease, verdict, adjust] with floats rounded to 2 decimals.
Why this case matters
Set-in sleeves need a fabric-dependent amount of cap ease to ease into the armhole.
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(cap, front, back, fabric):
R = {'woven': (Fraction(5, 2), Fraction(9, 2)), 'knit': (Fraction(0), Fraction(3, 2)), 'leather': (Fraction(0), Fraction(1, 2))}
f = fabric.strip().lower()
if f not in R:
return 'error: fabric'
lo, hi = R[f]
ease = Fraction(cap) - Fraction(front)
if ease < lo:
verdict = 'too little'
elif ease > hi:
verdict = 'too much'
else:
verdict = 'ok'
adjust = ((lo + hi) / 2 - ease) / 2
return [round(float(ease), 2), verdict, round(float(adjust), 2)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['woven ok', ['50', '23', '24', 'woven'], [3.0, 'ok', 0.25]],
['knit too much', ['52', '24', '24.5', 'knit'], [3.5, 'too much', -1.38]],
['leather at lower bound', ['46', '23', '23', 'leather'], [0.0, 'ok', 0.12]],
['regression: armhole length', ['52', '23.5', '22', 'leather'], [6.5, 'too much', -3.12]],
['repair check: armhole length', ['50.5', '24', '22', 'knit'], [4.5, 'too much', -1.88]],
['generated control 1', ['50.5', '24', '22', 'felt'], 'error: fabric'],
['generated control 2', ['49', '23.5', '24.5', 'Knit '], [1.0, 'ok', -0.12]],
['generated control 3', ['50.5', '22', '22', 'Knit '], [6.5, 'too much', -2.88]]],
[['knit too much', ['52', '24', '24.5', 'knit'], [3.5, 'too much', -1.38]],
['leather at lower bound', ['46', '23', '23', 'leather'], [0.0, 'ok', 0.12]],
['woven lower edge', ['50.5', '24', '24', 'woven'], [2.5, 'ok', 0.5]],
['regression: armhole length', ['52', '23.5', '23', 'knit'], [5.5, 'too much', -2.38]],
['repair check: armhole length', ['52', '23.5', '23', 'Knit '], [5.5, 'too much', -2.38]],
['generated control 1', ['50.5', '22', '23', 'Knit '], [5.5, 'too much', -2.38]],
['generated control 2', ['52', '22', '24.5', 'leather'], [5.5, 'too much', -2.62]],
['generated control 3', ['48', '23.5', '24.5', 'woven'], [0.0, 'too little', 1.75]]],
[['leather at lower bound', ['46', '23', '23', 'leather'], [0.0, 'ok', 0.12]],
['woven lower edge', ['50.5', '24', '24', 'woven'], [2.5, 'ok', 0.5]],
['woven ok', ['50', '23', '24', 'woven'], [3.0, 'ok', 0.25]],
['regression: armhole length', ['46', '23.5', '23', 'woven'], [-0.5, 'too little', 2.0]],
['repair check: armhole length', ['52', '22', '23', 'woven'], [7.0, 'too much', -1.75]],
['generated control 1', ['52', '22', '24.5', 'woven'], [5.5, 'too much', -1.0]],
['generated control 2', ['46', '22', '22', 'woven'], [2.0, 'too little', 0.75]],
['generated control 3', ['49', '24', '24.5', 'leather'], [0.5, 'ok', -0.12]]],
[['woven lower edge', ['50.5', '24', '24', 'woven'], [2.5, 'ok', 0.5]],
['woven ok', ['50', '23', '24', 'woven'], [3.0, 'ok', 0.25]],
['knit too much', ['52', '24', '24.5', 'knit'], [3.5, 'too much', -1.38]],
['regression: armhole length', ['46', '22', '24.5', 'knit'], [-0.5, 'too little', 0.62]],
['repair check: armhole length', ['49', '22', '24.5', 'leather'], [2.5, 'too much', -1.12]],
['generated control 1', ['49', '22', '24.5', 'felt'], 'error: fabric'],
['generated control 2', ['49', '24', '24.5', 'woven'], [0.5, 'too little', 1.5]],
['generated control 3', ['50.5', '22', '22', 'Knit '], [6.5, 'too much', -2.88]]],
[['woven ok', ['50', '23', '24', 'woven'], [3.0, 'ok', 0.25]],
['knit too much', ['52', '24', '24.5', 'knit'], [3.5, 'too much', -1.38]],
['leather at lower bound', ['46', '23', '23', 'leather'], [0.0, 'ok', 0.12]],
['regression: armhole length', ['49', '22', '24.5', 'woven'], [2.5, 'ok', 0.5]],
['repair check: armhole length', ['52', '22', '23', 'knit'], [7.0, 'too much', -3.12]],
['generated control 1', ['46', '22', '22', 'Knit '], [2.0, 'too much', -0.62]],
['generated control 2', ['52', '23.5', '22', 'felt'], 'error: fabric'],
['generated control 3', ['48', '22', '22', 'woven'], [4.0, 'ok', -0.25]]]]
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 |
|---|---|---|---|
| woven ok | [27.0, 'too much', -11.75] | [3.0, 'ok', 0.25] | Failed |
| knit too much | [28.0, 'too much', -13.62] | [3.5, 'too much', -1.38] | Failed |
| leather at lower bound | [23.0, 'too much', -11.38] | [0.0, 'ok', 0.12] | Failed |
| regression: armhole length | [28.5, 'too much', -14.12] | [6.5, 'too much', -3.12] | Failed |
| repair check: armhole length | [26.5, 'too much', -12.88] | [4.5, 'too much', -1.88] | Failed |
| generated control 1 | error: fabric | error: fabric | Passed |
| generated control 2 | [25.5, 'too much', -12.38] | [1.0, 'ok', -0.12] | Failed |
| generated control 3 | [28.5, 'too much', -13.88] | [6.5, 'too much', -2.88] | Failed |
SHA-256 / 8ba9d2c0e2825df9c41550fb367bded00866acc8d00456a4e356e4b57452a73f
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(cap, front, back, fabric):
R = {'woven': (Fraction(5, 2), Fraction(9, 2)), 'knit': (Fraction(0), Fraction(3, 2)), 'leather': (Fraction(0), Fraction(1, 2))}
f = fabric.strip().lower()
if f not in R:
return 'error: fabric'
lo, hi = R[f]
ease = Fraction(cap) - 2 * Fraction(front)
if ease < lo:
verdict = 'too little'
elif ease > hi:
verdict = 'too much'
else:
verdict = 'ok'
adjust = ((lo + hi) / 2 - ease) / 2
return [round(float(ease), 2), verdict, round(float(adjust), 2)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['woven ok', ['50', '23', '24', 'woven'], [3.0, 'ok', 0.25]],
['knit too much', ['52', '24', '24.5', 'knit'], [3.5, 'too much', -1.38]],
['leather at lower bound', ['46', '23', '23', 'leather'], [0.0, 'ok', 0.12]],
['regression: armhole length', ['52', '23.5', '22', 'leather'], [6.5, 'too much', -3.12]],
['repair check: armhole length', ['50.5', '24', '22', 'knit'], [4.5, 'too much', -1.88]],
['generated control 1', ['50.5', '24', '22', 'felt'], 'error: fabric'],
['generated control 2', ['49', '23.5', '24.5', 'Knit '], [1.0, 'ok', -0.12]],
['generated control 3', ['50.5', '22', '22', 'Knit '], [6.5, 'too much', -2.88]]],
[['knit too much', ['52', '24', '24.5', 'knit'], [3.5, 'too much', -1.38]],
['leather at lower bound', ['46', '23', '23', 'leather'], [0.0, 'ok', 0.12]],
['woven lower edge', ['50.5', '24', '24', 'woven'], [2.5, 'ok', 0.5]],
['regression: armhole length', ['52', '23.5', '23', 'knit'], [5.5, 'too much', -2.38]],
['repair check: armhole length', ['52', '23.5', '23', 'Knit '], [5.5, 'too much', -2.38]],
['generated control 1', ['50.5', '22', '23', 'Knit '], [5.5, 'too much', -2.38]],
['generated control 2', ['52', '22', '24.5', 'leather'], [5.5, 'too much', -2.62]],
['generated control 3', ['48', '23.5', '24.5', 'woven'], [0.0, 'too little', 1.75]]],
[['leather at lower bound', ['46', '23', '23', 'leather'], [0.0, 'ok', 0.12]],
['woven lower edge', ['50.5', '24', '24', 'woven'], [2.5, 'ok', 0.5]],
['woven ok', ['50', '23', '24', 'woven'], [3.0, 'ok', 0.25]],
['regression: armhole length', ['46', '23.5', '23', 'woven'], [-0.5, 'too little', 2.0]],
['repair check: armhole length', ['52', '22', '23', 'woven'], [7.0, 'too much', -1.75]],
['generated control 1', ['52', '22', '24.5', 'woven'], [5.5, 'too much', -1.0]],
['generated control 2', ['46', '22', '22', 'woven'], [2.0, 'too little', 0.75]],
['generated control 3', ['49', '24', '24.5', 'leather'], [0.5, 'ok', -0.12]]],
[['woven lower edge', ['50.5', '24', '24', 'woven'], [2.5, 'ok', 0.5]],
['woven ok', ['50', '23', '24', 'woven'], [3.0, 'ok', 0.25]],
['knit too much', ['52', '24', '24.5', 'knit'], [3.5, 'too much', -1.38]],
['regression: armhole length', ['46', '22', '24.5', 'knit'], [-0.5, 'too little', 0.62]],
['repair check: armhole length', ['49', '22', '24.5', 'leather'], [2.5, 'too much', -1.12]],
['generated control 1', ['49', '22', '24.5', 'felt'], 'error: fabric'],
['generated control 2', ['49', '24', '24.5', 'woven'], [0.5, 'too little', 1.5]],
['generated control 3', ['50.5', '22', '22', 'Knit '], [6.5, 'too much', -2.88]]],
[['woven ok', ['50', '23', '24', 'woven'], [3.0, 'ok', 0.25]],
['knit too much', ['52', '24', '24.5', 'knit'], [3.5, 'too much', -1.38]],
['leather at lower bound', ['46', '23', '23', 'leather'], [0.0, 'ok', 0.12]],
['regression: armhole length', ['49', '22', '24.5', 'woven'], [2.5, 'ok', 0.5]],
['repair check: armhole length', ['52', '22', '23', 'knit'], [7.0, 'too much', -3.12]],
['generated control 1', ['46', '22', '22', 'Knit '], [2.0, 'too much', -0.62]],
['generated control 2', ['52', '23.5', '22', 'felt'], 'error: fabric'],
['generated control 3', ['48', '22', '22', 'woven'], [4.0, 'ok', -0.25]]]]
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 |
|---|---|---|---|
| woven ok | [4.0, 'ok', -0.25] | [3.0, 'ok', 0.25] | Failed |
| knit too much | [4.0, 'too much', -1.62] | [3.5, 'too much', -1.38] | Failed |
| leather at lower bound | [0.0, 'ok', 0.12] | [0.0, 'ok', 0.12] | Passed |
| regression: armhole length | [5.0, 'too much', -2.38] | [6.5, 'too much', -3.12] | Failed |
| repair check: armhole length | [2.5, 'too much', -0.88] | [4.5, 'too much', -1.88] | Failed |
| generated control 1 | error: fabric | error: fabric | Passed |
| generated control 2 | [2.0, 'too much', -0.62] | [1.0, 'ok', -0.12] | Failed |
| generated control 3 | [6.5, 'too much', -2.88] | [6.5, 'too much', -2.88] | Passed |
SHA-256 / b1032114594dfe78e7e418d7d47c7b41723326ca78ca185543636d7e79341903
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(cap, front, back, fabric):
R = {'woven': (Fraction(5, 2), Fraction(9, 2)), 'knit': (Fraction(0), Fraction(3, 2)), 'leather': (Fraction(0), Fraction(1, 2))}
f = fabric.strip().lower()
if f not in R:
return 'error: fabric'
lo, hi = R[f]
ease = Fraction(cap) - (Fraction(front) + Fraction(back))
if ease < lo:
verdict = 'too little'
elif ease > hi:
verdict = 'too much'
else:
verdict = 'ok'
adjust = ((lo + hi) / 2 - ease) / 2
return [round(float(ease), 2), verdict, round(float(adjust), 2)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['woven ok', ['50', '23', '24', 'woven'], [3.0, 'ok', 0.25]],
['knit too much', ['52', '24', '24.5', 'knit'], [3.5, 'too much', -1.38]],
['leather at lower bound', ['46', '23', '23', 'leather'], [0.0, 'ok', 0.12]],
['regression: armhole length', ['52', '23.5', '22', 'leather'], [6.5, 'too much', -3.12]],
['repair check: armhole length', ['50.5', '24', '22', 'knit'], [4.5, 'too much', -1.88]],
['generated control 1', ['50.5', '24', '22', 'felt'], 'error: fabric'],
['generated control 2', ['49', '23.5', '24.5', 'Knit '], [1.0, 'ok', -0.12]],
['generated control 3', ['50.5', '22', '22', 'Knit '], [6.5, 'too much', -2.88]]],
[['knit too much', ['52', '24', '24.5', 'knit'], [3.5, 'too much', -1.38]],
['leather at lower bound', ['46', '23', '23', 'leather'], [0.0, 'ok', 0.12]],
['woven lower edge', ['50.5', '24', '24', 'woven'], [2.5, 'ok', 0.5]],
['regression: armhole length', ['52', '23.5', '23', 'knit'], [5.5, 'too much', -2.38]],
['repair check: armhole length', ['52', '23.5', '23', 'Knit '], [5.5, 'too much', -2.38]],
['generated control 1', ['50.5', '22', '23', 'Knit '], [5.5, 'too much', -2.38]],
['generated control 2', ['52', '22', '24.5', 'leather'], [5.5, 'too much', -2.62]],
['generated control 3', ['48', '23.5', '24.5', 'woven'], [0.0, 'too little', 1.75]]],
[['leather at lower bound', ['46', '23', '23', 'leather'], [0.0, 'ok', 0.12]],
['woven lower edge', ['50.5', '24', '24', 'woven'], [2.5, 'ok', 0.5]],
['woven ok', ['50', '23', '24', 'woven'], [3.0, 'ok', 0.25]],
['regression: armhole length', ['46', '23.5', '23', 'woven'], [-0.5, 'too little', 2.0]],
['repair check: armhole length', ['52', '22', '23', 'woven'], [7.0, 'too much', -1.75]],
['generated control 1', ['52', '22', '24.5', 'woven'], [5.5, 'too much', -1.0]],
['generated control 2', ['46', '22', '22', 'woven'], [2.0, 'too little', 0.75]],
['generated control 3', ['49', '24', '24.5', 'leather'], [0.5, 'ok', -0.12]]],
[['woven lower edge', ['50.5', '24', '24', 'woven'], [2.5, 'ok', 0.5]],
['woven ok', ['50', '23', '24', 'woven'], [3.0, 'ok', 0.25]],
['knit too much', ['52', '24', '24.5', 'knit'], [3.5, 'too much', -1.38]],
['regression: armhole length', ['46', '22', '24.5', 'knit'], [-0.5, 'too little', 0.62]],
['repair check: armhole length', ['49', '22', '24.5', 'leather'], [2.5, 'too much', -1.12]],
['generated control 1', ['49', '22', '24.5', 'felt'], 'error: fabric'],
['generated control 2', ['49', '24', '24.5', 'woven'], [0.5, 'too little', 1.5]],
['generated control 3', ['50.5', '22', '22', 'Knit '], [6.5, 'too much', -2.88]]],
[['woven ok', ['50', '23', '24', 'woven'], [3.0, 'ok', 0.25]],
['knit too much', ['52', '24', '24.5', 'knit'], [3.5, 'too much', -1.38]],
['leather at lower bound', ['46', '23', '23', 'leather'], [0.0, 'ok', 0.12]],
['regression: armhole length', ['49', '22', '24.5', 'woven'], [2.5, 'ok', 0.5]],
['repair check: armhole length', ['52', '22', '23', 'knit'], [7.0, 'too much', -3.12]],
['generated control 1', ['46', '22', '22', 'Knit '], [2.0, 'too much', -0.62]],
['generated control 2', ['52', '23.5', '22', 'felt'], 'error: fabric'],
['generated control 3', ['48', '22', '22', 'woven'], [4.0, 'ok', -0.25]]]]
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 |
|---|---|---|---|
| woven ok | [3.0, 'ok', 0.25] | [3.0, 'ok', 0.25] | Passed |
| knit too much | [3.5, 'too much', -1.38] | [3.5, 'too much', -1.38] | Passed |
| leather at lower bound | [0.0, 'ok', 0.12] | [0.0, 'ok', 0.12] | Passed |
| regression: armhole length | [6.5, 'too much', -3.12] | [6.5, 'too much', -3.12] | Passed |
| repair check: armhole length | [4.5, 'too much', -1.88] | [4.5, 'too much', -1.88] | Passed |
| generated control 1 | error: fabric | error: fabric | Passed |
| generated control 2 | [1.0, 'ok', -0.12] | [1.0, 'ok', -0.12] | Passed |
| generated control 3 | [6.5, 'too much', -2.88] | [6.5, 'too much', -2.88] | Passed |
SHA-256 / 9f26548385c3498855c980dd88d3c3adea082acef7295afae67521e613f98112
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:34.457000+00:00.
Case digest / 5d378bc163b99dc88e836f172e9ab95e676ab05a5bd2593f9f4281af68bb2d58