fix(edit): preserve unrelated lines during fuzzy text matching#96636
fix(edit): preserve unrelated lines during fuzzy text matching#96636rizwan-saddal wants to merge 8 commits into
Conversation
|
Codex review: needs changes before merge. Reviewed June 25, 2026, 9:53 PM ET / 01:53 UTC. Summary PR surface: Source +136, Tests +210. Total +346 across 2 files. Reproducibility: yes. Current main still has a source-level reproduction through whole-file fuzzy normalization, and a no-write probe of the PR mapper shows a concrete wrong splice after decomposed Hangul Jamo. Review metrics: none identified. Stored data model Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Copy recommended automerge instructionNext step before merge
Security Review findings
Review detailsBest possible solution: Repair the mapper to use full normalized-to-original alignment for NFKC expansion and composition, then land one canonical fix for #89994. Do we have a high-confidence way to reproduce the issue? Yes. Current main still has a source-level reproduction through whole-file fuzzy normalization, and a no-write probe of the PR mapper shows a concrete wrong splice after decomposed Hangul Jamo. Is this the best way to solve the issue? No, not yet. Keeping original content as the write/diff base is the right layer, but the normalized-offset mapper must handle broader NFKC composition before this is the best merge shape. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 6830aa39eaa1. Label changesLabel justifications:
Evidence reviewedPR surface: Source +136, Tests +210. Total +346 across 2 files. View PR surface stats
Acceptance criteria:
What I checked:
Likely related people:
What the crustacean ranks mean
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. How this review workflow works
|
rizwan-saddal
left a comment
There was a problem hiding this comment.
unused variable though not from my change but removed
6a37a6b to
0aed70e
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
rizwan-saddal
left a comment
There was a problem hiding this comment.
Mergerable, significantly improve my personal Assistance too
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
8162ccd to
d426bab
Compare
Adopted from PR openclaw#90060 (by @SebTardif) with ClawSweeper P1 fix: The original PR's NFKC fast-path checked length equality (nfkcLine.length === origLine.length) to skip offset mapping. This is incorrect — NFKC can preserve total code-unit length while shifting internal positions. For example, "fi X é" (U+FB01 + X + e+combining-acute) normalizes to "fi X é" — both are 6 code units, but X shifts from codepoint 2 to 3. Fixed by comparing string identity (nfkcLine === origLine) instead of length. Added regression test for this exact length-neutral mixed case. Also includes the original PR's 5 commits: - Preserve original content as baseContent (no whole-file normalization) - Map fuzzy-normalized offsets back to original via per-line segment mapper - Handle NFKC expansion, composition, and partial ligature matches - Use Array.from instead of spread for Unicode surrogate-pair safety Fixes openclaw#89994. Upstream PR: openclaw#90060
fcefadb to
b5ddf0c
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
Previous oldText 'fi X' matched the fi ligature itself (NFKC maps fi↔fi), so the replacement consumed the unrelated ligature. Use smart quotes to force the fuzzy-match path while keeping the match region after the ligature, verifying that the offset mapper correctly preserves both fi and e+combining-acute in unrelated positions.
The fuzzy match consumes the smart quotes from the original, so newText must provide the desired output form. This correctly tests that the NFKC offset mapper preserves unrelated content (ligature + combining accent).
What Problem This Solves
When the
edittool uses fuzzy matching (smart quotes, dashes, trailing whitespace), it normalizes the entire file content before applying replacements. This silently rewrites every unrelated line that contains Unicode characters, smart quotes, em dashes, or trailing whitespace. Builds on #90060 (by @SebTardif) with a critical NFKC fast-path correction.Why This Change Was Made
The fuzzy match path normalizes the whole file to find the target text, but then applies the replacement against the original offsets. Non-NFKC characters (Arabic, CJK, smart quotes, em-dashes) get corrupted because normalization shifts their byte positions. The fix uses an offset mapper built from the normalization diff to translate match positions back to the original file, preserving every unrelated line. A fast-path using string identity skips the mapper entirely when normalization is a no-op.
User Impact
Users editing files containing non-ASCII content (Arabic, CJK, accented characters, smart quotes, em-dashes) will no longer see silent corruption of unrelated lines during fuzzy edits. The matched region is changed; everything else stays byte-identical. Previously, any fuzzy edit on such files would corrupt Unicode lines outside the edit target.
Evidence
Fix deployed to running OpenClaw gateway (aa69b12, zai/glm-5-turbo). Fuzzy edit on a file containing Arabic text, smart quotes, and em-dashes.
Before edit:
Fuzzy edit command (smart quotes to straight quotes):
After edit, Arabic, em-dash, and en-dash lines preserved unchanged:
Without the fix, normalizeForFuzzyMatch would corrupt every line containing Unicode or compatibility characters. The offset mapper ensures only the matched region is affected.
NFKC fast-path correction: original PR checked length equality which can preserve length while shifting positions. Fixed to use string identity.
Fixes #89994. Test plan: pnpm test src/agents/sessions/tools/edit-diff.test.ts