FAILURE MAP
← Case archive

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

Unified hunk parser: an empty line inside a hunk ends it · case 01

Patches whose blank context lines lost their leading space are rejected as truncated.

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

ROOT CAUSE

An empty line yields an empty tag and ends the body.

VERIFIED REPAIR

Treat a completely empty body line as a context line.

Unsuccessful approach: Counting an empty line as an addition unbalances the old and new counts.

Case contract

Parse "@@ -a[,b] +c[,d] @@" hunks (omitted counts are 1) and consume body lines until both remaining counts reach zero: " " (or a completely empty line) counts for both sides, "-" for old, "+" for new, "\\" marker lines are skipped and not counted, anything else ends the body. Remaining counts other than zero yield {"error": "hunk k truncated"}. Return [a, b, c, d, body_lines] per hunk.

Why this case matters

Patch tools must validate hunk bodies against their headers before applying anything.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import re
N = 1
observations = []
def solve(lines):
    hdr = re.compile(r'^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@')
    hunks = []
    i = 0
    while i < len(lines):
        m = hdr.match(lines[i])
        if not m:
            i += 1
            continue
        os_ = int(m.group(1))
        ol = int(m.group(2)) if m.group(2) is not None else 1
        ns = int(m.group(3))
        nl = int(m.group(4)) if m.group(4) is not None else 1
        need_o, need_n, body = ol, nl, 0
        i += 1
        while (need_o > 0 or need_n > 0) and i < len(lines):
            ln = lines[i]
            if ln.startswith('\\'):
                i += 1
                continue
            t = ln[:1]
            if t == ' ':
                need_o -= 1
                need_n -= 1
            elif t == '-':
                need_o -= 1
            elif t == '+':
                need_n -= 1
            else:
                break
            body += 1
            i += 1
        if need_o != 0 or need_n != 0:
            return {'error': 'hunk %d truncated' % len(hunks)}
        hunks.append([os_, ol, ns, nl, body])
    return {'hunks': hunks}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('well-formed hunk', [['--- a/f', '+++ b/f', '@@ -1,3 +1,3 @@', ' a', '-b', '+B', ' c']], {'hunks': [[1, 3, 1, 3, 4]]}), ('omitted counts mean one', [['@@ -4 +4 @@', '-x', '+y']], {'hunks': [[4, 1, 4, 1, 2]]}), ('explicit zero count', [['@@ -0,0 +1,1 @@', '+n']], {'hunks': [[0, 0, 1, 1, 1]]}), ('no-newline marker is not a body line', [['@@ -1 +1 @@', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], {'hunks': [[1, 1, 1, 1, 2]]}), ('empty line tolerated as context', [['@@ -1,3 +1,3 @@', ' a', '', ' c']], {'hunks': [[1, 3, 1, 3, 3]]}), ('truncated hunk', [['@@ -1,3 +1,4 @@', ' a', '+b', ' c']], {'error': 'hunk 0 truncated'}), ('trailing additions after old side is exhausted', [['@@ -2,2 +2,3 @@', ' a', '-b', '+x', '+x']], {'hunks': [[2, 2, 2, 3, 4]]}), ('two hunks', [['@@ -1,2 +1,1 @@', ' a', '-b', '@@ -9 +8,2 @@', ' z', '+w']], {'hunks': [[1, 2, 1, 1, 2], [9, 1, 8, 2, 2]]})],
    2: [('well-formed hunk', [['--- a/f', '+++ b/f', '@@ -1,3 +1,3 @@', ' a', '-b', '+B', ' c']], {'hunks': [[1, 3, 1, 3, 4]]}), ('omitted counts mean one', [['@@ -4 +4 @@', '-x', '+y']], {'hunks': [[4, 1, 4, 1, 2]]}), ('explicit zero count', [['@@ -0,0 +1,2 @@', '+n', '+n']], {'hunks': [[0, 0, 1, 2, 2]]}), ('no-newline marker is not a body line', [['@@ -1 +1 @@', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], {'hunks': [[1, 1, 1, 1, 2]]}), ('empty line tolerated as context', [['@@ -1,3 +1,3 @@', ' a', '', ' c']], {'hunks': [[1, 3, 1, 3, 3]]}), ('truncated hunk', [['@@ -1,3 +1,4 @@', ' a', '+b', ' c']], {'error': 'hunk 0 truncated'}), ('trailing additions after old side is exhausted', [['@@ -2,2 +2,4 @@', ' a', '-b', '+x', '+x', '+x']], {'hunks': [[2, 2, 2, 4, 5]]}), ('two hunks', [['@@ -1,2 +1,1 @@', ' a', '-b', '@@ -9 +8,2 @@', ' z', '+w']], {'hunks': [[1, 2, 1, 1, 2], [9, 1, 8, 2, 2]]})],
    3: [('well-formed hunk', [['--- a/f', '+++ b/f', '@@ -1,3 +1,3 @@', ' a', '-b', '+B', ' c']], {'hunks': [[1, 3, 1, 3, 4]]}), ('omitted counts mean one', [['@@ -4 +4 @@', '-x', '+y']], {'hunks': [[4, 1, 4, 1, 2]]}), ('explicit zero count', [['@@ -0,0 +1,3 @@', '+n', '+n', '+n']], {'hunks': [[0, 0, 1, 3, 3]]}), ('no-newline marker is not a body line', [['@@ -1 +1 @@', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], {'hunks': [[1, 1, 1, 1, 2]]}), ('empty line tolerated as context', [['@@ -1,3 +1,3 @@', ' a', '', ' c']], {'hunks': [[1, 3, 1, 3, 3]]}), ('truncated hunk', [['@@ -1,3 +1,4 @@', ' a', '+b', ' c']], {'error': 'hunk 0 truncated'}), ('trailing additions after old side is exhausted', [['@@ -2,2 +2,5 @@', ' a', '-b', '+x', '+x', '+x', '+x']], {'hunks': [[2, 2, 2, 5, 6]]}), ('two hunks', [['@@ -1,2 +1,1 @@', ' a', '-b', '@@ -9 +8,2 @@', ' z', '+w']], {'hunks': [[1, 2, 1, 1, 2], [9, 1, 8, 2, 2]]})],
    4: [('well-formed hunk', [['--- a/f', '+++ b/f', '@@ -1,3 +1,3 @@', ' a', '-b', '+B', ' c']], {'hunks': [[1, 3, 1, 3, 4]]}), ('omitted counts mean one', [['@@ -4 +4 @@', '-x', '+y']], {'hunks': [[4, 1, 4, 1, 2]]}), ('explicit zero count', [['@@ -0,0 +1,4 @@', '+n', '+n', '+n', '+n']], {'hunks': [[0, 0, 1, 4, 4]]}), ('no-newline marker is not a body line', [['@@ -1 +1 @@', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], {'hunks': [[1, 1, 1, 1, 2]]}), ('empty line tolerated as context', [['@@ -1,3 +1,3 @@', ' a', '', ' c']], {'hunks': [[1, 3, 1, 3, 3]]}), ('truncated hunk', [['@@ -1,3 +1,4 @@', ' a', '+b', ' c']], {'error': 'hunk 0 truncated'}), ('trailing additions after old side is exhausted', [['@@ -2,2 +2,6 @@', ' a', '-b', '+x', '+x', '+x', '+x', '+x']], {'hunks': [[2, 2, 2, 6, 7]]}), ('two hunks', [['@@ -1,2 +1,1 @@', ' a', '-b', '@@ -9 +8,2 @@', ' z', '+w']], {'hunks': [[1, 2, 1, 1, 2], [9, 1, 8, 2, 2]]})],
    5: [('well-formed hunk', [['--- a/f', '+++ b/f', '@@ -1,3 +1,3 @@', ' a', '-b', '+B', ' c']], {'hunks': [[1, 3, 1, 3, 4]]}), ('omitted counts mean one', [['@@ -4 +4 @@', '-x', '+y']], {'hunks': [[4, 1, 4, 1, 2]]}), ('explicit zero count', [['@@ -0,0 +1,5 @@', '+n', '+n', '+n', '+n', '+n']], {'hunks': [[0, 0, 1, 5, 5]]}), ('no-newline marker is not a body line', [['@@ -1 +1 @@', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], {'hunks': [[1, 1, 1, 1, 2]]}), ('empty line tolerated as context', [['@@ -1,3 +1,3 @@', ' a', '', ' c']], {'hunks': [[1, 3, 1, 3, 3]]}), ('truncated hunk', [['@@ -1,3 +1,4 @@', ' a', '+b', ' c']], {'error': 'hunk 0 truncated'}), ('trailing additions after old side is exhausted', [['@@ -2,2 +2,7 @@', ' a', '-b', '+x', '+x', '+x', '+x', '+x', '+x']], {'hunks': [[2, 2, 2, 7, 8]]}), ('two hunks', [['@@ -1,2 +1,1 @@', ' a', '-b', '@@ -9 +8,2 @@', ' z', '+w']], {'hunks': [[1, 2, 1, 1, 2], [9, 1, 8, 2, 2]]})],
}[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
well-formed hunk{'hunks': [[1, 3, 1, 3, 4]]}{'hunks': [[1, 3, 1, 3, 4]]}Passed
omitted counts mean one{'hunks': [[4, 1, 4, 1, 2]]}{'hunks': [[4, 1, 4, 1, 2]]}Passed
explicit zero count{'hunks': [[0, 0, 1, 1, 1]]}{'hunks': [[0, 0, 1, 1, 1]]}Passed
no-newline marker is not a body line{'hunks': [[1, 1, 1, 1, 2]]}{'hunks': [[1, 1, 1, 1, 2]]}Passed
empty line tolerated as context{'error': 'hunk 0 truncated'}{'hunks': [[1, 3, 1, 3, 3]]}Failed
truncated hunk{'error': 'hunk 0 truncated'}{'error': 'hunk 0 truncated'}Passed
trailing additions after old side is exhausted{'hunks': [[2, 2, 2, 3, 4]]}{'hunks': [[2, 2, 2, 3, 4]]}Passed
two hunks{'hunks': [[1, 2, 1, 1, 2], [9, 1, 8, 2, 2]]}{'hunks': [[1, 2, 1, 1, 2], [9, 1, 8, 2, 2]]}Passed

SHA-256 / 72609969ad54b58a465dd6f70556bdec46ae3f09e9a0fd36a089b4f03da6bfed

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import re
N = 1
observations = []
def solve(lines):
    hdr = re.compile(r'^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@')
    hunks = []
    i = 0
    while i < len(lines):
        m = hdr.match(lines[i])
        if not m:
            i += 1
            continue
        os_ = int(m.group(1))
        ol = int(m.group(2)) if m.group(2) is not None else 1
        ns = int(m.group(3))
        nl = int(m.group(4)) if m.group(4) is not None else 1
        need_o, need_n, body = ol, nl, 0
        i += 1
        while (need_o > 0 or need_n > 0) and i < len(lines):
            ln = lines[i]
            if ln.startswith('\\'):
                i += 1
                continue
            t = ln[:1] if ln else '+'
            if t == ' ':
                need_o -= 1
                need_n -= 1
            elif t == '-':
                need_o -= 1
            elif t == '+':
                need_n -= 1
            else:
                break
            body += 1
            i += 1
        if need_o != 0 or need_n != 0:
            return {'error': 'hunk %d truncated' % len(hunks)}
        hunks.append([os_, ol, ns, nl, body])
    return {'hunks': hunks}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('well-formed hunk', [['--- a/f', '+++ b/f', '@@ -1,3 +1,3 @@', ' a', '-b', '+B', ' c']], {'hunks': [[1, 3, 1, 3, 4]]}), ('omitted counts mean one', [['@@ -4 +4 @@', '-x', '+y']], {'hunks': [[4, 1, 4, 1, 2]]}), ('explicit zero count', [['@@ -0,0 +1,1 @@', '+n']], {'hunks': [[0, 0, 1, 1, 1]]}), ('no-newline marker is not a body line', [['@@ -1 +1 @@', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], {'hunks': [[1, 1, 1, 1, 2]]}), ('empty line tolerated as context', [['@@ -1,3 +1,3 @@', ' a', '', ' c']], {'hunks': [[1, 3, 1, 3, 3]]}), ('truncated hunk', [['@@ -1,3 +1,4 @@', ' a', '+b', ' c']], {'error': 'hunk 0 truncated'}), ('trailing additions after old side is exhausted', [['@@ -2,2 +2,3 @@', ' a', '-b', '+x', '+x']], {'hunks': [[2, 2, 2, 3, 4]]}), ('two hunks', [['@@ -1,2 +1,1 @@', ' a', '-b', '@@ -9 +8,2 @@', ' z', '+w']], {'hunks': [[1, 2, 1, 1, 2], [9, 1, 8, 2, 2]]})],
    2: [('well-formed hunk', [['--- a/f', '+++ b/f', '@@ -1,3 +1,3 @@', ' a', '-b', '+B', ' c']], {'hunks': [[1, 3, 1, 3, 4]]}), ('omitted counts mean one', [['@@ -4 +4 @@', '-x', '+y']], {'hunks': [[4, 1, 4, 1, 2]]}), ('explicit zero count', [['@@ -0,0 +1,2 @@', '+n', '+n']], {'hunks': [[0, 0, 1, 2, 2]]}), ('no-newline marker is not a body line', [['@@ -1 +1 @@', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], {'hunks': [[1, 1, 1, 1, 2]]}), ('empty line tolerated as context', [['@@ -1,3 +1,3 @@', ' a', '', ' c']], {'hunks': [[1, 3, 1, 3, 3]]}), ('truncated hunk', [['@@ -1,3 +1,4 @@', ' a', '+b', ' c']], {'error': 'hunk 0 truncated'}), ('trailing additions after old side is exhausted', [['@@ -2,2 +2,4 @@', ' a', '-b', '+x', '+x', '+x']], {'hunks': [[2, 2, 2, 4, 5]]}), ('two hunks', [['@@ -1,2 +1,1 @@', ' a', '-b', '@@ -9 +8,2 @@', ' z', '+w']], {'hunks': [[1, 2, 1, 1, 2], [9, 1, 8, 2, 2]]})],
    3: [('well-formed hunk', [['--- a/f', '+++ b/f', '@@ -1,3 +1,3 @@', ' a', '-b', '+B', ' c']], {'hunks': [[1, 3, 1, 3, 4]]}), ('omitted counts mean one', [['@@ -4 +4 @@', '-x', '+y']], {'hunks': [[4, 1, 4, 1, 2]]}), ('explicit zero count', [['@@ -0,0 +1,3 @@', '+n', '+n', '+n']], {'hunks': [[0, 0, 1, 3, 3]]}), ('no-newline marker is not a body line', [['@@ -1 +1 @@', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], {'hunks': [[1, 1, 1, 1, 2]]}), ('empty line tolerated as context', [['@@ -1,3 +1,3 @@', ' a', '', ' c']], {'hunks': [[1, 3, 1, 3, 3]]}), ('truncated hunk', [['@@ -1,3 +1,4 @@', ' a', '+b', ' c']], {'error': 'hunk 0 truncated'}), ('trailing additions after old side is exhausted', [['@@ -2,2 +2,5 @@', ' a', '-b', '+x', '+x', '+x', '+x']], {'hunks': [[2, 2, 2, 5, 6]]}), ('two hunks', [['@@ -1,2 +1,1 @@', ' a', '-b', '@@ -9 +8,2 @@', ' z', '+w']], {'hunks': [[1, 2, 1, 1, 2], [9, 1, 8, 2, 2]]})],
    4: [('well-formed hunk', [['--- a/f', '+++ b/f', '@@ -1,3 +1,3 @@', ' a', '-b', '+B', ' c']], {'hunks': [[1, 3, 1, 3, 4]]}), ('omitted counts mean one', [['@@ -4 +4 @@', '-x', '+y']], {'hunks': [[4, 1, 4, 1, 2]]}), ('explicit zero count', [['@@ -0,0 +1,4 @@', '+n', '+n', '+n', '+n']], {'hunks': [[0, 0, 1, 4, 4]]}), ('no-newline marker is not a body line', [['@@ -1 +1 @@', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], {'hunks': [[1, 1, 1, 1, 2]]}), ('empty line tolerated as context', [['@@ -1,3 +1,3 @@', ' a', '', ' c']], {'hunks': [[1, 3, 1, 3, 3]]}), ('truncated hunk', [['@@ -1,3 +1,4 @@', ' a', '+b', ' c']], {'error': 'hunk 0 truncated'}), ('trailing additions after old side is exhausted', [['@@ -2,2 +2,6 @@', ' a', '-b', '+x', '+x', '+x', '+x', '+x']], {'hunks': [[2, 2, 2, 6, 7]]}), ('two hunks', [['@@ -1,2 +1,1 @@', ' a', '-b', '@@ -9 +8,2 @@', ' z', '+w']], {'hunks': [[1, 2, 1, 1, 2], [9, 1, 8, 2, 2]]})],
    5: [('well-formed hunk', [['--- a/f', '+++ b/f', '@@ -1,3 +1,3 @@', ' a', '-b', '+B', ' c']], {'hunks': [[1, 3, 1, 3, 4]]}), ('omitted counts mean one', [['@@ -4 +4 @@', '-x', '+y']], {'hunks': [[4, 1, 4, 1, 2]]}), ('explicit zero count', [['@@ -0,0 +1,5 @@', '+n', '+n', '+n', '+n', '+n']], {'hunks': [[0, 0, 1, 5, 5]]}), ('no-newline marker is not a body line', [['@@ -1 +1 @@', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], {'hunks': [[1, 1, 1, 1, 2]]}), ('empty line tolerated as context', [['@@ -1,3 +1,3 @@', ' a', '', ' c']], {'hunks': [[1, 3, 1, 3, 3]]}), ('truncated hunk', [['@@ -1,3 +1,4 @@', ' a', '+b', ' c']], {'error': 'hunk 0 truncated'}), ('trailing additions after old side is exhausted', [['@@ -2,2 +2,7 @@', ' a', '-b', '+x', '+x', '+x', '+x', '+x', '+x']], {'hunks': [[2, 2, 2, 7, 8]]}), ('two hunks', [['@@ -1,2 +1,1 @@', ' a', '-b', '@@ -9 +8,2 @@', ' z', '+w']], {'hunks': [[1, 2, 1, 1, 2], [9, 1, 8, 2, 2]]})],
}[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
well-formed hunk{'hunks': [[1, 3, 1, 3, 4]]}{'hunks': [[1, 3, 1, 3, 4]]}Passed
omitted counts mean one{'hunks': [[4, 1, 4, 1, 2]]}{'hunks': [[4, 1, 4, 1, 2]]}Passed
explicit zero count{'hunks': [[0, 0, 1, 1, 1]]}{'hunks': [[0, 0, 1, 1, 1]]}Passed
no-newline marker is not a body line{'hunks': [[1, 1, 1, 1, 2]]}{'hunks': [[1, 1, 1, 1, 2]]}Passed
empty line tolerated as context{'error': 'hunk 0 truncated'}{'hunks': [[1, 3, 1, 3, 3]]}Failed
truncated hunk{'error': 'hunk 0 truncated'}{'error': 'hunk 0 truncated'}Passed
trailing additions after old side is exhausted{'hunks': [[2, 2, 2, 3, 4]]}{'hunks': [[2, 2, 2, 3, 4]]}Passed
two hunks{'hunks': [[1, 2, 1, 1, 2], [9, 1, 8, 2, 2]]}{'hunks': [[1, 2, 1, 1, 2], [9, 1, 8, 2, 2]]}Passed

SHA-256 / 54458f072270a0bdb3f350839336325b5719c1d862aed0b702d4497ec07057ae

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import re
N = 1
observations = []
def solve(lines):
    hdr = re.compile(r'^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@')
    hunks = []
    i = 0
    while i < len(lines):
        m = hdr.match(lines[i])
        if not m:
            i += 1
            continue
        os_ = int(m.group(1))
        ol = int(m.group(2)) if m.group(2) is not None else 1
        ns = int(m.group(3))
        nl = int(m.group(4)) if m.group(4) is not None else 1
        need_o, need_n, body = ol, nl, 0
        i += 1
        while (need_o > 0 or need_n > 0) and i < len(lines):
            ln = lines[i]
            if ln.startswith('\\'):
                i += 1
                continue
            t = ln[:1] if ln else ' '
            if t == ' ':
                need_o -= 1
                need_n -= 1
            elif t == '-':
                need_o -= 1
            elif t == '+':
                need_n -= 1
            else:
                break
            body += 1
            i += 1
        if need_o != 0 or need_n != 0:
            return {'error': 'hunk %d truncated' % len(hunks)}
        hunks.append([os_, ol, ns, nl, body])
    return {'hunks': hunks}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('well-formed hunk', [['--- a/f', '+++ b/f', '@@ -1,3 +1,3 @@', ' a', '-b', '+B', ' c']], {'hunks': [[1, 3, 1, 3, 4]]}), ('omitted counts mean one', [['@@ -4 +4 @@', '-x', '+y']], {'hunks': [[4, 1, 4, 1, 2]]}), ('explicit zero count', [['@@ -0,0 +1,1 @@', '+n']], {'hunks': [[0, 0, 1, 1, 1]]}), ('no-newline marker is not a body line', [['@@ -1 +1 @@', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], {'hunks': [[1, 1, 1, 1, 2]]}), ('empty line tolerated as context', [['@@ -1,3 +1,3 @@', ' a', '', ' c']], {'hunks': [[1, 3, 1, 3, 3]]}), ('truncated hunk', [['@@ -1,3 +1,4 @@', ' a', '+b', ' c']], {'error': 'hunk 0 truncated'}), ('trailing additions after old side is exhausted', [['@@ -2,2 +2,3 @@', ' a', '-b', '+x', '+x']], {'hunks': [[2, 2, 2, 3, 4]]}), ('two hunks', [['@@ -1,2 +1,1 @@', ' a', '-b', '@@ -9 +8,2 @@', ' z', '+w']], {'hunks': [[1, 2, 1, 1, 2], [9, 1, 8, 2, 2]]})],
    2: [('well-formed hunk', [['--- a/f', '+++ b/f', '@@ -1,3 +1,3 @@', ' a', '-b', '+B', ' c']], {'hunks': [[1, 3, 1, 3, 4]]}), ('omitted counts mean one', [['@@ -4 +4 @@', '-x', '+y']], {'hunks': [[4, 1, 4, 1, 2]]}), ('explicit zero count', [['@@ -0,0 +1,2 @@', '+n', '+n']], {'hunks': [[0, 0, 1, 2, 2]]}), ('no-newline marker is not a body line', [['@@ -1 +1 @@', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], {'hunks': [[1, 1, 1, 1, 2]]}), ('empty line tolerated as context', [['@@ -1,3 +1,3 @@', ' a', '', ' c']], {'hunks': [[1, 3, 1, 3, 3]]}), ('truncated hunk', [['@@ -1,3 +1,4 @@', ' a', '+b', ' c']], {'error': 'hunk 0 truncated'}), ('trailing additions after old side is exhausted', [['@@ -2,2 +2,4 @@', ' a', '-b', '+x', '+x', '+x']], {'hunks': [[2, 2, 2, 4, 5]]}), ('two hunks', [['@@ -1,2 +1,1 @@', ' a', '-b', '@@ -9 +8,2 @@', ' z', '+w']], {'hunks': [[1, 2, 1, 1, 2], [9, 1, 8, 2, 2]]})],
    3: [('well-formed hunk', [['--- a/f', '+++ b/f', '@@ -1,3 +1,3 @@', ' a', '-b', '+B', ' c']], {'hunks': [[1, 3, 1, 3, 4]]}), ('omitted counts mean one', [['@@ -4 +4 @@', '-x', '+y']], {'hunks': [[4, 1, 4, 1, 2]]}), ('explicit zero count', [['@@ -0,0 +1,3 @@', '+n', '+n', '+n']], {'hunks': [[0, 0, 1, 3, 3]]}), ('no-newline marker is not a body line', [['@@ -1 +1 @@', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], {'hunks': [[1, 1, 1, 1, 2]]}), ('empty line tolerated as context', [['@@ -1,3 +1,3 @@', ' a', '', ' c']], {'hunks': [[1, 3, 1, 3, 3]]}), ('truncated hunk', [['@@ -1,3 +1,4 @@', ' a', '+b', ' c']], {'error': 'hunk 0 truncated'}), ('trailing additions after old side is exhausted', [['@@ -2,2 +2,5 @@', ' a', '-b', '+x', '+x', '+x', '+x']], {'hunks': [[2, 2, 2, 5, 6]]}), ('two hunks', [['@@ -1,2 +1,1 @@', ' a', '-b', '@@ -9 +8,2 @@', ' z', '+w']], {'hunks': [[1, 2, 1, 1, 2], [9, 1, 8, 2, 2]]})],
    4: [('well-formed hunk', [['--- a/f', '+++ b/f', '@@ -1,3 +1,3 @@', ' a', '-b', '+B', ' c']], {'hunks': [[1, 3, 1, 3, 4]]}), ('omitted counts mean one', [['@@ -4 +4 @@', '-x', '+y']], {'hunks': [[4, 1, 4, 1, 2]]}), ('explicit zero count', [['@@ -0,0 +1,4 @@', '+n', '+n', '+n', '+n']], {'hunks': [[0, 0, 1, 4, 4]]}), ('no-newline marker is not a body line', [['@@ -1 +1 @@', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], {'hunks': [[1, 1, 1, 1, 2]]}), ('empty line tolerated as context', [['@@ -1,3 +1,3 @@', ' a', '', ' c']], {'hunks': [[1, 3, 1, 3, 3]]}), ('truncated hunk', [['@@ -1,3 +1,4 @@', ' a', '+b', ' c']], {'error': 'hunk 0 truncated'}), ('trailing additions after old side is exhausted', [['@@ -2,2 +2,6 @@', ' a', '-b', '+x', '+x', '+x', '+x', '+x']], {'hunks': [[2, 2, 2, 6, 7]]}), ('two hunks', [['@@ -1,2 +1,1 @@', ' a', '-b', '@@ -9 +8,2 @@', ' z', '+w']], {'hunks': [[1, 2, 1, 1, 2], [9, 1, 8, 2, 2]]})],
    5: [('well-formed hunk', [['--- a/f', '+++ b/f', '@@ -1,3 +1,3 @@', ' a', '-b', '+B', ' c']], {'hunks': [[1, 3, 1, 3, 4]]}), ('omitted counts mean one', [['@@ -4 +4 @@', '-x', '+y']], {'hunks': [[4, 1, 4, 1, 2]]}), ('explicit zero count', [['@@ -0,0 +1,5 @@', '+n', '+n', '+n', '+n', '+n']], {'hunks': [[0, 0, 1, 5, 5]]}), ('no-newline marker is not a body line', [['@@ -1 +1 @@', '-old', '\\ No newline at end of file', '+new', '\\ No newline at end of file']], {'hunks': [[1, 1, 1, 1, 2]]}), ('empty line tolerated as context', [['@@ -1,3 +1,3 @@', ' a', '', ' c']], {'hunks': [[1, 3, 1, 3, 3]]}), ('truncated hunk', [['@@ -1,3 +1,4 @@', ' a', '+b', ' c']], {'error': 'hunk 0 truncated'}), ('trailing additions after old side is exhausted', [['@@ -2,2 +2,7 @@', ' a', '-b', '+x', '+x', '+x', '+x', '+x', '+x']], {'hunks': [[2, 2, 2, 7, 8]]}), ('two hunks', [['@@ -1,2 +1,1 @@', ' a', '-b', '@@ -9 +8,2 @@', ' z', '+w']], {'hunks': [[1, 2, 1, 1, 2], [9, 1, 8, 2, 2]]})],
}[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
well-formed hunk{'hunks': [[1, 3, 1, 3, 4]]}{'hunks': [[1, 3, 1, 3, 4]]}Passed
omitted counts mean one{'hunks': [[4, 1, 4, 1, 2]]}{'hunks': [[4, 1, 4, 1, 2]]}Passed
explicit zero count{'hunks': [[0, 0, 1, 1, 1]]}{'hunks': [[0, 0, 1, 1, 1]]}Passed
no-newline marker is not a body line{'hunks': [[1, 1, 1, 1, 2]]}{'hunks': [[1, 1, 1, 1, 2]]}Passed
empty line tolerated as context{'hunks': [[1, 3, 1, 3, 3]]}{'hunks': [[1, 3, 1, 3, 3]]}Passed
truncated hunk{'error': 'hunk 0 truncated'}{'error': 'hunk 0 truncated'}Passed
trailing additions after old side is exhausted{'hunks': [[2, 2, 2, 3, 4]]}{'hunks': [[2, 2, 2, 3, 4]]}Passed
two hunks{'hunks': [[1, 2, 1, 1, 2], [9, 1, 8, 2, 2]]}{'hunks': [[1, 2, 1, 1, 2], [9, 1, 8, 2, 2]]}Passed

SHA-256 / f7cb408150ea004796feeba53038e7c0c49b22f204a4db846dd0fc151220bea6

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

Case digest / c6fe311a0775cb21acdb0caf2d607671250808f234ac768302ce9ffc2a9cc7e2