Summary
The Kanban dashboard update endpoint allows direct status writes to running. That bypasses the dispatcher/claim path that normally creates a run row, claim lock, expiry, and worker process metadata.
Evidence
plugins/kanban/dashboard/plugin_api.py:394-419 handles status updates.
plugins/kanban/dashboard/plugin_api.py:417-418 sends s in ("todo", "running", "triage") to _set_status_direct(...).
_set_status_direct is documented as a drag/drop helper at plugins/kanban/dashboard/plugin_api.py:469-480, including direct transitions such as running -> ready; however it also permits * -> running through the route above.
- Normal claim/run creation goes through
hermes_cli/kanban_db.py:1244-1330 (claim_task), which atomically transitions ready -> running, sets claim fields, and inserts a task_runs row.
Impact
A dashboard/API caller can create tasks with status='running' but no active run row, claim lock, worker PID, or spawned worker. These tasks can become stuck or violate Kanban's run-history invariants.
Suggested fix
- Do not allow dashboard/API direct transitions into
running.
- Only
claim_task/dispatcher should enter running.
- If the UI needs a manual “start” action, route it through the same claim/run creation path.
- Add regression tests ensuring
PATCH /tasks/{id} with status='running' is rejected or claims through the canonical path.
Summary
The Kanban dashboard update endpoint allows direct status writes to
running. That bypasses the dispatcher/claim path that normally creates a run row, claim lock, expiry, and worker process metadata.Evidence
plugins/kanban/dashboard/plugin_api.py:394-419handles status updates.plugins/kanban/dashboard/plugin_api.py:417-418sendss in ("todo", "running", "triage")to_set_status_direct(...)._set_status_directis documented as a drag/drop helper atplugins/kanban/dashboard/plugin_api.py:469-480, including direct transitions such asrunning -> ready; however it also permits* -> runningthrough the route above.hermes_cli/kanban_db.py:1244-1330(claim_task), which atomically transitionsready -> running, sets claim fields, and inserts atask_runsrow.Impact
A dashboard/API caller can create tasks with
status='running'but no active run row, claim lock, worker PID, or spawned worker. These tasks can become stuck or violate Kanban's run-history invariants.Suggested fix
running.claim_task/dispatcher should enterrunning.PATCH /tasks/{id}withstatus='running'is rejected or claims through the canonical path.