From 259cabd7380562a7a42c341945fb5e57e577f361 Mon Sep 17 00:00:00 2001 From: Codeman maintainer Date: Fri, 13 Nov 2026 20:29:31 +0100 Subject: [PATCH] chore(web): remove the Ralph wizard and its plan-generation UI The wizard's only entry point was the "Start Ralph Loop" button on the start screen, removed in 1.50.0, so none of this could be opened or triggered from the app any more: - ralph-wizard.js (the wizard, plan generation flow and the floating plan subagent windows) and the #ralphWizardModal markup; - the "Plan Wizard Agents" section of the monitor panel with its cancel button, and the five plan:* SSE handlers that only fed these surfaces; - the wizard branches in the subagent window code: connection lines to the wizard and to plan agents, window placement beside the wizard, and the wizard cleanup on reconnect. The ordinary path (agent window to its parent tab) is unchanged, only un-nested; - the wizard's state on the app object and its z-index constant; - its styles: 67 classes, three keyframes and a second identical @keyframes spin. What stays: the Ralph panel, the Ralph tab in session options, the plan routes (/api/generate-plan, /api/generate-plan-detailed, /api/cancel-plan-generation, the ralph-wizard file routes) and the plan:* SSE events, which are part of the public API. A client that starts plan generation over the API still gets its events; the page no longer draws anything for them. Co-Authored-By: Claude Fable 5.2 --- docs/architecture-invariants.md | 2 +- scripts/build.mjs | 1 - src/web/CLAUDE.md | 2 +- src/web/public/api-client.js | 2 +- src/web/public/app.js | 45 -- src/web/public/constants.js | 5 +- src/web/public/entrance-animations.js | 2 +- src/web/public/index.html | 194 ----- src/web/public/keyboard-accessory.js | 3 +- src/web/public/mobile.css | 24 - src/web/public/ralph-panel.js | 148 +--- src/web/public/ralph-wizard.js | 1071 ------------------------- src/web/public/session-ui.js | 2 +- src/web/public/styles.css | 723 ----------------- src/web/public/subagent-windows.js | 284 +------ test/tab-rail-search.browser.test.ts | 1 - test/tab-rail-search.test.ts | 1 - 17 files changed, 43 insertions(+), 2467 deletions(-) delete mode 100644 src/web/public/ralph-wizard.js diff --git a/docs/architecture-invariants.md b/docs/architecture-invariants.md index d58d3655..679a32af 100644 --- a/docs/architecture-invariants.md +++ b/docs/architecture-invariants.md @@ -1339,7 +1339,7 @@ Tests: `test/mobile-prompt-composer.test.ts` (in the CI gate, deliberately not u ### Z-index layers -**Z-index layers**: subagent windows (1000), split picker menu (1000, `.split-picker-menu`), Tiles count menu (1000, `.tile-count-menu`), the closing grid's still copy (`.tile-grid-ghosts`, z-index 3 inside `.main`, over the single view coming back; hidden under `.main.webview-active`), plan agents (1100), mobile/tablet fixed header (1200, `mobile.css`), modals on ≤768px (1300 — must beat the fixed header or the modal close button is buried), log viewers (2000), connection-loss overlay (2500, above the fixed header and modals), image popups (3000), response viewer (5000, backdrop 4999), folder grid (5090, `#folderGridOverlay` — above the response viewer a folder link opens it from, below the file preview its tiles open, so a tile's preview and its ←/→ paging sit on top of the grid), file-preview overlay (5100 — must outrank the response viewer, which can launch it; at its old 2000 a path clicked in the chat opened BEHIND the chat), toasts/path picker (10000+, deliberately above the preview), the custom-model center-status banner (10001, `.center-status-banner` — `[hidden]` must re-assert `display: none` over its own `display: flex`, same trap as `.home-sessions[hidden]`, or `dismiss()` leaves an invisible click-blocker dead centre on screen), the swap-confirm and context-warning modals (10010, `#customModelSwapConfirmModal`/`#customModelContextWarningModal` — must clear both the plain `.modal` z-index of 1000 and the center-status banner it can appear over), terminal touch-selection bar (900 — above terminal content and the local-echo overlay, deliberately BELOW floating agent windows so it can never cover their controls), local echo overlay (7), iOS IME composition preview (EFFECTIVE layer depends on its home: with local echo on it is part of the local echo overlay at 7, drawn by `setComposition()` as an underlined tail after the pending text; with local echo off it is a span at z-index 6 inside `.xterm-helpers`, but `.xterm-helpers` is its own z-index 5 stacking context, so the span's effective layer is 5. That is below the overlay's 7, which is why the span cannot be used while the overlay holds text: typed text never reaches the PTY before Enter, the PTY cursor that places the span stays at the prompt start, and the overlay's opaque line div covers it). +**Z-index layers**: subagent windows (1000), split picker menu (1000, `.split-picker-menu`), Tiles count menu (1000, `.tile-count-menu`), the closing grid's still copy (`.tile-grid-ghosts`, z-index 3 inside `.main`, over the single view coming back; hidden under `.main.webview-active`), mobile/tablet fixed header (1200, `mobile.css`), modals on ≤768px (1300 — must beat the fixed header or the modal close button is buried), log viewers (2000), connection-loss overlay (2500, above the fixed header and modals), image popups (3000), response viewer (5000, backdrop 4999), folder grid (5090, `#folderGridOverlay` — above the response viewer a folder link opens it from, below the file preview its tiles open, so a tile's preview and its ←/→ paging sit on top of the grid), file-preview overlay (5100 — must outrank the response viewer, which can launch it; at its old 2000 a path clicked in the chat opened BEHIND the chat), toasts/path picker (10000+, deliberately above the preview), the custom-model center-status banner (10001, `.center-status-banner` — `[hidden]` must re-assert `display: none` over its own `display: flex`, same trap as `.home-sessions[hidden]`, or `dismiss()` leaves an invisible click-blocker dead centre on screen), the swap-confirm and context-warning modals (10010, `#customModelSwapConfirmModal`/`#customModelContextWarningModal` — must clear both the plain `.modal` z-index of 1000 and the center-status banner it can appear over), terminal touch-selection bar (900 — above terminal content and the local-echo overlay, deliberately BELOW floating agent windows so it can never cover their controls), local echo overlay (7), iOS IME composition preview (EFFECTIVE layer depends on its home: with local echo on it is part of the local echo overlay at 7, drawn by `setComposition()` as an underlined tail after the pending text; with local echo off it is a span at z-index 6 inside `.xterm-helpers`, but `.xterm-helpers` is its own z-index 5 stacking context, so the span's effective layer is 5. That is below the overlay's 7, which is why the span cannot be used while the overlay holds text: typed text never reaches the PTY before Enter, the PTY cursor that places the span stays at the prompt start, and the overlay's opaque line div covers it). ## Security layers diff --git a/scripts/build.mjs b/scripts/build.mjs index d949fcad..f095fbc0 100644 --- a/scripts/build.mjs +++ b/scripts/build.mjs @@ -157,7 +157,6 @@ console.log('\n[build] content-hash cache busting'); 'settings-ui.js', 'panels-ui.js', 'session-ui.js', - 'ralph-wizard.js', 'api-client.js', 'subagent-windows.js', 'image-input.js', diff --git a/src/web/CLAUDE.md b/src/web/CLAUDE.md index 5cc46b70..e4825913 100644 --- a/src/web/CLAUDE.md +++ b/src/web/CLAUDE.md @@ -94,6 +94,6 @@ Frontend JS modules have `@fileoverview` with `@dependency`/`@loadorder` tags. L **SSE staleness watchdog** (`computeSseStale()` in constants.js, `_checkSseStale()` + a 5s interval in app.js): an `EventSource` can stop delivering without erroring, so the client forces a reconnect when nothing arrives. ⚠️ The server keepalive must stay the named `sse:heartbeat` event (`cleanupDeadClients()`, sse-stream-manager.ts), never an SSE comment, which `EventSource` cannot observe; its no-op client listener must stay registered. ⚠️ Judge staleness only while `connected` and online (the loop breaker). ⚠️ The liveness stamp lives inside `addListener`. ⚠️ Clear the interval only at the top of `connectSSE()`, or intervals stack. ⚠️ The watchdog cannot see an attempt that never OPENS (no response headers: no `open`, no `error`, never `connected`), so each attempt is bounded by `SSE_CONNECT_TIMEOUT_MS` (15s, `CodemanSseStale.CONNECT_TIMEOUT_MS`) and then retried through `_handleSseConnectionFailure()`, the same backoff `onerror` uses. Its timer is cleared at the top of `connectSSE()` BEFORE the offline early return, on `open`, and in `_handleSseConnectionFailure()`; the timer and the handler both ignore an `EventSource` that has been replaced. The window `offline` handler leaves it running on purpose (`navigator.onLine` can report offline on a working network). Tests: `test/sse-connect-timeout.test.ts`. → [architecture-invariants#sse-staleness-watchdog](../../docs/architecture-invariants.md#sse-staleness-watchdog) -**Z-index layers** (keep new overlays consistent with this stack): local echo overlay (7; with local echo on it also draws the iOS IME composition preview, as an underlined tail after its pending text via `setComposition`), iOS IME composition preview span when local echo is off (6 inside `.xterm-helpers`, whose own z-index 5 is its EFFECTIVE layer, so it sits UNDER the overlay and must never be used while the overlay shows text), terminal touch-selection bar (900, below floating agent windows), subagent windows + split picker menu + Tiles count menu (1000), plan agents (1100), mobile/tablet fixed header (1200), modals on ≤768px (1300, must beat the fixed header), log viewers (2000), connection-loss overlay (2500), image popups (3000), response viewer (5000, backdrop 4999), folder grid (5090, above the response viewer it opens from, below the file preview its tiles open), file-preview overlay (5100, must outrank the response viewer that launches it), toasts/path picker (10000+), custom-model center-status banner (10001; its `[hidden]` must re-assert `display: none` or `dismiss()` leaves an invisible click-blocker), custom-model swap-confirm/context-warning modals (10010). → [architecture-invariants#z-index-layers](../../docs/architecture-invariants.md#z-index-layers) +**Z-index layers** (keep new overlays consistent with this stack): local echo overlay (7; with local echo on it also draws the iOS IME composition preview, as an underlined tail after its pending text via `setComposition`), iOS IME composition preview span when local echo is off (6 inside `.xterm-helpers`, whose own z-index 5 is its EFFECTIVE layer, so it sits UNDER the overlay and must never be used while the overlay shows text), terminal touch-selection bar (900, below floating agent windows), subagent windows + split picker menu + Tiles count menu (1000), mobile/tablet fixed header (1200), modals on ≤768px (1300, must beat the fixed header), log viewers (2000), connection-loss overlay (2500), image popups (3000), response viewer (5000, backdrop 4999), folder grid (5090, above the response viewer it opens from, below the file preview its tiles open), file-preview overlay (5100, must outrank the response viewer that launches it), toasts/path picker (10000+), custom-model center-status banner (10001; its `[hidden]` must re-assert `display: none` or `dismiss()` leaves an invisible click-blocker), custom-model swap-confirm/context-warning modals (10010). → [architecture-invariants#z-index-layers](../../docs/architecture-invariants.md#z-index-layers) **Keyboard shortcuts**: Escape (close), Ctrl+? (shortcut overlay), Ctrl/Cmd/Alt+K (session palette), Ctrl+Tab (next), Alt+[/] (prev/next tab), Alt+1-9 (switch tab), Ctrl+Shift+{/} (move tab left/right), Shift+Enter or Ctrl+Enter (newline), Ctrl+C (copy selection, else interrupt) / Ctrl+Shift+C (copy, never interrupts), Ctrl+L (clear), Ctrl+Shift+R (restore size), Ctrl+Shift+V (voice input), Ctrl/Cmd +/- (font), Shift+Wheel (local scrollback when mouse passthrough is active), Shift+drag (start a selection in a stripped-DECSET pane, where xterm's own Shift branch is unreachable and a Shift+drag used to select nothing; `_installShiftDragSelection`), right-click (copy the selection, the mintty/PuTTY convention, since xterm paints into a canvas and the native menu has no Copy for it; with nothing selected the native menu is left alone). Rebindable via the registry. ⚠️ **Ctrl+W is deliberately NOT bound** (owner decision): it is delete-word in every shell and agent CLI, and as Close Session it killed sessions with no confirm; `close-session` keeps `bindings: []` and stays bindable (`test/ctrl-w-never-closes.test.ts`). diff --git a/src/web/public/api-client.js b/src/web/public/api-client.js index fea0d2b5..0e14c5e8 100644 --- a/src/web/public/api-client.js +++ b/src/web/public/api-client.js @@ -7,7 +7,7 @@ * * @mixin Extends CodemanApp.prototype via Object.assign * @dependency app.js (CodemanApp class must be defined) - * @loadorder 14 of 15 — loaded after ralph-wizard.js + * @loadorder 14 of 15 — loaded after session-ui.js */ // Codeman — Centralized API fetch helpers for CodemanApp diff --git a/src/web/public/app.js b/src/web/public/app.js index 5633aa21..8e58b9fd 100644 --- a/src/web/public/app.js +++ b/src/web/public/app.js @@ -11,7 +11,6 @@ * panels-ui.js — Subagent panel, agent teams, project insights, file browser, log viewer, * image popups, monitor, token stats, toast, system stats * session-ui.js — Quick start, session options modal, case settings, mobile case picker - * ralph-wizard.js — Ralph Loop wizard modal * api-client.js — API helper methods (fetch wrappers) * subagent-windows.js — Floating subagent terminal windows * @@ -299,13 +298,6 @@ const _SSE_HANDLER_MAP = [ [SSE_EVENTS.TUNNEL_QR_REGENERATED, '_onTunnelQrRegenerated'], [SSE_EVENTS.TUNNEL_QR_AUTH_USED, '_onTunnelQrAuthUsed'], - // Plan orchestration - [SSE_EVENTS.PLAN_SUBAGENT, '_onPlanSubagent'], - [SSE_EVENTS.PLAN_PROGRESS, '_onPlanProgress'], - [SSE_EVENTS.PLAN_STARTED, '_onPlanStarted'], - [SSE_EVENTS.PLAN_CANCELLED, '_onPlanCancelled'], - [SSE_EVENTS.PLAN_COMPLETED, '_onPlanCompleted'], - // Orchestrator loop [SSE_EVENTS.ORCHESTRATOR_STATE_CHANGED, '_onOrchestratorStateChanged'], [SSE_EVENTS.ORCHESTRATOR_PLAN_PROGRESS, '_onOrchestratorPlanProgress'], @@ -872,17 +864,6 @@ class CodemanApp { this.ralphStatePanelCollapsed = true; // Default to collapsed this.ralphClosedSessions = new Set(); // Sessions where user explicitly closed Ralph panel - // Plan subagent windows (visible agents during plan generation) - this.planSubagents = new Map(); // Map - this.planSubagentWindowZIndex = ZINDEX_PLAN_SUBAGENT_BASE; - this.planGenerationStopped = false; // Flag to ignore SSE events after Stop - this.planAgentsMinimized = false; // Whether agent windows are minimized to tab - - // Wizard dragging state - this.wizardDragState = null; // { startX, startY, startLeft, startTop, isDragging } - this.wizardDragListeners = null; // { move, up } for cleanup - this.wizardPosition = null; // { left, top } - null means centered - // Project Insights tracking (active Bash tools with clickable file paths) this.projectInsights = new Map(); // Map this.logViewerWindows = new Map(); // Map @@ -5058,10 +5039,6 @@ class CodemanApp { // wrapping) clipped xterm's bottom rows behind the toolbar until a tab // switch or a window resize. // Clear any other orphaned timers - if (this.planLoadingTimer) { - clearInterval(this.planLoadingTimer); - this.planLoadingTimer = null; - } if (this.timerCountdownInterval) { clearInterval(this.timerCountdownInterval); this.timerCountdownInterval = null; @@ -11140,28 +11117,6 @@ class CodemanApp { this.renderRalphStatePanel(); } - // ═══════════════════════════════════════════════════════════════ - // Ralph Loop Wizard (methods in ralph-wizard.js) - // ═══════════════════════════════════════════════════════════════ - - // Wizard state (initialized here, methods loaded from ralph-wizard.js) - ralphWizardStep = 1; - ralphWizardConfig = { - taskDescription: '', - completionPhrase: 'COMPLETE', - maxIterations: 10, - caseName: 'testcase', - enableRespawn: false, - generatedPlan: null, - planGenerated: false, - skipPlanGeneration: false, - planDetailLevel: 'detailed', - existingPlan: null, - useExistingPlan: false, - }; - planLoadingTimer = null; - planLoadingStartTime = null; - // ═══════════════════════════════════════════════════════════════ // Kill Sessions // ═══════════════════════════════════════════════════════════════ diff --git a/src/web/public/constants.js b/src/web/public/constants.js index f3f2b2ae..7421e1c7 100644 --- a/src/web/public/constants.js +++ b/src/web/public/constants.js @@ -16,7 +16,7 @@ * @dependency None (first in load order) * @loadorder 1 of 15 — constants.js → mobile-handlers.js → voice-input.js → notification-manager.js * → keyboard-accessory.js → input-cjk.js → app.js → terminal-ui.js → respawn-ui.js - * → ralph-panel.js → settings-ui.js → panels-ui.js → session-ui.js → ralph-wizard.js + * → ralph-panel.js → settings-ui.js → panels-ui.js → session-ui.js * → api-client.js → subagent-windows.js */ @@ -135,7 +135,6 @@ const TUI_REDRAW_SETTLE_MS = 400; // Grace for a TUI to redraw after a // Z-index base values for layered floating windows const ZINDEX_SUBAGENT_BASE = 1000; -const ZINDEX_PLAN_SUBAGENT_BASE = 1100; const ZINDEX_LOG_VIEWER_BASE = 2000; const ZINDEX_IMAGE_POPUP_BASE = 3000; @@ -1964,7 +1963,7 @@ function getEventCoords(e) { return { clientX: e.clientX, clientY: e.clientY }; } -// HTML escape utility (shared by NotificationManager, CodemanApp, and ralph-wizard.js) +// HTML escape utility (shared by NotificationManager and the CodemanApp mixins) const _htmlEscapeMap = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }; const _htmlEscapePattern = /[&<>"']/g; function escapeHtml(text) { diff --git a/src/web/public/entrance-animations.js b/src/web/public/entrance-animations.js index a7068e0a..76fa99d2 100644 --- a/src/web/public/entrance-animations.js +++ b/src/web/public/entrance-animations.js @@ -58,7 +58,7 @@ * @dependency app.js (tab render pipeline), subagent-windows.js (window + line hooks), * tile-grid.js (tile mount, reveal and still-copy hooks) * @dependency constants.js (escapeHtml) - * @loadorder 12.6 of 16, after webview-tabs.js, before ralph-wizard.js + * @loadorder 12.6 of 16, after webview-tabs.js, before api-client.js */ /** Tab entrance styles. `key` doubles as the `data-tab-anim` value. */ diff --git a/src/web/public/index.html b/src/web/public/index.html index 9d1a3248..7d1d1430 100644 --- a/src/web/public/index.html +++ b/src/web/public/index.html @@ -1280,16 +1280,6 @@
No mux sessions
-
Background Agents @@ -4217,189 +4207,6 @@
- - - -