From a67780a717a5b526bbbaa50275a60b7dee22b533 Mon Sep 17 00:00:00 2001 From: dengm Date: Sat, 30 May 2026 12:32:01 +0800 Subject: [PATCH 1/2] fix: plan panel squeezing layout (#2338) + storm breaker deadlock (#2345) - Remove execution-phase condition from planPanelOpen so the conversation area returns to full width after accepting a plan. - Reorder allSuppressed check above steerQueue in repair path to prevent infinite loop when storm breaker suppresses all tool calls. --- src/cli/ui/App.tsx | 3 +-- src/loop.ts | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/cli/ui/App.tsx b/src/cli/ui/App.tsx index 5f410619b..dde059ab2 100644 --- a/src/cli/ui/App.tsx +++ b/src/cli/ui/App.tsx @@ -918,8 +918,7 @@ function AppInner({ stagedInput || pendingCheckpoint || pendingRevision || - pendingReviseEditor || - (planStepsRef.current && planStepsRef.current.length > 0 && !planMode) + pendingReviseEditor ); // Wall-clock when the latest tool_start fired. Cleared when the // matching `tool` event arrives (or at turn end). Tools are diff --git a/src/loop.ts b/src/loop.ts index 3668edf57..2b0df1137 100644 --- a/src/loop.ts +++ b/src/loop.ts @@ -1153,9 +1153,6 @@ export class CacheFirstLoop { } if (repairedCalls.length === 0) { - if (this._steerQueue.length > 0) { - continue; - } if (allSuppressed) { try { yield* forceSummaryAfterIterLimit(this.summaryContext(), { reason: "stuck" }); @@ -1165,6 +1162,9 @@ export class CacheFirstLoop { } return; } + if (this._steerQueue.length > 0) { + continue; + } restoreModelIfNeeded(); yield { turn: this._turn, role: "done", content: assistantContent }; this._steerQueue.length = 0; From 69a520b4b951e00bf11526816868e13dcd7196a7 Mon Sep 17 00:00:00 2001 From: dengm Date: Sun, 31 May 2026 20:15:30 +0800 Subject: [PATCH 2/2] fix(shell): skip Windows /-prefixed flags in allowlist path guard On Windows, path.isAbsolute('/f') returns true and path.resolve(root, '/f') resolves to D:\f, escaping the sandbox. The path-escape guard only skipped -prefixed tokens (Linux flags), not /-prefixed tokens (Windows flags like /f, /im). This caused every Windows-flag command to fail the workspace check, making shell allowlist / 'Always allow' never take effect. --- src/tools/shell/parse.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/tools/shell/parse.ts b/src/tools/shell/parse.ts index d6e6702be..79bf33a69 100644 --- a/src/tools/shell/parse.ts +++ b/src/tools/shell/parse.ts @@ -349,7 +349,14 @@ export function isAllowed( if (projectRoot) { const root = pathMod.resolve(projectRoot); for (const tok of argv) { - if (!tok || tok.startsWith("-") || tok.includes("://") || tok.startsWith("$")) continue; + if ( + !tok || + tok.startsWith("-") || + tok.startsWith("/") || + tok.includes("://") || + tok.startsWith("$") + ) + continue; let expanded = tok; if (expanded.startsWith("~")) expanded = pathMod.join(homedir(), expanded.slice(1)); const resolved = pathMod.resolve(root, expanded);