FAILURE MAP
← Case archive

FA-80731 / Bidirectional text layout / Open access

Direction-relative alignment: end alignment mapping · case 01

End-aligned RTL text sits on the right.

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

ROOT CAUSE

end always maps to the right edge.

VERIFIED REPAIR

Map end to left for RTL and right for LTR.

Unsuccessful approach: Mapping end like start swaps both directions.

Case contract

Input [line width, content width, align, rtl]. justify (last line) behaves as start. start = left for LTR, right for RTL; end is the opposite. Overflowing centered content aligns to start. center offset is floor(slack/2) for LTR and ceil(slack/2) for RTL. Return the x offset of the content.

Why this case matters

Mixed right-to-left and left-to-right text must resolve levels and visual order exactly, or words, numbers and carets land in the wrong place.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    lw, cw, align, rtl = x
    if align == 'justify':
        align = 'start'
    if align == 'start':
        align = 'right' if rtl else 'left'
    elif align == 'end':
        align = 'right'
    if cw > lw and align == 'center':
        align = 'left' if not rtl else 'right'
    if align == 'left':
        return 0
    if align == 'right':
        return lw - cw
    slack = lw - cw
    return (slack + 1) // 2 if rtl else slack // 2
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('RTL end is left', [20, 5, 'end', True], 0), ('regression: end alignment mapping', [36, 28, 'end', True], 0), ('partial-repair probe', [16, 28, 'end', False], -12), ('partial-repair probe', [21, 46, 'end', False], -25), ('odd slack RTL center', [20, 5, 'center', True], 8), ('overflowing center RTL', [10, 15, 'center', True], -5), ('control layout', [17, 39, 'center', True], -22), ('control layout', [37, 31, 'justify', True], 6)], [('regression: end alignment mapping', [37, 25, 'end', True], 0), ('regression: end alignment mapping', [22, 30, 'end', True], 0), ('regression: end alignment mapping', [11, 26, 'end', True], 0), ('partial-repair probe', [13, 1, 'end', False], 12), ('RTL end is left', [20, 5, 'end', True], 0), ('odd slack RTL center', [20, 5, 'center', True], 8), ('control layout', [23, 3, 'justify', True], 20), ('control layout', [29, 29, 'justify', False], 0)], [('regression: end alignment mapping', [18, 8, 'end', True], 0), ('regression: end alignment mapping', [36, 9, 'end', True], 0), ('partial-repair probe', [38, 19, 'end', False], 19), ('partial-repair probe', [27, 20, 'end', False], 7), ('odd slack RTL center', [20, 5, 'center', True], 8), ('overflowing center RTL', [10, 15, 'center', True], -5), ('control layout', [20, 40, 'start', False], 0), ('control layout', [15, 28, 'center', False], 0)], [('regression: end alignment mapping', [11, 34, 'end', True], 0), ('regression: end alignment mapping', [37, 25, 'end', True], 0), ('regression: end alignment mapping', [21, 8, 'end', True], 0), ('partial-repair probe', [33, 31, 'end', False], 2), ('odd slack RTL center', [20, 5, 'center', True], 8), ('RTL end is left', [20, 5, 'end', True], 0), ('control layout', [35, 16, 'right', True], 19), ('control layout', [21, 20, 'left', False], 0)], [('regression: end alignment mapping', [35, 50, 'end', True], 0), ('regression: end alignment mapping', [20, 7, 'end', True], 0), ('partial-repair probe', [33, 31, 'end', False], 2), ('regression: end alignment mapping', [32, 30, 'end', True], 0), ('RTL end is left', [20, 5, 'end', True], 0), ('odd slack RTL center', [20, 5, 'center', True], 8), ('control layout', [10, 37, 'start', True], -27), ('control layout', [35, 3, 'center', True], 16)]]
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
RTL end is left150Failed
regression: end alignment mapping80Failed
partial-repair probe-12-12Passed
partial-repair probe-25-25Passed
odd slack RTL center88Passed
overflowing center RTL-5-5Passed
control layout-22-22Passed
control layout66Passed

