@@ -424,20 +424,34 @@ describe("resolveAttemptFsWorkspaceOnly", () => {
|
424 | 424 | }); |
425 | 425 | |
426 | 426 | describe("resolveUnknownToolGuardThreshold", () => { |
427 | | -it("returns undefined when loop detection is disabled", () => { |
428 | | -expect(resolveUnknownToolGuardThreshold({ enabled: false, unknownToolThreshold: 4 })).toBe( |
429 | | -undefined, |
430 | | -); |
431 | | -expect(resolveUnknownToolGuardThreshold(undefined)).toBe(undefined); |
| 427 | +it("returns the default threshold when no loop-detection config is provided", () => { |
| 428 | +expect(resolveUnknownToolGuardThreshold(undefined)).toBe(10); |
| 429 | +expect(resolveUnknownToolGuardThreshold({})).toBe(10); |
432 | 430 | }); |
433 | 431 | |
434 | | -it("uses the default threshold when loop detection is enabled without an override", () => { |
435 | | -expect(resolveUnknownToolGuardThreshold({ enabled: true })).toBe(10); |
| 432 | +it("stays on even when tools.loopDetection.enabled is false (safety net)", () => { |
| 433 | +// The unknown-tool guard has no false-positive surface — the tool is |
| 434 | +// objectively not registered — so it is always on regardless of the |
| 435 | +// opt-in genericRepeat/pingPong/pollNoProgress detectors. |
| 436 | +expect(resolveUnknownToolGuardThreshold({ enabled: false })).toBe(10); |
| 437 | +expect(resolveUnknownToolGuardThreshold({ enabled: false, unknownToolThreshold: 3 })).toBe(3); |
436 | 438 | }); |
437 | 439 | |
438 | 440 | it("uses the configured threshold override when provided", () => { |
439 | 441 | expect(resolveUnknownToolGuardThreshold({ enabled: true, unknownToolThreshold: 4 })).toBe(4); |
440 | 442 | }); |
| 443 | + |
| 444 | +it("falls back to the default threshold when the override is non-positive", () => { |
| 445 | +expect(resolveUnknownToolGuardThreshold({ unknownToolThreshold: 0 })).toBe(10); |
| 446 | +expect(resolveUnknownToolGuardThreshold({ unknownToolThreshold: -5 })).toBe(10); |
| 447 | +expect( |
| 448 | +resolveUnknownToolGuardThreshold({ unknownToolThreshold: Number.NaN }), |
| 449 | +).toBe(10); |
| 450 | +}); |
| 451 | + |
| 452 | +it("floors fractional overrides", () => { |
| 453 | +expect(resolveUnknownToolGuardThreshold({ unknownToolThreshold: 3.7 })).toBe(3); |
| 454 | +}); |
441 | 455 | }); |
442 | 456 | |
443 | 457 | describe("wrapStreamFnTrimToolCallNames", () => { |
|