fix: extend loopDetection to cover exec tool calls (#34574)#52126
fix: extend loopDetection to cover exec tool calls (#34574)#52126poushwell wants to merge 6 commits into
Conversation
exec is the most dangerous tool type but was not covered by loop detection. 121 identical shell commands produced zero alerts. Extended loop detectors to include exec tool calls. Same thresholds (repeatThreshold: 3, criticalThreshold: 6) now apply to exec. Closes #34574 Made-with: Cursor
Greptile SummaryThis PR extends
Confidence Score: 4/5
Prompt To Fix All With AIThis is a comment left during a code review.
Path: src/agents/tool-loop-detection.test.ts
Line: 290-307
Comment:
**Missing test for the critical escalation path**
The primary behavior this PR adds — exec calls escalating to `critical` at `criticalThreshold` — has no test. The test named "warns for repeated exec calls at repeat threshold" only covers the warning branch (`count: 3` equals `warningThreshold: 3`). A test that passes `count: 6` (equal to `criticalThreshold`) and asserts `level === "critical"` is needed to verify the core fix described in the PR.
```suggestion
it("warns for repeated exec calls at repeat threshold", () => {
const result = detectLoopAfterRepeatedCalls({
toolName: "exec",
toolParams: { command: "ls /tmp" },
result: {
content: [{ type: "text", text: "file-a\nfile-b" }],
details: { status: "completed", exitCode: 0 },
},
count: 3,
config: execThresholdConfig,
});
expect(result.stuck).toBe(true);
if (result.stuck) {
expect(result.level).toBe("warning");
expect(result.detector).toBe("generic_repeat");
}
});
it("escalates exec to critical at criticalThreshold", () => {
const result = detectLoopAfterRepeatedCalls({
toolName: "exec",
toolParams: { command: "ls /tmp" },
result: {
content: [{ type: "text", text: "file-a\nfile-b" }],
details: { status: "completed", exitCode: 0 },
},
count: 6,
config: execThresholdConfig,
});
expect(result.stuck).toBe(true);
if (result.stuck) {
expect(result.level).toBe("critical");
expect(result.detector).toBe("generic_repeat");
expect(result.message).toContain("CRITICAL");
}
});
```
How can I resolve this? If you propose a fix, please make it concise.Last reviewed commit: "fix: extend loopDete..." |
| it("warns for repeated exec calls at repeat threshold", () => { | ||
| const result = detectLoopAfterRepeatedCalls({ | ||
| toolName: "exec", | ||
| toolParams: { command: "ls /tmp" }, | ||
| result: { | ||
| content: [{ type: "text", text: "file-a\nfile-b" }], | ||
| details: { status: "completed", exitCode: 0 }, | ||
| }, | ||
| count: 3, | ||
| config: execThresholdConfig, | ||
| }); | ||
|
|
||
| expect(result.stuck).toBe(true); | ||
| if (result.stuck) { | ||
| expect(result.level).toBe("warning"); | ||
| expect(result.detector).toBe("generic_repeat"); | ||
| } | ||
| }); |
There was a problem hiding this comment.
Missing test for the critical escalation path
The primary behavior this PR adds — exec calls escalating to critical at criticalThreshold — has no test. The test named "warns for repeated exec calls at repeat threshold" only covers the warning branch (count: 3 equals warningThreshold: 3). A test that passes count: 6 (equal to criticalThreshold) and asserts level === "critical" is needed to verify the core fix described in the PR.
| it("warns for repeated exec calls at repeat threshold", () => { | |
| const result = detectLoopAfterRepeatedCalls({ | |
| toolName: "exec", | |
| toolParams: { command: "ls /tmp" }, | |
| result: { | |
| content: [{ type: "text", text: "file-a\nfile-b" }], | |
| details: { status: "completed", exitCode: 0 }, | |
| }, | |
| count: 3, | |
| config: execThresholdConfig, | |
| }); | |
| expect(result.stuck).toBe(true); | |
| if (result.stuck) { | |
| expect(result.level).toBe("warning"); | |
| expect(result.detector).toBe("generic_repeat"); | |
| } | |
| }); | |
| it("warns for repeated exec calls at repeat threshold", () => { | |
| const result = detectLoopAfterRepeatedCalls({ | |
| toolName: "exec", | |
| toolParams: { command: "ls /tmp" }, | |
| result: { | |
| content: [{ type: "text", text: "file-a\nfile-b" }], | |
| details: { status: "completed", exitCode: 0 }, | |
| }, | |
| count: 3, | |
| config: execThresholdConfig, | |
| }); | |
| expect(result.stuck).toBe(true); | |
| if (result.stuck) { | |
| expect(result.level).toBe("warning"); | |
| expect(result.detector).toBe("generic_repeat"); | |
| } | |
| }); | |
| it("escalates exec to critical at criticalThreshold", () => { | |
| const result = detectLoopAfterRepeatedCalls({ | |
| toolName: "exec", | |
| toolParams: { command: "ls /tmp" }, | |
| result: { | |
| content: [{ type: "text", text: "file-a\nfile-b" }], | |
| details: { status: "completed", exitCode: 0 }, | |
| }, | |
| count: 6, | |
| config: execThresholdConfig, | |
| }); | |
| expect(result.stuck).toBe(true); | |
| if (result.stuck) { | |
| expect(result.level).toBe("critical"); | |
| expect(result.detector).toBe("generic_repeat"); | |
| expect(result.message).toContain("CRITICAL"); | |
| } | |
| }); |
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/tool-loop-detection.test.ts
Line: 290-307
Comment:
**Missing test for the critical escalation path**
The primary behavior this PR adds — exec calls escalating to `critical` at `criticalThreshold` — has no test. The test named "warns for repeated exec calls at repeat threshold" only covers the warning branch (`count: 3` equals `warningThreshold: 3`). A test that passes `count: 6` (equal to `criticalThreshold`) and asserts `level === "critical"` is needed to verify the core fix described in the PR.
```suggestion
it("warns for repeated exec calls at repeat threshold", () => {
const result = detectLoopAfterRepeatedCalls({
toolName: "exec",
toolParams: { command: "ls /tmp" },
result: {
content: [{ type: "text", text: "file-a\nfile-b" }],
details: { status: "completed", exitCode: 0 },
},
count: 3,
config: execThresholdConfig,
});
expect(result.stuck).toBe(true);
if (result.stuck) {
expect(result.level).toBe("warning");
expect(result.detector).toBe("generic_repeat");
}
});
it("escalates exec to critical at criticalThreshold", () => {
const result = detectLoopAfterRepeatedCalls({
toolName: "exec",
toolParams: { command: "ls /tmp" },
result: {
content: [{ type: "text", text: "file-a\nfile-b" }],
details: { status: "completed", exitCode: 0 },
},
count: 6,
config: execThresholdConfig,
});
expect(result.stuck).toBe(true);
if (result.stuck) {
expect(result.level).toBe("critical");
expect(result.detector).toBe("generic_repeat");
expect(result.message).toContain("CRITICAL");
}
});
```
How can I resolve this? If you propose a fix, please make it concise.Made-with: Cursor
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6ce51d9129
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| const recentCount = history.filter( | ||
| (h) => h.toolName === toolName && h.argsHash === currentHash, | ||
| ).length; |
There was a problem hiding this comment.
Use consecutive streak for exec critical blocking
The new critical path keys off recentCount, which is the total number of matching exec calls anywhere in the history window, not a consecutive or no-progress streak. Because this commit turns that condition into a hard block, a session can now be stopped after six reused commands even when those calls are interleaved with other work or producing different outputs (for example, periodic exec checks during a long task). This creates false-positive blocks in normal workflows; the critical branch should require consecutive/no-progress evidence before blocking.
Useful? React with 👍 / 👎.
|
Closing this as implemented after Codex review. Current What I checked:
So I’m closing this as already implemented rather than keeping a duplicate issue open. Review notes: reviewed against bc73141e8284; fix evidence: release v2026.4.23, commit a9797214338b. |
What: loopDetection did not escalate to critical for repeated exec calls. 121 identical shell commands = zero critical alerts.
Why: exec is the most dangerous tool type. The generic repeat detector was warn-only for non-poll tools, so criticalThreshold never triggered for exec.
Changes:
Testing:
vitest run src/agents/tool-loop-detection.test.ts— all passedCloses #34574