Problem
When a model's str_replace old_string does not match, the tool already shows an anchor snippet of the actual file text and a writeFileHint (which is suppressed for large files). Some models ignore this and hammer str_replace until the RepeatedToolCall stuck-loop detector force-terminates the run as INCOMPLETE.
Observed live (dogfooding Qwopus3.6-35B-A3B-Coder-MTP on the Strix): three runs of #850 all INCOMPLETE'd via RepeatedToolCall, with 12-30 str_replace calls returning "not found". Three system-prompt nudges (re-read-before-edit, prefer write_file, converge-and-submit) did not fix it - the model ignored the prompt. The fix has to be harness-enforced in the tool, not prompted.
This is the highest-leverage lever for the "swap in any better local model" goal: a model weak at surgical edits should still be able to land changes deterministically, without per-model prompt tuning.
Proposed fix
Track consecutive str_replace failures per file in the tool (per-run state; StrReplaceTool is instantiated per workspace). On the 2nd+ consecutive failure for a file, escalate the failure result:
- a strong directive: "you have failed to str_replace this file N times; stop calling str_replace on it";
- for reasonably-sized files, the full numbered current content, so the model can
write_file the whole corrected file with zero guesswork (this also fixes the large-file gap where writeFileHint currently returns nothing).
Reset the counter on any successful edit to that file. Model-agnostic; extends the #942/#944 recovery work into a deterministic escape hatch.
Acceptance
- A single failure keeps the current anchor-context hint (unchanged).
- The 2nd+ consecutive failure on a file returns an escalated message with the full file content + a
write_file directive.
- A successful edit resets the counter.
- Unit-tested.
Problem
When a model's
str_replaceold_stringdoes not match, the tool already shows an anchor snippet of the actual file text and awriteFileHint(which is suppressed for large files). Some models ignore this and hammerstr_replaceuntil theRepeatedToolCallstuck-loop detector force-terminates the run as INCOMPLETE.Observed live (dogfooding Qwopus3.6-35B-A3B-Coder-MTP on the Strix): three runs of #850 all INCOMPLETE'd via
RepeatedToolCall, with 12-30str_replacecalls returning "not found". Three system-prompt nudges (re-read-before-edit, prefer write_file, converge-and-submit) did not fix it - the model ignored the prompt. The fix has to be harness-enforced in the tool, not prompted.This is the highest-leverage lever for the "swap in any better local model" goal: a model weak at surgical edits should still be able to land changes deterministically, without per-model prompt tuning.
Proposed fix
Track consecutive
str_replacefailures per file in the tool (per-run state;StrReplaceToolis instantiated per workspace). On the 2nd+ consecutive failure for a file, escalate the failure result:write_filethe whole corrected file with zero guesswork (this also fixes the large-file gap wherewriteFileHintcurrently returns nothing).Reset the counter on any successful edit to that file. Model-agnostic; extends the #942/#944 recovery work into a deterministic escape hatch.
Acceptance
write_filedirective.