anomalyco / anomalyco/opencode

edit fuzzy replacers can bypass multiple-match ambiguity when equivalent candidates differ in whitespace

Open
#41,872 0 comments 0 reactions 1 assignee View on GitHub

@jlongster is already working on this.

Since Aug 11, 2026.

Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

Description

The fuzzy edit replacement pipeline can commit one candidate before discovering that another semantically equivalent candidate also matches the requested oldString.

Verified in current dev SHA d4704347465c1ee63d0c213ed00e648e7f0231c5 and the local checkout b9f3b382fc.

replace() iterates each string yielded by a replacer and immediately returns when that concrete string is byte-unique in content:

for (const search of replacer(content, oldString)) {
  const index = content.indexOf(search)
  ...
  const lastIndex = content.lastIndexOf(search)
  if (index !== lastIndex) continue
  return content.substring(0, index) + newString + content.substring(index + search.length)
}

But fuzzy replacers such as WhitespaceNormalizedReplacer can yield different concrete strings for multiple equivalent matches. Example content:

alpha   beta
alpha\tbeta

with oldString = "alpha beta" and default replaceAll=false:

  • both lines normalize to the same requested text;
  • the replacer yields "alpha beta" and "alpha\tbeta";
  • the first yielded concrete string is byte-unique, so replace() edits it immediately;
  • the second semantic candidate is never considered, so the normal “Found multiple matches... provide more surrounding context” safeguard is bypassed.

The same pattern can affect other replacers that yield distinct concrete spans for one fuzzy query.

Expected behavior:

  • resolve all candidates for a matching strategy before committing;
  • deduplicate by span/location, not just concrete matched bytes;
  • if more than one candidate survives and replaceAll=false, reject as ambiguous and ask for more context;
  • preserve the current disproportionate-match guard;
  • add regression tests with whitespace/indentation/escape variants that are textually different but semantically equivalent under the selected replacer.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.