Skip to content

Comments

intake(lote-A): import upstream PR #1833#5

Open
nsalvacao wants to merge 8 commits intobaseline/develop-sync-2026-02-17from
intake/lote-A-pr-1833
Open

intake(lote-A): import upstream PR #1833#5
nsalvacao wants to merge 8 commits intobaseline/develop-sync-2026-02-17from
intake/lote-A-pr-1833

Conversation

@nsalvacao
Copy link
Owner

@nsalvacao nsalvacao commented Feb 17, 2026

Upstream intake PR for isolated review.

Checklist:

  • Automated checks green
  • Bot review comments triaged
  • Manual review complete
  • Safe for baseline merge

AndyMik90 and others added 8 commits February 17, 2026 15:32
When an agent process exits with incomplete/stuck subtasks, the task gets
stuck in the Kanban UI — it spins forever, can't be stopped, and can't be
dragged back to planning.

This fix addresses 5 specific state synchronization gaps between the backend
process lifecycle and the frontend XState state machine:

1. Reset execution progress on terminal state transitions (task-store.ts)
   - When tasks reach terminal states (human_review, error, done, pr_created),
     execution progress is now reset to idle
   - Prevents stuck tasks from showing stale progress indicators in UI

2. Propagate final phase updates even after XState settles (agent-events-handlers.ts)
   - Final 'complete' or 'failed' phase updates are now sent to renderer
   - Previously these were silently dropped, causing UI to never show completion

3. Add fallback exit handler to force state transition (agent-events-handlers.ts)
   - If task remains in_progress 500ms after process exit, force to human_review
   - Safety net for when XState fails to properly handle PROCESS_EXITED event

4. Disable dragging for in_progress tasks (SortableTaskCard.tsx)
   - Prevents users from dragging tasks that are currently running or stuck
   - Adds disabled flag to useSortable hook when status is 'in_progress'

5. Allow stop button for stuck tasks (TaskCard.tsx)
   - Users can now force-stop stuck tasks using the stop button
   - Removed the isStuck check that prevented stopping stuck tasks

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The 500ms fallback safety net was calling `taskStateManager.forceTransition()`
which doesn't exist, causing TypeScript compilation errors.

Fixed to:
- Use `handleUiEvent()` with `USER_STOPPED` event (proper XState transition)
- Look up both task and project fresh (avoid stale closure references)
- Add null check for `checkProject` before proceeding

This ensures the fallback actually works when XState fails to transition
tasks out of in_progress after process exit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add named constant STUCK_TASK_FALLBACK_TIMEOUT_MS for magic number
- Use XState getCurrentState() instead of cached task status to avoid stale cache issues
- Check XState active states directly (planning, coding, qa_review, qa_fixing)
- Improve logging to show actual XState state name
- Add inline comments explaining the stale cache avoidance strategy

This resolves all 3 blocking issues from the Auto Claude review:
1. CRITICAL: forceTransition() method - fixed by using handleUiEvent()
2. MEDIUM: Stale closure - fixed by checking XState directly
3. MEDIUM: Magic number - fixed by using named constant

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…onstants

Resolves NEW-001 and CMT-001 from the follow-up review:
- Extract XSTATE_ACTIVE_STATES to shared constant in task-state-utils.ts
- Export XSTATE_ACTIVE_STATES from state-machines index
- Replace hardcoded hasPlan: true with dynamic plan file check
- Pattern matches TASK_STOP handler (execution-handlers.ts lines 299-310)
- Tasks stuck in 'planning' state now correctly route to backlog, not human_review
- Improved logging shows hasPlan value for debugging

This ensures the fallback safety net routes tasks to the correct Kanban column
based on whether a plan file exists with subtasks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract hasPlan logic into shared hasPlanWithSubtasks() utility in plan-file-utils.ts
  to eliminate duplication and centralize plan validation logic
- Make setTimeout callback async to avoid blocking readFileSync in event loop
- Replace hardcoded terminal status check with cleaner .includes() pattern
- Add status gate for final phase updates to prevent UI flicker when failed
  phase arrives after task has transitioned to human_review
- Import and use hasPlanWithSubtasks in agent-events-handlers.ts

All review comments addressed:
- Gemini: Critical/Medium - forceTransition method, magic number (already fixed in previous commit)
- Gemini: Medium - hardcoded status list (now uses .includes)
- CodeRabbit: Trivial - extract XSTATE_ACTIVE_STATES (already fixed in previous commit)
- CodeRabbit: Minor - derive hasPlan from file check (now uses shared utility)
- CodeRabbit: Minor - prevent UI flicker from final phase updates (now gates on status)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixed all 3 findings from the latest auto-claude review:

1. [NCR-NEW-001] MEDIUM: Fallback safety net timeout race condition
   - Store setTimeout timer reference in a Map keyed by taskId
   - Export cancelFallbackTimer() function to clear pending timers
   - Call cancelFallbackTimer() at start of TASK_START handler
   - Prevents stale timer from incorrectly stopping newly restarted tasks
   - Clean up timer reference after it fires

2. [CMT-NEW-001] LOW: Duplicate hasPlan detection logic
   - Replace inline hasPlan logic in execution-handlers.ts TASK_STOP
   - Use shared hasPlanWithSubtasks() utility from plan-file-utils.ts
   - Eliminates code duplication and ensures consistent behavior

3. [CMT-001] LOW: Misleading async keyword
   - Remove async from setTimeout callback in agent-events-handlers.ts
   - No await expressions exist in the callback
   - All operations (getCurrentState, hasPlanWithSubtasks) are synchronous

All changes maintain backward compatibility and fix the race condition
where restarting a task within 500ms could be incorrectly stopped by
the fallback timer from the previous process exit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The fallback safety net timer was only cancelled in the TASK_START handler,
but not in the TASK_UPDATE_STATUS auto-start path or TASK_RECOVER_STUCK
auto-restart path. This meant a stale timer could incorrectly stop a
newly restarted task if it was restarted within the 500ms window via
drag-to-in-progress or recovery auto-restart.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gemini-code-assist
Copy link

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants