FA-75751 / Text diff and three-way merge / Open access
Unified hunk parser: no-newline markers end the hunk body · case 01
Patches touching a last line without newline are reported as truncated.
ROOT CAUSE
Marker lines are not skipped, so they fall into the "anything else" branch and stop the body.
VERIFIED REPAIR
Skip "\\" marker lines without counting them.
Unsuccessful approach: Skipping markers but counting them in the body length misreports the hunk size.
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]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| 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 | {'error': 'hunk 0 truncated'} | {'hunks': [[1, 1, 1, 1, 2]]} | Failed |
| 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 / 5faf733c08a1fe88b1d6796745b52e13bc8d3353edb9c01d608ac645a69cb3fd
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
body += 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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| 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, 3]]} | {'hunks': [[1, 1, 1, 1, 2]]} | Failed |
| 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 / b06d8855db56c5f90895db189af3ba172cab6227d76cd1759f04ef56527f4d7c
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| 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.706795+00:00.
Case digest / c40ba733472727774295cee365fb38042a5c2c1462f4758e9dc0ec75ec16fc86