FAILURE MAP
← Case archive

FA-75516 / Text diff and three-way merge / Open access

Patience diff anchors: reconstruction starts from the first pile · case 01

Only a single anchor is returned even when a long chain exists.

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

ROOT CAUSE

The chain is rebuilt from the top of the first pile instead of the last.

VERIFIED REPAIR

Start reconstruction from the top of the last pile.

Unsuccessful approach: Starting from the last candidate follows a chain that may be shorter than the longest one.

Case contract

Candidates are lines occurring exactly once in the old side and exactly once in the new side, as (old index, new index) pairs in old order. Keep the longest chain with increasing new index, found with patience piles (bisect on pile tops by new index, back pointers to the previous pile top) and reconstructed from the top of the last pile. Return the anchor pairs.

Why this case matters

Patience diff anchors on unique lines to produce readable diffs of code with many repeated braces and blank lines.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import bisect
import collections
N = 1
observations = []
def solve(a, b):
    ca = collections.Counter(a)
    cb = collections.Counter(b)
    posb = {x: j for j, x in enumerate(b)}
    cand = [(i, posb[x]) for i, x in enumerate(a) if ca[x] == 1 and cb.get(x, 0) == 1]
    tails = []
    back = {}
    for idx, (i, j) in enumerate(cand):
        lo = bisect.bisect_left([cand[t][1] for t in tails], j)
        if lo == len(tails):
            tails.append(idx)
        else:
            tails[lo] = idx
        back[idx] = tails[lo - 1] if lo > 0 else None
    res = []
    t = tails[0] if tails else None
    while t is not None:
        res.append(list(cand[t]))
        t = back[t]
    return res[::-1]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('unique lines in order', [['a', 'b', 'c', 'd'], ['a', 'x', 'c', 'd']], [[0, 0], [2, 2], [3, 3]]), ('crossing unique lines keep the longest chain', [['f1', 'f2', 'f3', 'g'], ['f2', 'f3', 'f1', 'g']], [[1, 0], [2, 1], [3, 3]]), ('duplicated in new side are not anchors', [['x', 'y', 'z'], ['y', 'x', 'y', 'z']], [[0, 1], [2, 3]]), ('duplicated in old side are not anchors', [['}', 'a', '}', 'b'], ['}', 'b', 'a']], [[3, 1]]), ('no unique common lines', [['r', 'r'], ['s', 's']], []), ('chain ends before the last candidate', [['u', 'v', 'w', 'p'], ['v', 'w', 'p', 'u']], [[1, 0], [2, 1], [3, 2]]), ('later short chain', [['m0', 'm1', 'm2', 'k'], ['k', 'm0', 'm1', 'm2']], [[0, 1], [1, 2], [2, 3]]), ('single candidate', [['q', 'z'], ['z', 'q', 'q']], [[1, 0]])],
    2: [('unique lines in order', [['a', 'b', 'c', 'd'], ['a', 'x', 'c', 'd']], [[0, 0], [2, 2], [3, 3]]), ('crossing unique lines keep the longest chain', [['f1', 'f2', 'f3', 'g'], ['f2', 'f3', 'f1', 'g']], [[1, 0], [2, 1], [3, 3]]), ('duplicated in new side are not anchors', [['x', 'y', 'z'], ['y', 'x', 'y', 'z']], [[0, 1], [2, 3]]), ('duplicated in old side are not anchors', [['}', 'a', '}', 'b'], ['}', 'b', 'a']], [[3, 1]]), ('no unique common lines', [['r', 'r'], ['s', 's']], []), ('chain ends before the last candidate', [['u', 'v', 'w', 'p'], ['u', 'v', 'w', 'p']], [[0, 0], [1, 1], [2, 2], [3, 3]]), ('later short chain', [['m0', 'm1', 'm2', 'm3', 'k'], ['k', 'm0', 'm1', 'm2', 'm3']], [[0, 1], [1, 2], [2, 3], [3, 4]]), ('single candidate', [['q', 'z'], ['z', 'q', 'q']], [[1, 0]])],
    3: [('unique lines in order', [['a', 'b', 'c', 'd'], ['a', 'x', 'c', 'd']], [[0, 0], [2, 2], [3, 3]]), ('crossing unique lines keep the longest chain', [['f1', 'f2', 'f3', 'g'], ['f2', 'f3', 'f1', 'g']], [[1, 0], [2, 1], [3, 3]]), ('duplicated in new side are not anchors', [['x', 'y', 'z'], ['y', 'x', 'y', 'z']], [[0, 1], [2, 3]]), ('duplicated in old side are not anchors', [['}', 'a', '}', 'b'], ['}', 'b', 'a']], [[3, 1]]), ('no unique common lines', [['r', 'r'], ['s', 's']], []), ('chain ends before the last candidate', [['u', 'v', 'w', 'p'], ['v', 'w', 'p', 'u']], [[1, 0], [2, 1], [3, 2]]), ('later short chain', [['m0', 'm1', 'm2', 'm3', 'm4', 'k'], ['k', 'm0', 'm1', 'm2', 'm3', 'm4']], [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5]]), ('single candidate', [['q', 'z'], ['z', 'q', 'q']], [[1, 0]])],
    4: [('unique lines in order', [['a', 'b', 'c', 'd'], ['a', 'x', 'c', 'd']], [[0, 0], [2, 2], [3, 3]]), ('crossing unique lines keep the longest chain', [['f1', 'f2', 'f3', 'g'], ['f2', 'f3', 'f1', 'g']], [[1, 0], [2, 1], [3, 3]]), ('duplicated in new side are not anchors', [['x', 'y', 'z'], ['y', 'x', 'y', 'z']], [[0, 1], [2, 3]]), ('duplicated in old side are not anchors', [['}', 'a', '}', 'b'], ['}', 'b', 'a']], [[3, 1]]), ('no unique common lines', [['r', 'r'], ['s', 's']], []), ('chain ends before the last candidate', [['u', 'v', 'w', 'p'], ['u', 'v', 'w', 'p']], [[0, 0], [1, 1], [2, 2], [3, 3]]), ('later short chain', [['m0', 'm1', 'm2', 'm3', 'm4', 'm5', 'k'], ['k', 'm0', 'm1', 'm2', 'm3', 'm4', 'm5']], [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6]]), ('single candidate', [['q', 'z'], ['z', 'q', 'q']], [[1, 0]])],
    5: [('unique lines in order', [['a', 'b', 'c', 'd'], ['a', 'x', 'c', 'd']], [[0, 0], [2, 2], [3, 3]]), ('crossing unique lines keep the longest chain', [['f1', 'f2', 'f3', 'g'], ['f2', 'f3', 'f1', 'g']], [[1, 0], [2, 1], [3, 3]]), ('duplicated in new side are not anchors', [['x', 'y', 'z'], ['y', 'x', 'y', 'z']], [[0, 1], [2, 3]]), ('duplicated in old side are not anchors', [['}', 'a', '}', 'b'], ['}', 'b', 'a']], [[3, 1]]), ('no unique common lines', [['r', 'r'], ['s', 's']], []), ('chain ends before the last candidate', [['u', 'v', 'w', 'p'], ['v', 'w', 'p', 'u']], [[1, 0], [2, 1], [3, 2]]), ('later short chain', [['m0', 'm1', 'm2', 'm3', 'm4', 'm5', 'm6', 'k'], ['k', 'm0', 'm1', 'm2', 'm3', 'm4', 'm5', 'm6']], [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7]]), ('single candidate', [['q', 'z'], ['z', 'q', 'q']], [[1, 0]])],
}[N]
for label, args, expected in cases:
    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
