Skip to content

Settling a thread within 2s of its run finishing still shows the "Thread completed" toast for it #26886

Open

Description

@rcnsh

What happened

If I click Settle too quickly after an agent finishes responding, the "Thread completed" toast still pops up for the thread I just settled.

Diagnosis

The completion notification waits out WORKING_EXIT_GRACE_MS (2s) before it fires. The wait was added for #24477, so that a thread doesn't notify between orchestrator runs. createThreadNotificationGate (apps/web/src/components/ThreadNotificationCoordinator.logic.ts) only cancels the pending timer when an observation stops being settled, the thread is archived, or a stop was requested.

Settling a thread doesn't cancel the timer:

  • In ThreadNotificationCoordinator.tsx, settled is status === "ready" && latestRun.status === "completed". resolveSidebarThreadStatus ignores settledAt / settledOverride, so a settled thread is still "ready" and its observation stays settled: true. The gate sees an unchanged completedAt and keeps the timer running (pending.get(key)?.at === at).
  • The sidebar row's Settle button and the thread.settle shortcut (⌘⇧S, via settleAndAdvance) both go through Sidebar.attemptSettle. If the settled thread is the one open, it navigates to the next thread after the settle succeeds.
  • When the timer fires, present() checks the active route. The settled thread is no longer active (or never was, when settled from another thread's sidebar row), so it shows the in-app "Thread completed" toast (or a desktop notification when the window isn't focused) for a thread the user has already dealt with.

If the user settles after the 2s window, the notification has already been skipped because they were viewing the thread, so the bug only shows up inside that window.

Suggested fix: treat a settled thread as not notifiable in the gate. For example, pass settledOverride === "settled" / settledAt >= completedAt as quiet, or cancel and skip the pending completion when the thread becomes settled.

Steps to reproduce

  1. Enable in-app notifications.
  2. Open a thread and send a prompt. Stay on the thread.
  3. Within ~2s of the agent finishing, click Settle on that thread's sidebar row (or press ⌘⇧S). The app advances to another thread.
  4. About 2s after the run completed, a "Thread completed" toast appears for the settled thread.

Version

0.1.5-nightly.20261029.3867 (6d82a22). The gate code is unchanged since 0.1.4-nightly.20261029.3853.

Environment

macOS 27.0.1, T3 Code (Nightly) desktop app against its local server, Claude Code 2.1.312

Evidence

# Threads settled 0–3s after their latest run completed (statev2.sqlite, read-only)
thread     run completed_at            settledAt                   delta
600cd4e8   2026-10-29T09:08:55.724Z    2026-10-29T09:08:57.464Z    1.74s
e3b365ea   2026-10-28T09:28:03.979Z    2026-10-28T09:28:05.754Z    1.78s
9ae9e6a4   2026-10-22T19:14:12.509Z    2026-10-22T19:14:13.994Z    1.49s
1d1b74ae   2026-10-22T09:08:24.367Z    2026-10-22T09:08:25.522Z    1.15s

Each of these settles landed 1–2s after completion, inside the 2s grace window, which is the case that leaks the toast. Auto-settles in the same database land at a delta of exactly 0s.

Related issues

#24477 introduced the 2s completion grace that this escapes. #20883 (the done toast stays open after opening the thread) is a different code path. I found no existing report of a settled thread still notifying.

Fix applied or workaround

None. Workaround: wait ~2s after a run finishes before settling.

Filed by

claude (claude-opus-5-5) via t3 triage

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions