NousResearch/hermes-agent
Fuzzy match deletes boundary space in replacements
Cluster 52491. Data as of
Nothing open on GitHub. Fix merged in #52678. Check it covers your case.
The short answer
0open issues
0open PRs
5items grouped
- Known?
- Yes. 5 related items grouped here, 1 issue already closed.
- Fix event
- A fix was merged to main in PR #52678. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
resolved, deciding PR #52678. That is separate from the fix event. - Still open
- Nothing open on GitHub.
A bug where whitespace-normalized fuzzy matching silently drops the boundary space after a match during str_replace or patch operations. Multiple fix attempts address preserving that boundary space in fuzzy replacements.
Open issues0
Open PRs0
Fixes on record
-
#52678 fix(fuzzy-match): preserve boundary space after whitespace-normalized match (#52491)
files:
tests/tools/test_fuzzy_match.py,tools/fuzzy_match.pyShow the diff
-
tests/tools/test_fuzzy_match.py@@ -43,6 +43,47 @@ def test_extra_spaces_match(self): assert count == 1 assert "bar" in new + def test_boundary_space_preserved_after_match(self): + """Regression: whitespace_normalized match ending with a non-space + character must NOT consume the word-boundary space that follows. + https://github.com/NousResearch/hermes-agent/issues/52491""" + # Case 1 — simple word boundary + new, count, strategy, err = fuzzy_find_and_replace( + "foo bar baz", "foo bar", "XY", + ) + assert err is None + assert count == 1 + assert strategy == "whitespace_normalized" + assert new == "XY baz", f"Boundary space deleted: {new!r}" + + def test_boundary_space_preserved_in_code_edit(self): + """Regression: real-world code-edit scenario where the space before + the next operator must survive a whitespace-normalized match.""" + content = "result = compute(a, b) + tail" + new, count, strategy, err = fuzzy_find_and_replace( + content, "compute(a, b)", "compute(a, b, c)", + ) + assert err is None + assert count == 1 + assert strategy == "whitespace_normalized" + assert new == "result = compute(a, b, c) + tail", f"Boundary space deleted: {new!r}" + + def test_trailing_ws_still_consumed_when_match_ends_with_space(self): + """When the normalized match itself ends with whitespace (pattern has + trailing space), the expansion must still consume the full whitespace + run in the original.""" + # Use a pattern with trailing space where the boundary is clear: + # content has "foo " then "bar", pattern is "foo " — the match + # should cover all 3 original spaces (the trailing ws run). + new, count, strategy, err = fuzzy_find_and_replace( + "a = foo + bar", "foo +", "XY", + ) + assert err is None + assert count == 1 + # "foo +" normalized to "foo +" matches; trailing spaces consumed + # Result: "a = XY bar" + assert "XY" in new and "bar" in new + class TestIndentDifference: def test_different_indentation(self): -
tools/fuzzy_match.py@@ -768,9 +768,14 @@ def _map_normalized_positions(original: str, normalized: str, else: orig_end = orig_start + (norm_end - norm_start) - # Expand to include trailing whitespace that was normalized - while orig_end < len(original) and original[orig_end] in ' \t': - orig_end += 1 + # Expand to include trailing whitespace that was normalized, + # but only when the normalized match itself ended with whitespace. + # When the match ends with a non-space character, the first + # whitespace in the original is a word boundary and must not be + # consumed. See https://github.com/NousResearch/hermes-agent/issues/52491 + if norm_end < len(normalized) and normalized[norm_end - 1] == ' ': + while orig_end < len(original) and original[orig_end] in ' \t': + orig_end += 1 original_matches.append((orig_start, min(orig_end, len(original))))
-
3 PRs closed without merging
From the close comments: duplicate 1 · superseded by another PR 1 · other 1
-
#52502 fix(fuzzy-match): preserve boundary space after whitespace-normalized match (#52491) · other →
#52678 -
#52513 fix(tools): preserve word-boundary space in whitespace-normalized edits · superseded by another PR →
#52678,#52502 -
#52861 fix(tools): preserve boundary spaces in fuzzy replacements · duplicate →
#52678,#52491
Closed issues · 1
- Closed#52491[Bug]: Fuzzy whitespace-normalized edit silently deletes the boundary space after a match (str_replace / patch corrupts file)
How this cluster was grouped
-
Link evidence (
structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference. -
Pairwise link density
0.40: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the LabAt a glance
- Merged PRs
- #52678
- Closed issues
- 1
- Attempts
- 3 PRs closed without merging
- Fix link checked
- 26 Jun 2026