FAILURE MAP
← Case archive

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

Circle skirt drafter: fabric span hem · case 01

The fabric width check ignores the hem allowance and the skirt cannot be cut in one piece.

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

ROOT CAUSE

Span omits the hem allowance on both sides.

VERIFIED REPAIR

Include the hem allowance on both sides of the span.

Unsuccessful approach: Adding a single hem covers only one side.

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 + 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) 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: fabric span hem', [70, 'full', 0, 1, 70, 3], [11.1, 10.1, 509.8, 166.3]],
  ['repair check: fabric span hem', [92, 'full', 2, 1.5, 70, 3], [15.0, 13.5, 533.8, 172.9]],
  ['generated control 1', [66, 'quarter', 1, 1, 70, 2], [42.7, 41.7, 177.0, 113.7]],
  ['generated control 2', [74.5, 'gored', 1, 1.5, 40, 2], 'error: kind'],
  ['generated control 3', [92, 'full', 2, 1, 70, 2], [15.0, 14.0, 533.8, 171.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]],
  ['gored rejected', [70, 'gored', 0, 1, 50, 2], 'error: kind'],
  ['regression: fabric span hem', [60, 'half', 0, 1, 40, 3], [19.1, 18.1, 185.7, 122.2]],
  ['repair check: fabric span hem', [80, 'half', 0, 1, 55, 2], [25.5, 24.5, 252.8, 162.9]],
  ['generated control 1', [60, 'gored', 1, 1.5, 40, 2], 'error: kind'],
  ['generated control 2', [74.5, 'gored', 0, 1, 70, 3], 'error: kind'],
  ['generated control 3', [60, 'quarter', 1, 1, 70, 3], [38.8, 37.8, 171.0, 110.8]]],
 [['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: fabric span hem', [92, 'full', 1, 1, 70, 2], [14.8, 13.8, 532.8, 171.6]],
  ['repair check: fabric span hem', [66, 'half', 1, 1.5, 55, 2], [21.3, 19.8, 239.8, 153.7]],
  ['generated control 1', [66, 'gored', 1, 1, 70, 3], 'error: kind'],
  ['generated control 2', [92, 'quarter', 2, 1, 40, 2], [59.8, 58.8, 156.8, 100.8]],
  ['generated control 3', [70, 'gored', 0, 1.5, 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: fabric span hem', [74.5, 'half', 1, 1.5, 55, 2], [24.0, 22.5, 248.3, 159.1]],
  ['repair check: fabric span hem', [70, 'full', 0, 1, 55, 2], [11.1, 10.1, 415.6, 134.3]],
  ['generated control 1', [80, 'quarter', 1, 1, 40, 2], [51.6, 50.6, 143.8, 92.6]],
  ['generated control 2', [80, 'gored', 0, 1, 70, 2], 'error: kind'],
  ['generated control 3', [80, 'gored', 0, 1, 55, 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]],
  ['quarter', [80, 'quarter', 1, 1.5, 70, 2], [51.6, 50.1, 191.0, 122.1]],
  ['regression: fabric span hem', [70, 'half', 0, 1, 55, 3], [22.3, 21.3, 242.8, 158.6]],
  ['repair check: fabric span hem', [60, 'half', 1, 1.5, 40, 3], [19.4, 17.9, 186.7, 121.8]],
  ['generated control 1', [60, 'gored', 1, 1, 40, 3], 'error: kind'],
  ['generated control 2', [70, 'full', 0, 1.5, 40, 2], [11.1, 9.6, 321.3, 103.3]],
  ['generated control 3', [60, 'full', 2, 1.5, 55, 2], [9.9, 8.4, 407.6, 130.7]]]]
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, 129.9][11.5, 10.0, 417.6, 133.9]Failed
half circle[21.0, 20.0, 191.7, 120.0][21.0, 20.0, 191.7, 126.0]Failed
quarter[51.6, 50.1, 191.0, 122.1][51.6, 50.1, 191.0, 122.1]Passed
regression: fabric span hem[11.1, 10.1, 509.8, 160.3][11.1, 10.1, 509.8, 166.3]Failed
repair check: fabric span hem[15.0, 13.5, 533.8, 166.9][15.0, 13.5, 533.8, 172.9]Failed
generated control 1[42.7, 41.7, 177.0, 113.7][42.7, 41.7, 177.0, 113.7]Passed
generated control 2error: kinderror: kindPassed
generated control 3[15.0, 14.0, 533.8, 167.9][15.0, 14.0, 533.8, 171.9]Failed

