Bug Description
The "Always Approve" button on destructive slash commands (/new, /reset, /undo, /clear) silently fails to persist. The user clicks "Always Approve," the gateway logs "User opted out of destructive slash confirm," but the approvals.destructive_slash_confirm: false setting never lands in config.yaml. On next /new, the confirmation prompt reappears. The user can click "Always Approve" dozens of times with zero effect.
Root Cause
save_config_value() in cli.py calls atomic_roundtrip_yaml_update() from utils.py, which imports ruamel.yaml. If ruamel.yaml is missing from the venv, the ImportError is caught and logged at ERROR level — but never surfaced to the user:
ERROR cli: Failed to save config: No module named 'ruamel'
The gateway code at gateway/run.py:12406-12420 catches exceptions from save_config_value and only logs a warning:
if choice == "always":
try:
from cli import save_config_value
save_config_value("approvals.destructive_slash_confirm", False)
logger.info("User opted out of destructive slash confirm ...")
except Exception as exc:
logger.warning("Failed to persist destructive_slash_confirm=false: %s", exc)
The info log fires before atomic_roundtrip_yaml_update actually executes (since it's called inside a try/except but the info log is outside the actual save), so the log says "opted out" regardless of whether the write succeeded. The user sees nothing wrong.
Why ruamel.yaml can be missing
ruamel.yaml IS declared in pyproject.toml as a required dependency. However, on installs that predate uv or installations done via pip install -e ., transitive dependencies may not be fully resolved. In this case the venv had 300+ packages but ruamel.yaml was absent.
Steps to Reproduce
- Ensure
ruamel.yaml is NOT installed in the Hermes venv:
/path/to/venv/bin/python -c "import ruamel.yaml" → ModuleNotFoundError
- In a gateway session (Telegram), type
/new
- Click Always Approve
- Check
~/.hermes/config.yaml — destructive_slash_confirm is not present
- Check
~/.hermes/logs/errors.log — contains Failed to save config: No module named 'ruamel'
- Type
/new again — confirmation prompt still appears
Actual Behavior
- Button appears to work (no visible error)
- Gateway log says "User opted out of destructive slash confirm" (misleading)
- Config is never written
- User is stuck in a loop — can click "Always Approve" forever with no effect
Expected Behavior
Either:
- The dependency on
ruamel.yaml is enforced so it's never missing (preferred)
- OR the failure is surfaced to the user with a clear error message ("Failed to save preference — missing dependency: ruamel.yaml")
Additionally: the "opted out" log line should fire after the save succeeds, not before.
Environment
- Hermes Agent: installed via
pip install -e . in venv
- OS: Debian Linux
- Python: 3.11
- Gateway: Telegram
Related
Suggested Fix
Option A (preferred): Guard the import or add ruamel.yaml as a hard runtime check at startup — refuse to start or warn loudly if it's absent, since config persistence is critical.
Option B: Surface the error to the user. The _maybe_confirm_destructive_slash handler could return an error message if save_config_value returns False, or the exception handler could include the actual error in the reply: "⚠️ Failed to save preference: No module named 'ruamel'. Try: pip install ruamel.yaml"
Bug Description
The "Always Approve" button on destructive slash commands (
/new,/reset,/undo,/clear) silently fails to persist. The user clicks "Always Approve," the gateway logs "User opted out of destructive slash confirm," but theapprovals.destructive_slash_confirm: falsesetting never lands inconfig.yaml. On next/new, the confirmation prompt reappears. The user can click "Always Approve" dozens of times with zero effect.Root Cause
save_config_value()incli.pycallsatomic_roundtrip_yaml_update()fromutils.py, which importsruamel.yaml. Ifruamel.yamlis missing from the venv, theImportErroris caught and logged atERRORlevel — but never surfaced to the user:The gateway code at
gateway/run.py:12406-12420catches exceptions fromsave_config_valueand only logs awarning:The
infolog fires beforeatomic_roundtrip_yaml_updateactually executes (since it's called inside a try/except but the info log is outside the actual save), so the log says "opted out" regardless of whether the write succeeded. The user sees nothing wrong.Why
ruamel.yamlcan be missingruamel.yamlIS declared inpyproject.tomlas a required dependency. However, on installs that predateuvor installations done viapip install -e ., transitive dependencies may not be fully resolved. In this case the venv had 300+ packages butruamel.yamlwas absent.Steps to Reproduce
ruamel.yamlis NOT installed in the Hermes venv:/path/to/venv/bin/python -c "import ruamel.yaml"→ModuleNotFoundError/new~/.hermes/config.yaml—destructive_slash_confirmis not present~/.hermes/logs/errors.log— containsFailed to save config: No module named 'ruamel'/newagain — confirmation prompt still appearsActual Behavior
Expected Behavior
Either:
ruamel.yamlis enforced so it's never missing (preferred)Additionally: the "opted out" log line should fire after the save succeeds, not before.
Environment
pip install -e .in venvRelated
save_config_value) has a different bug (wrong file target on first run)/newstalling issue where "Always Approve" is the documented workaround (but that workaround doesn't actually work whenruamel.yamlis missing)Suggested Fix
Option A (preferred): Guard the import or add
ruamel.yamlas a hard runtime check at startup — refuse to start or warn loudly if it's absent, since config persistence is critical.Option B: Surface the error to the user. The
_maybe_confirm_destructive_slashhandler could return an error message ifsave_config_valuereturnsFalse, or the exception handler could include the actual error in the reply:"⚠️ Failed to save preference: No module named 'ruamel'. Try: pip install ruamel.yaml"