FAILURE MAP
← Case archive

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

Circle skirt drafter: cut radius · case 01

The skirt waist is two seam allowances too big.

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

ROOT CAUSE

The seam allowance enlarges the waist hole instead of shrinking it.

VERIFIED REPAIR

Subtract one seam allowance from the waist radius.

Unsuccessful approach: Subtracting two allowances makes the waist too small.

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 + 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: cut radius', [60, 'quarter', 2, 1, 70, 3], [39.5, 38.5, 172.0, 111.5]],
  ['repair check: cut radius', [74.5, 'full', 2, 1.5, 40, 2], [12.2, 10.7, 327.8, 105.4]],
  ['generated control 1', [60, 'full', 1, 1.5, 70, 3], [9.7, 8.2, 500.8, 162.4]],
  ['generated control 2', [92, 'full', 1, 1, 70, 2], [14.8, 13.8, 532.8, 171.6]],
  ['generated control 3', [74.5, 'quarter', 2, 1.5, 55, 3], [48.7, 47.2, 162.9, 105.2]]],
 [['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: cut radius', [80, 'quarter', 1, 1, 55, 3], [51.6, 50.6, 167.4, 108.6]],
  ['repair check: cut radius', [60, 'quarter', 2, 1, 40, 3], [39.5, 38.5, 124.8, 81.5]],
  ['generated control 1', [92, 'gored', 1, 1, 55, 3], 'error: kind'],
  ['generated control 2', [66, 'gored', 0, 1, 55, 3], 'error: kind'],
  ['generated control 3', [92, 'full', 0, 1, 40, 2], [14.6, 13.6, 343.3, 111.3]]],
 [['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: cut radius', [66, 'half', 2, 1.5, 55, 2], [21.6, 20.1, 240.8, 154.3]],
  ['repair check: cut radius', [66, 'quarter', 0, 1.5, 55, 2], [42.0, 40.5, 152.4, 97.5]],
  ['generated control 1', [66, 'gored', 0, 1.5, 55, 3], 'error: kind'],
  ['generated control 2', [66, 'gored', 1, 1, 55, 3], 'error: kind'],
  ['generated control 3', [92, 'full', 1, 1.5, 55, 2], [14.8, 13.3, 438.6, 140.6]]],
 [['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: cut radius', [80, 'quarter', 1, 1, 40, 3], [51.6, 50.6, 143.8, 93.6]],
  ['repair check: cut radius', [92, 'quarter', 0, 1, 70, 2], [58.6, 57.6, 202.0, 129.6]],
  ['generated control 1', [92, 'half', 0, 1, 40, 3], [29.3, 28.3, 217.7, 142.6]],
  ['generated control 2', [92, 'full', 0, 1, 70, 3], [14.6, 13.6, 531.8, 173.3]],
  ['generated control 3', [66, 'quarter', 0, 1, 70, 2], [42.0, 41.0, 176.0, 113.0]]],
 [['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: cut radius', [92, 'quarter', 0, 1.5, 55, 3], [58.6, 57.1, 178.4, 115.1]],
  ['repair check: cut radius', [74.5, 'quarter', 1, 1.5, 55, 3], [48.1, 46.6, 161.9, 104.6]],
  ['generated control 1', [66, 'quarter', 1, 1, 70, 3], [42.7, 41.7, 177.0, 114.7]],
  ['generated control 2', [66, 'quarter', 0, 1, 40, 3], [42.0, 41.0, 128.8, 84.0]],
  ['generated control 3', [80, 'gored', 0, 1, 70, 2], 'error: kind']]]
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, 13.0, 417.6, 139.9][11.5, 10.0, 417.6, 133.9]Failed
half circle[21.0, 22.0, 191.7, 130.0][21.0, 20.0, 191.7, 126.0]Failed
quarter[51.6, 53.1, 191.0, 125.1][51.6, 50.1, 191.0, 122.1]Failed
regression: cut radius[39.5, 40.5, 172.0, 113.5][39.5, 38.5, 172.0, 111.5]Failed
repair check: cut radius[12.2, 13.7, 327.8, 111.4][12.2, 10.7, 327.8, 105.4]Failed
generated control 1[9.7, 11.2, 500.8, 168.4][9.7, 8.2, 500.8, 162.4]Failed
generated control 2[14.8, 15.8, 532.8, 175.6][14.8, 13.8, 532.8, 171.6]Failed
generated control 3[48.7, 50.2, 162.9, 108.2][48.7, 47.2, 162.9, 105.2]Failed

SHA-256 / 1440629da6c449a732f73fa3769e0dc1ff8a05e48fb7073e316d60fc08eecaa5

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 - 2 * 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: cut radius', [60, 'quarter', 2, 1, 70, 3], [39.5, 38.5, 172.0, 111.5]],
  ['repair check: cut radius', [74.5, 'full', 2, 1.5, 40, 2], [12.2, 10.7, 327.8, 105.4]],
  ['generated control 1', [60, 'full', 1, 1.5, 70, 3], [9.7, 8.2, 500.8, 162.4]],
  ['generated control 2', [92, 'full', 1, 1, 70, 2], [14.8, 13.8, 532.8, 171.6]],
  ['generated control 3', [74.5, 'quarter', 2, 1.5, 55, 3], [48.7, 47.2, 162.9, 105.2]]],
 [['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: cut radius', [80, 'quarter', 1, 1, 55, 3], [51.6, 50.6, 167.4, 108.6]],
  ['repair check: cut radius', [60, 'quarter', 2, 1, 40, 3], [39.5, 38.5, 124.8, 81.5]],
  ['generated control 1', [92, 'gored', 1, 1, 55, 3], 'error: kind'],
  ['generated control 2', [66, 'gored', 0, 1, 55, 3], 'error: kind'],
  ['generated control 3', [92, 'full', 0, 1, 40, 2], [14.6, 13.6, 343.3, 111.3]]],
 [['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: cut radius', [66, 'half', 2, 1.5, 55, 2], [21.6, 20.1, 240.8, 154.3]],
  ['repair check: cut radius', [66, 'quarter', 0, 1.5, 55, 2], [42.0, 40.5, 152.4, 97.5]],
  ['generated control 1', [66, 'gored', 0, 1.5, 55, 3], 'error: kind'],
  ['generated control 2', [66, 'gored', 1, 1, 55, 3], 'error: kind'],
  ['generated control 3', [92, 'full', 1, 1.5, 55, 2], [14.8, 13.3, 438.6, 140.6]]],
 [['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: cut radius', [80, 'quarter', 1, 1, 40, 3], [51.6, 50.6, 143.8, 93.6]],
  ['repair check: cut radius', [92, 'quarter', 0, 1, 70, 2], [58.6, 57.6, 202.0, 129.6]],
  ['generated control 1', [92, 'half', 0, 1, 40, 3], [29.3, 28.3, 217.7, 142.6]],
  ['generated control 2', [92, 'full', 0, 1, 70, 3], [14.6, 13.6, 531.8, 173.3]],
  ['generated control 3', [66, 'quarter', 0, 1, 70, 2], [42.0, 41.0, 176.0, 113.0]]],
 [['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: cut radius', [92, 'quarter', 0, 1.5, 55, 3], [58.6, 57.1, 178.4, 115.1]],
  ['repair check: cut radius', [74.5, 'quarter', 1, 1.5, 55, 3], [48.1, 46.6, 161.9, 104.6]],
  ['generated control 1', [66, 'quarter', 1, 1, 70, 3], [42.7, 41.7, 177.0, 114.7]],
  ['generated control 2', [66, 'quarter', 0, 1, 40, 3], [42.0, 41.0, 128.8, 84.0]],
  ['generated control 3', [80, 'gored', 0, 1, 70, 2], 'error: kind']]]
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, 8.5, 417.6, 130.9][11.5, 10.0, 417.6, 133.9]Failed
half circle[21.0, 19.0, 191.7, 124.0][21.0, 20.0, 191.7, 126.0]Failed
quarter[51.6, 48.6, 191.0, 120.6][51.6, 50.1, 191.0, 122.1]Failed
regression: cut radius[39.5, 37.5, 172.0, 110.5][39.5, 38.5, 172.0, 111.5]Failed
repair check: cut radius[12.2, 9.2, 327.8, 102.4][12.2, 10.7, 327.8, 105.4]Failed
generated control 1[9.7, 6.7, 500.8, 159.4][9.7, 8.2, 500.8, 162.4]Failed
generated control 2[14.8, 12.8, 532.8, 169.6][14.8, 13.8, 532.8, 171.6]Failed
generated control 3[48.7, 45.7, 162.9, 103.7][48.7, 47.2, 162.9, 105.2]Failed

