Skip to content

Polish Huddle voice controls - #4694

Merged
wesbillman merged 13 commits into
mainfrom
kennylopez-huddle-stop-speaking
Aug 4, 2026
Merged

wesbillman merged 13 commits into
mainfrom
kennylopez-huddle-stop-speaking

Conversation

@klopez4212

Copy link
Copy Markdown
Contributor

Summary

  • add a visible Stop control for interrupting agent speech
  • make push-to-talk available by default while preserving manual mute controls
  • refine agent management, muted audio states, drawer layering, and return navigation
  • suppress duplicate notification sounds for Huddle messages

Why

Huddles could trap users behind long agent speech, hide useful agent controls, and leave temporary Huddle state visible after the call. The drawer also regressed when the terminal substrate began painting behind the rounded app surface.

Validation

  • just desktop-ci
  • focused Huddle Playwright coverage for the drawer, speech interruption, agent picker, and leave navigation

Signed-off-by: kenny lopez <klopez4212@gmail.com>
klopez4212 added a commit that referenced this pull request Aug 4, 2026
@klopez4212

Copy link
Copy Markdown
Contributor Author

🤖 Huddle UI snapshots

Drawer and agent voice controls

The drawer keeps its surface behind the rounded app and exposes agent controls from the avatar.

01-huddle-drawer-agent-menu

Interrupt agent speech

A responding agent replaces its name with a visible Stop control without changing tile height.

02-speaking-stop-control

Add an agent

The picker uses the shared modal styling and starts a stopped agent when selected.

03-add-agent-dialog

@klopez4212
klopez4212 marked this pull request as ready for review August 4, 2026 13:53
@klopez4212
klopez4212 requested a review from a team as a code owner August 4, 2026 13:53

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

Copy link
Copy Markdown

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: 5d7192503c

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread desktop/src/features/huddle/HuddleContext.tsx

@wesbillman wesbillman 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.

Requesting changes on Wes's behalf. I found three user-visible correctness issues in the new Huddle controls: the displayed mute action can leave the microphone open after PTT release, a stale Stop click can discard the next agent utterance, and removing an agent can leave that agent's current/queued speech playing. Details and requested regression coverage are inline. I am acting on Wes's behalf and am not approving this PR.

Comment thread desktop/src/features/huddle/HuddleContext.tsx
Comment thread desktop/src-tauri/src/huddle/commands.rs Outdated
Comment thread desktop/src-tauri/src/huddle/commands.rs
Signed-off-by: kenny lopez <klopez4212@gmail.com>
…p-speaking

Signed-off-by: kenny lopez <klopez4212@gmail.com>

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

Copy link
Copy Markdown

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: 53d4e079a1

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread desktop/src-tauri/src/huddle/tts_pipeline_controls.rs Outdated
Comment thread desktop/src/features/huddle/components/AddAgentDialog.tsx Outdated
Signed-off-by: kenny lopez <klopez4212@gmail.com>
…p-speaking

Signed-off-by: kenny lopez <klopez4212@gmail.com>

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

Copy link
Copy Markdown

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: 1015ade24e

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread desktop/src-tauri/src/huddle/tts_speaker_cancellation.rs Outdated
Comment thread desktop/src-tauri/src/huddle/commands.rs Outdated
Comment thread desktop/src/features/huddle/components/AddAgentDialog.tsx
Signed-off-by: kenny lopez <klopez4212@gmail.com>

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

Copy link
Copy Markdown

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: 80258a5066

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread desktop/src/features/huddle/HuddleContext.tsx
Signed-off-by: kenny lopez <klopez4212@gmail.com>

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

Copy link
Copy Markdown

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: 6e9fbbd176

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread desktop/src/features/huddle/components/ParticipantList.tsx
Signed-off-by: kenny lopez <klopez4212@gmail.com>

@wesbillman wesbillman 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.

Carl here, commenting on Wes's behalf. Requesting changes at exact head 05c7623b1debc8619fd9d1dcf29677e59bc76d01.

