refactor(desktop): coordinate TTS playback - #6341
Merged
Merged
Conversation
Co-authored-by: Wren <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@buzz.block.builderlab.xyz> Signed-off-by: Wren <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@buzz.block.builderlab.xyz>
…tions The playback coordinator queued audio and replaced players under its own lock, but the mic-gate flag those transitions imply (`tts_active`) was published outside it. Append and cancellation could therefore interleave in either direction and leave the gate disagreeing with what is audibly playing: - a cancellation winning after an append committed left a stale `true`, so the mic stayed gated with nothing playing; - an append winning the lock handoff after a replacement had a late `false` land on top of it, ungating the mic for the whole utterance and feeding our own TTS back to VAD as a barge-in. `append_if` and `cancel_if_live` now each take a `commit` callback that runs under the coordinator, after the queue mutation and before release. Both directions are one transition again, matching the pre-refactor behavior where `_ops` was held across the flag write. The old player is still dropped outside the lock, so rodio teardown does not extend the critical section. `release_playback` keeps the unconditional clear on the not-live path: publishing only inside the replacement would drop the flag write when there is nothing live to replace. Also removes `first_append` from the `prepare_audio` chain. It was written but never read there, and clearing it during preparation recorded an append that authorization might still refuse. It is now coordinator-private: cleared by `append_if` on the accepted path only, rearmed by `cancel_if_live` and `release_if_drained`. Signed-off-by: Dawn <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@buzz.block.builderlab.xyz>
jedwards27
pushed a commit
to jedwards27/buzz
that referenced
this pull request
Aug 20, 2026
* origin/main: feat(desktop): make the Projects overview follow the selected section (block#6335) refactor(desktop): coordinate TTS playback (block#6341) fix(desktop): show complete repository trees (block#5102) Signed-off-by: Carl <5f365698229751c0461f57bb03a4e93134e6e936bd7039ebe7b737282a43c754@buzz.block.builderlab.xyz>
funge
added a commit
to funge/buzz
that referenced
this pull request
Aug 20, 2026
…-shortcut * origin/main: (341 commits) feat(desktop): make the Projects overview follow the selected section (block#6335) refactor(desktop): coordinate TTS playback (block#6341) fix(desktop): show complete repository trees (block#5102) Add appearance preference previews (block#6193) fix(desktop): restore emoji recents (block#6263) chore: serialize mobile pre-push checks (block#6322) fix(buzz-acp): loosen workspace-scan guardrail to allow named paths (block#6261) fix(buzz-dev-mcp): expand leading ~ in read_file/str_replace paths (block#6271) perf(desktop): move five hot renderer paths from JS into Rust (block#6024) fix(media): accept portrait video resolutions (block#6058) fix(desktop): hide archived channels from #/Tab autocomplete (block#6156) Unify mobile channel details (block#6113) Revert "fix(acp): gate relay-signed workflow messages on their attributed author" (block#6311) fix(desktop): morph the drawer panel icon instead of sliding it (block#6306) feat(desktop): refine repository-aware project workspaces (block#6003) Fix mobile Activity thread navigation (block#5850) perf(desktop): parallelize relay agent directory rebuild (block#6258) Refine the mobile emoji picker (block#5853) fix(desktop): exclude archived agents from nest, order regeneration (block#5905) Add font size and conversation density preferences (block#5644) ... Signed-off-by: John Funge <funge@squareup.com> # Conflicts: # desktop/src/features/messages/ui/MessageComposer.tsx # desktop/src/features/settings/ui/KeyboardShortcutsCard.tsx
wpfleger96
pushed a commit
that referenced
this pull request
Aug 20, 2026
…as-aware-labels * origin/main: feat(desktop): make Projects workspaces selectable (#6368) Add Buzz-native collaboration benchmarks (#6264) Polish mobile timeline and emoji interactions (#6297) feat(desktop): make the Projects overview follow the selected section (#6335) refactor(desktop): coordinate TTS playback (#6341) Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
tellaho
added a commit
that referenced
this pull request
Aug 20, 2026
…ress * origin/main: fix(desktop): distinguish duplicate agent devices (#6337) feat(desktop): close Buzz window with Cmd+W (#6314) refactor(prompt): simplify Buzz agent guidance (#6340) feat(desktop): make Projects workspaces selectable (#6368) Add Buzz-native collaboration benchmarks (#6264) Polish mobile timeline and emoji interactions (#6297) feat(desktop): make the Projects overview follow the selected section (#6335) refactor(desktop): coordinate TTS playback (#6341) fix(desktop): show complete repository trees (#5102) Add appearance preference previews (#6193) fix(desktop): restore emoji recents (#6263) chore: serialize mobile pre-push checks (#6322) fix(buzz-acp): loosen workspace-scan guardrail to allow named paths (#6261) fix(buzz-dev-mcp): expand leading ~ in read_file/str_replace paths (#6271) perf(desktop): move five hot renderer paths from JS into Rust (#6024) fix(media): accept portrait video resolutions (#6058) fix(desktop): hide archived channels from #/Tab autocomplete (#6156) Unify mobile channel details (#6113) Revert "fix(acp): gate relay-signed workflow messages on their attributed author" (#6311) Signed-off-by: Taylor Ho <taylorkmho@gmail.com> # Conflicts: # desktop/src/features/messages/ui/MentionAutocomplete.test.mjs
morgmart
added a commit
that referenced
this pull request
Aug 20, 2026
…handoff * origin/main: feat(desktop): refine context-aware Projects collaboration (#6396) fix(desktop): distinguish duplicate agent devices (#6337) feat(desktop): close Buzz window with Cmd+W (#6314) refactor(prompt): simplify Buzz agent guidance (#6340) feat(desktop): make Projects workspaces selectable (#6368) Add Buzz-native collaboration benchmarks (#6264) Polish mobile timeline and emoji interactions (#6297) feat(desktop): make the Projects overview follow the selected section (#6335) refactor(desktop): coordinate TTS playback (#6341) fix(desktop): show complete repository trees (#5102) Add appearance preference previews (#6193) fix(desktop): restore emoji recents (#6263) chore: serialize mobile pre-push checks (#6322) Signed-off-by: morgmart <98432065+morgmart@users.noreply.github.com>
wpfleger96
pushed a commit
that referenced
this pull request
Aug 20, 2026
…el-directory * origin/main: feat(desktop): refine context-aware Projects collaboration (#6396) fix(desktop): distinguish duplicate agent devices (#6337) feat(desktop): close Buzz window with Cmd+W (#6314) refactor(prompt): simplify Buzz agent guidance (#6340) feat(desktop): make Projects workspaces selectable (#6368) Add Buzz-native collaboration benchmarks (#6264) Polish mobile timeline and emoji interactions (#6297) feat(desktop): make the Projects overview follow the selected section (#6335) refactor(desktop): coordinate TTS playback (#6341) Signed-off-by: Hayt <9e1c23a3fd83f61da34420e4e88ff1b16e45cafcc0cd9019eb07d4ecfa8ca9b0@buzz.block.builderlab.xyz>
wpfleger96
added a commit
that referenced
this pull request
Aug 20, 2026
…el-directory * origin/main: feat(desktop): refine context-aware Projects collaboration (#6396) fix(desktop): distinguish duplicate agent devices (#6337) feat(desktop): close Buzz window with Cmd+W (#6314) refactor(prompt): simplify Buzz agent guidance (#6340) feat(desktop): make Projects workspaces selectable (#6368) Add Buzz-native collaboration benchmarks (#6264) Polish mobile timeline and emoji interactions (#6297) feat(desktop): make the Projects overview follow the selected section (#6335) refactor(desktop): coordinate TTS playback (#6341) Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Hayt <9e1c23a3fd83f61da34420e4e88ff1b16e45cafcc0cd9019eb07d4ecfa8ca9b0@buzz.block.builderlab.xyz>
atishpatel
added a commit
that referenced
this pull request
Aug 20, 2026
…ounting-and-solo * origin/main: (48 commits) fix(hooks): scope pre-push lanes to branch merge-base diff (#6423) Enforce a three-day dependency cooldown (#6426) perf(desktop): resolve references without directory scans (#6328) feat(llm): stamp thinking effort on call-completed log line (#6424) Fix cross-owner relay agent mentions in owner-only builds (#6338) feat(cli): accept Buzz message links for thread reads (#6359) feat(workflows): add workflow editor (#6248) fix(desktop): preserve huddle speech boundaries (#6397) test(desktop): use a wordlist-safe separator in passphrase word-count test (#6356) fix(models): curate Databricks alias-aware labels for 5 missing endpoints (#6360) fix(acp): guard against unrequested public relay skills (#6394) feat(desktop): refine context-aware Projects collaboration (#6396) fix(desktop): distinguish duplicate agent devices (#6337) feat(desktop): close Buzz window with Cmd+W (#6314) refactor(prompt): simplify Buzz agent guidance (#6340) feat(desktop): make Projects workspaces selectable (#6368) Add Buzz-native collaboration benchmarks (#6264) Polish mobile timeline and emoji interactions (#6297) feat(desktop): make the Projects overview follow the selected section (#6335) refactor(desktop): coordinate TTS playback (#6341) ... Signed-off-by: Atish Patel <atishpatel2012@gmail.com>
brow
added a commit
that referenced
this pull request
Aug 20, 2026
…ifications-pr * origin/main: (33 commits) fix(hooks): scope pre-push lanes to branch merge-base diff (#6423) Enforce a three-day dependency cooldown (#6426) perf(desktop): resolve references without directory scans (#6328) feat(llm): stamp thinking effort on call-completed log line (#6424) Fix cross-owner relay agent mentions in owner-only builds (#6338) feat(cli): accept Buzz message links for thread reads (#6359) feat(workflows): add workflow editor (#6248) fix(desktop): preserve huddle speech boundaries (#6397) test(desktop): use a wordlist-safe separator in passphrase word-count test (#6356) fix(models): curate Databricks alias-aware labels for 5 missing endpoints (#6360) fix(acp): guard against unrequested public relay skills (#6394) feat(desktop): refine context-aware Projects collaboration (#6396) fix(desktop): distinguish duplicate agent devices (#6337) feat(desktop): close Buzz window with Cmd+W (#6314) refactor(prompt): simplify Buzz agent guidance (#6340) feat(desktop): make Projects workspaces selectable (#6368) Add Buzz-native collaboration benchmarks (#6264) Polish mobile timeline and emoji interactions (#6297) feat(desktop): make the Projects overview follow the selected section (#6335) refactor(desktop): coordinate TTS playback (#6341) ... Signed-off-by: Tom Brow <tomb@block.xyz>
tlongwell-block
added a commit
that referenced
this pull request
Aug 21, 2026
## Problem Humans cannot interrupt agents in huddles: agent TTS keeps playing over a talking human (reported by @tlongwell-block, 2026-08-20). The full requirement: **any human talking — local or remote, any input mode, any audio rig — must interrupt any agent on the huddle.** ## This is a restoration, not a new feature - **`b29c8cdaa` (#4281, 2026-08-04) deleted working local VAD barge-in.** The pre-image shipped `BARGE_IN_DEBOUNCE_FRAMES = 20` (320 ms sustained speech cancels TTS), live at the production call site (`pipeline.rs` passed `Some(tts_cancel)` unconditionally). The same day, `ce3cf3cd2` (#4694) flipped the default input mode from VAD to push-to-talk, which masked the loss. - **`068a83b09` (#5671, 2026-08-13) removed the remaining TTS-awareness plumbing from STT** (deliberately, to keep transcribing over agent audio — a good change). Consequence: this PR is a re-plumb through the `PlaybackCoordinator` from #6341, not a revert. - A gap that **never** worked is also closed: PTT-mode users who open the mic via the mute button (`manual_mic_unmuted` postdates the deletion) transcribed fine but could not barge in. ## Design All floor state lives under the single `PlaybackCoordinator` lock — onset acceptance, epoch bump, synthesis invalidation, player replacement, and output lease are one committed transition. No cancel flag can be observed out of order with the playback state it describes. - **Human floor**: local + per-peer remote ownership with epoch invalidation. Onset cancels playback by queue replacement; late synthesis for a stale epoch cannot append or restart. - **Local onset (VAD)**: on an **isolated output route** (all CoreAudio output-stream terminals report headphones), a confirmed short onset interrupts immediately — no echo path exists. On a **coupled route** (speakers, unknown, virtual, mixed), the restored **20-frame / 320 ms sustained-speech debounce** discriminates a real human from speaker bleed; the deleted code's comment records that 80 ms was tried and false-triggered on laptop speakers. Route classification is queried fresh at each onset (never cached — default-device re-routing mid-huddle would strand a stale verdict). - **Mic-open gate is per-frame**: barge-in observes on any frame where the mic is actually open — pure VAD mode, or PTT with the mic manually unmuted (key-held frames defer to the shortcut's own cancel). - **Remote onset**: sustained non-DTX frames from a peer enter the same persistent floor (independent of whether playback is live — a human speaking while TTS is idle blocks late-arriving synthesis from starting over them). Release on sustained DTX/absence, peer departure, and recv-loop exit, with guards so a vanished peer cannot wedge the floor. - **Output lease**: accepted appends renew an `Active` lease; drain/cancel/onset start a 100 ms tail hangover (conservative against measured ~12 ms/~1 ms CoreAudio tails), so speaker-tail bleed in the just-drained window cannot self-trigger the coupled path. ## Known limitations (phase 2 pointers) - Coupled-route mid-output barge-in pays the 320 ms debounce; a playback-reference echo discriminator would shorten it. - A speakers-rig participant's bleed can enter their mic and hold the floor for other machines (bounded by release debounce). - Non-macOS routes classify as coupled (fail-safe). ## Verification - Full `buzz-desktop --lib` suite at head `b0459ae4a`: **2707 passed, 0 failed, 18 ignored** (pinned cargo 1.95.0). - Exact CI recipe `just desktop-tauri-clippy`: PASS at head; base arm at merge-base `b728a2af3` confirms the two `#[allow(clippy::too_many_arguments)]`s cover branch-caused threshold crossings (human_floor threading), not inherited noise. - Regression tests pin: 20-frame threshold + reset-on-gap, short-coupled rejection, sustained-coupled acceptance, coupled-idle acceptance, remote-idle delayed-TTS rejection, output-tail hangover boundary (during = rejected, after = accepted), isolated onset, per-frame mic-open gate truth table, PTT+manual-unmute sustained coupled acquisition. - `LocalBargeIn::observe` is covered as two joined halves (gate truth table in `local_barge_in.rs`, floor transition in `tts_playback.rs`); its body is a straight-line wrapper around a live CoreAudio query, left uninjected deliberately. - Coverage precision (mutation-verified): `manual_open_ptt_sustained_speech_acquires_coupled_floor` pins the gate → 20-frame debounce → acquire → floor-blocked chain on the coupled-**idle** cell. The live-output override leg is carried by `sustained_coupled_speech_overrides_live_output_suppression` (tts_playback.rs); the joiner's `sustained_coupled` argument is not load-bearing there (flipping it to `false` leaves the test green, while shortening the debounce by one frame turns it red). - Live arms in progress: pre-regression build `b29c8cdaa^` staged to confirm the deleted mechanism worked; two-endpoint remote-leg test pending a second human. ## Commits 1. `fb681a5a9` — restore human barge-in (coordinator floor, lease, route isolation, remote floor, 320 ms coupled debounce) 2. `b4265418e` — enable barge-in for manually opened mics (per-frame gate; closes the PTT-open-mic gap) 3. `886489f2b` — extract local barge-in policy module (file-size ratchet; also hoists the CoreAudio route query from per-frame to per-onset, named in the commit message) 4. `b0459ae4a` — two targeted clippy allows for the widened worker signatures ## Credits Built by **Wren**. Regression archaeology and the PTT-open-mic gap by **Dawn** (who also killed her own first fix as vacuous and caught a clippy blocker before it hit CI). Review blockers (coordinator serialization, idle-onset floors, output lease) by **Mari**. Live rig verification by **Max**. Coordination and verification by **Eva**. Opened by Eva with Tyler's explicit direction; commits carry agent trailers. --------- Signed-off-by: Wren <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@buzz.block.builderlab.xyz> Co-authored-by: Wren <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@buzz.block.builderlab.xyz>
tellaho
added a commit
that referenced
this pull request
Aug 21, 2026
…ress * origin/main: fix(desktop): distinguish duplicate agent devices (#6337) feat(desktop): close Buzz window with Cmd+W (#6314) refactor(prompt): simplify Buzz agent guidance (#6340) feat(desktop): make Projects workspaces selectable (#6368) Add Buzz-native collaboration benchmarks (#6264) Polish mobile timeline and emoji interactions (#6297) feat(desktop): make the Projects overview follow the selected section (#6335) refactor(desktop): coordinate TTS playback (#6341) fix(desktop): show complete repository trees (#5102) Add appearance preference previews (#6193) fix(desktop): restore emoji recents (#6263) chore: serialize mobile pre-push checks (#6322) fix(buzz-acp): loosen workspace-scan guardrail to allow named paths (#6261) fix(buzz-dev-mcp): expand leading ~ in read_file/str_replace paths (#6271) perf(desktop): move five hot renderer paths from JS into Rust (#6024) fix(media): accept portrait video resolutions (#6058) fix(desktop): hide archived channels from #/Tab autocomplete (#6156) Unify mobile channel details (#6113) Revert "fix(acp): gate relay-signed workflow messages on their attributed author" (#6311) # Conflicts: # desktop/src/features/messages/ui/MentionAutocomplete.test.mjs Signed-off-by: Taylor Ho <taylorkmho@gmail.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.
Summary
PlaybackCoordinatoras the exclusive owner of the rodioPlayerThis is the behavior-preserving coordinator prerequisite for the follow-up floor-authorization policy. The only intentional playout difference is +2 ms silence at playback-chunk starts to prevent the measured fresh-player bootstrap chirp.
Verification (all at this exact head,
8bfa4c0531834dce39f5ad0266f2674505e659bf)cargo clippy --manifest-path desktop/src-tauri/Cargo.toml --workspace --all-targets -- -D warnings— cleancargo test --manifest-path desktop/src-tauri/Cargo.toml --package buzz-desktop— 2,596 passed / 17 ignored / 0 failedstarts_playback_chunkinvariantbuild_sentence_append_bufferpath): bootstrap chirp eliminated (660.1 Hz head vs 660 Hz control), no false drain, cancel-to-silence ~1 ms vs 12 ms baselinePlayer::dropsemanticsPlayout cost
Provenance
Authored and reviewed by Buzz agents (Wren: implementation; Dawn: line review, known-answer control, mutation testing; Max: live CoreAudio gates; Eva: coordination and final verification), with review records on the Buzz relay. This PR was briefly merged to main directly by mistake and reverted via ref reset; this is the same commit going through the front door.