* feat: add markdown editor for task descriptions and comments
- Add MarkdownEditor component with formatting toolbar (bold, italic, code, link, list, heading, code block)
- Add MarkdownRenderer component using react-markdown with remark-gfm and rehype-highlight
- Update TaskDetailsTab to use MarkdownEditor for task descriptions with preview
- Update CommentsSection to use MarkdownEditor for comments
- Update TaskCard to render markdown description snippets
- Add markdown settings schema (enableMarkdown, enableCodeHighlighting)
- Add Markdown section to TasksTab settings with feature toggles
- Support Ctrl+B/I/K keyboard shortcuts for formatting
- Respect enableMarkdown toggle to fallback to plain text
- All builds pass, no new lint errors
* fix: address review feedback — route conflict, settings validation, card perf
---------
Co-authored-by: Brad Groux <bradgroux@Brads-Mac-mini.local>
Routes mount at /api/workflows/runs/* not /api/workflow-runs/*.
Fixed in: WorkflowRunView, WorkflowRunList, WorkflowSection,
useWorkflowStats hook.
Fixes: 404 on active runs, stats, and run list endpoints
Toast calls directly in render body caused infinite re-render loop:
render → toast() → state change → render → toast() → ...
Moved all three error toasts into useEffect hooks with proper
dependency arrays.
The list endpoint returns summary objects without steps/agents arrays.
Components were accessing .steps.length and .agents.length without
optional chaining, causing 'Cannot read properties of undefined' errors.
Fixed in: WorkflowsPage, WorkflowRunView, WorkflowRunList,
ActiveRunsList, RecentRunsList
All workflow API endpoints return { success, data, meta } but frontend
components were passing the full envelope to setState instead of extracting
the data array/object. Fixed in WorkflowsPage, WorkflowRunView,
WorkflowRunList, and WorkflowSection.
Fixes: workflows.filter is not a function runtime error
- Add isWorkflowLoading state to handle workflow fetch separately from run fetch
- Fix loading condition to show skeleton while either fetch is pending
- Remove workflow requirement from 'not found' check (only check run)
- Add fallback rendering using run.steps when workflow fetch fails
- Fix effect dependencies to trigger only on workflowId change
- Add proper cancellation pattern with isCancelled flag
- Clear old workflow state when run changes to new ID
Issue: Component could show 'not found' error while workflow was still
loading, or fail to render when workflow fetch failed even with valid
run data.
Impact: High - prevents confusing error states and blank screens during
network delays.
Codex Final Gate Review: 1 blocking issue fixed, 3 non-blocking observations documented.
Quality Gate: TypeCheck passed (web + server)
Final Scores: 10/10/10/10
Status: Ready to merge
- Modified useTaskSync hook to invalidate task-counts cache on task:changed events
- Implemented 250ms debounce to prevent rapid re-fetches during bulk operations
- Counters in BoardSidebar now update instantly when tasks change status
- No new HTTP requests needed — uses existing WebSocket connection
- Typecheck passed with zero errors
Resolves: Real-time task counter updates (Phase 3)
- WorkflowsPage: list all workflows, start runs
- WorkflowRunList: filter and browse runs by status
- WorkflowRunView: live step-by-step progress with WebSocket updates
- WorkflowSection: run workflows from TaskDetailPanel
- Navigation: added Workflows tab to header
- ViewContext: added 'workflows' view type
All components follow existing VK patterns:
- Lazy-loaded like BacklogPage/ArchivePage
- WebSocket live updates for run status
- Color-coded step status (green/blue/red/yellow/gray)
- Resume button for blocked runs
- TypeScript strict, zero errors
Quality gate: typecheck passed ✅
- New GET /api/tasks/counts endpoint for sidebar totals (independent of board filters)
- New useTaskCounts() hook + BoardSidebar rewired
- New bulk endpoints: POST /api/tasks/bulk-update, bulk-archive-by-ids, /api/backlog/bulk-demote
- BulkActionsBar uses single API calls instead of N sequential requests
- Array size validation (max 100) on all bulk endpoints
- Parallel execution via Promise.allSettled() (~26x faster)
- Updated squad chat model field documentation (#106)
- Version bump to 2.1.4
Closes#104, #105
10/10/10/10 reviewed by TARS (gh-sonnet)
- Add squad-post.sh for regular agent messages
- Add squad-event.sh for lifecycle events (spawned/completed/failed/status)
- Add model field to squad messages (types, server, UI, scripts)
- System events render as divider lines in squad chat panel
- Model attribution displays next to agent names in UI
- Full protocol documented in SQUAD-CHAT-PROTOCOL.md
- Updated CONTRIBUTING.md, README.md, and all SOPs
- Added VK_HOST/VK_PORT env vars to .env.example
4-check cross-model review: 10/10 (Code/GPT-5.1, Func/Grok, Perf/Grok, Sec/GPT-5.1)
Agents: R2-D2 (feature), TARS/CASE/Ava/K-2SO (reviews)
- Add autoSaveDelayMs to TaskBehaviorSettings (default: 500ms)
- Update useDebouncedSave hook to use config setting instead of hardcoded value
- Add UI control in Tasks settings tab (slider: 200-5000ms, step 100)
- Add validation schema (min: 200ms, max: 5000ms)
The default 500ms delay was too aggressive for comfortable text editing,
causing interruptions mid-sentence. This makes the delay user-configurable
to accommodate different typing speeds and preferences.
Co-authored-by: OpenClaw Agent <agent@openclaw.ai>
Add individual on/off toggles for each dashboard widget in
Settings > Board & Display. When 'Show Dashboard' is enabled,
a nested list of 12 widget toggles appears:
- Token Usage, Run Duration, Agent Comparison, Status Timeline
- Cost per Task, Agent Utilization, Wall Time, Session Metrics
- Activity Clock, Where Time Went, Hourly Activity, Trends Charts
All default to ON. Server-side Zod schema updated to accept
the new dashboardWidgets object. Shared types already had the
DashboardWidgetSettings interface from a prior commit.
Archive:
- Optimistic removal from cache on archive (instant UI update)
- Rollback on error, refetch on settle
Agent Registry:
- Fix RegistryStats interface to match server (total/online/busy/idle/offline)
- Add 'idle' status style (blue) to MultiAgentPanel
- Panel already dynamic — no hardcoded agent limit
Cost Per Task:
- Enhanced clickable styling (border, hover highlight, arrow indicator)
- Tasks already wired to open-task event
Telemetry:
- Capped 3 Feb 2 outliers from 15-19min to 10min
- Token events verified present for Feb 3-5 (backfilled earlier)
Data fixes:
- Backfill agent='veritas' on 987 telemetry events (were 'unknown')
- Backfill run.tokens events for Feb 3-5 (46 events, estimated from durations)
- Reset stuck agent status to idle
Utilization:
- Switch from status-history (1 entry!) to telemetry-based computation
- Timezone-aware date bucketing via tz query param
- Current day uses elapsed time, not full 24h
Dashboard layout:
- Remove Success Rate chart (redundant with Session Metrics)
- Task Activity Per Day now full width
- Fix tooltip info icons (delayDuration=0, asChild, button wrapper)
- Default period changed from 3d to 7d (token data starts Jan 31)
- Add ?tz=<offset> to metrics endpoints (e.g. ?tz=-6 for CST, ?tz=9 for JST)
- Server defaults to system time when tz is omitted
- Client auto-sends browser timezone offset on utilization requests
- Shared helpers: toLocalDateStr(), getTodayStr(), getElapsedTodayMs()
- Date bucketing and 'today' detection respect the requested timezone
- Works for any timezone — not hardcoded to any region
- Fix daily utilization: use elapsed time for current day (was 100% because
active time ÷ 0 hours elapsed = infinity, capped to 100%)
- Activity Clock + Hourly Activity: switch from broken activity.json (1 record)
to status-history endpoint (has actual agent state transitions)
- Task-cost API: add project + totalDurationMs fields for Where Time Went
- Where Time Went: pull real project data from task-cost telemetry
- Wall Time toggle: rewrite with clear labels + info tooltips
- Normalize Feb 3 telemetry outlier (66min → 19min)
GH #92 created: Dashboard widget toggles with descriptions
- Remove Success/Errors card (Sessions widget covers it)
- Activity Over Time: add Y-axis 'Events' label
- Where Time Went: pull real data from telemetry by project (was blank)
- Wall Time: rewrite as Total Agent Time + Avg Run Duration with tooltips
- Activity Clock: add info tooltip explaining the visualization
- Agent Comparison: lower minRuns to 1 so all agents show
- Task-cost API: add project + totalDurationMs fields for widgets
- Normalize Feb 3 time outlier (66min → 19min, capped at p95)
- TrendsCharts (Task Activity per Day): full width layout