P1 — a stale Stop click can discard the same agent's next queued utterance after the displayed utterance has already drained. active_speaker and tts_active remain set until the worker notices player.empty() during receive-timeout or pre-synthesis cleanup (desktop/src-tauri/src/huddle/tts.rs:557-575, 662-677). During that real drain→cleanup window, the UI still presents Alice's Stop action. Clicking it passes request_active_speaker_cancel's ownership check and advances Alice's generation (desktop/src-tauri/src/huddle/tts_voice_transition.rs:133-157), invalidating Alice text already queued under the prior generation (desktop/src-tauri/src/huddle/tts.rs:603-608) even though the utterance the user intended to stop is over.

The new regression does not cover this ordering because it manually clears active_speaker before issuing the stale click (tts_voice_transition.rs:463-475). Please bind Stop to actual player/utterance liveness under the same synchronization and add a regression where playback is empty but ownership cleanup has not run; Alice's already-queued next utterance must survive.

The earlier mute/PTT, agent-removal, unrelated-speaker, provider-start, and wrong-speaker Stop issues appear fixed.

Signed-off-by: kenny lopez <klopez4212@gmail.com>
…p-speaking

Signed-off-by: kenny lopez <klopez4212@gmail.com>
@klopez4212

Copy link
Copy Markdown
Contributor Author

🤖 Addressed Wes’s P1 in 0aa4cbb. Stop now reads the actual Rodio player under the same player-operation lock used for append and clear, and only advances the selected agent’s generation when playback is still non-empty and that agent still owns it. Added a device-free regression with an empty player, stale Alice ownership, and Alice’s already-queued next utterance; the Stop request is rejected and the queued utterance remains current. All 66 Huddle TTS tests, strict Clippy, 4,177 desktop tests, the native workspace suite, and the full merged-tree pre-push gate pass. Latest main is merged at 241d57f.

@wesbillman wesbillman 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.

I’m commenting on Wes Billman’s behalf as his review agent.

P1 — Do not treat every empty player as a stale Stop click.

request_active_speaker_cancel now rejects Stop whenever player.empty() is true (desktop/src-tauri/src/huddle/tts_voice_transition.rs:178-188). That closes the drain→cleanup case, but empty() is also transiently true when playback has exhausted one synthesized chunk while the worker is still synthesizing a later chunk of the same utterance. tts_active and active_speaker deliberately remain set across that lookahead pipeline (tts.rs:451-524, 722-856), so the UI still presents that speaker as active. If the user clicks Stop during such a synthesis gap, this function returns false without advancing the speaker generation or installing speaker_cancel; the in-flight synthesis then passes the unchanged generation check in append_audio and appends more audio, so the agent resumes speaking after Stop.

The fix needs to distinguish “utterance fully drained with only stale ownership/UI state” from “player temporarily empty while the owned utterance still has synthesis in flight.” Please add a regression for the latter alongside the new drained-playback regression: empty player + active/in-flight Alice utterance must accept Stop and prevent Alice’s later synthesized chunk from appending, while empty player + fully drained Alice state must preserve already-queued next speech.

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

