Skip to content

fix(agents): edit rejects a unique match as ambiguous - #115738

Merged
steipete merged 1 commit into
openclaw:mainfrom
Yigtwxx:fix/edit-exact-match-uniqueness
Jul 29, 2026
Merged

fix(agents): edit rejects a unique match as ambiguous#115738
steipete merged 1 commit into
openclaw:mainfrom
Yigtwxx:fix/edit-exact-match-uniqueness

Conversation

@Yigtwxx

@Yigtwxx Yigtwxx commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes an issue where an agent using the edit tool would have a perfectly unambiguous edit refused with:

Found 2 occurrences of the text in <path>. The text must be unique.
Please provide more context to make it unique.

even though the text it asked to replace occurs exactly once in the file.

The trigger is ordinary: another line in the file is identical to the target except for characters that only matter to fuzzy matching, such as trailing whitespace, a smart quote, an en-dash, or a non-breaking space. Files that mix straight and curly quotes, or that have stray trailing spaces, hit this routinely.

The practical cost falls on the model. It is told to "provide more context", so it retries with a larger oldText, which frequently spans another near-duplicate line and is refused again.

Why This Change Was Made

applyEditsToNormalizedContent locates the edit with fuzzyFindText, which is documented to try an exact match first and only fall back to fuzzy matching. The uniqueness gate immediately below it called countOccurrences, which unconditionally normalizes both sides before counting.

So the match and the safety check ran in two different string spaces. On the exact path the match was found in raw content, while the count was taken after normalization had folded away exactly the distinctions the match had relied on. Any sibling line that is only fuzzily identical inflated the count, and the edit was rejected as ambiguous.

The fix counts in whichever space the match was actually found in, using matchResult.usedFuzzyMatch, which the function already computes and returns. Fuzzy matches keep counting fuzzily, so an edit that really is ambiguous under normalization is still refused. Nothing about matching, normalization, or the error text changes.

User Impact

Agents can now apply an edit whose target text is genuinely unique, even when the file contains near-duplicate lines differing only in trailing whitespace or Unicode punctuation. Ambiguity protection is unchanged for fuzzy matches, so edits that could land in the wrong place are still refused.

Evidence

Two tests were added to src/agents/sessions/tools/edit-diff.test.ts.

The first pins the fix and is load-bearing. Against the unfixed source it fails with the exact defect:

FAIL src/agents/sessions/tools/edit-diff.test.ts
  > applyEditsToNormalizedContent uniqueness
  > replaces an exactly unique match when trailing whitespace makes a sibling line fuzzy-identical
Error: Found 2 occurrences of the text in test.ts. The text must be unique.
 ❯ getDuplicateError src/agents/sessions/tools/edit-diff.ts:428:12
 ❯ applyEditsToNormalizedContent src/agents/sessions/tools/edit-diff.ts:495:13

Test Files  1 failed (1)
     Tests  1 failed | 12 passed (13)

The second is the control case: content where the target is ambiguous only under normalization, and where no exact match exists at all. It asserts the duplicate error is still raised, so the change cannot be read as simply weakening the uniqueness gate.

After the fix, both pass along with the existing suite:

Test Files  1 passed (1)
     Tests  14 passed (14)

oxfmt --check is clean on both touched files.

One note on scope: src/agents/sessions/tools/edit.test.ts has two pre-existing failures in renders previews through custom edit operations. They reproduce identically with this change stashed, so they are unrelated to it and are left alone.

AI-assisted: written and verified with an AI coding agent; the failing-test-first measurement, the control case, and the stashed comparison above were reviewed by me.

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: XS labels Jul 29, 2026
@Yigtwxx
Yigtwxx force-pushed the fix/edit-exact-match-uniqueness branch 2 times, most recently from 995dc10 to b2ee025 Compare July 29, 2026 09:42
The match is found exact-first, but the uniqueness count always ran in the
fuzzy-normalized space. Normalization folds away trailing whitespace, smart
quotes, dashes and NBSP, so lines the exact match had told apart could be
counted as duplicates and a genuinely unique edit was refused.

Count in whichever space the match was actually found in. Fuzzy matches keep
counting fuzzily, so ambiguous fuzzy edits are still refused.
@Yigtwxx
Yigtwxx force-pushed the fix/edit-exact-match-uniqueness branch from b2ee025 to 424b876 Compare July 29, 2026 12:43
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. labels Jul 29, 2026
@clawsweeper

clawsweeper Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 29, 2026, 9:00 AM ET / 13:00 UTC.

ClawSweeper review

What this changes

The PR changes the agent edit tool so a uniquely exact oldText is counted exactly, while fuzzy-found matches continue to use normalized ambiguity counting.

Merge readiness

Blocked until real behavior proof from a real setup is added - 4 items remain

Keep this PR open for normal review. The patch is a focused, plausible repair: it makes the uniqueness check use the same exact-or-fuzzy comparison space that selected the edit, while retaining normalized ambiguity rejection for fuzzy matches. It still needs a rebase against current main and real after-fix behavior proof beyond unit-test output.

Priority: P2
Reviewed head: 424b87668f6feae7be5babaa7e581698e6abea7c

Review scores

