From 84e1d31e5442eeff0bfcf1c2ffab6acf7fe95f45 Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Sun, 21 Jun 2026 17:06:48 -0700 Subject: [PATCH] refactor(kanban): fold worker/orchestrator skills into injected guidance (#50473) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The kanban-worker and kanban-orchestrator bundled skills existed only to be force-loaded into dispatcher-spawned workers, gated by environments:[kanban] so they wouldn't leak into normal CLI listings. That gating was fragile (the leak that #50443 patched) and the --skills auto-load was already best-effort — most workers ran without it because the bundled skill isn't present in profile-scoped skills dirs. Remove the skills entirely and promote their load-bearing content (workspace kinds, deliverable artifacts, created-card integrity, profile discovery) into KANBAN_GUIDANCE, which is already injected into every kanban worker's system prompt. Net result: every worker reliably gets the guidance, nothing can leak into a CLI/blank-slate session, and the gating machinery is gone. - agent/prompt_builder.py: promote the 4 load-bearing rules into KANBAN_GUIDANCE - hermes_cli/kanban_db.py: drop --skills kanban-worker auto-injection + _kanban_worker_skill_available probe - hermes_cli/kanban_swarm.py: drop skills=[kanban-orchestrator] on the root card - hermes_cli/kanban.py: drop kanban-init skill seeding; fix help text - delete skills/devops/kanban-{worker,orchestrator} - docs: delete the two skill pages (EN+zh), fix sidebars/catalog/kanban.md/kanban-worker-lanes.md and the video-orchestrator + codex-lane references - tests: update spawn-argv expectations; re-bound the guidance-size guard Supersedes the skill-leak half of #50443 (credit @helix4u for flagging the area). --- agent/prompt_builder.py | 17 ++ agent/skill_utils.py | 6 +- hermes_cli/kanban.py | 24 +- hermes_cli/kanban_db.py | 87 ++----- hermes_cli/kanban_swarm.py | 1 - .../kanban-video-orchestrator/SKILL.md | 7 +- .../assets/setup.sh.tmpl | 2 +- .../references/examples.md | 4 +- .../references/kanban-setup.md | 10 +- .../references/role-archetypes.md | 54 ++-- .../references/tool-matrix.md | 37 +-- .../scripts/bootstrap_pipeline.py | 2 - skills/devops/kanban-orchestrator/SKILL.md | 214 ---------------- skills/devops/kanban-worker/SKILL.md | 214 ---------------- .../test_kanban_core_functionality.py | 52 ++-- tests/hermes_cli/test_kanban_goal_mode.py | 3 - tests/tools/test_kanban_tools.py | 14 +- tools/kanban_tools.py | 4 +- website/docs/reference/skills-catalog.md | 3 +- .../features/kanban-worker-lanes.md | 11 +- website/docs/user-guide/features/kanban.md | 45 +--- .../autonomous-ai-agents-kanban-codex-lane.md | 2 +- .../devops/devops-kanban-orchestrator.md | 231 ------------------ .../bundled/devops/devops-kanban-worker.md | 210 ---------------- .../creative-kanban-video-orchestrator.md | 4 +- .../current/reference/skills-catalog.md | 3 +- .../features/kanban-worker-lanes.md | 11 +- .../current/user-guide/features/kanban.md | 40 +-- .../devops/devops-kanban-orchestrator.md | 207 ---------------- .../bundled/devops/devops-kanban-worker.md | 202 --------------- .../creative-kanban-video-orchestrator.md | 4 +- website/sidebars.ts | 10 - 32 files changed, 160 insertions(+), 1575 deletions(-) delete mode 100644 skills/devops/kanban-orchestrator/SKILL.md delete mode 100644 skills/devops/kanban-worker/SKILL.md delete mode 100644 website/docs/user-guide/skills/bundled/devops/devops-kanban-orchestrator.md delete mode 100644 website/docs/user-guide/skills/bundled/devops/devops-kanban-worker.md delete mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/skills/bundled/devops/devops-kanban-orchestrator.md delete mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/skills/bundled/devops/devops-kanban-worker.md diff --git a/agent/prompt_builder.py b/agent/prompt_builder.py index 97836f27b05..92378512261 100644 --- a/agent/prompt_builder.py +++ b/agent/prompt_builder.py @@ -238,6 +238,23 @@ KANBAN_GUIDANCE = ( "of the decomposition. Do NOT execute the work yourself; your job is " "routing, not implementation.\n" "\n" + "## Reference details that change outcomes\n" + "\n" + "- **Workspace.** `cd $HERMES_KANBAN_WORKSPACE` first. For a `worktree` kind " + "with no `.git`, `git worktree add " + "${HERMES_KANBAN_BRANCH:-wt/$HERMES_KANBAN_TASK}` from the main repo, then " + "cd there.\n" + "- **Deliverables.** Files a human wants go in " + "`kanban_complete(artifacts=[])` (top-level param; paths in " + "`metadata` are NOT uploaded). Files must exist at completion.\n" + "- **Created cards.** List ids in `kanban_complete(created_cards=[...])` " + "ONLY when captured from a successful `kanban_create` return — never invent " + "or paste ids; the kernel rejects the completion on any phantom id.\n" + "- **Orchestrating: discover profiles first.** The dispatcher SILENTLY " + "drops a card with an unknown assignee (it sits in `ready` forever). Ground " + "every assignee in a real profile (`hermes profile list`, or ask the user), " + "and express dependencies via `parents=[...]` on `kanban_create`, not prose.\n" + "\n" "## Do NOT\n" "\n" "- Do not shell out to `hermes kanban ` for board operations. Use " diff --git a/agent/skill_utils.py b/agent/skill_utils.py index 9f16534a450..338fa37cb85 100644 --- a/agent/skill_utils.py +++ b/agent/skill_utils.py @@ -280,9 +280,9 @@ def skill_matches_environment(frontmatter: Dict[str, Any]) -> bool: This is an OFFER-time filter: it controls whether a skill shows up in the skills index / autocomplete / slash-command list. It is intentionally NOT enforced by ``skill_view`` or ``--skills`` preloading — an explicit load is - explicit consent, and load-bearing force-loads (e.g. the kanban dispatcher - injecting ``--skills kanban-worker``) must always succeed regardless of how - the offer surfaces filter the skill. + explicit consent, and load-bearing force-loads (e.g. a dispatcher pinning + a task to a specialist skill via ``--skills``) must always succeed + regardless of how the offer surfaces filter the skill. A skill matches when ANY of its declared environments is currently active (OR semantics, mirroring ``platforms``). Unknown env tags fail open. diff --git a/hermes_cli/kanban.py b/hermes_cli/kanban.py index 31c4bf68ae8..db83b9f64f8 100644 --- a/hermes_cli/kanban.py +++ b/hermes_cli/kanban.py @@ -26,7 +26,7 @@ from typing import Any, Optional from hermes_cli import kanban_db as kb from hermes_cli import kanban_swarm as ks -from hermes_cli.profiles import get_active_profile_name, get_profile_dir, seed_profile_skills +from hermes_cli.profiles import get_active_profile_name # --------------------------------------------------------------------------- @@ -330,8 +330,8 @@ def build_parser(parent_subparsers: argparse._SubParsersAction) -> argparse.Argu help="Author name recorded on the task (default: user)") p_create.add_argument("--skill", action="append", default=[], dest="skills", help="Skill to force-load into the worker " - "(repeatable). Appended to the built-in " - "kanban-worker skill. Example: " + "(repeatable). The kanban lifecycle is already " + "injected automatically. Example: " "--skill translation --skill github-code-review") p_create.add_argument("--max-retries", type=int, default=None, metavar="N", @@ -1223,21 +1223,6 @@ def _cmd_init(args: argparse.Namespace) -> int: path = kb.init_db() print(f"Kanban DB initialized at {path}") - # Seed bundled skills (e.g. kanban-worker) into the active profile so - # the kanban dispatcher can use them without a separate `hermes profile - # create` step. This is best-effort — a missing or broken profile is - # not fatal to `kanban init`. - try: - profile_name = get_active_profile_name() or "default" - profile_dir = get_profile_dir(profile_name) - result = seed_profile_skills(profile_dir, quiet=True) - if result: - copied = result.get("copied", []) - if copied: - print(f"Seeded skill(s) into profile {profile_name}: {', '.join(copied)}") - except Exception: - pass # best-effort - print() # Enumerate profiles on disk so the user knows what assignees are # already addressable. Multica does this auto-detection on its @@ -1461,8 +1446,7 @@ def _cmd_show(args: argparse.Namespace) -> int: parents = kb.parent_ids(conn, args.task_id) children = kb.child_ids(conn, args.task_id) runs = kb.list_runs(conn, args.task_id, **rsk) - # Workers hand off via ``task_runs.summary`` (kanban-worker skill); - # ``tasks.result`` is left NULL unless the caller explicitly passed + # Workers hand off via ``task_runs.summary``; ``tasks.result`` is left NULL unless the caller explicitly passed # ``result=``. Surfacing the latest summary here keeps ``show`` from # looking like a no-op when the worker actually did real work. latest_summary = kb.latest_summary(conn, args.task_id) diff --git a/hermes_cli/kanban_db.py b/hermes_cli/kanban_db.py index 8127a7a0ad8..c3107e37d75 100644 --- a/hermes_cli/kanban_db.py +++ b/hermes_cli/kanban_db.py @@ -804,10 +804,9 @@ class Task: current_run_id: Optional[int] = None workflow_template_id: Optional[str] = None current_step_key: Optional[str] = None - # Force-loaded skills for the worker on this task (appended to the - # dispatcher's built-in `kanban-worker` via --skills). Stored as a - # JSON array of skill names. None = use only the defaults; empty - # list = explicitly no extra skills. + # Force-loaded skills for the worker on this task (passed via + # --skills). Stored as a JSON array of skill names. None = use only + # the defaults; empty list = explicitly no extra skills. skills: Optional[list] = None model_override: Optional[str] = None # Per-task override for the consecutive-failure circuit breaker. @@ -1045,8 +1044,7 @@ CREATE TABLE IF NOT EXISTS tasks ( workflow_template_id TEXT, current_step_key TEXT, -- Force-loaded skills for the worker on this task, stored as JSON. - -- Appended to the dispatcher's built-in `--skills kanban-worker`. - -- NULL or empty array = no extras. + -- Passed to the worker via `--skills`. NULL or empty array = no extras. skills TEXT, -- Per-task model override. When set, the dispatcher passes -m -- to the worker, overriding the profile's default model. NULL = use @@ -1848,8 +1846,7 @@ def _migrate_add_optional_columns(conn: sqlite3.Connection) -> None: ) if "skills" not in cols: # JSON array of skill names the dispatcher force-loads into the - # worker (additive to the built-in `kanban-worker`). NULL is fine - # for existing rows. + # worker via --skills. NULL is fine for existing rows. _add_column_if_missing(conn, "tasks", "skills", "skills TEXT") if "max_retries" not in cols: @@ -2285,9 +2282,8 @@ def create_task( ``skills`` is an optional list of skill names to force-load into the worker when dispatched. Stored as JSON; the dispatcher passes - each name to ``hermes --skills ...`` alongside the built-in - ``kanban-worker``. Use this to pin a task to a specialist skill - (e.g. ``skills=["translation"]`` so the worker loads the + each name to ``hermes --skills ...``. Use this to pin a task to a + specialist skill (e.g. ``skills=["translation"]`` so the worker loads the translation skill regardless of the profile's default config). """ assignee = _canonical_assignee(assignee) @@ -2348,7 +2344,7 @@ def create_task( f"{quoted} {noun}, not skill name(s). " "Put toolsets in the assignee profile's `toolsets:` config " "instead of per-task skills. Skills are named skill bundles " - "(e.g. `kanban-worker`, `blogwatcher`); toolsets are runtime " + "(e.g. `blogwatcher`, `github-code-review`); toolsets are runtime " "capabilities (e.g. `web`, `browser`, `terminal`)." ) skills_list = cleaned @@ -6994,11 +6990,11 @@ def _dispatch_once_locked( if claimed.workspace_kind == "worktree": set_branch_name(conn, claimed.id, resolved_branch_name or (claimed.branch_name or "").strip() or f"wt/{claimed.id}") _maybe_emit_scratch_tip(conn, claimed.id, claimed.workspace_kind) - # Force-load sdlc-review skill for review agents. The - # _default_spawn function already auto-loads kanban-worker, and - # appends task.skills via --skills. Setting task.skills here - # means the review agent gets both kanban-worker (lifecycle) - # and sdlc-review (review logic: AC verification, merge, etc.). + # Force-load the sdlc-review skill for review agents — it carries + # the review logic (AC verification, merge, etc.). The mandatory + # kanban lifecycle is already injected into every worker's system + # prompt via KANBAN_GUIDANCE, so this is the only extra skill the + # review agent needs. claimed.skills = ["sdlc-review"] _spawn = spawn_fn if spawn_fn is not None else _default_spawn try: @@ -7223,41 +7219,6 @@ def _resolve_hermes_argv() -> list[str]: return _module_hermes_argv() -def _kanban_worker_skill_available(hermes_home: Optional[str]) -> bool: - """True if the bundled ``kanban-worker`` skill resolves for the home the - spawned worker will run under. - - The dispatcher injects ``--skills kanban-worker`` into every worker. When - the worker activates a profile (``hermes -p ``), its ``SKILLS_DIR`` - becomes ``/skills`` — which on many profiles does NOT contain - the bundled skill (it ships in the *default* root home, not every - profile-scoped skills dir). Preloading a missing skill is fatal at CLI - startup (``ValueError: Unknown skill(s): kanban-worker``), aborting the - worker before the agent loop runs. Gate the flag on actual resolvability; - the kanban lifecycle contract is still injected via ``KANBAN_GUIDANCE``, so - omitting the flag only drops the supplementary pattern library. - """ - from pathlib import Path as _Path - - # An unset HERMES_HOME means the worker falls back to the default root - # home (``~/.hermes``), which ships the bundled skill. - base = _Path(hermes_home) if hermes_home else (_Path.home() / ".hermes") - skills_root = base / "skills" - if not skills_root.is_dir(): - return False - # Canonical bundled location first (cheap), then a bounded scan for - # profiles that have it nested elsewhere. - if (skills_root / "devops" / "kanban-worker" / "SKILL.md").is_file(): - return True - try: - for skill_md in skills_root.rglob("kanban-worker/SKILL.md"): - if skill_md.is_file(): - return True - except OSError: - pass - return False - - def _worker_terminal_timeout_env( max_runtime_seconds: Optional[int], current_timeout: Optional[str], @@ -7440,32 +7401,14 @@ def _default_spawn( # profile-local worker sessions still register configured hooks. "--accept-hooks", ] - # Auto-load the kanban-worker skill so every dispatched worker - # has the pattern library (good summary/metadata shapes, retry - # diagnostics, block-reason examples) in its context, even if - # the profile hasn't wired it into skills config. The MANDATORY - # lifecycle is already in the system prompt via KANBAN_GUIDANCE; - # this skill is the deeper reference. Users can point a profile - # at a different/additional skill via config if they want — - # --skills is additive to the profile's default skill set. - # - # Only add the flag when the skill actually resolves for the home - # the worker runs under: the bundled skill is absent from many - # profile-scoped skills dirs, and preloading a missing skill is - # fatal at CLI startup. Omitting it is safe — the lifecycle - # contract still ships via KANBAN_GUIDANCE. - if _kanban_worker_skill_available(env.get("HERMES_HOME")): - cmd.extend(["--skills", "kanban-worker"]) # Per-task force-loaded skills. Each name goes in its own # `--skills X` pair rather than a single comma-joined arg: the CLI # accepts both forms (action='append' + comma-split), but # per-name pairs are easier to read in `ps` output and avoid any # quoting ambiguity if a skill name ever contains unusual chars. - # Dedupe against the built-in so we don't double-load kanban-worker - # if a task author asks for it explicitly. if task.skills: for sk in task.skills: - if sk and sk != "kanban-worker": + if sk: cmd.extend(["--skills", sk]) if task.model_override: cmd.extend(["-m", task.model_override]) @@ -8322,7 +8265,7 @@ def latest_run(conn: sqlite3.Connection, task_id: str) -> Optional[Run]: def latest_summary(conn: sqlite3.Connection, task_id: str) -> Optional[str]: """Return the latest non-null ``task_runs.summary`` for ``task_id``. - The kanban-worker skill writes its handoff to ``task_runs.summary`` + The worker writes its handoff to ``task_runs.summary`` via ``complete_task(summary=...)``; ``tasks.result`` is left empty unless the caller passes ``result=`` explicitly. Dashboards and CLI "show" views need this value to surface what a worker actually did diff --git a/hermes_cli/kanban_swarm.py b/hermes_cli/kanban_swarm.py index fe47a4c7713..4903d91275c 100644 --- a/hermes_cli/kanban_swarm.py +++ b/hermes_cli/kanban_swarm.py @@ -124,7 +124,6 @@ def create_swarm( idempotency_key=idempotency_key, workspace_kind=workspace_kind, workspace_path=workspace_path, - skills=["kanban-orchestrator"], ) # If idempotency returned an existing non-archived root, do not duplicate the diff --git a/optional-skills/creative/kanban-video-orchestrator/SKILL.md b/optional-skills/creative/kanban-video-orchestrator/SKILL.md index c5ac2a8c96e..6ce9dd29322 100644 --- a/optional-skills/creative/kanban-video-orchestrator/SKILL.md +++ b/optional-skills/creative/kanban-video-orchestrator/SKILL.md @@ -8,7 +8,7 @@ platforms: [linux, macos, windows] metadata: hermes: tags: [video, kanban, multi-agent, orchestration, production-pipeline] - related_skills: [kanban-orchestrator, kanban-worker, ascii-video, manim-video, p5js, comfyui, touchdesigner-mcp, blender-mcp, pixel-art, ascii-art, songwriting-and-ai-music, heartmula, songsee, spotify, youtube-content, claude-design, excalidraw, architecture-diagram, concept-diagrams, baoyu-comic, baoyu-infographic, humanizer, gif-search, meme-generation] + related_skills: [ascii-video, manim-video, p5js, comfyui, touchdesigner-mcp, blender-mcp, pixel-art, ascii-art, songwriting-and-ai-music, heartmula, songsee, spotify, youtube-content, claude-design, excalidraw, architecture-diagram, concept-diagrams, baoyu-comic, baoyu-infographic, humanizer, gif-search, meme-generation] credits: | The single-project workspace layout, profile-config patching pattern, SOUL.md-per-profile model, TEAM.md task-graph convention, and @@ -174,8 +174,9 @@ task graphs. See **[references/examples.md](references/examples.md)**. 6. **The director never executes.** Even with the full `kanban + terminal + file` toolset, the director's `SOUL.md` rules forbid it from executing work itself. It decomposes and routes only — every concrete task becomes - a `hermes kanban create` call to a specialist profile. The - `kanban-orchestrator` skill spells this out further. + a `hermes kanban create` call to a specialist profile. The kanban + orchestration guidance auto-injected into every kanban worker's system + prompt spells this out further. 7. **Don't over-decompose.** A 30-second product video does NOT need 20 tasks. Aim for the smallest task graph that still parallelizes well and exposes the diff --git a/optional-skills/creative/kanban-video-orchestrator/assets/setup.sh.tmpl b/optional-skills/creative/kanban-video-orchestrator/assets/setup.sh.tmpl index 3f7629d6293..c6a95848c6d 100644 --- a/optional-skills/creative/kanban-video-orchestrator/assets/setup.sh.tmpl +++ b/optional-skills/creative/kanban-video-orchestrator/assets/setup.sh.tmpl @@ -64,7 +64,7 @@ echo "═══ Configuring profiles ═══" configure_profile() { local profile="$1" local toolsets_json="$2" # JSON array string, e.g. '["kanban","terminal","file"]' - local skills_json="$3" # JSON array string, e.g. '["kanban-worker","ascii-video"]' + local skills_json="$3" # JSON array string, e.g. '["ascii-video"]' python3 - "$profile" "$toolsets_json" "$skills_json" "$WORKSPACE" <<'PY' """Patch a Hermes profile config.yaml using PyYAML so we don't depend on the exact default-config string format. Validates the patch took effect and exits diff --git a/optional-skills/creative/kanban-video-orchestrator/references/examples.md b/optional-skills/creative/kanban-video-orchestrator/references/examples.md index 8cfaac81b8c..2b6beb8b37c 100644 --- a/optional-skills/creative/kanban-video-orchestrator/references/examples.md +++ b/optional-skills/creative/kanban-video-orchestrator/references/examples.md @@ -39,8 +39,8 @@ T8 reviewer final QA (parent: T7) **Key choices:** - Local ComfyUI via `comfyui` skill is preferred over external API for cost/control — but external APIs are fine if ComfyUI isn't installed -- `editor` profile is ffmpeg-only, no Hermes skill required beyond - `kanban-worker` +- `editor` profile is ffmpeg-only, no Hermes skill required (kanban guidance + is auto-injected into every kanban worker) - Storyboarder produces `storyboard.excalidraw` alongside the markdown ## Example 2 — Product / marketing teaser diff --git a/optional-skills/creative/kanban-video-orchestrator/references/kanban-setup.md b/optional-skills/creative/kanban-video-orchestrator/references/kanban-setup.md index 53e4f269997..0a85164e07f 100644 --- a/optional-skills/creative/kanban-video-orchestrator/references/kanban-setup.md +++ b/optional-skills/creative/kanban-video-orchestrator/references/kanban-setup.md @@ -101,7 +101,7 @@ default-config schema drift: configure_profile() { local profile="$1" local toolsets_json="$2" # JSON array, e.g. '["kanban","terminal","file"]' - local skills_json="$3" # JSON array, e.g. '["kanban-worker","ascii-video"]' + local skills_json="$3" # JSON array, e.g. '["ascii-video"]' python3 - "$profile" "$toolsets_json" "$skills_json" <<'PY' import json, os, sys, yaml profile, ts_json, sk_json = sys.argv[1:4] @@ -133,16 +133,16 @@ the entire production. **Critical content for the director's SOUL.md:** - **Anti-temptation rules:** "Do not execute the work yourself. For every concrete task, create a kanban task and assign it. Decompose, route, comment, - approve — that's the whole job." (The `kanban-orchestrator` skill provides - the deeper playbook; load it.) + approve — that's the whole job." (The kanban orchestration guidance is + auto-injected into every kanban worker's system prompt — no skill to load.) - **Decomposition steps:** Read `brief.md`, `TEAM.md`, `taste/`. Use the team graph in `TEAM.md` to fan out tasks. - **The workspace_path rule** (see below). Other profiles' SOUL.md is briefer; mostly mechanical: who you are, what you read, what you produce, what skills/tools to use, where to write outputs. -Most non-director profiles should `always_load: kanban-worker` for the -deeper-than-baseline kanban guidance. +The kanban lifecycle guidance is auto-injected into every kanban worker's +system prompt, so no profile needs to load a kanban skill. ### Initial kanban task diff --git a/optional-skills/creative/kanban-video-orchestrator/references/role-archetypes.md b/optional-skills/creative/kanban-video-orchestrator/references/role-archetypes.md index 95eaeb33b66..1d13b708416 100644 --- a/optional-skills/creative/kanban-video-orchestrator/references/role-archetypes.md +++ b/optional-skills/creative/kanban-video-orchestrator/references/role-archetypes.md @@ -18,15 +18,16 @@ The vision-holder. Reads the brief and brand guide, decomposes into a task graph, comments to steer creative direction, approves the final cut. - **Toolsets:** kanban, terminal, file -- **Skills:** `kanban-orchestrator`. The kanban plugin auto-injects baseline - orchestration guidance for free; `kanban-orchestrator` is the deeper - decomposition playbook. Add `creative-ideation` if the brief is wide-open - and needs framing help. +- **Skills:** no extra skill needed — the kanban orchestration guidance + (decomposition playbook, "decompose, don't execute" discipline) is + auto-injected into every kanban worker's system prompt. Add + `creative-ideation` if the brief is wide-open and needs framing help. - **Personality:** Tied to the brand voice — see `assets/soul.md.tmpl` The director has the same toolset as everyone else, but its `SOUL.md` rules **forbid** execution. The "decompose, don't execute" discipline is enforced -by personality + the kanban-orchestrator skill, not by missing tools. +by personality + the auto-injected kanban orchestration guidance, not by +missing tools. ## Pre-production roles @@ -38,7 +39,7 @@ Writes scripts, dialogue, voiceover copy, narration. Use for any video with spoken or written words beyond a tagline. - **Toolsets:** kanban, file -- **Skills:** `kanban-worker`, `humanizer` (post-process to strip AI-tells) +- **Skills:** `humanizer` (post-process to strip AI-tells) - **Outputs:** `script.md`, `narration.md`, `dialogue/scene-NN.md` ### copywriter @@ -47,7 +48,7 @@ Like `writer` but specifically for marketing copy: taglines, CTAs, voiceover scripts for product videos. - **Toolsets:** kanban, file -- **Skills:** `kanban-worker`, `humanizer` +- **Skills:** `humanizer` - **Outputs:** `copy.md` ### concept-artist / visual-designer @@ -58,7 +59,7 @@ follow. Often produces still reference frames using image-generation APIs or local skills. - **Toolsets:** kanban, terminal, file -- **Skills:** `kanban-worker` plus any project-specific design skill — +- **Skills:** any project-specific design skill — `claude-design` (UI/web), `sketch` (quick mockup variants), `popular-web-designs` (matching known web aesthetic), `pixel-art` (retro), `ascii-art` (terminal/retro), `excalidraw` (hand-drawn frames), @@ -71,7 +72,7 @@ Maps the brief to a beat-by-beat shot list with timing. Critical for narrative film and music video. Often pairs with a diagramming tool. - **Toolsets:** kanban, file -- **Skills:** `kanban-worker` plus a diagram skill — `excalidraw` (sketch), +- **Skills:** a diagram skill — `excalidraw` (sketch), `architecture-diagram` (technical/system), `concept-diagrams` (educational/ scientific) - **Outputs:** `storyboard.md` with one row per scene/shot, optional @@ -83,7 +84,7 @@ Designs the visual language: framing, color, motion, transitions. Reviews generator output for visual consistency. Hands off per-scene `VISUAL_SPEC.md`. - **Toolsets:** kanban, terminal, file, video, vision -- **Skills:** `kanban-worker` plus the visual skill that matches the project +- **Skills:** the visual skill that matches the project (e.g., `ascii-video` for ASCII work, `manim-video` for explainers, `touchdesigner-mcp` for real-time visuals, etc.) - **Outputs:** `scenes/scene-NN/VISUAL_SPEC.md`, review comments on renderer @@ -124,8 +125,9 @@ instead of overloading one. Each loads a different creative skill. | `renderer-video` | (external image-to-video API: Runway / Kling / Luma) | Animating still images in narrative film | | `renderer-motion-graphics` | (external — Remotion CLI) | Motion graphics, kinetic typography, UI animations | -For external-API renderers, the profile holds the API client logic; only -`kanban-worker` is loaded, plus the terminal toolset and the API key. +For external-API renderers, the profile holds the API client logic; no extra +skill is loaded (kanban guidance is auto-injected into every kanban worker), +plus the terminal toolset and the API key. ### image-generator @@ -133,7 +135,7 @@ Specifically for text-to-image generation. Often produces stills that go to `renderer-video` for animation. - **Toolsets:** kanban, terminal, file -- **Skills:** `kanban-worker`, optionally `comfyui` (drives a local +- **Skills:** optionally `comfyui` (drives a local ComfyUI install for image generation) - **External APIs (alternative to local ComfyUI):** FAL, Replicate, OpenAI Images, Midjourney @@ -146,7 +148,7 @@ ComfyUI's image-to-video workflows locally. Almost always follows `image-generator` in narrative film pipelines. - **Toolsets:** kanban, terminal, file -- **Skills:** `kanban-worker`, optionally `comfyui` (for local image-to-video +- **Skills:** optionally `comfyui` (for local image-to-video workflows like AnimateDiff or WAN) - **External APIs:** Runway, Kling, Luma, Pika - **Outputs:** `scenes/scene-NN/clip.mp4` @@ -159,7 +161,7 @@ spectrograms when the editor or renderer needs a visual reference of the audio's energy. - **Toolsets:** kanban, terminal, file -- **Skills:** `kanban-worker`, `songsee` (audio visualization), plus one of: +- **Skills:** `songsee` (audio visualization), plus one of: - `songwriting-and-ai-music` — when commissioning lyrics + Suno prompts - `heartmula` — when generating music with the open-source local model - `spotify` — when sourcing existing tracks @@ -169,11 +171,11 @@ audio's energy. ### voice-talent / narrator Generates voiceover audio. Calls a TTS API directly; no Hermes skill required -beyond `kanban-worker`. The user can also supply pre-recorded VO instead of -generation. +(kanban guidance is auto-injected into every kanban worker). The user can also +supply pre-recorded VO instead of generation. - **Toolsets:** kanban, terminal, file -- **Skills:** `kanban-worker` +- **Skills:** none — kanban guidance is auto-injected into every kanban worker - **External APIs:** ElevenLabs, OpenAI TTS, etc. - **Outputs:** `audio/voiceover/line-NN.mp3`, `audio/voiceover/timeline.mp3` @@ -183,7 +185,7 @@ Sound effects and ambient design. Often optional unless the brief calls for sound design specifically. - **Toolsets:** kanban, terminal, file -- **Skills:** `kanban-worker`, `songsee` for audio-feature visualization when +- **Skills:** `songsee` for audio-feature visualization when designing to a track - **Outputs:** `audio/sfx/*.mp3` @@ -195,7 +197,7 @@ Assembles the final cut from clips. Uses ffmpeg for stitching, fades, transitions. Reviews each clip for pacing and quality before assembly. - **Toolsets:** kanban, terminal, file -- **Skills:** `kanban-worker` +- **Skills:** none — kanban guidance is auto-injected into every kanban worker - **External tools:** ffmpeg, ffprobe - **Outputs:** `output/final.mp4`, `output/final-noaudio.mp4` @@ -206,7 +208,7 @@ brand-consistent output and the editor just stitches, the colorist is overkill. Worth including for narrative film with hero shots. - **Toolsets:** kanban, terminal, file -- **Skills:** `kanban-worker` +- **Skills:** none — kanban guidance is auto-injected into every kanban worker - **Outputs:** `output/final-graded.mp4` ### audio-mixer @@ -215,7 +217,7 @@ Mixes voiceover + music + SFX into a final audio track. Sets levels, ducks music under VO, normalizes loudness (LUFS). - **Toolsets:** kanban, terminal, file -- **Skills:** `kanban-worker` +- **Skills:** none — kanban guidance is auto-injected into every kanban worker - **External tools:** ffmpeg with `loudnorm` filter, optional `sox` - **Outputs:** `audio/final-mix.mp3` @@ -225,7 +227,7 @@ Burns subtitles into the video, generates SRT, handles accessibility. Can also generate captions from audio via Whisper. - **Toolsets:** kanban, terminal, file -- **Skills:** `kanban-worker` +- **Skills:** none — kanban guidance is auto-injected into every kanban worker - **External tools:** Whisper (CLI or API), ffmpeg subtitle filters - **Outputs:** `output/captions.srt`, `output/final-captioned.mp4` @@ -235,7 +237,7 @@ Final encode + format variants. Produces deliverables for each platform target (square for IG, vertical for TikTok, full HD for YouTube, etc.). - **Toolsets:** kanban, terminal, file -- **Skills:** `kanban-worker` +- **Skills:** none — kanban guidance is auto-injected into every kanban worker - **Outputs:** `output/final-1080.mp4`, `output/final-9x16.mp4`, etc. ## QA roles @@ -248,7 +250,7 @@ quality). Distinct from the cinematographer (who reviews visuals during production) and the editor (who reviews for assembly). - **Toolsets:** kanban, terminal, file, video, vision -- **Skills:** `kanban-worker` +- **Skills:** none — kanban guidance is auto-injected into every kanban worker - **Review tools:** `video_analyze` (native clip review via multimodal LLM), `vision_analyze` (frame/thumbnail review), ffprobe - **Outputs:** `review-notes.md`, comments on tasks @@ -260,7 +262,7 @@ when the brand guidelines are detailed and a generic reviewer might miss violations. - **Toolsets:** kanban, file -- **Skills:** `kanban-worker` +- **Skills:** none — kanban guidance is auto-injected into every kanban worker - **Outputs:** comments + `brand-review.md` ## Composing teams — heuristics diff --git a/optional-skills/creative/kanban-video-orchestrator/references/tool-matrix.md b/optional-skills/creative/kanban-video-orchestrator/references/tool-matrix.md index b5e59c31478..11e2c3d9d6f 100644 --- a/optional-skills/creative/kanban-video-orchestrator/references/tool-matrix.md +++ b/optional-skills/creative/kanban-video-orchestrator/references/tool-matrix.md @@ -50,18 +50,12 @@ called from the terminal toolset; they don't appear in `always_load`. | `gif-search` | Find existing GIFs | Editor / concept artist sourcing references | | `gifs` | GIF tooling | Masterer producing GIF deliverables | -### Kanban infrastructure (`hermes-agent/skills/devops/`) - -| Skill | What it does | When to load | -|-------|--------------|--------------| -| `kanban-orchestrator` | Decomposition playbook + anti-temptation rules for orchestrator profiles | Director only | -| `kanban-worker` | Pitfalls, examples, edge cases for kanban workers (deeper than auto-injected guidance) | Any profile — load when handling tricky multi-step workflows | +### Kanban infrastructure The kanban plugin auto-injects baseline orchestration guidance into every worker's system prompt — the `kanban_create` fan-out pattern, claim/handoff -lifecycle, and the "decompose, don't execute" rule for orchestrators. -`kanban-orchestrator` and `kanban-worker` are deeper playbooks loaded when a -profile needs them. +lifecycle, and the "decompose, don't execute" rule for orchestrators. There is +no kanban skill to load; the guidance is always present for kanban workers. ## External tools (called from terminal toolset) @@ -102,8 +96,7 @@ toolsets: - terminal - file skills: - always_load: - - kanban-orchestrator + always_load: [] ``` The director's terminal access is conventional but the SOUL.md rules forbid @@ -117,7 +110,6 @@ toolsets: - file skills: always_load: - - kanban-worker - humanizer # post-process scripts to strip AI-tells ``` @@ -132,7 +124,6 @@ toolsets: - file skills: always_load: - - kanban-worker # plus one or more (style-dependent): # - claude-design (UI / web product video) # - sketch (quick mockup variants) @@ -151,7 +142,6 @@ toolsets: - file skills: always_load: - - kanban-worker # one of: # - excalidraw (sketch storyboards) # - architecture-diagram (technical/system content) @@ -169,7 +159,6 @@ toolsets: - vision # vision_analyze — review stills / exported frames skills: always_load: - - kanban-worker # the visual skill that matches the project, e.g.: # - ascii-video (ASCII projects) # - manim-video (math/explainer) @@ -188,7 +177,6 @@ toolsets: - file skills: always_load: - - kanban-worker # ONE skill per renderer variant (or empty for external-API renderers): # - ascii-video (renderer-ascii) # - manim-video (renderer-manim) @@ -202,9 +190,9 @@ skills: ``` For external-API renderers (image-to-video-generator using Runway, voice-talent -using ElevenLabs, renderer-motion-graphics using Remotion), `always_load` only -contains `kanban-worker` — the role's work is API-driven and the API key + -terminal commands suffice. +using ElevenLabs, renderer-motion-graphics using Remotion), `always_load` is +empty — the role's work is API-driven and the API key + +terminal commands suffice (kanban guidance is auto-injected regardless). For multi-skill renderer setups (rare — usually one variant per skill is cleaner) use `--skill ` on individual `kanban_create` calls to override @@ -219,7 +207,6 @@ toolsets: - file skills: always_load: - - kanban-worker # for image-generator that drives ComfyUI locally: # - comfyui env_required: @@ -242,7 +229,6 @@ toolsets: - file skills: always_load: - - kanban-worker - songsee # spectrograms / audio analysis # plus (depending on what the project needs): # - songwriting-and-ai-music (commissioning Suno tracks) @@ -260,11 +246,11 @@ toolsets: - video # video_analyze — editor reviews assembled cuts natively - vision # vision_analyze — spot-check frames skills: - always_load: - - kanban-worker + always_load: [] ``` -These are mostly ffmpeg-driven; no special skill needed beyond `kanban-worker`. +These are mostly ffmpeg-driven; no special skill needed (kanban guidance is +auto-injected into every kanban worker). For captioner add Whisper invocation patterns to the SOUL.md. ### reviewer / brand-cop @@ -277,8 +263,7 @@ toolsets: - video # video_analyze — review full clips natively - vision # vision_analyze — review stills / exported frames skills: - always_load: - - kanban-worker + always_load: [] ``` ## API key requirements diff --git a/optional-skills/creative/kanban-video-orchestrator/scripts/bootstrap_pipeline.py b/optional-skills/creative/kanban-video-orchestrator/scripts/bootstrap_pipeline.py index 7203427b9ab..aa4e067ae82 100755 --- a/optional-skills/creative/kanban-video-orchestrator/scripts/bootstrap_pipeline.py +++ b/optional-skills/creative/kanban-video-orchestrator/scripts/bootstrap_pipeline.py @@ -423,8 +423,6 @@ def render_soul_md(team_member: dict, plan: dict) -> str: "- **Decompose, route, comment, approve — that's the whole job.**\n" "- **Read TEAM.md** for the canonical task graph. Do not invent " "new roles unless the brief truly demands it.\n" - "- **Load the `kanban-orchestrator` skill** for the deeper " - "decomposition playbook beyond the auto-injected baseline.\n" ) common_commands = ( diff --git a/skills/devops/kanban-orchestrator/SKILL.md b/skills/devops/kanban-orchestrator/SKILL.md deleted file mode 100644 index fb5aa58a865..00000000000 --- a/skills/devops/kanban-orchestrator/SKILL.md +++ /dev/null @@ -1,214 +0,0 @@ ---- -name: kanban-orchestrator -description: Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role. -version: 3.0.0 -platforms: [linux, macos, windows] -environments: [kanban] -metadata: - hermes: - tags: [kanban, multi-agent, orchestration, routing] - related_skills: [kanban-worker] ---- - -# Kanban Orchestrator — Decomposition Playbook - -> The **core worker lifecycle** (including the `kanban_create` fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the `KANBAN_GUIDANCE` system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing. - -## Profiles are user-configured — not a fixed roster - -Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (`docker-worker`, `cron-worker`); some run a curated specialist team they've named themselves. There is **no default specialist roster** — the orchestrator skill does not know what profiles exist on this machine. - -Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names — it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to `researcher` on a setup that only has `docker-worker` just sits in `ready` forever. - -**Step 0: discover available profiles before planning.** - -Use one of these: - -- `hermes profile list` — prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user. -- `kanban_list(assignee="")` — sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering. -- **Just ask the user.** "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist. - -Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call. - -## When to use the board (vs. just doing the work) - -Create Kanban tasks when any of these are true: - -1. **Multiple specialists are needed.** Research + analysis + writing is three profiles. -2. **The work should survive a crash or restart.** Long-running, recurring, or important. -3. **The user might want to interject.** Human-in-the-loop at any step. -4. **Multiple subtasks can run in parallel.** Fan-out for speed. -5. **Review / iteration is expected.** A reviewer profile loops on drafter output. -6. **The audit trail matters.** Board rows persist in SQLite forever. - -If *none* of those apply — it's a small one-shot reasoning task — use `delegate_task` instead or answer the user directly. - -## The anti-temptation rules - -Your job description says "route, don't execute." The rules that enforce that: - -- **Do not execute the work yourself.** Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" — stop and create a task for the right specialist. -- **For any concrete task, create a Kanban task and assign it.** Every single time. -- **Split multi-lane requests before creating cards.** A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card. -- **Run independent lanes in parallel.** If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies. -- **Never create dependent work as independent ready cards.** If a card must wait for another card, pass `parents=[...]` in the original `kanban_create` call. Do not create it first and link it later, and do not rely on prose like "wait for T1" inside the body. -- **If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use.** Do not invent profile names; the dispatcher will silently drop unknown assignees. -- **Decompose, route, and summarize — that's the whole job.** - -## Decomposition playbook - -### Step 1 — Understand the goal - -Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet. - -### Step 2 — Sketch the task graph - -Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card: - -1. Extract the lanes from the request. -2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create. -3. Decide whether each lane is independent or gated by another lane. -4. Create independent lanes as parallel cards with no parent links. -5. Create synthesis/review/integration cards with parent links to the lanes they depend on. A child created with unfinished parents starts in `todo`; the dispatcher promotes it to `ready` only after every parent is done. - -Examples of prompts that should fan out (using placeholder profile names — substitute whatever exists on the user's setup): - -- "Build an app" → one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile. -- "Fix blockers and check model variants" → one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both. -- "Research docs and implement" → a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings. -- "Analyze this screenshot and find the related code" → one card to a vision-capable profile for the visual analysis while another searches the codebase. - -Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists. - -Show the graph to the user before creating cards. Let them correct it — including which actual profile name should own each lane. - -### Step 3 — Create tasks and link - -Use the profile names from Step 0. The example below uses placeholders ``, ``, `` — replace them with what the user actually has. - -```python -t1 = kanban_create( - title="research: Postgres cost vs current", - assignee="", # whichever profile handles research on this setup - body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.", - tenant=os.environ.get("HERMES_TENANT"), -)["task_id"] - -t2 = kanban_create( - title="research: Postgres performance vs current", - assignee="", # same profile, run in parallel - body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.", -)["task_id"] - -t3 = kanban_create( - title="synthesize migration recommendation", - assignee="", # whichever profile does synthesis/analysis - body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.", - parents=[t1, t2], -)["task_id"] - -t4 = kanban_create( - title="draft decision memo", - assignee="", # whichever profile drafts user-facing prose - body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.", - parents=[t3], -)["task_id"] -``` - -`parents=[...]` gates promotion — children stay in `todo` until every parent reaches `done`, then auto-promote to `ready`. No manual coordination needed; the dispatcher and dependency engine handle it. - -If the task graph has dependencies, create the parent cards first, capture their returned ids, and include those ids in the child card's `parents` list during the child `kanban_create` call. Avoid creating all cards in parallel and linking them afterward; that creates a window where the dispatcher can claim a child before its inputs exist. - -### Step 4 — Complete your own task - -If you were spawned as a task yourself (e.g. a planner profile was assigned `T0: "investigate Postgres migration"`), mark it done with a summary of what you created: - -```python -kanban_complete( - summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation", - metadata={ - "task_graph": { - "T1": {"assignee": "", "parents": []}, - "T2": {"assignee": "", "parents": []}, - "T3": {"assignee": "", "parents": ["T1", "T2"]}, - "T4": {"assignee": "", "parents": ["T3"]}, - }, - }, -) -``` - -### Step 5 — Report back to the user - -Tell them what you created in plain prose, naming the actual profiles you used: - -> I've queued 4 tasks: -> - **T1** (``): cost comparison -> - **T2** (``): performance comparison, in parallel with T1 -> - **T3** (``): synthesizes T1 + T2 into a recommendation -> - **T4** (``): turns T3 into a CTO memo -> -> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or `hermes kanban tail ` to follow along. - -## Common patterns - -**Fan-out + fan-in (research → synthesize):** N research-style cards with no parents, one synthesis card with all of them as parents. - -**Parallel implementation + validation:** one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence. - -**Pipeline with gates:** `planner → implementer → reviewer`. Each stage's `parents=[previous_task]`. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns. - -**Same-profile queue:** N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes — that profile processes them in priority order, accumulating experience in its own memory. - -**Human-in-the-loop:** Any task can `kanban_block()` to wait for input. Dispatcher respawns after `/unblock`. The comment thread carries the full context. - -## Pitfalls - -**Inventing profile names that don't exist.** The dispatcher silently fails to spawn unknown assignees — the card just sits in `ready` forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure. - -**Bundling independent lanes into one card.** If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both. - -**Over-linking because of wording.** "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result. - -**Forgetting dependency links.** If the task graph says `research -> implement -> review`, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist. - -**Reassignment vs. new task.** If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task — don't re-run the same task with a stern look. The new task is assigned to the original implementer profile. - -**Argument order for links.** `kanban_link(parent_id=..., child_id=...)` — parent first. Mixing them up demotes the wrong task to `todo`. - -**Don't pre-create the whole graph if the shape depends on intermediate findings.** If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators. - -**Tenant inheritance.** If `HERMES_TENANT` is set in your env, pass `tenant=os.environ.get("HERMES_TENANT")` on every `kanban_create` call so child tasks stay in the same namespace. - -## Goal-mode cards (persistent workers) - -By default a dispatched worker gets **one shot** at its card: it does its work, calls `kanban_complete`/`kanban_block`, and exits. For open-ended cards where one turn rarely finishes the job, pass `goal_mode=True` to wrap that worker in a Ralph-style goal loop — the same engine behind the `/goal` slash command: - -```python -kanban_create( - title="Translate the full docs site to French", - body="Acceptance: every page translated, no English left, links intact.", - assignee="", - goal_mode=True, # judge re-checks the card after each turn - goal_max_turns=15, # optional budget (default 20) -)["task_id"] -``` - -How it behaves: -- After each worker turn, an auxiliary judge evaluates the worker's response against the card's **title + body** (treated as the acceptance criteria). -- Not done + budget remains → the worker keeps going **in the same session** (full context retained — not a fresh respawn). -- Worker calls `kanban_complete`/`kanban_block` itself → loop stops, normal lifecycle. -- Budget exhausted without completion → the card is **blocked** for human review (sticky), never a silent exit. - -When to use it: long, multi-step, or "keep going until X is true" cards. When NOT to: cheap one-shot cards (translation of a single string, a quick lookup) — the judge overhead isn't worth it, and the dispatcher's existing retry/circuit-breaker already handles transient worker failures. - -Write the body as **explicit acceptance criteria** — the judge is only as good as the goal text. "Translate the README" is weaker than "Translate every section of the README to French; no English sentences remain." - -## Recovering stuck workers - -When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a ⚠ badge and opens a **Recovery** section in the drawer. Three primary actions: - -1. **Reclaim** (or `hermes kanban reclaim `) — abort the running worker immediately and reset the task to `ready`. The existing claim TTL is ~15 min; this is the fast path out. -2. **Reassign** (or `hermes kanban reassign --reclaim`) — switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker. -3. **Change profile model** — the dashboard prints a copy-paste hint for `hermes -p model` since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model. - -Hallucination warnings appear on tasks where a worker's `kanban_complete(created_cards=[...])` claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references `t_` ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions — the trail stays for debugging. diff --git a/skills/devops/kanban-worker/SKILL.md b/skills/devops/kanban-worker/SKILL.md deleted file mode 100644 index c9e91504e89..00000000000 --- a/skills/devops/kanban-worker/SKILL.md +++ /dev/null @@ -1,214 +0,0 @@ ---- -name: kanban-worker -description: Pitfalls, examples, and edge cases for Hermes Kanban workers. The lifecycle itself is auto-injected into every worker's system prompt as KANBAN_GUIDANCE (from agent/prompt_builder.py); this skill is what you load when you want deeper detail on specific scenarios. -version: 2.0.0 -platforms: [linux, macos, windows] -environments: [kanban] -metadata: - hermes: - tags: [kanban, multi-agent, collaboration, workflow, pitfalls] - related_skills: [kanban-orchestrator] ---- - -# Kanban Worker — Pitfalls and Examples - -> You're seeing this skill because the Hermes Kanban dispatcher spawned you as a worker with `--skills kanban-worker` — it's loaded automatically for every dispatched worker. The **lifecycle** (6 steps: orient → work → heartbeat → block/complete) also lives in the `KANBAN_GUIDANCE` block that's auto-injected into your system prompt. This skill is the deeper detail: good handoff shapes, retry diagnostics, edge cases. - -## Workspace handling - -Your workspace kind determines how you should behave inside `$HERMES_KANBAN_WORKSPACE`: - -| Kind | What it is | How to work | -|---|---|---| -| `scratch` | Fresh tmp dir, yours alone | Read/write freely; it gets GC'd when the task is archived. | -| `dir:` | Shared persistent directory | Other runs will read what you write. Treat it like long-lived state. Path is guaranteed absolute (the kernel rejects relative paths). | -| `worktree` | Git worktree at the resolved path | If `.git` doesn't exist, run `git worktree add ${HERMES_KANBAN_BRANCH:-wt/$HERMES_KANBAN_TASK}` from the main repo first, then cd and work normally. Commit work here. | - -## Tenant isolation - -If `$HERMES_TENANT` is set, the task belongs to a tenant namespace. When reading or writing persistent memory, prefix memory entries with the tenant so context doesn't leak across tenants: - -- Good: `business-a: Acme is our biggest customer` -- Bad (leaks): `Acme is our biggest customer` - -## Good summary + metadata shapes - -The `kanban_complete(summary=..., metadata=...)` handoff is how downstream workers read what you did. Patterns that work: - -**Coding task:** -```python -kanban_complete( - summary="shipped rate limiter — token bucket, keys on user_id with IP fallback, 14 tests pass", - metadata={ - "changed_files": ["rate_limiter.py", "tests/test_rate_limiter.py"], - "tests_run": 14, - "tests_passed": 14, - "decisions": ["user_id primary, IP fallback for unauthenticated requests"], - }, -) -``` - -**Coding task that needs human review (review-required):** - -For most code-changing tasks, the work isn't truly *done* until a human reviewer has eyes on it. Block instead of complete, with `reason` prefixed `review-required: ` so the dashboard surfaces the row as needing review. Drop the structured metadata (changed files, test counts, diff/PR url) into a comment first, since `kanban_block` only carries the human-readable reason — comments are the durable annotation channel. Reviewer either approves and runs `hermes kanban unblock ` (which re-spawns you with the comment thread for any follow-ups) or asks for changes via another comment. - -```python -import json - -kanban_comment( - body="review-required handoff:\n" + json.dumps({ - "changed_files": ["rate_limiter.py", "tests/test_rate_limiter.py"], - "tests_run": 14, - "tests_passed": 14, - "diff_path": "/path/to/worktree", # or PR url if pushed - "decisions": ["user_id primary, IP fallback for unauthenticated requests"], - }, indent=2), -) -kanban_block( - reason="review-required: rate limiter shipped, 14/14 tests pass — needs eyes on the user_id/IP fallback choice before merging", -) -``` - -Use `kanban_complete` only when the task is genuinely terminal — e.g. a one-line typo fix, a docs change with no functional consequences, or a research task where the artifact IS the writeup itself. - -**Research task:** -```python -kanban_complete( - summary="3 competing libraries reviewed; vLLM wins on throughput, SGLang on latency, Tensorrt-LLM on memory efficiency", - metadata={ - "sources_read": 12, - "recommendation": "vLLM", - "benchmarks": {"vllm": 1.0, "sglang": 0.87, "trtllm": 0.72}, - }, -) -``` - -**Review task:** -```python -kanban_complete( - summary="reviewed PR #123; 2 blocking issues found (SQL injection in /search, missing CSRF on /settings)", - metadata={ - "pr_number": 123, - "findings": [ - {"severity": "critical", "file": "api/search.py", "line": 42, "issue": "raw SQL concat"}, - {"severity": "high", "file": "api/settings.py", "issue": "missing CSRF middleware"}, - ], - "approved": False, - }, -) -``` - -Shape `metadata` so downstream parsers (reviewers, aggregators, schedulers) can use it without re-reading your prose. - -## Shipping deliverables (`artifacts=[...]`) - -If your task produced files a human actually wants — a chart, a PDF, a spreadsheet, a generated image, an archive — pass their **absolute paths** to `kanban_complete(artifacts=[...])`. The gateway notifier uploads each one as a native attachment to whoever subscribed to the task, so the deliverable lands in their chat alongside the completion message instead of being a path they have to go fetch. - -```python -kanban_complete( - summary="Q3 revenue analysis: 14% QoQ growth, EMEA the laggard. Chart + full PDF attached.", - artifacts=["/tmp/q3-revenue.png", "/tmp/q3-report.pdf"], - metadata={"rows_analyzed": 48000, "growth_qoq": 0.14}, -) -``` - -Images and video embed inline; PDFs, docx, csv/xlsx/json/yaml, pptx, zip/tar/gz, audio, and html upload as files. Rules: - -- **Absolute paths only**, and the file must still exist when you complete — don't point at a scratch file you already deleted. -- **Only real deliverables.** Skip intermediate logs, scratch files, and inputs the human already has. -- `artifacts` is the **top-level** parameter the notifier reads. Do not bury deliverable paths in `metadata` (e.g. `metadata.codex_lane.artifacts`) and expect them to upload — the notifier only scans the top-level `artifacts` list, with a best-effort fallback over your `summary`/`result` text. Metadata paths are for downstream-worker bookkeeping, not delivery. -- A bare string is auto-promoted to a one-element list, and it merges with any pre-existing `metadata.artifacts` without dupes. - -Same primitive works outside kanban: any agent surface delivers a file just by writing its absolute path into the response, and Slack/Discord/Telegram/etc. upload it natively — the `artifacts` param is the structured kanban entry point. - -## Claiming cards you actually created - -If your run produced new kanban tasks (via `kanban_create`), pass the ids in `created_cards` on `kanban_complete`. The kernel verifies each id exists and was created by your profile; any phantom id blocks the completion with an error listing what went wrong, and the rejected attempt is permanently recorded on the task's event log. **Only list ids you captured from a successful `kanban_create` return value — never invent ids from prose, never paste ids from earlier runs, never claim cards another worker created.** - -```python -# GOOD — capture return values, then claim them. -c1 = kanban_create(title="remediate SQL injection", assignee="security-worker") -c2 = kanban_create(title="fix CSRF middleware", assignee="web-worker") - -kanban_complete( - summary="Review done; spawned remediations for both findings.", - metadata={"pr_number": 123, "approved": False}, - created_cards=[c1["task_id"], c2["task_id"]], -) -``` - -```python -# BAD — claiming ids you don't have captured return values for. -kanban_complete( - summary="Created remediation cards t_a1b2c3d4, t_deadbeef", # hallucinated - created_cards=["t_a1b2c3d4", "t_deadbeef"], # → gate rejects -) -``` - -If a `kanban_create` call fails (exception, tool_error), the card was NOT created — do not include a phantom id for it. Retry the create, or omit the id and mention the failure in your summary. The prose-scan pass also catches `t_` references in your free-form summary that don't resolve; these don't block the completion but show up as advisory warnings on the task in the dashboard. - -## Block reasons that get answered fast - -Bad: `"stuck"` — the human has no context. - -Good: one sentence naming the specific decision you need. Leave longer context as a comment instead. - -```python -kanban_comment( - task_id=os.environ["HERMES_KANBAN_TASK"], - body="Full context: I have user IPs from Cloudflare headers but some users are behind NATs with thousands of peers. Keying on IP alone causes false positives.", -) -kanban_block(reason="Rate limit key choice: IP (simple, NAT-unsafe) or user_id (requires auth, skips anonymous endpoints)?") -``` - -The block message is what appears in the dashboard / gateway notifier. The comment is the deeper context a human reads when they open the task. - -## Heartbeats worth sending - -Good heartbeats name progress: `"epoch 12/50, loss 0.31"`, `"scanned 1.2M/2.4M rows"`, `"uploaded 47/120 videos"`. - -Bad heartbeats: `"still working"`, empty notes, sub-second intervals. Every few minutes max; skip entirely for tasks under ~2 minutes. - -## Retry scenarios - -If you open the task and `kanban_show` returns `runs: [...]` with one or more closed runs, you're a retry. The prior runs' `outcome` / `summary` / `error` tell you what didn't work. Don't repeat that path. Typical retry diagnostics: - -- `outcome: "timed_out"` — the previous attempt hit `max_runtime_seconds`. You may need to chunk the work or shorten it. -- `outcome: "crashed"` — OOM or segfault. Reduce memory footprint. -- `outcome: "spawn_failed"` + `error: "..."` — usually a profile config issue (missing credential, bad PATH). Ask the human via `kanban_block` instead of retrying blindly. -- `outcome: "reclaimed"` + `summary: "task archived..."` — operator archived the task out from under the previous run; you probably shouldn't be running at all, check status carefully. -- `outcome: "blocked"` — a previous attempt blocked; the unblock comment should be in the thread by now. - -## Notification routing - -You can configure the gateway to receive cross-profile Kanban task notifications by adding `notification_sources` to `~/.hermes/config.yaml`. -- `notification_sources: ['*']` accepts subscriptions from all profiles. -- `notification_sources: ['default', 'zilor-ppt']` or `"default,zilor-ppt"` restricts subscriptions to specified profiles. -- Omitting the key keeps the default behavior (profile isolation). - -## Do NOT - -- Call `delegate_task` as a substitute for `kanban_create`. `delegate_task` is for short reasoning subtasks inside YOUR run; `kanban_create` is for cross-agent handoffs that outlive one API loop. -- Call `clarify` to ask the human a question. You are running headless — there is no live user to answer. The call will time out (default ~120s) and the task will sit silently in `running` with no signal that it needs input. Use `kanban_comment` (context) + `kanban_block(reason=...)` (decision needed) instead — the task surfaces on the board as blocked, the operator sees it, unblocks with their answer in a comment, and you respawn with the thread. -- Modify files outside `$HERMES_KANBAN_WORKSPACE` unless the task body says to. -- Create follow-up tasks assigned to yourself — assign to the right specialist. -- Complete a task you didn't actually finish. Block it instead. - -## Pitfalls - -**Task state can change between dispatch and your startup.** Between when the dispatcher claimed and when your process actually booted, the task may have been blocked, reassigned, or archived. Always `kanban_show` first. If it reports `blocked` or `archived`, stop — you shouldn't be running. - -**Workspace may have stale artifacts.** Especially `dir:` and `worktree` workspaces can have files from previous runs. Read the comment thread — it usually explains why you're running again and what state the workspace is in. - -**Don't rely on the CLI when the guidance is available.** The `kanban_*` tools work across all terminal backends (Docker, Modal, SSH). `hermes kanban ` from your terminal tool will fail in containerized backends because the CLI isn't installed there. When in doubt, use the tool. - -## CLI fallback (for scripting) - -Every tool has a CLI equivalent for human operators and scripts: -- `kanban_show` ↔ `hermes kanban show --json` -- `kanban_complete` ↔ `hermes kanban complete --summary "..." --metadata '{...}'` -- `kanban_block` ↔ `hermes kanban block "reason"` -- `kanban_create` ↔ `hermes kanban create "title" --assignee [--parent ]` -- etc. - -Use the tools from inside an agent; the CLI exists for the human at the terminal. diff --git a/tests/hermes_cli/test_kanban_core_functionality.py b/tests/hermes_cli/test_kanban_core_functionality.py index 2762e220e79..fc56f6c0f37 100644 --- a/tests/hermes_cli/test_kanban_core_functionality.py +++ b/tests/hermes_cli/test_kanban_core_functionality.py @@ -2703,20 +2703,17 @@ def test_build_worker_context_caps_huge_summary(kanban_home): conn.close() -def test_default_spawn_auto_loads_kanban_worker_skill(kanban_home, monkeypatch): - """The dispatcher's _default_spawn must include --skills kanban-worker - in its argv so every worker loads the skill automatically, even if - the profile hasn't wired it into its default skills config. +def test_default_spawn_does_not_auto_load_any_skill(kanban_home, monkeypatch): + """The dispatcher no longer auto-loads a bundled kanban skill. + + The kanban lifecycle (formerly the kanban-worker/kanban-orchestrator + skills) is now injected into every worker's system prompt via + KANBAN_GUIDANCE, so _default_spawn must NOT append a `--skills` flag + when the task carries no per-task skills. We intercept Popen to capture the argv without actually spawning a hermes subprocess (which would hang trying to call an LLM). """ - # Pretend the bundled kanban-worker skill resolves for this isolated - # HERMES_HOME — the fixture creates an empty tmpdir without the - # devops/kanban-worker tree, and _default_spawn gates the --skills - # flag on actual resolvability. - monkeypatch.setattr(kb, "_kanban_worker_skill_available", lambda _h: True) - captured = {} class FakeProc: @@ -2742,10 +2739,8 @@ def test_default_spawn_auto_loads_kanban_worker_skill(kanban_home, monkeypatch): conn.close() cmd = captured["cmd"] - assert "--skills" in cmd, f"spawn argv missing --skills: {cmd}" - idx = cmd.index("--skills") - assert cmd[idx + 1] == "kanban-worker", ( - f"expected 'kanban-worker', got {cmd[idx + 1]!r}" + assert "--skills" not in cmd, ( + f"spawn argv should not auto-load any skill: {cmd}" ) assert "--accept-hooks" in cmd, f"spawn argv missing --accept-hooks: {cmd}" assert cmd.index("--accept-hooks") < cmd.index("chat"), ( @@ -2985,8 +2980,7 @@ def test_create_task_skills_lists_all_toolset_typos(kanban_home): def test_default_spawn_appends_per_task_skills(kanban_home, monkeypatch): """Dispatcher argv must carry one `--skills X` pair per task skill, - in addition to the built-in kanban-worker.""" - monkeypatch.setattr(kb, "_kanban_worker_skill_available", lambda _h: True) + in declared order. No skill is auto-loaded anymore.""" captured = {} class FakeProc: @@ -3019,10 +3013,8 @@ def test_default_spawn_appends_per_task_skills(kanban_home, monkeypatch): for i, tok in enumerate(cmd): if tok == "--skills" and i + 1 < len(cmd): skill_names.append(cmd[i + 1]) - # kanban-worker first (built-in), then per-task extras in order. - assert skill_names[0] == "kanban-worker", skill_names - assert "translation" in skill_names - assert "github-code-review" in skill_names + # Only the per-task skills, in declared order — nothing auto-loaded. + assert skill_names == ["translation", "github-code-review"], skill_names # --skills must appear BEFORE the `chat` subcommand so argparse # attaches them to the top-level parser, not the subcommand. chat_idx = cmd.index("chat") @@ -3034,9 +3026,9 @@ def test_default_spawn_appends_per_task_skills(kanban_home, monkeypatch): ) -def test_default_spawn_dedupes_kanban_worker_from_task_skills(kanban_home, monkeypatch): - """If a task explicitly lists 'kanban-worker', we don't double-pass it.""" - monkeypatch.setattr(kb, "_kanban_worker_skill_available", lambda _h: True) +def test_default_spawn_passes_task_skills_verbatim(kanban_home, monkeypatch): + """Per-task skills are passed through verbatim — there is no built-in + kanban skill to dedupe against anymore.""" captured = {} class FakeProc: @@ -3052,7 +3044,7 @@ def test_default_spawn_dedupes_kanban_worker_from_task_skills(kanban_home, monke try: tid = kb.create_task( conn, title="dup", assignee="x", - skills=["kanban-worker", "translation"], + skills=["translation", "github-code-review"], ) task = kb.get_task(conn, tid) workspace = kb.resolve_workspace(task) @@ -3061,12 +3053,14 @@ def test_default_spawn_dedupes_kanban_worker_from_task_skills(kanban_home, monke conn.close() cmd = captured["cmd"] - worker_pairs = [ - i for i, tok in enumerate(cmd) - if tok == "--skills" and i + 1 < len(cmd) and cmd[i + 1] == "kanban-worker" + skill_names = [ + cmd[i + 1] + for i, tok in enumerate(cmd) + if tok == "--skills" and i + 1 < len(cmd) ] - assert len(worker_pairs) == 1, ( - f"kanban-worker appeared {len(worker_pairs)} times in argv: {cmd}" + # Exactly the task's skills, once each, in order — no auto-loaded extras. + assert skill_names == ["translation", "github-code-review"], ( + f"unexpected --skills in argv: {cmd}" ) diff --git a/tests/hermes_cli/test_kanban_goal_mode.py b/tests/hermes_cli/test_kanban_goal_mode.py index 17317437483..e8984a1aa62 100644 --- a/tests/hermes_cli/test_kanban_goal_mode.py +++ b/tests/hermes_cli/test_kanban_goal_mode.py @@ -132,8 +132,6 @@ def test_spawn_sets_goal_env_only_when_enabled(kanban_home, monkeypatch): return _FakeProc() monkeypatch.setattr("subprocess.Popen", _fake_popen) - # Avoid the kanban-worker skill probe touching the real skills dir. - monkeypatch.setattr(kb, "_kanban_worker_skill_available", lambda home: False) with kb.connect() as conn: tid = kb.create_task( @@ -162,7 +160,6 @@ def test_spawn_no_goal_env_for_plain_task(kanban_home, monkeypatch): return _FakeProc() monkeypatch.setattr("subprocess.Popen", _fake_popen) - monkeypatch.setattr(kb, "_kanban_worker_skill_available", lambda home: False) with kb.connect() as conn: tid = kb.create_task(conn, title="plain", assignee="default") diff --git a/tests/tools/test_kanban_tools.py b/tests/tools/test_kanban_tools.py index e9b41f812bb..ccd51a59cd3 100644 --- a/tests/tools/test_kanban_tools.py +++ b/tests/tools/test_kanban_tools.py @@ -1224,8 +1224,16 @@ def test_kanban_guidance_in_worker_prompt(monkeypatch, tmp_path): def test_kanban_guidance_prompt_size_bounded(monkeypatch, tmp_path): - """Sanity: the guidance block is under 4 KB so it doesn't blow - up the cached prompt.""" + """Sanity: the guidance block stays lean so it doesn't blow up the + cached prompt. + + The ceiling guards against unbounded growth, not against any growth. + The block absorbed the load-bearing worker/orchestrator reference + details (workspace kinds, deliverable artifacts, created-card claims, + profile discovery) when the standalone kanban-worker / kanban-orchestrator + skills were removed and folded into this always-injected guidance, so the + ceiling is sized to fit that content with a little headroom. + """ monkeypatch.setenv("HERMES_KANBAN_TASK", "t_fake") home = tmp_path / ".hermes" home.mkdir() @@ -1234,7 +1242,7 @@ def test_kanban_guidance_prompt_size_bounded(monkeypatch, tmp_path): monkeypatch.setattr(_P, "home", lambda: tmp_path) from agent.prompt_builder import KANBAN_GUIDANCE - assert 1_500 < len(KANBAN_GUIDANCE) < 4_096, ( + assert 1_500 < len(KANBAN_GUIDANCE) < 5_500, ( f"KANBAN_GUIDANCE is {len(KANBAN_GUIDANCE)} chars — too short (missing?) or too long" ) diff --git a/tools/kanban_tools.py b/tools/kanban_tools.py index 7752b53a4bd..d997305b406 100644 --- a/tools/kanban_tools.py +++ b/tools/kanban_tools.py @@ -1382,8 +1382,8 @@ KANBAN_CREATE_SCHEMA = { "items": {"type": "string"}, "description": ( "Skill names to force-load into the dispatched " - "worker (in addition to the built-in kanban-worker " - "skill). Use this to pin a task to a specialist " + "worker. The kanban lifecycle is already injected " + "automatically; use this to pin a task to a specialist " "context — e.g. ['translation'] for a translation " "task, ['github-code-review'] for a reviewer task. " "The names must match skills installed on the " diff --git a/website/docs/reference/skills-catalog.md b/website/docs/reference/skills-catalog.md index 5ccb1f5f5ca..da07eaa0929 100644 --- a/website/docs/reference/skills-catalog.md +++ b/website/docs/reference/skills-catalog.md @@ -62,8 +62,7 @@ If a skill is missing from this list but present in the repo, the catalog is reg | Skill | Description | Path | |-------|-------------|------| -| [`kanban-orchestrator`](/docs/user-guide/skills/bundled/devops/devops-kanban-orchestrator) | Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill... | `devops/kanban-orchestrator` | -| [`kanban-worker`](/docs/user-guide/skills/bundled/devops/devops-kanban-worker) | Pitfalls, examples, and edge cases for Hermes Kanban workers. The lifecycle itself is auto-injected into every worker's system prompt as KANBAN_GUIDANCE (from agent/prompt_builder.py); this skill is what you load when you want deeper det... | `devops/kanban-worker` | + ## dogfood diff --git a/website/docs/user-guide/features/kanban-worker-lanes.md b/website/docs/user-guide/features/kanban-worker-lanes.md index 675169f9892..69f879c6b11 100644 --- a/website/docs/user-guide/features/kanban-worker-lanes.md +++ b/website/docs/user-guide/features/kanban-worker-lanes.md @@ -7,7 +7,7 @@ This page is the contract. It exists for two audiences: - **Operators** picking which lanes to wire into a board (which profiles to create, which assignees to use). - **Plugin / integration authors** wanting to add a new lane shape (a CLI worker that wraps Codex / Claude Code / OpenCode, a containerised review worker, a non-Hermes service that pulls tasks via the API). -If you're writing the worker code itself — the agent that runs *inside* a lane — the [`kanban-worker`](https://github.com/NousResearch/hermes-agent/blob/main/skills/devops/kanban-worker/SKILL.md) skill is the deeper procedural detail. +If you're writing the worker code itself — the agent that runs *inside* a lane — the kanban lifecycle and reference details are injected into the worker's system prompt automatically (the `KANBAN_GUIDANCE` block in [`agent/prompt_builder.py`](https://github.com/NousResearch/hermes-agent/blob/main/agent/prompt_builder.py)). ## The hierarchy @@ -64,7 +64,7 @@ For most code-changing tasks, the work isn't truly *done* the moment the worker - **Drop structured metadata into a `kanban_comment` first** since `kanban_block` only carries the human-readable `reason`. Comments are the durable annotation channel — every audit-relevant field (changed_files, tests_run, diff_path or PR url, decisions) belongs there. - **Reviewer either approves and unblocks**, which respawns the worker with the comment thread for follow-ups; or asks for changes via another comment, which the next worker run sees as part of `kanban_show`'s context. -The [`kanban-worker`](https://github.com/NousResearch/hermes-agent/blob/main/skills/devops/kanban-worker/SKILL.md) skill has worked examples for both `kanban_complete` (truly terminal tasks — typo fixes, docs changes, research writeups) and the `review-required` block pattern. +The injected `KANBAN_GUIDANCE` covers both `kanban_complete` (truly terminal tasks — typo fixes, docs changes, research writeups) and the `review-required` block pattern. ## Logs and audit trail @@ -80,9 +80,9 @@ The dashboard renders run history with summaries, metadata blocks, and exit-stat ### Hermes profile lane (default) -The shape every kanban worker takes today: the assignee is a profile name, the dispatcher spawns `hermes -p `, the worker auto-loads the [`kanban-worker`](https://github.com/NousResearch/hermes-agent/blob/main/skills/devops/kanban-worker/SKILL.md) skill plus the `KANBAN_GUIDANCE` system-prompt block, and uses the `kanban_*` tools to terminate the run. No setup beyond defining the profile. +The shape every kanban worker takes today: the assignee is a profile name, the dispatcher spawns `hermes -p `, the worker gets the `KANBAN_GUIDANCE` system-prompt block injected automatically, and uses the `kanban_*` tools to terminate the run. No setup beyond defining the profile. -When you create profiles for your fleet, choose names that match the *role* you want the orchestrator to route to. The orchestrator (when there is one) discovers your profile names via `hermes profile list` — there's no fixed roster the system assumes (see the [`kanban-orchestrator`](https://github.com/NousResearch/hermes-agent/blob/main/skills/devops/kanban-orchestrator/SKILL.md) skill for the orchestrator side of the contract). +When you create profiles for your fleet, choose names that match the *role* you want the orchestrator to route to. The orchestrator (when there is one) discovers your profile names via `hermes profile list` — there's no fixed roster the system assumes (the orchestrator side of the contract is part of the injected `KANBAN_GUIDANCE`). ### Orchestrator profile lane @@ -110,5 +110,4 @@ So lane authors don't have to reimplement these: - [Kanban overview](./kanban) — the user-facing intro. - [Kanban tutorial](./kanban-tutorial) — walkthrough with the dashboard open. -- [`kanban-worker`](https://github.com/NousResearch/hermes-agent/blob/main/skills/devops/kanban-worker/SKILL.md) — the skill the worker process loads. -- [`kanban-orchestrator`](https://github.com/NousResearch/hermes-agent/blob/main/skills/devops/kanban-orchestrator/SKILL.md) — the orchestrator side. +- [`KANBAN_GUIDANCE`](https://github.com/NousResearch/hermes-agent/blob/main/agent/prompt_builder.py) — the worker + orchestrator lifecycle injected into every kanban worker's system prompt. diff --git a/website/docs/user-guide/features/kanban.md b/website/docs/user-guide/features/kanban.md index 66a1ac0be90..c2fe8a0a88b 100644 --- a/website/docs/user-guide/features/kanban.md +++ b/website/docs/user-guide/features/kanban.md @@ -310,7 +310,7 @@ kanban_create( kanban_complete(summary="decomposed into 2 research tasks + 1 writer; linked dependencies") ``` -The "(Orchestrators)" tools — `kanban_list`, `kanban_create`, `kanban_link`, `kanban_unblock`, and `kanban_comment` on foreign tasks — are available through the same toolset; the convention (enforced by the `kanban-orchestrator` skill) is that worker profiles don't fan out or route unrelated work, and orchestrator profiles don't execute implementation work. Dispatcher-spawned workers are still task-scoped for destructive lifecycle operations and cannot mutate unrelated tasks. +The "(Orchestrators)" tools — `kanban_list`, `kanban_create`, `kanban_link`, `kanban_unblock`, and `kanban_comment` on foreign tasks — are available through the same toolset; the convention (encoded in the auto-injected kanban guidance) is that worker profiles don't fan out or route unrelated work, and orchestrator profiles don't execute implementation work. Dispatcher-spawned workers are still task-scoped for destructive lifecycle operations and cannot mutate unrelated tasks. ### Why tools instead of shelling to `hermes kanban` @@ -322,7 +322,7 @@ Three reasons: **Zero schema footprint on normal sessions.** A regular `hermes chat` session has zero `kanban_*` tools in its schema unless the active profile explicitly enables the `kanban` toolset for orchestrator work. Dispatcher-spawned task workers get task-scoped tools because `HERMES_KANBAN_TASK` is set; orchestrator profiles get the broader routing surface through config. No tool bloat for users who never touch kanban. -The `kanban-worker` and `kanban-orchestrator` skills teach the model which tool to call when and in what order. +The auto-injected kanban guidance teaches the model which tool to call when and in what order. ### Recommended handoff evidence @@ -358,9 +358,9 @@ Keep secrets, raw logs, tokens, OAuth material, and unrelated transcripts out of tests, say so explicitly in `summary` and use `metadata` for the evidence that does exist, such as source URLs, issue ids, or manual review steps. -### The worker skill +### The worker lifecycle -Any profile that should be able to work kanban tasks must load the `kanban-worker` skill. It teaches the worker the full lifecycle in **tool calls**, not CLI commands: +Every profile that works kanban tasks automatically gets the worker lifecycle — it's injected into the worker's system prompt at spawn (the `KANBAN_GUIDANCE` block), so there is **nothing to install or configure**. It teaches the worker the full lifecycle in **tool calls**, not CLI commands: 1. On spawn, call `kanban_show()` to read title + body + parent handoffs + prior attempts + full comment thread. 2. `cd $HERMES_KANBAN_WORKSPACE` (via the terminal tool) and do the work there. @@ -374,22 +374,7 @@ protocol. If the worker process exits with status 0 while the task is still 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`, -etc.): - -```bash -hermes -p skills list | grep kanban-worker -``` - -If the bundled copy is missing, restore it for that profile: - -```bash -hermes -p skills reset kanban-worker --restore -``` - -The dispatcher also auto-passes `--skills kanban-worker` when spawning every worker, so the worker always has the pattern library available even if a profile's default skills config doesn't include it. +The lifecycle plus the load-bearing reference details (workspace kinds, deliverable `artifacts`, claiming created cards) ship in that system-prompt block, so every worker has them regardless of which profile it runs under — no per-profile skill setup required. ### Pinning extra skills to a specific task @@ -426,7 +411,7 @@ hermes kanban create "audit auth flow" \ **From the dashboard**, type the skills comma-separated into the **skills** field of the inline create form. -These skills are **additive** to the built-in `kanban-worker` — the dispatcher emits one `--skills ` flag for each (and for the built-in), so the worker spawns with all of them loaded. The skill names must match skills that are actually installed on the assignee's profile (run `hermes skills list` to see what's available); there's no runtime install. +The dispatcher emits one `--skills ` flag per skill listed, so the worker spawns with all of them loaded on top of the auto-injected kanban guidance. The skill names must match skills that are actually installed on the assignee's profile (run `hermes skills list` to see what's available); there's no runtime install. ### Goal-mode cards (`--goal`) @@ -442,9 +427,9 @@ hermes kanban create "Translate the docs site to French" \ Use it for open-ended, multi-step, or "keep going until X is true" cards. Skip it for cheap one-shot work — the per-turn judge overhead isn't worth it, and the dispatcher's existing retry/circuit-breaker already handles transient worker failures. The judge is only as good as your goal text, so write the body as **explicit acceptance criteria**. -### The orchestrator skill +### How the orchestrator behaves -A **well-behaved orchestrator does not do the work itself.** It decomposes the user's goal into tasks, links them, assigns each to one of the profiles you've set up, and steps back. The `kanban-orchestrator` skill encodes this as tool-call patterns: anti-temptation rules, a Step-0 profile-discovery prompt (the dispatcher silently fails on unknown assignee names, so the orchestrator must ground every card in profiles that actually exist on your machine), and a decomposition playbook keyed on `kanban_create` / `kanban_link` / `kanban_comment`. +A **well-behaved orchestrator does not do the work itself.** It decomposes the user's goal into tasks, links them, assigns each to one of the profiles you've set up, and steps back. The orchestrator guidance — anti-temptation rules, a Step-0 profile-discovery prompt (the dispatcher silently fails on unknown assignee names, so the orchestrator must ground every card in profiles that actually exist on your machine), and a decomposition playbook keyed on `kanban_create` / `kanban_link` / `kanban_comment` — is injected into the worker's system prompt automatically; there is nothing to install. A canonical orchestrator turn (two parallel researchers handing off to a writer): @@ -465,19 +450,7 @@ kanban_complete( ) ``` -`kanban-orchestrator` is a bundled skill. It is synced into each profile during -install and update, so there is no separate Skills Hub install step. Verify it is -present in your orchestrator profile: - -```bash -hermes -p orchestrator skills list | grep kanban-orchestrator -``` - -If the bundled copy is missing, restore it for that profile: - -```bash -hermes -p orchestrator skills reset kanban-orchestrator --restore -``` +The orchestrator guidance ships in the worker's system prompt automatically — there is nothing to install or sync per profile. For best results, pair it with a profile whose toolsets are restricted to board operations (`kanban`, `gateway`, `memory`) so the orchestrator literally cannot execute implementation tasks even if it tries. diff --git a/website/docs/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-kanban-codex-lane.md b/website/docs/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-kanban-codex-lane.md index aac59a16d04..671b696264a 100644 --- a/website/docs/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-kanban-codex-lane.md +++ b/website/docs/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-kanban-codex-lane.md @@ -20,7 +20,7 @@ Use when a Hermes Kanban worker wants to run Codex CLI as an isolated implementa | Author | Hermes Agent | | License | MIT | | Tags | `kanban`, `codex`, `worktrees`, `autonomous-agents`, `prediction-market-bot` | -| Related skills | [`kanban-worker`](/docs/user-guide/skills/bundled/devops/devops-kanban-worker), [`codex`](/docs/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-codex), [`hermes-agent`](/docs/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-hermes-agent) | +| Related skills | [`codex`](/docs/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-codex), [`hermes-agent`](/docs/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-hermes-agent) | ## Reference: full SKILL.md diff --git a/website/docs/user-guide/skills/bundled/devops/devops-kanban-orchestrator.md b/website/docs/user-guide/skills/bundled/devops/devops-kanban-orchestrator.md deleted file mode 100644 index 7e5c46c88ff..00000000000 --- a/website/docs/user-guide/skills/bundled/devops/devops-kanban-orchestrator.md +++ /dev/null @@ -1,231 +0,0 @@ ---- -title: "Kanban Orchestrator" -sidebar_label: "Kanban Orchestrator" -description: "Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban" ---- - -{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */} - -# Kanban Orchestrator - -Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role. - -## Skill metadata - -| | | -|---|---| -| Source | Bundled (installed by default) | -| Path | `skills/devops/kanban-orchestrator` | -| Version | `3.0.0` | -| Platforms | linux, macos, windows | -| Tags | `kanban`, `multi-agent`, `orchestration`, `routing` | -| Related skills | [`kanban-worker`](/docs/user-guide/skills/bundled/devops/devops-kanban-worker) | - -## Reference: full SKILL.md - -:::info -The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active. -::: - -# Kanban Orchestrator — Decomposition Playbook - -> The **core worker lifecycle** (including the `kanban_create` fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the `KANBAN_GUIDANCE` system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing. - -## Profiles are user-configured — not a fixed roster - -Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (`docker-worker`, `cron-worker`); some run a curated specialist team they've named themselves. There is **no default specialist roster** — the orchestrator skill does not know what profiles exist on this machine. - -Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names — it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to `researcher` on a setup that only has `docker-worker` just sits in `ready` forever. - -**Step 0: discover available profiles before planning.** - -Use one of these: - -- `hermes profile list` — prints the table of profiles configured on this machine. Run it through your terminal tool if you have one; otherwise ask the user. -- `kanban_list(assignee="")` — sanity-check a single name. Returns an empty list (rather than an error) for an unknown assignee, so this only confirms a name you're already considering. -- **Just ask the user.** "What profiles do you have set up?" is a fine first turn when the goal needs more than one specialist. - -Cache the result in your working memory for the rest of the conversation. Re-asking every turn wastes a tool call. - -## When to use the board (vs. just doing the work) - -Create Kanban tasks when any of these are true: - -1. **Multiple specialists are needed.** Research + analysis + writing is three profiles. -2. **The work should survive a crash or restart.** Long-running, recurring, or important. -3. **The user might want to interject.** Human-in-the-loop at any step. -4. **Multiple subtasks can run in parallel.** Fan-out for speed. -5. **Review / iteration is expected.** A reviewer profile loops on drafter output. -6. **The audit trail matters.** Board rows persist in SQLite forever. - -If *none* of those apply — it's a small one-shot reasoning task — use `delegate_task` instead or answer the user directly. - -## The anti-temptation rules - -Your job description says "route, don't execute." The rules that enforce that: - -- **Do not execute the work yourself.** Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" — stop and create a task for the right specialist. -- **For any concrete task, create a Kanban task and assign it.** Every single time. -- **Split multi-lane requests before creating cards.** A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card. -- **Run independent lanes in parallel.** If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies. -- **Never create dependent work as independent ready cards.** If a card must wait for another card, pass `parents=[...]` in the original `kanban_create` call. Do not create it first and link it later, and do not rely on prose like "wait for T1" inside the body. -- **If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use.** Do not invent profile names; the dispatcher will silently drop unknown assignees. -- **Decompose, route, and summarize — that's the whole job.** - -## Decomposition playbook - -### Step 1 — Understand the goal - -Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet. - -### Step 2 — Sketch the task graph - -Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card: - -1. Extract the lanes from the request. -2. Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create. -3. Decide whether each lane is independent or gated by another lane. -4. Create independent lanes as parallel cards with no parent links. -5. Create synthesis/review/integration cards with parent links to the lanes they depend on. A child created with unfinished parents starts in `todo`; the dispatcher promotes it to `ready` only after every parent is done. - -Examples of prompts that should fan out (using placeholder profile names — substitute whatever exists on the user's setup): - -- "Build an app" → one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile. -- "Fix blockers and check model variants" → one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both. -- "Research docs and implement" → a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings. -- "Analyze this screenshot and find the related code" → one card to a vision-capable profile for the visual analysis while another searches the codebase. - -Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists. - -Show the graph to the user before creating cards. Let them correct it — including which actual profile name should own each lane. - -### Step 3 — Create tasks and link - -Use the profile names from Step 0. The example below uses placeholders ``, ``, `` — replace them with what the user actually has. - -```python -t1 = kanban_create( - title="research: Postgres cost vs current", - assignee="", # whichever profile handles research on this setup - body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.", - tenant=os.environ.get("HERMES_TENANT"), -)["task_id"] - -t2 = kanban_create( - title="research: Postgres performance vs current", - assignee="", # same profile, run in parallel - body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.", -)["task_id"] - -t3 = kanban_create( - title="synthesize migration recommendation", - assignee="", # whichever profile does synthesis/analysis - body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.", - parents=[t1, t2], -)["task_id"] - -t4 = kanban_create( - title="draft decision memo", - assignee="", # whichever profile drafts user-facing prose - body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.", - parents=[t3], -)["task_id"] -``` - -`parents=[...]` gates promotion — children stay in `todo` until every parent reaches `done`, then auto-promote to `ready`. No manual coordination needed; the dispatcher and dependency engine handle it. - -If the task graph has dependencies, create the parent cards first, capture their returned ids, and include those ids in the child card's `parents` list during the child `kanban_create` call. Avoid creating all cards in parallel and linking them afterward; that creates a window where the dispatcher can claim a child before its inputs exist. - -### Step 4 — Complete your own task - -If you were spawned as a task yourself (e.g. a planner profile was assigned `T0: "investigate Postgres migration"`), mark it done with a summary of what you created: - -```python -kanban_complete( - summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation", - metadata={ - "task_graph": { - "T1": {"assignee": "", "parents": []}, - "T2": {"assignee": "", "parents": []}, - "T3": {"assignee": "", "parents": ["T1", "T2"]}, - "T4": {"assignee": "", "parents": ["T3"]}, - }, - }, -) -``` - -### Step 5 — Report back to the user - -Tell them what you created in plain prose, naming the actual profiles you used: - -> I've queued 4 tasks: -> - **T1** (``): cost comparison -> - **T2** (``): performance comparison, in parallel with T1 -> - **T3** (``): synthesizes T1 + T2 into a recommendation -> - **T4** (``): turns T3 into a CTO memo -> -> The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or `hermes kanban tail ` to follow along. - -## Common patterns - -**Fan-out + fan-in (research → synthesize):** N research-style cards with no parents, one synthesis card with all of them as parents. - -**Parallel implementation + validation:** one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence. - -**Pipeline with gates:** `planner → implementer → reviewer`. Each stage's `parents=[previous_task]`. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns. - -**Same-profile queue:** N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes — that profile processes them in priority order, accumulating experience in its own memory. - -**Human-in-the-loop:** Any task can `kanban_block()` to wait for input. Dispatcher respawns after `/unblock`. The comment thread carries the full context. - -## Pitfalls - -**Inventing profile names that don't exist.** The dispatcher silently fails to spawn unknown assignees — the card just sits in `ready` forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure. - -**Bundling independent lanes into one card.** If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both. - -**Over-linking because of wording.** "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result. - -**Forgetting dependency links.** If the task graph says `research -> implement -> review`, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist. - -**Reassignment vs. new task.** If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task — don't re-run the same task with a stern look. The new task is assigned to the original implementer profile. - -**Argument order for links.** `kanban_link(parent_id=..., child_id=...)` — parent first. Mixing them up demotes the wrong task to `todo`. - -**Don't pre-create the whole graph if the shape depends on intermediate findings.** If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators. - -**Tenant inheritance.** If `HERMES_TENANT` is set in your env, pass `tenant=os.environ.get("HERMES_TENANT")` on every `kanban_create` call so child tasks stay in the same namespace. - -## Goal-mode cards (persistent workers) - -By default a dispatched worker gets **one shot** at its card: it does its work, calls `kanban_complete`/`kanban_block`, and exits. For open-ended cards where one turn rarely finishes the job, pass `goal_mode=True` to wrap that worker in a Ralph-style goal loop — the same engine behind the `/goal` slash command: - -```python -kanban_create( - title="Translate the full docs site to French", - body="Acceptance: every page translated, no English left, links intact.", - assignee="", - goal_mode=True, # judge re-checks the card after each turn - goal_max_turns=15, # optional budget (default 20) -)["task_id"] -``` - -How it behaves: -- After each worker turn, an auxiliary judge evaluates the worker's response against the card's **title + body** (treated as the acceptance criteria). -- Not done + budget remains → the worker keeps going **in the same session** (full context retained — not a fresh respawn). -- Worker calls `kanban_complete`/`kanban_block` itself → loop stops, normal lifecycle. -- Budget exhausted without completion → the card is **blocked** for human review (sticky), never a silent exit. - -When to use it: long, multi-step, or "keep going until X is true" cards. When NOT to: cheap one-shot cards (translation of a single string, a quick lookup) — the judge overhead isn't worth it, and the dispatcher's existing retry/circuit-breaker already handles transient worker failures. - -Write the body as **explicit acceptance criteria** — the judge is only as good as the goal text. "Translate the README" is weaker than "Translate every section of the README to French; no English sentences remain." - -## Recovering stuck workers - -When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a ⚠ badge and opens a **Recovery** section in the drawer. Three primary actions: - -1. **Reclaim** (or `hermes kanban reclaim `) — abort the running worker immediately and reset the task to `ready`. The existing claim TTL is ~15 min; this is the fast path out. -2. **Reassign** (or `hermes kanban reassign --reclaim`) — switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker. -3. **Change profile model** — the dashboard prints a copy-paste hint for `hermes -p model` since profile config lives on disk; edit it in a terminal, then Reclaim to retry with the new model. - -Hallucination warnings appear on tasks where a worker's `kanban_complete(created_cards=[...])` claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references `t_` ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions — the trail stays for debugging. diff --git a/website/docs/user-guide/skills/bundled/devops/devops-kanban-worker.md b/website/docs/user-guide/skills/bundled/devops/devops-kanban-worker.md deleted file mode 100644 index e5cdc3277b8..00000000000 --- a/website/docs/user-guide/skills/bundled/devops/devops-kanban-worker.md +++ /dev/null @@ -1,210 +0,0 @@ ---- -title: "Kanban Worker — Pitfalls, examples, and edge cases for Hermes Kanban workers" -sidebar_label: "Kanban Worker" -description: "Pitfalls, examples, and edge cases for Hermes Kanban workers" ---- - -{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */} - -# Kanban Worker - -Pitfalls, examples, and edge cases for Hermes Kanban workers. The lifecycle itself is auto-injected into every worker's system prompt as KANBAN_GUIDANCE (from agent/prompt_builder.py); this skill is what you load when you want deeper detail on specific scenarios. - -## Skill metadata - -| | | -|---|---| -| Source | Bundled (installed by default) | -| Path | `skills/devops/kanban-worker` | -| Version | `2.0.0` | -| Platforms | linux, macos, windows | -| Tags | `kanban`, `multi-agent`, `collaboration`, `workflow`, `pitfalls` | -| Related skills | [`kanban-orchestrator`](/docs/user-guide/skills/bundled/devops/devops-kanban-orchestrator) | - -## Reference: full SKILL.md - -:::info -The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active. -::: - -# Kanban Worker — Pitfalls and Examples - -> You're seeing this skill because the Hermes Kanban dispatcher spawned you as a worker with `--skills kanban-worker` — it's loaded automatically for every dispatched worker. The **lifecycle** (6 steps: orient → work → heartbeat → block/complete) also lives in the `KANBAN_GUIDANCE` block that's auto-injected into your system prompt. This skill is the deeper detail: good handoff shapes, retry diagnostics, edge cases. - -## Workspace handling - -Your workspace kind determines how you should behave inside `$HERMES_KANBAN_WORKSPACE`: - -| Kind | What it is | How to work | -|---|---|---| -| `scratch` | Fresh tmp dir, yours alone | Read/write freely; it gets GC'd when the task is archived. | -| `dir:` | Shared persistent directory | Other runs will read what you write. Treat it like long-lived state. Path is guaranteed absolute (the kernel rejects relative paths). | -| `worktree` | Git worktree at the resolved path | If `.git` doesn't exist, run `git worktree add ${HERMES_KANBAN_BRANCH:-wt/$HERMES_KANBAN_TASK}` from the main repo first, then cd and work normally. Commit work here. | - -## Tenant isolation - -If `$HERMES_TENANT` is set, the task belongs to a tenant namespace. When reading or writing persistent memory, prefix memory entries with the tenant so context doesn't leak across tenants: - -- Good: `business-a: Acme is our biggest customer` -- Bad (leaks): `Acme is our biggest customer` - -## Good summary + metadata shapes - -The `kanban_complete(summary=..., metadata=...)` handoff is how downstream workers read what you did. Patterns that work: - -**Coding task:** -```python -kanban_complete( - summary="shipped rate limiter — token bucket, keys on user_id with IP fallback, 14 tests pass", - metadata={ - "changed_files": ["rate_limiter.py", "tests/test_rate_limiter.py"], - "tests_run": 14, - "tests_passed": 14, - "decisions": ["user_id primary, IP fallback for unauthenticated requests"], - }, -) -``` - -**Coding task that needs human review (review-required):** - -For most code-changing tasks, the work isn't truly *done* until a human reviewer has eyes on it. Block instead of complete, with `reason` prefixed `review-required: ` so the dashboard surfaces the row as needing review. Drop the structured metadata (changed files, test counts, diff/PR url) into a comment first, since `kanban_block` only carries the human-readable reason — comments are the durable annotation channel. Reviewer either approves and runs `hermes kanban unblock ` (which re-spawns you with the comment thread for any follow-ups) or asks for changes via another comment. - -```python -import json - -kanban_comment( - body="review-required handoff:\n" + json.dumps({ - "changed_files": ["rate_limiter.py", "tests/test_rate_limiter.py"], - "tests_run": 14, - "tests_passed": 14, - "diff_path": "/path/to/worktree", # or PR url if pushed - "decisions": ["user_id primary, IP fallback for unauthenticated requests"], - }, indent=2), -) -kanban_block( - reason="review-required: rate limiter shipped, 14/14 tests pass — needs eyes on the user_id/IP fallback choice before merging", -) -``` - -Use `kanban_complete` only when the task is genuinely terminal — e.g. a one-line typo fix, a docs change with no functional consequences, or a research task where the artifact IS the writeup itself. - -**Research task:** -```python -kanban_complete( - summary="3 competing libraries reviewed; vLLM wins on throughput, SGLang on latency, Tensorrt-LLM on memory efficiency", - metadata={ - "sources_read": 12, - "recommendation": "vLLM", - "benchmarks": {"vllm": 1.0, "sglang": 0.87, "trtllm": 0.72}, - }, -) -``` - -**Review task:** -```python -kanban_complete( - summary="reviewed PR #123; 2 blocking issues found (SQL injection in /search, missing CSRF on /settings)", - metadata={ - "pr_number": 123, - "findings": [ - {"severity": "critical", "file": "api/search.py", "line": 42, "issue": "raw SQL concat"}, - {"severity": "high", "file": "api/settings.py", "issue": "missing CSRF middleware"}, - ], - "approved": False, - }, -) -``` - -Shape `metadata` so downstream parsers (reviewers, aggregators, schedulers) can use it without re-reading your prose. - -## Claiming cards you actually created - -If your run produced new kanban tasks (via `kanban_create`), pass the ids in `created_cards` on `kanban_complete`. The kernel verifies each id exists and was created by your profile; any phantom id blocks the completion with an error listing what went wrong, and the rejected attempt is permanently recorded on the task's event log. **Only list ids you captured from a successful `kanban_create` return value — never invent ids from prose, never paste ids from earlier runs, never claim cards another worker created.** - -```python -# GOOD — capture return values, then claim them. -c1 = kanban_create(title="remediate SQL injection", assignee="security-worker") -c2 = kanban_create(title="fix CSRF middleware", assignee="web-worker") - -kanban_complete( - summary="Review done; spawned remediations for both findings.", - metadata={"pr_number": 123, "approved": False}, - created_cards=[c1["task_id"], c2["task_id"]], -) -``` - -```python -# BAD — claiming ids you don't have captured return values for. -kanban_complete( - summary="Created remediation cards t_a1b2c3d4, t_deadbeef", # hallucinated - created_cards=["t_a1b2c3d4", "t_deadbeef"], # → gate rejects -) -``` - -If a `kanban_create` call fails (exception, tool_error), the card was NOT created — do not include a phantom id for it. Retry the create, or omit the id and mention the failure in your summary. The prose-scan pass also catches `t_` references in your free-form summary that don't resolve; these don't block the completion but show up as advisory warnings on the task in the dashboard. - -## Block reasons that get answered fast - -Bad: `"stuck"` — the human has no context. - -Good: one sentence naming the specific decision you need. Leave longer context as a comment instead. - -```python -kanban_comment( - task_id=os.environ["HERMES_KANBAN_TASK"], - body="Full context: I have user IPs from Cloudflare headers but some users are behind NATs with thousands of peers. Keying on IP alone causes false positives.", -) -kanban_block(reason="Rate limit key choice: IP (simple, NAT-unsafe) or user_id (requires auth, skips anonymous endpoints)?") -``` - -The block message is what appears in the dashboard / gateway notifier. The comment is the deeper context a human reads when they open the task. - -## Heartbeats worth sending - -Good heartbeats name progress: `"epoch 12/50, loss 0.31"`, `"scanned 1.2M/2.4M rows"`, `"uploaded 47/120 videos"`. - -Bad heartbeats: `"still working"`, empty notes, sub-second intervals. Every few minutes max; skip entirely for tasks under ~2 minutes. - -## Retry scenarios - -If you open the task and `kanban_show` returns `runs: [...]` with one or more closed runs, you're a retry. The prior runs' `outcome` / `summary` / `error` tell you what didn't work. Don't repeat that path. Typical retry diagnostics: - -- `outcome: "timed_out"` — the previous attempt hit `max_runtime_seconds`. You may need to chunk the work or shorten it. -- `outcome: "crashed"` — OOM or segfault. Reduce memory footprint. -- `outcome: "spawn_failed"` + `error: "..."` — usually a profile config issue (missing credential, bad PATH). Ask the human via `kanban_block` instead of retrying blindly. -- `outcome: "reclaimed"` + `summary: "task archived..."` — operator archived the task out from under the previous run; you probably shouldn't be running at all, check status carefully. -- `outcome: "blocked"` — a previous attempt blocked; the unblock comment should be in the thread by now. - -## Notification routing - -You can configure the gateway to receive cross-profile Kanban task notifications by adding `notification_sources` to `~/.hermes/config.yaml`. -- `notification_sources: ['*']` accepts subscriptions from all profiles. -- `notification_sources: ['default', 'zilor-ppt']` or `"default,zilor-ppt"` restricts subscriptions to specified profiles. -- Omitting the key keeps the default behavior (profile isolation). - -## Do NOT - -- Call `delegate_task` as a substitute for `kanban_create`. `delegate_task` is for short reasoning subtasks inside YOUR run; `kanban_create` is for cross-agent handoffs that outlive one API loop. -- Call `clarify` to ask the human a question. You are running headless — there is no live user to answer. The call will time out (default ~120s) and the task will sit silently in `running` with no signal that it needs input. Use `kanban_comment` (context) + `kanban_block(reason=...)` (decision needed) instead — the task surfaces on the board as blocked, the operator sees it, unblocks with their answer in a comment, and you respawn with the thread. -- Modify files outside `$HERMES_KANBAN_WORKSPACE` unless the task body says to. -- Create follow-up tasks assigned to yourself — assign to the right specialist. -- Complete a task you didn't actually finish. Block it instead. - -## Pitfalls - -**Task state can change between dispatch and your startup.** Between when the dispatcher claimed and when your process actually booted, the task may have been blocked, reassigned, or archived. Always `kanban_show` first. If it reports `blocked` or `archived`, stop — you shouldn't be running. - -**Workspace may have stale artifacts.** Especially `dir:` and `worktree` workspaces can have files from previous runs. Read the comment thread — it usually explains why you're running again and what state the workspace is in. - -**Don't rely on the CLI when the guidance is available.** The `kanban_*` tools work across all terminal backends (Docker, Modal, SSH). `hermes kanban ` from your terminal tool will fail in containerized backends because the CLI isn't installed there. When in doubt, use the tool. - -## CLI fallback (for scripting) - -Every tool has a CLI equivalent for human operators and scripts: -- `kanban_show` ↔ `hermes kanban show --json` -- `kanban_complete` ↔ `hermes kanban complete --summary "..." --metadata '{...}'` -- `kanban_block` ↔ `hermes kanban block "reason"` -- `kanban_create` ↔ `hermes kanban create "title" --assignee [--parent ]` -- etc. - -Use the tools from inside an agent; the CLI exists for the human at the terminal. diff --git a/website/docs/user-guide/skills/optional/creative/creative-kanban-video-orchestrator.md b/website/docs/user-guide/skills/optional/creative/creative-kanban-video-orchestrator.md index 25f081e43ce..7195aaceeaf 100644 --- a/website/docs/user-guide/skills/optional/creative/creative-kanban-video-orchestrator.md +++ b/website/docs/user-guide/skills/optional/creative/creative-kanban-video-orchestrator.md @@ -21,7 +21,7 @@ Plan, set up, and monitor a multi-agent video production pipeline backed by Herm | License | MIT | | Platforms | linux, macos, windows | | Tags | `video`, `kanban`, `multi-agent`, `orchestration`, `production-pipeline` | -| Related skills | [`kanban-orchestrator`](/docs/user-guide/skills/bundled/devops/devops-kanban-orchestrator), [`kanban-worker`](/docs/user-guide/skills/bundled/devops/devops-kanban-worker), [`ascii-video`](/docs/user-guide/skills/bundled/creative/creative-ascii-video), [`manim-video`](/docs/user-guide/skills/bundled/creative/creative-manim-video), [`p5js`](/docs/user-guide/skills/bundled/creative/creative-p5js), [`comfyui`](/docs/user-guide/skills/bundled/creative/creative-comfyui), [`touchdesigner-mcp`](/docs/user-guide/skills/bundled/creative/creative-touchdesigner-mcp), [`blender-mcp`](/docs/user-guide/skills/optional/creative/creative-blender-mcp), [`pixel-art`](/docs/user-guide/skills/optional/creative/creative-pixel-art), [`ascii-art`](/docs/user-guide/skills/bundled/creative/creative-ascii-art), [`songwriting-and-ai-music`](/docs/user-guide/skills/bundled/creative/creative-songwriting-and-ai-music), [`heartmula`](/docs/user-guide/skills/bundled/media/media-heartmula), [`songsee`](/docs/user-guide/skills/bundled/media/media-songsee), `spotify`, [`youtube-content`](/docs/user-guide/skills/bundled/media/media-youtube-content), [`claude-design`](/docs/user-guide/skills/bundled/creative/creative-claude-design), [`excalidraw`](/docs/user-guide/skills/bundled/creative/creative-excalidraw), [`architecture-diagram`](/docs/user-guide/skills/bundled/creative/creative-architecture-diagram), [`concept-diagrams`](/docs/user-guide/skills/optional/creative/creative-concept-diagrams), [`baoyu-comic`](/docs/user-guide/skills/optional/creative/creative-baoyu-comic), [`baoyu-infographic`](/docs/user-guide/skills/bundled/creative/creative-baoyu-infographic), [`humanizer`](/docs/user-guide/skills/bundled/creative/creative-humanizer), [`gif-search`](/docs/user-guide/skills/bundled/media/media-gif-search), [`meme-generation`](/docs/user-guide/skills/optional/creative/creative-meme-generation) | +| Related skills | [`ascii-video`](/docs/user-guide/skills/bundled/creative/creative-ascii-video), [`manim-video`](/docs/user-guide/skills/bundled/creative/creative-manim-video), [`p5js`](/docs/user-guide/skills/bundled/creative/creative-p5js), [`comfyui`](/docs/user-guide/skills/bundled/creative/creative-comfyui), [`touchdesigner-mcp`](/docs/user-guide/skills/bundled/creative/creative-touchdesigner-mcp), [`blender-mcp`](/docs/user-guide/skills/optional/creative/creative-blender-mcp), [`pixel-art`](/docs/user-guide/skills/optional/creative/creative-pixel-art), [`ascii-art`](/docs/user-guide/skills/bundled/creative/creative-ascii-art), [`songwriting-and-ai-music`](/docs/user-guide/skills/bundled/creative/creative-songwriting-and-ai-music), [`heartmula`](/docs/user-guide/skills/bundled/media/media-heartmula), [`songsee`](/docs/user-guide/skills/bundled/media/media-songsee), `spotify`, [`youtube-content`](/docs/user-guide/skills/bundled/media/media-youtube-content), [`claude-design`](/docs/user-guide/skills/bundled/creative/creative-claude-design), [`excalidraw`](/docs/user-guide/skills/bundled/creative/creative-excalidraw), [`architecture-diagram`](/docs/user-guide/skills/bundled/creative/creative-architecture-diagram), [`concept-diagrams`](/docs/user-guide/skills/optional/creative/creative-concept-diagrams), [`baoyu-comic`](/docs/user-guide/skills/optional/creative/creative-baoyu-comic), [`baoyu-infographic`](/docs/user-guide/skills/bundled/creative/creative-baoyu-infographic), [`humanizer`](/docs/user-guide/skills/bundled/creative/creative-humanizer), [`gif-search`](/docs/user-guide/skills/bundled/media/media-gif-search), [`meme-generation`](/docs/user-guide/skills/optional/creative/creative-meme-generation) | ## Reference: full SKILL.md @@ -187,7 +187,7 @@ task graphs. See **[references/examples.md](https://github.com/NousResearch/herm file` toolset, the director's `SOUL.md` rules forbid it from executing work itself. It decomposes and routes only — every concrete task becomes a `hermes kanban create` call to a specialist profile. The - `kanban-orchestrator` skill spells this out further. + auto-injected kanban orchestration guidance spells this out further. 7. **Don't over-decompose.** A 30-second product video does NOT need 20 tasks. Aim for the smallest task graph that still parallelizes well and exposes the diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/reference/skills-catalog.md b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/reference/skills-catalog.md index 20773484b6c..305224a7cf4 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/reference/skills-catalog.md +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/reference/skills-catalog.md @@ -62,8 +62,7 @@ Hermes 在执行 `hermes update` 时也会同步内置技能,但同步清单 | 技能 | 描述 | 路径 | |-------|-------------|------| -| [`kanban-orchestrator`](/user-guide/skills/bundled/devops/devops-kanban-orchestrator) | 面向编排器(orchestrator)配置文件的分解策略与反诱惑规则,用于通过 Kanban 路由工作。"不要自己做工作"规则和基本生命周期会自动注入每个 Kanban worker 的系统 prompt;如需更深入的细节,请加载此技能。 | `devops/kanban-orchestrator` | -| [`kanban-worker`](/user-guide/skills/bundled/devops/devops-kanban-worker) | Hermes Kanban worker 的陷阱、示例和边界情况。生命周期本身会作为 `KANBAN_GUIDANCE` 自动注入每个 worker 的系统 prompt(来自 `agent/prompt_builder.py`);当需要更深入细节时加载此技能。 | `devops/kanban-worker` | + ## dogfood diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/features/kanban-worker-lanes.md b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/features/kanban-worker-lanes.md index 138eb76c972..5d728eed7fb 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/features/kanban-worker-lanes.md +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/features/kanban-worker-lanes.md @@ -7,7 +7,7 @@ - **运维人员**:选择将哪些通道接入看板(创建哪些 profile,使用哪些 assignee)。 - **插件/集成作者**:希望添加新的通道形态(封装 Codex / Claude Code / OpenCode 的 CLI worker、容器化审查 worker、通过 API 拉取任务的非 Hermes 服务)。 -如果你编写的是 worker 代码本身——即运行在通道*内部*的 agent——请参阅 [`kanban-worker`](https://github.com/NousResearch/hermes-agent/blob/main/skills/devops/kanban-worker/SKILL.md) skill,其中包含更深入的操作细节。 +如果你编写的是 worker 代码本身——即运行在通道*内部*的 agent——kanban 生命周期与参考细节会自动注入到 worker 的系统提示中([`agent/prompt_builder.py`](https://github.com/NousResearch/hermes-agent/blob/main/agent/prompt_builder.py) 中的 `KANBAN_GUIDANCE` 块)。 ## 层级结构 @@ -64,7 +64,7 @@ kanban 内核强制要求每次运行恰好由其中一项终止。既未调用 - **先将结构化元数据写入 `kanban_comment`**,因为 `kanban_block` 只携带人类可读的 `reason`。Comment 是持久的注解通道——所有与审计相关的字段(changed_files、tests_run、diff_path 或 PR url、决策记录)都应放在这里。 - **Reviewer 批准并解除阻塞**,这将重新生成 worker 并附带 comment 线程用于后续跟进;或通过另一条 comment 要求修改,下一次 worker 运行时将通过 `kanban_show` 的上下文看到这些内容。 -[`kanban-worker`](https://github.com/NousResearch/hermes-agent/blob/main/skills/devops/kanban-worker/SKILL.md) skill 中有 `kanban_complete`(真正终态的任务——拼写修复、文档变更、研究报告)和 `review-required` block 模式的完整示例。 +自动注入的 `KANBAN_GUIDANCE` 同时涵盖 `kanban_complete`(真正终态的任务——拼写修复、文档变更、研究报告)和 `review-required` block 模式。 ## 日志与审计追踪 @@ -80,9 +80,9 @@ kanban 内核强制要求每次运行恰好由其中一项终止。既未调用 ### Hermes profile 通道(默认) -当前所有 kanban worker 采用的形态:assignee 是 profile 名称,调度器生成 `hermes -p `,worker 自动加载 [`kanban-worker`](https://github.com/NousResearch/hermes-agent/blob/main/skills/devops/kanban-worker/SKILL.md) skill 以及 `KANBAN_GUIDANCE` 系统提示块,并使用 `kanban_*` 工具终止运行。除定义 profile 外无需任何额外配置。 +当前所有 kanban worker 采用的形态:assignee 是 profile 名称,调度器生成 `hermes -p `,worker 会自动获得注入的 `KANBAN_GUIDANCE` 系统提示块,并使用 `kanban_*` 工具终止运行。除定义 profile 外无需任何额外配置。 -为你的 fleet 创建 profile 时,选择与你希望 orchestrator 路由到的*角色*相匹配的名称。orchestrator(如果存在)通过 `hermes profile list` 发现你的 profile 名称——系统不假设固定的名单(orchestrator 侧的契约请参阅 [`kanban-orchestrator`](https://github.com/NousResearch/hermes-agent/blob/main/skills/devops/kanban-orchestrator/SKILL.md) skill)。 +为你的 fleet 创建 profile 时,选择与你希望 orchestrator 路由到的*角色*相匹配的名称。orchestrator(如果存在)通过 `hermes profile list` 发现你的 profile 名称——系统不假设固定的名单(orchestrator 侧的契约也是注入的 `KANBAN_GUIDANCE` 的一部分)。 ### Orchestrator profile 通道 @@ -110,5 +110,4 @@ profile 通道的特化形态:orchestrator 是一个 Hermes profile,其工 - [Kanban 概览](./kanban) — 面向用户的介绍。 - [Kanban 教程](./kanban-tutorial) — 开启仪表板的完整演练。 -- [`kanban-worker`](https://github.com/NousResearch/hermes-agent/blob/main/skills/devops/kanban-worker/SKILL.md) — worker 进程加载的 skill。 -- [`kanban-orchestrator`](https://github.com/NousResearch/hermes-agent/blob/main/skills/devops/kanban-orchestrator/SKILL.md) — orchestrator 侧。 \ No newline at end of file +- [`KANBAN_GUIDANCE`](https://github.com/NousResearch/hermes-agent/blob/main/agent/prompt_builder.py) — 注入到每个 kanban worker 系统提示中的 worker + orchestrator 生命周期。 \ No newline at end of file diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/features/kanban.md b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/features/kanban.md index febeb213c7b..075296d687b 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/features/kanban.md +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/features/kanban.md @@ -240,7 +240,7 @@ kanban_create( kanban_complete(summary="decomposed into 2 research tasks + 1 writer; linked dependencies") ``` -"(编排器)"工具 —— `kanban_list`、`kanban_create`、`kanban_link`、`kanban_unblock`,以及对外部任务的 `kanban_comment` —— 通过同一工具集提供;约定(由 `kanban-orchestrator` skill 强制执行)是 worker 配置文件不进行扇出或路由无关工作,编排器配置文件不执行实现工作。调度器启动的 worker 仍然针对破坏性生命周期操作限定在任务范围内,无法修改无关任务。 +"(编排器)"工具 —— `kanban_list`、`kanban_create`、`kanban_link`、`kanban_unblock`,以及对外部任务的 `kanban_comment` —— 通过同一工具集提供;约定(编码在自动注入的 kanban 指引中)是 worker 配置文件不进行扇出或路由无关工作,编排器配置文件不执行实现工作。调度器启动的 worker 仍然针对破坏性生命周期操作限定在任务范围内,无法修改无关任务。 ### 为什么使用工具而不是 shell 执行 `hermes kanban` @@ -252,7 +252,7 @@ kanban_complete(summary="decomposed into 2 research tasks + 1 writer; linked dep **对普通会话零 schema 占用。** 普通的 `hermes chat` 会话在其 schema 中没有任何 `kanban_*` 工具,除非活动配置文件为编排器工作显式启用了 `kanban` 工具集。调度器启动的任务 worker 因为设置了 `HERMES_KANBAN_TASK` 而获得任务范围的工具;编排器配置文件通过配置获得更广泛的路由界面。对于从不使用 kanban 的用户,没有工具膨胀。 -`kanban-worker` 和 `kanban-orchestrator` skill 教导模型何时调用哪个工具以及调用顺序。 +自动注入的 kanban 指引教导模型何时调用哪个工具以及调用顺序。 ### 推荐的交接证据 @@ -280,9 +280,9 @@ kanban_complete(summary="decomposed into 2 research tasks + 1 writer; linked dep 不要将密钥、原始日志、token(令牌)、OAuth 材料和无关记录放入 `metadata`。改为存储指针和摘要。如果任务没有文件或测试,在 `summary` 中明确说明,并在 `metadata` 中放置确实存在的证据,例如来源 URL、issue id 或手动审查步骤。 -### Worker skill +### Worker 生命周期 -任何应该能够处理 kanban 任务的配置文件都必须加载 `kanban-worker` skill。它通过**工具调用**(而非 CLI 命令)教导 worker 完整的生命周期: +任何处理 kanban 任务的配置文件都会**自动**获得 worker 生命周期 —— 它在启动时被注入到 worker 的系统 prompt 中(`KANBAN_GUIDANCE` 块),因此**无需安装或配置任何东西**。它通过**工具调用**(而非 CLI 命令)教导 worker 完整的生命周期: 1. 启动时,调用 `kanban_show()` 读取标题 + 正文 + 父级交接 + 先前尝试 + 完整评论线程。 2. 通过终端工具执行 `cd $HERMES_KANBAN_WORKSPACE`,在那里完成工作。 @@ -291,20 +291,6 @@ kanban_complete(summary="decomposed into 2 research tasks + 1 writer; linked dep 最终的 `kanban_complete` / `kanban_block` 调用是 worker 协议的一部分。如果 worker 进程以状态 0 退出而任务仍处于 `running` 状态,调度器将其视为协议违规,发出 `protocol_violation` 事件,并在下一个 tick 自动阻塞任务而不是重新启动它进入同一循环。这通常意味着模型写了一个纯文本答案并退出,而没有使用 Kanban 工具界面。 -`kanban-worker` 是一个内置 skill,在安装和更新期间同步到每个配置文件 —— 无需单独的 Skills Hub 安装步骤。验证它是否存在于你用于 kanban worker 的配置文件中(`researcher`、`writer`、`ops` 等): - -```bash -hermes -p skills list | grep kanban-worker -``` - -如果内置副本丢失,为该配置文件恢复它: - -```bash -hermes -p skills reset kanban-worker --restore -``` - -调度器在启动每个 worker 时也会自动传递 `--skills kanban-worker`,因此即使配置文件的默认 skills 配置不包含它,worker 也始终拥有该模式库。 - ### 为特定任务固定额外 skill 有时单个任务需要受让人配置文件默认不携带的专业上下文 —— 需要 `translation` skill 的翻译任务、需要 `github-code-review` 的审查任务、需要 `security-pr-audit` 的安全审计。与其每次都编辑受让人的配置文件,不如直接将 skill 附加到任务上。 @@ -340,11 +326,11 @@ hermes kanban create "audit auth flow" \ **从仪表盘**,在内联创建表单的 **skills** 字段中以逗号分隔输入 skill 名称。 -这些 skill 是对内置 `kanban-worker` 的**补充** —— 调度器为每个 skill(以及内置的)发出一个 `--skills ` 标志,因此 worker 启动时加载了所有这些 skill。skill 名称必须与受让人配置文件上实际安装的 skill 匹配(运行 `hermes skills list` 查看可用内容);没有运行时安装。 +调度器为列出的每个 skill 发出一个 `--skills ` 标志,因此 worker 在自动注入的 kanban 指引之上加载了所有这些 skill。skill 名称必须与受让人配置文件上实际安装的 skill 匹配(运行 `hermes skills list` 查看可用内容);没有运行时安装。 -### 编排器 skill +### 编排器的行为方式 -**行为良好的编排器不会自己做工作。** 它将用户的目标分解为任务,链接它们,将每个任务分配给你设置的配置文件之一,然后退后。`kanban-orchestrator` skill 将此编码为工具调用模式:反诱惑规则、Step-0 配置文件发现提示(调度器在未知受让人名称上静默失败,因此编排器必须将每张卡片落地到你机器上实际存在的配置文件),以及以 `kanban_create` / `kanban_link` / `kanban_comment` 为核心的分解手册。 +**行为良好的编排器不会自己做工作。** 它将用户的目标分解为任务,链接它们,将每个任务分配给你设置的配置文件之一,然后退后。编排器指引 —— 反诱惑规则、Step-0 配置文件发现提示(调度器在未知受让人名称上静默失败,因此编排器必须将每张卡片落地到你机器上实际存在的配置文件),以及以 `kanban_create` / `kanban_link` / `kanban_comment` 为核心的分解手册 —— 会自动注入到 worker 的系统 prompt 中;无需安装任何东西。 典型的编排器轮次(两个并行研究员交接给一个写作者): @@ -365,17 +351,7 @@ kanban_complete( ) ``` -`kanban-orchestrator` 是一个内置 skill。它在安装和更新期间同步到每个配置文件,因此无需单独的 Skills Hub 安装步骤。验证它是否存在于你的编排器配置文件中: - -```bash -hermes -p orchestrator skills list | grep kanban-orchestrator -``` - -如果内置副本丢失,为该配置文件恢复它: - -```bash -hermes -p orchestrator skills reset kanban-orchestrator --restore -``` +编排器指引随 worker 的系统 prompt 自动提供 —— 无需按配置文件安装或同步任何东西。 为获得最佳效果,将其与工具集限制为看板操作(`kanban`、`gateway`、`memory`)的配置文件配对,这样编排器即使尝试也无法执行实现任务。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/skills/bundled/devops/devops-kanban-orchestrator.md b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/skills/bundled/devops/devops-kanban-orchestrator.md deleted file mode 100644 index 2ef00910292..00000000000 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/skills/bundled/devops/devops-kanban-orchestrator.md +++ /dev/null @@ -1,207 +0,0 @@ ---- -title: "Kanban Orchestrator" -sidebar_label: "Kanban Orchestrator" -description: "用于通过 Kanban 路由工作的编排器 profile 的任务分解手册及反诱惑规则" ---- - -{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */} - -# Kanban Orchestrator - -用于通过 Kanban 路由工作的编排器 profile 的任务分解手册及反诱惑规则。"不要自己执行工作"规则和基本生命周期会自动注入每个 kanban worker 的系统 prompt(提示词)中;本 skill 是当你专门扮演编排器角色时使用的更深层手册。 - -## Skill 元数据 - -| | | -|---|---| -| 来源 | 内置(默认安装) | -| 路径 | `skills/devops/kanban-orchestrator` | -| 版本 | `3.0.0` | -| 平台 | linux, macos, windows | -| 标签 | `kanban`, `multi-agent`, `orchestration`, `routing` | -| 相关 skill | [`kanban-worker`](/user-guide/skills/bundled/devops/devops-kanban-worker) | - -## 参考:完整 SKILL.md - -:::info -以下是 Hermes 在触发此 skill 时加载的完整 skill 定义。这是 skill 激活时 agent 所看到的指令内容。 -::: - -# Kanban Orchestrator — 任务分解手册 - -> **核心 worker 生命周期**(包括 `kanban_create` 扇出模式和"分解而非执行"规则)通过 `KANBAN_GUIDANCE` 系统 prompt 块自动注入每个 kanban 进程。本 skill 是当你作为编排器 profile、整个职责就是路由时使用的更深层手册。 - -## Profile 由用户配置——不是固定名单 - -Hermes 的配置因人而异。有些用户运行单个 profile 处理所有事务;有些运行小型集群(`docker-worker`、`cron-worker`);有些运行自己命名的精选专家团队。**没有默认的专家名单**——编排器 skill 不知道此机器上存在哪些 profile。 - -在扇出之前,你必须基于实际存在的 profile 来制定分解方案。调度器会静默地忽略无法识别的 assignee 名称——它不会自动纠正、不会建议、也不会回退。因此,在只有 `docker-worker` 的配置上,分配给 `researcher` 的卡片会永远停留在 `ready` 状态。 - -**第 0 步:在规划前发现可用的 profile。** - -使用以下方法之一: - -- `hermes profile list` — 打印此机器上已配置的 profile 表。如果有终端工具,通过终端工具运行;否则询问用户。 -- `kanban_list(assignee="")` — 验证单个名称。对于未知 assignee 返回空列表(而非报错),因此只能确认你已在考虑的名称。 -- **直接询问用户。** 当目标需要多个专家时,"你配置了哪些 profile?"是一个合理的开场问题。 - -将结果缓存在工作记忆中供本次对话使用。每轮都重新询问会浪费工具调用。 - -## 何时使用看板(vs. 直接执行工作) - -当以下任一条件成立时,创建 Kanban 任务: - -1. **需要多个专家。** 研究 + 分析 + 写作需要三个 profile。 -2. **工作应在崩溃或重启后继续存在。** 长期运行、周期性或重要的任务。 -3. **用户可能需要介入。** 任意步骤需要人工参与。 -4. **多个子任务可以并行运行。** 扇出以提高速度。 -5. **预期需要审查/迭代。** 审查者 profile 循环处理起草者的输出。 -6. **审计追踪很重要。** 看板行永久保存在 SQLite 中。 - -如果*以上均不适用*——这是一个小型一次性推理任务——改用 `delegate_task` 或直接回答用户。 - -## 反诱惑规则 - -你的职责描述是"路由,不执行"。执行该规则的约束: - -- **不要自己执行工作。** 你受限的工具集通常甚至不包含用于实现的终端/文件/代码/网络工具。如果你发现自己在"快速修复这个"——停下来,为合适的专家创建任务。 -- **对于任何具体任务,创建 Kanban 任务并分配它。** 每一次都如此。 -- **在创建卡片之前拆分多通道请求。** 用户的一个 prompt 可能包含多个独立的工作流。先提取这些通道,然后每个通道创建一张卡片,而不是将不相关的工作打包到单个实现者卡片中。 -- **并行运行独立通道。** 如果两张卡片不需要彼此的输出,不要链接它们,让调度器可以扇出处理。只链接真正的数据依赖。 -- **永远不要将依赖工作创建为独立的 ready 卡片。** 如果一张卡片必须等待另一张卡片,在原始 `kanban_create` 调用中传入 `parents=[...]`。不要先创建再链接,也不要依赖卡片正文中的"等待 T1"之类的描述。 -- **如果没有专家适合现有 profile,询问用户应创建哪个 profile 或使用哪个现有 profile。** 不要凭空发明 profile 名称;调度器会静默丢弃未知 assignee。 -- **分解、路由、汇总——这就是全部工作。** - -## 任务分解手册 - -### 第 1 步——理解目标 - -如果目标不明确,提出澄清性问题。询问的成本很低;派出错误的团队代价高昂。 - -### 第 2 步——草拟任务图 - -在创建任何内容之前,在回复用户时大声(在响应中)草拟任务图。将每个具体工作流视为候选卡片: - -1. 从请求中提取通道。 -2. 将每个通道映射到第 0 步中发现的某个 profile。如果某个通道不适合任何现有 profile,询问用户使用或创建哪个。 -3. 决定每个通道是独立的还是受另一个通道门控的。 -4. 将独立通道创建为无父链接的并行卡片。 -5. 将综合/审查/集成卡片创建时带上其所依赖通道的父链接。使用未完成父任务创建的子任务从 `todo` 开始;调度器仅在每个父任务完成后才将其提升为 `ready`。 - -应该扇出的 prompt 示例(使用占位符 profile 名称——替换为用户配置中实际存在的名称): - -- "构建一个应用" → 一张卡片给面向设计的 profile 负责产品/UI 方向,一两张卡片给工程 profile 负责实现,如果用户有审查者 profile,再加一张后续的集成/审查卡片。 -- "修复阻塞项并检查模型变体" → 一张实现卡片用于修复阻塞项,加一张发现/研究卡片用于配置/源码验证。最终的审查者卡片可以依赖两者。 -- "研究文档并实现" → 文档研究卡片可以与代码库发现卡片并行运行;只有当实现真正需要这些发现时才等待。 -- "分析这张截图并找到相关代码" → 一张卡片给具备视觉能力的 profile 进行视觉分析,同时另一张卡片搜索代码库。 - -"也"、"最后"或"和"等词语不自动意味着依赖关系。它们通常意味着"确保在汇报前涵盖这一点"。只有当一张卡片在另一张卡片的输出存在之前无法开始时,才链接任务。 - -在创建卡片之前将任务图展示给用户。让他们纠正——包括哪个实际 profile 名称应该负责每个通道。 - -### 第 3 步——创建任务并链接 - -使用第 0 步中的 profile 名称。以下示例使用占位符 ``、``、``——替换为用户实际拥有的名称。 - -```python -t1 = kanban_create( - title="research: Postgres cost vs current", - assignee="", # whichever profile handles research on this setup - body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.", - tenant=os.environ.get("HERMES_TENANT"), -)["task_id"] - -t2 = kanban_create( - title="research: Postgres performance vs current", - assignee="", # same profile, run in parallel - body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.", -)["task_id"] - -t3 = kanban_create( - title="synthesize migration recommendation", - assignee="", # whichever profile does synthesis/analysis - body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.", - parents=[t1, t2], -)["task_id"] - -t4 = kanban_create( - title="draft decision memo", - assignee="", # whichever profile drafts user-facing prose - body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.", - parents=[t3], -)["task_id"] -``` - -`parents=[...]` 门控提升——子任务保持在 `todo` 状态,直到每个父任务达到 `done`,然后自动提升为 `ready`。无需手动协调;调度器和依赖引擎会处理这一切。 - -如果任务图有依赖关系,先创建父卡片,捕获其返回的 id,并在子卡片的 `kanban_create` 调用中将这些 id 包含在 `parents` 列表中。避免并行创建所有卡片后再链接;这会产生一个时间窗口,调度器可能在子任务的输入存在之前就认领它。 - -### 第 4 步——完成你自己的任务 - -如果你是作为任务被派生的(例如,规划者 profile 被分配了 `T0: "调查 Postgres 迁移"`),用你创建内容的摘要标记它为完成: - -```python -kanban_complete( - summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation", - metadata={ - "task_graph": { - "T1": {"assignee": "", "parents": []}, - "T2": {"assignee": "", "parents": []}, - "T3": {"assignee": "", "parents": ["T1", "T2"]}, - "T4": {"assignee": "", "parents": ["T3"]}, - }, - }, -) -``` - -### 第 5 步——向用户汇报 - -用简明的文字告诉他们你创建了什么,并说明你使用的实际 profile 名称: - -> 我已排队 4 个任务: -> - **T1**(``):成本对比 -> - **T2**(``):性能对比,与 T1 并行 -> - **T3**(``):综合 T1 + T2 生成建议 -> - **T4**(``):将 T3 转化为 CTO 备忘录 -> -> 调度器现在将认领 T1 和 T2。T3 在两者完成后启动。T4 完成时你会收到 gateway 通知。使用仪表板或 `hermes kanban tail ` 跟踪进度。 - -## 常见模式 - -**扇出 + 扇入(研究 → 综合):** N 张无父链接的研究类卡片,一张以所有研究卡片为父的综合卡片。 - -**并行实现 + 验证:** 一张实现者卡片进行变更,同时一张探索/研究卡片验证配置、文档或源码映射。审查者卡片可以依赖两者。不要因为用户在一句话中同时提到了两者,就让实现者承担不相关的验证工作。 - -**带门控的流水线:** `planner → implementer → reviewer`。每个阶段的 `parents=[previous_task]`。审查者阻塞或完成;如果审查者阻塞,操作员带着反馈解除阻塞并重新派发。 - -**同 profile 队列:** N 个任务,全部分配给同一个 profile,彼此之间无依赖。调度器串行处理——该 profile 按优先级顺序处理它们,在自己的记忆中积累经验。 - -**人工参与循环:** 任何任务都可以调用 `kanban_block()` 等待输入。调度器在 `/unblock` 后重新派发。评论线程携带完整上下文。 - -## 常见陷阱 - -**发明不存在的 profile 名称。** 调度器会静默地忽略无法识别的 assignee——卡片会永远停留在 `ready` 状态。始终从第 0 步发现的 profile 中分配;如果不确定,询问用户。 - -**将独立通道打包到一张卡片中。** 如果用户要求两个独立的结果,创建两张卡片。示例:"修复阻塞项并检查模型变体"不是一个修复任务;为修复创建一张修复/工程卡片,为变体检查创建一张探索/研究卡片,然后可选地将审查门控在两者之上。 - -**因措辞而过度链接。** "最后检查 X"如果 X 是静态配置、文档或源码发现,仍然可以与实现并行。只有当检查依赖于实现结果时,才将其链接在实现之后。 - -**忘记依赖链接。** 如果任务图说 `research -> implement -> review`,不要将所有任务创建为独立的 ready 卡片。使用父链接,确保 implement/review 在其输入存在之前无法运行。 - -**重新分配 vs. 新任务。** 如果审查者以"需要修改"阻塞,创建一个从审查者任务链接的**新**任务——不要用严厉的眼神重新运行同一个任务。新任务分配给原始实现者 profile。 - -**链接的参数顺序。** `kanban_link(parent_id=..., child_id=...)` — 父任务在前。混淆顺序会将错误的任务降级为 `todo`。 - -**如果形状取决于中间发现,不要预先创建整个任务图。** 如果 T3 的结构取决于 T1 和 T2 的发现,让 T3 作为一个"综合发现"任务存在,其第一步是读取父任务的交接内容并规划其余部分。编排器可以派生编排器。 - -**Tenant 继承。** 如果你的环境中设置了 `HERMES_TENANT`,在每次 `kanban_create` 调用中传入 `tenant=os.environ.get("HERMES_TENANT")`,以确保子任务保持在同一命名空间中。 - -## 恢复卡住的 worker - -当一个 worker profile 持续崩溃、产生幻觉或被自身错误阻塞时(通常是:错误的模型、缺少 skill、凭据损坏),kanban 仪表板会在任务上标记 ⚠ 徽章,并在抽屉中打开**恢复**部分。三个主要操作: - -1. **Reclaim**(或 `hermes kanban reclaim `)——立即中止正在运行的 worker 并将任务重置为 `ready`。现有认领 TTL 约为 15 分钟;这是最快的解决路径。 -2. **Reassign**(或 `hermes kanban reassign --reclaim`)——将任务切换到不同的 profile(此配置上存在的 profile)并让调度器用新 worker 认领它。 -3. **更改 profile 模型**——仪表板会打印 `hermes -p model` 的复制粘贴提示,因为 profile 配置存储在磁盘上;在终端中编辑它,然后 Reclaim 以使用新模型重试。 - -当 worker 的 `kanban_complete(created_cards=[...])` 声明包含不存在或非该 worker profile 创建的卡片 id 时(门控会阻止完成),或者自由格式摘要引用了无法解析的 `t_` id 时(建议性文本扫描,非阻塞),会出现幻觉警告。两者都会产生审计事件,即使在恢复操作后也会持久保存——追踪记录保留用于调试。 \ No newline at end of file diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/skills/bundled/devops/devops-kanban-worker.md b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/skills/bundled/devops/devops-kanban-worker.md deleted file mode 100644 index ad2d1ff63d8..00000000000 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/skills/bundled/devops/devops-kanban-worker.md +++ /dev/null @@ -1,202 +0,0 @@ ---- -title: "Kanban Worker — Hermes Kanban worker 的陷阱、示例与边界情况" -sidebar_label: "Kanban Worker" -description: "Hermes Kanban worker 的陷阱、示例与边界情况" ---- - -{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */} - -# Kanban Worker - -Hermes Kanban worker 的陷阱、示例与边界情况。生命周期本身会自动注入到每个 worker 的系统 prompt(提示词)中,作为 `KANBAN_GUIDANCE`(来自 `agent/prompt_builder.py`);当你需要深入了解特定场景时,加载此 skill 即可。 - -## Skill 元数据 - -| | | -|---|---| -| 来源 | 内置(默认安装) | -| 路径 | `skills/devops/kanban-worker` | -| 版本 | `2.0.0` | -| 平台 | linux, macos, windows | -| 标签 | `kanban`, `multi-agent`, `collaboration`, `workflow`, `pitfalls` | -| 相关 skill | [`kanban-orchestrator`](/user-guide/skills/bundled/devops/devops-kanban-orchestrator) | - -## 参考:完整 SKILL.md - -:::info -以下是 Hermes 在触发此 skill 时加载的完整 skill 定义。这是 skill 激活时 agent 所看到的指令内容。 -::: - -# Kanban Worker — 陷阱与示例 - -> 你看到此 skill,是因为 Hermes Kanban 调度器以 `--skills kanban-worker` 参数将你作为 worker 派生——它会为每个被派发的 worker 自动加载。**生命周期**(6 个步骤:orient → work → heartbeat → block/complete)也存在于自动注入到你系统 prompt 中的 `KANBAN_GUIDANCE` 块里。此 skill 是更深层的细节:良好的交接形式、重试诊断、边界情况。 - -## 工作区处理 - -你的工作区类型决定了你在 `$HERMES_KANBAN_WORKSPACE` 内部的行为方式: - -| 类型 | 含义 | 操作方式 | -|---|---|---| -| `scratch` | 全新的临时目录,仅供你使用 | 自由读写;任务归档后会被 GC 回收。 | -| `dir:` | 共享的持久化目录 | 其他运行实例会读取你写入的内容。将其视为长期状态。路径保证为绝对路径(内核拒绝相对路径)。 | -| `worktree` | 位于已解析路径的 Git worktree | 若 `.git` 不存在,先从主仓库执行 `git worktree add `,然后 cd 进去正常工作。在此提交工作。 | - -## 租户隔离 - -若 `$HERMES_TENANT` 已设置,则该任务属于某个租户命名空间。在读写持久化内存时,请为内存条目添加租户前缀,以防上下文跨租户泄漏: - -- 正确:`business-a: Acme is our biggest customer` -- 错误(会泄漏):`Acme is our biggest customer` - -## 良好的 summary + metadata 形式 - -`kanban_complete(summary=..., metadata=...)` 的交接方式是下游 worker 读取你工作成果的途径。以下是有效的模式: - -**编码任务:** -```python -kanban_complete( - summary="shipped rate limiter — token bucket, keys on user_id with IP fallback, 14 tests pass", - metadata={ - "changed_files": ["rate_limiter.py", "tests/test_rate_limiter.py"], - "tests_run": 14, - "tests_passed": 14, - "decisions": ["user_id primary, IP fallback for unauthenticated requests"], - }, -) -``` - -**需要人工审查的编码任务(review-required):** - -对于大多数涉及代码变更的任务,在人工审查者过目之前,工作并未真正*完成*。应使用 block 而非 complete,并在 `reason` 前加 `review-required: ` 前缀,以便仪表板将该行标记为待审查。先将结构化元数据(变更文件、测试计数、diff/PR url)写入 comment,因为 `kanban_block` 只携带人类可读的原因——comment 是持久化注释的渠道。审查者可执行 `hermes kanban unblock ` 批准(这会携带 comment 线程重新派生你以处理后续事项),或通过另一条 comment 要求修改。 - -```python -import json - -kanban_comment( - body="review-required handoff:\n" + json.dumps({ - "changed_files": ["rate_limiter.py", "tests/test_rate_limiter.py"], - "tests_run": 14, - "tests_passed": 14, - "diff_path": "/path/to/worktree", # or PR url if pushed - "decisions": ["user_id primary, IP fallback for unauthenticated requests"], - }, indent=2), -) -kanban_block( - reason="review-required: rate limiter shipped, 14/14 tests pass — needs eyes on the user_id/IP fallback choice before merging", -) -``` - -仅在任务真正终结时使用 `kanban_complete`——例如单行拼写修复、无功能影响的文档变更,或产出物本身即为成果的研究任务。 - -**研究任务:** -```python -kanban_complete( - summary="3 competing libraries reviewed; vLLM wins on throughput, SGLang on latency, Tensorrt-LLM on memory efficiency", - metadata={ - "sources_read": 12, - "recommendation": "vLLM", - "benchmarks": {"vllm": 1.0, "sglang": 0.87, "trtllm": 0.72}, - }, -) -``` - -**审查任务:** -```python -kanban_complete( - summary="reviewed PR #123; 2 blocking issues found (SQL injection in /search, missing CSRF on /settings)", - metadata={ - "pr_number": 123, - "findings": [ - {"severity": "critical", "file": "api/search.py", "line": 42, "issue": "raw SQL concat"}, - {"severity": "high", "file": "api/settings.py", "issue": "missing CSRF middleware"}, - ], - "approved": False, - }, -) -``` - -请将 `metadata` 的结构设计为下游解析器(审查者、聚合器、调度器)无需重新阅读你的文字描述即可直接使用。 - -## 认领你实际创建的卡片 - -若你的运行产生了新的 kanban 任务(通过 `kanban_create`),请在 `kanban_complete` 的 `created_cards` 中传入这些 id。内核会验证每个 id 是否存在且由你的 profile 创建;任何幻构的 id 都会导致完成操作被阻断,并附带错误列表说明问题所在,且被拒绝的尝试会永久记录在任务的事件日志中。**只列出你从成功的 `kanban_create` 返回值中捕获的 id——绝不凭空捏造 id,绝不粘贴来自早期运行的 id,绝不认领其他 worker 创建的卡片。** - -```python -# 正确 — 捕获返回值,然后认领。 -c1 = kanban_create(title="remediate SQL injection", assignee="security-worker") -c2 = kanban_create(title="fix CSRF middleware", assignee="web-worker") - -kanban_complete( - summary="Review done; spawned remediations for both findings.", - metadata={"pr_number": 123, "approved": False}, - created_cards=[c1["task_id"], c2["task_id"]], -) -``` - -```python -# 错误 — 认领没有捕获返回值的 id。 -kanban_complete( - summary="Created remediation cards t_a1b2c3d4, t_deadbeef", # 幻构 - created_cards=["t_a1b2c3d4", "t_deadbeef"], # → 门控拒绝 -) -``` - -若 `kanban_create` 调用失败(异常、tool_error),则卡片未被创建——不要为其包含幻构 id。重试创建,或省略该 id 并在 summary 中说明失败情况。散文扫描阶段也会捕获你自由格式 summary 中无法解析的 `t_` 引用;这些不会阻断完成操作,但会在仪表板的任务上显示为建议性警告。 - -## 能快速得到回应的 block 原因 - -差:`"stuck"` — 人类没有任何上下文。 - -好:一句话说明你需要的具体决策。将更长的上下文作为 comment 留下。 - -```python -kanban_comment( - task_id=os.environ["HERMES_KANBAN_TASK"], - body="Full context: I have user IPs from Cloudflare headers but some users are behind NATs with thousands of peers. Keying on IP alone causes false positives.", -) -kanban_block(reason="Rate limit key choice: IP (simple, NAT-unsafe) or user_id (requires auth, skips anonymous endpoints)?") -``` - -block 消息是仪表板/gateway 通知器中显示的内容。comment 是人类打开任务时阅读的深层上下文。 - -## 值得发送的 heartbeat - -好的 heartbeat 应说明进度:`"epoch 12/50, loss 0.31"`、`"scanned 1.2M/2.4M rows"`、`"uploaded 47/120 videos"`。 - -差的 heartbeat:`"still working"`、空 notes、亚秒级间隔。最多每隔几分钟发送一次;对于约 2 分钟以内的任务可完全跳过。 - -## 重试场景 - -若你打开任务后 `kanban_show` 返回的 `runs: [...]` 中包含一个或多个已关闭的运行,说明你是一次重试。先前运行的 `outcome` / `summary` / `error` 会告诉你哪里出了问题。不要重复那条路径。典型的重试诊断: - -- `outcome: "timed_out"` — 上次尝试达到了 `max_runtime_seconds`。你可能需要将工作分块或缩短。 -- `outcome: "crashed"` — OOM 或段错误。减少内存占用。 -- `outcome: "spawn_failed"` + `error: "..."` — 通常是 profile 配置问题(缺少凭证、错误的 PATH)。通过 `kanban_block` 询问人类,而不是盲目重试。 -- `outcome: "reclaimed"` + `summary: "task archived..."` — 操作员在上次运行期间将任务归档;你可能根本不应该在运行,请仔细检查状态。 -- `outcome: "blocked"` — 上次尝试被阻断;解除阻断的 comment 现在应该已在线程中。 - -## 禁止事项 - -- 不要用 `delegate_task` 替代 `kanban_create`。`delegate_task` 用于你的运行内部的短期推理子任务;`kanban_create` 用于跨 agent 的、超出单次 API 循环的交接。 -- 不要修改 `$HERMES_KANBAN_WORKSPACE` 之外的文件,除非任务正文明确要求。 -- 不要创建分配给自己的后续任务——分配给合适的专家。 -- 不要完成一个你实际上没有完成的任务。改为 block 它。 - -## 陷阱 - -**任务状态可能在调度与启动之间发生变化。** 从调度器认领任务到你的进程实际启动之间,任务可能已被 block、重新分配或归档。始终先执行 `kanban_show`。若其报告 `blocked` 或 `archived`,请停止——你不应该在运行。 - -**工作区可能存在过期产物。** 尤其是 `dir:` 和 `worktree` 工作区可能包含来自先前运行的文件。阅读 comment 线程——它通常会解释你为何再次运行以及工作区处于何种状态。 - -**当指导已可用时,不要依赖 CLI。** `kanban_*` 工具可在所有终端后端(Docker、Modal、SSH)上工作。从你的终端工具执行 `hermes kanban ` 在容器化后端中会失败,因为 CLI 未安装在那里。如有疑问,使用工具。 - -## CLI 回退(用于脚本) - -每个工具都有对应的 CLI 等价命令,供人工操作员和脚本使用: -- `kanban_show` ↔ `hermes kanban show --json` -- `kanban_complete` ↔ `hermes kanban complete --summary "..." --metadata '{...}'` -- `kanban_block` ↔ `hermes kanban block "reason"` -- `kanban_create` ↔ `hermes kanban create "title" --assignee [--parent ]` -- 等等。 - -在 agent 内部使用工具;CLI 供终端前的人类使用。 \ No newline at end of file diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/skills/optional/creative/creative-kanban-video-orchestrator.md b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/skills/optional/creative/creative-kanban-video-orchestrator.md index 15bbaaec8d1..a1ba562abf8 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/skills/optional/creative/creative-kanban-video-orchestrator.md +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/skills/optional/creative/creative-kanban-video-orchestrator.md @@ -21,7 +21,7 @@ description: "规划、搭建并监控由 Hermes Kanban 支撑的多智能体视 | 许可证 | MIT | | 平台 | linux, macos, windows | | 标签 | `video`, `kanban`, `multi-agent`, `orchestration`, `production-pipeline` | -| 相关技能 | [`kanban-orchestrator`](/user-guide/skills/bundled/devops/devops-kanban-orchestrator)、[`kanban-worker`](/user-guide/skills/bundled/devops/devops-kanban-worker)、[`ascii-video`](/user-guide/skills/bundled/creative/creative-ascii-video)、[`manim-video`](/user-guide/skills/bundled/creative/creative-manim-video)、[`p5js`](/user-guide/skills/bundled/creative/creative-p5js)、[`comfyui`](/user-guide/skills/bundled/creative/creative-comfyui)、[`touchdesigner-mcp`](/user-guide/skills/bundled/creative/creative-touchdesigner-mcp)、[`blender-mcp`](/user-guide/skills/optional/creative/creative-blender-mcp)、[`pixel-art`](/user-guide/skills/bundled/creative/creative-pixel-art)、[`ascii-art`](/user-guide/skills/bundled/creative/creative-ascii-art)、[`songwriting-and-ai-music`](/user-guide/skills/bundled/creative/creative-songwriting-and-ai-music)、[`heartmula`](/user-guide/skills/bundled/media/media-heartmula)、[`songsee`](/user-guide/skills/bundled/media/media-songsee)、[`spotify`](/user-guide/skills/bundled/media/media-spotify)、[`youtube-content`](/user-guide/skills/bundled/media/media-youtube-content)、[`claude-design`](/user-guide/skills/bundled/creative/creative-claude-design)、[`excalidraw`](/user-guide/skills/bundled/creative/creative-excalidraw)、[`architecture-diagram`](/user-guide/skills/bundled/creative/creative-architecture-diagram)、[`concept-diagrams`](/user-guide/skills/optional/creative/creative-concept-diagrams)、[`baoyu-comic`](/user-guide/skills/bundled/creative/creative-baoyu-comic)、[`baoyu-infographic`](/user-guide/skills/bundled/creative/creative-baoyu-infographic)、[`humanizer`](/user-guide/skills/bundled/creative/creative-humanizer)、[`gif-search`](/user-guide/skills/bundled/media/media-gif-search)、[`meme-generation`](/user-guide/skills/optional/creative/creative-meme-generation) | +| 相关技能 | [`ascii-video`](/user-guide/skills/bundled/creative/creative-ascii-video)、[`manim-video`](/user-guide/skills/bundled/creative/creative-manim-video)、[`p5js`](/user-guide/skills/bundled/creative/creative-p5js)、[`comfyui`](/user-guide/skills/bundled/creative/creative-comfyui)、[`touchdesigner-mcp`](/user-guide/skills/bundled/creative/creative-touchdesigner-mcp)、[`blender-mcp`](/user-guide/skills/optional/creative/creative-blender-mcp)、[`pixel-art`](/user-guide/skills/bundled/creative/creative-pixel-art)、[`ascii-art`](/user-guide/skills/bundled/creative/creative-ascii-art)、[`songwriting-and-ai-music`](/user-guide/skills/bundled/creative/creative-songwriting-and-ai-music)、[`heartmula`](/user-guide/skills/bundled/media/media-heartmula)、[`songsee`](/user-guide/skills/bundled/media/media-songsee)、[`spotify`](/user-guide/skills/bundled/media/media-spotify)、[`youtube-content`](/user-guide/skills/bundled/media/media-youtube-content)、[`claude-design`](/user-guide/skills/bundled/creative/creative-claude-design)、[`excalidraw`](/user-guide/skills/bundled/creative/creative-excalidraw)、[`architecture-diagram`](/user-guide/skills/bundled/creative/creative-architecture-diagram)、[`concept-diagrams`](/user-guide/skills/optional/creative/creative-concept-diagrams)、[`baoyu-comic`](/user-guide/skills/bundled/creative/creative-baoyu-comic)、[`baoyu-infographic`](/user-guide/skills/bundled/creative/creative-baoyu-infographic)、[`humanizer`](/user-guide/skills/bundled/creative/creative-humanizer)、[`gif-search`](/user-guide/skills/bundled/media/media-gif-search)、[`meme-generation`](/user-guide/skills/optional/creative/creative-meme-generation) | ## 参考:完整 SKILL.md @@ -146,7 +146,7 @@ director profile 从此接管,通过 kanban 工具集将工作分解并路由 5. **尊重现有技能。** 当某个场景适合现有技能时,相关渲染器应通过任务上的 `--skill ` 或 profile 中的 `always_load` 加载该技能。不要重新推导技能已提供的内容。 -6. **director 绝不执行。** 即使拥有完整的 `kanban + terminal + file` 工具集,director 的 `SOUL.md` 规则也禁止其自行执行工作。它只负责分解和路由——每个具体任务都变成对专业 profile 的 `hermes kanban create` 调用。`kanban-orchestrator` 技能对此有进一步说明。 +6. **director 绝不执行。** 即使拥有完整的 `kanban + terminal + file` 工具集,director 的 `SOUL.md` 规则也禁止其自行执行工作。它只负责分解和路由——每个具体任务都变成对专业 profile 的 `hermes kanban create` 调用。自动注入的 kanban 编排指引对此有进一步说明。 7. **不要过度分解。** 一个 30 秒的产品视频**不需要** 20 个任务。目标是最小任务图,同时仍能良好并行化并暴露正确的人工审核节点。 diff --git a/website/sidebars.ts b/website/sidebars.ts index 20aed93581e..a5779b6a418 100644 --- a/website/sidebars.ts +++ b/website/sidebars.ts @@ -188,16 +188,6 @@ const sidebars: SidebarsConfig = { 'user-guide/skills/bundled/data-science/data-science-jupyter-live-kernel', ], }, - { - type: 'category', - label: 'devops', - key: 'skills-bundled-devops', - collapsed: true, - items: [ - 'user-guide/skills/bundled/devops/devops-kanban-orchestrator', - 'user-guide/skills/bundled/devops/devops-kanban-worker', - ], - }, { type: 'category', label: 'dogfood',