Skip to content

fix: stop spinner on failed file edits and add re-anchor experiment (#12032)#12033

Draft
roomote-v0[bot] wants to merge 1 commit intomainfrom
fix/12032-spinner-on-failed-edit-and-reanchor
Draft

fix: stop spinner on failed file edits and add re-anchor experiment (#12032)#12033
roomote-v0[bot] wants to merge 1 commit intomainfrom
fix/12032-spinner-on-failed-edit-and-reanchor

Conversation

@roomote-v0
Copy link
Copy Markdown
Contributor

@roomote-v0 roomote-v0 bot commented Mar 29, 2026

Summary

This PR attempts to address Issue #12032. Feedback and guidance are welcome.

Part 1: Fix spinner stuck on failed file edits (UI bug)

Problem: When a file edit tool (e.g., apply_diff) fails due to LLM hallucination, the loading spinner at the top of the UI keeps spinning indefinitely. This happens because handlePartial() creates a partial ask message during streaming, but when the edit fails in execute(), no code finalizes (closes) that partial ask message.

Fix:

  • ApplyDiffTool: Added finalizePartialToolAskIfNeeded() helper (matching the pattern already in EditFileTool) that closes any outstanding partial ask message on error paths. Added didSendPartialToolAsk and partialToolAskRelPath tracking properties, set in handlePartial().
  • ApplyDiffTool: Always show diff_error message on every failure (previously only shown on 2nd consecutive failure), giving immediate visual feedback.
  • ApplyDiffTool: Set didToolFailInCurrentTurn = true on diff apply failure for consistency.
  • EditFileTool: Always show diff_error message on every failure (previously only shown on 2nd consecutive failure).

Part 2: Re-anchor before edit experiment

Problem: LLMs hallucinate file contents when editing, especially for longer files or after many conversation turns. The issue author reports this can be architecturally solved in 80%+ of cases by requiring a re-read step before every edit.

Solution: Added a new experimental setting reAnchorBeforeEdit that, when enabled, adds a system prompt guideline instructing the model to always re-read a file (using read_file) immediately before editing it. This uses more tokens but significantly reduces hallucination-based edit failures.

Changes:

  • packages/types/src/experiment.ts: Added reAnchorBeforeEdit to experiment IDs and schema
  • src/shared/experiments.ts: Added RE_ANCHOR_BEFORE_EDIT config (default: off)
  • src/core/prompts/sections/tool-use-guidelines.ts: Accepts experiments config, adds re-anchoring instruction when enabled
  • src/core/prompts/system.ts: Passes experiments to getToolUseGuidelinesSection()
  • webview-ui/src/i18n/locales/en/settings.json: Added localization keys
  • Settings UI auto-renders via existing ExperimentalSettings component

Tests

  • Updated editFileTool.spec.ts to reflect that diff_error is now shown on every failure
  • Updated experiments.spec.ts with new experiment tests
  • Added tool-use-guidelines.spec.ts to verify re-anchor guideline behavior

All existing and new tests pass. Lint and type checks pass.

Interactively review PR in Roo Code Cloud

…12032)

Part 1 - UI Bug Fix:
- ApplyDiffTool: Add finalizePartialToolAskIfNeeded to close partial ask
  messages on error paths, preventing stuck spinners
- ApplyDiffTool: Always show diff_error on first failure (was >= 2)
- ApplyDiffTool: Set didToolFailInCurrentTurn on diff apply failure
- EditFileTool: Always show diff_error on first failure (was >= 2)

Part 2 - Re-anchor Before Edit Experiment:
- Add reAnchorBeforeEdit experiment type to packages/types
- Add RE_ANCHOR_BEFORE_EDIT to shared experiments config (default off)
- When enabled, adds system prompt guideline instructing the model to
  re-read a file before every edit to reduce hallucination-based failures
- Add English localization keys for settings UI
- Settings UI auto-renders via existing ExperimentalSettings component
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant