diff --git a/index.ts b/index.ts index b00553e..b658a79 100644 --- a/index.ts +++ b/index.ts @@ -356,6 +356,10 @@ async function handleRun( const mode = await selectExecutionMode(ctx, project, taskFile); const plan = buildPlanByMode(mode, project, completed); + // Show execution plan before starting so user can see batch breakdown + const formattedPlan = formatExecutionPlan(plan); + ctx.ui.notify(`${formattedPlan}\n\nStarting ${mode} execution...`, "info"); + await executePlanBatches( plan, project, diff --git a/src/executor.ts b/src/executor.ts index 841a33f..7be049c 100644 --- a/src/executor.ts +++ b/src/executor.ts @@ -74,6 +74,8 @@ export async function runTask( // Live progress widget above the editor — animated spinner + tool call tree // Using setWidget instead of setWorkingMessage because the working message area // is only visible during parent agent streaming, not during extension command execution. + // Widget key is unique per task so parallel tasks each get their own widget. + const widgetKey = `ralph-task-${task.id}`; const SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]; let frameIndex = 0; const theme = ctx.ui.theme; @@ -102,7 +104,7 @@ export async function runTask( } } - ctx.ui.setWidget("ralph-task", lines); + ctx.ui.setWidget(widgetKey, lines); }; // Smooth spinner animation at 100ms intervals @@ -138,7 +140,7 @@ export async function runTask( // Clear progress widget and status after task finishes clearInterval(spinnerTimer); - ctx.ui.setWidget("ralph-task", undefined); + ctx.ui.setWidget(widgetKey, undefined); ctx.ui.setStatus("ralph", undefined); if (!output.success) { diff --git a/src/parser.ts b/src/parser.ts index a0c9970..f00bab9 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -90,7 +90,10 @@ function parseFioFormat( if (inDeps) { // Format 2: Arrow notation with multiple targets // "01 -> 02,03,06 (description)" means 02, 03, 06 depend on 01 - const arrowMatch = line.match(/^(\d+)\s*->\s*([\d,\s]+?)(?:\s*\(|$)/); + // Supports optional markdown list prefix: "- 01 -> 02,03,06" + const arrowMatch = line.match( + /^(?:\s*[-*]\s+)?(\d+)\s*->\s*([\d,\s]+?)(?:\s*\(|$)/, + ); if (arrowMatch) { const [, from, targets] = arrowMatch; const fromId = `0${from}`; @@ -108,7 +111,10 @@ function parseFioFormat( } // Format 1: Natural language "X depends on A, B, C" - const dependsMatch = line.match(/^(\d+)\s+depends\s+on\s+([\d,\s]+)/i); + // Supports optional markdown list prefix: "- 13 depends on 17, 18, 19" + const dependsMatch = line.match( + /^(?:\s*[-*]\s+)?(\d+)\s+depends\s+on\s+([\d,\s]+)/i, + ); if (dependsMatch) { const [, taskId, depsList] = dependsMatch; const taskIdPadded = `0${taskId}`;