SHA-256 / ff96e32ecbfcb2d65988c5bde1b41ea937903c8059437057708fd9c176b5e27f

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    lw, cw, align, rtl = x
    if align == 'justify':
        align = 'start'
    if align == 'start':
        align = 'right' if rtl else 'left'
    elif align == 'end':
        align = 'right' if rtl else 'left'
    if cw > lw and align == 'center':
        align = 'left' if not rtl else 'right'
    if align == 'left':
        return 0
    if align == 'right':
        return lw - cw
    slack = lw - cw
    return (slack + 1) // 2 if rtl else slack // 2
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('RTL end is left', [20, 5, 'end', True], 0), ('regression: end alignment mapping', [36, 28, 'end', True], 0), ('partial-repair probe', [16, 28, 'end', False], -12), ('partial-repair probe', [21, 46, 'end', False], -25), ('odd slack RTL center', [20, 5, 'center', True], 8), ('overflowing center RTL', [10, 15, 'center', True], -5), ('control layout', [17, 39, 'center', True], -22), ('control layout', [37, 31, 'justify', True], 6)], [('regression: end alignment mapping', [37, 25, 'end', True], 0), ('regression: end alignment mapping', [22, 30, 'end', True], 0), ('regression: end alignment mapping', [11, 26, 'end', True], 0), ('partial-repair probe', [13, 1, 'end', False], 12), ('RTL end is left', [20, 5, 'end', True], 0), ('odd slack RTL center', [20, 5, 'center', True], 8), ('control layout', [23, 3, 'justify', True], 20), ('control layout', [29, 29, 'justify', False], 0)], [('regression: end alignment mapping', [18, 8, 'end', True], 0), ('regression: end alignment mapping', [36, 9, 'end', True], 0), ('partial-repair probe', [38, 19, 'end', False], 19), ('partial-repair probe', [27, 20, 'end', False], 7), ('odd slack RTL center', [20, 5, 'center', True], 8), ('overflowing center RTL', [10, 15, 'center', True], -5), ('control layout', [20, 40, 'start', False], 0), ('control layout', [15, 28, 'center', False], 0)], [('regression: end alignment mapping', [11, 34, 'end', True], 0), ('regression: end alignment mapping', [37, 25, 'end', True], 0), ('regression: end alignment mapping', [21, 8, 'end', True], 0), ('partial-repair probe', [33, 31, 'end', False], 2), ('odd slack RTL center', [20, 5, 'center', True], 8), ('RTL end is left', [20, 5, 'end', True], 0), ('control layout', [35, 16, 'right', True], 19), ('control layout', [21, 20, 'left', False], 0)], [('regression: end alignment mapping', [35, 50, 'end', True], 0), ('regression: end alignment mapping', [20, 7, 'end', True], 0), ('partial-repair probe', [33, 31, 'end', False], 2), ('regression: end alignment mapping', [32, 30, 'end', True], 0), ('RTL end is left', [20, 5, 'end', True], 0), ('odd slack RTL center', [20, 5, 'center', True], 8), ('control layout', [10, 37, 'start', True], -27), ('control layout', [35, 3, 'center', True], 16)]]
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
RTL end is left150Failed
regression: end alignment mapping80Failed
partial-repair probe0-12Failed
partial-repair probe0-25Failed
odd slack RTL center88Passed
overflowing center RTL-5-5Passed
control layout-22-22Passed
control layout66Passed

SHA-256 / 781fe22f55ef85844642ef9b8087db614ac986168e6da1a6fb79ae9ffa533028

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    lw, cw, align, rtl = x
    if align == 'justify':
        align = 'start'
    if align == 'start':
        align = 'right' if rtl else 'left'
    elif align == 'end':
        align = 'left' if rtl else 'right'
    if cw > lw and align == 'center':
        align = 'left' if not rtl else 'right'
    if align == 'left':
        return 0
    if align == 'right':
        return lw - cw
    slack = lw - cw
    return (slack + 1) // 2 if rtl else slack // 2
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('RTL end is left', [20, 5, 'end', True], 0), ('regression: end alignment mapping', [36, 28, 'end', True], 0), ('partial-repair probe', [16, 28, 'end', False], -12), ('partial-repair probe', [21, 46, 'end', False], -25), ('odd slack RTL center', [20, 5, 'center', True], 8), ('overflowing center RTL', [10, 15, 'center', True], -5), ('control layout', [17, 39, 'center', True], -22), ('control layout', [37, 31, 'justify', True], 6)], [('regression: end alignment mapping', [37, 25, 'end', True], 0), ('regression: end alignment mapping', [22, 30, 'end', True], 0), ('regression: end alignment mapping', [11, 26, 'end', True], 0), ('partial-repair probe', [13, 1, 'end', False], 12), ('RTL end is left', [20, 5, 'end', True], 0), ('odd slack RTL center', [20, 5, 'center', True], 8), ('control layout', [23, 3, 'justify', True], 20), ('control layout', [29, 29, 'justify', False], 0)], [('regression: end alignment mapping', [18, 8, 'end', True], 0), ('regression: end alignment mapping', [36, 9, 'end', True], 0), ('partial-repair probe', [38, 19, 'end', False], 19), ('partial-repair probe', [27, 20, 'end', False], 7), ('odd slack RTL center', [20, 5, 'center', True], 8), ('overflowing center RTL', [10, 15, 'center', True], -5), ('control layout', [20, 40, 'start', False], 0), ('control layout', [15, 28, 'center', False], 0)], [('regression: end alignment mapping', [11, 34, 'end', True], 0), ('regression: end alignment mapping', [37, 25, 'end', True], 0), ('regression: end alignment mapping', [21, 8, 'end', True], 0), ('partial-repair probe', [33, 31, 'end', False], 2), ('odd slack RTL center', [20, 5, 'center', True], 8), ('RTL end is left', [20, 5, 'end', True], 0), ('control layout', [35, 16, 'right', True], 19), ('control layout', [21, 20, 'left', False], 0)], [('regression: end alignment mapping', [35, 50, 'end', True], 0), ('regression: end alignment mapping', [20, 7, 'end', True], 0), ('partial-repair probe', [33, 31, 'end', False], 2), ('regression: end alignment mapping', [32, 30, 'end', True], 0), ('RTL end is left', [20, 5, 'end', True], 0), ('odd slack RTL center', [20, 5, 'center', True], 8), ('control layout', [10, 37, 'start', True], -27), ('control layout', [35, 3, 'center', True], 16)]]
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
RTL end is left00Passed
regression: end alignment mapping00Passed
partial-repair probe-12-12Passed
partial-repair probe-25-25Passed
odd slack RTL center88Passed
overflowing center RTL-5-5Passed
control layout-22-22Passed
control layout66Passed

SHA-256 / 36fca3d8eac5fc73e82645e76fbbc701623dbd9950b6ce76c13dc9c84348f3ac

Verification & scope

A deterministic toy bidi model over stipulated class labels and integer levels; it is inspired by, but does not claim conformance to, any published algorithm. 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:49:56.700224+00:00.

Case digest / 713a9a6eb487022fa1e5be2ca0202d47e33b6456212d9f2122c953b23de22a0f