Files
cleveragents-core/features/tui_persona_state_coverage.feature
HAL9000 8b066b6721 fix(lsp): preserve injected registry/lifecycle + deconflict persona test steps
LspRuntime.__init__ and LspActorService.__init__ used ``x or Y()`` to
default the registry/runtime kwargs. LspRegistry defines __len__, so an
empty instance is falsy, and the OR silently discarded a caller-supplied
empty registry — making the constructor parameter unusable. Replace with
explicit ``is None`` checks so callers can inject collaborators at
construction time. The previous workaround in lsp_actor_service_steps.py
reached into ``service._runtime._registry`` to compensate; the steps now
inject via the public LspRuntime + LspActorService constructors, no
private-attribute access.

Also deconflict three behave AmbiguousStep collisions in the bundled TUI
persona work that prevented behave-parallel from registering any step
definitions (the unit_tests gate was aborting at load time):

  * tui_persona_cycle_steps.py duplicated the registry-setup and active-
    persona steps already defined in tui_persona_system_steps.py — drop
    the duplicates and let the system file own them.
  * tui_persona_state_coverage_steps.py / .feature shared
    ``the registry last persona should be set to "X"`` with
    tui_persona_cycle_steps.py while asserting on a different mock —
    rename the coverage step to ``the mock registry set_last_persona
    should have been called with "X"``.
  * lsp_actor_service_steps.py registered the "actor bindings are
    activated" step under @when only; the deactivate scenario uses it
    after a ``Given/And`` chain, so behave inherited Given and the step
    was undefined. Register the same handler under both @given and
    @when.

Reformat three files that ``ruff format --check`` flagged
(tui_persona_cycle_steps.py, tui_persona_state_coverage_steps.py via
the rename, tui/persona/state.py) so the lint gate goes green.

ISSUES CLOSED: #5663
2026-06-04 13:06:20 -04:00

69 lines
3.3 KiB
Gherkin

Feature: TUI Persona State Coverage
Scenarios that exercise previously uncovered code paths
in the tui/persona/state.py module.
Background:
Given a mock persona registry is prepared
Scenario: active_name resolves default when session is new
When I request the active name for a new session "sess-1"
Then the active name should be the resolved default persona name
Scenario: active_name returns cached name on second call
Given session "sess-2" already has active persona "analyst"
When I request the active name for a new session "sess-2"
Then the active name should be "analyst"
Scenario: active_persona falls back to default when registry returns None
Given session "sess-3" is bound to a persona name not in the registry
When I request the active persona for session "sess-3"
Then the persona should be the registry default
And the session should be rebound to the default persona name
Scenario: active_persona returns the looked-up persona when found
Given session "sess-4" is bound to a persona name that exists in the registry
When I request the active persona for session "sess-4"
Then the persona should be the one from the registry
Scenario: set_active_persona raises ValueError for unknown persona
When I try to set an unknown persona "ghost" for session "sess-5"
Then tpscov a ValueError should be raised with message containing "Unknown persona"
Scenario: set_active_persona sets and returns a known persona
When I set persona "coder" for session "sess-6"
Then the returned persona name should be "coder"
And session "sess-6" should have active persona "coder"
And the mock registry set_last_persona should have been called with "coder"
Scenario: set_active_persona skips preset init when session already has one
Given the preset for session "sess-6b" is already set to "turbo"
When I set persona "coder" for session "sess-6b"
Then the returned persona name should be "coder"
And the preset for session "sess-6b" should still be "turbo"
Scenario: current_preset returns default for a new session
When I request the current preset for new session "sess-7"
Then the current preset should be "default"
Scenario: cycle_preset returns default when persona has no argument presets
Given a persona with no argument presets is active for session "sess-8"
When I cycle the preset for session "sess-8"
Then the cycled preset should be "default"
Scenario: cycle_preset picks first preset when current is not in the list
Given a persona with presets "default,fast,slow" is active for session "sess-9"
And the current preset for session "sess-9" is "nonexistent"
When I cycle the preset for session "sess-9"
Then the cycled preset should be "default"
Scenario: cycle_preset advances to the next preset in the list
Given a persona with presets "default,fast,slow" is active for session "sess-10"
And the current preset for session "sess-10" is "default"
When I cycle the preset for session "sess-10"
Then the cycled preset should be "fast"
Scenario: effective_arguments delegates to persona with current preset
Given a persona with base arguments and presets is active for session "sess-11"
When I request the effective arguments for session "sess-11"
Then the effective arguments should merge base and preset overrides