You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Recurring cron jobs silently stopped firing after the first execution due to a double-unlock panic in the timer callback. The defer s.mu.Unlock() added for TOCTOU protection conflicted with existing manual unlock calls, causing sync: unlock of unlocked mutex panic. The recover() caught the panic but the goroutine exited without rescheduling.
Mobile Sync Overlay on Every Message
fix(relay): close slow client connection on send buffer drop to prevent ordinal gaps (8993fda0)
Relay's sendRaw had a 2s timeout that silently dropped live-forward events when the mobile client's send buffer was full. Dropped events created ordinal gaps that triggered full-screen "Syncing with relay" overlays on every message. Now closes the slow client's WebSocket connection (code 1013) so it reconnects and resumes from its last ACKed cursor.
The active_session barrier ordinal check triggered sync overlay even after initial sync was complete. Added !_resumeCompleted guard so it only shows during initial connect.
fix(mobile): gap recovery relaySync overlay after resume completes (e8eba2ac)
Gap recovery path (_scheduleGapRecovery and _runScheduledGapRecovery) also triggered sync overlay without checking _resumeCompleted. Added the same guard to both call sites.
Concurrency & Race Condition Fixes
fix(mcp): c.closed data race — bool to atomic.Bool (6d6548cb)
Abort() wrote c.closed without holding c.mu while sendRequest/sendNotification read it under c.mu. Changed to atomic.Bool.
fix(im): WeCom and Mattermost WebSocket concurrent writes without mutex (df7e0042)
Heartbeat goroutines and Send/TriggerTyping goroutines wrote to the same WebSocket concurrently, causing gorilla/websocket panic. Same pattern as Discord (fixed in ac99cab5). Added writeMu sync.Mutex.
fix(a2a): CancelTask races with execute completion (d8a1080e)
CancelTask's Canceled state was silently overwritten by execute()'s Completed when they raced. Added terminal state guard in updateStatus().
fix(session): runMaintenance saveIndex without cross-process lock loses entries (b708030a)
runMaintenance called saveIndex without holding the cross-process flock. If another process (Desktop + CLI) appended to the index during maintenance, the new entry was overwritten. Now acquires flock, reloads index, and merges.
fix(context): tokenCountLocked called after mu.Unlock in ApplyCompactResult (df231351)
ApplyCompactResult called tokenCountLocked() after releasing mu, racing with concurrent Add/RecordUsage. Reused the value computed under lock.
fix(debug): cleanupStaleLogs runs before defaultLogDir is set + liveSink data race (c48b04f6)
Stale log cleanup silently did nothing because defaultLogDir was assigned after cleanupStaleLogs() was called. Also fixed liveSink read without lock racing with SetLiveSink.
Provider Fixes
fix(openai): usage leaks across retry attempts (844fca81)
var usage *TokenUsage declared outside the retry loop retained failed attempt's stats. Reset to nil at the start of each attempt. Same pattern as Gemini (fixed in 922135df).
fix(gemini): retryDelay double-call shows wrong wait time (2197ceda)
retryDelay() with ±25% jitter was called twice — once for display, once for sleep — showing incorrect wait times. Stored to variable. Same pattern as Anthropic (fixed in 3c3aa53a).
Browser Automation
fix(browser): 7 functions missing CDP timeout protection can hang indefinitely (d25c01a9)
doExtract, doScreenshot, doEvaluate, doLinks, doScroll, doBack, doContent used bare tab.ctx (no deadline). Chrome stall (JS infinite loop, page never loads) caused permanent hang. Added context.WithTimeout matching the pattern of 11 other functions.
extractFilePaths didn't recognize notebook_path as a path field, so sandbox checks were silently skipped. notebook_edit could write .ipynb files outside the workspace in bypass/autopilot modes.
Other Fixes
fix(tui): handle SIGHUP for graceful shutdown on terminal close (0577dc9a)
SIGHUP (terminal close, SSH disconnect, display sleep) killed the process immediately without saving session. Now sends tea.QuitMsg for graceful shutdown.