From bac71f4654dfcab48d0b1be20ef34917e86a9549 Mon Sep 17 00:00:00 2001 From: roboomp Date: Sat, 25 Jul 2026 12:05:54 +0000 Subject: [PATCH] fix(coding-agent): stopped blocked vibe reset loops Disable reset-mode loops when vibe mode prevents the required session transition, so the prompt is not resubmitted into the unchanged session. Added focused regression coverage for the blocked transition. Fixes #6607 --- packages/coding-agent/CHANGELOG.md | 2 +- .../src/modes/interactive-mode.ts | 5 +++++ .../test/interactive-mode-loop.test.ts | 19 +++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 224595f77..2d63cc570 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -4,7 +4,7 @@ ### Fixed -- Fixed `/new`, `/drop`, `/fork`, and `/move` crashing or doing unnecessary work when invoked during vibe mode; interactive session transitions now show the existing exit-vibe warning and leave the session unchanged ([#6607](https://github.com/can1357/oh-my-pi/issues/6607)). +- Fixed `/new`, `/drop`, `/fork`, and `/move` crashing or doing unnecessary work when invoked during vibe mode; interactive session transitions now show the existing exit-vibe warning and leave the session unchanged, and reset loops disable themselves instead of resubmitting into that unchanged session ([#6607](https://github.com/can1357/oh-my-pi/issues/6607)). ## [17.1.3] - 2026-07-24 diff --git a/packages/coding-agent/src/modes/interactive-mode.ts b/packages/coding-agent/src/modes/interactive-mode.ts index 45544a487..9c4b718ab 100644 --- a/packages/coding-agent/src/modes/interactive-mode.ts +++ b/packages/coding-agent/src/modes/interactive-mode.ts @@ -1395,6 +1395,11 @@ export class InteractiveMode implements InteractiveModeContext { return; } + if (action === "reset" && this.vibeModeEnabled) { + this.disableLoopMode("Exit vibe mode before using reset loops. Loop mode disabled."); + return; + } + if (!consumeLoopLimitIteration(this.loopLimit)) { this.disableLoopMode("Loop limit reached. Loop mode disabled."); return; diff --git a/packages/coding-agent/test/interactive-mode-loop.test.ts b/packages/coding-agent/test/interactive-mode-loop.test.ts index 032f9b53f..bdd9d31a4 100644 --- a/packages/coding-agent/test/interactive-mode-loop.test.ts +++ b/packages/coding-agent/test/interactive-mode-loop.test.ts @@ -138,6 +138,25 @@ describe("InteractiveMode loop auto-submit", () => { expect(resolved[0].text).toBe("deliver this"); }); + it("disables reset loops when vibe blocks the session transition", async () => { + vi.useFakeTimers(); + settings.set("loop.mode", "reset"); + mode.vibeModeEnabled = true; + mode.loopModeEnabled = true; + mode.loopPrompt = "do not resubmit"; + const showStatus = vi.spyOn(mode, "showStatus"); + const resolved: SubmittedUserInput[] = []; + void mode.getUserInput().then(input => resolved.push(input)); + + vi.advanceTimersByTime(800); + await flushMicrotasks(); + + expect(resolved).toHaveLength(0); + expect(mode.loopModeEnabled).toBe(false); + expect(mode.loopPrompt).toBeUndefined(); + expect(showStatus).toHaveBeenCalledWith("Exit vibe mode before using reset loops. Loop mode disabled."); + }); + it("reports waiting, running, paused, resumed, and disabled loop states", async () => { const setLoopModeStatus = vi.spyOn(mode.statusLine, "setLoopModeStatus");