unique lines in order[[0, 0]][[0, 0], [2, 2], [3, 3]]Failed
crossing unique lines keep the longest chain[[1, 0]][[1, 0], [2, 1], [3, 3]]Failed
duplicated in new side are not anchors[[0, 1]][[0, 1], [2, 3]]Failed
duplicated in old side are not anchors[[3, 1]][[3, 1]]Passed
no unique common lines[][]Passed
chain ends before the last candidate[[1, 0]][[1, 0], [2, 1], [3, 2]]Failed
later short chain[[3, 0]][[0, 1], [1, 2], [2, 3]]Failed
single candidate[[1, 0]][[1, 0]]Passed

SHA-256 / e9bdae05ef7141a8f5dd70b3f3255c6b9680c0f73ac92b0ceae059bb746ebebe

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import bisect
import collections
N = 1
observations = []
def solve(a, b):
    ca = collections.Counter(a)
    cb = collections.Counter(b)
    posb = {x: j for j, x in enumerate(b)}
    cand = [(i, posb[x]) for i, x in enumerate(a) if ca[x] == 1 and cb.get(x, 0) == 1]
    tails = []
    back = {}
    for idx, (i, j) in enumerate(cand):
        lo = bisect.bisect_left([cand[t][1] for t in tails], j)
        if lo == len(tails):
            tails.append(idx)
        else:
            tails[lo] = idx
        back[idx] = tails[lo - 1] if lo > 0 else None
    res = []
    t = len(cand) - 1 if cand else None
    while t is not None:
        res.append(list(cand[t]))
        t = back[t]
    return res[::-1]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('unique lines in order', [['a', 'b', 'c', 'd'], ['a', 'x', 'c', 'd']], [[0, 0], [2, 2], [3, 3]]), ('crossing unique lines keep the longest chain', [['f1', 'f2', 'f3', 'g'], ['f2', 'f3', 'f1', 'g']], [[1, 0], [2, 1], [3, 3]]), ('duplicated in new side are not anchors', [['x', 'y', 'z'], ['y', 'x', 'y', 'z']], [[0, 1], [2, 3]]), ('duplicated in old side are not anchors', [['}', 'a', '}', 'b'], ['}', 'b', 'a']], [[3, 1]]), ('no unique common lines', [['r', 'r'], ['s', 's']], []), ('chain ends before the last candidate', [['u', 'v', 'w', 'p'], ['v', 'w', 'p', 'u']], [[1, 0], [2, 1], [3, 2]]), ('later short chain', [['m0', 'm1', 'm2', 'k'], ['k', 'm0', 'm1', 'm2']], [[0, 1], [1, 2], [2, 3]]), ('single candidate', [['q', 'z'], ['z', 'q', 'q']], [[1, 0]])],
    2: [('unique lines in order', [['a', 'b', 'c', 'd'], ['a', 'x', 'c', 'd']], [[0, 0], [2, 2], [3, 3]]), ('crossing unique lines keep the longest chain', [['f1', 'f2', 'f3', 'g'], ['f2', 'f3', 'f1', 'g']], [[1, 0], [2, 1], [3, 3]]), ('duplicated in new side are not anchors', [['x', 'y', 'z'], ['y', 'x', 'y', 'z']], [[0, 1], [2, 3]]), ('duplicated in old side are not anchors', [['}', 'a', '}', 'b'], ['}', 'b', 'a']], [[3, 1]]), ('no unique common lines', [['r', 'r'], ['s', 's']], []), ('chain ends before the last candidate', [['u', 'v', 'w', 'p'], ['u', 'v', 'w', 'p']], [[0, 0], [1, 1], [2, 2], [3, 3]]), ('later short chain', [['m0', 'm1', 'm2', 'm3', 'k'], ['k', 'm0', 'm1', 'm2', 'm3']], [[0, 1], [1, 2], [2, 3], [3, 4]]), ('single candidate', [['q', 'z'], ['z', 'q', 'q']], [[1, 0]])],
    3: [('unique lines in order', [['a', 'b', 'c', 'd'], ['a', 'x', 'c', 'd']], [[0, 0], [2, 2], [3, 3]]), ('crossing unique lines keep the longest chain', [['f1', 'f2', 'f3', 'g'], ['f2', 'f3', 'f1', 'g']], [[1, 0], [2, 1], [3, 3]]), ('duplicated in new side are not anchors', [['x', 'y', 'z'], ['y', 'x', 'y', 'z']], [[0, 1], [2, 3]]), ('duplicated in old side are not anchors', [['}', 'a', '}', 'b'], ['}', 'b', 'a']], [[3, 1]]), ('no unique common lines', [['r', 'r'], ['s', 's']], []), ('chain ends before the last candidate', [['u', 'v', 'w', 'p'], ['v', 'w', 'p', 'u']], [[1, 0], [2, 1], [3, 2]]), ('later short chain', [['m0', 'm1', 'm2', 'm3', 'm4', 'k'], ['k', 'm0', 'm1', 'm2', 'm3', 'm4']], [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5]]), ('single candidate', [['q', 'z'], ['z', 'q', 'q']], [[1, 0]])],
    4: [('unique lines in order', [['a', 'b', 'c', 'd'], ['a', 'x', 'c', 'd']], [[0, 0], [2, 2], [3, 3]]), ('crossing unique lines keep the longest chain', [['f1', 'f2', 'f3', 'g'], ['f2', 'f3', 'f1', 'g']], [[1, 0], [2, 1], [3, 3]]), ('duplicated in new side are not anchors', [['x', 'y', 'z'], ['y', 'x', 'y', 'z']], [[0, 1], [2, 3]]), ('duplicated in old side are not anchors', [['}', 'a', '}', 'b'], ['}', 'b', 'a']], [[3, 1]]), ('no unique common lines', [['r', 'r'], ['s', 's']], []), ('chain ends before the last candidate', [['u', 'v', 'w', 'p'], ['u', 'v', 'w', 'p']], [[0, 0], [1, 1], [2, 2], [3, 3]]), ('later short chain', [['m0', 'm1', 'm2', 'm3', 'm4', 'm5', 'k'], ['k', 'm0', 'm1', 'm2', 'm3', 'm4', 'm5']], [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6]]), ('single candidate', [['q', 'z'], ['z', 'q', 'q']], [[1, 0]])],
    5: [('unique lines in order', [['a', 'b', 'c', 'd'], ['a', 'x', 'c', 'd']], [[0, 0], [2, 2], [3, 3]]), ('crossing unique lines keep the longest chain', [['f1', 'f2', 'f3', 'g'], ['f2', 'f3', 'f1', 'g']], [[1, 0], [2, 1], [3, 3]]), ('duplicated in new side are not anchors', [['x', 'y', 'z'], ['y', 'x', 'y', 'z']], [[0, 1], [2, 3]]), ('duplicated in old side are not anchors', [['}', 'a', '}', 'b'], ['}', 'b', 'a']], [[3, 1]]), ('no unique common lines', [['r', 'r'], ['s', 's']], []), ('chain ends before the last candidate', [['u', 'v', 'w', 'p'], ['v', 'w', 'p', 'u']], [[1, 0], [2, 1], [3, 2]]), ('later short chain', [['m0', 'm1', 'm2', 'm3', 'm4', 'm5', 'm6', 'k'], ['k', 'm0', 'm1', 'm2', 'm3', 'm4', 'm5', 'm6']], [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7]]), ('single candidate', [['q', 'z'], ['z', 'q', 'q']], [[1, 0]])],
}[N]
for label, args, expected in cases:
    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