SHA-256 / 594101319452d61ddac1caee0d4138f107b0547527625c521d77c3f0d1f04544

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
    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: fabric span hem', [70, 'full', 0, 1, 70, 3], [11.1, 10.1, 509.8, 166.3]],
  ['repair check: fabric span hem', [92, 'full', 2, 1.5, 70, 3], [15.0, 13.5, 533.8, 172.9]],
  ['generated control 1', [66, 'quarter', 1, 1, 70, 2], [42.7, 41.7, 177.0, 113.7]],
  ['generated control 2', [74.5, 'gored', 1, 1.5, 40, 2], 'error: kind'],
  ['generated control 3', [92, 'full', 2, 1, 70, 2], [15.0, 14.0, 533.8, 171.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]],
  ['gored rejected', [70, 'gored', 0, 1, 50, 2], 'error: kind'],
  ['regression: fabric span hem', [60, 'half', 0, 1, 40, 3], [19.1, 18.1, 185.7, 122.2]],
  ['repair check: fabric span hem', [80, 'half', 0, 1, 55, 2], [25.5, 24.5, 252.8, 162.9]],
  ['generated control 1', [60, 'gored', 1, 1.5, 40, 2], 'error: kind'],
  ['generated control 2', [74.5, 'gored', 0, 1, 70, 3], 'error: kind'],
  ['generated control 3', [60, 'quarter', 1, 1, 70, 3], [38.8, 37.8, 171.0, 110.8]]],
 [['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: fabric span hem', [92, 'full', 1, 1, 70, 2], [14.8, 13.8, 532.8, 171.6]],
  ['repair check: fabric span hem', [66, 'half', 1, 1.5, 55, 2], [21.3, 19.8, 239.8, 153.7]],
  ['generated control 1', [66, 'gored', 1, 1, 70, 3], 'error: kind'],
  ['generated control 2', [92, 'quarter', 2, 1, 40, 2], [59.8, 58.8, 156.8, 100.8]],
  ['generated control 3', [70, 'gored', 0, 1.5, 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: fabric span hem', [74.5, 'half', 1, 1.5, 55, 2], [24.0, 22.5, 248.3, 159.1]],
  ['repair check: fabric span hem', [70, 'full', 0, 1, 55, 2], [11.1, 10.1, 415.6, 134.3]],
  ['generated control 1', [80, 'quarter', 1, 1, 40, 2], [51.6, 50.6, 143.8, 92.6]],
  ['generated control 2', [80, 'gored', 0, 1, 70, 2], 'error: kind'],
  ['generated control 3', [80, 'gored', 0, 1, 55, 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]],
  ['quarter', [80, 'quarter', 1, 1.5, 70, 2], [51.6, 50.1, 191.0, 122.1]],
  ['regression: fabric span hem', [70, 'half', 0, 1, 55, 3], [22.3, 21.3, 242.8, 158.6]],
  ['repair check: fabric span hem', [60, 'half', 1, 1.5, 40, 3], [19.4, 17.9, 186.7, 121.8]],
  ['generated control 1', [60, 'gored', 1, 1, 40, 3], 'error: kind'],
  ['generated control 2', [70, 'full', 0, 1.5, 40, 2], [11.1, 9.6, 321.3, 103.3]],
  ['generated control 3', [60, 'full', 2, 1.5, 55, 2], [9.9, 8.4, 407.6, 130.7]]]]
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, 131.9][11.5, 10.0, 417.6, 133.9]Failed
half circle[21.0, 20.0, 191.7, 123.0][21.0, 20.0, 191.7, 126.0]Failed
quarter[51.6, 50.1, 191.0, 122.1][51.6, 50.1, 191.0, 122.1]Passed
regression: fabric span hem[11.1, 10.1, 509.8, 163.3][11.1, 10.1, 509.8, 166.3]Failed
repair check: fabric span hem[15.0, 13.5, 533.8, 169.9][15.0, 13.5, 533.8, 172.9]Failed
generated control 1[42.7, 41.7, 177.0, 113.7][42.7, 41.7, 177.0, 113.7]Passed
generated control 2error: kinderror: kindPassed
generated control 3[15.0, 14.0, 533.8, 169.9][15.0, 14.0, 533.8, 171.9]Failed

