Skip to content

Fix history loading race condition in ThreadManager#1853

Merged
siddseethepalli merged 1 commit into
mainfrom
swarm/task-2
Feb 14, 2026
Merged

Fix history loading race condition in ThreadManager#1853
siddseethepalli merged 1 commit into
mainfrom
swarm/task-2

Conversation

@siddseethepalli
Copy link
Copy Markdown
Contributor

@siddseethepalli siddseethepalli commented Feb 14, 2026

Summary

Addresses review feedback on #1814:

  • Race condition fix: Replaced single pendingHistoryThreadId with a pendingHistoryBySessionId dictionary, and added sessionId to the daemon's history_response payload. This ensures rapid tab switching doesn't route history from one thread into another — each in-flight request is correlated by session ID.

  • Overwrite guard: populateFromHistory now skips replacing messages if the thread already contains user-sent messages, preventing a late history_response from clobbering live conversation.

Changed files

  • assistant/src/daemon/ipc-protocol.ts — added sessionId to HistoryResponse
  • assistant/src/daemon/handlers.ts — echo sessionId back in response
  • clients/macos/.../IPCMessages.swift — added sessionId to HistoryResponseMessage
  • clients/macos/.../ThreadManager.swift — dictionary-based pending tracking
  • clients/macos/.../ChatViewModel.swift — guard against overwriting live messages
  • assistant/src/__tests__/ipc-snapshot.test.ts + snapshot — updated test fixture

Test plan

  • IPC snapshot tests pass with updated fixture
  • TypeScript type-check passes
  • Manual: restore threads, rapidly switch tabs, verify history lands in correct thread
  • Manual: send a message on a restored thread, verify late history_response doesn't overwrite it

Open with Devin

Bug 1: Replace single pendingHistoryThreadId with a dictionary keyed by
sessionId so rapid tab switches don't route history from Thread A into
Thread B. Add sessionId to the daemon's history_response payload so the
client can correlate responses back to the correct thread.

Bug 2: Guard populateFromHistory against overwriting live messages — skip
replacement if the thread already has user-sent messages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 132fec26ed

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread clients/macos/vellum-assistant/Features/Chat/ChatViewModel.swift
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 4 additional findings.

Open in Devin Review

ashleeradka added a commit that referenced this pull request Feb 14, 2026
- Resolved modify/delete conflict with IPCMessages.swift (file moved to shared/)
- Ported sessionId field to HistoryResponseMessage from main (#1853)
- Auto-merged changes to ChatViewModel, ThreadManager, and other macOS files

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@siddseethepalli
Copy link
Copy Markdown
Contributor Author

Addressed in #1903

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