unique lines in order[[0, 0], [2, 2], [3, 3]][[0, 0], [2, 2], [3, 3]]Passed
crossing unique lines keep the longest chain[[1, 0], [2, 1], [3, 3]][[1, 0], [2, 1], [3, 3]]Passed
duplicated in new side are not anchors[[0, 1], [2, 3]][[0, 1], [2, 3]]Passed
duplicated in old side are not anchors[[3, 1]][[3, 1]]Passed
no unique common lines[][]Passed
chain ends before the last candidate[[1, 0], [2, 1], [3, 2]][[1, 0], [2, 1], [3, 2]]Passed
later short chain[[3, 0]][[0, 1], [1, 2], [2, 3]]Failed
single candidate[[1, 0]][[1, 0]]Passed

SHA-256 / 7ea2e425c9ac114f524d981a785b0710b19d0c9de16dd3ec0cb40595d5e1d784

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import bisect
import collections
N = 1
observations = []
def solve(a, b):
    ca = collections.Counter(a)
    cb = collections.Counter(b)
    posb = {x: j for j, x in enumerate(b)}
    cand = [(i, posb[x]) for i, x in enumerate(a) if ca[x] == 1 and cb.get(x, 0) == 1]
    tails = []
    back = {}
    for idx, (i, j) in enumerate(cand):
        lo = bisect.bisect_left([cand[t][1] for t in tails], j)
        if lo == len(tails):
            tails.append(idx)
        else:
            tails[lo] = idx
        back[idx] = tails[lo - 1] if lo > 0 else None
    res = []
    t = tails[-1] if tails else None
    while t is not None:
        res.append(list(cand[t]))
        t = back[t]
    return res[::-1]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('unique lines in order', [['a', 'b', 'c', 'd'], ['a', 'x', 'c', 'd']], [[0, 0], [2, 2], [3, 3]]), ('crossing unique lines keep the longest chain', [['f1', 'f2', 'f3', 'g'], ['f2', 'f3', 'f1', 'g']], [[1, 0], [2, 1], [3, 3]]), ('duplicated in new side are not anchors', [['x', 'y', 'z'], ['y', 'x', 'y', 'z']], [[0, 1], [2, 3]]), ('duplicated in old side are not anchors', [['}', 'a', '}', 'b'], ['}', 'b', 'a']], [[3, 1]]), ('no unique common lines', [['r', 'r'], ['s', 's']], []), ('chain ends before the last candidate', [['u', 'v', 'w', 'p'], ['v', 'w', 'p', 'u']], [[1, 0], [2, 1], [3, 2]]), ('later short chain', [['m0', 'm1', 'm2', 'k'], ['k', 'm0', 'm1', 'm2']], [[0, 1], [1, 2], [2, 3]]), ('single candidate', [['q', 'z'], ['z', 'q', 'q']], [[1, 0]])],
    2: [('unique lines in order', [['a', 'b', 'c', 'd'], ['a', 'x', 'c', 'd']], [[0, 0], [2, 2], [3, 3]]), ('crossing unique lines keep the longest chain', [['f1', 'f2', 'f3', 'g'], ['f2', 'f3', 'f1', 'g']], [[1, 0], [2, 1], [3, 3]]), ('duplicated in new side are not anchors', [['x', 'y', 'z'], ['y', 'x', 'y', 'z']], [[0, 1], [2, 3]]), ('duplicated in old side are not anchors', [['}', 'a', '}', 'b'], ['}', 'b', 'a']], [[3, 1]]), ('no unique common lines', [['r', 'r'], ['s', 's']], []), ('chain ends before the last candidate', [['u', 'v', 'w', 'p'], ['u', 'v', 'w', 'p']], [[0, 0], [1, 1], [2, 2], [3, 3]]), ('later short chain', [['m0', 'm1', 'm2', 'm3', 'k'], ['k', 'm0', 'm1', 'm2', 'm3']], [[0, 1], [1, 2], [2, 3], [3, 4]]), ('single candidate', [['q', 'z'], ['z', 'q', 'q']], [[1, 0]])],
    3: [('unique lines in order', [['a', 'b', 'c', 'd'], ['a', 'x', 'c', 'd']], [[0, 0], [2, 2], [3, 3]]), ('crossing unique lines keep the longest chain', [['f1', 'f2', 'f3', 'g'], ['f2', 'f3', 'f1', 'g']], [[1, 0], [2, 1], [3, 3]]), ('duplicated in new side are not anchors', [['x', 'y', 'z'], ['y', 'x', 'y', 'z']], [[0, 1], [2, 3]]), ('duplicated in old side are not anchors', [['}', 'a', '}', 'b'], ['}', 'b', 'a']], [[3, 1]]), ('no unique common lines', [['r', 'r'], ['s', 's']], []), ('chain ends before the last candidate', [['u', 'v', 'w', 'p'], ['v', 'w', 'p', 'u']], [[1, 0], [2, 1], [3, 2]]), ('later short chain', [['m0', 'm1', 'm2', 'm3', 'm4', 'k'], ['k', 'm0', 'm1', 'm2', 'm3', 'm4']], [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5]]), ('single candidate', [['q', 'z'], ['z', 'q', 'q']], [[1, 0]])],
    4: [('unique lines in order', [['a', 'b', 'c', 'd'], ['a', 'x', 'c', 'd']], [[0, 0], [2, 2], [3, 3]]), ('crossing unique lines keep the longest chain', [['f1', 'f2', 'f3', 'g'], ['f2', 'f3', 'f1', 'g']], [[1, 0], [2, 1], [3, 3]]), ('duplicated in new side are not anchors', [['x', 'y', 'z'], ['y', 'x', 'y', 'z']], [[0, 1], [2, 3]]), ('duplicated in old side are not anchors', [['}', 'a', '}', 'b'], ['}', 'b', 'a']], [[3, 1]]), ('no unique common lines', [['r', 'r'], ['s', 's']], []), ('chain ends before the last candidate', [['u', 'v', 'w', 'p'], ['u', 'v', 'w', 'p']], [[0, 0], [1, 1], [2, 2], [3, 3]]), ('later short chain', [['m0', 'm1', 'm2', 'm3', 'm4', 'm5', 'k'], ['k', 'm0', 'm1', 'm2', 'm3', 'm4', 'm5']], [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6]]), ('single candidate', [['q', 'z'], ['z', 'q', 'q']], [[1, 0]])],
    5: [('unique lines in order', [['a', 'b', 'c', 'd'], ['a', 'x', 'c', 'd']], [[0, 0], [2, 2], [3, 3]]), ('crossing unique lines keep the longest chain', [['f1', 'f2', 'f3', 'g'], ['f2', 'f3', 'f1', 'g']], [[1, 0], [2, 1], [3, 3]]), ('duplicated in new side are not anchors', [['x', 'y', 'z'], ['y', 'x', 'y', 'z']], [[0, 1], [2, 3]]), ('duplicated in old side are not anchors', [['}', 'a', '}', 'b'], ['}', 'b', 'a']], [[3, 1]]), ('no unique common lines', [['r', 'r'], ['s', 's']], []), ('chain ends before the last candidate', [['u', 'v', 'w', 'p'], ['v', 'w', 'p', 'u']], [[1, 0], [2, 1], [3, 2]]), ('later short chain', [['m0', 'm1', 'm2', 'm3', 'm4', 'm5', 'm6', 'k'], ['k', 'm0', 'm1', 'm2', 'm3', 'm4', 'm5', 'm6']], [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7]]), ('single candidate', [['q', 'z'], ['z', 'q', 'q']], [[1, 0]])],
}[N]
for label, args, expected in cases:
    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
unique lines in order[[0, 0], [2, 2], [3, 3]][[0, 0], [2, 2], [3, 3]]Passed
crossing unique lines keep the longest chain[[1, 0], [2, 1], [3, 3]][[1, 0], [2, 1], [3, 3]]Passed
duplicated in new side are not anchors[[0, 1], [2, 3]][[0, 1], [2, 3]]Passed
duplicated in old side are not anchors[[3, 1]][[3, 1]]Passed
no unique common lines[][]Passed
chain ends before the last candidate[[1, 0], [2, 1], [3, 2]][[1, 0], [2, 1], [3, 2]]Passed
later short chain[[0, 1], [1, 2], [2, 3]][[0, 1], [1, 2], [2, 3]]Passed
single candidate[[1, 0]][[1, 0]]Passed

SHA-256 / a4ca7ad5760d347b3246a7a4dd5466be1f11bce1a8b13acf73db996373b0bb00

Verification & scope

A deterministic, bounded teaching model of one diff, patch or merge rule with stipulated conventions; it is not a production diff or version-control implementation and makes no claim of conformance to any specific tool. 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:07.358301+00:00.

Case digest / c70f646883fb9110a6fc14c440ecef85947a4b7d9138440b231022ac4cb4ae57