ADR 0004 — One task database: revert the Hermes kanban adoption, keep our own board¶
- Status: Accepted
- Date: 2026-06-09
- Decision owner: Jordan Hubbard
- Context: Phase 2 of
kanban-adopt-01. Phase 1 shipped a dashboard link-out to the Hermes kanban (PR #122). This ADR answers how the Hermes kanban store (kanban.db) should relate to the MAC hub task ledger (mac.db, themac tasksystem) — and concludes by reversing the Phase-1 adoption.
Current storage authority — 2026-09-14¶
The single-ledger decision remains in force. Its original SQLite storage detail
is historical: src/mac/store.py now accepts only PostgreSQL DSNs, and ordinary
startup verifies the explicit ordered migration ledger. Hermes state databases
remain separate from the MAC task authority.
TL;DR verdict¶
There must be exactly one task database — the MAC task ledger (mac.db).
We evaluated making Hermes' kanban read from that ledger (a pluggable task
store). It is not feasible cheaply: kanban_db.py is a 7,386-line concrete
SQLite module with no store seam, ~200 raw-SQL call sites, 7 tables, and
SQLite-specific CAS/migration machinery — and it is vendored upstream, so a
semantic rewrite is exactly the heavy fork ADR 0001 tells us not to carry.
Per the decision rule ("if Hermes can't be patched to a pluggable task store
easily, revert and keep our own"): revert the Hermes kanban adoption (the
Phase-1 dashboard link) and keep the bespoke board (renderTasks) as the single
task UI over the single store. An earlier draft of this ADR proposed coexisting
with a bridge; that is rejected in favor of one store.
Ground truth (today, not assumptions)¶
| mac.db task ledger | kanban.db Hermes kanban | |
|---|---|---|
| Purpose | Fleet work-queue | Goal-decomposition + multi-agent swarm |
| Model | models.py Task, store.py tasks |
_hermes/hermes_cli/kanban_db.py tasks |
| Distinctive fields | required_capabilities, lease_id/leased_until, owner_agent_id, max_attempts, project |
board, workspace_kind/workspace_path/branch_name (git worktrees), task_links, task_comments/task_events, task_runs, worker_pid/last_heartbeat_at, claim_lock CAS |
| States | open/blocked/claimed/running/needs_review/reviewing/completed/failed/cancelled |
triage/todo/scheduled/ready/running/blocked/review/done/archived |
| Location | One explicitly configured shared hub DB per fleet (MAC_DB or Postgres) |
Per-board local SQLite (~/.hermes/kanban.db) |
No bridge exists today: nothing in src/mac/ (outside _hermes/) imports
kanban_db; neither dispatcher reads the other's DB; the only links were agent
identity and the PR #122 hyperlink (now reverted).
Feasibility of a pluggable kanban store (the decision gate)¶
Measured against src/mac/_hermes/hermes_cli/kanban_db.py:
- 7,386 lines, no abstraction seam — no
Protocol/ABC/Store; the classes are data records, not a swappable backend. - Every function takes
conn: sqlite3.Connectionand runs raw SQL; ~200execute/BEGIN IMMEDIATE/ON CONFLICT/RETURNINGsites; plus_migrate_add_optional_columns,_table_has_drifted,_rebuild_drifted_tables,_check_file_length_invariant— all SQLite-specific. - Vendored upstream. Reworking the data layer is a large fork of a fast-moving dependency, contradicting ADR 0001's "pinned, pruned snapshot; no semantic surgery" guidance.
Both routes to "kanban on mac.db" are expensive: (a) introduce a store interface
and rewrite ~200 call sites in vendored code, or (b) recreate all 7 kanban tables
inside mac.db (which is hosting the kanban schema, not one tasks table).
Neither is "easy." → revert.
Decision¶
mac.dbis the single task database. All fleet work ismac task.- Revert the Phase-1 Hermes kanban adoption — remove the dashboard kanban
service link (PR #122). Keep the bespoke
renderTasksboard (with CEO-mode creation, #119, and the refresh fix, #121) as the single task surface. - Do not fork Hermes kanban. If the fleet later wants kanban-style
decomposition/swarm, build it natively against
mac.db(a board view + parent/child task links over the existing ledger), not by adopting a second store.
“One task database” means one authoritative database per running control
plane. Only the hub owns that database; fleet spokes are database-free clients
of its API. A SQLite file opened with --db elsewhere is a separate standalone
authority, not a replica, and must be configured explicitly. MAC does not merge
their task state. Repository .tickets/ files are migration/compatibility
mirrors and GitHub issues are external planning sources; neither participates
in leases, dispatch, review, or workflow state until a hub task is explicitly
created from it.
Consequences¶
- Pros: one store, one source of truth, no second DB to back up/observe, no heavy vendored fork to carry. The board we keep already works (refresh fix + CEO mode shipped).
- Cons: we forgo Hermes' ready-made swarm/decompose UI; any such capability is now ours to build on the ledger.
- Reversal:
kanban-adopt-01is closed as won't-adopt; reopen only if Hermes upstream grows a pluggable task-store seam that removes the fork cost.
Follow-up¶
- Closes
kanban-adopt-01(won't-adopt). - Optional, native: parent/child links + a board-style lens over
mac.dbtasks if decomposition UX is wanted later — tracked separately, not by adoptingkanban.db.