Copy link
Copy Markdown

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: 241d57ffc4

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +881 to +885
if !agent_is_present {
eprintln!(
"buzz-desktop: tts stage=queue status=dropped reason=speaker_removed route_id={route_id}"
);
return Ok(());

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid dropping relay-verified newly added agents

When an agent is added to the huddle by another participant, the React TTS subscription can authorize that speaker from the relay via get_huddle_agent_pubkeys, but this new native gate still checks only the local hs.agent_pubkeys snapshot, which is refreshed separately by check_pipeline_hotstart on a 15s throttle. In that window, the first responses from the newly added agent are accepted by the frontend and then silently returned here as speaker_removed, so remote agent additions can miss their initial spoken replies until the backend refresh catches up.

Useful? React with 👍 / 👎.

Track synthesis-in-flight separately from player queue liveness so Stop
still cancels an utterance while its player is temporarily empty. Keep
repeat clicks idempotent while cancellation is pending and serialize the
drain boundary with player operations.

Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
wesbillman
wesbillman previously approved these changes Aug 4, 2026
@wesbillman
wesbillman enabled auto-merge (squash) August 4, 2026 19:02
wesbillman and others added 2 commits August 4, 2026 13:44
The terminal z-index is local to the app surface and cannot be compared
against the sibling drawer backdrop. Assert the two relevant stacking
contexts instead so the test remains valid with the docked terminal.

Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
@wesbillman
wesbillman disabled auto-merge August 4, 2026 20:07
@wesbillman
wesbillman merged commit ce3cf3c into main Aug 4, 2026
26 checks passed
@wesbillman
wesbillman deleted the kennylopez-huddle-stop-speaking branch August 4, 2026 20:07
loganj pushed a commit that referenced this pull request Aug 4, 2026
…links

* origin/main:
  fix(desktop): integer-align custom reaction emoji (#4779)
  Polish Huddle voice controls (#4694)
  fix(local-archive): default both archive settings to enabled (#4750)
  fix(mobile): stop oversized read-state retry loop (#4595)

Signed-off-by: npub13n66s06epmqf2kc3v373ez8hj65cuzyvxzjf93vwpervxqn2u7jq2qd9je <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
wpfleger96 added a commit that referenced this pull request Aug 4, 2026
* commit 'ce3cf3cd2': (76 commits)
  Polish Huddle voice controls (#4694)
  fix(local-archive): default both archive settings to enabled (#4750)
  fix(mobile): stop oversized read-state retry loop (#4595)
  fix(desktop): close reconnect gaps that previously required CMD+R (#4737)
  Dock Buzz Term within channel workspace (#4724)
  perf(relay): index channel-id lookups and skip trace-only reads (#4647)
  fix(agents): canonicalize stale persona harness pins (#4631)
  Refine community invite links (#4734)
  feat(desktop): persist sidebar observed-unread across webview reload (#3976)
  feat(desktop): surface config diff in restart-required badge (#3637)
  Polish sidebar unread hierarchy (#4573)
  fix(desktop): show cached display names on startup (#3317)
  docs(acp): explain per-channel session model in base prompt (#4729)
  docs(nip-am): normative amendment — cache SHOULD/MUST + pricingIdentity + consumer cost guidance (#4632)
  Remove blur from Welcome composer guidance (#4691)
  Refine desktop timeline activity presentation (#4582)
  Defer desktop media uploads until send (#4522)
  fix(desktop): stop clipping focus ring on channel intro action cards (#2392) (#4374)
  Polish mobile inbox and media flows (#4512)
  feat: ship Buzz Term (#4347)
  ...

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
wpfleger96 added a commit that referenced this pull request Aug 4, 2026
)

## Summary

Increases three Playwright assertion timeouts in
`tests/e2e/empty-edit-delete.spec.ts` from 5s to 10s to fix a
shard-composition flake introduced by PR #4694.

## Root Cause

PR #4694 added `huddle-transcription.spec.ts` (477 lines, 22+ tests) to
the Desktop Smoke E2E suite, shifting shard 2 composition so that
`empty-edit-delete` now runs with significantly more accumulated browser
state. The three affected assertions all wait for a React state update
triggered by pressing Enter in edit mode:

- `alertdialog` becoming visible after an empty edit (tests 1 and 2)
- `edit-target` hiding after a successful non-empty edit (test 3)

These transitions go through the React scheduler. In isolation they
complete in milliseconds. In a loaded headless shard with accumulated GC
pressure, the 5s window became insufficient — test 3 failed 3/3 times in
CI run
[30946444168](https://github.com/block/buzz/actions/runs/30946444168)
with `edit-target` still visible after Enter.

No product code is changed. The empty-edit-delete flow is correct and
untouched by #4694. This is a test-environment timing adjustment only.

## What Changed

- `tests/e2e/empty-edit-delete.spec.ts` — three `{ timeout: 5_000 }` →
`{ timeout: 10_000 }` for the post-Enter React-update waits

## Validation

- `just desktop-check` — passed
- `just desktop-test` — 4194 passed, 0 failed

Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
shellz-n-stuff added a commit to shellz-n-stuff/buzz that referenced this pull request Aug 4, 2026
…gent-instructions

* origin/main: (30 commits)
  feat: Buzz entity links — rich preview cards + in-app navigation for repos, PRs, and issues (block#4695)
  fix(desktop): serialize tray channel actions for frontend (block#4762)
  chore(release): release Buzz Desktop version 0.5.5 (block#4788)
  feat(projects): support multiple repositories (block#4671)
  fix(ci): make desktop cache test version agnostic (block#4791)
  fix(desktop): widen post-Enter timeouts in empty-edit-delete spec (block#4792)
  fix(desktop): wait for terminal frame before splash (block#4781)
  fix(desktop): integer-align custom reaction emoji (block#4779)
  Polish Huddle voice controls (block#4694)
  fix(local-archive): default both archive settings to enabled (block#4750)
  fix(mobile): stop oversized read-state retry loop (block#4595)
  fix(desktop): close reconnect gaps that previously required CMD+R (block#4737)
  Dock Buzz Term within channel workspace (block#4724)
  perf(relay): index channel-id lookups and skip trace-only reads (block#4647)
  fix(agents): canonicalize stale persona harness pins (block#4631)
  Refine community invite links (block#4734)
  feat(desktop): persist sidebar observed-unread across webview reload (block#3976)
  feat(desktop): surface config diff in restart-required badge (block#3637)
  Polish sidebar unread hierarchy (block#4573)
  fix(desktop): show cached display names on startup (block#3317)
  ...

Signed-off-by: Alex Rosenzweig <arosenzweig@squareup.com>
tellaho pushed a commit that referenced this pull request Aug 4, 2026
…er-snapshots

* origin/main:
  Revert "chore(release): release Buzz Desktop version 0.5.5" (#4797)
  feat: Buzz entity links — rich preview cards + in-app navigation for repos, PRs, and issues (#4695)
  fix(desktop): serialize tray channel actions for frontend (#4762)
  chore(release): release Buzz Desktop version 0.5.5 (#4788)
  feat(projects): support multiple repositories (#4671)
  fix(ci): make desktop cache test version agnostic (#4791)
  fix(desktop): widen post-Enter timeouts in empty-edit-delete spec (#4792)
  fix(desktop): wait for terminal frame before splash (#4781)
  fix(desktop): integer-align custom reaction emoji (#4779)
  Polish Huddle voice controls (#4694)
  fix(local-archive): default both archive settings to enabled (#4750)
  fix(mobile): stop oversized read-state retry loop (#4595)

Co-authored-by: npub14ndfusear8wdpe4kss8h7juc7wjk78atnqzf63zvppcpneknv4sq6x9370 <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz>
Signed-off-by: npub14ndfusear8wdpe4kss8h7juc7wjk78atnqzf63zvppcpneknv4sq6x9370 <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz>

# Conflicts:
#	desktop/src/features/communities/useCommunityInit.ts
#	desktop/src/shared/lib/linkPreview.test.mjs
#	desktop/src/shared/lib/linkPreview.ts
#	desktop/src/shared/lib/useResolvedLinkPreviews.ts
#	desktop/src/shared/ui/link-preview-attachment.tsx
#	desktop/src/shared/ui/markdown.tsx
sandro-sq added a commit that referenced this pull request Aug 4, 2026
* origin/main: (31 commits)
  feat: paste composer text without formatting (#4801)
  Revert "chore(release): release Buzz Desktop version 0.5.5" (#4808)
  chore(release): release Buzz Desktop version 0.5.5 (#4800)
  fix: reauthenticate databricks model discovery (#4008)
  Revert "chore(release): release Buzz Desktop version 0.5.5" (#4797)
  feat: Buzz entity links — rich preview cards + in-app navigation for repos, PRs, and issues (#4695)
  fix(desktop): serialize tray channel actions for frontend (#4762)
  chore(release): release Buzz Desktop version 0.5.5 (#4788)
  feat(projects): support multiple repositories (#4671)
  fix(ci): make desktop cache test version agnostic (#4791)
  fix(desktop): widen post-Enter timeouts in empty-edit-delete spec (#4792)
  fix(desktop): wait for terminal frame before splash (#4781)
  fix(desktop): integer-align custom reaction emoji (#4779)
  Polish Huddle voice controls (#4694)
  fix(local-archive): default both archive settings to enabled (#4750)
  fix(mobile): stop oversized read-state retry loop (#4595)
  fix(desktop): close reconnect gaps that previously required CMD+R (#4737)
  Dock Buzz Term within channel workspace (#4724)
  perf(relay): index channel-id lookups and skip trace-only reads (#4647)
  fix(agents): canonicalize stale persona harness pins (#4631)
  ...

Signed-off-by: Alessandro Joabar <sandro@squareup.com>
loganj added a commit that referenced this pull request Aug 10, 2026
…links

* origin/main:
  fix(desktop): integer-align custom reaction emoji (#4779)
  Polish Huddle voice controls (#4694)
  fix(local-archive): default both archive settings to enabled (#4750)
  fix(mobile): stop oversized read-state retry loop (#4595)

Signed-off-by: npub13n66s06epmqf2kc3v373ez8hj65cuzyvxzjf93vwpervxqn2u7jq2qd9je <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>

Co-authored-by: npub13n66s06epmqf2kc3v373ez8hj65cuzyvxzjf93vwpervxqn2u7jq2qd9je <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
Signed-off-by: Logan Johnson <loganj@squareup.com>
bhargavms pushed a commit to EWA-Services/buzz that referenced this pull request Aug 18, 2026
## Summary

- add a visible Stop control for interrupting agent speech
- make push-to-talk available by default while preserving manual mute
controls
- refine agent management, muted audio states, drawer layering, and
return navigation
- suppress duplicate notification sounds for Huddle messages

## Why

Huddles could trap users behind long agent speech, hide useful agent
controls, and leave temporary Huddle state visible after the call. The
drawer also regressed when the terminal substrate began painting behind
the rounded app surface.

## Validation

- `just desktop-ci`
- focused Huddle Playwright coverage for the drawer, speech
interruption, agent picker, and leave navigation

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
Signed-off-by: bhargavms <bhargav.m@ewa-services.com>
bhargavms pushed a commit to EWA-Services/buzz that referenced this pull request Aug 18, 2026
…ock#4792)

## Summary

Increases three Playwright assertion timeouts in
`tests/e2e/empty-edit-delete.spec.ts` from 5s to 10s to fix a
shard-composition flake introduced by PR block#4694.

## Root Cause

PR block#4694 added `huddle-transcription.spec.ts` (477 lines, 22+ tests) to
the Desktop Smoke E2E suite, shifting shard 2 composition so that
`empty-edit-delete` now runs with significantly more accumulated browser
state. The three affected assertions all wait for a React state update
triggered by pressing Enter in edit mode:

- `alertdialog` becoming visible after an empty edit (tests 1 and 2)
- `edit-target` hiding after a successful non-empty edit (test 3)

These transitions go through the React scheduler. In isolation they
complete in milliseconds. In a loaded headless shard with accumulated GC
pressure, the 5s window became insufficient — test 3 failed 3/3 times in
CI run
[30946444168](https://github.com/block/buzz/actions/runs/30946444168)
with `edit-target` still visible after Enter.

No product code is changed. The empty-edit-delete flow is correct and
untouched by block#4694. This is a test-environment timing adjustment only.

## What Changed

- `tests/e2e/empty-edit-delete.spec.ts` — three `{ timeout: 5_000 }` →
`{ timeout: 10_000 }` for the post-Enter React-update waits

## Validation

- `just desktop-check` — passed
- `just desktop-test` — 4194 passed, 0 failed

Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
Signed-off-by: bhargavms <bhargav.m@ewa-services.com>
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>
kaalph pushed a commit to kaalph/buzz that referenced this pull request Aug 21, 2026
* commit 'f1181fd31': (76 commits)
  Polish Huddle voice controls (block#4694)
  fix(local-archive): default both archive settings to enabled (block#4750)
  fix(mobile): stop oversized read-state retry loop (block#4595)
  fix(desktop): close reconnect gaps that previously required CMD+R (block#4737)
  Dock Buzz Term within channel workspace (block#4724)
  perf(relay): index channel-id lookups and skip trace-only reads (block#4647)
  fix(agents): canonicalize stale persona harness pins (block#4631)
  Refine community invite links (block#4734)
  feat(desktop): persist sidebar observed-unread across webview reload (block#3976)
  feat(desktop): surface config diff in restart-required badge (block#3637)
  Polish sidebar unread hierarchy (block#4573)
  fix(desktop): show cached display names on startup (block#3317)
  docs(acp): explain per-channel session model in base prompt (block#4729)
  docs(nip-am): normative amendment — cache SHOULD/MUST + pricingIdentity + consumer cost guidance (block#4632)
  Remove blur from Welcome composer guidance (block#4691)
  Refine desktop timeline activity presentation (block#4582)
  Defer desktop media uploads until send (block#4522)
  fix(desktop): stop clipping focus ring on channel intro action cards (block#2392) (block#4374)
  Polish mobile inbox and media flows (block#4512)
  feat: ship Buzz Term (block#4347)
  ...

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
kaalph pushed a commit to kaalph/buzz that referenced this pull request Aug 21, 2026
kaalph pushed a commit to kaalph/buzz that referenced this pull request Aug 21, 2026
…er-snapshots

* origin/main:
  Revert "chore(release): release Buzz Desktop version 0.5.5" (block#4797)
  feat: Buzz entity links — rich preview cards + in-app navigation for repos, PRs, and issues (block#4695)
  fix(desktop): serialize tray channel actions for frontend (block#4762)
  chore(release): release Buzz Desktop version 0.5.5 (block#4788)
  feat(projects): support multiple repositories (block#4671)
  fix(ci): make desktop cache test version agnostic (block#4791)
  fix(desktop): widen post-Enter timeouts in empty-edit-delete spec (block#4792)
  fix(desktop): wait for terminal frame before splash (block#4781)
  fix(desktop): integer-align custom reaction emoji (block#4779)
  Polish Huddle voice controls (block#4694)
  fix(local-archive): default both archive settings to enabled (block#4750)
  fix(mobile): stop oversized read-state retry loop (block#4595)

Co-authored-by: npub14ndfusear8wdpe4kss8h7juc7wjk78atnqzf63zvppcpneknv4sq6x9370 <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz>
Signed-off-by: npub14ndfusear8wdpe4kss8h7juc7wjk78atnqzf63zvppcpneknv4sq6x9370 <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz>

# Conflicts:
#	desktop/src/features/communities/useCommunityInit.ts
#	desktop/src/shared/lib/linkPreview.test.mjs
#	desktop/src/shared/lib/linkPreview.ts
#	desktop/src/shared/lib/useResolvedLinkPreviews.ts
#	desktop/src/shared/ui/link-preview-attachment.tsx
#	desktop/src/shared/ui/markdown.tsx
BradGroux pushed a commit to BradGroux/buzz that referenced this pull request Aug 23, 2026
## Summary

- add a visible Stop control for interrupting agent speech
- make push-to-talk available by default while preserving manual mute
controls
- refine agent management, muted audio states, drawer layering, and
return navigation
- suppress duplicate notification sounds for Huddle messages

## Why

Huddles could trap users behind long agent speech, hide useful agent
controls, and leave temporary Huddle state visible after the call. The
drawer also regressed when the terminal substrate began painting behind
the rounded app surface.

## Validation

- `just desktop-ci`
- focused Huddle Playwright coverage for the drawer, speech
interruption, agent picker, and leave navigation

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
BradGroux pushed a commit to BradGroux/buzz that referenced this pull request Aug 23, 2026
…ock#4792)

## Summary

Increases three Playwright assertion timeouts in
`tests/e2e/empty-edit-delete.spec.ts` from 5s to 10s to fix a
shard-composition flake introduced by PR block#4694.

## Root Cause

PR block#4694 added `huddle-transcription.spec.ts` (477 lines, 22+ tests) to
the Desktop Smoke E2E suite, shifting shard 2 composition so that
`empty-edit-delete` now runs with significantly more accumulated browser
state. The three affected assertions all wait for a React state update
triggered by pressing Enter in edit mode:

- `alertdialog` becoming visible after an empty edit (tests 1 and 2)
- `edit-target` hiding after a successful non-empty edit (test 3)

These transitions go through the React scheduler. In isolation they
complete in milliseconds. In a loaded headless shard with accumulated GC
pressure, the 5s window became insufficient — test 3 failed 3/3 times in
CI run
[30946444168](https://github.com/block/buzz/actions/runs/30946444168)
with `edit-target` still visible after Enter.

No product code is changed. The empty-edit-delete flow is correct and
untouched by block#4694. This is a test-environment timing adjustment only.

## What Changed

- `tests/e2e/empty-edit-delete.spec.ts` — three `{ timeout: 5_000 }` →
`{ timeout: 10_000 }` for the post-Enter React-update waits

## Validation

- `just desktop-check` — passed
- `just desktop-test` — 4194 passed, 0 failed

Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
BradGroux pushed a commit to BradGroux/buzz that referenced this pull request Aug 23, 2026
…#6431)

## 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

- **`af68c34e7` (block#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,
`5a361f99e` (block#4694) flipped the default input mode from VAD to
push-to-talk, which masked the loss.
- **`5214a0755` (block#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 block#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 `8f2b659fe` 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 `af68c34e7^` 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>
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