- Cost Prediction Service: predicts task cost based on type, priority, complexity, history
- Prediction factors: type multiplier, priority multiplier, description complexity, project adjustment
- Historical base cost: calculated from telemetry data for similar tasks
- Confidence levels: low/medium/high based on sample size
- Accuracy tracking: predicted vs actual cost comparison for completed tasks
- Accuracy stats: MAE, mean/median accuracy, within-20%/50% metrics, per-type breakdown
- Task schema: added costPrediction and actualCost fields
- REST API: POST /predict, GET /accuracy, GET /accuracy/stats
- Agent Registry Service: registration, heartbeat, capability discovery, stale detection
- REST API: POST /register, POST /:id/heartbeat, DELETE /:id, GET /stats, GET /capabilities/:cap
- Persistent storage: .veritas-kanban/agent-registry.json
- Auto-offline: agents without heartbeat for 5min marked offline
- AGENTS.md template: docs/AGENTS-TEMPLATE.md with full integration guide
## Highlights
- Activity Page Redesign — Full-width status history, clickable navigation, color-coded badges
- Task Templates UI (#39) — Full management interface for templates
- Analytics API (#43) — Timeline and aggregate metrics endpoints
- Status Transition Hooks — Quality gates for task status changes
- 7 GitHub Issues Closed (#47, #48, #49, #51, #53, #56, #82)
## Changes
- Bump all packages to 1.6.0
- Update CHANGELOG.md with comprehensive release notes
- Update README.md version badge and roadmap
- Update FEATURES.md with new sections:
- Task Templates (v1.6.0)
- Analytics API (v1.6.0)
- Dashboard Filter Bar (v1.6.0)
- Redesigned Activity Feed section
- Activity page: purple for sub-agent, amber for in-progress, blue for done
- Status badges: uniform width, color-coded by status type
- Merged agent status and task status changes into unified view
- Task status badges use kanban column colors:
- todo → slate
- in-progress → blue
- blocked → amber
- done → green
- Both types sorted by timestamp, grouped by day
- Task ID + title clickable to open task
- Status badges now fixed width (w-20) to match 'sub-agent'
- Task ID moved to same row, before task title
- Task ID same font size as title, gray color
- Removed Activity Feed column and all related components
- Status History now takes full width
- Removed 'Status History' header label
- Kept Daily Summary panel at top
- Simplified from 626 lines to 240 lines
1. KanbanBoard now consumes pendingTaskId from ViewContext
- Clicking status history entry navigates to board AND opens task detail
- Fetches task from API if not in current filtered list
2. Status history now captures taskId/taskTitle from activeAgents
- When status changes via activeAgents (not activeTask), derive task info
- Falls back to first activeAgent's taskId/taskTitle
- Fixes missing titles in ~90% of status history entries
- Add onTaskClick prop to StatusHistoryPanel
- Make rows clickable when taskId is present
- Task title shows as link style (primary color + underline on hover)
- Keyboard accessible (Enter/Space to click)
- Falls back to em-dash when no task title
- Add comprehensive ANALYTICS.md documenting all endpoints
- Document data models, metrics, and usage examples
- Add TESTING_ANALYTICS.md with test scenarios
- Update swagger.ts with analytics schemas and endpoints
- Include performance benchmarks and troubleshooting guide
Add pre-transition gates that must pass before status change is allowed:
- require-agent: Task must have agent assigned
- require-plan: Description must contain Plan section
- require-verification-complete: All verification steps checked
- require-time-tracked: Time tracking must have entries
- require-closing-comment: Task must have at least one comment
- require-subtasks-complete: All subtasks completed
- require-blocker-reason: blockedReason must be set
Add post-transition actions that fire after status change:
- auto-start-timer: Start time tracking
- auto-stop-timer: Stop time tracking
- send-webhook: POST to URL
- send-notification: Send to channel
- prompt-lessons-learned: Flag for capture
- log-activity: Log to activity feed
API:
- GET/PUT/PATCH /api/settings/transition-hooks
- POST /api/settings/transition-hooks/validate
- CRUD for individual rules at /api/settings/transition-hooks/rules
Config stored in .veritas-kanban/transition-hooks.json
Also adds 'cancelled' status and 'critical' priority to shared types.
Ref: task_20260201_04iPHh
Added docs/SOP-shared-resources.md covering:
- Single repo vs multi-repo directory structures
- Mounting strategies (copy, symlinks, git submodules, npm packages)
- What to share vs what to keep project-specific
- Referencing shared resources in tasks and prompts
- Versioning and update protocols
- Migration checklist
Updated GETTING-STARTED.md to reference the new prompt-registry templates.
Credit: BoardKit Orchestrator (Monika Voutov) for the shared resources pattern.
Closes#77
New CLI command that validates environment and helps new users get started:
- Checks Node version (requires >=18)
- Verifies server is running and accessible
- Tests API authentication
- Optionally creates a welcome task with next steps
- Supports --json output for automation
- Supports --skip-task to skip sample task creation
Updated docs/GETTING-STARTED.md to reference the new command.
Credit: BoardKit Orchestrator (Monika Voutov) for the wizard pattern inspiration.
Closes#71
Extended path traversal protection to two services missed in initial audit:
- trace-service.ts: validate attemptId, taskId, traceId before path.join
- template-service.ts: validate templateId in templatePath()
Both now use validatePathSegment() + ensureWithinBase() from utils/sanitize.ts.
Ref: RF-002a Batch 3a Findings (High+Medium severity)
Bug 1: /api/metrics/all was passing the period filter to task counts,
showing only tasks touched within the time window (e.g., 33 todo in 24h)
instead of current board state (124 todo total).
Fix: computeAllMetrics now passes null to computeTaskMetrics so task
status counts always reflect current state. Period filter still applies
to telemetry metrics (runs, tokens, duration).
Bug 2: /api/backlog/count was double-wrapping response (route wrapped
with success/data, then middleware wrapped again).
Fix: Route now returns { count } and lets responseEnvelopeMiddleware
handle wrapping.
Bug: taskToFilename() generates filename from current title, but the
actual file on disk may have a different slug if the title changed after
creation. This caused INTERNAL_ERROR on archive/delete/restore.
Fix: Added findTaskFile() helper that searches by task ID prefix instead
of computing the expected filename. Applied to archiveTask, deleteTask,
and restoreTask.
Also: archiveSprint now throws ValidationError instead of generic Error
for better API error responses.
tasks/backlog/*.md and tasks/examples/*.md were not covered by
.gitignore — only active/ and archive/ were. Added both patterns
and removed 56 tracked task files from the index.
Files remain on disk (only removed from git tracking).
SEC-001: Path traversal prevention
- Add validatePathSegment() and ensureWithinBase() to server/src/utils/sanitize.ts
- Apply to chat-service (sessionId/taskId in file paths)
- Apply to conflict-service (filePath in path.join)
- Apply to clawdbot-agent-service (taskId/attemptId in log/request paths)
SEC-007: Admin authorization on mutating endpoints
- settings.ts: PATCH /features requires authorize('admin')
- config.ts: POST/PATCH/DELETE repos, PUT agents, PUT default-agent
- activity.ts: DELETE / requires authorize('admin')
- notifications.ts: POST/mark-sent/check require authorize('admin','agent'), DELETE requires admin
- status-history.ts: DELETE / requires authorize('admin')
- Updated test harnesses with admin auth injection
Agent Status Indicator: WebSocket fix
- BoardSidebar now uses useRealtimeAgentStatus (WebSocket) instead of useGlobalAgentStatus (polling)
- Fixed field name mismatch: server broadcasts 'activeAgents' but hook expected 'subAgents'
- Hook now correctly reads activeAgents from both WebSocket messages and REST fallback
- Added connection status indicator and stale detection to sidebar
- Fixed agent-status.ts spread order for persisted status restore
Pre-existing fixes included (from earlier RF-002 sub-agent diffs):
- auth.ts: X-Forwarded-For only trusted when trust proxy configured
- rate-limit.ts: isLocalhost returns false in production
- telemetry-service: CSV formula injection prefix sanitization
- Frontend: window.open noopener/noreferrer on all instances
The agent status indicator on the VK board was not updating during
sub-agent workloads because OpenClaw sub-agents (spawned via
sessions_spawn) run outside VK's clawdbot-agent-service — nothing
was POSTing to /api/agent/status.
Server fix:
- Reset subAgentCount to 0 when status transitions to idle
(previously only cleared activeTask, errorMessage, and activeAgents)
Workflow fix (in clawd workspace):
- Created vk-status.sh script to wrap the agent status API
- Added mandatory SOP to AGENTS.md: orchestrator calls vk-status.sh
before/after every spawn, and every sub-agent task prompt includes
a curl POST to /api/agent/status as its first action
- Works regardless of which model runs the sub-agent (Codex, Sonnet,
GPT, etc.) — both the orchestrator and the agent itself report in
- Remove container max-width from main layout — all views now full-width
- Convert Archive from sidebar to full page with search, filters, bulk restore
- Add Archive nav button in header (replaces sidebar icon)
- Archive page matches Backlog/Activity design: expand-in-place, checkboxes, badges
- Sprint filter on archive page
- Consistent UX across Board, Activity, Backlog, and Archive views