HERMES-GIELIE/api
Hermes Agent a39ec45b9f fix(kanban): protect dispatcher contract — reject raw status='running' PATCH
The PATCH /api/kanban/tasks/:id endpoint allowed any status-to-any-status
transition for the non-claim/complete/block/archive set via raw
`UPDATE tasks SET status = ?`. This let UI users (or any client) flip a
task to 'running' without going through kb.claim_task(), bypassing
claim_lock + claim_expires + started_at + worker_pid. The dispatcher
treats such a phantom-claimed task as orphaned and may reclaim, hide, or
double-dispatch it.

Match the agent dashboard plugin's contract
(plugins/kanban/dashboard/plugin_api.py update_task):

- status='running' via PATCH → ValueError (HTTP 400)
- status='ready' from currently-blocked → kb.unblock_task() (fires
  'unblocked' event)
- status='ready' from anything else, plus status in {'todo', 'triage'}
  → new _set_status_direct() helper that nulls claim fields when leaving
  'running', closes any active run with outcome='reclaimed', and
  appends a 'status' event row to task_events
- status='done', 'blocked', 'archived' → unchanged (already structured)

Frontend changes:
- Drop 'running' from the .kanban-status-actions button row in the task
  detail pane (clicking it would always 400 anyway).
- allowKanbanDrop() refuses the 'running' column as a drop target with
  dropEffect='none' so users see immediate visual feedback that the
  dispatcher/claim path owns running.

Tests added (3, all passing):
- test_patch_status_running_is_rejected_to_protect_dispatcher_contract
- test_patch_status_done_to_running_is_rejected
- test_patch_status_blocked_to_ready_routes_through_unblock_task

Existing 12 tests still pass.

Co-authored-by: ai-ag2026 <ai-ag2026@users.noreply.github.com>
2026-05-04 23:06:42 +00:00
..
__init__.py Hermes Web UI — Sprints 11-14: multi-provider models, settings, session QoL, alerts, polish 2026-03-31 07:02:47 +00:00
agent_sessions.py fix: keep cross-source continuations separate in sidebar 2026-05-04 09:30:47 +02:00
auth.py fix: keep frontend routes under subpath mounts 2026-05-04 00:06:58 -07:00
background.py feat(commands): /background, /btw slash commands + undo button + reasoning chip 2026-04-24 01:24:51 +00:00
clarify.py feat(clarify): SSE long-connection for real-time clarify notifications (#1355) 2026-04-30 21:32:51 +00:00
commands.py feat: slash command parity + skill autocomplete — v0.50.91 (PR #711) 2026-04-19 05:37:44 +00:00
config.py Stage 296: PR #1648 — session save mode config (closes #1406) by @Michaelyklam 2026-05-04 21:26:52 +00:00
extensions.py Opus pre-release follow-ups for PR #1445 2026-05-02 03:49:40 +00:00
gateway_watcher.py release: v0.50.241 (#1293) 2026-04-29 19:54:07 -07:00
helpers.py v0.50.255: Opus follow-ups (4 fixes) + CHANGELOG 2026-05-01 17:19:53 +00:00
kanban_bridge.py fix(kanban): protect dispatcher contract — reject raw status='running' PATCH 2026-05-04 23:06:42 +00:00
metering.py fix: show TPS in assistant message headers 2026-05-04 21:26:43 +00:00
models.py feat: add session save mode config 2026-05-04 14:05:49 -07:00
oauth.py fix(oauth): honor cancel during Codex device-token exchange (follow-up to #1652) 2026-05-04 14:49:38 -07:00
onboarding.py feat: add Codex OAuth onboarding flow 2026-05-04 14:07:16 -07:00
profiles.py Apply Opus pre-release SHOULD-FIX + NITs (in-PR per release policy) 2026-05-04 16:17:26 +00:00
providers.py test: cover provider config cleanup path 2026-05-04 09:04:07 -07:00
rollback.py v0.50.255: Opus follow-ups (4 fixes) + CHANGELOG 2026-05-01 17:19:53 +00:00
routes.py feat: harden Kanban review feedback 2026-05-04 22:56:43 +00:00
session_ops.py Show profile home in /status command (refs #463) (#1380) 2026-05-01 04:46:37 +00:00
session_recovery.py fix: absorb Opus advisor doc-only SHOULD-FIX nits 2026-05-03 20:54:02 +00:00
startup.py fix: P0 hotfixes — API regression, code block parser, chmod override 2026-05-01 12:10:48 +00:00
state_sync.py security: bandit fixes B310/B324/B110 + QuietHTTPServer (#354) 2026-04-13 11:11:56 -07:00
streaming.py Stage 296: PR #1648 — session save mode config (closes #1406) by @Michaelyklam 2026-05-04 21:26:52 +00:00
terminal.py absorb: address Opus review findings (security + correctness) 2026-04-29 05:06:34 +00:00
updates.py chore(release): stamp v0.50.293 — 3-PR batch + 2 Opus follow-ups absorbed 2026-05-04 16:33:57 +00:00
upload.py Merge remote-tracking branch 'refs/remotes/pr/1229' into stage/batch-v0.50.238 2026-04-29 15:17:57 +00:00
workspace.py fix: batch v0.50.234-235 — XSS hardening, workspace validation, profile switch fixes (#1206) 2026-04-27 21:39:30 -07:00