FA-8896 / Selection controls / Open access
Two-thumb range-slider constraints: The high thumb violates minimum thumb separation · case 01
The high thumb violates minimum thumb separation.
ROOT CAUSE
The high separation operation uses `low` where the contract requires `low+gap`.
VERIFIED REPAIR
Implement the high separation operation as `low+gap`.
Unsuccessful approach: Subtracting the gap allows the high thumb below the low thumb.
Case contract
Thumbs clamp to domain and maintain minimum separation; translating preserves span and clamps delta against both domain edges.
Why this case matters
A deterministic model of two-thumb range-slider constraints; this isolates one interface invariant without requiring a browser.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(low, high, target, value, minimum, maximum, gap):
if target == 'low': low = max(minimum, min(value, high-gap))
elif target == 'high': high = min(maximum, max(value, low))
elif target == 'translate':
delta = max(minimum-low, min(value, maximum-high))
low += delta; high += delta
return (low, high)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('low minimum', solve(20, 60, 'low', -10, 0, 100, 10), (0, 60))
check('low gap', solve(20, 60, 'low', 65, 0, 100, 10), (50, 60))
check('high maximum', solve(20, 60, 'high', 120, 0, 100, 10), (20, 100))
check('high gap', solve(20, 60, 'high', 15, 0, 100, 10), (20, 30))
check('translate upper', solve(20, 60, 'translate', 80, 0, 100, 10), (60, 100))
check('translate lower', solve(20, 60, 'translate', -40, 0, 100, 10), (0, 40))
check('ordinary', solve(20, 60, 'low', 30, 0, 100, 10), (30, 60))
check('parameterized range translation', solve(2*N,6*N,'translate',N,0,10*N,N), (3*N,7*N))
for repetition in range(N):
check('repeat ordinary', solve(20, 60, 'low', 30, 0, 100, 10), (30, 60))
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 |
|---|---|---|---|
| low minimum | [0, 60] | [0, 60] | Passed |
| low gap | [50, 60] | [50, 60] | Passed |
| high maximum | [20, 100] | [20, 100] | Passed |
| high gap | [20, 20] | [20, 30] | Failed |
| translate upper | [60, 100] | [60, 100] | Passed |
| translate lower | [0, 40] | [0, 40] | Passed |
| ordinary | [30, 60] | [30, 60] | Passed |
| parameterized range translation | [3, 7] | [3, 7] | Passed |
| repeat ordinary | [30, 60] | [30, 60] | Passed |
SHA-256 / 5a9bbe5b8563cbefcf41875ba8351e09c5b05fc68df0b311c3cc26612d8db1a5
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(low, high, target, value, minimum, maximum, gap):
if target == 'low': low = max(minimum, min(value, high-gap))
elif target == 'high': high = min(maximum, max(value, low-gap))
elif target == 'translate':
delta = max(minimum-low, min(value, maximum-high))
low += delta; high += delta
return (low, high)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('low minimum', solve(20, 60, 'low', -10, 0, 100, 10), (0, 60))
check('low gap', solve(20, 60, 'low', 65, 0, 100, 10), (50, 60))
check('high maximum', solve(20, 60, 'high', 120, 0, 100, 10), (20, 100))
check('high gap', solve(20, 60, 'high', 15, 0, 100, 10), (20, 30))
check('translate upper', solve(20, 60, 'translate', 80, 0, 100, 10), (60, 100))
check('translate lower', solve(20, 60, 'translate', -40, 0, 100, 10), (0, 40))
check('ordinary', solve(20, 60, 'low', 30, 0, 100, 10), (30, 60))
check('parameterized range translation', solve(2*N,6*N,'translate',N,0,10*N,N), (3*N,7*N))
for repetition in range(N):
check('repeat ordinary', solve(20, 60, 'low', 30, 0, 100, 10), (30, 60))
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 |
|---|---|---|---|
| low minimum | [0, 60] | [0, 60] | Passed |
| low gap | [50, 60] | [50, 60] | Passed |
| high maximum | [20, 100] | [20, 100] | Passed |
| high gap | [20, 15] | [20, 30] | Failed |
| translate upper | [60, 100] | [60, 100] | Passed |
| translate lower | [0, 40] | [0, 40] | Passed |
| ordinary | [30, 60] | [30, 60] | Passed |
| parameterized range translation | [3, 7] | [3, 7] | Passed |
| repeat ordinary | [30, 60] | [30, 60] | Passed |
SHA-256 / 2bbbdebed76a8e0fa838556b0704e01b1ce7796db6d1e95917930487dcbc2afb
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(low, high, target, value, minimum, maximum, gap):
if target == 'low': low = max(minimum, min(value, high-gap))
elif target == 'high': high = min(maximum, max(value, low+gap))
elif target == 'translate':
delta = max(minimum-low, min(value, maximum-high))
low += delta; high += delta
return (low, high)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('low minimum', solve(20, 60, 'low', -10, 0, 100, 10), (0, 60))
check('low gap', solve(20, 60, 'low', 65, 0, 100, 10), (50, 60))
check('high maximum', solve(20, 60, 'high', 120, 0, 100, 10), (20, 100))
check('high gap', solve(20, 60, 'high', 15, 0, 100, 10), (20, 30))
check('translate upper', solve(20, 60, 'translate', 80, 0, 100, 10), (60, 100))
check('translate lower', solve(20, 60, 'translate', -40, 0, 100, 10), (0, 40))
check('ordinary', solve(20, 60, 'low', 30, 0, 100, 10), (30, 60))
check('parameterized range translation', solve(2*N,6*N,'translate',N,0,10*N,N), (3*N,7*N))
for repetition in range(N):
check('repeat ordinary', solve(20, 60, 'low', 30, 0, 100, 10), (30, 60))
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 |
|---|---|---|---|
| low minimum | [0, 60] | [0, 60] | Passed |
| low gap | [50, 60] | [50, 60] | Passed |
| high maximum | [20, 100] | [20, 100] | Passed |
| high gap | [20, 30] | [20, 30] | Passed |
| translate upper | [60, 100] | [60, 100] | Passed |
| translate lower | [0, 40] | [0, 40] | Passed |
| ordinary | [30, 60] | [30, 60] | Passed |
| parameterized range translation | [3, 7] | [3, 7] | Passed |
| repeat ordinary | [30, 60] | [30, 60] | Passed |
SHA-256 / c5bcab482e6424907206e6ec681d206c66b535482629e5f2619ebb054c6c6d72
Verification & scope
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:38:25.376216+00:00.
Case digest / 512fffa818bb72a678fb0f0143bfbf22ac5eb25639249c2fa9c27b36ccf558bd