diff --git a/apps/ui/src/components/ui/task-progress-panel.tsx b/apps/ui/src/components/ui/task-progress-panel.tsx index 5cb5826f..414be1e7 100644 --- a/apps/ui/src/components/ui/task-progress-panel.tsx +++ b/apps/ui/src/components/ui/task-progress-panel.tsx @@ -230,7 +230,7 @@ export function TaskProgressPanel({ )} >
-
+
{/* Vertical Connector Line */}
diff --git a/apps/ui/src/components/views/board-view/components/kanban-card/agent-info-panel.tsx b/apps/ui/src/components/views/board-view/components/kanban-card/agent-info-panel.tsx index 87268652..60eba50f 100644 --- a/apps/ui/src/components/views/board-view/components/kanban-card/agent-info-panel.tsx +++ b/apps/ui/src/components/views/board-view/components/kanban-card/agent-info-panel.tsx @@ -1,6 +1,6 @@ // @ts-nocheck -import { useEffect, useState } from 'react'; -import { Feature, ThinkingLevel } from '@/store/app-store'; +import { useEffect, useState, useMemo } from 'react'; +import { Feature, ThinkingLevel, ParsedTask } from '@/store/app-store'; import type { ReasoningEffort } from '@automaker/types'; import { getProviderFromModel } from '@/lib/utils'; import { @@ -72,6 +72,22 @@ export function AgentInfoPanel({ const [isSummaryDialogOpen, setIsSummaryDialogOpen] = useState(false); const [isTodosExpanded, setIsTodosExpanded] = useState(false); + // Derive effective todos from planSpec.tasks when available, fallback to agentInfo.todos + // This fixes the issue where Kanban cards show "0/0 tasks" when the agent uses planSpec + // instead of emitting TodoWrite tool calls in the output log + const effectiveTodos = useMemo(() => { + // First priority: use planSpec.tasks if available (modern approach) + if (feature.planSpec?.tasks && feature.planSpec.tasks.length > 0) { + return feature.planSpec.tasks.map((task: ParsedTask) => ({ + content: task.description, + // Map 'failed' status to 'pending' since todo display doesn't support 'failed' + status: task.status === 'failed' ? 'pending' : task.status, + })); + } + // Fallback: use parsed agentInfo.todos from agent-output.md + return agentInfo?.todos || []; + }, [feature.planSpec?.tasks, agentInfo?.todos]); + useEffect(() => { const loadContext = async () => { if (contextContent) { @@ -189,13 +205,13 @@ export function AgentInfoPanel({
{/* Task List Progress */} - {agentInfo.todos.length > 0 && ( + {effectiveTodos.length > 0 && (
- {agentInfo.todos.filter((t) => t.status === 'completed').length}/ - {agentInfo.todos.length} tasks + {effectiveTodos.filter((t) => t.status === 'completed').length}/ + {effectiveTodos.length} tasks
- {(isTodosExpanded ? agentInfo.todos : agentInfo.todos.slice(0, 3)).map( + {(isTodosExpanded ? effectiveTodos : effectiveTodos.slice(0, 3)).map( (todo, idx) => (
{todo.status === 'completed' ? ( @@ -227,7 +243,7 @@ export function AgentInfoPanel({
) )} - {agentInfo.todos.length > 3 && ( + {effectiveTodos.length > 3 && ( )}
@@ -286,10 +302,10 @@ export function AgentInfoPanel({ {agentInfo.toolCallCount} tool calls - {agentInfo.todos.length > 0 && ( + {effectiveTodos.length > 0 && ( - {agentInfo.todos.filter((t) => t.status === 'completed').length} tasks done + {effectiveTodos.filter((t) => t.status === 'completed').length} tasks done )}
diff --git a/apps/ui/src/components/views/board-view/dialogs/agent-output-modal.tsx b/apps/ui/src/components/views/board-view/dialogs/agent-output-modal.tsx index 7b900409..f96c5807 100644 --- a/apps/ui/src/components/views/board-view/dialogs/agent-output-modal.tsx +++ b/apps/ui/src/components/views/board-view/dialogs/agent-output-modal.tsx @@ -380,11 +380,11 @@ export function AgentOutputModal({ {effectiveViewMode === 'changes' ? ( -
+
{projectPath ? ( ) : effectiveViewMode === 'summary' && summary ? ( -
+
{summary}
) : ( @@ -409,7 +409,7 @@ export function AgentOutputModal({
{isLoading && !output ? (