{"repo":"NousResearch/hermes-agent","public_id":"27136","display_label":"Kanban worker handling of unresolved skills, plus one unrelated Gemini fix","summary":"Most members concern making a Kanban worker or the CLI warn instead of crash when a preloaded or unknown skill cannot be looked up. One member, about adding a role field to Gemini systemInstruction for Gemma compatibility, does not appear related to this theme.","subsystem":"agent","counts":{"members":6,"open_issues":1,"open_issues_distinct":1,"open_prs":1,"closed_issues":1,"merged_prs":1,"attempt_prs":3},"landed_fix":{"status":"merged_to_main","basis":"structural","pr":55585,"merged_at":"2026-06-30T10:42:21+00:00"},"resolution":{"state":"partially_resolved","by":"pr-55585"},"freshness":{"state":"verified","last_verified_at":"2026-06-30T10:42:21+00:00","is_stale":false},"grouping":{"backbone":"STRUCTURAL_PARTIAL","link_density":0.29066666666666663},"fix_edges":[{"issue_number":27136,"pr_number":55585,"tier":"verified","basis":"closing_ref","confidence":0.95,"recoverable_from_timeline":true,"pr_merged_at":"2026-06-30T10:42:21+00:00"}],"members":[{"kind":"issue","number":27136,"title":"fix(cli): unknown skills should warn instead of crash to prevent Kanban worker auto-blocking","url":null,"state":"closed"},{"kind":"issue","number":54088,"title":"Kanban worker should not crash when an optional preloaded skill cannot be resolved","url":null,"state":"open"},{"kind":"pr","number":27123,"title":"fix(gemini): add missing role field to systemInstruction for Gemma compatibility","url":null,"state":"closed","close_reason":{"refs":[{"kind":"commit","value":"018009bc3","number":0},{"kind":"pr","value":"#55585","number":55585},{"kind":"pr","value":"#27123","number":27123}],"category":"merged_via","implication":"superseded"},"merged":false},{"kind":"pr","number":27201,"title":"fix(cli): unknown skills should warn instead of crash","url":null,"state":"closed","close_reason":{"refs":[{"kind":"commit","value":"018009bc382de86f864e3fa8af3982c2f0aa7bfb","number":0}],"category":"merged_via","implication":"superseded"},"merged":false},{"kind":"pr","number":54100,"title":"fix(kanban): keep a dispatcher-owned worker running when the whole skill set is missing (#54088)","url":null,"state":"open","close_reason":{"category":"uncategorized","implication":"needs_llm"},"merged":false},{"kind":"pr","number":55585,"title":"fix(kanban): unknown skill warns instead of crashing the worker","url":null,"state":"merged","close_reason":{"category":"merged"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["cli.py","scripts/release.py","tui_gateway/server.py"],"fix_hunks":[{"file":"cli.py","hunks":["@@ -15359,7 +15359,21 @@ def main(\n         )\n         if missing_skills:\n             missing_display = \", \".join(missing_skills)\n-            raise ValueError(f\"Unknown skill(s): {missing_display}\")\n+            # If at least one skill loaded, degrade gracefully: skip the\n+            # unknown ones and continue. A typo'd skill name should not crash\n+            # the worker (which auto-blocks the Kanban task after retries).\n+            # Only when EVERY requested skill is missing do we hard-fail, so a\n+            # fully-misconfigured worker fails loudly instead of running blind.\n+            if loaded_skills:\n+                logger.warning(\n+                    \"Unknown skill(s) requested, skipping: %s. \"\n+                    \"Continuing with: %s. \"\n+                    \"List available skills with `hermes skills list`.\",\n+                    missing_display,\n+                    \", \".join(loaded_skills),\n+                )\n+            else:\n+                raise ValueError(f\"Unknown skill(s): {missing_display}\")\n         if skills_prompt:\n             cli.system_prompt = \"\\n\\n\".join(\n                 part for part in (cli.system_prompt, skills_prompt) if part"]},{"file":"scripts/release.py","hunks":["@@ -45,6 +45,7 @@\n \n # Auto-extracted from noreply emails + manual overrides\n AUTHOR_MAP = {\n+    \"193368749+jimmyjohansson84@users.noreply.github.com\": \"jimmyjohansson84\",  # PR #27123 salvage (Kanban unknown-skill warn-instead-of-crash; #27136)\n     \"[redacted:email]\": \"theAgenticBuilder\",  # PR #14180 salvage (route delegate_task progress lines through _safe_print so ACP stdio JSON-RPC frames stay clean)\n     \"[redacted:email]\": \"huangxudong663-sys\",  # PR #15157 salvage (isinstance(dict) guard on tool-call model_extra; NVIDIA NIM non-dict crash)\n     \"[redacted:email]\": \"Nickperillo\",  # PR #8008 salvage (Discord channel-name matching + flush pending sends on shutdown)"]},{"file":"tui_gateway/server.py","hunks":["@@ -4212,12 +4212,25 @@ def _make_agent(\n     if startup_skills:\n         from agent.skill_commands import build_preloaded_skills_prompt\n \n-        skills_prompt, _loaded_skills, missing_skills = build_preloaded_skills_prompt(\n+        skills_prompt, loaded_skills, missing_skills = build_preloaded_skills_prompt(\n             startup_skills,\n             task_id=session_id or key,\n         )\n         if missing_skills:\n-            raise ValueError(f\"Unknown skill(s): {', '.join(missing_skills)}\")\n+            missing_display = \", \".join(missing_skills)\n+            # Degrade gracefully when some skills loaded; only hard-fail when\n+            # every requested skill is missing. Mirrors cli.py — a typo'd skill\n+            # name should not crash the worker and auto-block the Kanban task.\n+            if loaded_skills:\n+                logger.warning(\n+                    \"Unknown skill(s) requested, skipping: %s. \"\n+                    \"Continuing with: %s. \"\n+                    \"List available skills with `hermes skills list`.\",\n+                    missing_display,\n+                    \", \".join(loaded_skills),\n+                )\n+            else:\n+                raise ValueError(f\"Unknown skill(s): {missing_display}\")\n         if skills_prompt:\n             system_prompt = \"\\n\\n\".join(\n                 part for part in (system_prompt, skills_prompt) if part\n"]}]}],"trust":{"default_tier":"verified","includes_suggested":false}}