hermes-bsd/tests/cli
kshitijk4poor 5cbc3fbdcc fix(cli): /yolo in chat must enable session bypass, not just set env var
The CLI's in-chat `/yolo` toggle mutated `os.environ["HERMES_YOLO_MODE"]`
but had no effect because `tools/approval.py:_YOLO_MODE_FROZEN` captures
that env var once at module-import time (a deliberate security floor that
keeps prompt-injected skills from flipping the bypass mid-run). By the
time the user reaches `/yolo` in a running CLI session, `tools.approval`
has already been imported, so the env flip after that is a silent no-op.

Result: `/yolo` advertised "⚠ YOLO" in the status bar while every
dangerous command still hit the approval prompt or got denied.  Only
`hermes --yolo` (set before tool imports), `HERMES_YOLO_MODE=1 hermes ...`,
and `hermes config set approvals.mode off` actually bypassed.

This patches the CLI to match what the gateway and TUI `/yolo` handlers
already do, plus mirrors the TUI's session-rename YOLO transfer:

* `_toggle_yolo()` now calls `enable_session_yolo(self.session_id)` /
  `disable_session_yolo(self.session_id)` instead of touching the env
  var.  Matches `gateway/run.py:_handle_yolo_command` and the
  `tui_gateway/server.py` key=="yolo" branch.
* Around each `run_conversation()` call, `run_agent()` now binds
  `set_current_session_key(self.session_id)` so
  `tools.approval.is_current_session_yolo_enabled()` resolves against
  the same key the toggle writes under, and resets it in `finally` so
  reused threads don't see stale identity.  Matches the
  `tui_gateway/server.py` and `gateway/platforms/api_server.py` binding
  pattern.
* New `_transfer_session_yolo()` helper carries YOLO bypass state
  across `self.session_id` reassignments — `/branch` forking into a
  new session id and the auto-compression sync that rotates into a
  fresh continuation session id.  Without this, the same UX failure
  mode the rest of this fix addresses (silent `/yolo` no-op) would
  reappear after a single `/branch` or auto-compression event.
  Mirrors `tui_gateway/server.py` ~line 1297-1305.
* New `_is_session_yolo_active()` helper replaces the two
  `bool(os.getenv("HERMES_YOLO_MODE"))` reads in the status-bar
  builders, so the badge reflects the actual bypass state.  Uses
  `getattr(self, "session_id", None)` so status-bar test fixtures
  that bypass `__init__` via `HermesCLI.__new__(HermesCLI)` don't
  trip `AttributeError` (the builders swallow exceptions silently
  and lose every field after the failure).  Still honors
  `_YOLO_MODE_FROZEN` so `hermes --yolo` keeps lighting it up.

The `_YOLO_MODE_FROZEN` security freeze is preserved — env-var-based
opt-in still only works when set before process start, which is the
documented contract for `--yolo` / `HERMES_YOLO_MODE`.

