fix(agent): prevent mutation verifier false positives from lint diagnostics - #24960
fix(agent): prevent mutation verifier false positives from lint diagnostics#24960zccyman wants to merge 1 commit into
Conversation
…ostics Successful file mutations (write_file, patch) were incorrectly reported as failures when their tool results included nested lint or LSP diagnostics containing "error" or "failed" keys. The generic heuristic in _detect_tool_failure() and classify_tool_failure() searches the entire result string for '"error"' or '"failed"' substrings. For write_file results with bytes_written + lint diagnostics, and patch results with success=true + LSP diagnostics, the nested diagnostic keys matched the heuristic, causing false positive failure classification. Fix: add an early-exit check for write_file and patch tools before the generic heuristic. If the result contains known success markers (bytes_written for write_file, success:true for patch) without a top-level error, return (False, "") immediately. Co-authored-by: _detect_tool_failure mirror in tool_guardrails.py Fixes NousResearch#24927
|
Closing as duplicate of #24929 (also flagged earlier in this thread by @alt-glitch). #24929 was selected for the salvage in #25011 because:
Thanks for the contribution and the fast turnaround on #24927 — the underlying bug is now being addressed via #25011. |
Summary
Fixes #24927
Successful file mutations (
write_file,patch) were incorrectly reported as failures when their tool results included nested lint or LSP diagnostics containing"error"or"failed"keys.Problem
The generic heuristic in
_detect_tool_failure()andclassify_tool_failure()searches the entire result string for'"error"'or'"failed"'substrings. This causes false positives when:{"bytes_written": 100, "lint": {"errors": [{"message": "unused variable", "severity": "error"}]}}— the nested"error"in lint diagnostics triggers the heuristic{"success": true, "diagnostics": {"error": "type mismatch"}}— the nested"error"in LSP diagnostics triggers the heuristicRoot Cause
Both
_detect_tool_failure()inagent/display.pyand its mirrorclassify_tool_failure()inagent/tool_guardrails.pyapply a generic substring heuristic that doesn't account for file-mutation tools returning structured diagnostic payloads alongside success markers.Fix
Added an early-exit check for
write_fileandpatchtools before the generic heuristic:write_file: ifbytes_writtenis present and no top-levelerror→ return successpatch: ifsuccessisTrue→ return success regardless of diagnosticsGenuine failures (top-level
errorkey, or no success markers) still fall through to the heuristic correctly.Testing
Added 12 regression tests across both files:
TestDetectToolFailureintest_display.py(8 tests):TestClassifyToolFailureMutationFalsePositiveintest_tool_guardrails.py(4 tests):All 53 tests pass (41 existing + 12 new), confirming zero regression.
Files Changed
agent/display.py— early-exit for mutation tools in_detect_tool_failure()agent/tool_guardrails.py— matching early-exit inclassify_tool_failure()tests/agent/test_display.py— 8 new teststests/agent/test_tool_guardrails.py— 4 new tests