mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-28 06:51:16 +08:00
Integration audit of the runs-as-first-class work (0146cb2bd) found five
bugs where structured runs got orphaned or dashboard parity was missing.
All behavioral fixes; no schema change needed.
Kernel
- archive_task: when called on a running task, now closes the
in-flight run with outcome='reclaimed' and clears current_run_id.
Previously, dashboard bulk-archive or CLI `kanban archive <running>`
would leave the task_runs row open with ended_at=NULL forever and
strand the pointer. Adds the claim_lock / claim_expires / worker_pid
clearing to the UPDATE so the task row is clean too.
- complete_task: embeds the first-line handoff summary in the
`completed` event payload (capped at 400 chars). Notifier can now
render `✔ task done — <title>\n<summary>` without a second SQL hit,
and the full summary still lives on the run row.
Dashboard plugin
- _set_status_direct: drag-drop OFF 'running' (to 'ready', 'todo',
'triage', 'done' — anywhere except back to 'running') now closes
the active run with outcome='reclaimed'. Clears worker_pid too.
Snapshots previous status + current_run_id before the UPDATE so
the decision has the right before-state. status event rows now
carry run_id when closing a run, NULL otherwise.
- UpdateTaskBody: adds `summary` and `metadata` fields. PATCH
/tasks/:id with status='done' now forwards them to complete_task,
giving the dashboard parity with `hermes kanban complete --summary
... --metadata ...`. Previously these fields only existed on the
CLI.
CLI
- `hermes kanban complete a b c --summary X` or `--metadata Y`:
refused with a clear stderr message instead of silently applying
the same handoff to every task. Bulk-close without handoff flags
still works. (Note: hermes_cli.main discards subcommand exit
codes via `args.func(args)` without propagating; tracked
separately. Side-effect check is the real guard.)
Gateway notifier
- Completion message prefers run.summary (carried in event payload)
over task.result. task.result remains the fallback for legacy rows
written before runs shipped.
- Docstring: renamed stale `spawn_auto_blocked` reference to
`gave_up` / `timed_out` — matches the actual TERMINAL_KINDS
tuple, which was already correct in code.
Tests (+8 in core functionality, +3 in dashboard plugin)
- archive_of_running_task_closes_run
- archive_of_ready_task_does_not_create_spurious_run
- dashboard_direct_status_change_off_running_closes_run
- dashboard_direct_status_change_within_same_state_is_noop_for_runs
- cli_bulk_complete_with_summary_rejects (side-effect assertion)
- cli_bulk_complete_without_summary_still_works
- completed_event_payload_carries_summary
- completed_event_payload_summary_none_when_missing
- patch_status_done_with_summary_and_metadata
- patch_status_done_without_summary_still_works (legacy path)
- patch_status_archive_closes_running_run (E2E through FastAPI TestClient)
164/164 kanban suite pass under scripts/run_tests.sh. Live smoke
(execute_code with isolated HERMES_HOME) covered all five fixed paths
plus a re-claim-after-drag-drop to confirm the fresh run is tracked
correctly after the orphan close.