From d896f6924d6d58adcf81d977aa7eb652a771a726 Mon Sep 17 00:00:00 2001 From: Prateek Date: Mon, 16 Feb 2026 23:52:39 +0530 Subject: [PATCH] fix: handle migration of legacy undefined-orchestrator sessions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses Cursor Bugbot review comment about orphaned legacy sessions. ## Changes 1. **ao start**: Automatically detects and migrates legacy 'undefined-orchestrator' sessions by stopping them before creating the new correctly-named session 2. **ao stop**: Checks for both new and legacy session names, stopping whichever exists ## Migration Strategy - When starting, if new session doesn't exist but legacy does: stop legacy → create new - When stopping, try new name first, fall back to legacy if not found - Metadata is properly archived in both cases ## Testing Migration logic tested with: - Legacy session present + ao start → legacy stopped, new created - Legacy session present + ao stop → legacy stopped - Both sessions present → prioritizes new session Co-Authored-By: Claude Opus 4.6 --- packages/cli/src/commands/start.ts | 58 ++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/packages/cli/src/commands/start.ts b/packages/cli/src/commands/start.ts index 735d0393c..6fde26149 100644 --- a/packages/cli/src/commands/start.ts +++ b/packages/cli/src/commands/start.ts @@ -202,6 +202,37 @@ export function registerStart(program: Command): void { // Check if orchestrator session already exists exists = await hasTmuxSession(sessionId); + // Migration: Check for legacy "undefined-orchestrator" session + const legacySessionId = "undefined-orchestrator"; + const legacyExists = await hasTmuxSession(legacySessionId); + + if (legacyExists && !exists) { + console.log( + chalk.yellow( + `\nFound legacy orchestrator session "${legacySessionId}"`, + ), + ); + console.log( + chalk.yellow( + `Stopping legacy session and creating new session "${sessionId}"...\n`, + ), + ); + + // Stop legacy session + try { + await exec("tmux", ["kill-session", "-t", legacySessionId]); + // Archive legacy metadata if it exists + deleteMetadata(config.dataDir, legacySessionId, true); + console.log(chalk.green(`✓ Legacy session stopped\n`)); + } catch (err) { + console.log( + chalk.yellow( + `Warning: Could not stop legacy session: ${err instanceof Error ? err.message : String(err)}\n`, + ), + ); + } + } + if (exists) { console.log( chalk.yellow( @@ -371,8 +402,11 @@ export function registerStop(program: Command): void { console.log(chalk.bold(`\nStopping orchestrator for ${chalk.cyan(project.name)}\n`)); - // Kill orchestrator session + // Kill orchestrator session (check both new and legacy names) const sessions = await getTmuxSessions(); + const legacySessionId = "undefined-orchestrator"; + let stopped = false; + if (sessions.includes(sessionId)) { const spinner = ora("Stopping orchestrator session").start(); await exec("tmux", ["kill-session", "-t", sessionId]); @@ -380,8 +414,26 @@ export function registerStop(program: Command): void { // Archive metadata deleteMetadata(config.dataDir, sessionId, true); - } else { - console.log(chalk.yellow(`Orchestrator session "${sessionId}" is not running`)); + stopped = true; + } else if (sessions.includes(legacySessionId)) { + // Migration: Stop legacy session if it exists + console.log(chalk.yellow(`Found legacy session "${legacySessionId}"`)); + const spinner = ora("Stopping legacy orchestrator session").start(); + await exec("tmux", ["kill-session", "-t", legacySessionId]); + spinner.succeed("Legacy orchestrator session stopped"); + + // Archive metadata + deleteMetadata(config.dataDir, legacySessionId, true); + stopped = true; + } + + if (!stopped) { + console.log( + chalk.yellow( + `Orchestrator session "${sessionId}" is not running\n` + + chalk.dim(`(Also checked for legacy session "${legacySessionId}")`), + ), + ); } // Stop dashboard