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");