FAILURE MAP
← Case archive

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

Circle skirt drafter: hem circumference radius · case 01

Hem circumference ignores the waist hole.

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

ROOT CAUSE

The hem radius is taken as the skirt length alone.

VERIFIED REPAIR

Hem radius = waist radius + length.

Unsuccessful approach: Using the cut radius shrinks the finished hem.

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] * 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: hem circumference radius', [60, 'quarter', 2, 1.5, 55, 2], [39.5, 38.0, 148.4, 95.0]],
  ['repair check: hem circumference radius', [74.5, 'half', 1, 1.5, 70, 2], [24.0, 22.5, 295.4, 189.1]],
  ['generated control 1', [66, 'full', 0, 1.5, 40, 2], [10.5, 9.0, 317.3, 102.0]],
  ['generated control 2', [92, 'quarter', 2, 1.5, 55, 3], [59.8, 58.3, 180.4, 116.3]],
  ['generated control 3', [80, 'half', 1, 1.5, 55, 2], [25.8, 24.3, 253.8, 162.6]]],
 [['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: hem circumference radius', [92, 'quarter', 2, 1, 40, 3], [59.8, 58.8, 156.8, 101.8]],
  ['repair check: hem circumference radius', [92, 'quarter', 0, 1, 40, 2], [58.6, 57.6, 154.8, 99.6]],
  ['generated control 1', [70, 'half', 1, 1, 55, 2], [22.6, 21.6, 243.8, 157.2]],
  ['generated control 2', [80, 'gored', 2, 1.5, 70, 2], 'error: kind'],
  ['generated control 3', [70, 'full', 2, 1.5, 55, 2], [11.5, 10.0, 417.6, 133.9]]],
 [['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: hem circumference radius', [70, 'full', 1, 1.5, 70, 3], [11.3, 9.8, 510.8, 165.6]],
  ['repair check: hem circumference radius', [60, 'half', 0, 1, 70, 2], [19.1, 18.1, 279.9, 180.2]],
  ['generated control 1', [92, 'gored', 1, 1.5, 40, 2], 'error: kind'],
  ['generated control 2', [60, 'gored', 0, 1, 70, 2], 'error: kind'],
  ['generated control 3', [80, 'full', 1, 1.5, 55, 2], [12.9, 11.4, 426.6, 136.8]]],
 [['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: hem circumference radius', [74.5, 'half', 0, 1, 70, 2], [23.7, 22.7, 294.4, 189.4]],
  ['repair check: hem circumference radius', [80, 'half', 0, 1, 70, 3], [25.5, 24.5, 299.9, 194.9]],
  ['generated control 1', [66, 'gored', 1, 1, 55, 3], 'error: kind'],
  ['generated control 2', [60, 'full', 1, 1.5, 40, 3], [9.7, 8.2, 312.3, 102.4]],
  ['generated control 3', [66, 'gored', 1, 1, 40, 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: hem circumference radius', [74.5, 'full', 2, 1.5, 40, 3], [12.2, 10.7, 327.8, 107.4]],
  ['repair check: hem circumference radius', [92, 'quarter', 1, 1, 40, 2], [59.2, 58.2, 155.8, 100.2]],
  ['generated control 1', [70, 'gored', 1, 1.5, 70, 3], 'error: kind'],
  ['generated control 2', [70, 'half', 2, 1, 55, 2], [22.9, 21.9, 244.8, 157.8]],
  ['generated control 3', [74.5, 'full', 1, 1.5, 55, 2], [12.0, 10.5, 421.1, 135.0]]]]
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, 345.6, 133.9][11.5, 10.0, 417.6, 133.9]Failed
half circle[21.0, 20.0, 125.7, 126.0][21.0, 20.0, 191.7, 126.0]Failed
quarter[51.6, 50.1, 110.0, 122.1][51.6, 50.1, 191.0, 122.1]Failed
regression: hem circumference radius[39.5, 38.0, 86.4, 95.0][39.5, 38.0, 148.4, 95.0]Failed
repair check: hem circumference radius[24.0, 22.5, 219.9, 189.1][24.0, 22.5, 295.4, 189.1]Failed
generated control 1[10.5, 9.0, 251.3, 102.0][10.5, 9.0, 317.3, 102.0]Failed
generated control 2[59.8, 58.3, 86.4, 116.3][59.8, 58.3, 180.4, 116.3]Failed
generated control 3[25.8, 24.3, 172.8, 162.6][25.8, 24.3, 253.8, 162.6]Failed

