FAILURE MAP
← Case archive

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

Patch reversal: an omitted count becomes an explicit zero · case 01

Reversing a single-line hunk produces a header claiming an empty range.

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

ROOT CAUSE

The formatter substitutes 0 for an omitted count, which by convention means 1.

VERIFIED REPAIR

Keep an omitted count omitted.

Unsuccessful approach: Writing an explicit ",1" is equivalent in meaning but no longer preserves the header form.

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 + ',' + (cnt or '0')
    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,0 +5,0 @@', '-y', '+x']['@@ -5 +5 @@', '-y', '+x']Failed
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 / 698f0abc232abbeba54229c490993b0eb1c46e6e9ef11ce3ea3582fe371e4ca1

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 + ',' + (cnt or '1')
    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,1 +5,1 @@', '-y', '+x']['@@ -5 +5 @@', '-y', '+x']Failed
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 / 81e159b3cc650643f7e4a35ee934098048b658a96314364955729e8bf14ee9b5

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

Case digest / cf220c40becf1677aee213423811dc3621f30e8c4913111bcdddfe4a53f02bff