From 713c231cf8d513d65a8f1dc5c23cd0090e2779f7 Mon Sep 17 00:00:00 2001 From: helix4u <4317663+helix4u@users.noreply.github.com> Date: Mon, 18 May 2026 20:36:27 -0700 Subject: [PATCH] docs(kanban): document worker protocol auto-blocks Salvages #21585 by @helix4u. Documents the protocol_violation event (worker exits successfully while task is still running), adds --max-retries to the create flag list and --failure-limit to dispatch. --- website/docs/reference/cli-commands.md | 4 ++-- website/docs/user-guide/features/kanban.md | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/website/docs/reference/cli-commands.md b/website/docs/reference/cli-commands.md index 37e52707cae..c6850e1c17f 100644 --- a/website/docs/reference/cli-commands.md +++ b/website/docs/reference/cli-commands.md @@ -395,7 +395,7 @@ Multi-profile, multi-project collaboration board. Each install can host many boa | `boards show` / `boards current` | Print the currently-active board's name, DB path, and task counts. | | `boards rename ""` | Change a board's display name. Slug is immutable. | | `boards rm ` | Archive (default) or hard-delete a board. `--delete` skips the archive step. Archived boards move to `boards/_archived/-/`. Refused for `default`. | -| `create ""` | Create a new task on the active board. Flags: `--body`, `--assignee`, `--parent` (repeatable), `--workspace scratch\|worktree\|dir:<path>`, `--tenant`, `--priority`, `--triage`, `--idempotency-key`, `--max-runtime`, `--skill` (repeatable). | +| `create "<title>"` | Create a new task on the active board. Flags: `--body`, `--assignee`, `--parent` (repeatable), `--workspace scratch\|worktree\|dir:<path>`, `--tenant`, `--priority`, `--triage`, `--idempotency-key`, `--max-runtime`, `--max-retries`, `--skill` (repeatable). | | `list` / `ls` | List tasks on the active board. Filter with `--mine`, `--assignee`, `--status`, `--tenant`, `--archived`, `--json`. | | `show <id>` | Show a task with comments and events. `--json` for machine output. | | `assign <id> <profile>` | Assign or reassign. Use `none` to unassign. Refused while task is running. | @@ -408,7 +408,7 @@ Multi-profile, multi-project collaboration board. Each install can host many boa | `unblock <id>` | Return a blocked task to ready. | | `archive <id>` | Hide from default list. `gc` will remove scratch workspaces. | | `tail <id>` | Follow a task's event stream. | -| `dispatch` | One dispatcher pass on the active board. Flags: `--dry-run`, `--max N`, `--json`. | +| `dispatch` | One dispatcher pass on the active board. Flags: `--dry-run`, `--max N`, `--failure-limit N`, `--json`. | | `context <id>` | Print the full context a worker would see (title + body + parent results + comments). | | `specify <id>` / `specify --all` | Flesh out a triage-column task into a concrete spec (title + body with goal, approach, acceptance criteria) via the auxiliary LLM, then promote it to `todo`. Flags: `--tenant` (scope `--all` to one tenant), `--author`, `--json`. Configure the model under `auxiliary.triage_specifier` in `config.yaml`. | | `decompose <id>` / `decompose --all` | Fan a triage-column task out into a graph of child tasks routed to specialist profiles by description (the orchestrator-driven path). Falls back to specify-style single-task promotion when the LLM decides the task doesn't benefit from fan-out. Same flags as `specify`. Configure the model under `auxiliary.kanban_decomposer` in `config.yaml`. Also runs automatically every dispatcher tick when `kanban.auto_decompose: true` (the default). See [Auto vs Manual orchestration](/docs/user-guide/features/kanban#auto-vs-manual-orchestration). | diff --git a/website/docs/user-guide/features/kanban.md b/website/docs/user-guide/features/kanban.md index 4fe9533cb95..3bd1b3eeea0 100644 --- a/website/docs/user-guide/features/kanban.md +++ b/website/docs/user-guide/features/kanban.md @@ -337,6 +337,13 @@ Any profile that should be able to work kanban tasks must load the `kanban-worke 3. Call `kanban_heartbeat(note="...")` every few minutes during long operations. 4. Complete with `kanban_complete(summary="...", metadata={...})`, or `kanban_block(reason="...")` if stuck. +That final `kanban_complete` / `kanban_block` call is part of the worker +protocol. If the worker process exits with status 0 while the task is still +`running`, the dispatcher treats that as a protocol violation, emits a +`protocol_violation` event, and auto-blocks the task on the next tick instead +of respawning it into the same loop. This usually means the model wrote a +plain-text answer and exited without using the Kanban tool surface. + `kanban-worker` is a bundled skill, synced into every profile during install and update — there is no separate Skills Hub install step. Verify it is present in whichever profile you use for kanban workers (`researcher`, `writer`, `ops`, @@ -826,6 +833,7 @@ Every transition appends a row to `task_events`. Each row carries an optional `r | `crashed` | `{pid, claimer}` | Worker PID no longer alive but TTL hadn't expired yet. | | `timed_out` | `{pid, elapsed_seconds, limit_seconds, sigkill}` | `max_runtime_seconds` exceeded; dispatcher SIGTERM'd (then SIGKILL'd after 5 s grace) and re-queued. | | `spawn_failed` | `{error, failures}` | One spawn attempt failed (missing PATH, workspace unmountable, …). Counter increments; task returns to `ready` for retry. | +| `protocol_violation` | `{pid, claimer, exit_code}` | Worker exited successfully while the task was still `running`, usually because it answered without calling `kanban_complete` or `kanban_block`. The dispatcher also emits `gave_up` and auto-blocks immediately instead of retrying. | | `gave_up` | `{failures, effective_limit, limit_source, error}` | Circuit breaker fired after N consecutive non-successful attempts. Task auto-blocks with the last error. The effective limit resolves as task `max_retries`, then dispatcher `failure_limit` / `kanban.failure_limit`, then the built-in default. | `hermes kanban tail <id>` shows these for a single task. `hermes kanban watch` streams them board-wide.