FAILURE MAP
← Case archive

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

Circle skirt drafter: ease application · case 01

The waistband has no wearing ease.

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

ROOT CAUSE

Ease is not added to the waist measurement.

VERIFIED REPAIR

Add ease before computing the radius.

Unsuccessful approach: Half the ease leaves the waist tight.

Case contract

kind full/half/quarter covers fraction 1, 1/2, 1/4 of a circle (else "error: kind"). Waist radius r = (waist+ease)/(2*pi*fraction); cut radius = r - sa (seam extends into the waist hole). Hem circumference = 2*pi*fraction*(r + length). Fabric span needed = 2*(cut_r + length + hem) for full and half, (cut_r + length + hem) for quarter. Return floats rounded to 1 decimal: [r, cut_r, hem_circumference, span].

Why this case matters

Circle skirt drafting converts waist size into a radius and checks the fabric width needed.

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(waist, kind, ease, sa, length, hem):
    FR = {'full': 1, 'half': 0.5, 'quarter': 0.25}
    if kind not in FR:
        return 'error: kind'
    W = waist
    r = W / (2 * math.pi * FR[kind])
    cut_r = r - sa
    hem_c = 2 * math.pi * FR[kind] * (r + length)
    span = 2 * (cut_r + length + hem) if kind != 'quarter' else cut_r + length + hem
    return [round(r, 1), round(cut_r, 1), round(hem_c, 1), round(span, 1)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['full circle', [70, 'full', 2, 1.5, 55, 2], [11.5, 10.0, 417.6, 133.9]],
  ['half circle', [66, 'half', 0, 1, 40, 3], [21.0, 20.0, 191.7, 126.0]],
  ['quarter', [80, 'quarter', 1, 1.5, 70, 2], [51.6, 50.1, 191.0, 122.1]],
  ['regression: ease application', [74.5, 'half', 2, 1.5, 55, 3], [24.4, 22.9, 249.3, 161.7]],
  ['repair check: ease application', [60, 'full', 1, 1.5, 55, 2], [9.7, 8.2, 406.6, 130.4]],
  ['generated control 1', [74.5, 'gored', 1, 1, 70, 2], 'error: kind'],
  ['generated control 2', [70, 'gored', 2, 1, 55, 2], 'error: kind'],
  ['generated control 3', [66, 'gored', 0, 1, 55, 2], 'error: kind']],
 [['half circle', [66, 'half', 0, 1, 40, 3], [21.0, 20.0, 191.7, 126.0]],
  ['quarter', [80, 'quarter', 1, 1.5, 70, 2], [51.6, 50.1, 191.0, 122.1]],
  ['gored rejected', [70, 'gored', 0, 1, 50, 2], 'error: kind'],
  ['regression: ease application', [92, 'quarter', 1, 1, 55, 2], [59.2, 58.2, 179.4, 115.2]],
  ['repair check: ease application', [80, 'full', 1, 1, 70, 2], [12.9, 11.9, 520.8, 167.8]],
  ['generated control 1', [66, 'gored', 1, 1, 55, 3], 'error: kind'],
  ['generated control 2', [92, 'gored', 0, 1.5, 55, 3], 'error: kind'],
  ['generated control 3', [92, 'gored', 2, 1.5, 55, 2], 'error: kind']],
 [['quarter', [80, 'quarter', 1, 1.5, 70, 2], [51.6, 50.1, 191.0, 122.1]],
  ['gored rejected', [70, 'gored', 0, 1, 50, 2], 'error: kind'],
  ['full circle', [70, 'full', 2, 1.5, 55, 2], [11.5, 10.0, 417.6, 133.9]],
  ['regression: ease application', [80, 'half', 1, 1, 70, 3], [25.8, 24.8, 300.9, 195.6]],
  ['repair check: ease application', [70, 'half', 2, 1, 55, 3], [22.9, 21.9, 244.8, 159.8]],
  ['generated control 1', [70, 'quarter', 0, 1.5, 55, 3], [44.6, 43.1, 156.4, 101.1]],
  ['generated control 2', [66, 'gored', 0, 1.5, 55, 2], 'error: kind'],
  ['generated control 3', [74.5, 'gored', 0, 1, 40, 2], 'error: kind']],
 [['gored rejected', [70, 'gored', 0, 1, 50, 2], 'error: kind'],
  ['full circle', [70, 'full', 2, 1.5, 55, 2], [11.5, 10.0, 417.6, 133.9]],
  ['half circle', [66, 'half', 0, 1, 40, 3], [21.0, 20.0, 191.7, 126.0]],
  ['regression: ease application', [92, 'full', 1, 1.5, 40, 3], [14.8, 13.3, 344.3, 112.6]],
  ['repair check: ease application', [80, 'half', 2, 1, 40, 3], [26.1, 25.1, 207.7, 136.2]],
  ['generated control 1', [70, 'gored', 0, 1, 40, 2], 'error: kind'],
  ['generated control 2', [70, 'gored', 2, 1, 40, 2], 'error: kind'],
  ['generated control 3', [60, 'quarter', 1, 1.5, 40, 3], [38.8, 37.3, 123.8, 80.3]]],
 [['full circle', [70, 'full', 2, 1.5, 55, 2], [11.5, 10.0, 417.6, 133.9]],
  ['half circle', [66, 'half', 0, 1, 40, 3], [21.0, 20.0, 191.7, 126.0]],
  ['quarter', [80, 'quarter', 1, 1.5, 70, 2], [51.6, 50.1, 191.0, 122.1]],
  ['regression: ease application', [74.5, 'full', 2, 1, 40, 3], [12.2, 11.2, 327.8, 108.4]],
  ['repair check: ease application', [70, 'quarter', 1, 1, 70, 3], [45.2, 44.2, 181.0, 117.2]],
  ['generated control 1', [92, 'gored', 0, 1, 70, 2], 'error: kind'],
  ['generated control 2', [66, 'full', 2, 1.5, 55, 3], [10.8, 9.3, 413.6, 134.6]],
  ['generated control 3', [92, 'full', 1, 1, 70, 3], [14.8, 13.8, 532.8, 173.6]]]]
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
full circle[11.1, 9.6, 415.6, 133.3][11.5, 10.0, 417.6, 133.9]Failed
half circle[21.0, 20.0, 191.7, 126.0][21.0, 20.0, 191.7, 126.0]Passed
quarter[50.9, 49.4, 190.0, 121.4][51.6, 50.1, 191.0, 122.1]Failed
regression: ease application[23.7, 22.2, 247.3, 160.4][24.4, 22.9, 249.3, 161.7]Failed
repair check: ease application[9.5, 8.0, 405.6, 130.1][9.7, 8.2, 406.6, 130.4]Failed
generated control 1error: kinderror: kindPassed
generated control 2error: kinderror: kindPassed
generated control 3error: kinderror: kindPassed

