fix(gateway): pivot personality on the next turn, not the one after - #73708
Open
keniniclaw-design wants to merge 2 commits into
Open
fix(gateway): pivot personality on the next turn, not the one after#73708keniniclaw-design wants to merge 2 commits into
keniniclaw-design wants to merge 2 commits into
Conversation
/personality wrote config.yaml and set _ephemeral_system_prompt correctly, but the model kept replying in the previous persona's voice for one more turn: with a populated transcript, prior assistant turns act as style exemplars and outweigh the system prompt. Only visible on the second and later swaps in a process. On a cold gateway the history is empty, nothing to imitate, and the swap looks correct — which is why a restart appears to fix it. tui_gateway._apply_personality_to_session already handles this by injecting a pivot marker, and documents the cause: "without this, LLMs tend to continue the tone established by earlier messages in the transcript". The gateway path had no equivalent. Stage a note keyed by session_key and prepend it to the next user message, mirroring _pending_model_notes rather than writing into the transcript — history rows need display_kind bookkeeping, and an untagged marker is the class of bug that broke /retry. Registered in _CONVERSATION_SCOPED_STATE so a staged-but-unconsumed note cannot leak across a reset or resume into a new conversation.
teknium1
reviewed
Jul 30, 2026
teknium1
left a comment
Contributor
There was a problem hiding this comment.
Thanks for identifying a real gateway/TUI parity gap. Current main's gateway /personality path still only changes _ephemeral_system_prompt (gateway/slash_commands.py:2532-2549), while the TUI adds an explicit pivot marker (tui_gateway/server.py:5543-5558).
Problems
- The submitted
_pending_personality_notesdictionary needs reworking for current main. Conversation-scoped state is now structural inConversationState(gateway/session_state.py:90-128) and boundary clearing goes throughGatewayRunner._clear_conversation_scope()(gateway/run.py:21849-21863). - The note-consumption hunk predates the TurnRunner extraction; current model-note consumption is in
TurnRunner.run_sync(gateway/run.py:4896-4900). tests/gateway/test_personality_pivot_note.pyverifies staging and/new, but does not exercise the subsequent agent turn or verify one-shot model delivery and clean persisted user text.
Suggested changes
- Port the staged pivot into
ConversationStateand consume it inTurnRunner.run_syncbeside the existing model-switch note path. - Add an end-to-end gateway-turn regression asserting the pivot reaches the model-facing payload once without becoming a visible/persisted user message.
Automated hermes-sweeper review.
| @@ -2311,6 +2311,7 @@ def _own_policy_open_startup_violation(config) -> Optional[str]: | |||
| "_session_reasoning_overrides", | |||
Contributor
There was a problem hiding this comment.
Current main has moved conversation-scoped state into gateway/session_state.py:ConversationState, whose clear() is invoked by every boundary. Please port this pivot state there rather than adding another runner-level dictionary to the legacy registry.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
/personality wrote config.yaml and set _ephemeral_system_prompt correctly, but the model kept replying in the previous persona's voice for one more turn: with a populated transcript, prior assistant turns act as style exemplars and outweigh the system prompt.
Only visible on the second and later swaps in a process. On a cold gateway the history is empty, nothing to imitate, and the swap looks correct — which is why a restart appears to fix it.
tui_gateway._apply_personality_to_session already handles this by injecting a pivot marker, and documents the cause: "without this, LLMs tend to continue the tone established by earlier messages in the transcript". The gateway path had no equivalent.
Stage a note keyed by session_key and prepend it to the next user message, mirroring _pending_model_notes rather than writing into the transcript — history rows need display_kind bookkeeping, and an untagged marker is the class of bug that broke /retry.
Registered in _CONVERSATION_SCOPED_STATE so a staged-but-unconsumed note cannot leak across a reset or resume into a new conversation.
What does this PR do?
Related Issue
Fixes #
Type of Change
Changes Made
How to Test
Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/AFor New Skills
hermes --toolsets skills -q "Use the X skill to do Y"Screenshots / Logs