8.4 KiB
Kanban — Reference vs. hermes-desktop: Report & Plan
Generated 2026-06-21. Sources: hermes-agent docs + kanban_db.py + plugins/kanban/dashboard/plugin_api.py; our src/main/kanban.ts + src/renderer/src/screens/Kanban/Kanban.tsx.
1. What Kanban is (in hermes-agent)
Hermes Kanban is a durable, SQLite-backed task board (~/.hermes/kanban.db, WAL mode) for coordinating multiple named agent profiles. It is the heavier sibling of delegate_task:
delegate_task |
Kanban | |
|---|---|---|
| Shape | RPC (fork→join) | Durable queue + state machine |
| Parent | Blocks | Fire-and-forget |
| Child | Anonymous subagent | Named profile w/ persistent memory |
| Resumable | No | Block→unblock→re-run; crash→reclaim |
| Human-in-loop | No | Comment / unblock anytime |
| Audit | Lost on compression | Durable SQLite rows |
Three surfaces, one kanban_db core (cannot drift):
- Agents drive it via
kanban_*tools (kanban_show/list/complete/block/heartbeat/comment/create/link/unblock). - Humans/scripts/cron drive it via
hermes kanban …CLI and/kanbanslash command. - Dashboard plugin (FastAPI + React SPA) at
plugins/kanban/— REST under/api/plugins/kanban/, livetask_eventsWebSocket.
Key concepts: Board (isolated queue, multi-project) · Task · Link (parent→child dependency, promotes todo→ready when all parents done) · Comment (inter-agent protocol) · Workspace (scratch / dir:<abs> / worktree) · Dispatcher (gateway-embedded loop, 60s tick: reclaim stale/crashed, promote, claim, spawn) · Tenant (soft namespace within a board).
Notable mechanics: auto-decompose of triage tasks, goal-mode cards (Ralph loop + judge), circuit-breaker (failure_limit, auto-block after N spawn failures), respawn guard (blocker_auth/recent_success/active_pr), scheduled_at delayed dispatch, diagnostics rule-engine, attachments (25 MB cap), Kanban Swarm topology helper.
2. Canonical statuses (the "kanban words")
From kanban_db.VALID_STATUSES:
triage · todo · scheduled · ready · running · blocked · review · done · archived
Dashboard BOARD_COLUMNS (plugin_api.py): triage, todo, scheduled, ready, running, blocked, review, done (+ archived via toggle).
VALID_INITIAL_STATUSES = {running, blocked}.
Allowed status transitions (from plugin PATCH /tasks/:id)
done→complete_task(result, summary, metadata)blocked→block_task(reason)scheduled→schedule_task(reason)ready→ if currentlyblocked/scheduled→unblock_task; else direct set (drag-droptodo→ready); refused if any parent notdone(409 names the blocking parent)archived→archive_taskrunning→ rejected ("use the dispatcher/claim path")todo/triage/scheduled→ direct set- Reopening a
done/archivedparent demotes stale-readychildren back totodo.
3. Actions / API surface
Canonical CLI verbs (hermes_cli/kanban.py)
init, create, list, show, assign, reassign, edit, promote, schedule, diagnostics, link, unlink, claim, comment, complete, block, unblock, archive, tail, watch, heartbeat, runs, assignees, dispatch, daemon, stats, log, notify-subscribe, notify-list, notify-unsubscribe, context, specify, decompose, swarm, gc, plus boards {list,create,rm,switch,show,rename,set-workdir}.
Dashboard REST (representative)
GET /board · GET/POST/PATCH/DELETE /tasks[/:id] · POST /tasks/bulk · attachments CRUD · POST /tasks/:id/comments · POST /tasks/:id/{specify,decompose} · GET/PATCH /profiles[/:name] + /describe-auto · GET/PUT /orchestration · POST/DELETE /links · POST /dispatch · GET /diagnostics · GET /workers/active · GET /runs/:id[/inspect] · POST /runs/:id/terminate · GET /config · WS /events.
Note: the reference desktop app (
hermes-agent/apps/desktop) has no kanban board UI — only/kanbanas a slash-command string and a notifications comment. The rich UI reference is the dashboard plugin, not that app.
4. What our hermes-desktop has today
Main (src/main/kanban.ts) — execs hermes kanban (local) or SSH-tunnels (sshRunKanban); blocks plain-remote mode. Exposes:
listBoards, currentBoard, switchBoard, createBoard, removeBoard, listTasks, getTask, createTask, assignTask, completeTask, blockTask, unblockTask, archiveTask, specifyTask, reclaimTask, commentTask, listClaw3dHqTasks, dispatchOnce.
Renderer (Kanban.tsx) — 6 columns triage, todo, ready, running, blocked, done; 6s poll; board switcher (+ read-only Claw3D HQ virtual board); create-task modal; create-board modal; read-only detail modal (body/summary/result/comments/events). Card actions: specify, mark-done, reclaim, unblock, block, archive. Drag-drop transitions: →done, →blocked (from todo/ready/running), blocked→ready.
5. Gap analysis (reference → ours)
A. Status coverage
| Status | Canonical | Our columns | Gap |
|---|---|---|---|
| triage,todo,ready,running,blocked,done | ✓ | ✓ | — |
| scheduled | ✓ | ✗ | Missing column — scheduled tasks fall through to todo bucket (Kanban.tsx:322). |
| review | ✓ | ✗ | Missing column — review tasks mis-bucket to todo. |
| archived | ✓ (toggle) | ✗ | No "show archived" toggle in UI (main supports includeArchived). |
B. Actions defined in main but NOT surfaced in UI
assignTask/ reassign — no reassign control in detail modal.commentTask— detail modal shows comments read-only; no compose box.removeBoard— no delete-board affordance.
C. Canonical actions NOT wired at all (no main fn, no UI)
decompose— the headline triage flow (fan-out to child graph). We only havespecify.promote(todo/blocked→ready recovery),schedule(scheduled_at),edit(title/body/priority in place — we can create but not edit),link/unlink(dependency editing),diagnostics,runs(attempt history —KanbanRuntyped but not fetched standalone),assignees/stats,notify-*,swarm,gc,tail/watch,heartbeat, boardsrename/set-workdir, attachments (upload/list/download/delete).
D. UX / behavior gaps vs dashboard plugin
- Polling vs live — we poll every 6s; plugin tails
task_eventsover WebSocket (instant, debounced). No WS bridge in our main. - No dependency / progress UI — no parent/child chips, no
N/Mprogress pill, no link editor. - No diagnostics surfacing — no distress badges (hallucination/crash/stuck-blocked) the plugin renders.
- No bulk multi-select actions.
- No orchestration controls — Auto/Manual decompose pill, profile-description editor, orchestrator settings.
- Transition rules are re-implemented client-side (
isValidDragTransition) and narrower than the backend — risk of drift; e.g. no→scheduled, no→review, no→readyfromtodovia drag. - Detail modal is read-only — can't edit title/body/priority/assignee or add comments/links inline.
6. Recommended plan (phased)
Phase 1 — Correctness (low effort, high value)
- Add
scheduled+reviewtoCOLUMNSanden/kanban.tsstatus.*(and other locales). Fixes silent mis-bucketing. - Add a "show archived" toggle (main already supports
includeArchived). - Wire comment compose in the detail modal (
commentTaskalready in main). - Wire reassign in the detail modal (
assignTaskalready in main).
Phase 2 — Parity actions
- Add main fns + UI for
decompose,edit(title/body/priority),promote,schedule(--at),link/unlink(dependency editor with parent/child chips + progress pill). - Add
runs/diagnostics` read views in the detail drawer (attempt history, distress badges).
Phase 3 — Live + richer UX
- Replace 6s poll with a
task_eventstail (SSHkanban watch --jsonstream, or local tail) for instant updates. - Bulk multi-select actions; orchestration Auto/Manual + profile descriptions; attachments.
Cross-cutting
- Prefer routing transitions through backend verbs rather than widening the client-side
isValidDragTransition, to avoid drift fromkanban_dbrules. - Keep SSH-tunnel + remote-unsupported guards on every new verb (existing pattern in
kanban.ts). - Each new IPC verb needs:
kanban.tsfn →ipc/register.ts→preload/index.ts(+.d.ts) → renderer.