SHA-256 / 23177fedacf2859a2cde4b8e3fab88c1114d86dfd97a6d0b3b53453e301e3e09

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(waist, kind, ease, sa, length, hem):
    FR = {'full': 1, 'half': 0.5, 'quarter': 0.25}
    if kind not in FR:
        return 'error: kind'
    W = waist + ease / 2
    r = W / (2 * math.pi * FR[kind])
    cut_r = r - sa
    hem_c = 2 * math.pi * FR[kind] * (r + length)
    span = 2 * (cut_r + length + hem) if kind != 'quarter' else cut_r + length + hem
    return [round(r, 1), round(cut_r, 1), round(hem_c, 1), round(span, 1)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['full circle', [70, 'full', 2, 1.5, 55, 2], [11.5, 10.0, 417.6, 133.9]],
  ['half circle', [66, 'half', 0, 1, 40, 3], [21.0, 20.0, 191.7, 126.0]],
  ['quarter', [80, 'quarter', 1, 1.5, 70, 2], [51.6, 50.1, 191.0, 122.1]],
  ['regression: ease application', [74.5, 'half', 2, 1.5, 55, 3], [24.4, 22.9, 249.3, 161.7]],
  ['repair check: ease application', [60, 'full', 1, 1.5, 55, 2], [9.7, 8.2, 406.6, 130.4]],
  ['generated control 1', [74.5, 'gored', 1, 1, 70, 2], 'error: kind'],
  ['generated control 2', [70, 'gored', 2, 1, 55, 2], 'error: kind'],
  ['generated control 3', [66, 'gored', 0, 1, 55, 2], 'error: kind']],
 [['half circle', [66, 'half', 0, 1, 40, 3], [21.0, 20.0, 191.7, 126.0]],
  ['quarter', [80, 'quarter', 1, 1.5, 70, 2], [51.6, 50.1, 191.0, 122.1]],
  ['gored rejected', [70, 'gored', 0, 1, 50, 2], 'error: kind'],
  ['regression: ease application', [92, 'quarter', 1, 1, 55, 2], [59.2, 58.2, 179.4, 115.2]],
  ['repair check: ease application', [80, 'full', 1, 1, 70, 2], [12.9, 11.9, 520.8, 167.8]],
  ['generated control 1', [66, 'gored', 1, 1, 55, 3], 'error: kind'],
  ['generated control 2', [92, 'gored', 0, 1.5, 55, 3], 'error: kind'],
  ['generated control 3', [92, 'gored', 2, 1.5, 55, 2], 'error: kind']],
 [['quarter', [80, 'quarter', 1, 1.5, 70, 2], [51.6, 50.1, 191.0, 122.1]],
  ['gored rejected', [70, 'gored', 0, 1, 50, 2], 'error: kind'],
  ['full circle', [70, 'full', 2, 1.5, 55, 2], [11.5, 10.0, 417.6, 133.9]],
  ['regression: ease application', [80, 'half', 1, 1, 70, 3], [25.8, 24.8, 300.9, 195.6]],
  ['repair check: ease application', [70, 'half', 2, 1, 55, 3], [22.9, 21.9, 244.8, 159.8]],
  ['generated control 1', [70, 'quarter', 0, 1.5, 55, 3], [44.6, 43.1, 156.4, 101.1]],
  ['generated control 2', [66, 'gored', 0, 1.5, 55, 2], 'error: kind'],
  ['generated control 3', [74.5, 'gored', 0, 1, 40, 2], 'error: kind']],
 [['gored rejected', [70, 'gored', 0, 1, 50, 2], 'error: kind'],
  ['full circle', [70, 'full', 2, 1.5, 55, 2], [11.5, 10.0, 417.6, 133.9]],
  ['half circle', [66, 'half', 0, 1, 40, 3], [21.0, 20.0, 191.7, 126.0]],
  ['regression: ease application', [92, 'full', 1, 1.5, 40, 3], [14.8, 13.3, 344.3, 112.6]],
  ['repair check: ease application', [80, 'half', 2, 1, 40, 3], [26.1, 25.1, 207.7, 136.2]],
  ['generated control 1', [70, 'gored', 0, 1, 40, 2], 'error: kind'],
  ['generated control 2', [70, 'gored', 2, 1, 40, 2], 'error: kind'],
  ['generated control 3', [60, 'quarter', 1, 1.5, 40, 3], [38.8, 37.3, 123.8, 80.3]]],
 [['full circle', [70, 'full', 2, 1.5, 55, 2], [11.5, 10.0, 417.6, 133.9]],
  ['half circle', [66, 'half', 0, 1, 40, 3], [21.0, 20.0, 191.7, 126.0]],
  ['quarter', [80, 'quarter', 1, 1.5, 70, 2], [51.6, 50.1, 191.0, 122.1]],
  ['regression: ease application', [74.5, 'full', 2, 1, 40, 3], [12.2, 11.2, 327.8, 108.4]],
  ['repair check: ease application', [70, 'quarter', 1, 1, 70, 3], [45.2, 44.2, 181.0, 117.2]],
  ['generated control 1', [92, 'gored', 0, 1, 70, 2], 'error: kind'],
  ['generated control 2', [66, 'full', 2, 1.5, 55, 3], [10.8, 9.3, 413.6, 134.6]],
  ['generated control 3', [92, 'full', 1, 1, 70, 3], [14.8, 13.8, 532.8, 173.6]]]]
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
full circle[11.3, 9.8, 416.6, 133.6][11.5, 10.0, 417.6, 133.9]Failed
half circle[21.0, 20.0, 191.7, 126.0][21.0, 20.0, 191.7, 126.0]Passed
quarter[51.2, 49.7, 190.5, 121.7][51.6, 50.1, 191.0, 122.1]Failed
regression: ease application[24.0, 22.5, 248.3, 161.1][24.4, 22.9, 249.3, 161.7]Failed
repair check: ease application[9.6, 8.1, 406.1, 130.3][9.7, 8.2, 406.6, 130.4]Failed
generated control 1error: kinderror: kindPassed
generated control 2error: kinderror: kindPassed
generated control 3error: kinderror: kindPassed

