From c1ee77eb337a89b80ab4f0201bb37c1a41f652b1 Mon Sep 17 00:00:00 2001 From: Brad Groux Date: Wed, 28 Jan 2026 06:51:28 -0600 Subject: [PATCH] =?UTF-8?q?US-1502/1503/1504:=20Propagate=20review=20?= =?UTF-8?q?=E2=86=92=20blocked=20across=20entire=20codebase?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Frontend (US-1502 & US-1503): - KanbanBoard.tsx: Column id/title changed to 'blocked'/'Blocked' - KanbanColumn.tsx: Color changed from amber-500 to red-500 - Dashboard.tsx: Metric card label/icon/color updated - TaskMetadataSection.tsx: Status label updated - useKeyboard.tsx: Keyboard shortcuts updated - useTasks.ts: tasksByStatus keys updated Backend (US-1504): - automation.ts: Task status on completion changed - notifications.ts: Status check updated - summary.ts: Status filtering updated - clawdbot-agent-service.ts: Success now sets 'done' instead of 'review' - metrics-service.ts: Status keys updated --- .../telemetry/events-2026-01-28.ndjson | 2 ++ server/.veritas-kanban/activity.json | 33 +++++++++++++++++++ server/src/routes/automation.ts | 4 +-- server/src/routes/notifications.ts | 2 +- server/src/routes/summary.ts | 4 +-- server/src/services/clawdbot-agent-service.ts | 2 +- server/src/services/metrics-service.ts | 2 +- web/src/components/board/KanbanBoard.tsx | 2 +- web/src/components/board/KanbanColumn.tsx | 2 +- web/src/components/dashboard/Dashboard.tsx | 10 +++--- .../task/detail/TaskMetadataSection.tsx | 2 +- web/src/hooks/useKeyboard.tsx | 4 +-- web/src/hooks/useTasks.ts | 4 +-- 13 files changed, 54 insertions(+), 19 deletions(-) diff --git a/.veritas-kanban/telemetry/events-2026-01-28.ndjson b/.veritas-kanban/telemetry/events-2026-01-28.ndjson index d0be1c15..fe7f2e5e 100644 --- a/.veritas-kanban/telemetry/events-2026-01-28.ndjson +++ b/.veritas-kanban/telemetry/events-2026-01-28.ndjson @@ -604,3 +604,5 @@ {"type":"task.status_changed","taskId":"task_20260128_ksQUvs","project":"veritas-kanban","status":"in-progress","previousStatus":"todo","id":"evt_WyBRK_mNhgAl","timestamp":"2026-01-28T12:34:14.344Z"} {"type":"task.status_changed","taskId":"task_20260128_ksQUvs","project":"veritas-kanban","status":"done","previousStatus":"in-progress","id":"evt_W2qXAeCbQMx-","timestamp":"2026-01-28T12:45:58.771Z"} {"type":"task.status_changed","taskId":"task_20260128_-WSaw3","project":"veritas-kanban","status":"in-progress","previousStatus":"todo","id":"evt_5rubDBi7a4sp","timestamp":"2026-01-28T12:46:18.174Z"} +{"type":"task.status_changed","taskId":"task_20260128_-WSaw3","project":"veritas-kanban","status":"done","previousStatus":"in-progress","id":"evt_FnNCrt7n93W-","timestamp":"2026-01-28T12:48:06.446Z"} +{"type":"task.status_changed","taskId":"task_20260128_iFFyez","project":"veritas-kanban","status":"in-progress","previousStatus":"todo","id":"evt_V84NFTY9QFuT","timestamp":"2026-01-28T12:48:25.548Z"} diff --git a/server/.veritas-kanban/activity.json b/server/.veritas-kanban/activity.json index 3f7020ab..400ee9ff 100644 --- a/server/.veritas-kanban/activity.json +++ b/server/.veritas-kanban/activity.json @@ -1,4 +1,37 @@ [ + { + "id": "activity_1769604505548_u0nvgi0nq", + "type": "status_changed", + "taskId": "task_20260128_iFFyez", + "taskTitle": "US-1502: Update Kanban column display — Blocked title + red color", + "details": { + "from": "todo", + "status": "in-progress" + }, + "timestamp": "2026-01-28T12:48:25.548Z" + }, + { + "id": "activity_1769604486483_yln4lo1t6", + "type": "comment_added", + "taskId": "task_20260128_-WSaw3", + "taskTitle": "US-1501: Rename TaskStatus review → blocked in shared types", + "details": { + "author": "Veritas", + "preview": "Updated TaskStatus from review → blocked in types ..." + }, + "timestamp": "2026-01-28T12:48:06.483Z" + }, + { + "id": "activity_1769604486446_s45ozs78g", + "type": "status_changed", + "taskId": "task_20260128_-WSaw3", + "taskTitle": "US-1501: Rename TaskStatus review → blocked in shared types", + "details": { + "from": "in-progress", + "status": "done" + }, + "timestamp": "2026-01-28T12:48:06.446Z" + }, { "id": "activity_1769604473427_cksmodaid", "type": "task_updated", diff --git a/server/src/routes/automation.ts b/server/src/routes/automation.ts index 857599c6..bd708367 100644 --- a/server/src/routes/automation.ts +++ b/server/src/routes/automation.ts @@ -81,7 +81,7 @@ router.post('/:taskId/complete', async (req, res) => { // Update task const updated = await taskService.updateTask(task.id, { - status: isSuccess ? 'done' : 'review', + status: isSuccess ? 'done' : 'blocked', attempt: { ...task.attempt, status: isSuccess ? 'complete' : 'failed', @@ -119,7 +119,7 @@ router.get('/pending', async (_req, res) => { const pending = tasks.filter(task => { if (task.type !== 'automation') return false; if (task.status === 'todo') return true; - if (task.status === 'review' && task.attempt?.agent === 'veritas' && task.attempt?.status === 'failed') { + if (task.status === 'blocked' && task.attempt?.agent === 'veritas' && task.attempt?.status === 'failed') { return true; // Failed, might need retry } return false; diff --git a/server/src/routes/notifications.ts b/server/src/routes/notifications.ts index 3e92ebee..d33edde7 100644 --- a/server/src/routes/notifications.ts +++ b/server/src/routes/notifications.ts @@ -194,7 +194,7 @@ router.post('/check', asyncHandler(async (_req, res) => { // Check for tasks in review (needs review notification) const inReview = tasks.filter(t => - t.status === 'review' && + t.status === 'blocked' && t.attempt?.status === 'complete' && t.attempt?.agent !== 'veritas' ); diff --git a/server/src/routes/summary.ts b/server/src/routes/summary.ts index fb26f1b6..5d10dd4d 100644 --- a/server/src/routes/summary.ts +++ b/server/src/routes/summary.ts @@ -12,7 +12,7 @@ router.get('/', async (_req, res) => { const byStatus = { todo: tasks.filter(t => t.status === 'todo').length, 'in-progress': tasks.filter(t => t.status === 'in-progress').length, - review: tasks.filter(t => t.status === 'review').length, + blocked: tasks.filter(t => t.status === 'blocked').length, done: tasks.filter(t => t.status === 'done').length, }; @@ -113,7 +113,7 @@ router.get('/memory', async (req, res) => { // Active high-priority const highPriority = tasks.filter(t => t.priority === 'high' && - (t.status === 'in-progress' || t.status === 'review') + (t.status === 'in-progress' || t.status === 'blocked') ); // Build markdown diff --git a/server/src/services/clawdbot-agent-service.ts b/server/src/services/clawdbot-agent-service.ts index ca1913ca..ffe309f5 100644 --- a/server/src/services/clawdbot-agent-service.ts +++ b/server/src/services/clawdbot-agent-service.ts @@ -195,7 +195,7 @@ export class ClawdbotAgentService { // Update task await this.taskService.updateTask(taskId, { - status: result.success ? 'review' : 'in-progress', + status: result.success ? 'done' : 'in-progress', attempt: { id: attemptId, agent: pending.agent, diff --git a/server/src/services/metrics-service.ts b/server/src/services/metrics-service.ts index a0766acb..90595bfa 100644 --- a/server/src/services/metrics-service.ts +++ b/server/src/services/metrics-service.ts @@ -99,7 +99,7 @@ export class MetricsService { const byStatus: Record = { 'todo': 0, 'in-progress': 0, - 'review': 0, + 'blocked': 0, 'done': 0, }; diff --git a/web/src/components/board/KanbanBoard.tsx b/web/src/components/board/KanbanBoard.tsx index 38291d4b..53f2e47c 100644 --- a/web/src/components/board/KanbanBoard.tsx +++ b/web/src/components/board/KanbanBoard.tsx @@ -34,7 +34,7 @@ import FeatureErrorBoundary from '@/components/shared/FeatureErrorBoundary'; const COLUMNS: { id: TaskStatus; title: string }[] = [ { id: 'todo', title: 'To Do' }, { id: 'in-progress', title: 'In Progress' }, - { id: 'review', title: 'Review' }, + { id: 'blocked', title: 'Blocked' }, { id: 'done', title: 'Done' }, ]; diff --git a/web/src/components/board/KanbanColumn.tsx b/web/src/components/board/KanbanColumn.tsx index 0bf3ceb5..6aaf86a8 100644 --- a/web/src/components/board/KanbanColumn.tsx +++ b/web/src/components/board/KanbanColumn.tsx @@ -17,7 +17,7 @@ interface KanbanColumnProps { const columnColors: Record = { 'todo': 'border-t-slate-500', 'in-progress': 'border-t-blue-500', - 'review': 'border-t-amber-500', + 'blocked': 'border-t-red-500', 'done': 'border-t-green-500', }; diff --git a/web/src/components/dashboard/Dashboard.tsx b/web/src/components/dashboard/Dashboard.tsx index 5484182f..c7bb0aeb 100644 --- a/web/src/components/dashboard/Dashboard.tsx +++ b/web/src/components/dashboard/Dashboard.tsx @@ -20,7 +20,7 @@ import { Archive, ListTodo, Play, - Eye, + Ban, RefreshCw } from 'lucide-react'; import { cn } from '@/lib/utils'; @@ -196,10 +196,10 @@ export function Dashboard() { color="blue" /> } - color="yellow" + label="Blocked" + value={metrics.tasks.byStatus['blocked'] || 0} + icon={} + color="red" /> = { 'todo': 'To Do', 'in-progress': 'In Progress', - 'review': 'Review', + 'blocked': 'Blocked', 'done': 'Done', }; diff --git a/web/src/hooks/useKeyboard.tsx b/web/src/hooks/useKeyboard.tsx index 67da94b8..7d5da604 100644 --- a/web/src/hooks/useKeyboard.tsx +++ b/web/src/hooks/useKeyboard.tsx @@ -28,7 +28,7 @@ const KeyboardContext = createContext(null); const STATUS_MAP: Record = { '1': 'todo', '2': 'in-progress', - '3': 'review', + '3': 'blocked', '4': 'done', }; @@ -68,7 +68,7 @@ export function KeyboardProvider({ children }: { children: ReactNode }) { // Get flat list of tasks sorted by column then position const getTaskList = useCallback(() => { - const statusOrder: TaskStatus[] = ['todo', 'in-progress', 'review', 'done']; + const statusOrder: TaskStatus[] = ['todo', 'in-progress', 'blocked', 'done']; return [...tasks].sort((a, b) => { const aIndex = statusOrder.indexOf(a.status); const bIndex = statusOrder.indexOf(b.status); diff --git a/web/src/hooks/useTasks.ts b/web/src/hooks/useTasks.ts index a6a60d7d..f5049217 100644 --- a/web/src/hooks/useTasks.ts +++ b/web/src/hooks/useTasks.ts @@ -204,7 +204,7 @@ export function useTasksByStatus(tasks: Task[] | undefined) { return { todo: [], 'in-progress': [], - review: [], + blocked: [], done: [], }; } @@ -212,7 +212,7 @@ export function useTasksByStatus(tasks: Task[] | undefined) { return { todo: sortByPosition(tasks.filter(t => t.status === 'todo')), 'in-progress': sortByPosition(tasks.filter(t => t.status === 'in-progress')), - review: sortByPosition(tasks.filter(t => t.status === 'review')), + blocked: sortByPosition(tasks.filter(t => t.status === 'blocked')), done: sortByPosition(tasks.filter(t => t.status === 'done')), }; }