hermes-bsd/tests/cli
Teknium 674fad1483
fix(goals): Ctrl+C during /goal loop auto-pauses the goal (#21888)
Reported: Ctrl+C during an active /goal loop felt like it did nothing —
the agent would interrupt the current turn, then immediately queue another
continuation and keep going until the session ended or the 20-turn budget
ran out.

Root cause: cli.py's _maybe_continue_goal_after_turn() ran in the finally:
block around self.chat(...) unconditionally. Whether the turn completed
normally, got interrupted, or returned an empty string, the judge ran on
whatever was in conversation_history and — because the judge is fail-open
— a "continue" verdict pushed another CONTINUATION_PROMPT onto
_pending_input. Ctrl+C was invisible to the hook.

Fix:
- chat() now captures result['interrupted'] onto self._last_turn_interrupted
  (resets to False at entry so early-returns don't leak prior state).
- _maybe_continue_goal_after_turn() checks the flag first: on interrupt,
  auto-pause via mgr.pause(reason='user-interrupted (Ctrl+C)') and print
  a one-liner pointing the user at /goal resume or /goal clear. No judge
  call, no continuation enqueued.
- Also added an empty-response guard that mirrors gateway/run.py's
  _handle_message logic (empty reply → transient failure → skip judging
  so we don't trip the consecutive-parse-failures backstop unnecessarily).

The goal stays in the DB as paused, so /goal resume recovers it after
the user has sorted out whatever made them cancel. /goal clear still
works as before for a full stop.

Tests: tests/cli/test_cli_goal_interrupt.py covers:
  - interrupted turn pauses + doesn't queue + judge is NOT called
  - paused goal is resumable
  - empty / whitespace / missing assistant reply skips judging
  - healthy turn still enqueues continuation / marks done
  - chat() resets _last_turn_interrupted at entry (anti-leak guard)

All 55 existing goal tests still pass.
2026-05-08 06:53:13 -07:00
..
__init__.py
test_branch_command.py
test_busy_input_mode_command.py
test_cli_approval_ui.py
test_cli_background_tui_refresh.py
test_cli_bracketed_paste_sanitizer.py
test_cli_browser_connect.py
test_cli_context_warning.py
test_cli_copy_command.py
test_cli_extension_hooks.py
test_cli_external_editor.py
test_cli_file_drop.py fix(cli): catch OSError in _resolve_attachment_path to prevent ENAMETOOLONG dropping long slash commands 2026-05-06 06:34:48 -07:00
test_cli_force_redraw.py fix(cli): recover classic CLI output after resize 2026-05-06 04:20:54 -07:00
test_cli_goal_interrupt.py fix(goals): Ctrl+C during /goal loop auto-pauses the goal (#21888) 2026-05-08 06:53:13 -07:00
test_cli_image_command.py
test_cli_init.py fix(cli): submit LF enter in thin PTYs (#20896) 2026-05-06 13:51:13 -07:00
test_cli_interrupt_subagent.py
test_cli_loading_indicator.py
test_cli_markdown_rendering.py fix(cli): preserve Windows hidden-dir paths in markdown 2026-05-04 05:04:36 -07:00
test_cli_mcp_config_watch.py
test_cli_new_session.py fix(cli,gateway): surface title errors from /new <name> 2026-05-04 03:14:50 -07:00
test_cli_prefix_matching.py
test_cli_preloaded_skills.py
test_cli_provider_resolution.py
test_cli_reload_skills.py
test_cli_retry.py
test_cli_save_config_value.py
test_cli_secret_capture.py
test_cli_shutdown_memory_messages.py
test_cli_skin_integration.py
test_cli_status_bar.py refactor: replace 'cmp' text with 🗜️ emoji in status bar 2026-05-07 05:27:45 -07:00
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_compress_focus.py
test_cprint_bg_thread.py fix(cli): recover classic CLI output after resize 2026-05-06 04:20:54 -07:00
test_cwd_env_respect.py fix(cli): local backend CLI always uses launch directory, stops .env sync of TERMINAL_CWD (#19334) 2026-05-04 11:36:19 +05:30
test_fast_command.py fix(anthropic): restrict fast mode to Opus 4.6 (Anthropic API contract) 2026-05-04 06:23:52 -07:00
test_gquota_command.py
test_manual_compress.py fix(cli): persist manual compress handoff 2026-05-05 04:42:48 -07:00
test_personality_none.py
test_quick_commands.py
test_reasoning_command.py test: pin per-turn reasoning extraction semantics 2026-05-05 05:00:05 -07:00
test_resume_display.py fix(cli): recover classic CLI output after resize 2026-05-06 04:20:54 -07:00
test_save_conversation_location.py
test_session_boundary_hooks.py
test_stream_delta_think_tag.py
test_surrogate_sanitization.py
test_tool_progress_scrollback.py
test_worktree.py
test_worktree_security.py