Config rot: ahora hermes config check avisa de selecciones renombradas, desinstaladas y desactivadas


Migraste un config.yaml antiguo a una máquina nueva, o desinstalaste un plugin hace unas semanas y renombraste un toolset. Hermes arranca, conversa y parece perfectamente sano — hasta que un día un bot de plataforma deja de responder, o simplemente falta toda una clase de herramientas. Abres el archivo de config y cada nombre que esperabas sigue ahí.

Esto es la config rot: los nombres de toolset guardados en platform_toolsets son los que Hermes creía que existían en el momento de guardar. Después de quitar un plugin o renombrar un toolset, esos nombres no apuntan a nada y el runtime los ignora en silencio. Un patch mergeado el 2026-09-29 (PR #127782, que rescata el #127392 conservando la autoría original) hace que hermes config check reporte las selecciones obsoletas y alinea su criterio con el del runtime.

Un solo resolver, tres puntos de llamada

El núcleo estructural del patch es reducir «¿este nombre guardado sigue siendo un toolset real?» a una única función:

# hermes_cli/toolset_validation.py
def saved_toolset_resolver(config: dict) -> Callable[[str], bool]:
    """is_valid_toolset for a saved platform_toolsets list, mirroring what
    tools_config._get_platform_tools lets through."""

Tanto hermes config check como hermes config migrate pasan ahora por ella. ¿Por qué importa? Porque antes del fix, migrate avisaba sobre nombres de servidores MCP y bundles de plugin-plataforma que estaban correctamente configurados, hasta el punto de sugerirte que cambiaras 'hermes-teams' por 'hermes-teams'. Una comprobación de migración que se contradice a sí misma es puro ruido.

Vale la pena recordar las nuevas reglas, porque explican por qué tu config ha dejado de gritar:

  • Un servidor MCP configurado cuenta como conocido, incluso cuando declara enabled: false. Está inactivo, no mal escrito. El código antiguo trataba «inactivo» como «no reconocido» y producía un inútil «unknown toolset — did you mean hermes-cli?».
  • known_plugin_toolsets ya no es prueba de que un toolset exista. Registra lo que se le ofreció a una plataforma en el momento de guardar, así que ocultaba justo el caso para el que existe esta comprobación: nombres dejados atrás por plugins desinstalados.
  • La búsqueda de plugins y el escaneo del manifiesto de plataformas solo se ejecutan para los nombres que las comprobaciones más baratas no consiguen ubicar. Una config limpia nunca dispara el descubrimiento de plugins, así que la comprobación en sí no cuesta nada.

Plataformas desactivadas: juzgadas como las ve el runtime

La segunda familia de falsas alarmas venía de plugins.disabled. El runtime es indulgente con la forma — solo acepta una lista —, pero la comprobación antigua juzgaba el valor YAML en bruto, así que esta línea:

plugins:
  disabled: platforms/telegram   # a string, ignored by the runtime

se reportaba como «platform disabled» mientras el runtime seguía cargándola tan tranquilo. Ahora la comprobación lee a través del propio lector del runtime (_get_disabled_plugins()), así que un valor que no sea una lista ya no se reporta como si desactivara algo.

Y cuando sí reporta, comprueba si las credenciales requeridas de la plataforma están realmente configuradas:

platform plugin 'platforms/telegram' is disabled while its required credentials are configured.
Run `hermes plugins enable platforms/telegram` if you want it active.

Fíjate en «required»: el filtro es _platform_manifest_env_entries(optional=False), así que las variables opcionales nunca cuentan. Una plataforma desactivada sin token se queda como está, y una variable de entorno opcional no puede confundirse con un «está claro que querías ejecutar esto».

Un crash arreglado y una comprobación eliminada

Otras dos cosas que parecen no tener relación, pero la tienen:

  • Un mcp_servers mal formado ya no mata el comando. Escríbelo como lista por accidente (mcp_servers: [a]) y el código antiguo lanzaba un traceback de AttributeError; ahora se ejecuta y reporta el problema como un diagnóstico normal. Un comando de diagnóstico que muere es el tipo de fallo menos útil que existe.
  • La comprobación de la clave toolsets de nivel superior ha desaparecido. El PR original también validaba la clave toolsets de nivel superior, pero la CLI resuelve los toolsets desde --toolsets o platform_toolsets, y solo lee la clave de nivel superior para el antiguo opt-in de kanban. Comprobar una clave que el runtime nunca lee solo te inventa trabajo.

La siguiente tabla procede de la propia ejecución de validación del patch (hermes config check real, HERMES_HOME temporal); a la izquierda, el comportamiento antiguo:

Caso Antes Ahora
platform_toolsets.cli lista un nombre eliminado reportado reportado
toolset de un plugin desinstalado, recordado en known_plugin_toolsets silencio reportado
servidor MCP con enabled: false listado en platform_toolsets «unknown toolset, did you mean hermes-cli?» silencio
mcp_servers: [a] (forma incorrecta) traceback AttributeError se ejecuta
plugins.disabled: platforms/telegram (string) con un token configurado reportado como desactivado (el runtime sigue cargándolo) silencio
plugins.disabled: [platforms/telegram] con un token configurado reportado reportado

Por qué tu config antigua sigue parseándose

Hay una rareza histórica fácil de pasar por alto: las primeras builds de hermes config set guardaban un argumento de array JSON puro como string, así que una config puede contener esto:

platform_toolsets:
  cli: '["browser", "terminal"]'    # a string, not a list

El runtime, hermes doctor y hermes plugins enable leen ahora esa sección a través de un único parser, así que coinciden en lo que has configurado. Cuando un lector se monta su propio shim de compatibilidad, los otros dos acaban viendo una configuración distinta.

Cuándo ejecutarlo

Versión corta: tras cambiar de máquina, desinstalar un plugin, renombrar un toolset o actualizar desde una build antigua.

hermes config check      # informa de las selecciones guardadas que ya no se resuelven
hermes config migrate    # migra y repara con el mismo resolver
hermes tools             # vuelve a elegir toolsets de forma interactiva
hermes plugins enable platforms/telegram   # activa una plataforma señalada por la comprobación

Tres conclusiones prácticas:

  1. Ante «disabled while its required credentials are configured», pregúntate si la desactivaste a propósito. La propia comprobación lo contempla: una credencial configurada solo es un motivo para mencionarlo. Si quieres que esté activa, ejecuta el hermes plugins enable sugerido.
  2. Ante un nombre de toolset que ya no se resuelve, no lo borres de inmediato. Comprueba si pertenecía a un plugin desinstalado; si aún quieres esa capacidad, reinstala el plugin. Borrar el nombre solo significa tener que reconfigurarlo más tarde.
  3. Un config check limpio no es una config perfecta. Solo juzga si el runtime puede honrar las selecciones guardadas, no si tu modelo es una buena elección o si tus claves están al día. Para esa clase de preguntas, usa hermes doctor.

Y esta comprobación solo resulta útil si la config se mantiene ordenada: la guía de configuración de MCP y el artículo sobre el catálogo de plugins insisten en lo mismo — añadir o quitar plugins y servidores MCP debe ir seguido de una limpieza de la config. Este patch saca ese paso de tu memoria y lo mete en un comando.

La versión corta

  • hermes config check ahora informa de los nombres guardados en platform_toolsets que ya no se resuelven, además de las plataformas desactivadas cuyas credenciales requeridas están configuradas.
  • Comparte un único resolver con hermes config migrate, lo que acaba con avisos autocontradictorios como sugerir 'hermes-teams' para 'hermes-teams'.
  • El criterio coincide con el del runtime: un servidor MCP desactivado es conocido, known_plugin_toolsets no es una prueba, un plugins.disabled que no es lista ya no miente y las variables de entorno opcionales nunca cuentan como requeridas.
  • El descubrimiento de plugins solo se ejecuta cuando hace falta, así que una config limpia no paga nada; un mcp_servers mal formado ya no hace caer el comando.
  • Se eliminó la comprobación de la clave toolsets de nivel superior porque la CLI nunca la lee (solo el kanban heredado).
  • Ejecútalo tras cambiar de máquina, quitar plugins o actualizar, y luego repara con hermes config migrate y hermes tools.

Uso completo en hermes config y hermes plugins.