From 8d57b9e5c5b0da3a2ce2284d6c4189cd91ceebf8 Mon Sep 17 00:00:00 2001 From: CleverThis Date: Sun, 19 Apr 2026 11:48:05 +0000 Subject: [PATCH 1/2] test(tui): add failing behave scenario for set_active_persona preset reset bug Implemented TDD scaffolding for issue #10500: - Added a new Behave feature: features/tdd_persona_state_set_active_persona_reset.feature - Contains two scenarios tagged @tdd_issue @tdd_issue_10500 @tdd_expected_fail - Verifies that PersonaState.set_active_persona() resets the preset to "default" when switching personas - Tests are intentionally failing to demonstrate TDD; the @tdd_expected_fail tag inverts results so CI passes - Added step definitions: features/steps/tdd_persona_state_set_active_persona_reset_steps.py - Implements the steps required by the feature to exercise set_active_persona() and preset handling - Rationale: The bug is that set_active_persona() only initializes the preset to "default" when there is no preset; if a non-default preset exists (e.g., "turbo"), switching personas leaves the preset unchanged instead of resetting to "default" Files added provide the failing test scenarios and their wiring, guiding the eventual fix for resetting presets on persona switches. --- ...na_state_set_active_persona_reset_steps.py | 110 ++++++++++++++++++ ...ona_state_set_active_persona_reset.feature | 23 ++++ 2 files changed, 133 insertions(+) create mode 100644 features/steps/tdd_persona_state_set_active_persona_reset_steps.py create mode 100644 features/tdd_persona_state_set_active_persona_reset.feature diff --git a/features/steps/tdd_persona_state_set_active_persona_reset_steps.py b/features/steps/tdd_persona_state_set_active_persona_reset_steps.py new file mode 100644 index 000000000..e2b1d821b --- /dev/null +++ b/features/steps/tdd_persona_state_set_active_persona_reset_steps.py @@ -0,0 +1,110 @@ +"""Step definitions for tdd_persona_state_set_active_persona_reset.feature. + +These steps capture bug #10500: PersonaState.set_active_persona() does not +reset the active preset to "default" when switching to a different persona. + +The current implementation only initialises the preset when the session has +no preset entry at all. If the session already has a non-default preset +(e.g. because the user cycled through presets), switching persona leaves +that preset unchanged instead of resetting it to "default". + +Expected (correct) behaviour: + state.set_active_persona(session_id, new_persona) + → state.current_preset(session_id) == "default" + +Actual (buggy) behaviour: + state.set_active_persona(session_id, new_persona) + → state.current_preset(session_id) == +""" + +from unittest.mock import MagicMock + +from behave import given, then, when + +from cleveragents.tui.persona.schema import Persona +from cleveragents.tui.persona.state import PersonaState + +# --------------------------------------------------------------------------- +# Helpers +# --------------------------------------------------------------------------- + + +def _make_persona(name, actor="ns/actor"): + """Build a minimal real Persona for testing.""" + return Persona(name=name, actor=actor) + + +def _make_mock_registry(personas): + """Return a MagicMock that quacks like PersonaRegistry.""" + registry = MagicMock() + default = next(iter(personas.values())) + registry.ensure_default.return_value = default + registry.get_last_persona.return_value = None + registry.set_last_persona = MagicMock() + + def _get(name): + return personas.get(name) + + registry.get.side_effect = _get + return registry + + +# --------------------------------------------------------------------------- +# Given steps +# --------------------------------------------------------------------------- + + +@given( + 'a session "{session_id}" with persona "{persona_name}"' + ' and a non-default preset "{preset_name}"' +) +def step_session_with_persona_and_preset( + context, session_id, persona_name, preset_name +): + """Set up a session that already has a non-default preset.""" + coder = _make_persona("coder", actor="ns/coder") + analyst = _make_persona("analyst", actor="ns/analyst") + registry = _make_mock_registry({"coder": coder, "analyst": analyst}) + context.state = PersonaState( + registry=registry, + active_by_session={session_id: persona_name}, + preset_by_session={session_id: preset_name}, + ) + + +@given('the preset for session "{session_id}" has been updated to "{preset_name}"') +def step_update_preset(context, session_id, preset_name): + """Directly update the preset for a session (simulates cycling).""" + context.state.preset_by_session[session_id] = preset_name + + +# --------------------------------------------------------------------------- +# When steps +# --------------------------------------------------------------------------- + + +@when('I switch session "{session_id}" to persona "{persona_name}"') +def step_switch_persona(context, session_id, persona_name): + """Call set_active_persona to switch the active persona.""" + context.state.set_active_persona(session_id, persona_name) + + +# --------------------------------------------------------------------------- +# Then steps +# --------------------------------------------------------------------------- + + +@then('the preset for session "{session_id}" should be "{expected_preset}"') +def step_verify_preset(context, session_id, expected_preset): + """Assert that the preset has been reset to the expected value. + + This assertion will FAIL while bug #10500 is unfixed because + set_active_persona() does not reset an existing preset to "default". + The @tdd_expected_fail tag inverts this failure so CI passes. + """ + actual = context.state.current_preset(session_id) + assert actual == expected_preset, ( + f"Bug #10500: expected preset '{expected_preset}' after switching persona " + f"but got '{actual}'. set_active_persona() does not reset an existing " + f"non-default preset to 'default'." + ) diff --git a/features/tdd_persona_state_set_active_persona_reset.feature b/features/tdd_persona_state_set_active_persona_reset.feature new file mode 100644 index 000000000..40135c104 --- /dev/null +++ b/features/tdd_persona_state_set_active_persona_reset.feature @@ -0,0 +1,23 @@ +@tdd_issue @tdd_issue_10500 +Feature: TDD Bug #10500 — PersonaState.set_active_persona() does not reset preset + As a TUI user + I want switching to a different persona to reset the active preset to "default" + So that I do not accidentally carry over a preset from a previous persona + + When a session has cycled to a non-default preset and the user then switches + to a different persona, the preset should be reset to "default". The current + implementation only initialises the preset when the session has no preset at + all; it leaves an existing non-default preset unchanged. + + @tdd_issue @tdd_issue_10500 @tdd_expected_fail + Scenario: Bug #10500 - switching persona resets preset to default + Given a session "sess-reset-1" with persona "coder" and a non-default preset "turbo" + When I switch session "sess-reset-1" to persona "analyst" + Then the preset for session "sess-reset-1" should be "default" + + @tdd_issue @tdd_issue_10500 @tdd_expected_fail + Scenario: Bug #10500 - switching persona resets preset even after multiple cycles + Given a session "sess-reset-2" with persona "coder" and a non-default preset "fast" + And the preset for session "sess-reset-2" has been updated to "slow" + When I switch session "sess-reset-2" to persona "analyst" + Then the preset for session "sess-reset-2" should be "default" -- 2.52.0 From 4ceed5e55a6c8405b940c08c6826d06f7b8abb8d Mon Sep 17 00:00:00 2001 From: HAL9000 Date: Mon, 27 Apr 2026 01:06:48 +0000 Subject: [PATCH 2/2] tests(tui): move TDD persona feature and steps under features/tui/persona; correct tags to 10499 --- .../tdd_persona_state_set_active_persona_reset_steps.py | 4 ++-- .../tdd_persona_state_set_active_persona_reset.feature | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) rename features/{ => tui/persona}/steps/tdd_persona_state_set_active_persona_reset_steps.py (96%) rename features/{ => tui/persona}/tdd_persona_state_set_active_persona_reset.feature (90%) diff --git a/features/steps/tdd_persona_state_set_active_persona_reset_steps.py b/features/tui/persona/steps/tdd_persona_state_set_active_persona_reset_steps.py similarity index 96% rename from features/steps/tdd_persona_state_set_active_persona_reset_steps.py rename to features/tui/persona/steps/tdd_persona_state_set_active_persona_reset_steps.py index e2b1d821b..7771f9115 100644 --- a/features/steps/tdd_persona_state_set_active_persona_reset_steps.py +++ b/features/tui/persona/steps/tdd_persona_state_set_active_persona_reset_steps.py @@ -10,11 +10,11 @@ that preset unchanged instead of resetting it to "default". Expected (correct) behaviour: state.set_active_persona(session_id, new_persona) - → state.current_preset(session_id) == "default" + -> state.current_preset(session_id) == "default" Actual (buggy) behaviour: state.set_active_persona(session_id, new_persona) - → state.current_preset(session_id) == + -> state.current_preset(session_id) == """ from unittest.mock import MagicMock diff --git a/features/tdd_persona_state_set_active_persona_reset.feature b/features/tui/persona/tdd_persona_state_set_active_persona_reset.feature similarity index 90% rename from features/tdd_persona_state_set_active_persona_reset.feature rename to features/tui/persona/tdd_persona_state_set_active_persona_reset.feature index 40135c104..394e56765 100644 --- a/features/tdd_persona_state_set_active_persona_reset.feature +++ b/features/tui/persona/tdd_persona_state_set_active_persona_reset.feature @@ -1,4 +1,4 @@ -@tdd_issue @tdd_issue_10500 +@tdd_issue @tdd_issue_10499 Feature: TDD Bug #10500 — PersonaState.set_active_persona() does not reset preset As a TUI user I want switching to a different persona to reset the active preset to "default" @@ -9,13 +9,13 @@ Feature: TDD Bug #10500 — PersonaState.set_active_persona() does not reset pre implementation only initialises the preset when the session has no preset at all; it leaves an existing non-default preset unchanged. - @tdd_issue @tdd_issue_10500 @tdd_expected_fail + @tdd_issue @tdd_issue_10499 @tdd_expected_fail Scenario: Bug #10500 - switching persona resets preset to default Given a session "sess-reset-1" with persona "coder" and a non-default preset "turbo" When I switch session "sess-reset-1" to persona "analyst" Then the preset for session "sess-reset-1" should be "default" - @tdd_issue @tdd_issue_10500 @tdd_expected_fail + @tdd_issue @tdd_issue_10499 @tdd_expected_fail Scenario: Bug #10500 - switching persona resets preset even after multiple cycles Given a session "sess-reset-2" with persona "coder" and a non-default preset "fast" And the preset for session "sess-reset-2" has been updated to "slow" -- 2.52.0