FAILURE MAP
← Case archive

FA-7911 / Text editing / Open access

Text selection replacement: Backward selections start replacement at the anchor · case 01

Backward selections start replacement at the anchor.

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

ROOT CAUSE

The backward start operation uses `anchor` where the contract requires `min(anchor, focus)`.

VERIFIED REPAIR

Implement the backward start operation as `min(anchor, focus)`.

Unsuccessful approach: Using the upper endpoint discards the selection direction normalization.

Case contract

Composition is preserved; replace the normalized half-open selection and collapse both endpoints immediately after inserted text.

Why this case matters

A deterministic model of text selection replacement; 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(text, anchor, focus, replacement, composing):
    if composing: return (text, anchor, focus)
    lo = anchor
    hi = max(anchor, focus)
    result = text[:lo] + replacement + text[hi:]
    caret = lo + len(replacement)
    return (result, caret, caret)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('composition', solve('abcdef', 1, 4, 'XY', True), ('abcdef', 1, 4))
check('forward', solve('abcdef', 1, 4, 'XY', False), ('aXYef', 3, 3))
check('backward', solve('abcdef', 4, 1, 'XY', False), ('aXYef', 3, 3))
check('insertion', solve('ab', 1, 1, 'XYZ', False), ('aXYZb', 4, 4))
check('delete', solve('abc', 0, 3, '', False), ('', 0, 0))
check('no selection', solve('abc', 2, 2, '', False), ('abc', 2, 2))
check('parameterized selected length', solve('a'*N, 0, N, 'X', False), ('X', 1, 1))
for repetition in range(N):
    check('repeat no selection', solve('abc', 2, 2, '', False), ('abc', 2, 2))
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
composition['abcdef', 1, 4]['abcdef', 1, 4]Passed
forward['aXYef', 3, 3]['aXYef', 3, 3]Passed
backward['abcdXYef', 6, 6]['aXYef', 3, 3]Failed
insertion['aXYZb', 4, 4]['aXYZb', 4, 4]Passed
delete['', 0, 0]['', 0, 0]Passed
no selection['abc', 2, 2]['abc', 2, 2]Passed
parameterized selected length['X', 1, 1]['X', 1, 1]Passed
repeat no selection['abc', 2, 2]['abc', 2, 2]Passed

SHA-256 / ccc1689ab8bc23b91b62a15cd4df140c1c2c3debba9c0225db31a081510d677f

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(text, anchor, focus, replacement, composing):
    if composing: return (text, anchor, focus)
    lo = max(anchor, focus)
    hi = max(anchor, focus)
    result = text[:lo] + replacement + text[hi:]
    caret = lo + len(replacement)
    return (result, caret, caret)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('composition', solve('abcdef', 1, 4, 'XY', True), ('abcdef', 1, 4))
check('forward', solve('abcdef', 1, 4, 'XY', False), ('aXYef', 3, 3))
check('backward', solve('abcdef', 4, 1, 'XY', False), ('aXYef', 3, 3))
check('insertion', solve('ab', 1, 1, 'XYZ', False), ('aXYZb', 4, 4))
check('delete', solve('abc', 0, 3, '', False), ('', 0, 0))
check('no selection', solve('abc', 2, 2, '', False), ('abc', 2, 2))
check('parameterized selected length', solve('a'*N, 0, N, 'X', False), ('X', 1, 1))
for repetition in range(N):
    check('repeat no selection', solve('abc', 2, 2, '', False), ('abc', 2, 2))
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
composition['abcdef', 1, 4]['abcdef', 1, 4]Passed
forward['abcdXYef', 6, 6]['aXYef', 3, 3]Failed
backward['abcdXYef', 6, 6]['aXYef', 3, 3]Failed
insertion['aXYZb', 4, 4]['aXYZb', 4, 4]Passed
delete['abc', 3, 3]['', 0, 0]Failed
no selection['abc', 2, 2]['abc', 2, 2]Passed
parameterized selected length['aX', 2, 2]['X', 1, 1]Failed
repeat no selection['abc', 2, 2]['abc', 2, 2]Passed

SHA-256 / f8bb19297456c52fc070eb78ac7702cc105241140472403288d1d87a28368cad

3 / The verified repair

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

N = 1
observations = []
def solve(text, anchor, focus, replacement, composing):
    if composing: return (text, anchor, focus)
    lo = min(anchor, focus)
    hi = max(anchor, focus)
    result = text[:lo] + replacement + text[hi:]
    caret = lo + len(replacement)
    return (result, caret, caret)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('composition', solve('abcdef', 1, 4, 'XY', True), ('abcdef', 1, 4))
check('forward', solve('abcdef', 1, 4, 'XY', False), ('aXYef', 3, 3))
check('backward', solve('abcdef', 4, 1, 'XY', False), ('aXYef', 3, 3))
check('insertion', solve('ab', 1, 1, 'XYZ', False), ('aXYZb', 4, 4))
check('delete', solve('abc', 0, 3, '', False), ('', 0, 0))
check('no selection', solve('abc', 2, 2, '', False), ('abc', 2, 2))
check('parameterized selected length', solve('a'*N, 0, N, 'X', False), ('X', 1, 1))
for repetition in range(N):
    check('repeat no selection', solve('abc', 2, 2, '', False), ('abc', 2, 2))
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
composition['abcdef', 1, 4]['abcdef', 1, 4]Passed
forward['aXYef', 3, 3]['aXYef', 3, 3]Passed
backward['aXYef', 3, 3]['aXYef', 3, 3]Passed
insertion['aXYZb', 4, 4]['aXYZb', 4, 4]Passed
delete['', 0, 0]['', 0, 0]Passed
no selection['abc', 2, 2]['abc', 2, 2]Passed
parameterized selected length['X', 1, 1]['X', 1, 1]Passed
repeat no selection['abc', 2, 2]['abc', 2, 2]Passed

SHA-256 / fc2f2c1a50e0138b1115cb5974ca3f32bfb6e374e5c68d2b170eef373d133908

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

Case digest / bbb864ecf781b518100f56105a7e8ed2d52f722898292862111bf885acfc63e6