Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

fix: clear stale blocked status when approval prompt disappears#6

Open
bloodcarter wants to merge 1 commit intoaannoo:mainfrom
bloodcarter:fix/stop-hook-nonblocking
Open

fix: clear stale blocked status when approval prompt disappears#6
bloodcarter wants to merge 1 commit intoaannoo:mainfrom
bloodcarter:fix/stop-hook-nonblocking

Conversation

@bloodcarter
Copy link

Problem

When a PTY agent displays a permission/approval prompt, the delivery loop correctly sets the agent's status to ■ blocked in the database. However, when the user approves the prompt and the agent resumes work, the status stays stuck as "blocked" until the agent's entire turn completes and the Stop hook fires.

Expected behavior

After a user approves a permission prompt, hcom list should show the agent as ▶ active or ◉ listening within a few seconds.

Actual behavior

hcom list continues to show ■ blocked for the duration of the agent's turn (potentially minutes), even though:

  • The approval prompt is no longer visible
  • The agent is actively processing (not actually blocked)

This can mislead orchestrators into attempting to unblock an agent that isn't stuck, potentially disrupting its work.

Root cause

In the delivery loop's gate-blocked branch (src/delivery.rs), when screen.approval goes from true to false:

  1. The approval detection at line 914 stops setting "blocked" (correct)
  2. The gate still blocks with reason = "not_idle" because the agent is actively producing output
  3. The existing stability recovery (line 938+) only checks if status == ST_ACTIVE — it never matches "blocked"
  4. The Stop hook sets "listening" but only fires after the turn completes
  5. No other code path clears "blocked" during this window

Result: status is stuck as "blocked" from approval-clear until turn-end.

Fix

Added an immediate recovery check in the gate-blocked branch: when approval_showing is false, gate.reason is "not_idle", and the DB status is still "blocked", clear it to "listening" right away. This runs before the existing ST_ACTIVE stability recovery.

} else if gate.reason == "not_idle" {
    // Immediate recovery: if approval just cleared but DB still says blocked,
    // clear it now — no need to wait for stability timeout.
    match db.get_status(&current_name) {
        Ok(Some((status, _))) if status == "blocked" => {
            if let Err(e) = db.set_status(
                &current_name,
                "listening",
                "pty:approval_cleared",
            ) { ... }
            attempt = 0;
            continue;
        }
        _ => {}
    }
    // ... existing ST_ACTIVE stability recovery follows

Why this is safe

  • No false positives: The only code path that sets status to "blocked" is the approval detection at line 914. If status is "blocked", it was set by approval.
  • No race condition: screen.approval is a one-way latch cleared only by user input, and clear_approval() also clears the output buffer to prevent re-triggering from stale OSC9 bytes.
  • No ping-pong: Once approval clears, a new OSC9 pattern from the agent would be required to re-trigger — which can't happen mid-turn.
  • Affects all PTY agent types (Claude, Gemini, Codex) since this is in the shared delivery loop.

Verification

  • Spawned a test agent, triggered permission prompts, confirmed status clears within ~2 seconds of approval (previously stuck for the full turn duration)
  • Code analysis independently verified by two separate reviewers tracing all status transitions

🤖 Generated with Claude Code

When a PTY-detected approval prompt is resolved, the delivery loop's
recovery branch only checked for ST_ACTIVE status, skipping recovery
when status was ST_BLOCKED. This left agents showing "blocked" in
hcom list even after the prompt was approved.

Add immediate blocked-to-listening transition when approval_showing
goes false but DB still says blocked.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.

1 participant