docs(kanban): worker lane contract + review-required convention (closes #19931)#23483
Merged
Conversation
Closes the architectural-pin part of #19931. Most of what that issue asked for is already implemented (logs under kanban root, env-pinned workspace, dispatcher routing of unknown assignees, lifecycle ownership, structured handoff conventions). What was missing: 1. A written contract integrators can point at when adding a new worker lane shape, and 2. The "code-changing workers should not auto-promote success to done" convention. This commit ships both as docs+convention layered on existing primitives. No kernel changes — the kanban_complete / kanban_block / kanban_comment surfaces already support the review-required pattern; we just hadn't written it down or made it visible to workers. Changes: - `agent/prompt_builder.py::KANBAN_GUIDANCE`: append the review-required exception to step 5 of the lifecycle. Workers get the cue auto-injected into their system prompt — drop structured metadata into a kanban_comment first, then end with kanban_block(reason="review-required: <summary>") instead of kanban_complete when the work needs review. Total prompt size went from ~3000 to ~3275 chars; well under the 4096 budget enforced by test_kanban_guidance_size. - `skills/devops/kanban-worker/SKILL.md`: add a worked example to the existing "Good summary + metadata shapes" section between the Coding-task and Research-task examples. Same shape as the others (kanban_comment with structured handoff JSON, then kanban_block with the human-readable reason). Plus a one-line guide on when to use kanban_complete vs the review-required pattern. - `website/docs/user-guide/features/kanban-worker-lanes.md` (new): the integrator-facing contract. Covers the hierarchy, the three things every lane must provide (assignee, spawn mechanism, lifecycle terminator), the env vars the dispatcher injects, the review-required convention, the failure modes the kernel handles for free, and an explicit "external CLI worker lane" deferred- pending-concrete-asker section that links to #19931 and #19924. - `website/sidebars.ts`: link the new page under user-guide/features. The "specialist worker lanes for external CLI tools (Codex / Claude Code / OpenCode)" runner is NOT shipped here. The dispatcher's spawn_fn parameter already supports plugin-shaped extension; the per-CLI integration work (auth, sandbox policy, exit-code mapping) needs a concrete asker. The new docs page tells would-be integrators the contract any such lane must satisfy. Refs #19931
Contributor
🔎 Lint report:
|
| Rule | Count |
|---|---|
invalid-argument-type |
3 |
First entries
run_agent.py:7160: [invalid-argument-type] invalid-argument-type: Argument to function `build_anthropic_client` is incorrect: Expected `str`, found `str | dict[Unknown, Unknown] | Any | ... omitted 3 union elements`
run_agent.py:13287: [invalid-argument-type] invalid-argument-type: Argument to function `len` is incorrect: Expected `Sized`, found `(str & ~AlwaysFalsy) | (dict[Unknown, Unknown] & ~AlwaysFalsy) | (Any & ~AlwaysFalsy) | ... omitted 3 union elements`
run_agent.py:13284: [invalid-argument-type] invalid-argument-type: Argument to function `_is_oauth_token` is incorrect: Expected `str`, found `str | dict[Unknown, Unknown] | Any | ... omitted 3 union elements`
✅ Fixed issues (3):
| Rule | Count |
|---|---|
invalid-argument-type |
3 |
First entries
run_agent.py:13287: [invalid-argument-type] invalid-argument-type: Argument to function `len` is incorrect: Expected `Sized`, found `(str & ~AlwaysFalsy) | (dict[Unknown | str, Unknown | str | dict[str, str]] & ~AlwaysFalsy) | (Any & ~AlwaysFalsy) | ... omitted 3 union elements`
run_agent.py:13284: [invalid-argument-type] invalid-argument-type: Argument to function `_is_oauth_token` is incorrect: Expected `str`, found `str | dict[Unknown | str, Unknown | str | dict[str, str]] | Any | ... omitted 3 union elements`
run_agent.py:7160: [invalid-argument-type] invalid-argument-type: Argument to function `build_anthropic_client` is incorrect: Expected `str`, found `str | dict[Unknown | str, Unknown | str | dict[str, str]] | Any | ... omitted 3 union elements`
Unchanged: 4263 pre-existing issues carried over.
Diagnostics are surfaced as warnings — this check never fails the build.
This was referenced May 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes the architectural-pin part of #19931 with docs + a small
review-requiredconvention, no kernel changes.What's missing on main vs the issue's 6 architectural rules
<root>/kanban/logs/<task_id>.logworker_logs_dir(board=...)--yolomode for autonomous workersskipped_nonspawnablelane + recent #23273 toolset-name validationkanban_complete(metadata={...})carries this; this PR documents the convention explicitlyWhat this PR ships
agent/prompt_builder.py::KANBAN_GUIDANCE: ~60 chars added to step 5 explaining the review-required exception. Auto-injected into every kanban worker's system prompt, so workers see the cue without loading any extra skill. Prompt size 3275/4096 chars; well under the test-enforced budget.skills/devops/kanban-worker/SKILL.md: worked example for thekanban_comment(structured metadata) +kanban_block(reason="review-required: ...")pattern, slotted between the existing Coding-task and Research-task examples.website/docs/user-guide/features/kanban-worker-lanes.md(new): the integrator-facing contract page. Covers the lane hierarchy, the three things every lane must provide (assignee, spawn mechanism, lifecycle terminator), the env vars the dispatcher injects, the review-required convention, the failure modes the kernel handles for free, and an explicit "external CLI worker lane" section flagged as deferred-pending-concrete-asker (with links back to Architecture: specialist worker lanes under Hermes Kanban orchestration #19931 and the closed-not-merged Codex PR feat: add Codex Kanban worker lane #19924).website/sidebars.ts: link the new page under user-guide/features.Why no kernel changes
kanban_complete/kanban_block/kanban_commentalready do everything needed.block_taskaccepts a free-formreason; comments are the durable structured-metadata channel; the dashboard already renders both.Why no
kanban_block(metadata=...)extensionThe skill example uses
kanban_comment(body=json.dumps(...))followed bykanban_block(reason=...)— comments are the durable annotation channel. Extendingkanban_blockto take metadata would be a real new tool surface; not warranted by one convention.What's NOT in this PR
External CLI worker lane runner (Codex CLI, Claude Code CLI, OpenCode CLI as kanban workers via dispatcher →
<cli> --task=<id>). The dispatcher'sspawn_fnparameter already supports plugin-shaped extension, but the per-CLI integration work (auth, sandbox policy, exit-code mapping, workspace injection) needs a concrete asker. The new docs page tells would-be integrators the contract any such lane must satisfy.#19924 was the Codex-specific concrete proposal; it closed without merging. Until someone shows up with a concrete plugin proposal and a real workflow they're trying to enable, the docs-only path is the right shape.
Validation
KANBAN_GUIDANCEsizetests/tools/test_kanban_tools.py(kanban_guidance subset)tests/tools/test_kanban_tools.py + tests/hermes_cli/test_kanban_db.py + test_kanban_core_functionality.pyCloses #19931.