Young's Mind
03 Decisions

Should Kanban be our Board, fed by Hermes? Yes — and it decides the per-agent-store question

Young, 2026-10-11: "Each agent own task db, that will be messy and unable to track tasks on their db. Kanban tracks everything on the plan. Goals and tasks. Should we add kanban as our Board and feed by Hermes?"

Should Kanban be our Board, fed by Hermes? Yes — and it decides the per-agent-store question

Young, 2026-10-11: "Each agent own task db, that will be messy and unable to track tasks on their db. Kanban tracks everything on the plan. Goals and tasks. Should we add kanban as our Board and feed by Hermes?"

Yes. And it answers the previous question, the per-agent store question, in the same move: if the board is the upstream, then a worker does not need its own database at all — it needs an adapter.


1. What I measured before saying yes

The gap is real and it is bigger than a preference. The V3 worker does not know the board exists — measured:

grep -rn 'HERMES_KANBAN|kanban.db|kanban_db' --include='*.py' .solos
  (no results — the V3 worker does NOT know the board exists)

So today, putting a task on the board does nothing to the executor. Two task systems, no bridge — the exact V2 defect ("two state machines with no bridge"), live in V3, and Young has just proposed the fix.

What the board has that we need — kanban.db carries 39 columns per task, including everything the executor reads from a task row:

The executor needsKanban has
a task idid
what to dotitle + body
who runs itassignee
statestatus (triage/todo/ready/running/blocked/review/done/archived)
prioritypriority
retry/limitsmax_retries, max_runtime_seconds
model pinningmodel_override, provider_override
goal loopgoal_mode, goal_max_turns
claim exclusivityclaim_lock, claim_expires — atomic, built

And the claim is the part we would have to build if we kept our own store: V2's eight concurrent writers on one JSON file produced 849 corruption events. Kanban's atomic claim already exists.

And the entry exists — operation/runtime/worker.py is the process a service runs ("drives RuntimeLoop — claim, run, sweep, heartbeat"), and serve.py is the A2A entry. The only missing piece is the adapter between them.

2. The architecture this produces

Young / Sol / Min / Mira
        │  hermes kanban create --assignee ace ...
        ▼
┌────────────────────────────┐
│  kanban.db (the ONE board) │   ← lifecycle truth: triage→todo→ready→running→done
│  39 cols, atomic claims    │
└────────────┬───────────────┘
             │  dispatcher claims atomically (built, inside the gateway)
             ▼
┌────────────────────────────┐
│  V3 worker (operation/)    │   ← the lane: should NOT need its own task db
│  RuntimeLoop + TaskStore   │      it reads the board; "tasks.db" becomes work
│                            │      NOTES, not a second registry
└────────────────────────────┘

Note the direction: the board feeds the workers, not the other way around. "Feed by Hermes" is exactly that — the board is upstream, the executor is downstream, and a result written back into kanban_complete means board → worker → board.

So the answer to the previous question changes: with the board as upstream, the per-agent tasks.db files should not exist as task registries. A worker's store becomes its attempt notebook, not a row-of-truth — the board is the row of truth.


3. 🔴 What I would do — and what it costs

The adapter is the one missing piece, and it is a read-only upstream:

StepWhatWhy it is safe
1kanban_adapter.py: read the board (--json), map status→local_state through cortex.tasks — never a copy, always a mappinguses the contract D2 named, so no second vocabulary
2worker.py --db default becomes the ONE shared store, and <agent>-tasks.db becomes a notes file (attempts, results) not a registrythe ten-database defect Young flagged, resolved by the change of role
3a task's kanban id is stored on the task row (external_task_id), so one card = one taskmakes the join mechanical and the drift probe possible
4never write status back to the board from the executor — result via kanban_comment; lifecycle truth stays on the boardTam's rule, in our tree: a worker never owns lifecycle truth

What this does NOT touch: the task contract (cortex/tasks/, D2), the five Heart worker units, the A2A listener, the already-proven executor. It is one new file and one default change.

4. What I am NOT deciding today

  • Whether the dispatcher spawns the worker, or the worker polls. Tam's lane doc says a plugin lane can supply spawn_fn — the Heart could be claimed by the board (a card assigned to ace), or it could poll for its own cards. Different failure shapes: the board-claimed model needs a fence (workers can only mutate their own card); the polling model needs a lock. Sol's lane and his call; I have not tested either live.
  • dispatch_in_gateway is not read on this host. The dispatcher demonstrably runs (it spawned workers), but I have never read the key's value. If it is false, the board→worker path above has a hole nobody can see until a card sits forever on ready — which is Tam's skipped_nonspawnable shape.
  • The per-agent store's "single-writer" contract (store.py documents it) has not been tested with two writers on one file. The shared store needs that test before the default flips.

5. The one-sentence answer

Yes — Kanban is the board, Hermes feeds it, and with the board as upstream the per-agent tasks.db files stop being task registries and become attempt notes. One new file (the adapter), one default change, one probe — the V2 "no bridge" defect cannot exist in a system with only one board.

Copyright © 2026