feat(session): inject debugging-loop hint when the same shell command keeps failing - #39990
feat(session): inject debugging-loop hint when the same shell command keeps failing#39990openchat-ai wants to merge 2 commits into
Conversation
|
The following comment was made by an LLM, it may be inaccurate: Based on my search results, here are potentially related PRs: Related PR:
Adjacent Feature:
The current PR (#39990) appears to be the primary implementation for this feature. PR #37110 may have related logic worth cross-referencing, and #39982 appears to be a complementary enhancement for shell command error handling. |
There was a problem hiding this comment.
Pull request overview
Adds a session-level loop detector to inject a debugging hint when repeated shell command failures indicate the model may be stuck iterating at the same hypothesis layer, integrating it into the main session prompt loop and covering the behavior with unit tests.
Changes:
- Introduces
LoopDetection.apply(...)to scan prior tool calls and inject a synthetic “examine the evidence” hint after repeated failures of the same command. - Wires loop detection into the session prompt loop alongside existing reminder injection.
- Adds a unit test suite exercising the injection/no-injection and idempotence behaviors.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| packages/opencode/src/session/loop-detection.ts | Implements failure counting and synthetic hint injection logic. |
| packages/opencode/src/session/prompt.ts | Invokes loop detection during prompt construction. |
| packages/opencode/test/session/loop-detection.test.ts | Adds tests for repeated-failure detection and injection behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| type: "tool", | ||
| callID: `call_${id}`, | ||
| tool: "shell", | ||
| state: { |
| Effect.provideService(FSUtil.Service, fsys), | ||
| Effect.provideService(Session.Service, sessions), | ||
| ) | ||
| LoopDetection.apply(msgs) |
| for (const msg of messages) { | ||
| if (msg.info.role !== "assistant") continue | ||
| for (const part of msg.parts) { | ||
| if (part.type !== "tool" || part.tool !== "shell" || part.state.status !== "completed") continue |
LoopDetection checked part.tool === "shell" but the shell tool's real id is "bash" (ShellID.ToolID), so the detector never counted real shell failures and the hint was never injected. Test fixtures had the same wrong id, so the suite passed while the feature was broken in production. - match on ShellID.ToolID in loop-detection.ts - assign the apply() return value at the prompt call site - use "bash" in loop-detection test fixtures
|
Hi there! First-time contributor here, and I noticed the CI checks on this PR are currently waiting for approval to run (they show as action_required). I'd be grateful if you could approve the workflow run whenever you have a moment — no rush at all. Happy to make any adjustments if needed, thanks! |
Issue for this PR
Closes #39772
Type of change
What does this PR do?
Part of #39772 (debugging loop detection). When the same shell command fails repeatedly (non-zero exit code) across a conversation, the model is likely cycling through hypotheses at the same layer - edit source, re-run, see the same failure - without descending to the actual evidence.
This PR adds a session-loop detector that runs alongside the existing reminders in the main prompt loop. After a shell command has failed 2+ times, it injects a synthetic hint into the last user message telling the model to stop proposing another hypothesis and instead examine the concrete evidence: the command's own error output, logs, core dumps, or traces.
Detection is keyed on the exact command string, only counts completed (non-aborted) shell tool calls, ignores successful runs, and is idempotent (the hint is only injected once).
How did you verify your code works?
Added a unit test suite in \ est/session/loop-detection.test.ts\ covering: injection at 2 failures, no injection at 1 failure, no re-injection on later steps, ignoring successful commands, independent per-command tracking, and the no-user-message case. All 6 pass. \�un typecheck\ passes.
The pre-existing failures in \ est/session/instruction.test.ts\ and compaction tests reproduce on clean \origin/dev\ and are unrelated.
Screenshots / recordings
N/A
Checklist