Skip to content

fix(acp): clear stale interrupted prompt when a new turn starts - #519

Open
hashbender wants to merge 1 commit into
mainfrom
mirror/pr-56624
Open

fix(acp): clear stale interrupted prompt when a new turn starts#519
hashbender wants to merge 1 commit into
mainfrom
mirror/pr-56624

Conversation

@hashbender

Copy link
Copy Markdown
Owner

What does this PR do?

Fixes a state-machine bug in the ACP adapter where a /steer on an idle session can resurrect a prompt the user cancelled and moved on from.

state.interrupted_prompt_text powers the "Zed-interrupt salvage" feature (replay an interrupted prompt when /steer arrives right after a client cancel, PR NousResearch#18258). But it is:

  • set only in cancel() — when a turn is actively running, and
  • cleared only inside the /steer salvage block.

No other path clears it. So this sequence leaks a stale value:

  1. Session is running prompt P1 = "refactor the auth module". User hits ESC → cancel() stores interrupted_prompt_text = "refactor the auth module". Turn ends.
  2. User sends an ordinary prompt P2 = "what's the weather". It runs to completion. interrupted_prompt_text is still "refactor the auth module" — the normal turn never cleared it.
  3. User later types /steer be concise on the idle session. The salvage block sees the stale value as truthy and runs:
    "refactor the auth module\n\nUser correction/guidance after interrupt: be concise" as a real LLM turn.

The user expected to nudge the current (nonexistent) turn; instead the agent silently re-executes an abandoned task from two turns ago.

Fix: clear interrupted_prompt_text at the turn-start transition (where is_running flips to True), so starting any real turn drops the stale salvage buffer. The /steer salvage path already consumes and clears the field before this point, so legitimate immediate-salvage (steer directly after a client cancel, with no intervening turn) is unaffected.

Related Issue

Fixes #

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • acp_adapter/server.py — in prompt(), set state.interrupted_prompt_text = "" in the is_running = True turn-start transition.
  • tests/acp_adapter/test_acp_commands.pytest_acp_normal_turn_clears_stale_interrupted_prompt: a running-cancel value is cleared by a completed normal turn, and a subsequent /steer runs only the steer text.

How to Test

  1. scripts/run_tests.sh tests/acp_adapter/test_acp_commands.py -q — 7 tests pass, including the existing salvage test test_acp_steer_after_zed_interrupt_replays_interrupted_prompt_with_guidance.
  2. Proof the fix is load-bearing: revert the acp_adapter/server.py hunk and rerun -k clears_stale → the new test fails (interrupted_prompt_text still holds the abandoned prompt, and /steer resurrects it); restore → it passes.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(acp):)
  • I searched for existing PRs to make sure this isn't a duplicate (searched interrupted_prompt_text — none; open PR fix(acp): ignore idle cancel before next prompt NousResearch/hermes-agent#50461 touches idle-cancel cancel_event poisoning, a different field/path, and leaves this bug)
  • My PR contains only changes related to this fix
  • I've run the test suite and all tests pass
  • I've added tests for my changes
  • I've tested on my platform: macOS 15

Documentation & Housekeeping

  • Documentation (README, docs/, docstrings) — N/A (inline comment explains the clear)
  • cli-config.yaml.example — N/A
  • CONTRIBUTING.md / AGENTS.md — N/A
  • Cross-platform impact — N/A (scripts/check-windows-footguns.py clean)
  • Tool descriptions/schemas — N/A

Mirror-of: NousResearch#56624
NousResearch#56624

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant