Skip to content

feat(kanban): support operator skill/failure/claim recovery via edit - #82234

Open
hendrixfreire wants to merge 1 commit into
NousResearch:mainfrom
hendrixfreire:fix/kanban-task-skill-recovery
Open

hendrixfreire wants to merge 1 commit into
NousResearch:mainfrom
hendrixfreire:fix/kanban-task-skill-recovery

Conversation

@hendrixfreire

@hendrixfreire hendrixfreire commented Aug 9, 2026

Copy link
Copy Markdown

What does this PR do?

Adds a first-class operator recovery surface to Hermes Kanban so the most common
post-dispatch failures can be fixed through supported CLI/API/dashboard paths
instead of editing the SQLite database by hand (issue #22925).

hermes kanban edit <id> (and /kanban edit) gains recovery flags shared by a
single kernel function (kanban_db.edit_task_recovery) that the CLI, the
/kanban gateway command, and the dashboard API all call:

  • --skills NAME... — replace a task's force-loaded skills (the "Unknown
    skill(s)" dispatch-failure class). Path-like names, toolset names, and
    comma-joined strings are rejected with a clear usage error; namespaced hub
    ids like official/category/name are preserved.
  • --clear-skills (alias --skills []) — store an explicit empty skill list,
    distinct from unset (= profile defaults).
  • --reset-failures — zero consecutive_failures and clear
    last_failure_error so the dispatcher's circuit breaker stops tripping.
  • --clear-claim — clear a stale (TTL-expired) claim and return the task
    to ready, closing the dangling run as reclaimed; refuses a live claim.

The dashboard exposes the same flow in the task drawer as a Skill recovery
control (replace/clear skills, reset failures, clear stale claim, and a
Save & retry action that applies the edit then unblocks to ready), backed
by POST /api/plugins/kanban/tasks/:id/recovery.

Related Issue

Refs #22925

Related/duplicate PRs found in duplicate-check:

Type of Change

  • ✨ New feature (non-breaking change that adds functionality)
  • ✅ Tests (adding or improving test coverage)
  • 📝 Documentation update

Changes Made

  • hermes_cli/kanban_db.py — new edit_task_recovery() kernel function with
    active-claim guard, live-claim guard, audit trail (edited event + operator
    comment); refactored skill normalization/validation into shared
    _normalize_skill_names() (used by both create and recovery), adding
    path-like-name rejection.
  • hermes_cli/kanban.pyedit subcommand recovery flags, --skills []
    alias handling, clear help text, slash help row.
  • plugins/kanban/dashboard/plugin_api.pyPOST /tasks/:id/recovery
    endpoint (400/404/409 mapping, returns updated task).
  • plugins/kanban/dashboard/dist/index.js + dist/style.css — Skill recovery
    control in the task drawer (disabled while a live worker is claimed).
  • tests/hermes_cli/test_kanban_task_skill_recovery.py — new E2E regression
    tests: kernel API + CLI recovery, live-claim guard, stale-claim clear, path
    rejection, audit trail, default + named boards.
  • tests/plugins/test_kanban_dashboard_plugin.py — dashboard endpoint tests.
  • website/docs/user-guide/features/kanban.md — new "Recovering a task after
    a dispatch failure" section + REST table row.
  • website/docs/reference/cli-commands.mdedit CLI reference row.

How to Test

  1. Create a task with a bad force-loaded skill and let the dispatch block it:
    hermes kanban create "test recovery" --skills nonexistent-skill --assignee <profile>
    (or simulate: hermes kanban edit t_xxx --skills translation --reset-failures)
  2. Replace the wrong skill and reset the failure streak, then release:
    hermes kanban edit t_xxx --skills translation --reset-failures
    hermes kanban unblock t_xxx
  3. Verify the task returns to ready and dispatches; hermes kanban show t_xxx
    shows an edited event and a RECOVERY EDIT: skills, failures comment.
  4. Dashboard: open the task drawer → Skill recovery → Save & retry.

Automated verification:

  • scripts/run_tests.sh tests/hermes_cli/test_kanban_task_skill_recovery.py tests/plugins/test_kanban_dashboard_plugin.py → 66 passed / 0 failed
  • scripts/run_tests.sh (full kanban sweep, 42 files) → 268 passed / 0 failed
  • scripts/run_tests.sh tests/cli/ → 953 passed / 0 failed
  • ruff check on all touched files → pass
  • scripts/check-windows-footguns.py --all → pass (939 files)
  • node --check plugins/kanban/dashboard/dist/index.js → exit 0

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (feat(kanban): …)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass (via scripts/run_tests.sh)
  • I've added tests for my changes
  • I've tested on my platform: macOS 26.5 (arm64), Python 3.11.15

Documentation & Housekeeping

  • I've updated relevant documentation (kanban.md, cli-commands.md) — not N/A
  • cli-config.yaml.example — N/A (no new config keys)
  • CONTRIBUTING.md/AGENTS.md — N/A (no architecture/workflow change to those docs)
  • I've considered cross-platform impact (Windows, macOS): skill path rejection handles both / and \ separators; check-windows-footguns.py passes
  • I've updated tool descriptions/schemas for changed tool behavior — N/A (kanban CLI help text updated; no tool schema change)

Screenshots / Logs

Test evidence (commands + results) captured during validation; see "How to Test"
above for the summary counts.

Adds a first-class recovery surface to `hermes kanban edit` (and the
dashboard task drawer) for the most common post-dispatch failures, so
operators no longer need to edit the SQLite DB by hand (issue NousResearch#22925):

* `--skills NAME...` replaces a task's force-loaded skills (the
  "Unknown skill(s)" dispatch-failure class); path-like names, toolset
  names, and comma-joined strings are rejected with a clear usage error.
  `--clear-skills` (or `--skills []`) stores an explicit empty list,
  distinct from unset (= profile defaults).
* `--reset-failures` zeroes consecutive_failures and clears
  last_failure_error so the dispatcher's circuit breaker stops tripping.
* `--clear-claim` clears a stale (TTL-expired) claim and returns the task
  to ready, closing the dangling run as `reclaimed`; refuses a live claim.

Safety invariants (kernel kanban_db.edit_task_recovery, shared by CLI,
/kanban, and dashboard API):
* Skills/failure edits are refused while a task is actively claimed/running
  (a live worker's payload is never mutated underneath it).
* `--clear-claim` refuses a claim whose TTL has not expired (use reclaim).
* Every applied edit records an `edited` event + a `RECOVERY EDIT:` comment
  under the operator's name; no recovery path touches the SQLite DB directly.

Ships the matching dashboard API endpoint POST /tasks/:id/recovery and the
Skill recovery control in the task drawer (Save & retry, disabled while a
live worker is claimed), plus docs (kanban.md recovery section, cli-commands
reference, slash help) and E2E regression tests for the blocked
dispatch-failure -> edit/clear skills -> reset failures -> unblock loop on
default and named boards, including the audit trail.

Closes NousResearch#22925
@spfcraze

spfcraze commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

This was generated by AI during triage.

Summary:
Fixes #22925 will auto-close the issue on merge, but the issue's proposed one-shot hermes kanban reset convenience command is not in this diff.

Problems:

Solution:
Link #22925 without the Fixes keyword, so the merge does not auto-close the issue while one of its proposed commands is undelivered.


Checked against 6fbfc22 — the PR head when this was written — and 2446c8b, main at the same moment.

@hendrixfreire hendrixfreire changed the title feat(kanban): support operator skill/failure/claim recovery via edit (closes #22925) feat(kanban): support operator skill/failure/claim recovery via edit Aug 9, 2026
@hendrixfreire

Copy link
Copy Markdown
Author

Thanks for the review — good catch. I removed the auto-close keyword so this PR no longer resolves #22925.

Changes applied:

  • Title: dropped the (closes #22925) suffix
  • Body: Fixes #22925Refs #22925 in the Related Issue section

The issue now stays open, correctly signaling that the proposed hermes kanban reset convenience command is still pending and will be delivered separately.

@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/cli CLI entry point, hermes_cli/, setup wizard comp/cron Cron scheduler and job management comp/dashboard Web dashboard / control panel UI (dashboard/, landing) comp/plugins Plugin system and bundled plugins tool/skills Skills system (list, view, manage) labels Aug 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard comp/cron Cron scheduler and job management comp/dashboard Web dashboard / control panel UI (dashboard/, landing) comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have tool/skills Skills system (list, view, manage) type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants