[upstream-sync] block/buzz 9e0c6b432..eedcd886a (14 commits) - #28
[upstream-sync] block/buzz 9e0c6b432..eedcd886a (14 commits)#28adrienlacombe wants to merge 18 commits into
Conversation
## Summary - render shared-agent instructions as literal text so Markdown cannot conceal spoiler contents, link destinations, or image sources - reject non-reviewable Unicode controls at every agent-definition boundary while preserving legitimate rendered emoji sequences - verify shared catalog event IDs and signatures before trusting authorship, coordinates, pagination, or executable content - preserve the exact system-prompt bytes between review and execution instead of silently stripping or normalizing content ## Security rationale Shared system prompts are executable configuration. Previously, catalog prompts were projected through the chat Markdown renderer, which could hide text, replace link destinations with benign labels, and turn image syntax into remote loads. Zero-width and bidirectional controls could also make reviewed text differ from what the agent executes. This change establishes a review invariant: the prompt a user sees is the prompt the agent executes. Definitions that cannot be reviewed faithfully are rejected rather than rewritten. Catalog events must also pass Nostr ID/signature verification before they can claim a publisher, coordinate, or cursor. ## What changed - catalog instructions render as exact literal text rather than rich Markdown - catalog relay events are verified on a fresh wire-shaped object before paging, coordinate selection, attribution, or projection - forged content, pubkeys, signatures, and invalid newer heads are ignored and cannot shadow a valid signed definition - TypeScript catalog parsing rejects unsafe remote definitions before they reach the UI - shared Rust validation covers persona create/update/import, inbound relay sync, definition-less managed-agent sync, and catalog publication paths - definition-less managed agents now fail closed on local create, local update, and publication before persistence or relay retention - linked managed agents validate their local name while treating the persona definition as authoritative; their inert record-level prompt is not executed or published - names reject layout controls; prompts retain ordinary newlines and tabs - legitimate emoji composition is supported, including contextual VS16, ZWJ, skin-tone, family, flag, and keycap sequences - detached selectors/joiners, bidirectional controls, tag characters, zero-width concealment, and other default-ignorables remain rejected - names are bounded to 128 characters and prompts to 64 KiB - contributor guidance documents the byte-for-byte review requirement for future sharing paths Validation reports the offending code point and never silently removes it. ## E2E recording [buzz-shared-agent-security-e2e.webm](https://github.com/user-attachments/assets/44d6b75f-0877-490f-bda4-a716fae3f700) The recording demonstrates: - a safe definition remains visible - a prompt containing zero-width `U+200B` is rejected - a name containing bidi override `U+202E` is rejected - the prompt is preserved exactly - spoiler, link, and image syntax remains literal and does not render or load ## Verification Passed locally: - `just test`: all 10 unit and Docker-backed integration stages - desktop frontend unit suite: 4,295 tests - persona catalog relay unit suite: 32 tests, including forged-event and cursor-shadowing cases - focused Rust definition-validation coverage: 3 local create/update tests and 6 publication-filtered tests - complete desktop Tauri library suite after rebase: 2,263 passed, 14 ignored, 0 failed - desktop Tauri clippy with warnings denied and Rust formatting - complete agent Playwright spec: 34 tests - the exact formerly failing `inbox-edit` immediate-attachment smoke test after rebase: 1 test - focused shared-agent publish, literal-review, hidden-control, signature, and cross-member import Playwright coverage - desktop E2E production build and TypeScript typecheck - changed-file formatting/lint and file-size ratchet - pre-commit secret scan and DCO signoff The branch was rebased onto current `main`, which includes the upstream attachment-button label fix. Fresh post-rebase GitHub CI is green for every required and selected check: Desktop Core, all four Desktop Smoke E2E shards, both Desktop E2E Integration shards and their aggregate, Desktop E2E Relay, Desktop Build (macOS), Windows Rust, Rust Lint, DCO, security scanners, and Desktop Release Candidate. The previously failing `Desktop Smoke E2E (3)` shard now passes. The repository-wide desktop check also reports existing CSS formatting/`!important` findings in `components.css` and `terminal.css`; neither file is changed by this PR. GitHub's Desktop Core lint and format stage passes on the rebased branch. --------- Signed-off-by: Alex Rosenzweig <arosenzweig@squareup.com>
## Summary - add a permission-gated mobile community invite page - create, copy, and natively share configurable invite links - invite a validated npub directly with member/admin role selection - reuse Buzz profile actions, search styling, settings rows, and modal sheets ## Validation - `just mobile-check` - `flutter test` (1,275 tests) - Pixel and iPhone review builds installed and launched --------- Signed-off-by: kenny lopez <klopez4212@gmail.com> Signed-off-by: Kenny Lopez <klopez4212@gmail.com> Signed-off-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz> Co-authored-by: Carl <3c4caeafb646d23867f1c4832e68211d77e2561946171625f75c3ce1a3f2670f@buzz.block.builderlab.xyz> Co-authored-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz>
## Summary - reuse the channel member snapshot so first-use `@` suggestions appear immediately - reduce selection-only composer rebuilds so iOS selection handles stay responsive - make Return insert a newline, send only from the composer button, and animate multiline growth with reduced-motion support ## Validation - `just mobile-check` - `just mobile-test` — 1,271 tests passed - signed iPhone Release and Pixel 10 debug builds installed and launched - `just ci` passed mobile, Rust, desktop, and web checks until the unrelated `buzz-terminal` lifecycle test timed out waiting for `$0`; reproduced unchanged in isolation --------- Signed-off-by: kenny lopez <klopez4212@gmail.com> Signed-off-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz Signed-off-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz> Co-authored-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz>
**Category:** improvement **User Impact:** Compact link previews now use a single-line title and smaller thumbnail, making conversations easier to scan. **Problem:** Compact previews gave long titles and oversized thumbnails too much visual weight in the message timeline. **Solution:** Keep titles to one ellipsized line and reduce image thumbnails to a 104×64 treatment while preserving the existing wide aspect ratio; Rich previews remain unchanged. <details> <summary>File changes</summary> **desktop/src/shared/ui/compact-link-preview-attachment.tsx** Tightens the Compact presentation with a single-line title and smaller wide thumbnail, leaving Rich previews untouched. **desktop/tests/e2e/messaging.spec.ts** Adds focused coverage for title overflow, exact 64px card and 104×64 thumbnail geometry, and successful decoded-image rendering using a realistic fixture, plus an optional visual capture. **desktop/tests/fixtures/github-pr-5629-og.png** Provides realistic visible image bytes for the compact-preview image-rendering E2E path. </details> ## Reproduction steps 1. Launch the desktop app with link preview style set to Compact. 2. Send a link whose preview has an image and a long title. 3. Confirm the thumbnail renders at the smaller wide size and the title truncates to one line with an ellipsis. 4. Switch link preview style to Rich and confirm its presentation is unchanged. ## Screenshot  --------- Signed-off-by: Taylor Ho <taylorkmho@gmail.com> Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz>
## Summary - persist stable workflow run `error_code` values separately from human diagnostics - expose NIP-98 authenticated, channel-authorized run history and approval reads with stable keyset pagination - connect Desktop to those authoritative reads and return the relay-created run ID on trigger - show truthful loading, failure, and pending-trace states, and do not render approval actions from non-actionable stored hashes ## Validation - pre-push `branch-skew`, `desktop-typecheck`, `desktop-test`, `rust-tests`, `desktop-tauri-checks`, and `desktop-check` all passed on `a097dbe5f` - Desktop tests: 4,761 passed, 0 failed - `cargo check -p buzz-relay` - `git diff --check` ## Remaining gate This does not claim a relay-backed Playwright workflow journey. The browser relay bridge still routes workflow invokes through in-memory handlers; that production-shaped acceptance gate remains follow-up work before Workflows can leave preview. --------- Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz> Co-authored-by: Mongo <5c25403eab7271f9f94ddd4f2b270e8cac2c92e2c830c51877cca6ec974ffb3f@buzz.block.builderlab.xyz> Co-authored-by: Princess Donut <68157ebd23b3897c1991015c3038658ea916200c67d3a54620b0754d1b92f6e0@buzz.block.builderlab.xyz>
…oxy (block#5799) **Category:** fix (CI) **User Impact:** None — test-only change that unblocks `main` and every open PR. **Problem:** `main` has been red since block#5629 landed on `45f4b91a3`: `Desktop Smoke E2E (3)` fails `compact link preview image geometry truncates long titles to one line` on every build (main run 31727837133, and e.g. block#5792, block#5790). Two independently-green PRs raced: block#5629 added the test stubbing its preview image at the raw relay origin (`http://localhost:3000/media/*.png`), while block#5627 rewrites sent snapshot media through the authenticated local media proxy (`http://127.0.0.1:54321` in the E2E mock bridge). Merged together, the image request goes to the proxy origin, the stub never matches, and `naturalWidth` stays `0`. **Solution:** Point the route stub at the mock proxy origin, matching the existing `sent link preview media uses the authenticated proxy in compact and rich cards` test in the same spec. **Testing:** Reproduced the failure locally on `45f4b91a3`, then with this fix: targeted test passes, and the full `messaging.spec.ts` smoke suite passes 58/58. Signed-off-by: Thomas Petersen <thomasp@squareup.com> Co-authored-by: Wintermute <3f1797424fd9ad6653a83665c660517777cd7f8c228c0d5907f49e01537f3ca5@buzz.block.builderlab.xyz>
…lock#5681) ## Summary - allow channel-member remote/headless agents only with current kind `10100` directory evidence, while stale member identities remain hidden - fail closed while managed/relay directories load, error, or background-refetch across channel, forum, and cached autocomplete surfaces - revalidate agent mention authorization immediately before normal sends and message-edit saves, including after deferred uploads - in owner-only builds, fetch fresh authoritative profile ownership at send time and deny missing, changed-owner, or unavailable proofs - preserve human mention tags when agent authorization is revoked or unknown Supersedes block#5536 because its contributor-fork head cannot be updated by maintainers. ## Validation Exact head: `7278cdd5fbcee676c7b858ea098503c62eeeff0d` - mandatory pre-push suites passed: desktop check/typecheck/tests, Rust tests, mobile tests, desktop Tauri checks, branch-skew - desktop unit tests: 4,732 passed - focused edit/ownership regressions: 8 passed - focused mention E2E: 5 passed (remote positive, stale-member negative, directory error, pre-send revocation, mid-send revocation) - file-size ratchet passed One first focused E2E batch had a timing-only miss where the send click did not emit; the isolated rerun passed. One separate pre-push attempt hit the existing randomized passphrase separator test; the successful exact-head push reran and passed the mandatory suite. --------- Signed-off-by: JDiz00 <174381550+JDiz00@users.noreply.github.com> Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: JDiz00 <174381550+JDiz00@users.noreply.github.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
### What changed? Inbox message action menus now show a standalone Delete action beside Edit for manageable messages. Delete reuses the existing confirmation and targets the message whose menu was opened, while the existing empty-edit deletion path remains unchanged. ### Why? Inbox users can delete a message directly without first entering edit mode. Thread context can contain multiple messages, so the action must preserve the active Inbox selection and delete only the chosen row. ### How is it tested? Desktop checks, typechecking, builds, and test suites pass. Added tests: - [Inbox edit and delete E2E coverage](https://github.com/block/buzz/tree/main/desktop/tests/e2e/inbox-edit.spec.ts) Signed-off-by: Tom Brow <tomb@block.xyz> Co-authored-by: Codex <noreply@openai.com>
## Summary - return complete channel rosters instead of truncating at 1,000 members - chunk `event_mentions` inserts inside one transaction so large kind `39002` snapshots remain discoverable by every `p` tag - add a targeted `buzz-admin reconcile-channels --channel <uuid>` force-republish path for stale discovery snapshots - cover a 1,501-member roster, 11,000-tag mention index, and kind `39002` tag construction past member 1,000 ## Why The relay builds NIP-29 discovery and several authorization decisions from `get_members()`, but that helper silently returned only the first 1,000 active members. Desktop then counted the truncated kind `39002` event, while late members could be rejected by roster-scanning member actions. Removing the roster cap exposes PostgreSQL's 65,535 bind-parameter ceiling in mention indexing, so the insert is chunked transactionally to preserve all-or-nothing indexing. The existing reconcilers only fill missing discovery events. The targeted admin option bypasses the separately known 1,000-channel reconciliation-list ceiling and replaces an existing channel snapshot using the configured production relay key. ## Attribution This supersedes and builds on block#3166 by @LordMelkor. Thank you for identifying the roster boundary and contributing the original complete-roster and mention-index patch. The production roster/query changes and the two PostgreSQL regressions retain that work's shape; this PR rebases it onto current `main`, adds relay coverage, and adds the targeted repair operation requested for rollout. ## Validation Exact pushed head: `24d02e4f3824150ed84913c9d230e675502e5b12` - `cargo check -p buzz-db -p buzz-admin` - `cargo test -p buzz-db channel::tests::get_members_returns_full_roster_beyond_1000 -- --ignored --exact --nocapture` - `cargo test -p buzz-db feed::tests::insert_mentions_indexes_rosters_past_bind_parameter_cap -- --ignored --exact --nocapture` - `cargo test -p buzz-relay --lib handlers::side_effects::tests::group_members_snapshot_keeps_members_past_one_thousand -- --exact` - `cargo run -q -p buzz-admin -- reconcile-channels --help` - mandatory pre-push hook: branch-skew, desktop checks/typecheck/tests, mobile tests, Rust tests, and desktop Tauri checks all passed on the pushed head ## Rollout 1. Deploy the relay/backend build. 2. Run `buzz-admin reconcile-channels --channel <general-channel-uuid>` with `BUZZ_RELAY_PRIVATE_KEY` configured. 3. Verify the replacement kind `39002` roster count matches the active database membership count. No schema migration or desktop release is required. Fixes block#3156 Supersedes block#3166 --------- Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
## Summary - add `just desktop-release-smoke`, a deterministic desktop correctness/reachability smoke against an ephemeral real local relay - preserve existing DM history when the first live DM enters a pageless query window, the desktop-v0.5.10 disappearing-DM regression - enforce foreground JS ordering: a frame and actionable sidebar input must dispatch before mounted stale queries begin resume refetches, while separately requiring the navigation to commit promptly - seed a 10,000-event dense-second fixture and verify exact event-ID reachability, SHA-256 identity, ordering, duplicate absence, bounded mounted rows, and drained render work - isolate Postgres per run, serialize the shared Redis DB, retain phase/relay/Playwright diagnostics, and gate desktop release manifest assembly on the smoke This is deliberately **not a performance-regression gate**. CDP and action timing fields are informational only. There is no candidate/baseline comparison or threshold. A future performance lane needs repeated equivalent fixtures, discrete interaction samples, and an explicit comparator/noise policy. The diagnostics record the fixture version, row count, wall-clock base timestamp (`fixtureSecond`), expected event-ID hash, observed state, and measurements. Because the created-at floor requires a current timestamp, paired comparison remains disabled. The release job runs on an isolated GitHub-hosted runner. The script also guards automatic local runs with a Redis allocation lock. Its remaining direct-PID cleanup and free-port selection race mean it should not be repurposed onto a persistent concurrent shared runner without first hardening process-group cleanup and port reservation. ### Related issue N/A ### Testing - `pnpm --dir desktop typecheck` - focused real-local-relay release smoke passed after adversarial review fixes - identical DM witness passed current and failed `desktop-v0.5.10` with the history-loss signature - identical foreground witness bytes (`2c1e97df04c9b8ca0304b66bbbe9bdb4d08924ad8ce0f68a9c490458fcc3aca8`) failed `desktop-v0.5.10` structurally: the first resume fetch was marker 1, before first frame/sidebar dispatch at marker 8 - with PR block#5696 (`59f613c40`) merged, the witness showed focus at 951.3 ms, first frame at 951.6 ms, click dispatch at 952.1 ms, first resume fetch at 968.9 ms, and route commit at 992.4 ms - the gate therefore protects first paint and actionable input dispatch; route commit is a bounded responsiveness witness, not a prerequisite for resume work - the corrected focused foreground scenario passed at `6d9b5be40da58bbee92a856b04c3558946d0a950`; the prior merged-tree full run passed DM retention and 10k reachability before exposing this contract mismatch - pre-push passed on exact pushed head `6d9b5be40da58bbee92a856b04c3558946d0a950`, including desktop checks, typecheck, desktop tests, Rust tests, mobile tests, and Tauri checks - full 10,000-event scenario reached 10,000/10,000 exact IDs with matching SHA-256, 199 continuation requests, and 95 mounted rows in about 4.4 minutes - reduced-row review run passed in 18.4 seconds ### Foreground witness boundary The Chromium test is a deterministic JS policy gate. Headless Chromium does not expose an honest blur/focus transition in this fixture, so the test drives the production focus listener and `document.hasFocus()` predicate together and records that simulation explicitly. It proves refetch fan-out ordering, not AppKit activation, WKWebView paint, or an activating physical click. A packaged macOS native lane is still required before claiming the actual desktop activation experience is certified. --------- Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
## Summary - inset the in-app Huddle tray with four rounded corners and even 8px spacing when Glass background is enabled - keep the popped-out Huddle dock full-width - hide and suppress Glass background on Linux ## Why The in-app tray reused the opaque backing needed by non-glass windows, which covered the native vibrancy around it. Linux does not support this window treatment. ## Testing - `pnpm -C desktop build:e2e` - focused Appearance and Huddle Playwright smoke tests - pre-push desktop checks, typecheck, and 4,666 unit tests --------- Signed-off-by: kenny lopez <klopez4212@gmail.com> Signed-off-by: Princess Donut <b238ea756dee4d98afa5883fc7f1de61eeabe65bf700e3a5a5a80db5e42e2c2b@buzz.block.builderlab.xyz> Co-authored-by: Princess Donut <b238ea756dee4d98afa5883fc7f1de61eeabe65bf700e3a5a5a80db5e42e2c2b@buzz.block.builderlab.xyz>
## Summary - avoid blocking first-DM navigation on a full channel-list refresh - publish the initial message through the acknowledged HTTP path instead of waiting on a missing WebSocket acknowledgement ## Validation - 4,715 desktop unit tests - desktop typecheck and checks - focused new-DM Playwright coverage --------- Signed-off-by: kenny lopez <klopez4212@gmail.com> Co-authored-by: Mongo <9cfd347903944d5b85aa6c93d2ab67381b978a92a31914bca69998968752a1d7@buzz.block.builderlab.xyz>
… s (env-gated latency levers) (block#5671) ## Overview **Category:** feat (env-gated experiment + one exact always-on optimization) **Problem:** Speech-end -> first TTS audio through the desktop huddle pipeline measures **924–1087 ms** on an M4 Max with a 0 ms LLM leg. Voice turns feel sluggish no matter how fast the agent replies. Baseline breakdown: ~300 ms hardcoded VAD silence flush + ~150–250 ms Parakeet decode + ~380–550 ms TTS synthesis before the first player append. **Outcome:** With all levers enabled, e2e time-to-first-audio measures **347–384 ms** (307–357 ms on a longer utterance) on the same hardware, harness, and production pipelines. Defaults preserve production behavior everywhere except one deterministic, bit-exact cache win. ## What's in here ### Levers (all default-off, env-gated) | Lever | Env | Effect (measured medians, short utterance) | |---|---|---| | Speculative Parakeet decode | `BUZZ_STT_SPECULATIVE=1` | STT leg -> ~max(flush, decode) | | Streaming TTS synthesis | `BUZZ_TTS_STREAMING=1`, `BUZZ_TTS_EMIT_FRAMES` | first audio 380–550 -> 211–320 ms (emit=12, bit-exact) | | ONNX intra-op threads | `BUZZ_STT_THREADS`, `BUZZ_TTS_THREADS` | TTS first audio 211–320 -> 129–180 ms (4 threads) | - **Speculative decode** starts the Parakeet decode at the *first* silent VAD frame, overlapping it with the flush window. Resumed speech invalidates the result (voiced-frame-count check); held silence emits it instantly at the flush boundary. - **Streaming TTS**: new `synth_chunk_streaming` (buzz-voice) interleaves the Flow LM frame loop with incremental *stateful* Mimi decoding, emitting PCM deltas to the player via the existing `PlaybackChunkAudio` decoration. At `emit_frames=12` (the decoder's native chunk) streamed audio is **bit-identical** to the batch path — verified by the ignored test `incremental_stateful_decode_matches_batch_decode` (max|diff|=0). Smaller deltas are faster but diverge (~23 dB SNR; decoder intra-chunk lookahead), hence the default of 12. > **Removed after live testing:** the `BUZZ_STT_FLUSH_MS` flush-window override. Lowering the silence window below natural mid-sentence pauses (the fast-path recipe said 150 ms) split single spoken sentences into multiple messages and confused the listening agents. The window is a turn-taking quality knob, not a latency lever — it is now fixed at the production 300 ms value. ### Push-to-talk grouping fix (always-on) A held push-to-talk shortcut is an explicit "I am not done talking" signal, so silence never ends the utterance while it is held — even when the microphone is also manually open. The utterance flushes on shortcut release (existing transmit-edge flush); a manually open mic with the shortcut up keeps normal VAD pause flushing. Gate is the pure `vad_flush_allowed` function with a unit-test truth table. ### Always-on (exact): voice-conditioning cache Phase profiling (`BUZZ_TTS_PHASE_LOG=1`) showed a fixed ~160 ms `condition_voice` Flow-LM pass on *every* chunk, re-deriving the same post-conditioning state for the same reference voice. The state is now snapshotted after first computation and restored per chunk (dtype-tagged tensor copies, keyed identically to the existing `cached_voice`). Deterministic — same tensors in, same tensors out. The default path's TTS leg drops from 380–550 ms to 225–355 ms with no configuration. ### Bench harness `huddle::latency_bench` (`#[cfg(test)]` + `#[ignore]`) drives the real `SttPipeline` and `TtsPipeline`, feeding a 48 kHz WAV in real-time 100 ms batches (AudioWorklet cadence) with a configurable fake LLM in place of the relay leg, timing speech-end -> transcript -> speak() -> first accepted player append. ``` BUZZ_STT_SPECULATIVE=1 BUZZ_TTS_STREAMING=1 \ BUZZ_TTS_THREADS=4 BUZZ_STT_THREADS=2 \ BUZZ_BENCH_WAV=<48k f32 mono wav> \ cargo test --release -p buzz-desktop --lib huddle::latency_bench -- --ignored --nocapture ``` ## Tradeoffs to weigh before promoting any lever to a default - **Speculative decode**: the speculative buffer has ~1 silent tail frame vs ~19; observed one CTC wobble ("fail" vs "failed") in 24 turns. Mitigation if productionized: zero-pad the speculative buffer to match the flush-path shape. - **Threads**: defaults stay 1 pending the min-spec (4-core Intel) A/B flagged in the existing `STT_NUM_THREADS` comment. - **Streaming at emit<12** is NOT the same waveform — don't ship below 12 without an ear pass. ## Validation - Full desktop lib suite: **2408 passed / 0 failed** at this head (`18fab2e1c`). - buzz-voice suite green; bit-exactness test passes against the production batch decode. - Defaults-only bench rerun stays in the baseline family everywhere except the exact conditioning-cache win (stt 525–532, tts 225–355). - `cargo clippy --workspace --all-targets -- -D warnings` + fmt clean (pre-push hook battery green). Measurement notes with per-lever logs: Eva's workspace, `RESEARCH/HUDDLE_E2E_LATENCY_OPTIMIZATION_2026_08_12.md` + `RESEARCH/HUDDLE_E2E_STT_FAKELLM_TTS_BASELINE_2026_08_12.md`. ## Suggested promotion order 1. Conditioning cache (in this PR, always-on, exact). 2. Streaming TTS at emit=12: bit-exact audio, biggest UX win — needs the env-gate removed + barge-in soak + an ear pass on a real huddle. 3. Speculative decode with silence padding: near-free ~100–150 ms. 4. Threads: after min-spec A/B. --------- Signed-off-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz> Signed-off-by: Wren <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@buzz.block.builderlab.xyz> Signed-off-by: Max <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@buzz.block.builderlab.xyz> Signed-off-by: Mari <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@buzz.block.builderlab.xyz> Signed-off-by: tlongwell-block <tlongwell@block.xyz> Co-authored-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz> Co-authored-by: Wren <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@buzz.block.builderlab.xyz> Co-authored-by: Max <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@buzz.block.builderlab.xyz> Co-authored-by: Mari <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@buzz.block.builderlab.xyz> Co-authored-by: tlongwell-block <tlongwell@block.xyz>
…ell (block#5711) ## Problem In compact link preview cards with an image, the thumbnail's corners looked inconsistent — the flush left side and the interior right side read as different shapes. ## Cause The `Attachment` shell rounds its corners with a **smooth-corner (squircle) clip path** via `useSmoothCorners`, not a plain `border-radius`. In compact image mode the shell has `p-0`, so the thumbnail sits flush against its left, top, and bottom edges. That means: - **Left corners** are carved by the shell's smoothed clip path. - **Right corners** are drawn by the thumbnail's own plain `border-radius`. A circular arc and a smoothed corner of the *same* radius are different shapes (at 16px the smoothed curve starts 25.6px along the edge instead of 16px). So the two sides could never match by picking a radius value — the thumbnail's class has no effect on its left corners at all. ## Fix Give the thumbnail the same `useSmoothCorners` treatment as the shell, so both sides share one curve. - Radius token unchanged: `rounded-2xl` (16px). - The shell and the shared `Attachment` component are untouched, so no other `Attachment` consumer changes. Verified on a rendered card — thumbnail vs shell now agree on all three: arc radius (16), smoothing (0.6), and curve start (25.6px). ## Hardening The underlying issue is an invariant that lived nowhere: **a child flush against a smooth-cornered parent must share its corner treatment.** This is why the bug was easy to introduce and hard to diagnose. - Documented the invariant in `smoothCorners.ts`, where anyone reaching for the hook will see it. - Added an `expectSmoothCorners()` guard to the existing compact-preview e2e test. Confirmed it **fails** when the fix is reverted, so it genuinely bites. Note: this cannot be a lint rule — "flush" is a runtime layout fact, not visible in the source. ## Known follow-up (not in this PR) The composer link preview (`useComposerLinkPreviews.tsx`) has the same latent issue: a flush thumbnail with a hand-copied `rounded-l-2xl` that happens to match the shell's current 16px. It is correct today only by coincidence of two literals agreeing. Left for a separate PR rather than expanding scope here. ## Screenshots The same compact card and content before and after the change. | Before | After | | --- | --- | | Original `rounded-xl` (12px) thumbnail: left corners are clipped by the card’s 16px smooth silhouette while the right corners keep the thumbnail’s smaller plain radius | `rounded-2xl` (16px) thumbnail with the same smooth-corner treatment as the card | |  |  | ## Verification - `pnpm exec biome check` on all three touched files - `pnpm exec tsc --noEmit` - `node --test src/shared/ui/smoothCorners.test.mjs` — 3 passed - All 18 link-preview e2e tests pass - Guard verified to fail without the fix, then pass with it Signed-off-by: morgmart <98432065+morgmart@users.noreply.github.com>
Sync 14 upstream commits (9e0c6b4..eedcd88). Conflicts, all at documented fork patch sites: - migrations/: upstream's 0031_workflow_run_error_codes.sql renumbered to 0033. The fork holds 0027 and 0028 and both have run on the live database, so sqlx checksums mean the fork's cannot move; upstream's has never run here, so it is the one that renumbers. Contents byte-identical. - crates/buzz-db/src/migration.rs: count 32 -> 33, and upstream's new workflow_run_error_codes test shifted from migrations[30]/version 31 to migrations[32]/version 33. Only the count arrived as a conflict; the indexed assertions merged as clean context. - .github/workflows/release.yml: upstream block#5699 added desktop-release-smoke, pinned to block/buzz, and required its success in assemble-manifest. Only the needs: list conflicted -- the gate condition merged silently. In a fork that job always reports skipped, so requiring success would strand latest.json again, the same breakage as block#3568. Accept success||skipped, matching the release-macos-x64 treatment. - desktop/src-tauri/src/relay.rs: kept both the fork's `pub mod allowlist;` and upstream's new `mod get;`. Signed-off-by: adrienlacombe <6303520+adrienlacombe@users.noreply.github.com>
The merged lock left buzz-admin's `uuid` entry undisambiguated. Upstream's buzz-admin change brings a second uuid version (0.8.2) into the tree alongside 1.23.1, so the bare name no longer resolves and `cargo metadata --locked` fails. Regenerated rather than hand-edited, per AGENTS.md. The only change is the disambiguating version suffix; no dependency version moved. Local gates read the working tree, so an unstaged re-resolve passes here and fails only in CI -- verify both locks from the committed state. Signed-off-by: adrienlacombe <6303520+adrienlacombe@users.noreply.github.com>
…ssion Two shape changes from this sync: - migrations/: upstream's 0031_workflow_run_error_codes.sql is 0033 here. Fifth renumbered migration across four syncs -- it has now fired on every sync that touched migrations/, so the note says to expect it by default rather than treating it as a possibility. The renumber table gains a row, including that upstream's new test also carries a `version == 1` lookup that must NOT move: a version literal is not automatically a renumber site, which the previous "sweep for version == N" advice did not qualify. - release.yml: assemble-manifest now accepts `skipped` from desktop-release-smoke as well as release-macos-x64. Recorded as a pattern rather than an incident -- this is the third time upstream has added a block/buzz-pinned lane to that gate, and all three arrived as clean context in the `if:` block while only the `needs:` list conflicted. Signed-off-by: adrienlacombe <6303520+adrienlacombe@users.noreply.github.com>
The merge resolution pushed desktop/src-tauri/src/relay.rs to 1002 lines against the hard 1000-line limit in desktop/scripts/check-file-sizes.mjs, failing Desktop Core. Upstream's new `mod get;` was +3; the fork's allowlist block and release-relay fallback are +14 over upstream's 987. Condensed the fork's own two comment blocks to 995 rather than touching upstream code. The full reasoning for both patches already lives in AGENTS.md's patch table, which is the durable record -- the in-file comments only need to mark the hunk as fork-local. Deliberately not splitting or reorganising upstream's relay.rs to make room: that would trade five lines for a permanent conflict surface in a file upstream is actively developing. Upstream is extracting submodules from it anyway. This is a clean-merge breakage, not a conflict -- nothing in the merge output pointed at it, and it surfaced only as a red Desktop Core. Signed-off-by: adrienlacombe <6303520+adrienlacombe@users.noreply.github.com>
CI round 2 — settled: 31 pass, 2 fail, 3 skippingThe ratchet fix in The 2 remaining reds are the pre-existing
Byte-identical to Worth recording that the two failures were at different steps of the same job, since Everything else is green — Still not auto-merged, by design. Tripwires 1 (new migration Fixing the |
Syncs
block/buzz9e0c6b432..eedcd886a— 14 commits, 150 files, +10957/−1815.What changed upstream
Desktop — Inbox message delete action (block#5779); agent-mention authorization enforced at send boundaries (block#5681); workflow run history made authoritative (block#5780); compact link previews reworked (block#5629, block#5711, block#5799); shared agent instruction review hardened (block#4220).
Huddle / voice — voice-turn time-to-first-audio cut ~1.0 s → ~0.35 s behind env gates (block#5671); glass Huddle tray behavior polished (block#5590); initial DM load sped up (block#5658).
Relay / db — complete channel member rosters (block#5765); workflow run error codes as a stable classification column, with a new migration (block#5780).
Mobile — community invites (block#5641); composer input regressions fixed (block#5594). 33 files.
CI — new
desktop-release-smokejob plusscripts/run-desktop-release-smoke.shandscripts/e2e-large-channel-roster.sh(block#5699).Conflicts
Three, all at documented fork patch sites.
migrations/+crates/buzz-db/src/migration.rs— upstream's0031_workflow_run_error_codes.sqlrenumbered to0033.The fork holds 0027 and 0028 and both have run on the live database; sqlx checksums applied migrations, so the fork's cannot move. Upstream's has never run here, so it is the one that renumbers. Contents byte-identical — the rename is the whole change.
This is the dangerous shape again: upstream's 0031 landed directly on the fork's
0031_community_deletion.sql, so the two files sorted adjacent and the tree looked plausible.ls migrations/*.sql | cut -d_ -f1 | sort | uniq -dis now empty.Assertions moved with it — only the count arrived as a conflict, the rest as clean context:
migrations.len()workflow_run_error_codes_…indexmigrations[30]migrations[32]version == 31version == 33find(|m| m.version == 1)That last row is the trap worth naming: AGENTS.md says to sweep for
version == Nliterals, and this test has one that must not move..github/workflows/release.yml—assemble-manifestwas made unreachable again, with no conflict marker.Upstream block#5699 added
desktop-release-smoke, pinnedif: github.repository == 'block/buzz', and addedneeds.desktop-release-smoke.result == 'success'toassemble-manifest's gate. Only theneeds:list conflicted — the gate condition merged in as clean context. In this fork that job always reportsskipped, so the gate could never be satisfied andlatest.jsonwould never be published while every updater archive and.siguploaded fine.Resolved as
success || skipped, matching the existingrelease-macos-x64treatment.block/buzzstill requires every lane to succeed. This is the third instance of this exact pattern (after block#3568 and the-ge 3platform count), so AGENTS.md now records it as a recurring shape rather than an incident.desktop/src-tauri/src/relay.rs— kept both sides: the fork'spub mod allowlist;and upstream's newmod get; pub use get::get_relay_json;.Also in this PR
fix(sync): re-resolve root Cargo.lock— the merged lock leftbuzz-admin'suuidentry undisambiguated once upstream'sbuzz-adminchange brought a seconduuid(0.8.2) into the tree. Regenerated, not hand-edited; no dependency version moved. Local gates read the working tree, so this fails only in CI if left unstaged.Verification
All run locally on the committed state.
cargo fmt --all --checkcargo fmt --manifest-path desktop/src-tauri/Cargo.toml --all --checkcargo clippy --workspace --all-targets -- -D warningscargo clippy --manifest-path desktop/src-tauri/Cargo.toml --all-targets -- -D warningscargo metadata --locked(root)cargo metadata --locked(desktop)scripts/test-release-ref-contract.shrelease ref contract passedscripts/test-oss-desktop-promotion.shscripts/test-oss-desktop-promotion-behavior.shscripts/test-mobile-worktree-overrides.shjust test-unitdart format --set-exit-if-changed .flutter analyzeflutter testMigration tests specifically confirmed green:
embedded_migrator_contains_consolidated_initial_schema,workflow_run_error_codes_are_additive_and_backfilled_without_parsing_diagnostics,deletion_surface_parity_between_migration_0029_and_schema_sql.The release-ref contract was run in a clean clone — from the working checkout it copies
target/(~53 GB).Needs a human look
This PR trips tripwire 1 (new migration) and tripwire 4 (conflict in
release.yml), so it is deliberately not auto-merged.migrations/0033_workflow_run_error_codes.sqlruns DDL against production on merge. It isALTER TABLE workflow_runs ADD COLUMN error_code TEXTplus a backfill oflegacy_unclassifiedover rows already in('failed','cancelled'). Additive andlock_timeout = '5s', butinfra/aws/ecs.tfsetsBUZZ_AUTO_MIGRATE=true, so merging applies it at relay boot. Worth a look at theworkflow_runsrow count before merging.The
release.ymlgate fix is only exercised at desktop release time, not by this PR's CI. If it is wrong, the symptom is a silently missinglatest.jsonrather than a red check.Not caused by this sync, but still true and still blocking real releases: rolling-manifest promotion remains unreachable in this fork (upstream ci(release): gate OSS desktop auto-update promotion block/buzz#5398).
assemble-manifeststagesupdater-manifest.jsonon the versioned release, but nothing promotes it tobuzz-desktop-latest, andscripts/promote-oss-desktop-release.shrequires exactly the four upstream platform triples where this fork produces three. Installed clients are not seeing new versions regardless of this PR.No wire-format changes. No event-kind changes. No fork-local patch deleted.
Merge with a merge commit, not squash. A squash drops the second parent, leaves the merge base stale, and makes every future sync re-resolve these same conflicts from the same base.
Update — CI round 1, and a clean-merge breakage it caught
First CI run came back 2 red:
Desktop CoreandDesktop(the latter is only the gate depending on the former). Those are two different failures and it matters which is which.Fixed here:
relay.rsbreached the file-size ratchetCaused by my conflict resolution, and a textbook clean-merge breakage — the merge reported nothing,
just test-unitwas green, and it surfaced only as a red job.desktop/scripts/check-file-sizes.mjsenforces a hard 1000. Upstream's newmod get;was +3; the fork's allowlist block and release-relay fallback are +14 over upstream's 987.Fixed in
841c5ede6by condensing the fork's own two comment blocks → 995 (8 over upstream, 5 of headroom). Deliberately did not split or reorganise upstream'srelay.rs: that trades five lines for a permanent conflict surface in a file upstream is actively developing — it is extracting submodules from it already. The full reasoning for both fork patches lives in the AGENTS.md patch table, which is the durable record; the in-file comments only need to mark the hunk.just desktop-checknow exits 0, and desktopfmt+clippywere re-run after the edit — both clean.There is a wider point recorded in AGENTS.md: this file's constraint is now the thing to watch on every sync. The fork moved
pub mod allowlist;out oflib.rsin the 2026-08-01 sync precisely becauselib.rswas at the ratchet — andrelay.rshas now become the constrained file in turn. It announces itself as a redDesktop Core, never as a conflict.Not fixed here:
Desktop Coreis already red onmainmainat67dc367d6fails the same job at a different step —desktop-test, notdesktop-check:Upstream's
messageLink/remarkMessageLinkstests hardcodebuzz://against this fork's renamedbitcoinmarkets://scheme. Pre-existing, unrelated to this sync, and not mine to fix here — it predates this PR and will keep any sync PR'sDesktop Corered until someone decides how to handle it (the options are carrying a test patch or teaching the tests to read the scheme constant).So expect this PR to settle with
Desktop Corestill red for that reason. The ratchet breach — the part this sync actually caused — is fixed. Every other check passed on round 1, includingMobile, all fourDesktop Smoke E2Eshards,Desktop E2E Relay,Backend Integration,Unit Tests,Rust Lint, both cross-compiles, and all four CodeQL analyses.