SHA-256 / b43d980aa56c805a86df6e8d61cb6bcaf37a6675a4b34384223a513f70ae851a

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: fabric span hem', [70, 'full', 0, 1, 70, 3], [11.1, 10.1, 509.8, 166.3]],
  ['repair check: fabric span hem', [92, 'full', 2, 1.5, 70, 3], [15.0, 13.5, 533.8, 172.9]],
  ['generated control 1', [66, 'quarter', 1, 1, 70, 2], [42.7, 41.7, 177.0, 113.7]],
  ['generated control 2', [74.5, 'gored', 1, 1.5, 40, 2], 'error: kind'],
  ['generated control 3', [92, 'full', 2, 1, 70, 2], [15.0, 14.0, 533.8, 171.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]],
  ['gored rejected', [70, 'gored', 0, 1, 50, 2], 'error: kind'],
  ['regression: fabric span hem', [60, 'half', 0, 1, 40, 3], [19.1, 18.1, 185.7, 122.2]],
  ['repair check: fabric span hem', [80, 'half', 0, 1, 55, 2], [25.5, 24.5, 252.8, 162.9]],
  ['generated control 1', [60, 'gored', 1, 1.5, 40, 2], 'error: kind'],
  ['generated control 2', [74.5, 'gored', 0, 1, 70, 3], 'error: kind'],
  ['generated control 3', [60, 'quarter', 1, 1, 70, 3], [38.8, 37.8, 171.0, 110.8]]],
 [['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: fabric span hem', [92, 'full', 1, 1, 70, 2], [14.8, 13.8, 532.8, 171.6]],
  ['repair check: fabric span hem', [66, 'half', 1, 1.5, 55, 2], [21.3, 19.8, 239.8, 153.7]],
  ['generated control 1', [66, 'gored', 1, 1, 70, 3], 'error: kind'],
  ['generated control 2', [92, 'quarter', 2, 1, 40, 2], [59.8, 58.8, 156.8, 100.8]],
  ['generated control 3', [70, 'gored', 0, 1.5, 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: fabric span hem', [74.5, 'half', 1, 1.5, 55, 2], [24.0, 22.5, 248.3, 159.1]],
  ['repair check: fabric span hem', [70, 'full', 0, 1, 55, 2], [11.1, 10.1, 415.6, 134.3]],
  ['generated control 1', [80, 'quarter', 1, 1, 40, 2], [51.6, 50.6, 143.8, 92.6]],
  ['generated control 2', [80, 'gored', 0, 1, 70, 2], 'error: kind'],
  ['generated control 3', [80, 'gored', 0, 1, 55, 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]],
  ['quarter', [80, 'quarter', 1, 1.5, 70, 2], [51.6, 50.1, 191.0, 122.1]],
  ['regression: fabric span hem', [70, 'half', 0, 1, 55, 3], [22.3, 21.3, 242.8, 158.6]],
  ['repair check: fabric span hem', [60, 'half', 1, 1.5, 40, 3], [19.4, 17.9, 186.7, 121.8]],
  ['generated control 1', [60, 'gored', 1, 1, 40, 3], 'error: kind'],
  ['generated control 2', [70, 'full', 0, 1.5, 40, 2], [11.1, 9.6, 321.3, 103.3]],
  ['generated control 3', [60, 'full', 2, 1.5, 55, 2], [9.9, 8.4, 407.6, 130.7]]]]
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: fabric span hem[11.1, 10.1, 509.8, 166.3][11.1, 10.1, 509.8, 166.3]Passed
repair check: fabric span hem[15.0, 13.5, 533.8, 172.9][15.0, 13.5, 533.8, 172.9]Passed
generated control 1[42.7, 41.7, 177.0, 113.7][42.7, 41.7, 177.0, 113.7]Passed
generated control 2error: kinderror: kindPassed
generated control 3[15.0, 14.0, 533.8, 171.9][15.0, 14.0, 533.8, 171.9]Passed

SHA-256 / 3c1f64887b1101d16a96f5c88dd9c956aa7b380a1f3cacf1d3a9a879281c921c

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

Case digest / bed6dcd2aaeeb4ca5914a79ef56a12d41ebc7fb4359a6d0da1d358e0e37af170