fix(tools): treat no-op writes and edits as terminal tool-loop failures (fixes #96983)#97044
Conversation
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
Codex review: needs real behavior proof before merge. Reviewed June 26, 2026, 6:36 PM ET / 22:36 UTC. Summary PR surface: Source +169, Tests +460. Total +629 across 7 files. Reproducibility: yes. source-level reproduction is high confidence: current main allows the reported no-op write/edit/apply_patch behavior, and PR head would skip an exact trailing-whitespace edit because the fuzzy-normalized old/new strings compare equal. Review metrics: 1 noteworthy metric.
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:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Security Review findings
Review detailsBest possible solution: Fix fuzzy no-op classification so exact formatting edits still apply, add latest-head proof for write/edit/apply_patch and the fuzzy edge case, then merge only after maintainers accept the terminal result semantics. Do we have a high-confidence way to reproduce the issue? Yes, source-level reproduction is high confidence: current main allows the reported no-op write/edit/apply_patch behavior, and PR head would skip an exact trailing-whitespace edit because the fuzzy-normalized old/new strings compare equal. Is this the best way to solve the issue? No, not as currently written. The file-tool boundary is the right layer, but fuzzy-equivalent edits should only be terminalized after proving the actual applied content is unchanged or that oldText did not match exactly. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against eba1ca683f6c. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +169, Tests +460. Total +629 across 7 files. View PR surface stats
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
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
c2b4903 to
63000f6
Compare
|
Merged via squash.
|
…es (fixes openclaw#96983) (openclaw#97044) * fix(tools): treat no-op writes and edits as terminal tool-loop failures Fixes openclaw#96983 * fix(tools): treat no-op writes and edits as terminal tool-loop failures Fixes openclaw#96983 * fix(tools): preserve valid sibling edits in mixed no-op batches Fixes openclaw#96983 * fix(tools): terminate apply_patch no-ops safely * fix(tools): validate no-op edits independently * fix(tools): preserve no-op edit overlap checks * fix(tools): preserve no-op patch file formatting * fix(tools): preserve move no-op formatting * fix(tools): narrow same-path move no-op typing * fix(tools): distinguish edit no-op errors * fix(tools): keep edit previews aligned with execution * fix(tools): align no-op validation and formatting * fix(tools): preserve empty patch and preview no-ops * fix(tools): preview fuzzy edit no-ops cleanly * fix(tools): isolate fuzzy-equivalent edit no-ops --------- Co-authored-by: Vincent Koc <[email protected]>
…es (fixes openclaw#96983) (openclaw#97044) * fix(tools): treat no-op writes and edits as terminal tool-loop failures Fixes openclaw#96983 * fix(tools): treat no-op writes and edits as terminal tool-loop failures Fixes openclaw#96983 * fix(tools): preserve valid sibling edits in mixed no-op batches Fixes openclaw#96983 * fix(tools): terminate apply_patch no-ops safely * fix(tools): validate no-op edits independently * fix(tools): preserve no-op edit overlap checks * fix(tools): preserve no-op patch file formatting * fix(tools): preserve move no-op formatting * fix(tools): narrow same-path move no-op typing * fix(tools): distinguish edit no-op errors * fix(tools): keep edit previews aligned with execution * fix(tools): align no-op validation and formatting * fix(tools): preserve empty patch and preview no-ops * fix(tools): preview fuzzy edit no-ops cleanly * fix(tools): isolate fuzzy-equivalent edit no-ops --------- Co-authored-by: Vincent Koc <[email protected]>
…es (fixes openclaw#96983) (openclaw#97044) * fix(tools): treat no-op writes and edits as terminal tool-loop failures Fixes openclaw#96983 * fix(tools): treat no-op writes and edits as terminal tool-loop failures Fixes openclaw#96983 * fix(tools): preserve valid sibling edits in mixed no-op batches Fixes openclaw#96983 * fix(tools): terminate apply_patch no-ops safely * fix(tools): validate no-op edits independently * fix(tools): preserve no-op edit overlap checks * fix(tools): preserve no-op patch file formatting * fix(tools): preserve move no-op formatting * fix(tools): narrow same-path move no-op typing * fix(tools): distinguish edit no-op errors * fix(tools): keep edit previews aligned with execution * fix(tools): align no-op validation and formatting * fix(tools): preserve empty patch and preview no-ops * fix(tools): preview fuzzy edit no-ops cleanly * fix(tools): isolate fuzzy-equivalent edit no-ops --------- Co-authored-by: Vincent Koc <[email protected]>
…es (fixes openclaw#96983) (openclaw#97044) * fix(tools): treat no-op writes and edits as terminal tool-loop failures Fixes openclaw#96983 * fix(tools): treat no-op writes and edits as terminal tool-loop failures Fixes openclaw#96983 * fix(tools): preserve valid sibling edits in mixed no-op batches Fixes openclaw#96983 * fix(tools): terminate apply_patch no-ops safely * fix(tools): validate no-op edits independently * fix(tools): preserve no-op edit overlap checks * fix(tools): preserve no-op patch file formatting * fix(tools): preserve move no-op formatting * fix(tools): narrow same-path move no-op typing * fix(tools): distinguish edit no-op errors * fix(tools): keep edit previews aligned with execution * fix(tools): align no-op validation and formatting * fix(tools): preserve empty patch and preview no-ops * fix(tools): preview fuzzy edit no-ops cleanly * fix(tools): isolate fuzzy-equivalent edit no-ops --------- Co-authored-by: Vincent Koc <[email protected]>
…es (fixes openclaw#96983) (openclaw#97044) * fix(tools): treat no-op writes and edits as terminal tool-loop failures Fixes openclaw#96983 * fix(tools): treat no-op writes and edits as terminal tool-loop failures Fixes openclaw#96983 * fix(tools): preserve valid sibling edits in mixed no-op batches Fixes openclaw#96983 * fix(tools): terminate apply_patch no-ops safely * fix(tools): validate no-op edits independently * fix(tools): preserve no-op edit overlap checks * fix(tools): preserve no-op patch file formatting * fix(tools): preserve move no-op formatting * fix(tools): narrow same-path move no-op typing * fix(tools): distinguish edit no-op errors * fix(tools): keep edit previews aligned with execution * fix(tools): align no-op validation and formatting * fix(tools): preserve empty patch and preview no-ops * fix(tools): preview fuzzy edit no-ops cleanly * fix(tools): isolate fuzzy-equivalent edit no-ops --------- Co-authored-by: Vincent Koc <[email protected]> (cherry picked from commit ab966c2)
What Problem This Solves
Fixes #96983.
When the
writetool is called with content identical to the existing file, or theedittool produces unchanged content, the agent loop treats these as progress and retries the same no-op mutation indefinitely.Why This Change Was Made
readOriginalWriteStatealready detects identical content. Now returns a terminal no-op result withterminate: trueinstead of proceeding with the write.oldText === newTextbefore execution. If all entries are no-op, returns a terminal result. If only some are no-op, the valid sibling replacements still execute normally.No changes madeerror fromedit-diff.tsand converts it to a terminal result.terminate: trueto explicitly signal the tool-loop to stop retrying.Changes Made
src/agents/sessions/tools/write.ts: Return{...textResult(...), terminate: true}when precheck detects identical content.src/agents/sessions/tools/edit.ts: Filter out no-op entries (oldText === newText) before execution, preserving valid sibling edits. CatchNo changes madeerror from edit-diff and return terminal result.src/agents/sessions/tools/write.test.ts: Added 2 regression tests.src/agents/sessions/tools/edit.test.ts: Added 3 regression tests (all no-op, mixed batch, real changes).Evidence
node scripts/run-vitest.mjs run src/agents/sessions/tools/write.test.ts src/agents/sessions/tools/edit.test.ts— 14/14 passedReal behavior proof
Environment: Linux, OpenClaw 2026.6.10, Node 24.13.1
terminate: true, file unchangedterminate: true, file unchangedWhat was not tested: E2E agent loop with LLM calling write/edit (requires real model inference).