feat(acp): accept extra MCP servers via BUZZ_ACP_EXTRA_MCP_COMMANDS - #6031
Closed
BradGroux wants to merge 2445 commits into
Closed
feat(acp): accept extra MCP servers via BUZZ_ACP_EXTRA_MCP_COMMANDS#6031BradGroux wants to merge 2445 commits into
BradGroux wants to merge 2445 commits into
Conversation
## Overview **Category:** improvement **User impact:** Link previews appear in the composer and travel as privacy-safe sender-authored snapshots, so recipients never contact the linked site merely by opening a conversation. **Problem:** Cold-cache link paste could freeze the composer before the URL painted; recipient-side unfurling leaked visits; invalid or unresolved preview work could interfere with sending or leave dead cards behind. **Solution:** Paint pasted links before starting cold resolver work, resolve only in the sender's composer, attach only complete validated snapshots at Send, and render authored snapshots without recipient fallback fetching. ## Behavior - **Cold paste stays responsive:** bare and angle-bracket URL paste paths commit the visible link before resolver work begins. - **Sender-only fetching:** metadata is resolved while composing; recipients render only the sender-authored snapshot. - **Send never waits:** pending, failed, invalid, and unsendable previews are omitted. They do not block or cancel the message. - **Terminal misses disappear:** failed, timed-out, or 404 resolver results remove the composer card while preserving visible link text. - **Display-text links work:** Markdown links such as `[review the pull request](…)` produce and send the same snapshots as bare URLs. - **Compact and Rich presentation:** Compact remains the default; Rich preserves source description line breaks and paragraphs. - **Immediate draft-wide dismissal:** clicking × immediately hides all previews for the draft, suppresses links pasted later, and emits only `["link-preview", "none"]`. No confirmation detour. Suppression resets after send or clearing the draft. - **Zero recipient fallback:** missing, stale, malformed, off-relay, unsupported, or suppressed snapshots remain ordinary visible links; recipients never regenerate them. ## Implementation - Resolve previews from deferred composer URL state so paste can paint first. - Upload finished preview media to the active community relay and snapshot only valid, sendable media references. - Atomically capture ready snapshots at submit time; never append a late preview after send. - Validate snapshot and suppression tags in desktop/native and relay ingestion, rejecting duplicate or mixed forms. - Render composer previews as stable 55px attachment cards at desktop and narrow widths. - Add deterministic E2E coverage for cold paste, ready/pending/failed/invalid previews, display-text links, multiline Rich descriptions, immediate dismissal, later-pasted links, and suppression reset. ## Validation Validated head: `64f2e2937a2c70e388c132ae14b6be6d11716db8` - Push hooks passed: `check-push-org`, branch skew, desktop check, mobile tests, desktop tests, Rust tests, and desktop Tauri checks. - Focused screenshot E2E at the validated head: 5/5 passed across Compact/Rich composer and recipient states, 800px/420px geometry, display-text links, multiline descriptions, and immediate dismissal. - PR CI was triggered for this exact head and is currently running; completed checks are green at the time of this update. - Worktree is clean and both PR head and validated branch resolve to `64f2e2937…`. ## Screenshots ### Compact composer | Loading | Ready | |---|---| |  |  | ### Rich composer | Loading | Ready | |---|---| |  |  | ### Responsive composer | 800px loading | 800px ready | |---|---| |  |  | | 420px loading | 420px ready | |---|---| |  |  | ### Recipient presentation | Compact | Rich | |---|---| |  |  | ### Display-text Markdown link | Composer | Recipient | |---|---| |  |  | ### Rich multiline description  ### Immediate dismissal | Before × | Immediately after × | |---|---| |  |  | --------- Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
## Summary <!-- What does this change and why? --> block#3419 is a tauri bug (tauri-apps/tauri#15110), which is already fixed in tauri-apps/tauri#15596. All we need is bump the @tauri-apps/cli version to include the bug fix. ```sh pnpm update --filter ./desktop @tauri-apps/cli@2.11.4 ``` This pr simply includes the changes after running the update command. ### Related issue <!-- Fixes block#1234, or N/A. Before opening: search existing issues/PRs for duplicates — link the closest one, or say "none found". --> fix block#3419 close block#3436. this pr supersedes it. ### Testing <!-- How was this verified? UI change? Include before/after screenshots (or a short recording). --> build the appimage and check the symlink in the appimage using `unsquashfs`. ```sh $ unsquashfs -o 944632 -ll /tmp/buzz/desktop/src-tauri/target/release/bundle/appimage/Buzz_0.5.4_amd64.AppImage | grep -i dirIcon lrwxrwxrwx root/root 8 2026-08-04 21:54 squashfs-root/.DirIcon -> Buzz.png ``` Signed-off-by: Tsung-Han Yu <14802181+johan456789@users.noreply.github.com>
…lders (block#4975) ## What users saw `buzz messages send` silently removed an explicitly supplied self-mention. The caller passed `--mention <sender-pubkey>` and received `accepted:true`, but the signed event had no matching `p` tag and `mention_pubkeys` was empty. ## Why it happened `nostr` 0.44 strips `p` tags matching the signer's pubkey by default. The codebase already opts out with `.allow_self_tagging()` for identity archive and unarchive requests, but the message and forum builders that accept mentions did not. The library therefore removed the tag during signing after the CLI had validated the explicit mention. ## What changed Added `.allow_self_tagging()` to all three event builders that accept mention tags: - `build_message` (kind 9) - `build_forum_post` (kind 45001) - `build_forum_comment` (kind 45003) An explicit mention now survives signing even when it matches the sender. ## How this was tested Added one regression test per builder. Each test signs with the same key included in the mention list and asserts that the resulting event preserves the self-referential `p` tag. Validation at `1ea172355`: ```text ./bin/cargo fmt --all -- --check cargo test -p buzz-sdk --lib cargo test -p buzz-cli --lib cargo clippy -p buzz-sdk -p buzz-cli --all-targets -- -D warnings ``` All 257 `buzz-sdk` tests and all 321 `buzz-cli` tests passed, and formatting and strict Clippy checks completed successfully. ## Scope and non-goals - Does not change mention validation, deduplication, or channel-member checks. - Does not change `normalize_mention_pubkeys`, which is not used by the messages-send path. - Does not add a dropped-mentions output field because the explicit tags are now preserved. Closes block#4906. --------- Signed-off-by: Brad Groux <bradgroux@hotmail.com> Signed-off-by: npub17q2gdupkvswvk5kprwc7plergm4gn295uw6fe4mjyjv53ahuhtnq02jd3f <f01486f036641ccb52c11bb1e0ff2346ea89a8b4e3b49cd772249948f6fcbae6@digitalmeld.communities.buzz.xyz> Signed-off-by: Brad Groux <3053586+BradGroux@users.noreply.github.com> Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: npub17q2gdupkvswvk5kprwc7plergm4gn295uw6fe4mjyjv53ahuhtnq02jd3f <f01486f036641ccb52c11bb1e0ff2346ea89a8b4e3b49cd772249948f6fcbae6@digitalmeld.communities.buzz.xyz> Co-authored-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
**Category:** fix **User Impact:** Mobile users who jump to Latest now see the newest message fully above the composer instead of partially hidden behind it. **Problem:** The channel message list treated the raw viewport bottom as the latest boundary even though the composer occupies part of that viewport. Latest jumps and follow-mode corrections could therefore place the newest message underneath the composer. **Solution:** Derive the latest alignment from the measured composer inset and use that same boundary for scrolling, follow detection, and layout correction. <img width="498" height="1008" alt="Screen Recording 2026-08-05 at 5 18 19 PM" src="https://github.com/user-attachments/assets/a7fc1a94-3ffb-4c34-908d-9bf4f3f082b4" /> <details> <summary>File changes</summary> **mobile/lib/features/channels/channel_detail_page/message_list.dart** Aligns Latest navigation and follow-mode correction with the visible bottom edge above the composer, and evaluates boundary state against the same geometry. **mobile/test/features/channels/channel_detail_page_test.dart** Adds a regression assertion that the newest live message clears the composer and that the Latest control disappears after navigation. </details> ## Reproduction steps 1. Open a mobile channel with enough messages to scroll away from the newest message. 2. Tap **Latest**. 3. Confirm the newest message is fully visible immediately above the composer and the **Latest** control disappears. 4. Resize the composer or keyboard while following latest and confirm the newest message remains above the composer. ## Tested fix The newest message remains fully visible above the composer after jumping to **Latest**.  ## Validation - `flutter analyze` — no issues - `flutter test` — 1,243 passed --------- Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
## Buzz Desktop release v0.5.6 - **Frozen main:** `c814c9ef463408dba61346b6de5d4b4cd5f5490d` - **Reviewed candidate:** `62158ac1b581f38ba64e80868f6c88e9e1ecf554` - **Previous desktop release:** `desktop-v0.5.5` - **Proposed immutable tag:** `desktop-v0.5.6` This PR may be **squash merged** after the Desktop Release Candidate check and all protected-branch checks pass. Merging authorizes publication of the exact reviewed candidate; later or unrelated changes on `main` cannot alter it. The checked-in changelog accounts for every non-merge commit in the release range. The Desktop tag points to the reviewed candidate commit, not the later squash commit. Publication remains bound to that immutable candidate tag. Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Release Automation <release-automation@users.noreply.github.com>
## Summary - treat provider `max_tokens` as an interrupted assistant response and continue the same turn with actionable feedback - discard tool calls from truncated responses, including malformed partial arguments, so they are neither executed nor replayed with invalid tool-result pairing - bound recovery to two retries while preserving normal finite `max_rounds` accounting ## Verification - `cargo fmt --all -- --check` - `cargo test -p buzz-agent` (422 unit tests plus all package integration/doc suites passed) - `cargo clippy -p buzz-agent --all-targets -- -D warnings` ## Notes The pre-push repository-wide hook also ran. Its Rust tests passed (2,270 passed, 14 ignored), but its `buzz-db` unit-test build was blocked because local rustc 1.89 is below sqlx 0.9's rustc 1.94 requirement. The affected package suite above is green on the exact pushed commit. Originating Buzz channel: `c3252dd2-0142-4e01-88c7-a2183c3960a5` Signed-off-by: Wren <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@buzz.block.builderlab.xyz> Co-authored-by: Wren <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@buzz.block.builderlab.xyz>
…block#5228) **Category:** fix **User Impact:** People who onboard by importing an existing key or recovering from a phone can now use "Skip for now" (and Next) on the harness setup and model config steps, instead of getting stuck. **Problem:** On the "Set up your agent harnesses" and "Configure your default model settings" onboarding steps, clicking **Skip for now** — or **Next** — did nothing for anyone who reached those steps by importing an existing key or recovering an identity from a phone. The app stayed frozen on the step. **Solution:** The onboarding state machine sets `continuingPubkeyRef` to the current pubkey on import/recovery to keep the flow on `onboarding` until setup finishes (added in block#4845). But `complete()` never cleared that ref, so once it matched the current pubkey the stage stayed pinned to `onboarding` forever — completion could never win. `complete()` now clears the ref so finishing/skipping actually settles the flow. Fresh-generated keys never set the ref, which is why first-run fresh-key skip already worked and the gap went unnoticed. <details> <summary>File changes</summary> **desktop/src/features/onboarding/machineOnboarding.ts** Clear `continuingPubkeyRef` inside `complete()` so an imported/recovered identity's "continuing" marker no longer outlives completion and pin the stage to `onboarding`. **desktop/tests/e2e/onboarding.spec.ts** Add a regression test that imports an existing key, reaches harness setup, clicks **Skip for now**, and asserts onboarding exits (reaches community onboarding). This fails without the fix. The existing skip tests only exercised the fresh-key path, which never set the ref — hence the gap. </details> ## Reproduction steps 1. Start onboarding and choose **Use an existing key** (or recover from a phone); import a key and continue to **Set up your agent harnesses**. 2. Click **Skip for now** (or **Next**). Before this change, nothing happens — the step is stuck. The same trap hits **Configure your default model settings**. 3. With this change, Skip/Next advances out of onboarding as intended. 4. Automated: `pnpm build:e2e && pnpm exec playwright test onboarding.spec.ts --project=integration -g "imported-key users can skip out of harness setup"` — passes with the fix, fails without it. ## Root cause Introduced by block#4845 (`feat(identity): recover desktop identity from a signed-in phone`), which added `continuingPubkeyRef.current === currentPubkey` as an independent condition selecting the `onboarding` stage. That guard has no off switch: `complete()` set the completion flag but never cleared the ref, so the OR'd condition kept the stage pinned. Not a revert candidate — the guard's intent (keep a just-published identity in onboarding until setup finishes) is correct; it just needed to release on completion. Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
…rride (block#5242) ## Problem Two v0.5.6-only regressions were introduced by block#4614 (the first enforced Tauri CSP): 1. **Tab-complete caret regression** — after tab-completing an @mention, #channel, or :emoji: shortcode, the cursor landed inside the inserted text instead of after the trailing space. TipTap inserts the correct text including the trailing space, but without its base stylesheet (`.ProseMirror { white-space: break-spaces }`) the trailing space collapses visually and the caret appears mid-name. 2. **Emoji picker unstyled** — the emoji-mart picker rendered as a giant unstyled layout (oversized search SVG, collapsed grid) because emoji-mart's shadow-root stylesheet injection was also blocked. Both symptoms have the same root cause. ## Root Cause Tauri's build-time asset processor scans `index.html` for inline `<style>` elements, injects a nonce token, and adds the corresponding `'nonce-…'` source to `style-src` at runtime. Per the CSP spec, **once a nonce is present in a directive, the browser ignores `'unsafe-inline'` for that directive**. `index.html` contained an inline `<style>` with the boot background color. When Tauri nonced it and injected `'nonce-…'` into `style-src`, the intended `style-src 'self' 'unsafe-inline'` became effectively `style-src 'self' 'nonce-…'` — blocking any runtime stylesheet injection not covered by a matching nonce: - TipTap's `injectCSS()` → `createStyleTag()` injecting `.ProseMirror { white-space: break-spaces; … }` - emoji-mart's shadow-root `document.createElement('style')` injection (Inline scripts follow a separate path — they are SHA-256 hashed, not nonced.) This only reproduces in packaged builds (where Tauri's custom protocol serves the HTML and enforces the policy). `tauri dev` loads from the Vite dev server and is not affected. ## Fix Move `html { background-color: #000; }` from an inline `<style>` in `index.html` to `desktop/public/boot.css`, linked via `<link rel="stylesheet">`. A linked stylesheet is not subject to Tauri's nonce injection, so `'unsafe-inline'` in `style-src` applies as declared. The `<link>` is render-blocking (same as the inline style was), so boot-flash behaviour is identical. **The production CSP string is unchanged.** This fix makes the policy apply as intended — no security properties are altered. Will's follow-up with the security team (Jordan Mecom / Eli Foster, authors of block#4614) is noted for post-ship. A Tauri-faithful CSP harness for the Vite dev path (so this class of regression is visible before a packaged build) is tracked as a separate follow-up. ## Files Changed - `desktop/index.html` — replace inline `<style>` with `<link rel="stylesheet" href="/boot.css" />` - `desktop/public/boot.css` — new file, the extracted `html { background-color: #000; }` plus rationale comment - `desktop/src-tauri/tests/csp.rs` — update comment: nonce for styles, SHA-256 for the boot script ## Testing - `just desktop-typecheck` ✅ - `just desktop-test` ✅ (4535/4535) - `just desktop-tauri-test` ✅ (all Rust tests including `csp.rs`) - Packaged validation: `pnpm tauri build --debug` completed; compiled binary bakes `style-src 'self' 'unsafe-inline'` with no nonce source injected ✅ --------- Signed-off-by: Will Pfleger <pfleger.will@gmail.com> Co-authored-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
## Summary - serialize the relay error-message test with all other tests mutating the process-wide admission gate - clear its 300-second rate-limit expiry after the assertion - prevent the paused-time waiter test from observing another test's state ## Root cause `relay::tests::oversized_hint_is_capped_in_relay_error_message_string` arms the process-wide gate for 300 seconds without taking `TEST_SERIAL` or resetting it. In a parallel test run, `relay_admission::tests::concurrent_429_extends_the_window_for_parked_waiters` can observe that expiry, producing the reported `300.001s` instead of `5s`. ## Validation - focused admission suite + relay error test repeated 10 times - pre-push `desktop-tauri-checks` passed, including the full Rust workspace suite - `branch-skew` passed Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
## Buzz Desktop release v0.5.7 - **Frozen main:** `cf0967517ce6545903089939acfa7eefdc1e8696` - **Reviewed candidate:** `c1972d72b0b80168d0ec8ff7c935d662c6586a0f` - **Previous desktop release:** `desktop-v0.5.6` - **Proposed immutable tag:** `desktop-v0.5.7` This PR may be **squash merged** after the Desktop Release Candidate check and all protected-branch checks pass. Merging authorizes publication of the exact reviewed candidate; later or unrelated changes on `main` cannot alter it. The checked-in changelog accounts for every non-merge commit in the release range. The Desktop tag points to the reviewed candidate commit, not the later squash commit. Publication remains bound to that immutable candidate tag. Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Release Automation <release-automation@users.noreply.github.com>
## What changed Bind the development Compose stack's published PostgreSQL, Redis, Adminer, Keycloak, MinIO, and Prometheus ports to `127.0.0.1`. ## Why Docker publishes a host port on every interface when no host address is specified. Running the development stack on a remote workstation or VPS therefore exposes its infrastructure services to that machine's public networks. Loopback bindings retain host-local development access and Docker's internal `buzz-net` connectivity without making those services Internet-reachable. ## Impact Local workflows continue using the same ports. Deliberate remote administration now requires an SSH tunnel or another trusted private-network path. ## Validation - `docker compose -f docker-compose.yml config --quiet` - Recreated the six affected services with their existing named volumes and Docker network - PostgreSQL remained healthy and retained all 54 application tables - Redis, MinIO, and Prometheus health checks passed - All affected ports were closed on the host's public IPv4 and IPv6 addresses while remaining available on loopback Origin: `buzz://message?channel=199eb7bc-3feb-484f-ae0e-4995123721ea&id=1c5bc387e86e21bb31677f56e1c862d4d9a17943bce91f8d93e825d029ce7f72` Signed-off-by: Paweł Karniej <karniej.p@gmail.com>
…starve the handoff summary (block#5248) ## Problem The handoff summarizer sends `max_tokens: 8192` (`HANDOFF_MAX_OUTPUT_TOKENS`) with no reasoning budget separation. On reasoning models, thinking tokens count against that cap: the model can spend the entire budget reasoning, length-stop with empty `content`, and `summarize()` — which only reads `content` — reports an empty summary. The handoff then degrades to lossy history truncation. Observed on deepseek-v4-flash during a terminal-bench 2.1 run (tb21-solo-3, 89 tasks): **13 consecutive handoff attempts across 5 trials failed exactly this way** (`handoff returned empty summary; truncating`), each burning ~3 minutes of full-cap reasoning, before a stochastically-short reasoning run finally fit. circuit-fibsqrt alone: 5 failures, 5 truncations, then success on attempt 6. video-processing failed its task by one frame after 3 context truncations. ## Fix `openrouter_summary_body` now grants reasoning its own equal-sized budget and excludes it from the response: - `reasoning.max_tokens = max_output_tokens` — thinking gets a dedicated budget instead of competing with the summary text - `reasoning.exclude = true` — reasoning is never in the response body; `summarize()` only reads `content` - `max_tokens = max_output_tokens * 2` — the total cap covers both budgets, so the text budget the caller asked for is actually available for text Non-reasoning endpoints ignore the `reasoning` object. Deliberately not paired with `provider.require_parameters`, for the reasons documented at `apply_openrouter_mutations` (it hard-404s valid model ids). The prior test `openrouter_summary_carries_neither_reasoning_nor_provider` asserted `reasoning` absent from the summary body — that assertion guarded against *effort-based* reasoning leaking in from config (the body is built independently of `cfg`, which is still true and still tested: `reasoning.effort` stays unset). Replaced with `openrouter_summary_budgets_reasoning_separately_and_carries_no_provider`. ## Verification - `cargo test -p buzz-agent`: 422 unit + 110 integration tests pass at bb2fedd - `cargo fmt` / `cargo clippy -p buzz-agent --all-targets`: clean - Not yet validated against a live OpenRouter reasoning endpoint — the failing scenario needs a long-context session to trigger organically. Evidence for the mechanism is from run artifacts (13/13 empty-summary length-stops on deepseek-v4-flash) and OpenRouter's documented `reasoning.max_tokens`/`reasoning.exclude` semantics. --------- Signed-off-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz> Co-authored-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
**Category:** improvement **User Impact:** Users can create, discover, and import agents from one consistent Add agent dialog. **Problem:** Agent creation, discovery, and import were split across a dropdown and separate dialogs, making the Add agent flow fragmented. The existing E2E suite also continued targeting the deleted dropdown after the flows were unified. **Solution:** Route the new-agent card directly into a unified dialog with dedicated Create, catalog, and Import navigation, then update the affected E2E coverage to exercise that interface and its current empty state. <details> <summary>File changes</summary> **desktop/src/features/agents/ui/AgentDefinitionDialog.tsx** Supports rendering the agent definition form inside the unified Add agent experience while retaining the standalone dialog behavior. **desktop/src/features/agents/ui/AgentDefinitionDialogShell.tsx** Adds the shared shell used to present agent-definition content consistently in embedded and standalone contexts. **desktop/src/features/agents/ui/AgentDialog.tsx** Passes the revised dialog state and close behavior through the existing agent dialog entry point. **desktop/src/features/agents/ui/AgentsView.tsx** Connects the Agents page to the unified Add agent dialog and opens newly added catalog agents in their profile panel. **desktop/src/features/agents/ui/PersonaCatalogDialog.tsx** Combines catalog browsing, agent creation, and snapshot import behind persistent navigation, including dirty-navigation confirmation. **desktop/src/features/agents/ui/UnifiedAgentsSection.tsx** Replaces the new-agent dropdown with a direct Add agent entry point and adjusts the responsive card grid. **desktop/src/features/agents/ui/personaLibraryCopy.ts** Updates catalog-facing copy for the unified experience. **desktop/src/features/agents/ui/usePersonaActions.ts** Returns the resolved local persona after catalog activation so the caller can open the added agent. **desktop/tests/e2e/agent-readiness-screenshots.spec.ts** Opens the embedded create pane directly for readiness screenshots. **desktop/tests/e2e/agents.spec.ts** Covers unified Create, catalog, and Import navigation and asserts the current shared-agent empty state. **desktop/tests/e2e/global-agent-config-screenshots.spec.ts** Updates global configuration screenshot setup for direct create-pane entry. **desktop/tests/e2e/inline-custom-harness.spec.ts** Updates custom harness setup for the embedded create form. **desktop/tests/e2e/persona-env-vars.spec.ts** Updates environment-variable and model-provider scenarios for direct create-pane entry. **desktop/tests/e2e/persona-model-combobox-screenshots.spec.ts** Updates model combobox screenshot setup for direct create-pane entry. **desktop/tests/e2e/smoke.spec.ts** Updates agent-creation smoke coverage for the unified Add agent dialog. **desktop/tests/e2e/where-to-run-config.spec.ts** Updates provider-selection coverage for the embedded create form. </details> ## Reproduction steps 1. Open the Agents page and select the new-agent card. 2. Confirm the Add agent dialog opens directly on Create without an intermediate dropdown. 3. Use the left navigation to browse shared agents and open Import. 4. Select a catalog agent and confirm the dialog closes and the added agent's profile panel opens. 5. Run the affected desktop Playwright smoke and integration specs and confirm all scenarios pass. --------- Signed-off-by: Taylor Ho <taylorkmho@gmail.com> Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz>
…nchmark agent rounds (block#5318) ## Problem Two failure modes from the `tb21-glm52-crusoe-1` benchmark run (GLM-5.2 solo, TB2.1) wedged or killed 13 of 89 trials without the model being at fault: 1. **Conversation poisoning on text-only endpoints.** Crusoe's serverless `crusoeai/GLM-5.2-NVFP4` rejects any request whose history contains an image with `400: ... is not a multimodal model`. The recovery machinery for exactly this case already exists — `AgentError::UnsupportedImageInput` → `replace_unsupported_images()` strips the image blocks, marks the tool result as an error, substitutes a text placeholder, and continues the turn. But classification only matched OpenRouter's 404 body (`no endpoints found that support image input`) and was only consulted on the 404 arms. The Crusoe 400 fell through to terminal `AgentError::Llm`: the image stayed in history, every subsequent call failed identically, buzz-acp rode its 10-retry ladder (~40 min), and the trial idled to budget death. Measured blast radius: **8 trials wedged, 12.7h aggregate idle-after-poison.** 2. **Bounded agent rounds in benchmark trials.** The harness default `DEFAULT_MAX_AGENT_ROUNDS = 32` ended solo trials mid-work when turns rotated (thinking-heavy models hit max_tokens rotation fast; 4 trials died this way). Benchmark trials already have a wall-clock budget as the real limit — the round cap only converts recoverable rotation into trial death. ## Fix - `is_unsupported_image_input_error()` also matches the verbatim `is not a multimodal model` body. Matcher stays deliberately tight (same doctrine as `is_context_length_error`): misclassifying a generic 400 as recoverable would mutate history for an error that removing images cannot fix. - Both status ladders — shared `post()` and `openrouter_post()` — consult it on their 400 arms and return the typed `UnsupportedImageInput` (OpenAI-compatible providers report this as 400; a BYOK/passthrough upstream can surface the provider's own 400 through OpenRouter). - Harness `DEFAULT_MAX_AGENT_ROUNDS` → `0` (unbounded — `BUZZ_AGENT_MAX_ROUNDS=0` is the agent config's documented unbounded value). Per-agent `budget.max_calls` in manifests still overrides. ## Acceptance - A 400 with the image-rejection body reaches the existing image-strip recovery path instead of wedging the session — asserted through `complete()` (covers the return path into the convergence mapper) and at the `openrouter_post` terminal, both proving single-attempt (a deterministic capability rejection must never be retried). - Ordinary 400s stay terminal `AgentError::Llm` (existing negative tests unchanged). - Benchmark trials run unbounded rounds by default; python tests updated for 0-is-legal with a negative arm at -1. ## Verification - `cargo test -p buzz-agent`: 427 + 18 + 20 + 15 + 8 + 1 + 48 passed, 0 failed (full package, 3 consecutive clean runs) - `cargo clippy -p buzz-agent --all-targets`, `cargo fmt --check`: clean - `uv run --extra dev pytest tests/` in harbor-buzz-orchestra: 35 passed - Pre-push hooks (full workspace rust-tests + desktop-tauri-checks) green on rustc 1.95.0 at head b043860 Signed-off-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz> Co-authored-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
## Buzz Desktop release v0.5.8 - **Frozen main:** `214fddc193ab22724b93fdceace0c046950cd795` - **Reviewed candidate:** `9c96dd553749bcd533482db18c3dc30cfa95dbfb` - **Previous desktop release:** `desktop-v0.5.7` - **Proposed immutable tag:** `desktop-v0.5.8` This PR may be **squash merged** after the Desktop Release Candidate check and all protected-branch checks pass. Merging authorizes publication of the exact reviewed candidate; later or unrelated changes on `main` cannot alter it. The checked-in changelog accounts for every non-merge commit in the release range. The Desktop tag points to the reviewed candidate commit, not the later squash commit. Publication remains bound to that immutable candidate tag. Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Release Automation <release-automation@users.noreply.github.com>
## Buzz Relay release v0.2.1 ### Changes since relay-v0.2.0: - fix(sdk): preserve self-mention p tags in message and forum event builders ([block#4975](block#4975)) ([`c814c9ef46`](block@c814c9e)) - feat(desktop): adding rich link previews to messages ([block#3818](block#3818)) ([`9c69278ff1`](block@9c69278)) - feat(relay): accept kind:30179 private managed-agent events at ingest ([block#5133](block#5133)) ([`f5ea99f85d`](block@f5ea99f)) - fix(media): require authenticated reads ([block#4610](block#4610)) ([`c400713e73`](block@c400713)) - feat(identity): recover desktop identity from a signed-in phone ([block#4845](block#4845)) ([`c113582971`](block@c113582)) - ci: prove the relay-driven mesh lifecycle — discover, join, infer, deny — with real nodes ([block#3862](block#3862)) ([`a496f622bb`](block@a496f62)) - relay: fuzz WebSocket 1012 restart-close timing on graceful drain (BUZZ_DRAIN_JITTER_MS) ([block#4542](block#4542)) ([`d02aa244ab`](block@d02aa24)) - fix(reactions): support max-length custom emoji ([block#3833](block#3833)) ([`acff8c97c7`](block@acff8c9)) - fix(channels): restrict private-channel invitations ([block#4612](block#4612)) ([`453fc26085`](block@453fc26)) - fix(workflow): bind trigger author to the signed event ([block#4607](block#4607)) ([`5c4d3e5245`](block@5c4d3e5)) - fix(git): revoke access for banned relay members ([block#4608](block#4608)) ([`b768a0574a`](block@b768a05)) - Define private managed agent wire protocol ([block#4593](block#4593)) ([`fad5a65b98`](block@fad5a65)) - perf(relay): index channel-id lookups and skip trace-only reads ([block#4647](block#4647)) ([`cd5756a81e`](block@cd5756a)) - Polish mobile inbox and media flows ([block#4512](block#4512)) ([`c7630e8cae`](block@c7630e8)) - fix(git): allow deleting the default branch ([block#4297](block#4297)) ([`767118dd1c`](block@767118d)) - feat(projects): add buzz projects CLI commands (NIP-MP kind:30621) ([block#4020](block#4020)) ([`d76f6b07f8`](block@d76f6b0)) - perf(relay): serve relay-membership checks from the read replica ([block#4124](block#4124)) ([`03ba494af5`](block@03ba494)) - fix(relay): allow open relays to set their NIP-11 workspace icon (kind:9033) ([block#3998](block#3998)) ([`3c9bb09faf`](block@3c9bb09)) - feat(relay): accept kind:30621 multi-repo projects at ingest ([block#3171](block#3171)) ([`e47312d13b`](block@e47312d)) - feat(relay): raise hosted community limit to five ([block#3829](block#3829)) ([`e8208939a4`](block@e820893)) - fix(relay): align NIP-11 max_limit with REQ ceiling ([block#3635](block#3635)) ([`deec4965bc`](block@deec496)) - feat(relay): gate kind 30178 team-catalog reads behind the shared tag ([block#3358](block#3358)) ([`57ece28061`](block@57ece28)) - fix(db): isolate usage metrics advisory-lock test on scratch DB ([block#3670](block#3670)) ([`d9c768d963`](block@d9c768d)) - perf(presence): reduce heartbeat frequency ([block#3783](block#3783)) ([`fdca2b05d0`](block@fdca2b0)) - feat(mesh): upgrade embedded mesh to v0.74 and harden shared compute (split 1/2 of block#3467) ([block#3741](block#3741)) ([`c002ed4946`](block@c002ed4)) - feat(replica): portable heartbeat-token fence with snapshot-local reader routing ([block#3268](block#3268)) ([`82f42a3653`](block@82f42a3)) - fix(git): channel binding tooling + author remediation for unbound repos ([block#3626](block#3626)) ([`ca40fdf49d`](block@ca40fdf)) - feat: configure S3 URL addressing style ([block#3400](block#3400)) ([`8bf7a625d5`](block@8bf7a62)) - feat(tracing): correlate trace IDs in relay logs ([block#3608](block#3608)) ([`6ec63b9f82`](block@6ec63b9)) - fix(relay): avoid subscription lock inversion ([block#3413](block#3413)) ([`3e70de3fa4`](block@3e70de3)) - feat(cli): add users set-status command for NIP-38 profile status ([block#3253](block#3253)) ([`eeb16abd5c`](block@eeb16ab)) - feat(relay): make Postgres pool size configurable, default 50 ([block#3191](block#3191)) ([`02714eaaf6`](block@02714ea)) - feat(tracing): add datastore tracing plumbing ([block#2760](block#2760)) ([`d4991db1bb`](block@d4991db)) - feat(invites): add use-limited invite links ([block#3141](block#3141)) ([`b87b0f8e5f`](block@b87b0f8)) - feat(admin): show reported message content in report detail ([block#3149](block#3149)) ([`27710a9094`](block@27710a9)) - resolve findings ([block#3150](block#3150)) ([`450a97ca0c`](block@450a97c)) - Revert "fix(cli,relay): resolve agents by verified owner" ([block#3168](block#3168)) ([`ccd5fe656d`](block@ccd5fe6)) - fix(cli,relay): resolve agents by verified owner ([block#2615](block#2615)) ([`137e672d8e`](block@137e672)) - fix(security): enforce durable community ban on NIP-43 relay-admin kinds 9030-9033 ([block#3128](block#3128)) ([`516946fe84`](block@516946f)) - fix(security): authorize kind:9000 role changes in both directions ([block#3017](block#3017)) ([`79f439bd89`](block@79f439b)) - feat(desktop): handle project work from Inbox ([block#3117](block#3117)) ([`cb2982b226`](block@cb2982b)) - feat(relay): make per-owner community limit configurable via BUZZ_MAX_COMMUNITIES_PER_OWNER ([block#2599](block#2599)) ([`7ada3f9832`](block@7ada3f9)) - feat(relay): add author-only-unless-shared read gate for kind 30175 ([block#2768](block#2768)) ([`06425bd90f`](block@06425bd)) - fix(core): block IPv6 transition SSRF targets ([block#2801](block#2801)) ([`b57467915a`](block@b574679)) - fix(workflow): bypass system proxies for webhooks ([block#2800](block#2800)) ([`bb002e71ce`](block@bb002e7)) - fix(audit): hash created_at at the precision Postgres stores ([block#2638](block#2638)) ([`9111b622e1`](block@9111b62)) - feat(desktop): make pull request reviews actionable ([block#2510](block#2510)) ([`1585dad4e7`](block@1585dad)) - fix(relay): decompress gzip-encoded git smart-HTTP request bodies ([block#2670](block#2670)) ([`c328869ccc`](block@c328869)) - fix(sharing): preserve agent/team snapshot tEXt chunks through media sanitization ([block#2438](block#2438)) ([`6a679115c0`](block@6a67911)) - fix(relay): send 1012 restart close to all clients on graceful drain ([block#2575](block#2575)) ([`f664ef378e`](block@f664ef3)) - fix(media): sanitize animated image uploads ([block#2524](block#2524)) ([`42e5a289da`](block@42e5a28)) - fix(channels): strip leading hash prefixes from names ([block#2250](block#2250)) ([`53d4d1116d`](block@53d4d11)) - feat(relay): make Redis pool size configurable, default 16 ([block#2521](block#2521)) ([`b4d9eb7bc1`](block@b4d9eb7)) - feat(desktop+acp): spawn a harness per (agent, community) pair at GUI startup — warm sockets, lazy LLM pool ([block#2122](block#2122)) ([`d5d4c4c840`](block@d5d4c4c)) - feat(media): add S3-truth per-community storage sweep ([block#2044](block#2044)) ([`07c22dadb9`](block@07c22da)) - feat(relay): log NIP-98 pubkey attribution on HTTP bridge requests ([block#2206](block#2206)) ([`6b52df2d32`](block@6b52df2)) - Revert "feat(relay): inventory unreachable Git objects" ([block#2275](block#2275)) ([`8b9b128072`](block@8b9b128)) - feat(relay): inventory unreachable Git objects ([block#2264](block#2264)) ([`4d823da995`](block@4d823da)) - relay: add author_type label to buzz_events_stored_total ([block#2243](block#2243)) ([`d3c221741b`](block@d3c2217)) - fix(git): make project branch workflows reliable ([block#2213](block#2213)) ([`f580efc10c`](block@f580efc)) - feat(cli): manage repository protection rules ([block#2193](block#2193)) ([`24d6790761`](block@24d6790)) - feat(cli): add agents archive/unarchive/archived subcommands ([block#2173](block#2173)) ([`741ca0c1a9`](block@741ca0c)) - fix(mobile): sanitize Android image uploads ([block#2188](block#2188)) ([`8fdb72b89d`](block@8fdb72b)) - fix(cli): paginate channel directory queries ([block#2181](block#2181)) ([`5bb3637bce`](block@5bb3637)) - fix(mobile): image upload fails due to unstripped metadata ([block#2185](block#2185)) ([`161b377483`](block@161b377)) - perf(relay): compact Git packs before manifest limits ([block#2172](block#2172)) ([`fd6e03ccea`](block@fd6e03c)) - perf(relay): cache Git pack hydration ([block#2169](block#2169)) ([`1b33b3acdb`](block@1b33b3a)) - fix(relay): bound and observe Git read operations ([block#2167](block#2167)) ([`72bf190409`](block@72bf190)) - relay: gate push enqueue on live leases; batch matcher pipeline (T1b/T1a-repair/T2b) ([block#2145](block#2145)) ([`aad7f98c48`](block@aad7f98)) - relay: add audit logging disable switch ([block#2134](block#2134)) ([`0cd9bc9a80`](block@0cd9bc9)) - relay: skip TTL deadline bump for known-permanent channels (T1a write-amp) ([block#2125](block#2125)) ([`bb3615e590`](block@bb3615e)) - fix(git): carry NIP-OA delegation in auth event ([block#2120](block#2120)) ([`3e11dc9461`](block@3e11dc9)) - Route lag-tolerant reads to an optional Postgres read replica ([block#2084](block#2084)) ([`b26be1ff9c`](block@b26be1f)) - fix: recover community access visibility ([block#2074](block#2074)) ([`d34b307dba`](block@d34b307)) - feat: proxy feedback-scoped admin attachments ([block#2059](block#2059)) ([`93739302fa`](block@9373930)) - feat: add read-only deployment moderation dashboard ([block#1999](block#1999)) ([`ea39127ae8`](block@ea39127)) - Bug-bash round 2: table scroll, Goose instructions, workflow mention wake ([block#2034](block#2034)) ([`b280e89349`](block@b280e89)) - Strip media metadata on clients and reject it at the relay ([block#2006](block#2006)) ([`d06e75cd3b`](block@d06e75c)) - [codex] Hold Git concurrency permits through streaming (BUZZ-SEC-018) ([block#1916](block#1916)) ([`1047442193`](block@1047442)) - [codex] Enforce shared relay admission limits (BUZZ-SEC-019) ([block#1917](block#1917)) ([`bc2f248aa2`](block@bc2f248)) - [codex] Block banned actors from moderation commands (BUZZ-SEC-007) ([block#1915](block#1915)) ([`1cf22688fb`](block@1cf2268)) - [codex] Fix relay WebSocket admission limits ([block#1682](block#1682)) ([`7343e6830b`](block@7343e68)) - feat: add invite QR and mobile direct join ([block#1957](block#1957)) ([`b7be6279bf`](block@b7be627)) - fix(join-policy): require legal consent on hosted invites ([block#1987](block#1987)) ([`78c7910994`](block@78c7910)) - [codex] Prevent actor-tag UI impersonation ([block#1931](block#1931)) ([`94e79d0ead`](block@94e79d0)) - Scope relay runtime state by community ([block#1658](block#1658)) ([`58c17cb5ab`](block@58c17cb)) - Apply optional relay join policy across join flows ([block#1894](block#1894)) ([`a810c50a8e`](block@a810c50)) - feat(media): require auth for relay media reads ([block#1926](block#1926)) ([`e421ad22c8`](block@e421ad2)) - feat(relay): add community unarchive endpoint ([block#1908](block#1908)) ([`f42ff84ea5`](block@f42ff84)) - feat(relay): gate Git web GUI separately ([block#1901](block#1901)) ([`e29a76c799`](block@e29a76c)) - mesh: upgrade runtime, enforce membership, add shared compute provider ([block#1656](block#1656)) ([`2e95fe4139`](block@2e95fe4)) - Route Git scratch through configured volume ([block#1884](block#1884)) ([`64c19ad46b`](block@64c19ad)) - feat(relay): gate usage metrics behind stable leader ([block#1814](block#1814)) ([`b28151465b`](block@b281514)) - Relay mesh: cross-pod tunnel + huddle transport (buzz-relay-mesh) ([block#1670](block#1670)) ([`e2c2b1f04a`](block@e2c2b1f)) - feat(push): deliver accepted relay events as wakes ([block#1866](block#1866)) ([`9f34782057`](block@9f34782)) - fix(db): resolve duplicate migration version ([block#1863](block#1863)) ([`ce24091c96`](block@ce24091)) - Add private product feedback sidecar ([block#1857](block#1857)) ([`60e203db0e`](block@60e203d)) - feat(relay): add durable community archival ([block#1834](block#1834)) ([`500c58d66c`](block@500c58d)) - feat(push): add public APNs gateway ([block#1770](block#1770)) ([`0079d22fb0`](block@0079d22)) - feat(relay): add atomic community ownership transfer ([block#1845](block#1845)) ([`b2766e5b4f`](block@b2766e5)) - Bound NIP-RS retention and search indexing ([block#1771](block#1771)) ([`d47874f0a4`](block@d47874f)) - Add optional standalone pairing relay to Helm chart ([block#1799](block#1799)) ([`7038cf0657`](block@7038cf0)) - fix(relay): publish membership snapshot on provisioning ([block#1761](block#1761)) ([`663f4fbc85`](block@663f4fb)) - feat(relay): per-community usage metrics ([block#1723](block#1723)) ([`e4bf8610da`](block@e4bf861)) - refactor(desktop): remove vestigial MCP toolsets config ([block#1776](block#1776)) ([`9166c2cb28`](block@9166c2c)) **To release:** merge this PR. The tag and build will happen automatically. Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
…ock#5324) The Prompt Context modal (observer feed → check icon under sent messages) was clipping all content and card right-padding at the dialog edge. **Root cause**: `PromptContextDialog` renders inside `DialogContent`, which is a CSS grid. The child flex wrapper had default `min-width: auto`, so the widest unbreakable token in the content (64-char hex event IDs, `Tags: [[...]]` JSON) set the grid track width, blowing it past `max-w-xl`. `overflow-hidden` then clipped everything at the dialog edge — including the section cards' right padding. **Fix**: - `AgentSessionTranscriptList.tsx`: add `min-w-0` to the `flex max-h-[85vh] flex-col` wrapper so the grid item can shrink below its max-content width. - `PromptSectionAccordion.tsx`: replace `wrap-break-word` with `wrap-anywhere` on the body text (open and collapsed states) and the title. `overflow-wrap: anywhere` reduces min-content width, which `break-word` does not, letting long tokens wrap inside the cards rather than inflating the track. The `line-clamp-2` collapsed preview is preserved unchanged. Signed-off-by: Will Pfleger <pfleger.will@gmail.com> Co-authored-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
…ck#5330) ## Problem The `WelcomeComposerGuidanceLayer` in the `#Welcome` channel was positioned with `absolute inset-x-0 bottom-full z-[-1]` — outside the `composerWrapperRef` measurement boundary. `useComposerHeightPadding` observes `composerWrapperRef`'s block size to set `paddingBottom` on the timeline scroll container, but the absolutely-positioned layer didn't contribute to that size. The banner sat directly on top of the newest message, blocking the thread affordance on that message, and had no manual dismiss control. ## Fix **Overlap**: Changed `WelcomeComposerGuidanceLayer` from `absolute inset-x-0 bottom-full z-[-1]` to `relative` (in normal flow). As a normal-flow child of `composer-dock`, the layer's full height is now measured by the ResizeObserver and fed into the timeline's `paddingBottom`, so the newest message is always fully visible and its thread affordance is always clickable while the banner shows. **Dismiss**: Added an `X` close button (`data-testid="welcome-composer-dismiss-button"`) on the prompt state. Clicking fires `onDismiss`, which drives `dismissing → hidden` immediately (same slide-down animation as the auto-dismiss path) and marks the channel ID as completed in the session ref so the banner does not reappear on channel re-entry within the session. **Refactor**: Extracted the banner state machine (refs, timers, `useEffect`s, and callbacks) from `ChannelPane.tsx` into `useWelcomeComposerBanner.ts`. This keeps `ChannelPane.tsx` well under the 1000-line file-size ratchet and makes the state machine independently testable. ## Changed files - `desktop/src/features/channels/ui/WelcomeComposerBanner.tsx` — `WelcomeComposerGuidanceLayer` positioning fix; `onDismiss` prop; dismiss button; `overflow-hidden` / `mb-0` / `flex-1` cleanup - `desktop/src/features/channels/ui/ChannelPane.tsx` — remove inline banner state machine, use `useWelcomeComposerBanner` hook, pass `onDismiss` - `desktop/src/features/channels/ui/useWelcomeComposerBanner.ts` — new hook owning all banner state --------- Signed-off-by: Will Pfleger <pfleger.will@gmail.com> Co-authored-by: Hayt <41ea58f1e64c243627e8acde7c89be667052ee6e17d8f021c1195be4324ebf04@buzz.block.builderlab.xyz>
## Problem
A provider can return HTTP 200 with a **truncated JSON body** — cleanly
closed connection, correct framing, content cut off mid-value. Both LLM
HTTP loops treated this as a terminal error on the first attempt:
`AgentError::Llm("json: EOF while parsing a value")`, surfaced as code
-32000 at the ACP boundary, killing the agent turn before it produced
anything.
Observed live in a tb2.1 bench trial (write-compressor, tb21-twins-1):
deepseek via OpenRouter returned a truncated body, the agent died
mid-prompt with 0 turns completed, and the trial scored 0 on a provider
hiccup.
Meanwhile the same loops already retry timeouts, 429s, 5xxs, 499s, and
mid-body stream stalls — a truncated-but-complete body was the one
transient upstream fault that fell through to terminal.
## Fix
In both `post()` and `openrouter_post()`
(`crates/buzz-agent/src/llm.rs`): when the fully-received success body
fails `serde_json::from_slice`, `continue` the **existing** retry loop
instead of returning terminal — same `MAX_RETRIES` (3) bound, same
`backoff_with_jitter`. On exhaustion, the error goes through
`terminal_llm_error` so it carries cumulative duration + attempt count
like every other retried failure (previously the `json:` error carried
neither).
`post_anthropic` routes through `post()`, so
Anthropic/OpenAI/Databricks/mesh and OpenRouter are all covered.
## Why this cannot re-run a tool call
Hard requirement: tool calls are not idempotent, and this change must
not introduce any possibility of replaying one.
1. **The retry lives inside the HTTP POST helper, below the parse
boundary.** Tool calls are only ever extracted from a *successfully
parsed* response value
(`parse_openai`/`parse_anthropic`/`parse_responses`, all downstream of
these helpers' `Ok` return). A malformed body never parses, therefore no
tool call was ever extracted from it, therefore nothing downstream of it
ever dispatched.
2. **What is re-sent is the completion request itself** — the identical
`body_bytes` captured once at function entry. Sending a completion
request executes no tools; it asks the model for the next message.
3. **Same safety class as existing behavior.** The loop already re-sends
this identical request on 429/5xx/timeout/stream-stall; this adds one
more transient-fault arm to the same loop with the same bytes.
## Tests
Three new tests mirroring the existing 499/dropped-connection fixtures
(raw `TcpListener` stubs):
- `post_retries_malformed_json_body_and_succeeds` — truncated 200 body
on attempt 1, valid JSON on attempt 2; asserts success and **exactly 2**
server-side requests
- `post_exhausts_retries_on_persistent_malformed_json` —
always-truncated body; asserts exactly `MAX_RETRIES` attempts and a
terminal error carrying `json:` + cumulative/attempt context
- `openrouter_post_retries_malformed_json_body_and_succeeds` — same
recovery through OpenRouter's separate loop
Full `cargo test -p buzz-agent` green at e7a5d7b (430 lib + all
integration targets, 0 failures); `cargo fmt` + `clippy --all-targets`
clean.
Originating conversation: buzz-benchmarking channel, thread 397a992d.
Signed-off-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
Co-authored-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
## Summary - remove the complete Welcome guidance surface when dismissal reaches `hidden` - preserve dismissal across the private and starter Welcome channels for the active identity - assert the starter channel's actual `welcome-everyone` title on re-entry ## Why PR block#5330 introduced two deterministic Desktop E2E failures: - the inner banner unmounted, but `welcome-composer-guidance-layer` remained - the re-entry test expected case-sensitive `Welcome` while navigating to `welcome-everyone` The state hook also scoped completion to channel IDs while `ChannelPane` remounts during navigation. The Welcome guidance is one experience spanning both Welcome channels, so completion now survives that remount while remaining identity-scoped. ## Validation At `b577eb42edffe889f63566f2457eacea720f3593`: - `pnpm -C desktop typecheck` - focused Biome check for all four changed files - E2E build - both `welcome-everywhere banner` integration tests repeated three times: **6/6 passed** - mandatory pre-push desktop check, typecheck, and full desktop unit suite: **4,535 passed** - `git diff --check` Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [clap](https://redirect.github.com/clap-rs/clap) | dependencies | patch | `4.6.1` → `4.6.6` | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](..block/issues/1) for more information. --- ### Release Notes <details> <summary>clap-rs/clap (clap)</summary> ### [`v4.6.6`](https://redirect.github.com/clap-rs/clap/compare/clap_complete-v4.6.5...clap_complete-v4.6.6) [Compare Source](https://redirect.github.com/clap-rs/clap/compare/v4.6.5...v4.6.6) ### [`v4.6.5`](https://redirect.github.com/clap-rs/clap/compare/clap_complete-v4.6.4...clap_complete-v4.6.5) [Compare Source](https://redirect.github.com/clap-rs/clap/compare/v4.6.4...v4.6.5) ### [`v4.6.4`](https://redirect.github.com/clap-rs/clap/blob/HEAD/CHANGELOG.md#464---2026-07-21) [Compare Source](https://redirect.github.com/clap-rs/clap/compare/v4.6.3...v4.6.4) ##### Internal - Update to syn v3 ### [`v4.6.3`](https://redirect.github.com/clap-rs/clap/blob/HEAD/CHANGELOG.md#463---2026-07-20) [Compare Source](https://redirect.github.com/clap-rs/clap/compare/v4.6.2...v4.6.3) ##### Fixes - *(derive)* Allow `"literal".function()` as attribute values ### [`v4.6.2`](https://redirect.github.com/clap-rs/clap/blob/HEAD/CHANGELOG.md#462---2026-07-15) [Compare Source](https://redirect.github.com/clap-rs/clap/compare/v4.6.1...v4.6.2) ##### Fixes - *(help)* Say `alias` when there is only one </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/block/buzz). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4zLjIiLCJ1cGRhdGVkSW5WZXIiOiI0NC4xMi4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [async-compression](https://redirect.github.com/Nullus157/async-compression) | dependencies | patch | `0.4.42` → `0.4.43` | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](..block/issues/1) for more information. --- ### Release Notes <details> <summary>Nullus157/async-compression (async-compression)</summary> ### [`v0.4.43`](https://redirect.github.com/Nullus157/async-compression/releases/tag/async-compression-v0.4.43) [Compare Source](https://redirect.github.com/Nullus157/async-compression/compare/async-compression-v0.4.42...async-compression-v0.4.43) ##### Other - Fix hang when decoding a corrupt subsequent zstd frame ([#​470](https://redirect.github.com/Nullus157/async-compression/pull/470)) </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/block/buzz). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4zLjIiLCJ1cGRhdGVkSW5WZXIiOiI0NC4xMi4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [diffy](https://redirect.github.com/bmwill/diffy) | dependencies | patch | `0.5.0` → `0.5.1` | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](..block/issues/1) for more information. --- ### Release Notes <details> <summary>bmwill/diffy (diffy)</summary> ### [`v0.5.1`](https://redirect.github.com/bmwill/diffy/blob/HEAD/CHANGELOG.md#051---2026-07-18) [Compare Source](https://redirect.github.com/bmwill/diffy/compare/0.5.0...0.5.1) ##### Fixed - [#​85](https://redirect.github.com/bmwill/diffy/pull/85) Merge conflict markers are now always placed on their own lines. Previously, a conflicting hunk at the end of a file without a trailing newline glued the next marker onto its last content line, producing unparseable output. This matches `git merge-file --diff3` behavior. </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/block/buzz). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4zLjIiLCJ1cGRhdGVkSW5WZXIiOiI0NC4zLjIiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbXX0=--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates: | Package | Type | Update | Change | Pending | |---|---|---|---|---| | [async-trait](https://redirect.github.com/dtolnay/async-trait) | dependencies | patch | `0.1.89` → `0.1.91` | `0.1.92` | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](..block/issues/1) for more information. --- ### Release Notes <details> <summary>dtolnay/async-trait (async-trait)</summary> ### [`v0.1.91`](https://redirect.github.com/dtolnay/async-trait/compare/0.1.90...0.1.91) [Compare Source](https://redirect.github.com/dtolnay/async-trait/compare/0.1.90...0.1.91) ### [`v0.1.90`](https://redirect.github.com/dtolnay/async-trait/releases/tag/0.1.90) [Compare Source](https://redirect.github.com/dtolnay/async-trait/compare/0.1.89...0.1.90) - Update to syn 3 </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/block/buzz). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4zLjIiLCJ1cGRhdGVkSW5WZXIiOiI0NC4xMi4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [arc-swap](https://redirect.github.com/vorner/arc-swap) | dependencies | patch | `1.9.1` → `1.9.2` | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](..block/issues/1) for more information. --- ### Release Notes <details> <summary>vorner/arc-swap (arc-swap)</summary> ### [`v1.9.2`](https://redirect.github.com/vorner/arc-swap/blob/HEAD/CHANGELOG.md#192) - Document RefCnt must not panic ([#​208](https://redirect.github.com/vorner/arc-swap/issues/208)). </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/block/buzz). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4zLjIiLCJ1cGRhdGVkSW5WZXIiOiI0NC4zLjIiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbXX0=--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [anyhow](https://redirect.github.com/dtolnay/anyhow) | dependencies | patch | `1.0.103` → `1.0.104` | | [anyhow](https://redirect.github.com/dtolnay/anyhow) | workspace.dependencies | patch | `1.0.103` → `1.0.104` | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](..block/issues/1) for more information. --- ### Release Notes <details> <summary>dtolnay/anyhow (anyhow)</summary> ### [`v1.0.104`](https://redirect.github.com/dtolnay/anyhow/releases/tag/1.0.104) [Compare Source](https://redirect.github.com/dtolnay/anyhow/compare/1.0.103...1.0.104) - Update `syn` dev-dependency to version 3 </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/block/buzz). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4zLjIiLCJ1cGRhdGVkSW5WZXIiOiI0NC4zLjIiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbXX0=--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | Type | Update | |---|---|---|---|---|---| | [@isomorphic-git/lightning-fs](https://redirect.github.com/isomorphic-git/lightning-fs) | [`4.6.2` → `4.6.3`](https://renovatebot.com/diffs/npm/@isomorphic-git%2flightning-fs/4.6.2/4.6.3) |  |  | dependencies | patch | | [@vitejs/plugin-react](https://redirect.github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react#readme) ([source](https://redirect.github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react)) | [`6.0.3` → `6.0.5`](https://renovatebot.com/diffs/npm/@vitejs%2fplugin-react/6.0.3/6.0.5) |  |  | devDependencies | patch | | [@vitejs/plugin-react](https://redirect.github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react#readme) ([source](https://redirect.github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react)) | [`6.0.3` → `6.0.5`](https://renovatebot.com/diffs/npm/@vitejs%2fplugin-react/6.0.3/6.0.5) |  |  | dependencies | patch | | [dorny/paths-filter](https://redirect.github.com/dorny/paths-filter) | `v4.0.2` → `v4.0.3` |  |  | action | patch | | [isomorphic-git](https://isomorphic-git.org/) ([source](https://redirect.github.com/isomorphic-git/isomorphic-git)) | [`1.38.7` → `1.38.10`](https://renovatebot.com/diffs/npm/isomorphic-git/1.38.7/1.38.10) |  |  | dependencies | patch | | [postcss](https://postcss.org/) ([source](https://redirect.github.com/postcss/postcss)) | [`8.5.19` → `8.5.26`](https://renovatebot.com/diffs/npm/postcss/8.5.19/8.5.26) |  |  | devDependencies | patch | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](..block/issues/1) for more information. --- ### Release Notes <details> <summary>isomorphic-git/lightning-fs (@​isomorphic-git/lightning-fs)</summary> ### [`v4.6.3`](https://redirect.github.com/isomorphic-git/lightning-fs/releases/tag/v4.6.3) [Compare Source](https://redirect.github.com/isomorphic-git/lightning-fs/compare/v4.6.2...v4.6.3) ##### Bug Fixes - IDB interface ([#​127](https://redirect.github.com/isomorphic-git/lightning-fs/issues/127)) ([035e472](https://redirect.github.com/isomorphic-git/lightning-fs/commit/035e4725b9e6aa72d10cadc5ace20dec7ac76afb)) </details> <details> <summary>vitejs/vite-plugin-react (@​vitejs/plugin-react)</summary> ### [`v6.0.5`](https://redirect.github.com/vitejs/vite-plugin-react/blob/HEAD/packages/plugin-react/CHANGELOG.md#605-2026-07-30) [Compare Source](https://redirect.github.com/vitejs/vite-plugin-react/compare/f4b549822ec239799d746c030abb0b9a7d8f0a04...68c0cb8796ce18bd049c3d05c5210eaf0617eac0) ##### Fixed the react compiler preset filter to be linear ([#​1353](https://redirect.github.com/vitejs/vite-plugin-react/pull/1353)) The improved filter in v6.0.3 was non-linear and caused a performance regression ([#​1349](https://redirect.github.com/vitejs/vite-plugin-react/issues/1349)). The filter was changed to be linear to avoid that. ### [`v6.0.4`](https://redirect.github.com/vitejs/vite-plugin-react/blob/HEAD/packages/plugin-react/CHANGELOG.md#604-2026-07-22) [Compare Source](https://redirect.github.com/vitejs/vite-plugin-react/compare/640fd358a0e82393acfce4e92e19a6ac6e1641a7...f4b549822ec239799d746c030abb0b9a7d8f0a04) ##### Fixed `$RefreshSig$ is not defined` error when running `vite dev` with `NODE_ENV=production` When running `vite dev` with `NODE_ENV=production`, the app errored with `$RefreshSig$ is not defined`. This error is now fixed. </details> <details> <summary>dorny/paths-filter (dorny/paths-filter)</summary> ### [`v4.0.3`](https://redirect.github.com/dorny/paths-filter/blob/HEAD/CHANGELOG.md#v403) [Compare Source](https://redirect.github.com/dorny/paths-filter/compare/v4.0.2...v4.0.3) - [Document safe handling of file list outputs in workflows](https://redirect.github.com/dorny/paths-filter/pull/326) - [Escape multi-line filenames in list-files shell and csv output](https://redirect.github.com/advisories/GHSA-7hc6-8hq5-9q2m) - [Add 'some-with-excludes' predicate quantifier](https://redirect.github.com/dorny/paths-filter/pull/322) - [Add contents permission to PR example](https://redirect.github.com/dorny/paths-filter/pull/248) - [Scope base-ignored warning to API path](https://redirect.github.com/dorny/paths-filter/pull/319) - [Update outputs in readme to account for the 'every' predicate-quantifier](https://redirect.github.com/dorny/paths-filter/pull/247) </details> <details> <summary>isomorphic-git/isomorphic-git (isomorphic-git)</summary> ### [`v1.38.10`](https://redirect.github.com/isomorphic-git/isomorphic-git/releases/tag/v1.38.10) [Compare Source](https://redirect.github.com/isomorphic-git/isomorphic-git/compare/v1.38.9...v1.38.10) ##### Bug Fixes - **statusMatrix:** do not traverse symlinks in GitWalkerFs ([#​1215](https://redirect.github.com/isomorphic-git/isomorphic-git/issues/1215)) ([#​2382](https://redirect.github.com/isomorphic-git/isomorphic-git/issues/2382)) ([90ea101](https://redirect.github.com/isomorphic-git/isomorphic-git/commit/90ea101d329daa84b99cc0140a6275896ebbaf68)) ### [`v1.38.9`](https://redirect.github.com/isomorphic-git/isomorphic-git/releases/tag/v1.38.9) [Compare Source](https://redirect.github.com/isomorphic-git/isomorphic-git/compare/v1.38.8...v1.38.9) ##### Bug Fixes - Preserve binary files when writing conflicted working tree ([#​2380](https://redirect.github.com/isomorphic-git/isomorphic-git/issues/2380)) ([b41b1ab](https://redirect.github.com/isomorphic-git/isomorphic-git/commit/b41b1abc3df87326e639b49d0694915540d6dfb5)) ### [`v1.38.8`](https://redirect.github.com/isomorphic-git/isomorphic-git/releases/tag/v1.38.8) [Compare Source](https://redirect.github.com/isomorphic-git/isomorphic-git/compare/v1.38.7...v1.38.8) ##### Bug Fixes - unsafe symlink from cherry pick ([#​2377](https://redirect.github.com/isomorphic-git/isomorphic-git/issues/2377)) ([4664c8e](https://redirect.github.com/isomorphic-git/isomorphic-git/commit/4664c8e1147c3c7ba87c027e92093d28607ef4c0)) </details> <details> <summary>postcss/postcss (postcss)</summary> ### [`v8.5.26`](https://redirect.github.com/postcss/postcss/blob/HEAD/CHANGELOG.md#8526) [Compare Source](https://redirect.github.com/postcss/postcss/compare/8.5.25...8.5.26) - Fixed `list.split()` regression (by [@​lazerg](https://redirect.github.com/lazerg)). - Track symlinks in path protection in source map loading (by [@​drengir1](https://redirect.github.com/drengir1)). ### [`v8.5.25`](https://redirect.github.com/postcss/postcss/blob/HEAD/CHANGELOG.md#8525) [Compare Source](https://redirect.github.com/postcss/postcss/compare/8.5.24...8.5.25) - Fixed 8.5.17 visitor regression. - Fixed `list.split()` for non-string values (by [@​amir-rezaei](https://redirect.github.com/amir-rezaei)). ### [`v8.5.24`](https://redirect.github.com/postcss/postcss/blob/HEAD/CHANGELOG.md#8524) [Compare Source](https://redirect.github.com/postcss/postcss/compare/8.5.23...8.5.24) - Preserve the BOM after the processing (by [@​hdimer](https://redirect.github.com/hdimer)). ### [`v8.5.23`](https://redirect.github.com/postcss/postcss/blob/HEAD/CHANGELOG.md#8523) [Compare Source](https://redirect.github.com/postcss/postcss/compare/8.5.22...8.5.23) - Do not load source map without `opts.from` for security reasons. ### [`v8.5.22`](https://redirect.github.com/postcss/postcss/blob/HEAD/CHANGELOG.md#8522) [Compare Source](https://redirect.github.com/postcss/postcss/compare/8.5.21...8.5.22) - Fixed custom property losing semicolon before a comment (by [@​sarathfrancis90](https://redirect.github.com/sarathfrancis90)). ### [`v8.5.21`](https://redirect.github.com/postcss/postcss/blob/HEAD/CHANGELOG.md#8521) [Compare Source](https://redirect.github.com/postcss/postcss/compare/8.5.20...8.5.21) - Fixed childless at-rule losing semicolon before comment (by [@​sarathfrancis90](https://redirect.github.com/sarathfrancis90)). - Fixed docs (by [@​isker](https://redirect.github.com/isker)). ### [`v8.5.20`](https://redirect.github.com/postcss/postcss/blob/HEAD/CHANGELOG.md#8520) [Compare Source](https://redirect.github.com/postcss/postcss/compare/8.5.19...8.5.20) - Fixed missing space if `AtRule#params` is set after (by [@​sarathfrancis90](https://redirect.github.com/sarathfrancis90)). - Fixed mixing AST error on warnings (by [@​MahinAnowar](https://redirect.github.com/MahinAnowar)). </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/block/buzz). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yODAuMCIsInVwZGF0ZWRJblZlciI6IjQ0LjEyLjAiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbXX0=--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
…ock#4439) This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [@tanstack/react-virtual](https://tanstack.com/virtual) ([source](https://redirect.github.com/TanStack/virtual/tree/HEAD/packages/react-virtual)) | [`3.14.8` → `3.14.9`](https://renovatebot.com/diffs/npm/@tanstack%2freact-virtual/3.14.8/3.14.9) |  |  | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](..block/issues/1) for more information. --- ### Release Notes <details> <summary>TanStack/virtual (@​tanstack/react-virtual)</summary> ### [`v3.14.9`](https://redirect.github.com/TanStack/virtual/blob/HEAD/packages/react-virtual/CHANGELOG.md#3149) [Compare Source](https://redirect.github.com/TanStack/virtual/compare/@tanstack/react-virtual@3.14.8...@tanstack/react-virtual@3.14.9) ##### Patch Changes - Updated dependencies \[[`a5417b4`](https://redirect.github.com/TanStack/virtual/commit/a5417b4b0d3c82876747bb9635db7239c28d3e44)]: - [@​tanstack/virtual-core](https://redirect.github.com/tanstack/virtual-core)@​3.17.7 </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/block/buzz). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4zLjIiLCJ1cGRhdGVkSW5WZXIiOiI0NC4zLjIiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbXX0=--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
## Summary - temporarily allow the informational `RUSTSEC-2026-0243` advisory for the retired `nostr-relay-pool` crate - document the exact MeshLLM → `nostr-sdk 0.44.1` transitive path and removal condition - keep every other advisory and the global dependency policy enforced ## Why an exception RustSec provides no patched `nostr-relay-pool` release because the standalone crate was absorbed into `nostr-sdk >= 0.45`. Buzz inherits it through pinned MeshLLM v0.74. A direct test bump to `nostr-sdk 0.45.1` removed the retired crate but produced 13 MeshLLM API compilation errors, so the durable fix requires an upstream source migration rather than a lockfile update. This narrow exception restores the required Security check while that migration is completed. It must be removed once MeshLLM adopts `nostr-sdk >= 0.45`. ## Validation - `bin/cargo-deny --locked check --config deny.toml advisories` - `bin/cargo-deny --locked check` - `git diff --check origin/main...HEAD` - mandatory pre-push Rust and desktop/Tauri checks ## Scope One four-line `deny.toml` addition. No Rust source, lockfile, runtime, or release behavior changes. Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
…ock#6456) Switching channels triggered a full-roster fetch (kind:39002 plus a kind:0 profile batch with every member pubkey as an author) in the common case, and several render paths walked the full roster per render. None of this scales past a few hundred members; the product target is 10k+. - **Members query staleTime 30s → 5min.** Every membership change the client can observe already invalidates the key explicitly: live join/leave system messages for the active channel, member-added/removed notifications for the current identity, and all membership mutations — including previously-uncovered direct write paths (moderation kick, agent-deletion cleanup), which now invalidate through a shared helper. The 30s window bought correctness we already had and charged a roster fetch per switch. - **ChannelMembersBar no longer mounts the roster query for non-DM channels** — the count renders from the channel summary, and the private-channel huddle gate accepts `channel.isMember` (derived from the same kind:39002 event as the roster's self entry). - **Roster-derived lookups are cached on roster identity** (`rosterDerivations.ts`): role map, agent-member subset, member/bot pubkey sets. These were rebuilt O(members) on every live message / profile re-key. React Query's structural sharing keeps the roster identity stable, so each derivation computes once per distinct roster. - **Backend: the kind:0 profile join in `get_channel_members` is capped at the first 500 members** (roster order). Members past the cap keep `display_name: None` (UI falls back to pubkey labels and profile caches); `role=="bot"` agent flags are roster-derived and unaffected. Full roster pagination is the structural follow-up. - **Composer keystroke path**: `useCanAddChannelMembers` re-scanned channels + roster per keystroke; now memoized on data identities, sharing the cached pubkey set. ### Measured / estimated impact | metric | before | after | |---|---|---| | roster fetches while switching (live trace) | nearly every switch | ≤1 per channel per 5 min | | roster fetch cost on the wire (live, 51-member channel) | 273ms per fetch | amortized away | | kind:0 `authors` filter size at 10k members | ~670KB per request (~67 B/pubkey) | capped at 500 authors (~34KB) | | warm-switch longtask at 10k members (mock harness, 4× throttle) | 364ms | 318ms | | per-render roster walks (role map, agent sets) at 10k members | O(members) per live message | once per distinct roster | Deferred deliberately: protocol-level roster pagination and removing `memberPubkeys` from channel summaries (needs relay support). --------- Signed-off-by: Max Lampert <maxwell@squareup.com>
…ng after leave (block#6458) Entering Projects fires a large fan: an exhaustive paginated relay enumeration (projects/repos/tombstones), five 2,000-event work-item queries plus assignment-operation scans, per-repo activity summaries, and a local-repository filesystem scan. Measured on a large community (101 issues / 258 PRs): | query | measured cost | |---|---| | work-items (5 × 2,000-event REQs + assignment scans) | 3.5–3.9s | | activity summaries | 4.1s | | repository activity | 1.0–2.2s | | local repository scan | 1.7s | Two lifecycle bugs made the fan far more expensive than it needs to be: - **Freshness windows guaranteed a full refetch on nearly every re-entry** (60s enumeration, 30s work-items/activity, 10s local scan) — i.e., the costs above were re-paid on almost every visit. Every local write path already invalidates its keys explicitly (issue/PR mutations, project creation, repo sync), so the short windows only served remote-actor freshness. Raised to 5m/2m/2m with a 30m enumeration cache: re-entries now paint from cache, and the fan re-runs at most every 2–5 minutes. - **Leaving Projects left the whole fan running**, competing with the next surface's channel fetches on the same relay connection. AbortSignal is now threaded through the enumeration and assignment pagination loops (optional params — behavior identical without a signal), and leaving the surface cancels the work-items query. Deliberately NOT cancelled: the enumeration (the always-mounted sidebar projects section observes it and its 30m cache is valuable), repo snapshots and local scans (native work that can't abort — cancelling would discard the finished result and force the same clones again), and activity summaries (a single bounded request). Abort behavior is covered by red-first unit tests on both pagination loops. Remaining follow-up (out of scope): the queries themselves want a relay-side aggregate instead of shipping thousands of events to compute counts client-side. --------- Signed-off-by: Max Lampert <maxwell@squareup.com>
**Category:** new-feature **User Impact:** Workflow authors can build filtered, runtime-aware automations, understand them at a glance, and get a clear warning before turning on workflows likely to run often. **Problem:** Workflow setup exposed raw configuration without enough help composing message templates, filtering triggers, or understanding saved behavior; activation could also make a broadly triggered workflow live without explaining its likely frequency. **Solution:** Batch 3 adds local, deterministic template variables, trigger filters, and semantic summaries, then refines cards and activation around configured behavior and a risk-aware warning boundary. Scheduling remains the already-shipped implementation, advanced expressions remain lossless, and network-backed identity/message enrichment stays in Batch 4. | Message inputs | Trigger filters | | --- | --- | | Caret-aware, keyboard-accessible suggestions expose trigger-local values and safe prior-step outputs in `send_message.text`. | Structured conditions and validated manual IDs block invalid submission while preserving advanced expressions. | |  |  | | Workflow cards | Risk-aware activation | | --- | --- | | Semantic labels, channel-first hierarchy, configured reaction/action visuals, real step stacks, and compact status controls make behavior scannable. | Broad message and frequent schedule triggers explain the risk before **Turn on**; narrowly scoped triggers proceed without unnecessary ceremony. | |  |  | ## Changes <details> <summary>File changes</summary> **desktop/src/features/workflows/ui/WorkflowActionsMenu.tsx** Separates direct card status controls from secondary actions while retaining modal status actions. **desktop/src/features/workflows/ui/WorkflowCard.tsx** Adds semantic behavior, channel-first hierarchy, configured reaction/action visuals, real subsequent-step stacks, status controls, and reduced-motion-aware trigger feedback. **desktop/src/features/workflows/ui/WorkflowDialog.tsx** Warns before activating broadly triggered workflows while allowing narrowly scoped workflows to proceed directly. **desktop/src/features/workflows/ui/WorkflowFormBuilder.tsx** Connects structured trigger filters and template-aware step inputs while preserving schedules, trigger transitions, and selected YAML authority. **desktop/src/features/workflows/ui/WorkflowStepCard.tsx** Replaces generic labels with deterministic configured-step descriptions. **desktop/src/features/workflows/ui/WorkflowTemplateTextarea.tsx** Adds caret-aware variable suggestions with keyboard navigation and focus restoration. **desktop/src/features/workflows/ui/WorkflowTriggerConditions.tsx** Adds structured local filters, validated author/message IDs, and a lossless advanced-expression fallback. **desktop/src/features/workflows/ui/workflowActivationWarning.ts** and **workflowActivationWarning.test.mjs** Classify broad message and frequent schedule triggers for contextual activation warnings. **desktop/src/features/workflows/ui/workflowConditionExpression.ts** and **workflowConditionExpression.test.mjs** Model and cover parsing, serialization, validation, and advanced-expression preservation. **desktop/src/features/workflows/ui/workflowDefinition.ts** and **workflowDefinition.test.mjs** Preserve trigger/step configuration and derive deterministic card metadata across YAML round trips. **desktop/src/features/workflows/ui/workflowStepDescription.ts** and **workflowStepDescription.test.mjs** Generate and cover local step summaries. **desktop/src/features/workflows/ui/workflowTemplateVariables.ts** and **workflowTemplateVariables.test.mjs** Define and cover trigger-specific, order-bounded variables and caret insertion. **desktop/src/features/workflows/ui/workflowTriggerDescription.ts** and **workflowTriggerDescription.test.mjs** Generate and cover semantic trigger summaries without network lookups. **desktop/tests/e2e/workflow-local-controls.spec.ts** and snapshot Cover filters, IDs, advanced expressions, autocomplete, activation choices, summaries, and YAML authority. **desktop/tests/e2e/workflow-reaction-picker.spec.ts** Covers configured reaction emoji in workflow nodes and summaries. **desktop/tests/e2e/workflows.spec.ts** Covers risk-aware activation warnings, direct safe creation, duplication, and card status controls. </details> ## Reproduction steps 1. Create a message-posted workflow in **Workflows**, add a Send message step, and type `{{trig`; verify keyboard-selectable variables insert at the caret. 2. Configure message-text and manual ID filters; verify malformed IDs block submission and advanced expressions survive Form/YAML transitions. 3. Create a broad message workflow; verify **Back** persists nothing, **Keep off** saves it disabled, and **Turn on** enables it. Confirm a narrowly triggered webhook skips the warning. 4. Inspect the saved card; verify its channel, semantic behavior, configured actions/reaction, real step stack, and status are understandable without opening YAML. ## Validation Validated at exact clean head `f99503819889b95ee3c61657c5c3850aae35481e` on base `a5ca7b0ca204ca8db0812bb69b52b0c66fac4577`. - Focused workflow regressions passed 59/60 locally; the only local miss was a 438-pixel macOS snapshot drift, while the checked-in Linux baseline comes from the failing CI artifact. Repository pre-push gates and E2E build/typecheck passed. - A broader 36-test smoke invocation had 31 passes and five unrelated pre-existing expectation/snapshot failures, so it is not claimed as fully green. Adversarial fixes are recorded in [round one](block#6470 (comment)) and [round two](block#6470 (comment)). --------- Signed-off-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Rizz <302abe414ca6e3134763d2539bfcf145aea2a63fe5f8455204ed602fd40cf381@buzz.block.builderlab.xyz> Co-authored-by: Rizz <302abe414ca6e3134763d2539bfcf145aea2a63fe5f8455204ed602fd40cf381@buzz.block.builderlab.xyz> Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Co-authored-by: Mongo <5398c5fd039b963ce132b3e078e7c4af097dd997517bb5e14c2682fe68c25197@buzz.block.builderlab.xyz>
…pec (block#6517) `biome check` fails with `lint/correctness/noUnusedVariables` on `ORIGINAL_CONTENT` in `desktop/tests/e2e/empty-edit-delete.spec.ts`, which fails `pnpm check` (Desktop Core) for **every PR touching desktop paths** — e.g. it currently blocks block#6460. It presumably landed while Desktop Core was path-skipped on the introducing PR. One-line removal; the constant has no remaining references (the assertions use `RENDERED_ORIGINAL_CONTENT`). Signed-off-by: Max Lampert <maxwell@squareup.com>
## Summary Follow-up to block#5644. Cmd +/- had become a text-only zoom: type scaled while rem-based padding, gaps, widths, avatars, and controls stayed frozen, which produced cramped layouts (see [#buzz-frontend thread](buzz://message?channel=a410ffde-c61f-416a-96e0-c296b5f5ecc9&id=1a758115cf07b00c097f6e988553908c045165325a57637519cfa7ed9c9accec)). Root cause: block#5644 introduced a virtual typography rem so the **Font size** preference could change text without moving layout — a good decoupling — but it also routed **Cmd +/- zoom** through that same px-valued token and pinned the real root at 16px. One decision ("freeze layout") was applied to two dials that shouldn't share it. This PR gives each dial one owner and lets CSS compose them: | Control | Changes | How | |---|---|---| | **Cmd +/- zoom** | Everything — true zoom | Scales the real `<html>` font-size again (`useWebviewZoomShortcuts`) | | **Font size preference** | Text only | Sets `data-font-size`; `typography.css` maps it to a unitless `--buzz-type-scale`, mirroring how density already works | `--buzz-type-rem` becomes `calc(1rem * var(--buzz-type-scale))` — rem-relative, so it rides on zoom automatically. Resulting text px = `16 × zoom × scale × token-ratio`. The 13 / 14 / 15px conversation contract is unchanged at default zoom. Density and the type ramp from block#5644 are untouched. The preference module no longer does px math or knows about zoom; the zoom hook no longer imports the preference module. Net deletion in production code. ## Validation - `pnpm test` — 5,308 desktop unit tests - `pnpm check:px-text`, `tsc --noEmit`, biome - Playwright: `top-chrome-zoom-clearance.spec.ts` (native-chrome clearance stays fixed under root zoom), `inbox-refactor-screenshots.spec.ts` (zoomed row padding now asserts `4.4px` instead of the frozen `4px`), and both `profile.spec.ts` zoom tests (composed zoom × preference, cross-window storage reset) - Before/after screenshots at 140% zoom in the comment below --------- Signed-off-by: morgmart <98432065+morgmart@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [Swatinem/rust-cache](https://redirect.github.com/Swatinem/rust-cache) ([changelog](https://redirect.github.com/Swatinem/rust-cache/compare/e18b497796c12c097a38f9edb9d0641fb99eee32..6323deb102c322ba6fcbdcafc7e3dddab59af2b6)) | action | digest | `e18b497` → `6323deb` | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](..block/issues/1) for more information. --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/block/buzz). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMi4wIiwidXBkYXRlZEluVmVyIjoiNDQuMzkuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [ubuntu](https://hub.docker.com/_/ubuntu) ([source](https://git.launchpad.net/cloud-images/+oci/ubuntu-base)) | container | digest | `4fbb8e6` → `561618e` | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](..block/issues/1) for more information. --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/block/buzz). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMi4wIiwidXBkYXRlZEluVmVyIjoiNDQuMjkuNSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [@tauri-apps/api](https://redirect.github.com/tauri-apps/tauri) | [`2.11.0` → `2.11.1`](https://renovatebot.com/diffs/npm/@tauri-apps%2fapi/2.11.0/2.11.1) |  |  | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](..block/issues/1) for more information. --- ### Release Notes <details> <summary>tauri-apps/tauri (@​tauri-apps/api)</summary> ### [`v2.11.1`](https://redirect.github.com/tauri-apps/tauri/releases/tag/%40tauri-apps/api-v2.11.1): @​tauri-apps/api v2.11.1 [Compare Source](https://redirect.github.com/tauri-apps/tauri/compare/@tauri-apps/api-v2.11.0...@tauri-apps/api-v2.11.1) <details> <summary><em><h4>PNPM Audit</h4></em></summary> ``` No known vulnerabilities found ``` </details> #### \[2.11.1] ##### Enhancements - [`916782601`](https://www.github.com/tauri-apps/tauri/commit/9167826011cc3d114bf12dfb301968fae479891f) ([#​15520](https://redirect.github.com/tauri-apps/tauri/pull/15520) by [@​polw1](https://www.github.com/tauri-apps/tauri/../../polw1)) Document that `Monitor.size`, `Monitor.position` and `Monitor.workArea` are in physical pixels, with examples showing how to convert them to the logical pixels expected by window creation options via `toLogical(monitor.scaleFactor)`. <details> <summary><em><h4>PNPM Publish</h4></em></summary> ``` > @tauri-apps/api@2.11.1 npm-publish /home/runner/work/tauri/tauri/packages/api > pnpm build && cd ./dist && pnpm publish --access public --loglevel silly --no-git-checks > @tauri-apps/api@2.11.1 build /home/runner/work/tauri/tauri/packages/api > rollup -c --configPlugin typescript �[36m �[1m./src/app.ts, ./src/core.ts, ./src/dpi.ts, ./src/event.ts, ./src/image.ts, ./src/index.ts, ./src/menu.ts, ./src/mocks.ts, ./src/path.ts, ./src/tray.ts, ./src/webview.ts, ./src/webviewWindow.ts, ./src/window.ts�[22m → �[1m./dist, ./dist�[22m...�[39m �[32mcreated �[1m./dist, ./dist�[22m in �[1m883ms�[22m�[39m �[36m �[1msrc/index.ts�[22m → �[1m../../crates/tauri/scripts/bundle.global.js�[22m...�[39m �[32mcreated �[1m../../crates/tauri/scripts/bundle.global.js�[22m in �[1m1.4s�[22m�[39m npm verbose cli /opt/hostedtoolcache/node/24.16.0/x64/bin/node /opt/hostedtoolcache/node/24.16.0/x64/bin/npm npm info using npm@11.13.0 npm info using node@v24.16.0 npm silly config load:file:/opt/hostedtoolcache/node/24.16.0/x64/lib/node_modules/npm/npmrc npm silly config load:file:/tmp/286e8dee195254a4370e608b672019b0/.npmrc npm silly config load:file:/home/runner/.npmrc npm silly config load:file:/home/runner/.config/pnpm/rc npm verbose title npm publish tauri-apps-api-2.11.1.tgz npm verbose argv "publish" "--ignore-scripts" "tauri-apps-api-2.11.1.tgz" "--access" "public" "--loglevel" "silly" npm verbose logfile logs-max:10 dir:/home/runner/.npm/_logs/2026-06-17T13_41_23_851Z- npm verbose logfile /home/runner/.npm/_logs/2026-06-17T13_41_23_851Z-debug-0.log npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm. See `npm help npmrc` for supported config options. npm warn Unknown env config "npm-globalconfig". This will stop working in the next major version of npm. See `npm help npmrc` for supported config options. npm warn Unknown env config "overrides". This will stop working in the next major version of npm. See `npm help npmrc` for supported config options. npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm. See `npm help npmrc` for supported config options. npm silly logfile done cleaning log files npm verbose publish [ 'tauri-apps-api-2.11.1.tgz' ] npm http cache file:/tmp/286e8dee195254a4370e608b672019b0/tauri-apps-api-2.11.1.tgz 0ms (cache hit) npm notice npm notice 📦 @tauri-apps/api@2.11.1 npm notice Tarball Contents npm notice 99.3kB CHANGELOG.md npm notice 10.2kB LICENSE_APACHE-2.0 npm notice 1.1kB LICENSE_MIT npm notice 3.5kB README.md npm notice 5.9kB app.cjs npm notice 5.4kB app.d.ts npm notice 5.5kB app.js npm notice 11.2kB core.cjs npm notice 6.5kB core.d.ts npm notice 10.7kB core.js npm notice 11.0kB dpi.cjs npm notice 8.8kB dpi.d.ts npm notice 10.8kB dpi.js npm notice 5.8kB event.cjs npm notice 4.9kB event.d.ts npm notice 5.7kB event.js npm notice 2.2kB external/tslib/tslib.es6.cjs npm notice 2.2kB external/tslib/tslib.es6.js npm notice 3.0kB image.cjs npm notice 2.4kB image.d.ts npm notice 2.9kB image.js npm notice 738B index.cjs npm notice 1.2kB index.d.ts npm notice 669B index.js npm notice 1.1kB menu.cjs npm notice 451B menu.d.ts npm notice 717B menu.js npm notice 3.6kB menu/base.cjs npm notice 887B menu/base.d.ts npm notice 3.6kB menu/base.js npm notice 2.2kB menu/checkMenuItem.cjs npm notice 1.5kB menu/checkMenuItem.d.ts npm notice 2.2kB menu/checkMenuItem.js npm notice 7.4kB menu/iconMenuItem.cjs npm notice 6.1kB menu/iconMenuItem.d.ts npm notice 7.4kB menu/iconMenuItem.js npm notice 5.1kB menu/menu.cjs npm notice 4.4kB menu/menu.d.ts npm notice 5.0kB menu/menu.js npm notice 1.7kB menu/menuItem.cjs npm notice 1.3kB menu/menuItem.d.ts npm notice 1.6kB menu/menuItem.js npm notice 1.1kB menu/predefinedMenuItem.cjs npm notice 2.6kB menu/predefinedMenuItem.d.ts npm notice 1.1kB menu/predefinedMenuItem.js npm notice 7.1kB menu/submenu.cjs npm notice 4.8kB menu/submenu.d.ts npm notice 6.9kB menu/submenu.js npm notice 9.8kB mocks.cjs npm notice 5.0kB mocks.d.ts npm notice 9.7kB mocks.js npm notice 1.8kB package.json npm notice 22.7kB path.cjs npm notice 17.7kB path.d.ts npm notice 21.7kB path.js npm notice 7.1kB tray.cjs npm notice 8.5kB tray.d.ts npm notice 7.0kB tray.js npm notice 20.7kB webview.cjs npm notice 23.8kB webview.d.ts npm notice 20.5kB webview.js npm notice 8.4kB webviewWindow.cjs npm notice 4.9kB webviewWindow.d.ts npm notice 8.3kB webviewWindow.js npm notice 68.1kB window.cjs npm notice 64.9kB window.d.ts npm notice 67.2kB window.js npm notice Tarball Details npm notice name: @tauri-apps/api npm notice version: 2.11.1 npm notice filename: tauri-apps-api-2.11.1.tgz npm notice package size: 135.7 kB npm notice unpacked size: 699.0 kB npm notice shasum: cd6b13fc26403ca095a02e39ecdbec8048d2872d npm notice integrity: sha512-M2FPuYND2m+wh[...]sUepJWugQCvAA== npm notice total files: 67 npm notice npm http fetch GET https://run-actions-1-azure-eastus.actions.githubusercontent.com/113//idtoken/***/***?api-version=2.0&audience=npm%3Aregistry.npmjs.org 200 76ms npm http fetch POST 201 https://registry.npmjs.org/-/npm/v1/oidc/token/exchange/package/@tauri-apps%2fapi 674ms npm verbose oidc Successfully retrieved and set token npm http fetch GET 200 https://registry.npmjs.org/@tauri-apps%2fapi 54ms (cache miss) npm notice Publishing to https://registry.npmjs.org/ with tag latest and public access npm notice publish Signed provenance statement with source and build information from GitHub Actions npm notice publish Provenance statement published to transparency log: https://search.sigstore.dev/?logIndex=1851797040 npm http fetch PUT 200 https://registry.npmjs.org/@tauri-apps%2fapi 2070ms + @tauri-apps/api@2.11.1 npm verbose cwd /tmp/286e8dee195254a4370e608b672019b0 npm verbose os Linux 6.17.0-1018-azure npm verbose node v24.16.0 npm verbose npm v11.13.0 npm verbose exit 0 npm info ok ``` </details> </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/block/buzz). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMi4wIiwidXBkYXRlZEluVmVyIjoiNDQuMzkuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [futures](https://rust-lang.github.io/futures-rs) ([source](https://redirect.github.com/rust-lang/futures-rs)) | dev-dependencies | patch | `0.3.32` → `0.3.34` | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](..block/issues/1) for more information. --- ### Release Notes <details> <summary>rust-lang/futures-rs (futures)</summary> ### [`v0.3.34`](https://redirect.github.com/rust-lang/futures-rs/blob/HEAD/CHANGELOG.md#0334---2026-08-11) [Compare Source](https://redirect.github.com/rust-lang/futures-rs/compare/0.3.33...0.3.34) - Preserve cloned waker identity. ([#​3032](https://redirect.github.com/rust-lang/futures-rs/issues/3032)) - Updato `syn` to 3. ([#​3028](https://redirect.github.com/rust-lang/futures-rs/issues/3028)) ### [`v0.3.33`](https://redirect.github.com/rust-lang/futures-rs/blob/HEAD/CHANGELOG.md#0333---2026-07-18) [Compare Source](https://redirect.github.com/rust-lang/futures-rs/compare/0.3.32...0.3.33) - Fix `ReadLine`'s soundness issue regarding to exception safety. ([#​3020](https://redirect.github.com/rust-lang/futures-rs/issues/3020)) - Fix unsound `Send` impl for `IterPinRef` and `Iter`. ([#​3003](https://redirect.github.com/rust-lang/futures-rs/issues/3003)) - Fix stacked borrows violation in `compat01as03` implementation. ([#​3012](https://redirect.github.com/rust-lang/futures-rs/issues/3012)) - Fix memory leak in `FuturesUnordered::IntoIter`. ([#​3005](https://redirect.github.com/rust-lang/futures-rs/issues/3005)) - Add `portable-atomic-alloc` feature and use it in `FuturesUnordered`. ([#​3007](https://redirect.github.com/rust-lang/futures-rs/issues/3007)) - Re-export `alloc::task::Wake`. ([#​3010](https://redirect.github.com/rust-lang/futures-rs/issues/3010)) - Update `spin` to 0.12. ([#​3014](https://redirect.github.com/rust-lang/futures-rs/issues/3014)) </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/block/buzz). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMi4wIiwidXBkYXRlZEluVmVyIjoiNDQuMjkuNSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [futures-util](https://rust-lang.github.io/futures-rs) ([source](https://redirect.github.com/rust-lang/futures-rs)) | dependencies | patch | `0.3.32` → `0.3.34` | | [futures-util](https://rust-lang.github.io/futures-rs) ([source](https://redirect.github.com/rust-lang/futures-rs)) | workspace.dependencies | patch | `0.3.32` → `0.3.34` | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](..block/issues/1) for more information. --- ### Release Notes <details> <summary>rust-lang/futures-rs (futures-util)</summary> ### [`v0.3.34`](https://redirect.github.com/rust-lang/futures-rs/blob/HEAD/CHANGELOG.md#0334---2026-08-11) [Compare Source](https://redirect.github.com/rust-lang/futures-rs/compare/0.3.33...0.3.34) - Preserve cloned waker identity. ([#​3032](https://redirect.github.com/rust-lang/futures-rs/issues/3032)) - Updato `syn` to 3. ([#​3028](https://redirect.github.com/rust-lang/futures-rs/issues/3028)) ### [`v0.3.33`](https://redirect.github.com/rust-lang/futures-rs/blob/HEAD/CHANGELOG.md#0333---2026-07-18) [Compare Source](https://redirect.github.com/rust-lang/futures-rs/compare/0.3.32...0.3.33) - Fix `ReadLine`'s soundness issue regarding to exception safety. ([#​3020](https://redirect.github.com/rust-lang/futures-rs/issues/3020)) - Fix unsound `Send` impl for `IterPinRef` and `Iter`. ([#​3003](https://redirect.github.com/rust-lang/futures-rs/issues/3003)) - Fix stacked borrows violation in `compat01as03` implementation. ([#​3012](https://redirect.github.com/rust-lang/futures-rs/issues/3012)) - Fix memory leak in `FuturesUnordered::IntoIter`. ([#​3005](https://redirect.github.com/rust-lang/futures-rs/issues/3005)) - Add `portable-atomic-alloc` feature and use it in `FuturesUnordered`. ([#​3007](https://redirect.github.com/rust-lang/futures-rs/issues/3007)) - Re-export `alloc::task::Wake`. ([#​3010](https://redirect.github.com/rust-lang/futures-rs/issues/3010)) - Update `spin` to 0.12. ([#​3014](https://redirect.github.com/rust-lang/futures-rs/issues/3014)) </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/block/buzz). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMi4wIiwidXBkYXRlZEluVmVyIjoiNDQuMzkuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [http](https://redirect.github.com/hyperium/http) | dependencies | patch | `1.4.0` → `1.4.2` | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](..block/issues/1) for more information. --- ### Release Notes <details> <summary>hyperium/http (http)</summary> ### [`v1.4.2`](https://redirect.github.com/hyperium/http/blob/HEAD/CHANGELOG.md#142-June-8-2026) [Compare Source](https://redirect.github.com/hyperium/http/compare/v1.4.1...v1.4.2) - Fix `uri::Builder` to allow `"*"` as the path when scheme and authority are also set, used in HTTP/2 requests. - Fix `Uri` to properly reject `DEL` characters. ### [`v1.4.1`](https://redirect.github.com/hyperium/http/blob/HEAD/CHANGELOG.md#141-May-25-2026) [Compare Source](https://redirect.github.com/hyperium/http/compare/v1.4.0...v1.4.1) - Fix `PathAndQuery::from_static()` and `from_shared()` to reject inputs that do not start with `/`. - Fix `Extend` for `HeaderMap` to clamp max size hint and not overflow. - Fix `header::IntoIter` that could use-after-free if the generic value type could panic on drop. - Fix `header::{IterMut, ValuesIterMut}` to not violate stacked borrows. </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/block/buzz). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMi4wIiwidXBkYXRlZEluVmVyIjoiNDQuMzkuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [http-body-util](https://redirect.github.com/hyperium/http-body) | dependencies | patch | `0.1.3` → `0.1.5` | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](..block/issues/1) for more information. --- ### Release Notes <details> <summary>hyperium/http-body (http-body-util)</summary> ### [`v0.1.5`](https://redirect.github.com/hyperium/http-body/compare/http-body-util-v0.1.4...http-body-util-v0.1.5) [Compare Source](https://redirect.github.com/hyperium/http-body/compare/http-body-util-v0.1.4...http-body-util-v0.1.5) ### [`v0.1.4`](https://redirect.github.com/hyperium/http-body/releases/tag/http-body-util-v0.1.4) [Compare Source](https://redirect.github.com/hyperium/http-body/compare/http-body-util-v0.1.3...http-body-util-v0.1.4) #### What's Changed - Add `Fused` body combinator that always returns `None` once completed. - Add `BodyExt::into_stream()` to convert a body into a `Stream`. - Add `Full::into_inner()` to get the full `Buf`. - Add `InspectFrame` and `InspectErr` combinators. </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/block/buzz). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMi4wIiwidXBkYXRlZEluVmVyIjoiNDQuMzkuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [sonner](https://sonner.emilkowal.ski/) ([source](https://redirect.github.com/emilkowalski/sonner)) | [`2.0.7` → `2.0.8`](https://renovatebot.com/diffs/npm/sonner/2.0.7/2.0.8) |  |  | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](..block/issues/1) for more information. --- ### Release Notes <details> <summary>emilkowalski/sonner (sonner)</summary> ### [`v2.0.8`](https://redirect.github.com/emilkowalski/sonner/compare/v2.0.7...ecce1841c55e4a72dfe139a8992b56498660125e) [Compare Source](https://redirect.github.com/emilkowalski/sonner/compare/v2.0.7...v2.0.8) </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/block/buzz). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4yOS41IiwidXBkYXRlZEluVmVyIjoiNDQuMzkuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [async-trait](https://redirect.github.com/dtolnay/async-trait) | dependencies | patch | `0.1.91` → `0.1.92` | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](..block/issues/1) for more information. --- ### Release Notes <details> <summary>dtolnay/async-trait (async-trait)</summary> ### [`v0.1.92`](https://redirect.github.com/dtolnay/async-trait/releases/tag/0.1.92) [Compare Source](https://redirect.github.com/dtolnay/async-trait/compare/0.1.91...0.1.92) - Resolve double\_must\_use clippy lint in generated code ([#​303](https://redirect.github.com/dtolnay/async-trait/issues/303)) </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/block/buzz). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4yOS41IiwidXBkYXRlZEluVmVyIjoiNDQuMzkuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
…ock#6531) **Category:** fix **User Impact:** Users can insert mentions earlier in a draft and continue typing without the caret corrupting the rest of the message. **Problem:** Caret correction ran after every document change, so typing a mention before existing text repeatedly advanced across the mention separator and interleaved spaces into the draft. **Solution:** Limit correction to the autocomplete settlement it was designed for, with transaction-level and browser-level regression coverage for known and unregistered mentions. <details> <summary>File changes</summary> **desktop/src/features/messages/lib/mentionHighlightExtension.ts** Restricts trailing-space caret advancement to an armed autocomplete settlement instead of every document change. **desktop/src/features/messages/lib/mentionHighlightExtension.test.mjs** Exercises the real ProseMirror plugin state and verifies mid-draft mention typing, unknown tokens, end-of-message typing, and completed-mention separators. **desktop/tests/e2e/mentions.spec.ts** Reproduces the reported composer workflow in Chromium and covers the same corruption path for an unregistered `@token`. </details> ## Reproduction steps 1. Open a channel and enter `hello world` in the composer. 2. Move the caret between `hello` and ` world`. 3. Type ` @bo`, select `bob` from autocomplete, and continue typing `abc`. 4. Confirm the composer reads `hello @bob abc world` with the caret after `abc`. 5. Repeat with an unregistered token such as ` @zzq` and confirm the existing text remains intact. ## Before / After | Before | After | | --- | --- | | Typing after a mid-draft mention walks the caret through the existing message. | Continued typing stays after the inserted mention. | |  |  | --------- Signed-off-by: Taylor Ho <taylorkmho@gmail.com> Co-authored-by: Mongo <5398c5fd039b963ce132b3e078e7c4af097dd997517bb5e14c2682fe68c25197@buzz.block.builderlab.xyz>
**Category:** improvement **User Impact:** Buzz-native project, repository, issue, and pull request links now appear once as compact inline chips, with their details available on hover. **Problem:** Buzz-native entity links rendered both an inline chip and a standalone preview card, repeating the same metadata and adding visual noise to conversations. **Solution:** Exclude Buzz-native links from the shared standalone-preview extractor while leaving entity parsing intact for chip tooltips and preserving external web previews and attachment cards. <details> <summary>File changes</summary> **desktop/src/shared/lib/linkPreview.ts** Stops Buzz-native preview candidates after parsing, including same-relay git clone URLs that normalize to repository entities, while allowing external URLs through the existing snapshot path. **desktop/src/shared/lib/linkPreview.test.mjs** Covers project, repository, issue, pull request, markdown-labeled, same-relay clone, and mixed external-link extraction behavior. **desktop/src/shared/ui/markdown/useMessageLinkPreviews.test.mjs** Confirms sent messages no longer merge a standalone Buzz entity card while external sender snapshots still render. </details> ## Reproduction steps 1. Open a desktop channel containing a `buzz://project`, `buzz://repo`, `buzz://issue`, or `buzz://pr` link. 2. Confirm the link renders as an inline entity chip without a second standalone Buzz card below the message. 3. Hover the chip and confirm its entity metadata remains available. 4. Post an external HTTPS link and confirm its web preview still renders. 5. Paste a same-relay `/git/<owner>/<repo>` clone URL and confirm it uses the repository chip without a duplicate card. ## Screenshots | Before | After | | --- | --- | | Inline chip plus redundant standalone Project card | Inline chip is now the sole presentation | |  |  | **After — rich metadata stays available on hover**  ## Verification At commit `3fa74cdd342ac1f6721b7d56a7f111af31e0e6e9`: - focused link-preview + Markdown unit suites — 119/119 passed - targeted registered smoke E2E — 8/8 passed, including labeled same-relay clone metadata, ordinary-link presentation, and in-app navigation - `cd desktop && pnpm exec tsc --noEmit` — passed - `git diff --check origin/main...HEAD` — passed - pre-push hooks — desktop check, TypeScript, and full desktop unit suite passed --------- Signed-off-by: Rizz <302abe414ca6e3134763d2539bfcf145aea2a63fe5f8455204ed602fd40cf381@buzz.block.builderlab.xyz> Signed-off-by: Taylor Ho <taylorkmho@gmail.com> Co-authored-by: Rizz <302abe414ca6e3134763d2539bfcf145aea2a63fe5f8455204ed602fd40cf381@buzz.block.builderlab.xyz> Co-authored-by: Mongo <5398c5fd039b963ce132b3e078e7c4af097dd997517bb5e14c2682fe68c25197@buzz.block.builderlab.xyz>
…6315) **Category:** new-feature **User Impact:** Users can keep selected agents addressed across consecutive messages without retyping their handles. **Problem:** Repeated conversations with agents require manually typing the same mentions on every turn, which adds friction and makes recipients easy to omit. **Solution:** The composer can now keep agents automatically addressed per channel, either from the mention controls or after a successful inline mention. Addressed agents remain visible in the toolbar, apply to channel threads, survive send failures safely, and never cross community boundaries. ## Changes <details> <summary>File changes</summary> **desktop/src-tauri/src/events/message_tags.rs** Preserves the automatic-address marker on validated mention reference tags. **desktop/src/features/channels/ui/ChannelPane.tsx** Wires the appropriate channel, thread, inbox, or forum composer context without leaking audiences across surfaces. **desktop/src/features/communities/useCommunityInit.ts** Clears composer audience state when the active community changes. **desktop/src/features/forum/ui/ForumComposer.tsx** Wires the appropriate channel, thread, inbox, or forum composer context without leaking audiences across surfaces. **desktop/src/features/forum/ui/ForumComposerAutocompletes.tsx** Wires the appropriate channel, thread, inbox, or forum composer context without leaking audiences across surfaces. **desktop/src/features/home/ui/InboxDetailPane.tsx** Wires the appropriate channel, thread, inbox, or forum composer context without leaking audiences across surfaces. **desktop/src/features/messages/lib/agentAddressMention.d.mts** Defines helpers and types for marked automatic-address mention tags. **desktop/src/features/messages/lib/agentAddressMention.mjs** Defines helpers and types for marked automatic-address mention tags. **desktop/src/features/messages/lib/agentAddressMention.test.mjs** Covers the automatic-address behavior and its failure, keyboard, layout, or persistence boundaries. **desktop/src/features/messages/lib/applyEditTagOverlay.mjs** Preserves automatic-address metadata when edited message tags are overlaid. **desktop/src/features/messages/lib/applyEditTagOverlay.test.mjs** Covers the automatic-address behavior and its failure, keyboard, layout, or persistence boundaries. **desktop/src/features/messages/lib/autoPinMentionedAgentsPreference.test.mjs** Covers the automatic-address behavior and its failure, keyboard, layout, or persistence boundaries. **desktop/src/features/messages/lib/autoPinMentionedAgentsPreference.ts** Stores the preference that keeps explicitly mentioned agents addressed for later messages. **desktop/src/features/messages/lib/extractMentionPersonas.ts** Separates persona recipients from the composer mention orchestration. **desktop/src/features/messages/lib/persistentAgentAudience.test.mjs** Covers the automatic-address behavior and its failure, keyboard, layout, or persistence boundaries. **desktop/src/features/messages/lib/persistentAgentAudience.ts** Maintains bounded, in-memory, channel-scoped automatic agent audiences. **desktop/src/features/messages/lib/useMentionSelection.ts** Centralizes mention picker selection state and agent-first selection behavior. **desktop/src/features/messages/lib/useMentions.ts** Exposes explicit picker origins and selection controls while preserving inline mention behavior. **desktop/src/features/messages/ui/ComposerAddressControls.test.mjs** Covers the automatic-address behavior and its failure, keyboard, layout, or persistence boundaries. **desktop/src/features/messages/ui/ComposerAddressControls.tsx** Renders compact addressed-agent avatars and the automatic-mention management entry point. **desktop/src/features/messages/ui/MentionAutocomplete.test.mjs** Covers the automatic-address behavior and its failure, keyboard, layout, or persistence boundaries. **desktop/src/features/messages/ui/MentionAutocomplete.tsx** Adds automatic-mention controls and options to the existing mention picker. **desktop/src/features/messages/ui/MessageAgentAddressPrefix.tsx** Shows which agents were automatically addressed on a sent message. **desktop/src/features/messages/ui/MessageComposer.tsx** Integrates automatic audiences, picker controls, accessible feedback, shortcuts, and send behavior. **desktop/src/features/messages/ui/MessageComposer.types.ts** Defines the simplified channel audience context shared by composer hosts. **desktop/src/features/messages/ui/MessageComposerToolbar.tsx** Places automatic-address controls in the composer toolbar without crowding narrow layouts. **desktop/src/features/messages/ui/MessageRow.tsx** Displays automatic-address metadata alongside sent message content. **desktop/src/features/messages/ui/MessageThreadPanel.tsx** Wires the appropriate channel, thread, inbox, or forum composer context without leaking audiences across surfaces. **desktop/src/features/messages/ui/composerAgentKeyboard.test.mjs** Covers the automatic-address behavior and its failure, keyboard, layout, or persistence boundaries. **desktop/src/features/messages/ui/persistentAgentAudienceHosts.test.mjs** Covers the automatic-address behavior and its failure, keyboard, layout, or persistence boundaries. **desktop/src/features/messages/ui/useAddressMentionPulse.test.mjs** Covers the automatic-address behavior and its failure, keyboard, layout, or persistence boundaries. **desktop/src/features/messages/ui/useAddressMentionPulse.ts** Provides success and failure animation signals for addressed-agent controls. **desktop/src/features/messages/ui/useAgentAddressLockPicker.test.mjs** Covers the automatic-address behavior and its failure, keyboard, layout, or persistence boundaries. **desktop/src/features/messages/ui/useAgentAddressLockPicker.ts** Coordinates adding, removing, and announcing automatically addressed agents. **desktop/src/features/messages/ui/useAlwaysAddressShortcut.ts** Implements the platform-aware shortcut for toggling automatic addressing. **desktop/src/features/messages/ui/useAutoPinMentionedAgents.ts** Promotes successfully sent inline agent mentions and provides a single undoable notification. **desktop/src/features/messages/ui/useComposerMentionPicker.ts** Opens the mention picker without rewriting the current draft. **desktop/src/features/messages/ui/useMentionSendFlow.helpers.test.mjs** Covers the automatic-address behavior and its failure, keyboard, layout, or persistence boundaries. **desktop/src/features/messages/ui/useMentionSendFlow.helpers.ts** Merges automatic and inline recipients, marks outgoing tags, and restores failed sends safely. **desktop/src/features/messages/ui/useMentionSendFlow.ts** Merges automatic and inline recipients, marks outgoing tags, and restores failed sends safely. **desktop/src/features/messages/ui/usePersistentAgentMentionHydration.ts** Removes the prior draft-text hydration approach now that automatic audiences stay at composer ingress. **desktop/src/features/settings/ui/AgentsSettingsPanel.tsx** Replaces the old global behavior with explicit composer-level automatic-mention controls. **desktop/src/features/settings/ui/PreventSleepSettingsCard.tsx** Replaces the old global behavior with explicit composer-level automatic-mention controls. **desktop/src/shared/lib/keyboard-shortcuts.ts** Defines the user-facing automatic-address keyboard shortcut label. **desktop/src/shared/ui/VideoReviewCommentMarkdown.tsx** Allows automatic-address prefixes to compose with video review timecodes. **desktop/tests/e2e/persistent-agent-audience.spec.ts** Covers the automatic-address behavior and its failure, keyboard, layout, or persistence boundaries. </details> ## Reproduction Steps 1. Open a channel with one or more agents and open the mention picker from the composer. 2. Select an agent for automatic mentions, then send several messages without retyping the handle; confirm the agent remains in the composer control and receives each message. 3. Mention another agent inline, send successfully, and confirm the agent becomes automatically addressed; use the notification's Undo action to reverse it. 4. Open a thread in the same channel and confirm the same addressed agents are available there. 5. Remove an agent from the composer control and confirm later messages stop addressing it. 6. Switch communities and confirm addressed agents do not carry into the other community. ## Screenshots All states below use the dark Buzz theme with a selected lilac accent. ### Addressed composer Selected agents stay visible at the composer ingress without adding handles to the draft.  ### Open mention menu The @ ingress opens the existing mention menu and shows which agents are already addressed.  ### Mention options The inline options pane controls whether a successful one-time agent mention carries into later messages.  ### Agent settings The same preference is available in **Settings → Agents → Conversations**.  --------- Signed-off-by: Taylor Ho <taylorkmho@gmail.com> Co-authored-by: Rizz <302abe414ca6e3134763d2539bfcf145aea2a63fe5f8455204ed602fd40cf381@buzz.block.builderlab.xyz> Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz>
## Summary - add foreground mobile Huddles on Android and iOS with native Opus capture/playback, mute, speaker routing, participants, lifecycle, and minimized drawer UI - keep mobile Huddle cards and roster state live, including ended rooms, relay-resolved profiles, and agents - broadcast desktop agent TTS through the existing Huddle audio protocol ## Scope Foreground human-to-human voice MVP only. Agent setup/transcripts, background calling, recording, and advanced device controls remain out of scope. ## Validation - `just mobile-check` - `just mobile-test` — 1,500 passed - `just desktop-check` and `just desktop-test` — 4,957 passed - desktop typecheck, strict Clippy, and Tauri tests — 2,445 passed, 15 ignored - mobile worktree identity contract checks - physical Pixel/iPhone behavior reviewed during development --------- Signed-off-by: kenny lopez <klopez4212@gmail.com> Signed-off-by: Kenny Lopez <klopez4212@gmail.com> Signed-off-by: Princess Donut <b238ea756dee4d98afa5883fc7f1de61eeabe65bf700e3a5a5a80db5e42e2c2b@buzz.block.builderlab.xyz> Signed-off-by: Tom Brow <tomb@block.xyz> Co-authored-by: Carl <3c4caeafb646d23867f1c4832e68211d77e2561946171625f75c3ce1a3f2670f@buzz.block.builderlab.xyz> Co-authored-by: Princess Donut <b238ea756dee4d98afa5883fc7f1de61eeabe65bf700e3a5a5a80db5e42e2c2b@buzz.block.builderlab.xyz> Co-authored-by: leader <71e9f2c44a6932b6772caaaccda1911d010463c3e2c6c40410b8329956046801@buzz.block.builderlab.xyz> Co-authored-by: Tom Brow <tomb@block.xyz> Co-authored-by: Mongo <9cfd347903944d5b85aa6c93d2ab67381b978a92a31914bca69998968752a1d7@buzz.block.builderlab.xyz>
## Why The ACP prompt puts a machine-specific Workspace prefix before static base guidance and labels the user-facing agent instruction layer as the generic System section. Because the cwd varies by launch and worktree, leading with it reduces reusable prompt-prefix stability. `[Workspace]` was added in [PR block#1194](block#1194) as a defensive fix after a broken `~/.sprout` → `~/.buzz` migration caused agents to scan `$HOME` and trigger macOS TCC prompts. This change retains that grounding while shrinking it to the current working directory and moving dynamic environment context after the static Base prompt. ## What - Emit the prompt in Base → Workspace → Agent Instructions order - Reduce Workspace to `Current working directory: <absolute path>` - Resolve cwd as an absolute native-platform path and preserve Windows drive/UNC paths instead of checking for a leading `/` - Emit Agent Instructions for persona and standalone agent instructions across modern and legacy ACP paths - Preserve parsing for archived observer frames that used System or the former Workspace-before-Base order, and align the persona catalog label ## Risk Assessment Medium-low — this changes prompt framing for every newly created agent session. Existing archived observer frames remain parseable, and execution still uses the same ACP working directory. Cwd resolution now fails clearly instead of substituting `/` when the process directory cannot be resolved. ## References - block#1103 - block#1194 Generated with Codex --------- Signed-off-by: Salman Mohammed <smohammed@squareup.com>
Diagnostic profiling on a large community (101 issues, 258 PRs) showed Projects tab switches taking 2.5–3.6s, dominated by single React commits of 0.5–1.5s and per-render recomputation — fetch work was already off the main thread; the cost was building the UI. ### Measured: tab click → painted, per tab | tab | before | after | |---|---|---:| | projects | 3,608ms | 320–580ms | | repositories | 3,126–3,534ms | 310–410ms | | tasks | 395–1,101ms | ~115ms | | reviews | 322–2,603ms | ~96ms | | activity | 597–741ms | ~148ms | Single-commit ceiling dropped from 1,541ms to ≤200ms (growth steps 25–40ms). Fixes in profiled-cost order: - **Profile popover body mounts only while open.** `UserProfilePopover` carried seven query subscriptions plus interaction hooks per instance even when closed; grids mount hundreds (five per card in people stacks, one per row author) — measured **~40ms per card**, the dominant share of the 1.2s card-tab commits. The always-mounted shell is now just the Radix root + trigger; trigger markup, hover timing, and keyboard handling are unchanged, and hover/tooltip event continuity is preserved because the trigger never remounts. - **Incremental row mounting.** The first 12 cards / 30 rows render in the first commit; the rest stream in 36–60-per-frame low-priority transitions. Grouped lists trim across group boundaries via a pure, tested slicer; the mounted count survives in-place refetches. - **Activity feed**: was rebuilt unmemoized on every render, markdown-flattening every issue/PR/comment body in the community just to sort and keep 30 items (~360+ flattens per render on the measured community). Now memoized, and bodies stay raw until after the sort+slice — 30 flattens, once per data change. - **Contribution graph** (always-visible rail, so every tab paid for it): ~180 day cells each wrapped in a Radix tooltip with per-cell Intl date formatting per render. Now memoized, cells precomputed once per data change, native `title` tooltips. (The activity-bar segments keep their styled Radix tooltips — pinned by an existing spec.) - **Rows/cards memoized with identity-stable props**: per-row selection arrays were rebuilt per row per render (O(n²) — 258 PRs × 258-item arrays each render) and are now hoisted and shared; people arrays derive inside the memoized cards; the rail's stat walk over every issue/PR is memoized. - **`content-visibility: auto`** on cards and rows so offscreen entries skip layout and paint; **tab switches run in a React transition** so the click stays responsive while the new tree mounts. Remaining known cost (out of scope): cold-entry data readiness — the work-item and activity queries ship thousands of events to compute counts (2–4s on a large community; see the fan-lifecycle PR). The structural fix is a relay-side aggregate; tracked as follow-up. --------- Signed-off-by: Max Lampert <maxwell@squareup.com>
## Summary - downgrade Mobile Huddle authentication and native media configuration from protocol v3 to the currently deployed relay's v2 contract - restore the released one-byte relay peer prefix while retaining later reconnect, roster, and playout-reset reliability fixes - update Android, iOS, protocol documentation, and focused tests together Protocol v2 does not carry v3's occupancy epoch on audio frames, so it cannot fence the narrow delayed-packet/peer-index-reuse race. This is an intentional compatibility tradeoff until the relay v3 rollout is ready. ### Related issue None found. ### Testing - `just mobile-check` - `just mobile-test` — 1,661 tests passed - Android debug build installed and launched on Pixel 10 as `xyz.block.buzz.mobile.sprout_mobile_profile_settings`; foreground process verified - signed iOS Release build installed and launched on iPhone as `com.buzz.buzzMobile`; running process verified A live two-device Huddle audio call remains a manual verification step. Signed-off-by: kenny lopez <klopez4212@gmail.com>
## Summary - arrange Huddle participants in a responsive, equal-weight cluster with spring enter/exit motion and a `+N` overflow - spotlight tapped participants over a blurred call surface, with a roster for hidden participants and no self-avatar action - add selection haptics across full-screen and drawer controls, including both end-call buttons <img width="1080" height="2424" alt="Screenshot_20260819-151448" src="https://github.com/user-attachments/assets/00b7fdca-2304-4788-9952-e07224798513" /> <img width="1080" height="2424" alt="Screenshot_20260819-151422" src="https://github.com/user-attachments/assets/a0cfc861-0519-44ff-bb56-4c983ed6344c" /> ## Validation - `just mobile-check` - focused participant, drawer-control, and full-screen end-call widget tests - Huddle-focused widget suite (15 tests) - full mobile Flutter suite (1,538 tests) ## Dependency Built on block#6056 and contains only the follow-up interaction work. Merge after block#6056 lands. --------- Signed-off-by: kenny lopez <klopez4212@gmail.com> Signed-off-by: Kenny Lopez <klopez4212@gmail.com> Signed-off-by: Princess Donut <b238ea756dee4d98afa5883fc7f1de61eeabe65bf700e3a5a5a80db5e42e2c2b@buzz.block.builderlab.xyz> Signed-off-by: Tom Brow <tomb@block.xyz> Co-authored-by: Carl <3c4caeafb646d23867f1c4832e68211d77e2561946171625f75c3ce1a3f2670f@buzz.block.builderlab.xyz> Co-authored-by: Princess Donut <b238ea756dee4d98afa5883fc7f1de61eeabe65bf700e3a5a5a80db5e42e2c2b@buzz.block.builderlab.xyz> Co-authored-by: leader <71e9f2c44a6932b6772caaaccda1911d010463c3e2c6c40410b8329956046801@buzz.block.builderlab.xyz> Co-authored-by: Tom Brow <tomb@block.xyz> Co-authored-by: Mongo <9cfd347903944d5b85aa6c93d2ab67381b978a92a31914bca69998968752a1d7@buzz.block.builderlab.xyz>
Desktop-managed Buzz agents could only use one MCP server (buzz-dev-mcp). Users who wanted web search or other third-party MCP tools alongside the built-in local tools had no way to add them — the desktop flow hardcodes a single MCP command and build_mcp_servers() always returned a vec of one entry. Added BUZZ_ACP_EXTRA_MCP_COMMANDS, a comma-separated env var where each entry is split on whitespace into command + args. build_mcp_servers() appends each as a separate McpServer after the primary server. Extra servers do not receive Buzz relay credentials (BUZZ_RELAY_URL, BUZZ_PRIVATE_KEY) or auth tags — they are third-party tools, not Buzz-native MCP servers. The primary mcp_command short-circuit is preserved: if it is empty, no servers are returned at all, even when extra commands are configured. This is option 1 from issue block#6023. It unblocks the web-search use case (e.g. npx -y mcp-remote https://mcp.tavily.com/mcp/...) without desktop UI changes. Closes block#6023 Signed-off-by: dm-builder <f01486f036641ccb52c11bb1e0ff2346ea89a8b4e3b49cd772249948f6fcbae6@digitalmeld.communities.buzz.xyz> Co-authored-by: Brad Groux <bradgroux@users.noreply.github.com> Signed-off-by: Brad Groux <bradgroux@users.noreply.github.com>
Two correctness issues in the extra MCP server path: 1. Server names derived only from the executable stem collided for common multi-server configurations. Two wrappers like 'npx -y first-mcp' and 'npx -y second-mcp' both became 'npx', tripping McpRegistry's duplicate check at spawn. Now disambiguate with a numeric suffix (npx, npx-2). 2. split_whitespace() corrupted quoted executable paths and arguments containing spaces. Replace with shlex::split, which handles standard shell quoting. Malformed entries are skipped with a warning instead of being silently reinterpreted. Also update the config doc comment to document the delimiter/quoting contract. Addresses themiguelamador's review feedback. Co-authored-by: Brad Groux <brad@digitalmeld.com> Signed-off-by: Brad Groux <brad@digitalmeld.com>
…e sanitization Four issues from wesbillman/Carl's review: P0 — Extra MCP processes received Buzz identity credentials despite the PR's isolation claim. build_mcp_servers gave extras an empty per-server env, but buzz-agent's spawn_one cleared and repopulated every MCP child's environment from PASSTHROUGH_ENV, which includes BUZZ_PRIVATE_KEY, BUZZ_RELAY_URL, and BUZZ_AUTH_TAG. Added a trusted flag to McpServer and McpServerStdio; spawn_one now withholds identity credentials from untrusted servers. The primary buzz-dev-mcp server is trusted; extras are not. P1 — BUZZ_ACP_EXTRA_MCP_COMMANDS was absent from Desktop's reserved env key list, allowing a portable persona or per-agent env to inject an arbitrary command. Added to reserved_env_keys.rs and its test. P1 — Malformed quoting logged the raw command (which may contain an embedded API key) and silently skipped the entry. Now fails closed with only the entry index; the raw command is never echoed. P1 — Generated names used the executable stem verbatim, violating McpRegistry's ASCII alphanumeric/hyphen and 128-byte contract. Added sanitize_mcp_name to replace non-conforming characters with hyphens, strip leading/trailing hyphens, and truncate to 128 bytes. Co-authored-by: Brad Groux <brad@digitalmeld.com> Signed-off-by: Brad Groux <brad@digitalmeld.com>
BradGroux
force-pushed
the
agent/extra-mcp-servers
branch
from
August 23, 2026 02:05
f028105 to
37c7132
Compare
BradGroux
force-pushed
the
agent/extra-mcp-servers
branch
from
August 23, 2026 18:24
37c7132 to
6b54411
Compare
Contributor
Author
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.
What users saw
Desktop-managed Buzz agents could receive only the built-in
buzz-dev-mcpserver. Operators had no process-level way to attach additional MCP servers to the ACP session.What changed
BUZZ_ACP_EXTRA_MCP_COMMANDSfor comma-separated extra MCP server commands..env.example.Example:
BUZZ_ACP_EXTRA_MCP_COMMANDS='npx -y first-mcp,"/opt/MCP Servers/second" --stdio'Verification
just cicargo test -p buzz-acp --quiet(786 unit tests and 9 lifecycle tests)cargo clippy -p buzz-acp --all-targets -- -D warningsNon-goals
Closes #6023