Skip to content

fix(voice): move active calls between sessions - #172

Merged
johnmatthewtennant merged 38 commits into
mainfrom
jtennant/voice-call-handoff
Aug 24, 2026
Merged

fix(voice): move active calls between sessions#172
johnmatthewtennant merged 38 commits into
mainfrom
jtennant/voice-call-handoff

Conversation

@johnmatthewtennant

@johnmatthewtennant johnmatthewtennant commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Voice conversations used to end when the user switched sessions. This follow-up makes the composer phone in an eligible session B transfer an active call from session A: Berd refreshes authoritative native state, stops and flushes the exact lifecycle in A, then starts B. Calls never overlap, and a failed stop leaves A active instead of starting B.

On macOS, showing the floating voice controls previously activated their native window. While the controls were visible, hover and clicks across the main Berd window could stop responding. The controls are now ordered in front without taking activation, remain first-click interactive, and retain keyboard and accessibility focus when the user intentionally moves focus to them. A failed show remains detectable so Berd does not disable its controls-readiness watchdog.

Ineligible sessions do not show the call button. Concurrent or stale transfer attempts reconcile to the authoritative native lifecycle.

Reviewer-reproducible examples

With Pocket voice installed:

  1. Start voice in session A, navigate to eligible session B, and click the composer phone once. Confirm A stops and B becomes active only after A finishes shutting down.
  2. With A active and the floating controls visible on macOS, hover and click controls throughout the main Berd window. Confirm they respond normally and the floating controls remain visible.
  3. Click the floating mute control. Then intentionally focus the floating controls and press Tab. Confirm mute works and keyboard focus reaches Hang up.
  4. Open a read-only or otherwise ineligible session. Confirm its composer does not show the call button.
  5. Trigger two eligible replacement attempts close together. Confirm only the authoritative winner remains active and transcripts continue routing to that session.
  6. Force A's stop to fail. Confirm A remains active, B does not start, and B shows the localized stop error.

@johnmatthewtennant
johnmatthewtennant marked this pull request as ready for review August 23, 2026 01:35
@johnmatthewtennant
johnmatthewtennant requested a review from a team August 23, 2026 01:35

@morgmart morgmart left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🤖 Automated code review

REQUEST_CHANGES: The replacement flow does not prove that the focused main window still owns the requested target session before stopping the active call. Supplied GitHub evidence was inspected; all listed check runs for the exact head SHA completed successfully, while the combined commit status remains pending and no Intersect Security Scanning run appears in the supplied evidence.

Deterministic publication result: 1 blocking and 0 non-blocking finding(s) publishable; 0 duplicate(s) suppressed.

Comment thread src-tauri/src/commands/native_voice.rs Outdated

@morgmart morgmart left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🤖 Automated code review

REQUEST_CHANGES: The current foreground-session acknowledgement has no bounded failure path, so one never-settling IPC request can wedge voice controls for the renderer indefinitely. The prior target-ownership issue is fixed and its resolved thread has a substantive human reply. Supplied GitHub evidence for the exact head SHA was inspected: all listed check runs completed successfully, the combined commit status remains pending, and no Intersect Security Scanning run appears in the supplied evidence.

Deterministic publication result: 1 blocking and 0 non-blocking finding(s) publishable; 0 duplicate(s) suppressed.

Comment thread src/features/voice-conversation/api/voiceConversation.ts
morgmart
morgmart previously approved these changes Aug 23, 2026

@morgmart morgmart left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🤖 Automated code review

APPROVE: Fresh review of the full exact three-dot comparison found no publishable blocking or non-blocking issues. The replacement flow now binds authorization to the current foreground session, bounds acknowledgement across supersessions, leaves the active call untouched on failure, releases the operation latch, and has discriminating lifecycle/race coverage. The two prior automated findings are fixed; both threads are resolved and contain substantive human-account replies. Accessibility, localization, navigation/consent guards, async and never-completes behavior, lifecycle races, test honesty, and project/design-system rules were checked. Supplied GitHub evidence for the exact head SHA was inspected: every listed check run completed successfully, the combined commit status remains pending, and no Intersect Security Scanning run appears in the supplied evidence; required checks still govern merge readiness.

