+
{/* 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 ? (