hermes-bsd/hermes_cli
Teknium de9238d37e
feat(kanban): hallucination gate + recovery UX for worker-created-card claims (#20232)
Workers completing a kanban task can now claim the ids of cards they
created via an optional ``created_cards`` field on ``kanban_complete``.
The kernel verifies each id exists and was created by the completing
worker's profile; any phantom id blocks the completion with a
``HallucinatedCardsError`` and records a
``completion_blocked_hallucination`` event on the task so the rejected
attempt is auditable. Successful completions also get a non-blocking
prose-scan pass over their ``summary`` + ``result`` that emits a
``suspected_hallucinated_references`` event for any ``t_<hex>``
reference that doesn't resolve.

Closes #20017.

Recovery UX (kernel + CLI + dashboard)
--------------------------------------

A structural gate alone isn't enough — operators also need to see and
act on stuck workers, especially when a profile's model is the root
cause. This PR ships the full loop:

* ``kanban_db.reclaim_task(task_id)`` — operator-driven reclaim that
  releases an active worker claim immediately (unlike
  ``release_stale_claims`` which only acts after claim_expires has
  passed). Emits a ``reclaimed`` event with ``manual: True`` payload.
* ``kanban_db.reassign_task(task_id, profile, reclaim_first=...)`` —
  switch a task to a different profile, optionally reclaiming a stuck
  running worker in the same call.
* ``hermes kanban reclaim <id> [--reason ...]`` and
  ``hermes kanban reassign <id> <profile> [--reclaim] [--reason ...]``
  CLI subcommands wired through to the same helpers.
* ``POST /api/plugins/kanban/tasks/{id}/reclaim`` and
  ``POST /api/plugins/kanban/tasks/{id}/reassign`` endpoints on the
  dashboard plugin.

Dashboard surfacing
-------------------

* ⚠ **warning badge** on cards with active hallucination events.
* **attention strip** at the top of the board listing all flagged
  tasks; dismissible per session.
* **events callout** in the task drawer — hallucination events render
  with a red left border, amber icon, and phantom ids as styled chips.
* **recovery section** in the task drawer with three actions: Reclaim,
  Reassign (with profile picker + reclaim-first checkbox), and a
  copy-to-clipboard hint for ``hermes -p <profile> model`` since
  profile config lives on disk and can't be edited from the browser.
  Auto-opens when the task has warnings, collapsed otherwise.
  Keyed by task id so state doesn't leak between drawers.

Active-vs-stale rule: warnings clear when a clean ``completed`` or
``edited`` event supersedes the hallucination, so recovery is never
permanently stigmatising — the audit events persist for debugging but
the badge goes away once the worker succeeds.

Skill updates
-------------

* ``skills/devops/kanban-worker/SKILL.md`` documents the
  ``created_cards`` contract with good/bad examples.
* ``skills/devops/kanban-orchestrator/SKILL.md`` gains a "Recovering
  stuck workers" section with the three actions and when to use each.

Tests
-----

* Kernel gate: verified-cards manifest, phantom rejection + audit
  event, cross-worker rejection, prose scan positive + negative.
* Recovery helpers: reclaim on running task, reclaim on non-running
  returns False, reassign refuses running without reclaim_first,
  reassign with reclaim_first succeeds on running.
* API endpoints: warnings field present on /board and /tasks/:id,
  warnings cleared after clean completion, reclaim 200 + 409 paths,
  reassign 200 + 409 + reclaim_first paths.
* CLI smoke: reclaim + reassign subcommands.

Live-verified end-to-end on a dashboard with seeded scenarios:
attention strip renders, badges land on the right cards, drawer
callout shows phantom chips, Reclaim on a running task flips status to
ready + emits manual reclaimed event + refreshes the drawer,
Reassign swaps the assignee and triggers board refresh.

359/359 kanban-suite tests pass
(test_kanban_{db,cli,boards,core_functionality} + dashboard + tools).
2026-05-05 08:06:55 -07:00
..
__init__.py
_parser.py
auth.py
auth_commands.py
azure_detect.py
backup.py fix(backup): floor pre-update backup_keep to 1 so the new backup survives 2026-05-04 05:07:13 -07:00
banner.py
browser_connect.py
callbacks.py
claw.py fix(claw): handle missing dir in _scan_workspace_state 2026-05-05 06:08:14 -07:00
cli_output.py
clipboard.py
codex_models.py
colors.py
commands.py feat(telegram): /topic off + help + auth gate + screenshot debounce 2026-05-04 12:07:17 -07:00
completion.py
config.py feat(i18n): add display.language for static message translation (zh/ja/de/es) (#20231) 2026-05-05 08:03:07 -07:00
copilot_auth.py
cron.py feat(cron): add no_agent mode for script-only cron jobs (watchdog pattern) (#19709) 2026-05-04 12:31:01 -07:00
curator.py feat(curator): add archive and prune subcommands (#20200) 2026-05-05 05:15:54 -07:00
curses_ui.py
debug.py
default_soul.py
dingtalk_auth.py
doctor.py fix(doctor): check gh auth status when GITHUB_TOKEN absent 2026-05-04 12:34:31 -07:00
dump.py
env_loader.py
fallback_cmd.py
gateway.py fix(gateway): handle planned service stops 2026-05-04 16:00:49 -07:00
goals.py
hooks.py
kanban.py feat(kanban): hallucination gate + recovery UX for worker-created-card claims (#20232) 2026-05-05 08:06:55 -07:00
kanban_db.py feat(kanban): hallucination gate + recovery UX for worker-created-card claims (#20232) 2026-05-05 08:06:55 -07:00
logs.py
main.py fix(cli): pin HERMES_KANBAN_BOARD at chat boot to stop subprocess board drift 2026-05-05 04:37:47 -07:00
mcp_config.py
memory_setup.py
model_catalog.py
model_normalize.py
model_switch.py fix: resolve model.aliases from config.yaml in /model alias resolution 2026-05-05 05:49:01 -07:00
models.py fix(models): strip :cloud/-cloud suffix from models.dev Ollama Cloud IDs 2026-05-04 12:38:15 -07:00
nous_subscription.py
oneshot.py
pairing.py
platforms.py
plugins.py
plugins_cmd.py
profiles.py
providers.py
pty_bridge.py
relaunch.py
runtime_provider.py
setup.py fix(cli): sanitize bracketed paste markers during setup 2026-05-05 06:12:42 -07:00
skills_config.py
skills_hub.py
skin_engine.py
slack_cli.py
status.py fix(status): add missing popular provider API keys to hermes status display 2026-05-04 05:14:13 -07:00
timeouts.py
tips.py feat(tips): add 100 new CLI startup tips (#20168) 2026-05-05 04:15:58 -07:00
tools_config.py
uninstall.py
vercel_auth.py
voice.py fix(tui): respect voice.record_key config (supersedes #19028, #19339) (#19835) 2026-05-04 15:49:28 -07:00
web_server.py
webhook.py