Repository navigation
Conversation
At boot the server accepts daemon session opens while plugins are still loading. A daemon that restarted alongside bb had its cut turns interrupted right away, so plugins that had not loaded yet never heard the turn.failed and thread.failed events, which are not replayed. handleHostSessionOpened now retires the previous session immediately but waits for whenRegistrationsSettled, the same wait turn sends use, before interrupting provisioning, pending interactions and active turns and reconciling the daemon's reported threads. The session-open response is held until then, so daemon events cannot race the reported thread snapshot. A session superseded during that wait skips recovery: its report is stale and the newer session recovers the host, which avoids reviving a thread from the stale report and failing its turn twice. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ymichael
deleted the
bb/wait-for-plugin-startup-before-daemon-reconnect-thr_gzagydpbdz
branch
October 30, 2026 19:49
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.
Human comments
What was wrong
At boot the server starts its HTTP listener and loads plugins in the background (
startServerPlugins, which ends inmarkRegistrationsSettled). A daemon that restarted along with bb reconnects during that window.handleHostSessionOpenedthen immediately interrupts the turns the new daemon process no longer has, firingturn.failedandthread.failed. Plugin events go only to plugins that have already loaded and are never replayed, so a plugin still loading at boot never hears that the restart cut those turns. Turn sends already wait for plugin startup (whenRegistrationsSettled). Reconnect recovery didn't. This blocks plugins (and #6612) from reacting to turns a restart cut.What changed
apps/server/src/internal/session-owner-side-effects.ts, inhandleHostSessionOpened:deps.providerRegistry.whenRegistrationsSettled(), the same wait with the same 30s cap that sends use. That covers interrupting environment provisioning, pending interactions and active turns, settling dangling background tasks, andreconcileDaemonReportedThreads. The/internal/session/openresponse is held until recovery finishes, so the daemon's WebSocket can't send events that conflict with the active-thread snapshot it reported. Plugin startup doesn't depend on a connected daemon, so this can't deadlock. After a boot, a machine shows as connected only once plugins have loaded (or after 30s).run.started) and its turn would then be failed a second time.No wire change, no protocol bump, no plugin SDK change.
How you verified
apps/server/test/internal/reconnect-recovery-waits-for-plugins.test.ts, using a provider registry withdeferRegistrationsSettled: true:activeand noturn.failedfires. After settling, the thread is inerrorwith exactly oneturn.failed. Fails without the wait: the thread was alreadyerror.turn.failed. Fails without the replaced-session check:turn.failedfired twice.pnpm exec turbo run test lint --filter=@bb/server: 368 files / 3789 tests pass, lint clean.🤖 Generated with Claude Code