From baf88931d4310ee97d50ddefae404b980d3eddea Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Mon, 20 Jul 2026 11:46:57 -0700 Subject: [PATCH] FN-8436: remove reconnecting status from Planning Mode Keep Planning Mode progress feedback in the loading pane without showing transient reconnecting text. - Remove reconnecting UI state and stream-state callback handling. - Preserve loading controls and generation progress during stream recovery. - Cover recovery behavior without the reconnecting hint. Files changed: .../FN-8436-planning-no-reconnecting-hint.md | 7 ++++++ .../dashboard/app/components/PlanningModeModal.tsx | 25 ++++------------------ .../PlanningModeModal.planning-flow.test.tsx | 6 ++++-- 3 files changed, 15 insertions(+), 23 deletions(-) Fusion-Task-Id: FN-8436 Fusion-Task-Lineage: 344eb8bd-fc5c-4cb1-aed0-27453a0cb701 Co-authored-by: Fusion (runfusion.ai) --- .../FN-8436-planning-no-reconnecting-hint.md | 7 ++++++ .../app/components/PlanningModeModal.tsx | 25 +++---------------- .../PlanningModeModal.planning-flow.test.tsx | 6 +++-- 3 files changed, 15 insertions(+), 23 deletions(-) create mode 100644 .changeset/FN-8436-planning-no-reconnecting-hint.md diff --git a/.changeset/FN-8436-planning-no-reconnecting-hint.md b/.changeset/FN-8436-planning-no-reconnecting-hint.md new file mode 100644 index 0000000000..f20992a572 --- /dev/null +++ b/.changeset/FN-8436-planning-no-reconnecting-hint.md @@ -0,0 +1,7 @@ +--- +"@runfusion/fusion": patch +--- + +summary: Stop showing Reconnecting status text in Planning Mode. +category: fix +dev: Remove PlanningModeModal isReconnecting UI state and the planning.reconnecting form-hint; generation progress remains via the loading pane only. diff --git a/packages/dashboard/app/components/PlanningModeModal.tsx b/packages/dashboard/app/components/PlanningModeModal.tsx index b3cc7960ac..6425973b25 100644 --- a/packages/dashboard/app/components/PlanningModeModal.tsx +++ b/packages/dashboard/app/components/PlanningModeModal.tsx @@ -350,7 +350,6 @@ export function PlanningModeModal({ isOpen, onClose, onTaskCreated, onTasksCreat const hasLoadedPersistedRef = useRef(false); const [streamingOutput, setStreamingOutput] = useState(""); const [showThinking, setShowThinking] = useState(true); - const [isReconnecting, setIsReconnecting] = useState(false); const [isRetrying, setIsRetrying] = useState(false); const [isAutoRetrying, setIsAutoRetrying] = useState(false); const [autoRetryAttempt, setAutoRetryAttempt] = useState(0); @@ -817,7 +816,6 @@ export function PlanningModeModal({ isOpen, onClose, onTaskCreated, onTasksCreat setBranchName(""); setBaseBranch(""); setStreamingOutput(""); - setIsReconnecting(false); setIsRetrying(false); resetPlanningAutoRetryBudget(); setIsRefiningSummary(false); @@ -930,7 +928,6 @@ export function PlanningModeModal({ isOpen, onClose, onTaskCreated, onTasksCreat passive stream catch-up event that overwrites a newer awaiting-input question. */ if (isAnsweredQuestion && editingQuestionIdRef.current !== normalizedQuestion.id) return; - setIsReconnecting(false); setIsRetrying(false); resetPlanningAutoRetryBudget(); setIsRefiningSummary(false); @@ -962,7 +959,6 @@ export function PlanningModeModal({ isOpen, onClose, onTaskCreated, onTasksCreat onSummary: (summary) => { if (isStaleEvent()) return; const normalizedSummary = normalizePlanningSummary(summary); - setIsReconnecting(false); setIsRetrying(false); resetPlanningAutoRetryBudget(); setIsRefiningSummary(false); @@ -1004,7 +1000,6 @@ export function PlanningModeModal({ isOpen, onClose, onTaskCreated, onTasksCreat // permanent error view. Refetch the session state — if the server // still has it in a recoverable state, silently reconnect; only // surface the error if the server actually persisted one. - setIsReconnecting(true); (async () => { try { const session = await fetchAiSession(sessionId); @@ -1019,7 +1014,6 @@ export function PlanningModeModal({ isOpen, onClose, onTaskCreated, onTasksCreat // fall through to error view below } - setIsReconnecting(false); /* FNXC:PlanningRetry 2026-07-15-00:00: FN-8332 limits the stuck-turn retry budget to generations started by @@ -1053,16 +1047,12 @@ export function PlanningModeModal({ isOpen, onClose, onTaskCreated, onTasksCreat })(); }, onComplete: () => { - setIsReconnecting(false); setIsRetrying(false); resetPlanningAutoRetryBudget(); setIsRefiningSummary(false); refineSummaryInFlightRef.current = false; currentSessionIdRef.current = null; }, - onConnectionStateChange: (state) => { - setIsReconnecting(state === "reconnecting"); - }, }); streamConnectionRef.current = connection; @@ -1155,7 +1145,6 @@ export function PlanningModeModal({ isOpen, onClose, onTaskCreated, onTasksCreat setIsAutoRetrying(false); } - setIsReconnecting(false); return; } catch (sessionRefreshError) { retryError = sessionRefreshError; @@ -1169,7 +1158,6 @@ export function PlanningModeModal({ isOpen, onClose, onTaskCreated, onTasksCreat session: retryTarget, errorMessage: getErrorMessage(retryError) || t("planning.retryFailed", "Retry failed. Please try again."), }); - setIsReconnecting(false); setIsAutoRetrying(false); } finally { if (!options.auto) { @@ -1220,7 +1208,6 @@ export function PlanningModeModal({ isOpen, onClose, onTaskCreated, onTasksCreat setStreamingOutput(""); setConversationHistory([]); setResponseHistory([]); - setIsReconnecting(false); resetPlanningAutoRetryBudget(); setIsRefiningSummary(false); refineSummaryInFlightRef.current = false; @@ -1251,7 +1238,6 @@ export function PlanningModeModal({ isOpen, onClose, onTaskCreated, onTasksCreat connectToPlanningStream(sessionId); setResponseHistory([]); } catch (err) { - setIsReconnecting(false); setError(getErrorMessage(err) || t("planning.failedStartSession", "Failed to start planning session")); setView({ type: "initial" }); currentSessionIdRef.current = null; @@ -1846,7 +1832,6 @@ export function PlanningModeModal({ isOpen, onClose, onTaskCreated, onTasksCreat if (!isOpen) { hasAutoStartedRef.current = false; hasLoadedPersistedRef.current = false; - setIsReconnecting(false); setIsRetrying(false); } }, [isOpen]); @@ -1940,7 +1925,6 @@ export function PlanningModeModal({ isOpen, onClose, onTaskCreated, onTasksCreat } streamConnectionRef.current?.close(); streamConnectionRef.current = null; - setIsReconnecting(false); setIsRetrying(false); setIsRefiningSummary(false); refineSummaryInFlightRef.current = false; @@ -2090,7 +2074,6 @@ export function PlanningModeModal({ isOpen, onClose, onTaskCreated, onTasksCreat streamConnectionRef.current?.close(); streamConnectionRef.current = null; - setIsReconnecting(false); setIsRetrying(false); setIsAutoRetrying(false); setIsRefiningSummary(false); @@ -2456,11 +2439,11 @@ export function PlanningModeModal({ isOpen, onClose, onTaskCreated, onTasksCreat
{error &&
{error}
} {/* - FNXC:PlanningMode 2026-07-15-00:00: - Awaiting-input questions are persisted database state, so transient idle SSE reconnects must not imply that the question is being regenerated. Reserve this hint for the active loading view, where live generation genuinely depends on the stream. + FNXC:PlanningMode 2026-07-20-12:00: + FN-8436 supersedes FN-8002's loading-only reconnect hint: Planning Mode never + surfaces a user-visible reconnecting status. The loading pane's generating/thinking, + elapsed-time, and Stop controls are the sole progress feedback while SSE recovers. */} - {isReconnecting && view.type === "loading" &&
{t("planning.reconnecting", "Reconnecting…")}
} - {view.type === "initial" && (
diff --git a/packages/dashboard/app/components/__tests__/PlanningModeModal.planning-flow.test.tsx b/packages/dashboard/app/components/__tests__/PlanningModeModal.planning-flow.test.tsx index b6b94d9882..c1697ad1fa 100644 --- a/packages/dashboard/app/components/__tests__/PlanningModeModal.planning-flow.test.tsx +++ b/packages/dashboard/app/components/__tests__/PlanningModeModal.planning-flow.test.tsx @@ -1932,7 +1932,7 @@ describe("PlanningModeModal", () => { expect(screen.queryByText("Reconnecting…")).toBeNull(); }); - it("shows the reconnecting hint while active generation is loading", async () => { + it("keeps generation chrome visible without a reconnecting hint during stream recovery", async () => { let streamHandlers: any; mockConnectPlanningStream.mockImplementationOnce((_sessionId: string, _projectId: string | undefined, handlers: any) => { streamHandlers = handlers; @@ -1955,11 +1955,13 @@ describe("PlanningModeModal", () => { fireEvent.click(screen.getByText("Start Planning")); await waitFor(() => expect(mockConnectPlanningStream).toHaveBeenCalledTimes(1)); + expect(screen.getByText("Generating next question...")).toBeInTheDocument(); act(() => { streamHandlers.onConnectionStateChange?.("reconnecting"); }); - expect(screen.getByText("Reconnecting…")).toBeInTheDocument(); + expect(screen.getByText("Generating next question...")).toBeInTheDocument(); + expect(screen.queryByText("Reconnecting…")).toBeNull(); }); it("shows summary view when resuming a complete persisted session", async () => {