SHA-256 / b992b8cb1e67bcc6f0cc6517c8e119f2d37716ef81f45b1fac5f9969d20ef9b0

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] * (cut_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: hem circumference radius', [60, 'quarter', 2, 1.5, 55, 2], [39.5, 38.0, 148.4, 95.0]],
  ['repair check: hem circumference radius', [74.5, 'half', 1, 1.5, 70, 2], [24.0, 22.5, 295.4, 189.1]],
  ['generated control 1', [66, 'full', 0, 1.5, 40, 2], [10.5, 9.0, 317.3, 102.0]],
  ['generated control 2', [92, 'quarter', 2, 1.5, 55, 3], [59.8, 58.3, 180.4, 116.3]],
  ['generated control 3', [80, 'half', 1, 1.5, 55, 2], [25.8, 24.3, 253.8, 162.6]]],
 [['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: hem circumference radius', [92, 'quarter', 2, 1, 40, 3], [59.8, 58.8, 156.8, 101.8]],
  ['repair check: hem circumference radius', [92, 'quarter', 0, 1, 40, 2], [58.6, 57.6, 154.8, 99.6]],
  ['generated control 1', [70, 'half', 1, 1, 55, 2], [22.6, 21.6, 243.8, 157.2]],
  ['generated control 2', [80, 'gored', 2, 1.5, 70, 2], 'error: kind'],
  ['generated control 3', [70, 'full', 2, 1.5, 55, 2], [11.5, 10.0, 417.6, 133.9]]],
 [['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: hem circumference radius', [70, 'full', 1, 1.5, 70, 3], [11.3, 9.8, 510.8, 165.6]],
  ['repair check: hem circumference radius', [60, 'half', 0, 1, 70, 2], [19.1, 18.1, 279.9, 180.2]],
  ['generated control 1', [92, 'gored', 1, 1.5, 40, 2], 'error: kind'],
  ['generated control 2', [60, 'gored', 0, 1, 70, 2], 'error: kind'],
  ['generated control 3', [80, 'full', 1, 1.5, 55, 2], [12.9, 11.4, 426.6, 136.8]]],
 [['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: hem circumference radius', [74.5, 'half', 0, 1, 70, 2], [23.7, 22.7, 294.4, 189.4]],
  ['repair check: hem circumference radius', [80, 'half', 0, 1, 70, 3], [25.5, 24.5, 299.9, 194.9]],
  ['generated control 1', [66, 'gored', 1, 1, 55, 3], 'error: kind'],
  ['generated control 2', [60, 'full', 1, 1.5, 40, 3], [9.7, 8.2, 312.3, 102.4]],
  ['generated control 3', [66, 'gored', 1, 1, 40, 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: hem circumference radius', [74.5, 'full', 2, 1.5, 40, 3], [12.2, 10.7, 327.8, 107.4]],
  ['repair check: hem circumference radius', [92, 'quarter', 1, 1, 40, 2], [59.2, 58.2, 155.8, 100.2]],
  ['generated control 1', [70, 'gored', 1, 1.5, 70, 3], 'error: kind'],
  ['generated control 2', [70, 'half', 2, 1, 55, 2], [22.9, 21.9, 244.8, 157.8]],
  ['generated control 3', [74.5, 'full', 1, 1.5, 55, 2], [12.0, 10.5, 421.1, 135.0]]]]
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, 408.2, 133.9][11.5, 10.0, 417.6, 133.9]Failed
half circle[21.0, 20.0, 188.5, 126.0][21.0, 20.0, 191.7, 126.0]Failed
quarter[51.6, 50.1, 188.6, 122.1][51.6, 50.1, 191.0, 122.1]Failed
regression: hem circumference radius[39.5, 38.0, 146.0, 95.0][39.5, 38.0, 148.4, 95.0]Failed
repair check: hem circumference radius[24.0, 22.5, 290.7, 189.1][24.0, 22.5, 295.4, 189.1]Failed
generated control 1[10.5, 9.0, 307.9, 102.0][10.5, 9.0, 317.3, 102.0]Failed
generated control 2[59.8, 58.3, 178.0, 116.3][59.8, 58.3, 180.4, 116.3]Failed
generated control 3[25.8, 24.3, 249.1, 162.6][25.8, 24.3, 253.8, 162.6]Failed

