From fcef6ba1af2f777ee690da6fe85cf6ef729db5e2 Mon Sep 17 00:00:00 2001 From: nesquena-hermes Date: Fri, 7 Aug 2026 20:05:49 -0700 Subject: [PATCH] Release exp-v0.52.175: identical-prompt retry settlement regression (#6631) (#6845) * test: pin identical-prompt retry settlement * Release exp-v0.52.175: two-direction regression for identical-prompt retry settlement (#6631) --------- Co-authored-by: nesquena-hermes --- CHANGELOG.md | 2 + ...st_issue6571_identical_retry_settlement.py | 79 +++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 tests/test_issue6571_identical_retry_settlement.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 56f424d8..d98ffd62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ - **Internal: added regression coverage for the empty-`tool_calls` drop on the metadata-restoration mirror path.** `_api_safe_message_positions()` must apply the same `tool_calls: []` drop as the main API sanitizer (#5737) so metadata restoration never treats a `tool_calls: []` row as a distinct message; a new test pins that empty arrays lose the key while populated tool-call chains (and their tool results) survive untouched. Test-only, no production change. Thanks @webtecnica. (#6803, #6796) +- **Internal: added a two-direction regression for identical-prompt retry settlement.** The active-turn ownership repair that resolves #6571 (settlement materializes the exact pending turn before checking for a terminal assistant answer) had no issue-specific coverage because the original reproduction omitted the runtime turn identity. A new test pins both directions through the real `_merged_transcript_lacks_final_assistant_answer()`: a successful identical-prompt retry keeps its terminal answer (not a `no_response`), while an otherwise-identical retry with no terminal answer still qualifies as a genuine failure. Test-only, no production change (a mutation bite — nulling the merge's `active_turn_identity` provenance — flips the successful case red, confirming the guard is live). (#6631, #6571) + - **The busy-time send behavior is now called "Default message mode," and new installs default to Steer.** The Settings → Preferences control formerly labeled "Busy input mode" is renamed to "Default message mode," and a fresh install now defaults to **Steer** (inject a mid-turn correction without interrupting) instead of Queue. Your existing choice is preserved — if you ever saved settings, your current mode (Queue/Interrupt/Steer) is migrated as-is and unchanged; only never-configured installs pick up the new Steer default. The saved preference still survives a reload or a brief server outage (the localStorage mirror from the previous release is intact). Thanks @rodboev. (#5162, #5145) ### Added diff --git a/tests/test_issue6571_identical_retry_settlement.py b/tests/test_issue6571_identical_retry_settlement.py new file mode 100644 index 00000000..b98b00b7 --- /dev/null +++ b/tests/test_issue6571_identical_retry_settlement.py @@ -0,0 +1,79 @@ +"""Regression coverage for #6571 identical-prompt retry settlement.""" + +from __future__ import annotations + +from api import streaming + + +PROMPT = "Apply the two requested configuration updates." + + +def _previous_turns(): + previous_display = [ + {"role": "user", "content": "Earlier task", "id": 1}, + {"role": "assistant", "content": "Earlier answer", "id": 2}, + {"role": "user", "content": PROMPT, "id": 10}, + ] + return previous_display, previous_display[:2] + + +def _active_turn_identity(): + return { + "token": "direct-stream:2", + "text": PROMPT, + "timestamp": 2.0, + "source": "webui", + "attachments": [], + "current_turn_user_idx": 2, + "turn_id": "turn-2", + } + + +def _lacks_final_answer(result_messages): + previous_display, previous_context = _previous_turns() + return streaming._merged_transcript_lacks_final_assistant_answer( + previous_display, + previous_context, + result_messages, + PROMPT, + source="webui", + drop_replayed_assistant=False, + active_turn_identity=_active_turn_identity(), + ) + + +def test_successful_identical_prompt_retry_keeps_terminal_answer(): + _previous_display, previous_context = _previous_turns() + result_messages = previous_context + [ + {"role": "user", "content": PROMPT, "id": 11}, + {"role": "assistant", "content": "Working on it.", "id": 12}, + { + "role": "tool", + "content": "update succeeded", + "tool_call_id": "tool-1", + "id": 13, + }, + { + "role": "assistant", + "content": "Both changes were applied and verified.", + "id": 14, + }, + ] + + assert _lacks_final_answer(result_messages) is False + + +def test_failed_identical_prompt_retry_still_lacks_terminal_answer(): + _previous_display, previous_context = _previous_turns() + result_messages = previous_context + [ + {"role": "user", "content": PROMPT, "id": 11}, + {"role": "assistant", "content": "Working on it.", "id": 12}, + { + "role": "tool", + "content": "update failed", + "tool_call_id": "tool-1", + "id": 13, + }, + ] + + assert _lacks_final_answer(result_messages) is True