Commit graph

315 commits

Author SHA1 Message Date
Brad Groux
cf413bbd64 feat(cli): add workflow commands - vk begin/done/block/unblock, time tracking, comments, agent status, projects (#44) 2026-02-01 02:05:40 -06:00
Brad Groux
bbc8d948b4 docs: update roadmap with current milestones and completed items 2026-01-31 23:48:09 -06:00
Brad Groux
9369ca8bcf docs: update all documentation for v1.2.0 + v1.3.0
- Bump all package versions to 1.3.0
- README: version badge, blocked column, new feature highlights
- CHANGELOG: full v1.2.0 and v1.3.0 entries
- FEATURES.md: GitHub sync, activity feed, standup summary sections
- FEATURES.md: storage architecture, API envelope docs, new CLI commands
- FEATURES.md: updated API endpoints table and response format docs
2026-01-31 23:33:37 -06:00
Brad Groux
879b095096 v1.3.0: Visibility & Automation (#21, #33, #34)
- Bidirectional GitHub Issues sync (#21)
  - GitHubSyncService with polling, label-based field mapping, circuit breaker
  - Inbound: import issues with 'kanban' label as tasks
  - Outbound: push status changes and comments back to GitHub
  - Config/state persistence, 5 new API endpoints
  - CLI: vk github sync/status/config/mappings
  - TaskGitHub interface added to shared types

- Activity feed view (#33)
  - Full-page chronological feed with day grouping
  - Filter bar: agent, type, date range (combinable)
  - Compact vs detailed view toggle
  - Infinite scroll via IntersectionObserver
  - Real-time WebSocket updates with animation
  - Agent field added to Activity, MAX_ACTIVITIES 1000→5000
  - New ViewContext for board/activity navigation

- Daily standup summary generation (#34)
  - GET /api/summary/standup with date, format params
  - JSON, markdown, and plain text output formats
  - Sections: completed, in-progress, blocked, upcoming, stats
  - CLI: vk summary standup with --yesterday, --date, --json flags
  - 12 new tests for standup logic

Closes #21, closes #33, closes #34
2026-01-31 23:15:08 -06:00
Brad Groux
a7877e57b5 v1.2.0: Foundation Hardening (#2, #6, #32)
- Standardize API response envelope and error format (#2)
  - Add UnauthorizedError, ForbiddenError, BadRequestError, InternalError classes
  - Add pagination support with sendPaginated() helper
  - Standardize all 11 route files to use error classes (zero ad-hoc patterns)
  - Standardize auth middleware error responses

- Abstract file storage behind repository interface (#6)
  - Extend storage interfaces: Activity, Template, StatusHistory, ManagedList, Telemetry
  - Implement file-based adapters in FileStorageProvider
  - Add fs-helpers.ts as centralized filesystem access layer
  - Remove direct fs imports from all 10 service/route files

- Complete blocked task status implementation (#32)
  - Fix MCP tools Zod/JSON schema definitions
  - Fix MCP active tasks filter
  - Fix CLI help text and status color formatting

Closes #2, closes #6, closes #32
2026-01-31 23:03:10 -06:00
Brad Groux
3430b265c3 feat: Add webhook notifications for Clawdbot Gateway integration (#36)
feat: Add webhook notifications for Clawdbot Gateway integration
2026-01-31 22:37:00 -06:00
Brad Groux
a421fada46 fix(docker): resolve build failures from lockfile mismatch and permissions
Fixes #35

- Copy real web/package.json instead of creating a minimal stub, which
  caused pnpm-lock.yaml specifier mismatch with --frozen-lockfile
- Add --ignore-scripts to skip husky prepare hook in container builds
- Remove web/node_modules after install (frontend is pre-built static)
- Create .veritas-kanban directory with correct ownership for non-root user

Closes #35
2026-01-31 22:31:07 -06:00
Scout Murphy
4189af29cb feat: Add webhook notifications for Clawdbot Gateway integration
- Add webhookUrl to NotificationSettingsSchema
- Create clawdbot-webhook-service with fire-and-forget delivery + 1 retry
- Hook into broadcastTaskChange and broadcastChatMessage in broadcast-service
- Support VERITAS_WEBHOOK_URL and VERITAS_WEBHOOK_SECRET env vars
- HMAC-SHA256 payload signing via X-Webhook-Signature header
- Add 16 tests covering config, signing, delivery, retry, and payload formatting
- Update .env.example with new env var documentation
2026-01-31 21:30:02 -07:00
Brad Groux
14fbf33609 fix: unwrap API envelope in shared client (fixes #27) 2026-01-31 12:09:58 -06:00
Brad Groux
28eeb58133 docs: add agent quickstart prompt to README 2026-01-31 11:41:22 -06:00
Brad Groux
f3e4ab2375 Merge pull request #26 from BradGroux/fix/timer-stop-cache-race-7
Fixes the timer stop race condition (Issue #7). Debounced field saves no longer overwrite timer state.
2026-01-31 07:28:55 -06:00
Brad Groux
d8dab5a612 chore: bump version to v1.1.0 + changelog 2026-01-31 07:09:18 -06:00
Brad Groux
a81b4ea1f7 Merge feat/v1.1-agent-routing-16-17-18: agent routing, chat interface (#16, #17, #18) 2026-01-31 07:08:06 -06:00
Brad Groux
cb3d3cdc04 fix: chat delete + export + input focus
- Fix delete not clearing UI (React Query kept stale data on 404 refetch)
- Fix post-delete send breaking (server recreates task sessions instead of 404)
- Add chat export as markdown (download icon next to trash)
- Auto-focus input on panel open and after each send
- Defensive delete on server (handle already-deleted sessions)
2026-01-31 07:06:00 -06:00
Brad Groux
321071b2b8 feat: chat clear history + title updates
- Board Chat / Task Chat dynamic title
- Trash icon in header to clear chat history
- Confirmation dialog before deleting
- Re-initializes task session after clear
- Floating chat bubble from previous commit
2026-01-31 06:49:35 -06:00
Brad Groux
974255bff3 feat: floating chat bubble with pulse indicator
- Floating chat icon in bottom-right corner
- Opens board-level chat (not tied to any task)
- Pulsing green dot when new response arrives while closed
- Hides bubble when chat panel is open
- Clears unread indicator on open
2026-01-31 06:46:26 -06:00
Brad Groux
89a5fd8b20 feat: wire up chat AI responses via Clawdbot gateway, fix UI bugs
- Chat now generates actual AI responses via Clawdbot gateway WebSocket
- Gateway chat client handles auth, streaming deltas, and final response
- Chat responses broadcast to UI via kanban WebSocket (shared connection)
- Fix double X close button on chat panel (SheetContent built-in + manual)
- Move Chat/Template buttons above tab row to reduce cramping
- Chat/Template buttons now 50/50 full width
- Fix subtask add button height mismatch
- Fix chat send crash (API response type mismatch)
- Remove non-functional agent/model dropdowns from chat panel
- Add model picker (sonnet/opus/haiku) to Agent panel in task detail
- Replace tooltip with inline mode hint text in chat
- Load chat history on panel open (deterministic task session ID)
- Chat stream uses shared WebSocket instead of opening duplicate connection
2026-01-31 06:44:42 -06:00
Brad Groux
643b62d90d feat: add agent filter to board FilterBar
- Agent dropdown in same row as search, project, type filters
- Options: All Agents, Auto (routing), Unassigned, + each configured agent
- URL sync support (?agent=claude-code)
- Filter logic handles auto, unassigned, and specific agent matching
2026-01-31 06:07:03 -06:00
Brad Groux
878ea8d088 fix: sticky header + match indicator dot sizes
- Header: sticky top-0 z-50 so it stays visible on scroll
- Agent status dot: w-2.5 → w-2 to match WebSocket indicator size
2026-01-31 06:04:02 -06:00
Brad Groux
c198f1c2c7 feat: chat interface frontend — panel, streaming, keyboard shortcuts (#18)
- ChatPanel: right-side slide-out panel with agent/model selectors
- Markdown rendering, tool call collapsible blocks, streaming indicator
- Ask/Build mode toggle for read-only vs mutation-capable conversations
- Task-scoped chat (from task detail) and board-level chat
- Cmd+Shift+C keyboard shortcut to toggle chat panel
- Chat button in header toolbar
- Chat tab in task detail panel
- API hooks (useChatSession, useSendChatMessage, useChatStream)
- WebSocket streaming placeholder (ready to wire up)
2026-01-31 06:02:17 -06:00
Brad Groux
fe721fd96b feat: chat interface frontend — panel, streaming, keyboard shortcuts (#18) 2026-01-31 06:01:21 -06:00
Brad Groux
e8e153d037 feat: chat interface backend — storage, API, WebSocket (#18) 2026-01-31 05:58:43 -06:00
Brad Groux
d12dcd6278 fix: align Sprint and Agent labels in task forms 2026-01-31 05:57:38 -06:00
Brad Groux
782f36c85b feat: agent selection on task creation (#17)
- Add agent field to CreateTaskForm state with 'auto' default
- Agent dropdown in CreateTaskDialog (Auto + all enabled agents)
- Agent field in TaskMetadataSection (task detail panel) — editable inline
- Pass agent through useTemplateForm to task creation API
- Server: accept agent field in create/update task schemas
- TaskService: persist agent field on task creation
- AgentPanel: pre-select task's assigned agent (priority: manual > pre-assigned > routed > default)
- Sprint and Agent dropdowns now share a row for compact layout
2026-01-31 05:53:33 -06:00
Brad Groux
fa7ac0fe1a feat: task-aware agent routing engine (#16)
- Add AgentRoutingConfig types with RoutingRule, RoutingMatchCriteria, RoutingResult
- Add DEFAULT_ROUTING_CONFIG with sensible defaults (code/bug/docs/review rules)
- Create AgentRoutingService with resolveAgent() and getFallback() methods
- First-match-wins rule evaluation with type, priority, project, minSubtasks criteria
- Array support for match criteria (e.g., type: ['code', 'bug'])
- Routing API: POST /agents/route, GET/PUT /agents/routing
- Integrate routing into ClawdbotAgentService.startAgent() for 'auto' agent selection
- Add agent field to Task, CreateTaskInput, UpdateTaskInput, TaskSummary schemas
- Settings UI: routing rules section in Agents tab with add/edit/remove/reorder
- Agent Panel: show routing recommendation when starting agent
- 17 unit tests for routing service (all passing)
- Full typecheck clean across shared, server, and web packages
2026-01-31 05:18:44 -06:00
Brad Groux
53b872cb4f fix: rewrite timer UI with self-contained local state (#7)
Root cause: TimeTrackingSection subscribed to the React Query ['tasks']
cache for timer state, but concurrent invalidations from debounced saves
(useUpdateTask.onSettled) triggered background refetches that overwrote
timer state with stale data. The cache sync effect then propagated that
stale data back into local state, causing the UI to snap back.

Fix: TimeTrackingSection is now fully self-contained:
- Local state initialized from prop, updated ONLY from API responses
- No React Query cache subscription (removed useTasks dependency)
- No cache sync effect — eliminates all race conditions
- On error, fetches fresh task state directly from server
- Cache is still patched after mutations (for board/other components)

Also removed onSettled invalidation from useUpdateTask — the onSuccess
handler already patches the cache with merged server response. The
aggressive invalidateQueries was the primary source of stale refetches.

Fixes: start/stop not reflecting, multiple timers per task, multi-second
delays, delete not refreshing, requiring panel close/reopen.

Closes #7
2026-01-31 05:05:22 -06:00
Brad Groux
b13ecce67a fix: per-task timer exclusivity, not global
Multiple tasks can each have running timers simultaneously — this supports
multi-agent workflows where different agents track different tasks.

Removed:
- getRunningTimerTask() method (global scan)
- Auto-stop of other tasks' timers in startTimer()
- otherRunningTask UI check that hid the Start button

Kept: per-task guard (can't start a timer on a task that already has one running).
2026-01-31 04:49:58 -06:00
Brad Groux
6d63c94c51 refactor: rewrite TimeTrackingSection for reliable state updates
Root cause of all timer UI bugs: the component relied on React Query's
cache propagation chain (mutation → patchTaskInList → useTasks() hook →
re-render) which was unreliable due to structural sharing, concurrent
invalidations from debounced saves, and the multi-layer prop pipeline
(useDebouncedSave → localTask → TaskDetailsTab → TimeTrackingSection).

The fix: TimeTrackingSection now owns its own local state, initialized
from the task prop and updated DIRECTLY from API responses after each
mutation. This guarantees instant UI updates regardless of React Query's
internal state:

- Start timer → API response → setTimeTracking → UI shows Stop immediately
- Stop timer → API response → setTimeTracking → UI shows Start immediately
- Delete entry → API response → setTimeTracking → entry disappears immediately
- Add entry → API response → setTimeTracking → entry appears immediately

The query cache is still patched as a secondary update path (for other
components) and synced from for external changes (WebSocket events,
background refetches), but it's no longer the primary driver.

Also:
- Server timer methods now throw ConflictError (409) / NotFoundError (404)
  instead of generic Error (which mapped to 500)
- Delete buttons disabled while a mutation is in flight
- Removed useCallback (unnecessary for onClick handlers)
- JSON fingerprint for cache sync prevents unnecessary effect fires
2026-01-31 04:48:17 -06:00
Brad Groux
167f1b2acb fix: enforce global timer exclusivity — only one timer at a time
- Server: startTimer() auto-stops any running timer on another task before
  starting the new one. Prevents multiple simultaneous timers.
- Server: updateTask() re-reads from cache inside file lock to prevent
  concurrent writes (debounced saves) from clobbering timer state.
- Server: Added WebSocket broadcasts to all timer routes (start/stop/add/delete)
  so other clients get real-time updates.
- UI: TimeTrackingSection hides Start button when another task has an
  active timer, showing 'Timer active on another task' instead.
- UI: Subscribe directly to query cache for timer state instead of relying
  on the debounced-save prop pipeline.
- UI: Added mutatingRef guard to prevent double-clicks on Start/Stop.

Fixes the issue where 3 tasks could have running timers simultaneously.
2026-01-31 04:41:50 -06:00
Brad Groux
bf61fd698b fix: preserve timer state during debounced field saves (#7)
When editing a task field (title, description, etc.) while a timer was
running, the debounced save's onSuccess handler would overwrite the
timeTracking cache with stale server data. This happened because:

1. User stops timer → useStopTimer patches cache (isRunning: false)
2. Pending debounced save fires → server responds with pre-stop data
3. useUpdateTask.onSuccess writes server response → isRunning: true again

The fix: in useUpdateTask.onSuccess, preserve the cached timeTracking
data unless the update explicitly included timeTracking changes. Since
useDebouncedSave only sends dirty fields (title, description, etc.),
timeTracking is never in the update input for normal field edits, so the
cache's more recent timer state is preserved.

Fixes #7
2026-01-31 04:08:06 -06:00
Brad Groux
bb453ab6e9 fix: allow explicit IDs when creating managed list items
ManagedListService.create() now accepts an optional 'id' field.
If provided, it uses the explicit ID instead of generating slug-nanoid.
Also adds duplicate ID check to prevent conflicts.

This fixes the corrupted task-type IDs (e.g., 'bug-GdN5rT' instead of 'bug')
that were caused by always appending random suffixes.
2026-01-31 00:34:57 -06:00
Brad Groux
762f7fa23a feat: per-status selection with toolbar buttons and column checkboxes (fixes #24)
- Add toggleGroup() to useBulkActions for toggling groups of IDs
- Add status filter buttons (Todo/In Progress/Blocked/Done) to BulkActionsBar
- Buttons are toggleable: click Done then Blocked to select both groups
- Visual states: filled (all selected), dimmed (partial), outline (none)
- Add column header checkboxes with tri-state (checked/indeterminate/unchecked)
- Empty columns hide their checkbox
- Status buttons hide when column has 0 tasks
2026-01-31 00:22:58 -06:00
Brad Groux
287ac80b3f fix: exempt localhost from auth rate limit (fixes #25) 2026-01-30 23:18:38 -06:00
Brad Groux
b536e60816 docs: add TROUBLESHOOTING.md with common issues and solutions 2026-01-30 23:11:36 -06:00
Brad Groux
33a90bbc63 fix: use TaskService singleton in all routes to fix cache fragmentation
Root cause: Each route file created its own TaskService instance via
'new TaskService()', resulting in 13+ separate in-memory caches.
When task-archive.ts archived a task, it removed it from its own cache,
but tasks.ts (which serves GET /api/tasks) still had the task in its
separate cache — so archived tasks continued appearing in the list.

Fix: All route files now use getTaskService() singleton, ensuring a
single shared cache across all endpoints. Service files retain their
own instances for test isolation.

Fixes #22
2026-01-30 05:29:48 -06:00
Brad Groux
cc4d9f09dc fix: use clean numeric inputs without browser spinners (fixes #19) 2026-01-30 00:00:53 -06:00
Brad Groux
793192e6b3 docs: rename Moltbot references to OpenClaw (formerly Clawdbot/Moltbot) 2026-01-29 23:39:11 -06:00
Brad Groux
a7973e14d9 fix: resolve TypeScript build errors in test files
- Remove unused React imports in AgentStatusIndicator and WebSocketIndicator tests
- Fix Response type cast in api-helpers test (as unknown as Response)
2026-01-29 15:55:23 -06:00
Brad Groux
c250a5a60f docs: final documentation pass for public release
- CONTRIBUTING: fix Node.js prerequisite (20 → 22), fix .env path, add seed docs, expand project structure
- CHANGELOG: move 1.1.0 to Unreleased (matches package.json 1.0.0), add seed data entry, fix link refs
- README: add examples/ and gitignored annotations to architecture tree
- docs/security.md: update Clawdbot reference to Moltbot, fix release date
2026-01-29 15:51:41 -06:00
Brad Groux
a2aa5053c6 feat: add seed data and first-run auto-seeding for clean public repo
- Remove tracked personal attachment screenshots from git
- Add tasks/attachments/ and tasks/archive-attachments/ to .gitignore
- Create 4 example tasks showcasing features (auth, bug, research, automation)
- Add seedIfEmpty() to TaskService for automatic first-run seeding
- Add pnpm seed script for manual seeding
- Update README quickstart with seed docs
- Fix version badge mismatch (1.1.0 → 1.0.0)
2026-01-29 15:45:38 -06:00
Brad Groux
39213341c7 docs: regenerate GIFs from MP4 source for better quality 2026-01-29 15:34:48 -06:00
Brad Groux
316126db24 docs: add screenshots and demo GIFs to README and FEATURES 2026-01-29 15:32:29 -06:00
Brad Groux
407014532c fix: optimistic UI toggle for timer start/stop button 2026-01-29 14:51:05 -06:00
Brad Groux
dab1cad542 fix: add credentials:include to all API write calls for cookie auth 2026-01-29 14:41:10 -06:00
Brad Groux
3de4285213 fix: instant UI update on timer start/stop/add/delete via optimistic cache patch 2026-01-29 14:35:01 -06:00
Brad Groux
cce151e64b fix: add task ID to board and archive search filters 2026-01-29 14:27:26 -06:00
Brad Groux
f60b218c10 fix: add in-process FIFO queue to file-lock for deterministic ordering
File-based locking with wx flag doesn't guarantee ordering within the
same Node.js process — concurrent fs.writeFile calls race at the OS
level. Added a per-file Promise chain that serializes lock requests
in FIFO order within the same process. The file lock still provides
cross-process protection.

Fixes flaky withFileLock serialization test (was ~30% failure rate,
now 20/20 passes).
2026-01-29 07:43:54 -06:00
Brad Groux
f531fad829 chore: add .nvmrc, fix issue template link, update changelog links to BradGroux 2026-01-29 07:39:40 -06:00
Brad Groux
8c892d7c22 fix: replace console.* with structured pino logger, fix ESLint errors in k6 load tests 2026-01-29 07:35:48 -06:00
Brad Groux
76b93ebe85 docs: update documentation for agent CRUD, theme toggle, and bug fixes 2026-01-29 07:23:26 -06:00