Skip to content

fix: sync ActiveTurnState.auto_approve when remember checkbox is set#2041

Closed
gaord wants to merge 1 commit into
Hmbown:mainfrom
gaord:fix/remember-auto-approve-active-turn
Closed

fix: sync ActiveTurnState.auto_approve when remember checkbox is set#2041
gaord wants to merge 1 commit into
Hmbown:mainfrom
gaord:fix/remember-auto-approve-active-turn

Conversation

@gaord
Copy link
Copy Markdown
Contributor

@gaord gaord commented May 25, 2026

Problem

When a user checks "Remember for this tool" and approves a tool call, subsequent tool calls within the same turn still require manual approval. The remember checkbox appears non-functional.

Root Cause

remember_thread_auto_approve() only persists thread.auto_approve = true to disk, but does not update the in-memory ActiveTurnState.auto_approve for the current turn.

When the next ApprovalRequired event arrives, active_turn_flags() reads from ActiveTurnState (which is still false), so approval_decision() returns DenyTool and the approval dialog pops up again.

The persisted thread.auto_approve only takes effect when the next turn starts (which creates a fresh ActiveTurnState from the stored thread record).

Fix

In remember_thread_auto_approve(), after persisting the thread record, also update the current turn's ActiveTurnState.auto_approve to true:

{
    let mut active = self.active.lock().await;
    if let Some(state) = active.engines.get_mut(thread_id) {
        if let Some(turn) = state.active_turn.as_mut() {
            turn.auto_approve = true;
        }
    }
}

This ensures active_turn_flags() returns the correct value immediately, and approval_decision() auto-approves remaining tool calls within the current turn.

Testing

  • Existing test approval_required_remember_flips_thread_auto_approve continues to pass (it only verifies persisted thread.auto_approve).
  • The fix adds the missing in-memory sync that the existing test does not cover.

When a user checks 'Remember for this tool' and approves a tool call,
remember_thread_auto_approve() only persisted thread.auto_approve to disk
but did not update the in-memory ActiveTurnState for the current turn.
This meant subsequent tool calls within the same turn would still require
manual approval, making the remember checkbox appear non-functional.

Now remember_thread_auto_approve() also sets
ActiveTurnState.auto_approve = true, so active_turn_flags() returns
the correct value and the approval_decision() logic auto-approves
remaining tool calls in the current turn.
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces logic to update the in-memory state of an active turn to enable auto-approval. The review feedback identifies a logic flaw where early returns in the function prevent this update from occurring if the persisted state is already set to auto-approve, suggesting a refactor of the control flow to ensure consistent synchronization.

Comment on lines +869 to +876
{
let mut active = self.active.lock().await;
if let Some(state) = active.engines.get_mut(thread_id) {
if let Some(turn) = state.active_turn.as_mut() {
turn.auto_approve = true;
}
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The in-memory synchronization logic added here is shadowed by the early return at line 857. If thread.auto_approve is already true in the persisted record (which can happen if a turn was started with an explicit auto_approve = false override), the function returns before reaching this block. To ensure the current turn is always updated when the user selects "Remember", the persistence logic should be decoupled from the in-memory update, and the early returns at lines 853 and 856 should be refactored to allow the sync to proceed even if the persisted state is already up-to-date or if loading the thread fails. Additionally, consider adding a test case that verifies in-memory sync when a turn override is present.

@Hmbown
Copy link
Copy Markdown
Owner

Hmbown commented May 25, 2026

Thanks @gaord — I harvested this fix into #2047 and preserved your commit author. I also added a focused regression assertion that verifies remember=true updates both the persisted thread policy and the active turn flags used by subsequent approvals. Local verification on #2047 includes cargo test -p codewhale-tui approval_required_remember_flips_thread_auto_approve --locked and cargo check -p codewhale-tui --locked. I’ll leave this PR open until #2047 lands, then it can be closed as superseded.

@Hmbown
Copy link
Copy Markdown
Owner

Hmbown commented May 25, 2026

Superseded by #2047, which merged as a6bd5ac. Thanks again @gaord — your fix was harvested with author credit preserved, and #2047 added the active-turn regression assertion before landing.

@Hmbown Hmbown closed this May 25, 2026
Hmbown added a commit that referenced this pull request May 25, 2026
- Added: voice input, RLM session objects (#2047)
- Fixed: slash-command recovery, Remember auto-approve sync (#2047, #2041)
- Thanks: @gaord (Ben Gao) for active-turn auto-approve fix
- Synced root and tui CHANGELOGs
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.

2 participants