| 1 | package agent |
| 2 | |
| 3 | import ( |
| 4 | "testing" |
| 5 | |
| 6 | "reasonix/internal/provider" |
| 7 | ) |
| 8 | |
| 9 | func TestNormalizedFailureRequiresConsecutiveBatches(t *testing.T) { |
| 10 | var loop turnLoopState |
| 11 | call := []provider.ToolCall{{Name: "bash"}} |
| 12 | failure := []toolOutcome{{errMsg: "exit status 255"}} |
| 13 | if consecutiveNormalizedFailure(call, failure, &loop) { |
| 14 | t.Fatal("first failure must not trip") |
| 15 | } |
| 16 | if consecutiveNormalizedFailure(call, []toolOutcome{{}}, &loop) { |
| 17 | t.Fatal("success must reset the category streak") |
| 18 | } |
| 19 | if consecutiveNormalizedFailure(call, failure, &loop) { |
| 20 | t.Fatal("failure after success must start a new streak") |
| 21 | } |
| 22 | } |
| 23 | |
| 24 | func TestNormalizedFailureChecksEveryBatchOutcome(t *testing.T) { |
| 25 | var loop turnLoopState |
| 26 | calls := []provider.ToolCall{{Name: "read_file"}, {Name: "bash"}} |
| 27 | outcomes := []toolOutcome{{}, {errMsg: "exit code: 1"}} |
| 28 | if consecutiveNormalizedFailure(calls, outcomes, &loop) { |
| 29 | t.Fatal("first batch failure must not trip") |
| 30 | } |
| 31 | if !consecutiveNormalizedFailure(calls, outcomes, &loop) { |
| 32 | t.Fatal("repeated failure in the second batch item must trip") |
| 33 | } |
| 34 | } |
| 35 |