SHA-256 / 1d9ae682c345740e11b078b2dc0cba96d0ce18a9a1d17d843879b42f572bb3bb

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(waist, kind, ease, sa, length, hem):
    FR = {'full': 1, 'half': 0.5, 'quarter': 0.25}
    if kind not in FR:
        return 'error: kind'
    W = waist + ease
    r = W / (2 * math.pi * FR[kind])
    cut_r = r - sa
    hem_c = 2 * math.pi * FR[kind] * (r + length)
    span = 2 * (cut_r + length + hem) if kind != 'quarter' else cut_r + length + hem
    return [round(r, 1), round(cut_r, 1), round(hem_c, 1), round(span, 1)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['full circle', [70, 'full', 2, 1.5, 55, 2], [11.5, 10.0, 417.6, 133.9]],
  ['half circle', [66, 'half', 0, 1, 40, 3], [21.0, 20.0, 191.7, 126.0]],
  ['quarter', [80, 'quarter', 1, 1.5, 70, 2], [51.6, 50.1, 191.0, 122.1]],
  ['regression: ease application', [74.5, 'half', 2, 1.5, 55, 3], [24.4, 22.9, 249.3, 161.7]],
  ['repair check: ease application', [60, 'full', 1, 1.5, 55, 2], [9.7, 8.2, 406.6, 130.4]],
  ['generated control 1', [74.5, 'gored', 1, 1, 70, 2], 'error: kind'],
  ['generated control 2', [70, 'gored', 2, 1, 55, 2], 'error: kind'],
  ['generated control 3', [66, 'gored', 0, 1, 55, 2], 'error: kind']],
 [['half circle', [66, 'half', 0, 1, 40, 3], [21.0, 20.0, 191.7, 126.0]],
  ['quarter', [80, 'quarter', 1, 1.5, 70, 2], [51.6, 50.1, 191.0, 122.1]],
  ['gored rejected', [70, 'gored', 0, 1, 50, 2], 'error: kind'],
  ['regression: ease application', [92, 'quarter', 1, 1, 55, 2], [59.2, 58.2, 179.4, 115.2]],
  ['repair check: ease application', [80, 'full', 1, 1, 70, 2], [12.9, 11.9, 520.8, 167.8]],
  ['generated control 1', [66, 'gored', 1, 1, 55, 3], 'error: kind'],
  ['generated control 2', [92, 'gored', 0, 1.5, 55, 3], 'error: kind'],
  ['generated control 3', [92, 'gored', 2, 1.5, 55, 2], 'error: kind']],
 [['quarter', [80, 'quarter', 1, 1.5, 70, 2], [51.6, 50.1, 191.0, 122.1]],
  ['gored rejected', [70, 'gored', 0, 1, 50, 2], 'error: kind'],
  ['full circle', [70, 'full', 2, 1.5, 55, 2], [11.5, 10.0, 417.6, 133.9]],
  ['regression: ease application', [80, 'half', 1, 1, 70, 3], [25.8, 24.8, 300.9, 195.6]],
  ['repair check: ease application', [70, 'half', 2, 1, 55, 3], [22.9, 21.9, 244.8, 159.8]],
  ['generated control 1', [70, 'quarter', 0, 1.5, 55, 3], [44.6, 43.1, 156.4, 101.1]],
  ['generated control 2', [66, 'gored', 0, 1.5, 55, 2], 'error: kind'],
  ['generated control 3', [74.5, 'gored', 0, 1, 40, 2], 'error: kind']],
 [['gored rejected', [70, 'gored', 0, 1, 50, 2], 'error: kind'],
  ['full circle', [70, 'full', 2, 1.5, 55, 2], [11.5, 10.0, 417.6, 133.9]],
  ['half circle', [66, 'half', 0, 1, 40, 3], [21.0, 20.0, 191.7, 126.0]],
  ['regression: ease application', [92, 'full', 1, 1.5, 40, 3], [14.8, 13.3, 344.3, 112.6]],
  ['repair check: ease application', [80, 'half', 2, 1, 40, 3], [26.1, 25.1, 207.7, 136.2]],
  ['generated control 1', [70, 'gored', 0, 1, 40, 2], 'error: kind'],
  ['generated control 2', [70, 'gored', 2, 1, 40, 2], 'error: kind'],
  ['generated control 3', [60, 'quarter', 1, 1.5, 40, 3], [38.8, 37.3, 123.8, 80.3]]],
 [['full circle', [70, 'full', 2, 1.5, 55, 2], [11.5, 10.0, 417.6, 133.9]],
  ['half circle', [66, 'half', 0, 1, 40, 3], [21.0, 20.0, 191.7, 126.0]],
  ['quarter', [80, 'quarter', 1, 1.5, 70, 2], [51.6, 50.1, 191.0, 122.1]],
  ['regression: ease application', [74.5, 'full', 2, 1, 40, 3], [12.2, 11.2, 327.8, 108.4]],
  ['repair check: ease application', [70, 'quarter', 1, 1, 70, 3], [45.2, 44.2, 181.0, 117.2]],
  ['generated control 1', [92, 'gored', 0, 1, 70, 2], 'error: kind'],
  ['generated control 2', [66, 'full', 2, 1.5, 55, 3], [10.8, 9.3, 413.6, 134.6]],
  ['generated control 3', [92, 'full', 1, 1, 70, 3], [14.8, 13.8, 532.8, 173.6]]]]
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
full circle[11.5, 10.0, 417.6, 133.9][11.5, 10.0, 417.6, 133.9]Passed
half circle[21.0, 20.0, 191.7, 126.0][21.0, 20.0, 191.7, 126.0]Passed
quarter[51.6, 50.1, 191.0, 122.1][51.6, 50.1, 191.0, 122.1]Passed
regression: ease application[24.4, 22.9, 249.3, 161.7][24.4, 22.9, 249.3, 161.7]Passed
repair check: ease application[9.7, 8.2, 406.6, 130.4][9.7, 8.2, 406.6, 130.4]Passed
generated control 1error: kinderror: kindPassed
generated control 2error: kinderror: kindPassed
generated control 3error: kinderror: kindPassed

SHA-256 / 92c60ce2e3f80048e3ae6eb3d2ff8670a564454c55a4b980aa2c226bb036ff4c

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

Case digest / a03c76615872fcf4bddfc6951b838a13c3c7099d548259726b40031e25b22c63