SHA-256 / 31a0830e2b68ab00820a612783c61d9cadb53c77afe992c4a663301b0dd74f37

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: hem circumference radius', [60, 'quarter', 2, 1.5, 55, 2], [39.5, 38.0, 148.4, 95.0]],
  ['repair check: hem circumference radius', [74.5, 'half', 1, 1.5, 70, 2], [24.0, 22.5, 295.4, 189.1]],
  ['generated control 1', [66, 'full', 0, 1.5, 40, 2], [10.5, 9.0, 317.3, 102.0]],
  ['generated control 2', [92, 'quarter', 2, 1.5, 55, 3], [59.8, 58.3, 180.4, 116.3]],
  ['generated control 3', [80, 'half', 1, 1.5, 55, 2], [25.8, 24.3, 253.8, 162.6]]],
 [['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: hem circumference radius', [92, 'quarter', 2, 1, 40, 3], [59.8, 58.8, 156.8, 101.8]],
  ['repair check: hem circumference radius', [92, 'quarter', 0, 1, 40, 2], [58.6, 57.6, 154.8, 99.6]],
  ['generated control 1', [70, 'half', 1, 1, 55, 2], [22.6, 21.6, 243.8, 157.2]],
  ['generated control 2', [80, 'gored', 2, 1.5, 70, 2], 'error: kind'],
  ['generated control 3', [70, 'full', 2, 1.5, 55, 2], [11.5, 10.0, 417.6, 133.9]]],
 [['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: hem circumference radius', [70, 'full', 1, 1.5, 70, 3], [11.3, 9.8, 510.8, 165.6]],
  ['repair check: hem circumference radius', [60, 'half', 0, 1, 70, 2], [19.1, 18.1, 279.9, 180.2]],
  ['generated control 1', [92, 'gored', 1, 1.5, 40, 2], 'error: kind'],
  ['generated control 2', [60, 'gored', 0, 1, 70, 2], 'error: kind'],
  ['generated control 3', [80, 'full', 1, 1.5, 55, 2], [12.9, 11.4, 426.6, 136.8]]],
 [['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: hem circumference radius', [74.5, 'half', 0, 1, 70, 2], [23.7, 22.7, 294.4, 189.4]],
  ['repair check: hem circumference radius', [80, 'half', 0, 1, 70, 3], [25.5, 24.5, 299.9, 194.9]],
  ['generated control 1', [66, 'gored', 1, 1, 55, 3], 'error: kind'],
  ['generated control 2', [60, 'full', 1, 1.5, 40, 3], [9.7, 8.2, 312.3, 102.4]],
  ['generated control 3', [66, 'gored', 1, 1, 40, 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: hem circumference radius', [74.5, 'full', 2, 1.5, 40, 3], [12.2, 10.7, 327.8, 107.4]],
  ['repair check: hem circumference radius', [92, 'quarter', 1, 1, 40, 2], [59.2, 58.2, 155.8, 100.2]],
  ['generated control 1', [70, 'gored', 1, 1.5, 70, 3], 'error: kind'],
  ['generated control 2', [70, 'half', 2, 1, 55, 2], [22.9, 21.9, 244.8, 157.8]],
  ['generated control 3', [74.5, 'full', 1, 1.5, 55, 2], [12.0, 10.5, 421.1, 135.0]]]]
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: hem circumference radius[39.5, 38.0, 148.4, 95.0][39.5, 38.0, 148.4, 95.0]Passed
repair check: hem circumference radius[24.0, 22.5, 295.4, 189.1][24.0, 22.5, 295.4, 189.1]Passed
generated control 1[10.5, 9.0, 317.3, 102.0][10.5, 9.0, 317.3, 102.0]Passed
generated control 2[59.8, 58.3, 180.4, 116.3][59.8, 58.3, 180.4, 116.3]Passed
generated control 3[25.8, 24.3, 253.8, 162.6][25.8, 24.3, 253.8, 162.6]Passed

SHA-256 / 95be89a3083cf594e920136e73b0b7fabc01e6d700a08e482c325e667d3e57e9

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

Case digest / b8150aa2638aff5ba799f077dff57ab715fdfd6acc8de9f60e23c26bc30cea86