Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions apps/frontend/src/main/ipc-handlers/task/execution-handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,11 @@ export function registerTaskExecutionHandlers(

console.warn('[TASK_START] Found task:', task.specId, 'status:', task.status, 'reviewReason:', task.reviewReason, 'subtasks:', task.subtasks.length);

// Clear stale tracking state from any previous execution so that:
// - terminalEventSeen doesn't suppress future PROCESS_EXITED events
// - lastSequenceByTask doesn't drop events from the new process
taskStateManager.prepareForRestart(taskId);

// Immediately mark as started so the UI moves the card to In Progress.
// Use XState actor state as source of truth (if actor exists), with task data as fallback.
// - plan_review: User approved the plan, send PLAN_APPROVED to transition to coding
Expand Down Expand Up @@ -315,6 +320,9 @@ export function registerTaskExecutionHandlers(
task,
project
);

// Clear stale tracking state so a subsequent restart works correctly
taskStateManager.prepareForRestart(taskId);
});

/**
Expand Down Expand Up @@ -658,6 +666,8 @@ export function registerTaskExecutionHandlers(

// Auto-start task when status changes to 'in_progress' and no process is running
if (status === 'in_progress' && !agentManager.isRunning(taskId)) {
// Clear stale tracking state before starting a new process
taskStateManager.prepareForRestart(taskId);
const mainWindow = getMainWindow();

// Check git status before auto-starting
Expand Down Expand Up @@ -1070,6 +1080,8 @@ export function registerTaskExecutionHandlers(
// Auto-restart the task if requested
let autoRestarted = false;
if (autoRestart) {
// Clear stale tracking state before restarting
taskStateManager.prepareForRestart(taskId);
// Check git status before auto-restarting
const gitStatusForRestart = checkGitStatus(project.path);
if (!gitStatusForRestart.isGitRepo || !gitStatusForRestart.hasCommits) {
Expand Down
12 changes: 12 additions & 0 deletions apps/frontend/src/main/task-state-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,18 @@ export class TaskStateManager {
return this.getCurrentState(taskId) === 'plan_review';
}

/**
* Reset tracking state for a task that is about to be restarted.
* Clears terminalEventSeen (so process exits aren't swallowed) and
* lastSequenceByTask (so events from the new process aren't dropped
* as duplicates). Does NOT stop or remove the XState actor, since
* the caller may still need to send events to it.
*/
prepareForRestart(taskId: string): void {
this.terminalEventSeen.delete(taskId);
this.lastSequenceByTask.delete(taskId);
}

clearTask(taskId: string): void {
this.lastSequenceByTask.delete(taskId);
this.lastStateByTask.delete(taskId);
Expand Down
Loading