Three bugs fixed in KeyboardHandler:
1. onKeyboardShow() used sessionData.terminal (always undefined) instead of app.terminal
2. Keyboard dismiss threshold (50px) too tight for iOS address bar drift — widened to 100px
3. No terminal refit on keyboard hide — caused black gap below terminal
Also added: dynamic baseline update for initialViewportHeight, safety check in
updateLayoutForKeyboard() that forces dismiss when keyboardOffset <= 0.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Clear teams/teamTasks maps in handleInit() on SSE reconnect
- Fix saveNowAsync() race condition with in-flight promise guard
- Add setMaxListeners() on Session, WebServer, SubagentWatcher,
ImageWatcher, TmuxManager to prevent MaxListenersExceeded warnings
- Debounce persistSessionState() per-session (100ms) to reduce
redundant toState() serialization across 25+ call sites
- Cache getLightSessionsState() with 1s TTL to avoid re-serializing
all sessions on every SSE connect and /api/sessions request
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Convert sync readFileSync/statSync to async in subagent-watcher.ts to
unblock event loop on hot paths (transcript reads, liveness checks)
- Fix Map mutation during iteration in closeSessionLogViewerWindows and
closeSessionImagePopups (collect IDs first, then iterate to close)
- Unify session cleanup into shared _cleanupSessionData() method called
from both closeSession() and session:deleted handler to prevent leaks
- Add Zod validation schemas for 20+ API routes that used raw type casts
- Add consecutive error tracking (5 errors/60s triggers exit for systemd
restart) and SIGHUP handler for SSH disconnect safety
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1. handleInit crash: commit cdc822d removed Map initializations for
teammateTerminals, teammatePanesByName, teams, teamTasks, teammateMap
from the constructor but left cleanup code that iterates them.
cleanupAllFloatingWindows() crashed on "not iterable", preventing
ALL frontend data (sessions, subagents) from loading.
2. claudeSessionId null on recovered sessions: only set inside
startInteractive(), never in constructor or persisted. After server
restart, recovered sessions had null claudeSessionId, so the
hasMatchingTab check always failed → no subagent windows.
Fixes:
- Re-add all 5 missing Map initializations in app.js constructor
- Set _claudeSessionId = this.id in Session constructor (Claudeman
always passes --session-id to Claude, so they always match)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Added IS_TEST_MODE (process.env.VITEST) guards to every method in TmuxManager and
ScreenManager that touches real tmux/screen sessions. Tests can never create, kill,
discover, or send input to real sessions. Removed broken E2E test suite entirely.
Rewrote test/setup.ts from 459 lines to minimal cleanup. Rewrote tmux-related tests
to verify test-mode safety behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
feat: interactive teammate tmux pane windows with xterm.js terminals
feat: auto-cleanup teams/subagents/pane windows on session delete
fix: only show agent/teammate windows when matching Claudeman tab exists
fix: UTF-8 encoding in teammate pane terminal output (Uint8Array)
fix: standalone pane window cleanup via subagentParentMap lookup
fix: xterm.js dimensions crash with deferred init + null-safe dispose
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- WebServer: Store session listener refs for explicit cleanup on delete
- RespawnController: Fix clearInterval bug (was using clearTimeout)
- RespawnController: Add try/catch to interval callbacks
- PlanOrchestrator: Guarantee progressInterval cleanup with try/finally
- SubagentWatcher: Guard idle timer against deleted agents
- Session: Add threshold validation for auto-clear/compact (1k-500k)
- Session: Add token sum overflow check in restoreTokens
- Session: Use LRUMap for _recentTaskDescriptions auto-eviction
Commit from flight QR118 in an Airbus A350-1000, stable connection thanks to Starlink!
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Backend fixes:
- Session: clear _recentTaskDescriptions Map in stop() and clearBuffers()
- Session: null promise callbacks after rejection in runPrompt() catch block
- Server: store subagent/image watcher listener refs and remove on shutdown
Frontend fixes:
- Plan file windows: store drag/resize handlers and clean up on close
- Plan file manager: store drag handler and clean up on close
- cleanupAllFloatingWindows: now cleans up plan file windows
These prevent unbounded memory growth in long-running sessions.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add --session-id flag to Claude CLI startup so Claudeman and Claude share the same session ID
- Set claudeSessionId immediately on session start (no waiting for JSON messages)
- Add persistent subagentParentMap to store agent-to-tab associations permanently
- Add /api/subagent-parents endpoints for server-side persistence
- Add fallback: use active session when claudeSessionId matching fails
- Connection lines now reliably connect agent windows to their parent tabs
- Survives page refresh, reconnect, and server restart
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove TUI from git (moved to .gitignore for local development)
- Remove React/Ink dependencies (unused in published version)
- Remove tui command from CLI
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Reduce getRecentSubagents window from 60 to 15 minutes
- Skip old/completed agents when restoring window states (10 min cutoff)
- Clear old activity data when new agent with same ID is discovered
- Force close existing window for agentId before opening fresh one
Fixes issue where old prompts/input from previous Ralph Loop runs
were displayed when clicking on subagent windows.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements the Execution Optimizer Rework plan that enables the system
to actually use the optimizer metadata (parallelGroups, agentType,
recommendedModel, requiresFreshContext, estimatedTokens) that was
previously generated but ignored.
New components:
- ExecutionBridge: Central coordinator that loads optimized plans,
manages parallel execution within groups, and coordinates with
SpawnOrchestrator for session-based execution
- ModelSelector: Routes tasks to appropriate models (opus/sonnet/haiku)
based on user defaults and agent type overrides. Optimizer
recommendations are advisory only - user preferences always win
- GroupScheduler: Builds topologically ordered execution groups,
manages dependencies, determines execution mode (session vs task-tool)
- ContextManager: Handles fresh context requirements via /clear+/init
or new session spawning
Features:
- Parallel task execution within groups (configurable limit)
- Group-level dependency tracking (lower groups complete first)
- Partial failure handling (continue with non-dependent tasks)
- Model configuration in App Settings > Models tab
- Agent type overrides (explore, implement, test, review)
- Execution control API endpoints (start, pause, resume, cancel)
- SSE events for real-time execution progress visibility
- Execution history tracking
API endpoints:
- GET/POST/PUT /api/execution/* for execution control
- GET/PUT /api/execution/model-config for model settings
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Session updates (like renaming) were broadcasting toDetailedState() which
doesn't include respawn controller state. The frontend would then overwrite
the session object, losing respawnEnabled/respawnConfig/respawn fields.
Added getSessionStateWithRespawn() helper that includes respawn controller
state in all session:updated broadcasts.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements image file watching in session working directories with
automatic popup display in the web UI:
- Add ImageWatcher class using chokidar for cross-platform file watching
- Add ImageDetectedEvent type for SSE broadcasting
- Integrate with session lifecycle (watch on create, unwatch on delete)
- Add image:detected SSE event handler in frontend
- Create draggable image popup window with open-in-new-tab support
- Add CSS styling with compact wizard layout
Supports: png, jpg, jpeg, gif, webp, bmp, svg
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds a new Phase 0 research agent that runs before all other analysis agents:
- Web search for GitHub repos, documentation, tutorials
- Codebase exploration for existing patterns
- Technical recommendations and potential challenges
- Creates enriched task description for downstream agents
- Research context injected into all analysis agents via {RESEARCH_CONTEXT}
- Saves output to research/ folder with prompt.md and result.json
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The plan generation API (/api/generate-plan-detailed) was incorrectly
detecting client disconnection because it listened to req.raw.on('close')
which fires when the HTTP request body finishes parsing, not when the
actual TCP connection closes.
This caused the error "Failed to parse plan - no JSON array found" because
the server would cancel all subagent sessions almost immediately after
starting them.
Fix:
- Changed from req.raw.on('close') to socket.on('close')
- Added responseSent flag to only cancel if response hasn't been sent
- Added E2E test to verify the fix
Tested with:
- Simple plan generation: 61 items, 138.5s, quality 0.82
- Smartphone app plan: 53 items, 93.4s, quality 0.75
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- SSE event listener cleanup: Track all listeners and remove on reconnect
to prevent listener accumulation (60+ listeners per connect cycle)
- Floating window cleanup: Remove drag listeners, ResizeObservers on close
- Session creation mutex: Prevent race conditions from concurrent requests
- Screen kill verification: Confirm processes are dead after kill signals
- State store circuit breaker: Prevent cascading failures with backup/recovery
- PTY spawn error handling: Wrap all spawn calls with proper error emission
- SSE graceful shutdown: Notify clients before server stops
- Async file writes: Replace blocking writeFileSync in hot paths
- DocumentFragment optimization: Batch DOM updates for plan rendering
- Timer cleanup: Clear notification/countdown timers on SSE reconnect
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add plan-orchestrator.ts with parallel subagent spawning
- Phase 1: 4 specialist subagents analyze in parallel (requirements, architecture, testing, risks)
- Phase 2: Synthesis merges and deduplicates outputs
- Phase 3: Verification subagent assigns priorities and identifies gaps
- New /api/generate-plan-detailed endpoint with SSE progress updates
- Auto-regenerate plan when switching between Standard/Enhanced modes
- Show quality score, warnings, and gaps from verification
- Rename "Detailed" to "Enhanced" button with tooltip
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add /api/sessions/:id/ralph-prompt/write endpoint to write prompt to @ralph_prompt.md
- Wizard now writes full prompt to file, then sends simple read command to Claude
- Fix session readiness check to wait for prompt character instead of notWorking flag
- Add E2E test infrastructure for ralph-loop workflow (port 3190)
- Add ralph-wizard-prod.mjs script for production testing
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix screen creation failing when using cpulimit/nice (env vars were passed
as command args instead of shell variables)
- Fix session status never becoming 'idle' after startInteractive()
- Add automatic state file cleanup on startup (removes orphaned sessions)
- Add /api/cleanup-state endpoint for manual cleanup
- Make frontend session readiness check more robust (20 attempts, multiple checks)
- Add fallback to direct PTY write if writeViaScreen fails
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
CPU Limiting:
- Add CpuLimitConfig type and settings in App Settings
- Use nice command for process priority (-20 to 19)
- Optional cpulimit integration for hard CPU limits (if installed)
- Applied to new sessions via screen-manager and session modules
Ralph Loop Wizard:
- 3-step wizard: Describe → Plan → Launch
- New /api/generate-plan endpoint generates implementation steps via Claude
- Plan editor with checkboxes, priorities (P0/P1/P2), reordering
- Skip plan option for manual workflows
- Compact wizard modal layout
UI Updates:
- Form section headers for grouped settings
- CPU limit status indicator (cpulimit availability)
- Wizard modal wider layout and inline fields
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
API Endpoints:
- GET /api/sessions/:id/fix-plan - Generate fix plan markdown from todos
- POST /api/sessions/:id/fix-plan/import - Import todos from markdown
- POST /api/sessions/:id/fix-plan/write - Write @fix_plan.md to working dir
- POST /api/sessions/:id/fix-plan/read - Read and import from working dir
RalphTracker Methods:
- generateFixPlanMarkdown() - Creates structured markdown with priority sections
- importFixPlanMarkdown() - Parses markdown and imports todos with priorities
UI Features:
- Menu dropdown in Ralph panel (hamburger icon)
- View Fix Plan modal with copy/write buttons
- Import from file button
- Reset Circuit Breaker button
- Fix plan modal with syntax-highlighted textarea
Bump version to 0.1392
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Smart Respawn Integration (2.5):
- Check circuit breaker OPEN state before respawn (blocks cycle)
- Check RALPH_STATUS EXIT_SIGNAL=true to stop respawn
- Check STATUS=BLOCKED to pause respawn for human intervention
- Use RECOMMENDATION from RALPH_STATUS in update prompt
- Emit respawn:blocked SSE event with reason and details
- Show notification when respawn is blocked
- Visual blocked state with pulsing red indicator
Priority-based Todos (part of 2.3):
- Add RalphTodoPriority type (P0/P1/P2/null)
- Parse priority from todo content (P0:, Critical:, High Priority, etc.)
- Add priority field to RalphTodoItem interface
- Update frontend to display priority badges with colors
- Sort todos by priority (P0 > P1 > P2) then by status
- Add CSS for priority badges and highlighted cards
Bump version to 0.1391
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 1 Ralph enhancement implementation:
- Parse RALPH_STATUS blocks from Claude output (status, tasks, files, tests)
- Circuit breaker state machine (CLOSED → HALF_OPEN → OPEN) for stuck detection
- Dual-condition exit gate (completion indicators >= 2 AND EXIT_SIGNAL)
- Frontend: circuit breaker badge (yellow warning, red stuck), status block display
- API: circuit breaker reset endpoint, ralph status endpoint
- Notifications when circuit breaker opens or exit gate is met
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add getLightState() and getLightSessionsState() methods
- SSE init payload reduced from ~1.9MB to ~5KB (~400x smaller)
- Terminal buffers are fetched on-demand when switching tabs
- Fixes UI becoming unresponsive on SSE reconnect
chore: bump version to 0.1388