FAILURE MAP
← Case archive

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

Patch reversal: no-newline markers detach from their lines · case 01

After reordering, the missing-newline marker follows the wrong line or starts a block.

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

ROOT CAUSE

Marker lines are treated as independent units instead of being attached to the preceding line.

VERIFIED REPAIR

Attach each "\\" marker line to the unit before it.

Unsuccessful approach: Dropping marker lines loses the missing-newline information entirely.

Case contract

Reverse one unified hunk: swap the old and new ranges in the header, keeping each range's count omitted if it was omitted and keeping any trailing header text; swap "-" and "+" on body lines; within each run of changed lines emit the (new) removed lines before the (new) added lines; a "\" marker line stays attached to the line it follows.

Why this case matters

Reverting a change applies the reversed patch, which must still be a valid, conventionally ordered hunk.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import re
N = 1
observations = []
def solve(lines):
    m = re.match(r'@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(.*)$', lines[0])
    a, an, c, cn, tail = m.groups()
    def fmt(s, cnt):
        return s if cnt is None else s + ',' + cnt
    out = ['@@ -%s +%s @@%s' % (fmt(c, cn), fmt(a, an), tail)]
    units = []
    for ln in lines[1:]:
        if False:
            units[-1].append(ln)
        else:
            units.append([ln])
    dels, adds = [], []
    def flush():
        for u in dels + adds:
            out.extend(u)
        dels.clear()
        adds.clear()
    for u in units:
        tag = u[0][:1]
        if tag == '+':
            dels.append(['-' + u[0][1:]] + u[1:])
        elif tag == '-':
            adds.append(['+' + u[0][1:]] + u[1:])
        else:
            flush()
            out.extend(u)
    flush()
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,1 @@', '+n0']], ['@@ -1,1 +0,0 @@', '-n0']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,3 @@', ' u', '-v', ' w', '+x0']], ['@@ -7,3 +7,3 @@', ' u', '+v', ' w', '-x0'])],
    2: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,2 @@', '+n0', '+n1']], ['@@ -1,2 +0,0 @@', '-n0', '-n1']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,4 @@', ' u', '-v', ' w', '+x0', '+x1']], ['@@ -7,4 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1'])],
    3: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,3 @@', '+n0', '+n1', '+n2']], ['@@ -1,3 +0,0 @@', '-n0', '-n1', '-n2']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,5 @@', ' u', '-v', ' w', '+x0', '+x1', '+x2']], ['@@ -7,5 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1', '-x2'])],
    4: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,4 @@', '+n0', '+n1', '+n2', '+n3']], ['@@ -1,4 +0,0 @@', '-n0', '-n1', '-n2', '-n3']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,6 @@', ' u', '-v', ' w', '+x0', '+x1', '+x2', '+x3']], ['@@ -7,6 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1', '-x2', '-x3'])],
    5: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,5 @@', '+n0', '+n1', '+n2', '+n3', '+n4']], ['@@ -1,5 +0,0 @@', '-n0', '-n1', '-n2', '-n3', '-n4']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,7 @@', ' u', '-v', ' w', '+x0', '+x1', '+x2', '+x3', '+x4']], ['@@ -7,7 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1', '-x2', '-x3', '-x4'])],
}[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
replacement block['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']Passed
omitted counts stay omitted['@@ -5 +5 @@', '-y', '+x']['@@ -5 +5 @@', '-y', '+x']Passed
explicit zero count['@@ -1,1 +0,0 @@', '-n0']['@@ -1,1 +0,0 @@', '-n0']Passed
no-newline marker follows its line['@@ -1,2 +1,2 @@', ' k', '+old', '\\ No newline at end of file', '-new', '\\ No newline at end of file']['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']Failed
several blocks['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']Passed
insertion only['@@ -2,3 +2,1 @@', ' p', '-q', '-r']['@@ -2,3 +2,1 @@', ' p', '-q', '-r']Passed
marker after the new side only['@@ -4,1 +4,1 @@', '-z2', '+z', '\\ No newline at end of file']['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']Failed
header without trailing text['@@ -7,3 +7,3 @@', ' u', '+v', ' w', '-x0']['@@ -7,3 +7,3 @@', ' u', '+v', ' w', '-x0']Passed

SHA-256 / 4762233cef09191e637a5f7dfa32f1f8466ca78d5c5e82db21921209e12e5543

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import re
N = 1
observations = []
def solve(lines):
    m = re.match(r'@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(.*)$', lines[0])
    a, an, c, cn, tail = m.groups()
    def fmt(s, cnt):
        return s if cnt is None else s + ',' + cnt
    out = ['@@ -%s +%s @@%s' % (fmt(c, cn), fmt(a, an), tail)]
    units = []
    for ln in lines[1:]:
        if ln.startswith('\\') and units:
            pass
        else:
            units.append([ln])
    dels, adds = [], []
    def flush():
        for u in dels + adds:
            out.extend(u)
        dels.clear()
        adds.clear()
    for u in units:
        tag = u[0][:1]
        if tag == '+':
            dels.append(['-' + u[0][1:]] + u[1:])
        elif tag == '-':
            adds.append(['+' + u[0][1:]] + u[1:])
        else:
            flush()
            out.extend(u)
    flush()
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,1 @@', '+n0']], ['@@ -1,1 +0,0 @@', '-n0']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,3 @@', ' u', '-v', ' w', '+x0']], ['@@ -7,3 +7,3 @@', ' u', '+v', ' w', '-x0'])],
    2: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,2 @@', '+n0', '+n1']], ['@@ -1,2 +0,0 @@', '-n0', '-n1']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,4 @@', ' u', '-v', ' w', '+x0', '+x1']], ['@@ -7,4 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1'])],
    3: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,3 @@', '+n0', '+n1', '+n2']], ['@@ -1,3 +0,0 @@', '-n0', '-n1', '-n2']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,5 @@', ' u', '-v', ' w', '+x0', '+x1', '+x2']], ['@@ -7,5 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1', '-x2'])],
    4: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,4 @@', '+n0', '+n1', '+n2', '+n3']], ['@@ -1,4 +0,0 @@', '-n0', '-n1', '-n2', '-n3']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,6 @@', ' u', '-v', ' w', '+x0', '+x1', '+x2', '+x3']], ['@@ -7,6 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1', '-x2', '-x3'])],
    5: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,5 @@', '+n0', '+n1', '+n2', '+n3', '+n4']], ['@@ -1,5 +0,0 @@', '-n0', '-n1', '-n2', '-n3', '-n4']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,7 @@', ' u', '-v', ' w', '+x0', '+x1', '+x2', '+x3', '+x4']], ['@@ -7,7 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1', '-x2', '-x3', '-x4'])],
}[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
replacement block['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']Passed
omitted counts stay omitted['@@ -5 +5 @@', '-y', '+x']['@@ -5 +5 @@', '-y', '+x']Passed
explicit zero count['@@ -1,1 +0,0 @@', '-n0']['@@ -1,1 +0,0 @@', '-n0']Passed
no-newline marker follows its line['@@ -1,2 +1,2 @@', ' k', '-new', '+old']['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']Failed
several blocks['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']Passed
insertion only['@@ -2,3 +2,1 @@', ' p', '-q', '-r']['@@ -2,3 +2,1 @@', ' p', '-q', '-r']Passed
marker after the new side only['@@ -4,1 +4,1 @@', '-z2', '+z']['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']Failed
header without trailing text['@@ -7,3 +7,3 @@', ' u', '+v', ' w', '-x0']['@@ -7,3 +7,3 @@', ' u', '+v', ' w', '-x0']Passed

SHA-256 / dc83b4eee31d4dc1dfebbb3445e6521977f8805171e636c1c03b30ca2344dfb9

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import re
N = 1
observations = []
def solve(lines):
    m = re.match(r'@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(.*)$', lines[0])
    a, an, c, cn, tail = m.groups()
    def fmt(s, cnt):
        return s if cnt is None else s + ',' + cnt
    out = ['@@ -%s +%s @@%s' % (fmt(c, cn), fmt(a, an), tail)]
    units = []
    for ln in lines[1:]:
        if ln.startswith('\\') and units:
            units[-1].append(ln)
        else:
            units.append([ln])
    dels, adds = [], []
    def flush():
        for u in dels + adds:
            out.extend(u)
        dels.clear()
        adds.clear()
    for u in units:
        tag = u[0][:1]
        if tag == '+':
            dels.append(['-' + u[0][1:]] + u[1:])
        elif tag == '-':
            adds.append(['+' + u[0][1:]] + u[1:])
        else:
            flush()
            out.extend(u)
    flush()
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,1 @@', '+n0']], ['@@ -1,1 +0,0 @@', '-n0']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,3 @@', ' u', '-v', ' w', '+x0']], ['@@ -7,3 +7,3 @@', ' u', '+v', ' w', '-x0'])],
    2: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,2 @@', '+n0', '+n1']], ['@@ -1,2 +0,0 @@', '-n0', '-n1']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,4 @@', ' u', '-v', ' w', '+x0', '+x1']], ['@@ -7,4 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1'])],
    3: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,3 @@', '+n0', '+n1', '+n2']], ['@@ -1,3 +0,0 @@', '-n0', '-n1', '-n2']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,5 @@', ' u', '-v', ' w', '+x0', '+x1', '+x2']], ['@@ -7,5 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1', '-x2'])],
    4: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,4 @@', '+n0', '+n1', '+n2', '+n3']], ['@@ -1,4 +0,0 @@', '-n0', '-n1', '-n2', '-n3']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,6 @@', ' u', '-v', ' w', '+x0', '+x1', '+x2', '+x3']], ['@@ -7,6 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1', '-x2', '-x3'])],
    5: [('replacement block', [['@@ -3,2 +3,2 @@ def f():', ' a', '-b', '+B', ' c']], ['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']), ('omitted counts stay omitted', [['@@ -5 +5 @@', '-x', '+y']], ['@@ -5 +5 @@', '-y', '+x']), ('explicit zero count', [['@@ -0,0 +1,5 @@', '+n0', '+n1', '+n2', '+n3', '+n4']], ['@@ -1,5 +0,0 @@', '-n0', '-n1', '-n2', '-n3', '-n4']), ('no-newline marker follows its line', [['@@ -1,2 +1,2 @@', ' k', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], ['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']), ('several blocks', [['@@ -1,6 +1,5 @@', '-a', ' b', '+c', '+d', ' e', '-f', '-g', '+h', ' i']], ['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']), ('insertion only', [['@@ -2,1 +2,3 @@', ' p', '+q', '+r']], ['@@ -2,3 +2,1 @@', ' p', '-q', '-r']), ('marker after the new side only', [['@@ -4,1 +4,1 @@', '-z', '+z2', '\\ No newline at end of file']], ['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']), ('header without trailing text', [['@@ -7,3 +7,7 @@', ' u', '-v', ' w', '+x0', '+x1', '+x2', '+x3', '+x4']], ['@@ -7,7 +7,3 @@', ' u', '+v', ' w', '-x0', '-x1', '-x2', '-x3', '-x4'])],
}[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
replacement block['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']['@@ -3,2 +3,2 @@ def f():', ' a', '-B', '+b', ' c']Passed
omitted counts stay omitted['@@ -5 +5 @@', '-y', '+x']['@@ -5 +5 @@', '-y', '+x']Passed
explicit zero count['@@ -1,1 +0,0 @@', '-n0']['@@ -1,1 +0,0 @@', '-n0']Passed
no-newline marker follows its line['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']['@@ -1,2 +1,2 @@', ' k', '-new', '\\ No newline at end of file', '+old', '\\ No newline at end of file']Passed
several blocks['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']['@@ -1,5 +1,6 @@', '+a', ' b', '-c', '-d', ' e', '-h', '+f', '+g', ' i']Passed
insertion only['@@ -2,3 +2,1 @@', ' p', '-q', '-r']['@@ -2,3 +2,1 @@', ' p', '-q', '-r']Passed
marker after the new side only['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']['@@ -4,1 +4,1 @@', '-z2', '\\ No newline at end of file', '+z']Passed
header without trailing text['@@ -7,3 +7,3 @@', ' u', '+v', ' w', '-x0']['@@ -7,3 +7,3 @@', ' u', '+v', ' w', '-x0']Passed

SHA-256 / 60005a6c39c3bb955d488ae11ca4bc7ac154f68e83ecf2270785580f27d1e4a7

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

Case digest / 697bf7df3f40fa7a20e643a343ffef0ca60d294647c19caded8c195f9acdcd3f