- Add broadcast-service.ts that sends task:changed events to all
connected WebSocket clients on any task mutation
- Wire broadcasts into task routes (create, update, delete, archive,
restore, reorder)
- Add useTaskSync hook — connects to WS, listens for task:changed,
invalidates React Query cache for instant board updates
- Add polling fallback: refetchInterval=10s, staleTime=5s on useTasks
- Auto-reconnect WebSocket with 3s backoff on disconnect
Board now updates within seconds of any external change (API calls
from Clawdbot agents, CLI, etc.) without manual page refresh.
Fixes: task_20260128_Zk4oV0
- Add readOnly prop to TaskDetailPanel — shows archived badge,
displays all fields as non-editable text, hides delete/template buttons,
shows 'Restore to Board' button instead
- Wire up task click in ArchiveSidebar to open read-only detail panel
- Add pagination to archive list (25 per page with 'Load More' button)
- Show results count when filters reduce the list
- ArchiveSidebar now manages its own detail panel internally
Fixes: task_20260128_tDh8SO
- Add position field to Task type (shared/types.ts)
- Add POST /api/tasks/reorder endpoint to persist ordering
- Update task-service with reorderTasks() method
- Switch TaskCard from useDraggable to useSortable (@dnd-kit/sortable)
- Wrap KanbanColumn tasks in SortableContext with verticalListSortingStrategy
- Update KanbanBoard DnD handlers to support both within-column reorder
and cross-column status changes
- Sort tasks by position in useTasksByStatus hook
- Use closestCorners collision detection for better sortable support
Fixes: task_20260128_4qCzGr
- stopTimer() set activeEntryId: undefined which js-yaml cannot serialize
- Changed to omit activeEntryId when clearing (conditional spread)
- Same fix in deleteTimeEntry() for active entry deletion
- Added deepCleanUndefined() to taskToMarkdown() as defense-in-depth
- Imported TimeTracking type for explicit typing
Fixes: task_20260128_RrQUWH
- Added SprintConfig interface extending ManagedListItem in shared types
- Created SprintService with seed migration from existing tasks
- Added /api/sprints endpoints using managed list router pattern
- Implemented useSprints and useSprintsManager hooks
- Updated TaskDetailPanel and CreateTaskDialog to use dynamic sprint list
- Added sprint management UI to SettingsDialog
- Sprint IDs match existing task.sprint values for backward compatibility
- Reference counter prevents deletion of sprints with tasks
- US-700 series (archive): US-701 through US-711
- US-800 series (archive): US-801 through US-808
- US-900 series (active): US-901 through US-919
- Created US-917 (sprint assignment), US-918 (subtask count), US-919 (task type on cards)
- All three marked done with closing comments
- Fixed path traversal in attachment filename sanitization
- Fixed Radix Select crash: empty string value ('') not supported
Changed 'No project' SelectItem from value='' to value='__none__'
in both TaskDetailPanel and CreateTaskDialog
- Updated task type colors: removed Rose, added bright Pink (fuchsia),
darkened Blue (700), darkened Green (700), added Yellow, added Brown
- Removed isDefault protection from delete (any item can be deleted)
- Removed hide/show toggle button from ManagedListManager
- Delete still blocked if item has task references (with clear message)
- Cleaned up isHidden flags from task-types.json
- Simplified delete dialog messaging
- ProjectService.init() had infinite recursion: list() → init() → seed → list() → init()...
- TagService seed checked file existence (always true after super.init creates it)
- Seed migrations now use seedItem() with raw project/tag strings as IDs
so they match existing task.project and task.tags values
- Added seedItem() to ManagedListService base for custom-ID seeding
- Cleaned up task-types.json (removed duplicate, restored Research)
PHASE 1: US-915 ManagedListService Foundation
- Added ManagedListItem and ManagedListServiceOptions types to shared/src/types.ts
- Created ManagedListService<T> base class with full CRUD, reorder, and reference checking
- Created createManagedListRouter factory for generic Express routes
- Created useManagedList hook for React with TanStack Query integration
- Added managedList API helpers to web/src/lib/api.ts
- Created ManagedListManager React component with drag-to-reorder using @dnd-kit
PHASE 2: US-913 Custom Task Types
- Changed TaskType from union to string in shared types
- Added TaskTypeConfig interface extending ManagedListItem with icon and color
- Created TaskTypeService using ManagedListService with 4 built-in default types
- Registered task-types routes at /api/task-types
- Updated server validation in tasks.ts and templates.ts to accept dynamic types
- Created useTaskTypes hook with helper functions (getTypeIcon, getTypeLabel, etc.)
- Updated FilterBar to use dynamic task types
- Updated TaskCard to accept and use dynamic task types
- Updated KanbanBoard and KanbanColumn to fetch and pass task types
- Updated TaskDetailPanel to use dynamic task types
- Updated CreateTaskDialog to use dynamic task types
- Updated SettingsDialog template form to use dynamic task types
- Added Task Types management section to Settings with full CRUD and customization
- Added taskTypes API namespace to web/src/lib/api.ts
All UI components now render task types dynamically from .veritas-kanban/task-types.json
Icon and color customization available in Settings with 20+ Lucide icons and 10 colors
- Export all templates as JSON file
- Import templates from JSON file with duplicate detection
- template-io utility for file handling and validation
- Import/Export buttons in SettingsDialog templates section
- Duplicates skipped during import with notification
- Add agent field to template editor (preferred agent for code tasks)
- Agent selector in AddTemplateForm with all available agents
- Agent displayed in template list alongside other defaults
- Templates can specify preferred agent (claude-code, amp, copilot, gemini, veritas)
- Add template-variables utility with support for {{date}}, {{datetime}}, {{project}}, {{author}}, {{custom:label}}
- Extract custom variables from templates and prompt user for values
- Interpolate variables in description and subtask titles on task creation
- Display custom variable input form in CreateTaskDialog
- Variables resolved at creation time for dynamic content
- Add subtasks field to CreateTaskInput
- Task service creates subtasks from template when task is created
- CreateTaskDialog displays subtasks from template
- Users can remove individual subtasks before creating
- Subtasks sorted by order field and auto-generated with IDs
- Extend TaskTemplate with version, category, tags, agent, subtaskTemplates, and blueprint fields
- Add SubtaskTemplate and BlueprintTask interfaces
- Implement v0 to v1 migration in template service (backward compatible)
- Export template types from shared package
- Server validates enhanced schema on create/update
TraceService:
- 4 coarse step types: init, execute, complete, error
- Trace ID = Attempt ID for natural correlation
- Traces stored as JSON files in .veritas-kanban/traces/
- Off by default (enable via POST /api/traces/enable)
API Endpoints:
- GET /api/traces/status — Check if tracing is enabled
- POST /api/traces/enable — Enable tracing
- POST /api/traces/disable — Disable tracing
- GET /api/traces/:attemptId — Get a specific trace
- GET /api/traces/task/:taskId — List all traces for a task
AgentService Integration:
- Automatically records trace steps when tracing is enabled
- init: worktree setup, prompt building
- execute: agent process running
- complete: post-run processing
- error: captures error details
New endpoints:
- GET /api/metrics/tasks — Task counts by status, total, completed, archived
- GET /api/metrics/runs?period=24h|7d — Error rate, success rate, run counts
- GET /api/metrics/tokens?period=24h|7d — Token totals, per-run stats (avg, p50, p95)
- GET /api/metrics/duration?period=24h|7d — Duration stats (avg, p50, p95)
- GET /api/metrics/all?period=24h|7d — All metrics in one call
All endpoints support optional project filter.