Repository navigation
fix(bridge): bound every agent-facing wait — client deadlines, MCP cancel, server connection cap - #253
Merged
Conversation
…ncel, server connection cap Four agent-facing hangs from docs/BUG_HUNT_2026-07.md: - BridgeClient: connect, write and response read are now bounded. Each call gets a deadline from BridgeTimeouts (15s for hello/status/stop/ cancel; consent window + the verb's budget + slack for guarded verbs; dictate derived from its own clamped timeoutSeconds). Expiry throws the new ClientError.timedOut(method:seconds:); the CLI exits 2 with a clear message, MCP returns a tool error. PersistentBridge drops the desynced connection on a timeout but never retries (the request may still run). - MCP server: tools/call runs on a serial worker queue so stdin keeps being read. notifications/cancelled is handled via MCPRequestTracker: a running dictate is stopped with dictate.cancel over a separate bridge connection (retried while the dictate is still in flight, e.g. waiting on consent), a queued call is skipped, and a cancelled request gets no response. Stdin EOF cancels the same way. - AgentBridgeServer: concurrent connections capped at 32 (over the cap the peer gets a `busy` error frame). Accepted sockets get SO_RCVTIMEO/ SO_SNDTIMEO via BridgeConnectionReader (core): idle connections close after 5 min, stop() is noticed within one 5s tick, torn writes shut the socket down. - WorkspaceContext: the git rev-parse that runs before the MCP keep-alive starts is abandoned after 2s. Each fix has a swift test that fails with the fix removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
What & why
Fixes the four agent-facing hangs from the July bug hunt (
docs/BUG_HUNT_2026-07.md). In each case an agent such as Claude Code, calling theopenwhispCLI or MCP server, could wait forever, or the mic could stay open long after the agent gave up.BridgeClienthad no timeouts.openwhisp statusand the other verbs could hang forever if the app was wedged.BridgeTimeouts):timeoutSeconds.ClientError.timedOut(method:seconds:). The CLI exits 2 with a clear message, and MCP returns a tool error.PersistentBridgedrops the out-of-sync connection on a timeout, but never retries (the request may still be running).notifications/cancelled. A cancelledopenwhisp_dictateleft the mic open for up to 300 s.tools/callnow runs on a serial worker queue, so stdin keeps being read.MCPRequestTrackerhandles cancellation:dictate.cancelover a separate bridge connection, retried while still in flight (for example while waiting on consent);AgentBridgeServerhad one thread per connection, with no cap and no socket timeouts.busyerror frame.SO_RCVTIMEO/SO_SNDTIMEOthroughBridgeConnectionReader(in core): idle connections close after 5 min,stop()is noticed within one 5 s tick, and torn writes shut the socket down.WorkspaceContext'sgit rev-parseblocked with no deadline before the MCP keep-alive started. It's now abandoned after 2 s.The decision logic sits in testable modules (
OpenWhispBridgeKit, plusBridgeConnectionPolicyinOpenWhispCore), following CLAUDE.md.docs/BUG_HUNT_2026-07.mdmarks the four items fixed.How it was tested
swift testpasses on the branch: 2,738 tests, as reported by the implementing sessionBridgeClientTimeoutTests,MCPServerCancellationTests,BridgeConnectionPolicyTests, plus additions toPersistentBridgeTestsandWorkspaceContextTests./build.sh: this branch was cut before chore(deps): update all native deps + CI, retire WhisperKit fork, ship SpeechAnalyzer again #250's Xcode 27 build fix landed. It merges cleanly with currentmain, and CI builds the merge.status): not yetPrivacy checklist
Notes
busy.BridgeConnectionPolicyis a newOpenWhispCorefile, registered inPackage.swift's explicitsources:list.🤖 Generated with Claude Code