Measure Result What it means
Overall readiness 🦪 silver shellfish (2/6) The implementation is focused and has meaningful regression/control tests, but it remains below the merge gate because only test-based proof is supplied.
Proof confidence 🦪 silver shellfish (2/6) Needs real behavior proof before merge: The PR body shows focused test and formatter output, which supports the regression claim but is not after-fix proof from a real agent edit setup; add redacted terminal or live output that shows the edit succeeds. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Needs proof Needs real behavior proof before merge: The PR body shows focused test and formatter output, which supports the regression claim but is not after-fix proof from a real agent edit setup; add redacted terminal or live output that shows the edit succeeds. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed 4 items Focused matching-space repair: The branch changes applyEditsToNormalizedContent so exact matches are counted against raw content and fuzzy matches retain the existing normalized count, directly aligning the duplicate gate with matchResult.usedFuzzyMatch.
Regression and control coverage: The branch adds one test for a raw-exact unique match with a whitespace-normalized sibling and one control test proving an ambiguous fuzzy-only match is still rejected.
Adjacent main-history context: A prior merged repair, #90060, changed fuzzy edit handling in the same function to preserve unrelated lines; this PR should be rebased and its focused test rerun against that current behavior.
Findings None None.
Security None None.

How this fits together

The agent edit tool receives a requested text replacement, locates the requested text through exact-first fuzzy matching, then either applies the replacement or reports an ambiguity error. This change sits between match selection and the safety gate that prevents an edit from targeting multiple locations.

flowchart LR
  A[Agent edit request] --> B[Exact-first text matcher]
  B --> C{Exact or fuzzy match?}
  C -->|Exact| D[Exact occurrence safety check]
  C -->|Fuzzy| E[Normalized occurrence safety check]
  D --> F[Apply edit or report ambiguity]
  E --> F
  F --> G[Updated file content or actionable error]
Loading

Before merge

  • Add real behavior proof - Needs real behavior proof before merge: The PR body shows focused test and formatter output, which supports the regression claim but is not after-fix proof from a real agent edit setup; add redacted terminal or live output that shows the edit succeeds. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
  • Resolve merge risk (P1) - The branch is behind current main, and the same edit-diff function was substantially changed by fix(edit): preserve unrelated lines during fuzzy text matching #90060; rebase and rerun the focused regression/control coverage before merge.
  • Resolve merge risk (P1) - The PR body contains unit-test and formatter output only; external PR policy requires an after-fix real behavior demonstration before merge.
  • Complete next step (P2) - The patch has no concrete code finding, but contributor-supplied real behavior proof and a rebase refresh are required before a merge decision.
Agent review details

Security

None.

PR surface

Source +9, Tests +28. Total +37 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 10 1 +9
Tests 1 28 0 +28
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 38 1 +37

Review metrics

None.

Stored data model

Persistent data-model change detected: serialized state: src/agents/sessions/tools/edit-diff.ts. Confirm migration or upgrade compatibility proof before merge.

Merge-risk options

Maintainer options:

  1. Decide the mitigation before merge
    Rebase onto current main, retain the exact-versus-fuzzy counting split if the focused regression and fuzzy control still pass, and add a redacted terminal recording or live output from an actual agent edit that shows the formerly rejected exact match now succeeds.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Technical review

Best possible solution:

Rebase onto current main, retain the exact-versus-fuzzy counting split if the focused regression and fuzzy control still pass, and add a redacted terminal recording or live output from an actual agent edit that shows the formerly rejected exact match now succeeds.

Do we have a high-confidence way to reproduce the issue?

No high-confidence live reproduction was independently established in this read-only review. The branch supplies a focused source-level reproduction and a control case that clearly describe the exact-versus-fuzzy mismatch.

Is this the best way to solve the issue?

Yes, provisionally: using the same comparison space for match selection and duplicate counting is the narrowest maintainable repair, provided it remains correct after rebasing onto the current fuzzy-edit implementation.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 4624f681add5.

Labels

Label changes:

  • add P2: This is a bounded agent editing reliability fix that can block an edit workflow but has no evidence of data loss, security impact, or core-runtime outage.
  • add rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🐚 platinum hermit.
  • add status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body shows focused test and formatter output, which supports the regression claim but is not after-fix proof from a real agent edit setup; add redacted terminal or live output that shows the edit succeeds. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Label justifications:

  • P2: This is a bounded agent editing reliability fix that can block an edit workflow but has no evidence of data loss, security impact, or core-runtime outage.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🐚 platinum hermit.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body shows focused test and formatter output, which supports the regression claim but is not after-fix proof from a real agent edit setup; add redacted terminal or live output that shows the edit succeeds. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Evidence

What I checked:

Likely related people:

  • steipete: The available history evidence confirms substantial recent maintenance around the agent edit path but did not expose per-line authorship; project-level agent-runtime routing is therefore only a low-confidence fallback. (role: likely agent-runtime decision owner; confidence: low; commits: 2d2ddc43d0dc; files: src/agents/sessions/tools/edit-diff.ts)

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Rebase onto current main and rerun the focused regression and fuzzy-control tests.
  • Add redacted terminal or live output from an actual agent edit that previously produced the duplicate error and now updates the intended file.

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@steipete
steipete merged commit 1ab48a7 into openclaw:main Jul 29, 2026
197 of 202 checks passed
@steipete

Copy link
Copy Markdown
Contributor

Merged via squash.

@Yigtwxx
Yigtwxx deleted the fix/edit-exact-match-uniqueness branch July 29, 2026 16:41
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 30, 2026
The match is found exact-first, but the uniqueness count always ran in the
fuzzy-normalized space. Normalization folds away trailing whitespace, smart
quotes, dashes and NBSP, so lines the exact match had told apart could be
counted as duplicates and a genuinely unique edit was refused.

Count in whichever space the match was actually found in. Fuzzy matches keep
counting fuzzily, so ambiguous fuzzy edits are still refused.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling P2 Normal backlog priority with limited blast radius. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. size: XS status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants