FA-97811 / Knitting and sewing pattern grading / Open access
Circle skirt drafter: ease application · case 01
The waistband has no wearing ease.
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| 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 1 | error: kind | error: kind | Passed |
| generated control 2 | error: kind | error: kind | Passed |
| generated control 3 | error: kind | error: kind | Passed |
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| 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 1 | error: kind | error: kind | Passed |
| generated control 2 | error: kind | error: kind | Passed |
| generated control 3 | error: kind | error: kind | Passed |
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| 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 1 | error: kind | error: kind | Passed |
| generated control 2 | error: kind | error: kind | Passed |
| generated control 3 | error: kind | error: kind | Passed |
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