Deterministic publication result: 0 blocking and 0 non-blocking finding(s) publishable; 0 duplicate(s) suppressed.

Pending checks: 1 check(s) are not complete.

This approval reflects the completed code review only; merge readiness remains governed by the repository's required checks.

@morgmart morgmart left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🤖 Automated code review

REQUEST_CHANGES: Per-session operation latches still allow two different eligible target sessions to execute replacement concurrently. The store now preserves a competing lifecycle winner, but the losing controller can still clear the winner's shared transcript route and stop shared assistant speech. The two supplied prior automated threads are resolved, fixed, and contain substantive human-account replies; this competing-target issue has no matching supplied thread. Supplied GitHub evidence for the exact head SHA was inspected: every listed check run completed successfully, the combined commit status remains pending, and no Intersect Security Scanning run appears in the supplied evidence.

Deterministic publication result: 1 blocking and 0 non-blocking finding(s) publishable; 0 duplicate(s) suppressed.

morgmart
morgmart previously approved these changes Aug 24, 2026

@morgmart morgmart left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🤖 Automated code review

APPROVE: Fresh review of the full exact three-dot comparison found no publishable blocking or non-blocking issues. The flow now binds stop and start to the current foreground generation, owner window, and focus under native lifecycle serialization; renderer replacement is serialized; shared transcript and assistant-speech resources activate only after the authoritative lifecycle wins; failure and stale-winner paths preserve current state. The three prior automated findings are fixed, and every supplied thread is resolved with a substantive human-account reply. Final self-check covered transfer and ordinary start/stop flows, accessibility, localization, navigation and consent guards, async failures and never-completes behavior, lifecycle and race handling, test honesty, design-system/project rules, duplicate overlap, and severity evidence. Supplied GitHub evidence for the exact head SHA was inspected: Clean-room frozen install and DCO completed successfully; frontend and platform Rust checks are still in progress; the combined status is pending; no Intersect Security Scanning run appears in the supplied evidence. Required checks still govern merge readiness.

Deterministic publication result: 0 blocking and 0 non-blocking finding(s) publishable; 0 duplicate(s) suppressed.

Pending checks: 4 check(s) are not complete.

This approval reflects the completed code review only; merge readiness remains governed by the repository's required checks.

@morgmart morgmart left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🤖 Automated code review

APPROVE: Fresh review of the full exact three-dot comparison found no publishable blocking or non-blocking issues. The transfer flow binds stop and start to authoritative foreground ownership and native lifecycle serialization, bounds acknowledgement waits, serializes competing replacements, and activates shared transcript and assistant-speech resources only for the winner. The macOS floating controls are shown without activation while retaining first-click interaction, and show failures continue through the existing recovery path. All three prior automated findings are fixed, and every supplied thread is resolved with substantive human-account replies. Final self-check covered transfer, ordinary start/stop, floating-control interaction, accessibility, localization, navigation and consent guards, async/error/never-completes behavior, lifecycle races, test honesty, design-system/project rules, duplicate overlap, and severity evidence. Supplied GitHub evidence for the exact head SHA was inspected: every listed check run completed successfully, the combined status remains pending, and no Intersect Security Scanning run appears in the supplied evidence; required checks still govern merge readiness.

Deterministic publication result: 0 blocking and 0 non-blocking finding(s) publishable; 0 duplicate(s) suppressed.

Pending checks: 1 check(s) are not complete.

This approval reflects the completed code review only; merge readiness remains governed by the repository's required checks.

@johnmatthewtennant
johnmatthewtennant merged commit 04505c3 into main Aug 24, 2026
8 checks passed
@johnmatthewtennant
johnmatthewtennant deleted the jtennant/voice-call-handoff branch August 24, 2026 15:47
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.

2 participants