Closes #33925
2026-05-28 12:10:21 -07:00
..
__init__.py
test_bracketed_paste_timeout.py fix(cli): bracketed-paste timeout prevents permanent input freeze (#16263) 2026-05-25 05:07:11 -07:00
test_branch_command.py fix(cli): synchronize HERMES_SESSION_ID across environment and contextvar during session switches 2026-05-23 17:46:55 -07:00
test_busy_input_mode_command.py
test_cli_approval_ui.py
test_cli_background_status_indicator.py feat(cli): show live background terminal-process count in status bar (#32061) 2026-05-25 05:35:02 -07:00
test_cli_background_tui_refresh.py
test_cli_bracketed_paste_sanitizer.py
test_cli_browser_connect.py test(cli): cover Brave binary CDP launch detection 2026-05-19 22:34:05 -07:00
test_cli_context_warning.py fix(context): align guidance with 64k minimum 2026-05-24 23:23:12 -07:00
test_cli_copy_command.py
test_cli_extension_hooks.py
test_cli_external_editor.py
test_cli_file_drop.py
test_cli_force_redraw.py
test_cli_goal_interrupt.py
test_cli_image_command.py
test_cli_init.py remove Vercel AI Gateway and Vercel Sandbox (#33067) 2026-05-27 00:43:32 -07:00
test_cli_insights_command.py
test_cli_interrupt_subagent.py
test_cli_light_mode.py
test_cli_loading_indicator.py
test_cli_markdown_rendering.py fix(cli): preserve cron asterisks in strip mode 2026-05-18 20:08:36 -07:00
test_cli_mcp_config_watch.py
test_cli_new_session.py fix(cli): synchronize HERMES_SESSION_ID across environment and contextvar during session switches 2026-05-23 17:46:55 -07:00
test_cli_prefix_matching.py
test_cli_preloaded_skills.py
test_cli_provider_resolution.py test(auth): update entitlement CI expectations 2026-05-28 00:19:31 -07:00
test_cli_reload_skills.py
test_cli_resume_command.py test(cli,gateway): cover bracket-stripping and gateway session-ID lookup 2026-05-25 01:33:32 -07:00
test_cli_retry.py
test_cli_save_config_value.py
test_cli_secret_capture.py fix(cli): show masked feedback for secret prompts 2026-05-25 01:20:33 -07:00
test_cli_shift_enter_newline.py
test_cli_shutdown_memory_messages.py
test_cli_skin_integration.py
test_cli_status_bar.py
test_cli_status_command.py
test_cli_steer_busy_path.py
test_cli_terminal_response_sanitizer.py
test_cli_tools_command.py
test_cli_user_message_preview.py
test_cli_yolo_toggle.py fix(cli): /yolo in chat must enable session bypass, not just set env var 2026-05-28 12:10:21 -07:00
test_compress_focus.py
test_cprint_bg_thread.py
test_ctrl_enter_newline.py
test_cwd_env_respect.py
test_destructive_slash_confirm.py fix(cli): add inline --yes/now skip for destructive slash commands (#30768) 2026-05-24 16:13:03 -07:00
test_destructive_slash_inline_skip_e2e.py fix(cli): add inline --yes/now skip for destructive slash commands (#30768) 2026-05-24 16:13:03 -07:00
test_exit_delete_session.py
test_exit_summary_resume_hint.py test(cli): cover exit resume hint -p flag across profiles 2026-05-25 01:41:54 -07:00
test_fast_command.py
test_gquota_command.py
test_manual_compress.py
test_personality_none.py
test_prompt_text_input_thread_safety.py
test_quick_commands.py
test_reasoning_command.py chore: ruff auto-fix PLR6201 resweep — tuple → set in membership tests (#27355) 2026-05-17 02:29:41 -07:00
test_resume_display.py test(cli): reconcile resume-recap tests with skip-tool-only default and compression-chain helper 2026-05-24 15:36:37 -07:00
test_resume_quiet_stderr.py test(cli): cover quiet-mode resume status lines routed to stderr 2026-05-25 01:47:12 -07:00
test_save_conversation_location.py
test_session_boundary_hooks.py
test_slash_command_interrupt.py test(cli): cover KeyboardInterrupt guard around slash command dispatch 2026-05-25 05:06:06 -07:00
test_slash_confirm_windows.py fix(cli): keep destructive slash modal on Linux 2026-05-27 05:57:01 -07:00
test_stream_delta_think_tag.py
test_surrogate_sanitization.py
test_tool_progress_scrollback.py fix(cli): decouple tool_progress=verbose from global DEBUG logging (#31379) 2026-05-24 02:19:20 -07:00
test_update_command.py feat(cli): add /update slash command to CLI and TUI (#23854) 2026-05-18 20:10:46 -04:00
test_worktree.py 🐛 fix(cli): handle missing remote tracking refs 2026-05-19 14:50:42 -07:00
test_worktree_security.py