SHA-256 / 3c67febc352135f033bcbd88f19aca8a30bad8db9ac8964375516311e271619d

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: cut radius', [60, 'quarter', 2, 1, 70, 3], [39.5, 38.5, 172.0, 111.5]],
  ['repair check: cut radius', [74.5, 'full', 2, 1.5, 40, 2], [12.2, 10.7, 327.8, 105.4]],
  ['generated control 1', [60, 'full', 1, 1.5, 70, 3], [9.7, 8.2, 500.8, 162.4]],
  ['generated control 2', [92, 'full', 1, 1, 70, 2], [14.8, 13.8, 532.8, 171.6]],
  ['generated control 3', [74.5, 'quarter', 2, 1.5, 55, 3], [48.7, 47.2, 162.9, 105.2]]],
 [['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: cut radius', [80, 'quarter', 1, 1, 55, 3], [51.6, 50.6, 167.4, 108.6]],
  ['repair check: cut radius', [60, 'quarter', 2, 1, 40, 3], [39.5, 38.5, 124.8, 81.5]],
  ['generated control 1', [92, 'gored', 1, 1, 55, 3], 'error: kind'],
  ['generated control 2', [66, 'gored', 0, 1, 55, 3], 'error: kind'],
  ['generated control 3', [92, 'full', 0, 1, 40, 2], [14.6, 13.6, 343.3, 111.3]]],
 [['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: cut radius', [66, 'half', 2, 1.5, 55, 2], [21.6, 20.1, 240.8, 154.3]],
  ['repair check: cut radius', [66, 'quarter', 0, 1.5, 55, 2], [42.0, 40.5, 152.4, 97.5]],
  ['generated control 1', [66, 'gored', 0, 1.5, 55, 3], 'error: kind'],
  ['generated control 2', [66, 'gored', 1, 1, 55, 3], 'error: kind'],
  ['generated control 3', [92, 'full', 1, 1.5, 55, 2], [14.8, 13.3, 438.6, 140.6]]],
 [['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: cut radius', [80, 'quarter', 1, 1, 40, 3], [51.6, 50.6, 143.8, 93.6]],
  ['repair check: cut radius', [92, 'quarter', 0, 1, 70, 2], [58.6, 57.6, 202.0, 129.6]],
  ['generated control 1', [92, 'half', 0, 1, 40, 3], [29.3, 28.3, 217.7, 142.6]],
  ['generated control 2', [92, 'full', 0, 1, 70, 3], [14.6, 13.6, 531.8, 173.3]],
  ['generated control 3', [66, 'quarter', 0, 1, 70, 2], [42.0, 41.0, 176.0, 113.0]]],
 [['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: cut radius', [92, 'quarter', 0, 1.5, 55, 3], [58.6, 57.1, 178.4, 115.1]],
  ['repair check: cut radius', [74.5, 'quarter', 1, 1.5, 55, 3], [48.1, 46.6, 161.9, 104.6]],
  ['generated control 1', [66, 'quarter', 1, 1, 70, 3], [42.7, 41.7, 177.0, 114.7]],
  ['generated control 2', [66, 'quarter', 0, 1, 40, 3], [42.0, 41.0, 128.8, 84.0]],
  ['generated control 3', [80, 'gored', 0, 1, 70, 2], 'error: kind']]]
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: cut radius[39.5, 38.5, 172.0, 111.5][39.5, 38.5, 172.0, 111.5]Passed
repair check: cut radius[12.2, 10.7, 327.8, 105.4][12.2, 10.7, 327.8, 105.4]Passed
generated control 1[9.7, 8.2, 500.8, 162.4][9.7, 8.2, 500.8, 162.4]Passed
generated control 2[14.8, 13.8, 532.8, 171.6][14.8, 13.8, 532.8, 171.6]Passed
generated control 3[48.7, 47.2, 162.9, 105.2][48.7, 47.2, 162.9, 105.2]Passed

SHA-256 / 3a48069c61df081c214544057ee2a794bea140d4c39cbb367ef48c6e3a4f9fe2

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

Case digest / 59914cd53bf0b2bc04f2da706719e4795511ed72d6b58af5f496792f49bc8edd