fix(patch): ignore inert context-only hunks (#63678)

This commit is contained in:
Teknium 2026-07-13 02:42:18 -07:00 committed by GitHub
parent b03c94dbed
commit dfeedf613d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 85 additions and 2 deletions

View file

@ -253,8 +253,11 @@ def _validate_operations(
from tools.fuzzy_match import fuzzy_find_and_replace
errors: List[str] = []
real_change_count = 0
for op in operations:
if op.operation != OperationType.UPDATE:
real_change_count += 1
if op.operation == OperationType.UPDATE:
read_result = file_ops.read_file_raw(op.file_path)
if read_result.error:
@ -262,8 +265,15 @@ def _validate_operations(
continue
simulated = read_result.content
for hunk in op.hunks:
for hunk_index, hunk in enumerate(op.hunks, start=1):
search_lines = [l.content for l in hunk.lines if l.prefix in {' ', '-'}]
removed_lines = [l.content for l in hunk.lines if l.prefix == '-']
added_lines = [l.content for l in hunk.lines if l.prefix == '+']
if not removed_lines and not added_lines:
# Models occasionally emit inert anchor hunks between real
# changes. Ignore them without poisoning the atomic patch.
continue
real_change_count += 1
if not search_lines:
# Addition-only hunk: validate context hint uniqueness
if hunk.context_hint:
@ -291,7 +301,7 @@ def _validate_operations(
if count == 0:
label = f"'{hunk.context_hint}'" if hunk.context_hint else "(no hint)"
msg = (
f"{op.file_path}: hunk {label} not found"
f"{op.file_path}: hunk {hunk_index} {label} not found"
+ (f"{match_error}" if match_error else "")
)
try:
@ -325,6 +335,9 @@ def _validate_operations(
# ADD: parent directory creation handled by write_file; no pre-check needed.
if not errors and real_change_count == 0:
errors.append("Patch contains no changes (only context lines were provided)")
return errors
@ -545,6 +558,8 @@ def _apply_update(op: PatchOperation, file_ops: Any) -> Tuple[bool, str, Optiona
elif line.prefix == '+':
replace_lines.append(line.content)
if search_lines and search_lines == replace_lines:
continue
if search_lines:
search_pattern = '\n'.join(search_lines)
replacement = '\n'.join(replace_lines)