FA-75761 / Text diff and three-way merge / Open access
Unified hunk parser: the body stops when either side is exhausted · case 01
Hunks ending in additions or removals are reported as truncated.
ROOT CAUSE
The body loop requires both counts to remain positive.
VERIFIED REPAIR
Continue while either side still expects lines.
Unsuccessful approach: Looping only while old lines remain still stops before trailing additions.
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 and 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 | {'error': 'hunk 0 truncated'} | {'hunks': [[4, 1, 4, 1, 2]]} | Failed |
| explicit zero count | {'error': 'hunk 0 truncated'} | {'hunks': [[0, 0, 1, 1, 1]]} | Failed |
| 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 | {'error': 'hunk 0 truncated'} | {'hunks': [[2, 2, 2, 3, 4]]} | Failed |
| two hunks | {'error': 'hunk 0 truncated'} | {'hunks': [[1, 2, 1, 1, 2], [9, 1, 8, 2, 2]]} | Failed |
SHA-256 / 86f4b297aa7b70669678bf9f11dc5bd5186b377b995fc63f14e5e3899cc5ae38
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 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 | {'error': 'hunk 0 truncated'} | {'hunks': [[4, 1, 4, 1, 2]]} | Failed |
| explicit zero count | {'error': 'hunk 0 truncated'} | {'hunks': [[0, 0, 1, 1, 1]]} | Failed |
| 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 | {'error': 'hunk 0 truncated'} | {'hunks': [[2, 2, 2, 3, 4]]} | Failed |
| two hunks | {'error': 'hunk 1 truncated'} | {'hunks': [[1, 2, 1, 1, 2], [9, 1, 8, 2, 2]]} | Failed |
SHA-256 / c2d2f4ad8e2e3d12c0577a9b4b4ed4a9bfbb228add211b5c1de19826fcb9079b
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.776085+00:00.
Case digest / 6c4ab5656eba8f0f0d1ccc3cd9868b4ee465ffb6793703d6319a62546a83af07