FAILURE MAP
← Case archive

FA-9051 / Undo and history / Open access

Adjacent typing undo coalescing: Coalescing loses the text preceding the first grouped edit · case 01

Coalescing loses the text preceding the first grouped edit.

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

ROOT CAUSE

The original before operation uses `(before, after)` where the contract requires `(history[-1][0], after)`.

VERIFIED REPAIR

Implement the original before operation as `(history[-1][0], after)`.

Unsuccessful approach: Keeping the old after-state omits the latest insertion.

Case contract

Only contiguous insertion edits without explicit boundary coalesce; preserve the first before-state and newest after-state; no-op input creates no history.

Why this case matters

A deterministic model of adjacent typing undo coalescing; 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(history, before, after, previous_kind, kind, previous_caret, caret, boundary):
    history = list(history)
    if before == after: return history
    merge = bool(history) and kind == 'insert' and previous_kind == kind and previous_caret == caret and not boundary
    if merge: history[-1] = (before, after)
    else: history.append((before, after))
    return history
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('noop', solve([('a','ab')], 'ab', 'ab', 'insert', 'insert', 2, 2, False), [('a', 'ab')])
check('empty noop', solve([], 'a', 'a', None, 'insert', None, 1, False), [])
check('delete', solve([('abcd','abc')], 'abc', 'ab', 'delete', 'delete', 3, 3, False), [('abcd', 'abc'), ('abc', 'ab')])
check('contiguous', solve([('a','ab')], 'ab', 'abc', 'insert', 'insert', 2, 2, False), [('a', 'abc')])
check('moved caret', solve([('a','ab')], 'ab', 'axb', 'insert', 'insert', 2, 1, False), [('a', 'ab'), ('ab', 'axb')])
check('boundary', solve([('a','ab')], 'ab', 'abc', 'insert', 'insert', 2, 2, True), [('a', 'ab'), ('ab', 'abc')])
check('empty', solve([], '', 'a', None, 'insert', None, 0, False), [('', 'a')])
check('parameterized inserted length', solve([], '', 'a'*N, None, 'insert', None, 0, False), [('', 'a'*N)])
for repetition in range(N):
    check('repeat empty', solve([], '', 'a', None, 'insert', None, 0, False), [('', 'a')])
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
noop[['a', 'ab']][['a', 'ab']]Passed
empty noop[][]Passed
delete[['abcd', 'abc'], ['abc', 'ab']][['abcd', 'abc'], ['abc', 'ab']]Passed
contiguous[['ab', 'abc']][['a', 'abc']]Failed
moved caret[['a', 'ab'], ['ab', 'axb']][['a', 'ab'], ['ab', 'axb']]Passed
boundary[['a', 'ab'], ['ab', 'abc']][['a', 'ab'], ['ab', 'abc']]Passed
empty[['', 'a']][['', 'a']]Passed
parameterized inserted length[['', 'a']][['', 'a']]Passed
repeat empty[['', 'a']][['', 'a']]Passed

SHA-256 / 45ce617353e50e4e31cd78e85e1221319f17b06e7622668f7ef8b8b98210f054

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(history, before, after, previous_kind, kind, previous_caret, caret, boundary):
    history = list(history)
    if before == after: return history
    merge = bool(history) and kind == 'insert' and previous_kind == kind and previous_caret == caret and not boundary
    if merge: history[-1] = (history[-1][0], history[-1][1])
    else: history.append((before, after))
    return history
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('noop', solve([('a','ab')], 'ab', 'ab', 'insert', 'insert', 2, 2, False), [('a', 'ab')])
check('empty noop', solve([], 'a', 'a', None, 'insert', None, 1, False), [])
check('delete', solve([('abcd','abc')], 'abc', 'ab', 'delete', 'delete', 3, 3, False), [('abcd', 'abc'), ('abc', 'ab')])
check('contiguous', solve([('a','ab')], 'ab', 'abc', 'insert', 'insert', 2, 2, False), [('a', 'abc')])
check('moved caret', solve([('a','ab')], 'ab', 'axb', 'insert', 'insert', 2, 1, False), [('a', 'ab'), ('ab', 'axb')])
check('boundary', solve([('a','ab')], 'ab', 'abc', 'insert', 'insert', 2, 2, True), [('a', 'ab'), ('ab', 'abc')])
check('empty', solve([], '', 'a', None, 'insert', None, 0, False), [('', 'a')])
check('parameterized inserted length', solve([], '', 'a'*N, None, 'insert', None, 0, False), [('', 'a'*N)])
for repetition in range(N):
    check('repeat empty', solve([], '', 'a', None, 'insert', None, 0, False), [('', 'a')])
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
noop[['a', 'ab']][['a', 'ab']]Passed
empty noop[][]Passed
delete[['abcd', 'abc'], ['abc', 'ab']][['abcd', 'abc'], ['abc', 'ab']]Passed
contiguous[['a', 'ab']][['a', 'abc']]Failed
moved caret[['a', 'ab'], ['ab', 'axb']][['a', 'ab'], ['ab', 'axb']]Passed
boundary[['a', 'ab'], ['ab', 'abc']][['a', 'ab'], ['ab', 'abc']]Passed
empty[['', 'a']][['', 'a']]Passed
parameterized inserted length[['', 'a']][['', 'a']]Passed
repeat empty[['', 'a']][['', 'a']]Passed

SHA-256 / 50b94d8101a91ecfd2689d68c947c44c7844d2aac4e301415794114be4422e49

3 / The verified repair

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

N = 1
observations = []
def solve(history, before, after, previous_kind, kind, previous_caret, caret, boundary):
    history = list(history)
    if before == after: return history
    merge = bool(history) and kind == 'insert' and previous_kind == kind and previous_caret == caret and not boundary
    if merge: history[-1] = (history[-1][0], after)
    else: history.append((before, after))
    return history
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('noop', solve([('a','ab')], 'ab', 'ab', 'insert', 'insert', 2, 2, False), [('a', 'ab')])
check('empty noop', solve([], 'a', 'a', None, 'insert', None, 1, False), [])
check('delete', solve([('abcd','abc')], 'abc', 'ab', 'delete', 'delete', 3, 3, False), [('abcd', 'abc'), ('abc', 'ab')])
check('contiguous', solve([('a','ab')], 'ab', 'abc', 'insert', 'insert', 2, 2, False), [('a', 'abc')])
check('moved caret', solve([('a','ab')], 'ab', 'axb', 'insert', 'insert', 2, 1, False), [('a', 'ab'), ('ab', 'axb')])
check('boundary', solve([('a','ab')], 'ab', 'abc', 'insert', 'insert', 2, 2, True), [('a', 'ab'), ('ab', 'abc')])
check('empty', solve([], '', 'a', None, 'insert', None, 0, False), [('', 'a')])
check('parameterized inserted length', solve([], '', 'a'*N, None, 'insert', None, 0, False), [('', 'a'*N)])
for repetition in range(N):
    check('repeat empty', solve([], '', 'a', None, 'insert', None, 0, False), [('', 'a')])
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
noop[['a', 'ab']][['a', 'ab']]Passed
empty noop[][]Passed
delete[['abcd', 'abc'], ['abc', 'ab']][['abcd', 'abc'], ['abc', 'ab']]Passed
contiguous[['a', 'abc']][['a', 'abc']]Passed
moved caret[['a', 'ab'], ['ab', 'axb']][['a', 'ab'], ['ab', 'axb']]Passed
boundary[['a', 'ab'], ['ab', 'abc']][['a', 'ab'], ['ab', 'abc']]Passed
empty[['', 'a']][['', 'a']]Passed
parameterized inserted length[['', 'a']][['', 'a']]Passed
repeat empty[['', 'a']][['', 'a']]Passed

SHA-256 / 9040f12ffc91fc2ab35075ff16280fb5513fb66e42e9db5093b7a765e2946624

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

Case digest / d1bbd075bd1b54251bcf53ccd1233ad5e0f6f1e571458224afa161e553b01755