Commit Graph

2319 Commits

Author SHA1 Message Date
Taylor Ho
2dcb090b61 Polish workflow trigger filters
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-14 09:22:22 -07:00
Taylor Ho
dfdde30d87 Align workflows layout with agents page
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-14 00:55:15 -07:00
Taylor Ho
b2761d893d Refine workflow card hover state
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-14 00:30:10 -07:00
Taylor Ho
2af66ff0ad Simplify workflow card footer
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-14 00:23:01 -07:00
Taylor Ho
0d92496f69 Add workflow enable toggle to card menu
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-14 00:21:19 -07:00
Taylor Ho
37f288942b Polish workflow index labels
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-14 00:17:35 -07:00
Taylor Ho
d52292870e Polish workflow trigger labels
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 23:46:52 -07:00
Taylor Ho
b6df66007a Hide unsupported workflow actions
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 23:46:35 -07:00
Taylor Ho
a9229f370a Test simplified workflow equality labels
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 23:45:55 -07:00
Taylor Ho
5d6ac15476 Simplify workflow equality labels
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 23:45:01 -07:00
Taylor Ho
8be1947168 Remove workflow step conditions from form
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 23:39:44 -07:00
Taylor Ho
c92338cde0 Clarify workflow author ID pagination
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 23:28:17 -07:00
Taylor Ho
7075eba33e Show workflow step details
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 23:27:19 -07:00
Taylor Ho
4a5bff2614 Clarify workflow text conditions
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 23:18:36 -07:00
Taylor Ho
4f6ccb2890 Polish workflow trigger presentation
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 23:15:00 -07:00
Taylor Ho
5c4a43ec22 Improve workflow trigger details
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 23:09:03 -07:00
Taylor Ho
b09299e0ae Add workflow message picker
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 22:49:22 -07:00
Taylor Ho
5cdbf19fd1 Clarify workflow step conditions
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 22:41:31 -07:00
Taylor Ho
314cfd0b7b Polish workflow trigger conditions and sequence editor
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 22:35:03 -07:00
Taylor Ho
2d51c6beef Limit workflow ID conditions to equality
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 22:07:35 -07:00
Taylor Ho
21268599d6 Clarify workflow condition defaults
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 21:50:32 -07:00
Taylor Ho
13c9c73ffa Polish workflow condition selectors
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 21:45:13 -07:00
Taylor Ho
c463f043e4 Polish workflow message inputs
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 14:12:38 -07:00
Taylor Ho
ac175010fa Polish workflow landing cards
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 14:12:37 -07:00
Taylor Ho
0e6a04fafd Mark unsupported workflow actions
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 14:12:37 -07:00
Taylor Ho
a97b0aa0d0 Label unsupported workflow reaction action
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 14:12:36 -07:00
Taylor Ho
3cf827b844 Use emoji picker across workflow fields
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 14:12:35 -07:00
Taylor Ho
20073b3a9d feat(workflows): polish conditions and fix listing
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 14:12:34 -07:00
Taylor Ho
75c6336818 fix(desktop): simplify monthly schedule warning
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 14:11:55 -07:00
Taylor Ho
604b9b7390 feat(desktop): improve workflow schedule picker
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 14:11:54 -07:00
Taylor Ho
a6e7e05b6e Guard unsaved workflow changes
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 14:11:53 -07:00
Taylor Ho
03e8542648 Fix workflow node selection styling
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 14:11:53 -07:00
Taylor Ho
a6ad61851d Simplify workflow inspector copy
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 14:11:52 -07:00
Taylor Ho
487745a667 Refine workflow inspector hierarchy
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 14:11:52 -07:00
Taylor Ho
1eb1921b07 Polish workflow builder interactions
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 14:11:51 -07:00
Taylor Ho
b883ac557b Redesign workflow editor
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 14:11:51 -07:00
Taylor Ho
75019b0906 Polish workflow creation form
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-13 14:11:50 -07:00
thomaspblock
b269e8df7e fix(desktop): route compact preview geometry fixture through media proxy (#5799)
**Category:** fix (CI)
**User Impact:** None — test-only change that unblocks `main` and every
open PR.

**Problem:** `main` has been red since #5629 landed on `45f4b91a3`:
`Desktop Smoke E2E (3)` fails `compact link preview image geometry
truncates long titles to one line` on every build (main run 31727837133,
and e.g. #5792, #5790). Two independently-green PRs raced: #5629 added
the test stubbing its preview image at the raw relay origin
(`http://localhost:3000/media/*.png`), while #5627 rewrites sent
snapshot media through the authenticated local media proxy
(`http://127.0.0.1:54321` in the E2E mock bridge). Merged together, the
image request goes to the proxy origin, the stub never matches, and
`naturalWidth` stays `0`.

**Solution:** Point the route stub at the mock proxy origin, matching
the existing `sent link preview media uses the authenticated proxy in
compact and rich cards` test in the same spec.

**Testing:** Reproduced the failure locally on `45f4b91a3`, then with
this fix: targeted test passes, and the full `messaging.spec.ts` smoke
suite passes 58/58.

Signed-off-by: Thomas Petersen <thomasp@squareup.com>
Co-authored-by: Wintermute <3f1797424fd9ad6653a83665c660517777cd7f8c228c0d5907f49e01537f3ca5@buzz.block.builderlab.xyz>
2026-08-13 13:42:16 -07:00
Wes
2693e0db1f Make workflow run history authoritative in Desktop (#5780)
## Summary

- persist stable workflow run `error_code` values separately from human
diagnostics
- expose NIP-98 authenticated, channel-authorized run history and
approval reads with stable keyset pagination
- connect Desktop to those authoritative reads and return the
relay-created run ID on trigger
- show truthful loading, failure, and pending-trace states, and do not
render approval actions from non-actionable stored hashes

## Validation

- pre-push `branch-skew`, `desktop-typecheck`, `desktop-test`,
`rust-tests`, `desktop-tauri-checks`, and `desktop-check` all passed on
`a097dbe5f`
- Desktop tests: 4,761 passed, 0 failed
- `cargo check -p buzz-relay`
- `git diff --check`

## Remaining gate

This does not claim a relay-backed Playwright workflow journey. The
browser relay bridge still routes workflow invokes through in-memory
handlers; that production-shaped acceptance gate remains follow-up work
before Workflows can leave preview.

---------

Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
Co-authored-by: Mongo <5c25403eab7271f9f94ddd4f2b270e8cac2c92e2c830c51877cca6ec974ffb3f@buzz.block.builderlab.xyz>
Co-authored-by: Princess Donut <68157ebd23b3897c1991015c3038658ea916200c67d3a54620b0754d1b92f6e0@buzz.block.builderlab.xyz>
mobile-v0.11.0-rc.1
2026-08-13 12:56:37 -07:00
Taylor Ho
45f4b91a36 fix(desktop): more compact "compact" link previews (#5629)
**Category:** improvement
**User Impact:** Compact link previews now use a single-line title and
smaller thumbnail, making conversations easier to scan.

**Problem:** Compact previews gave long titles and oversized thumbnails
too much visual weight in the message timeline.

**Solution:** Keep titles to one ellipsized line and reduce image
thumbnails to a 104×64 treatment while preserving the existing wide
aspect ratio; Rich previews remain unchanged.

<details>
<summary>File changes</summary>

**desktop/src/shared/ui/compact-link-preview-attachment.tsx**
Tightens the Compact presentation with a single-line title and smaller
wide thumbnail, leaving Rich previews untouched.

**desktop/tests/e2e/messaging.spec.ts**
Adds focused coverage for title overflow, exact 64px card and 104×64
thumbnail geometry, and successful decoded-image rendering using a
realistic fixture, plus an optional visual capture.

**desktop/tests/fixtures/github-pr-5629-og.png**
Provides realistic visible image bytes for the compact-preview
image-rendering E2E path.

</details>

## Reproduction steps

1. Launch the desktop app with link preview style set to Compact.
2. Send a link whose preview has an image and a long title.
3. Confirm the thumbnail renders at the smaller wide size and the title
truncates to one line with an ellipsis.
4. Switch link preview style to Rich and confirm its presentation is
unchanged.

## Screenshot

![Compact link preview at 64px tall with a decoded real-image thumbnail
and one-line truncated
title](https://d24qwcpro867f5.cloudfront.net/repos/buzz/prs/5629/compact-link-preview-real-image-64px.png)

---------

Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz>
2026-08-13 10:51:49 -07:00
klopez4212
98d3d77b42 Fix mobile composer input regressions (#5594)
## Summary

- reuse the channel member snapshot so first-use `@` suggestions appear
immediately
- reduce selection-only composer rebuilds so iOS selection handles stay
responsive
- make Return insert a newline, send only from the composer button, and
animate multiline growth with reduced-motion support

## Validation

- `just mobile-check`
- `just mobile-test` — 1,271 tests passed
- signed iPhone Release and Pixel 10 debug builds installed and launched
- `just ci` passed mobile, Rust, desktop, and web checks until the
unrelated `buzz-terminal` lifecycle test timed out waiting for `$0`;
reproduced unchanged in isolation

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Signed-off-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz
Signed-off-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz>
Co-authored-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz>
2026-08-13 17:58:29 +01:00
klopez4212
8abc2baf0b Add mobile community invites (#5641)
## Summary
- add a permission-gated mobile community invite page
- create, copy, and natively share configurable invite links
- invite a validated npub directly with member/admin role selection
- reuse Buzz profile actions, search styling, settings rows, and modal
sheets

## Validation
- `just mobile-check`
- `flutter test` (1,275 tests)
- Pixel and iPhone review builds installed and launched

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Signed-off-by: Kenny Lopez <klopez4212@gmail.com>
Signed-off-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz>
Co-authored-by: Carl <3c4caeafb646d23867f1c4832e68211d77e2561946171625f75c3ce1a3f2670f@buzz.block.builderlab.xyz>
Co-authored-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz>
2026-08-13 17:47:44 +01:00
Alex Rosenzweig
a96af89526 Harden shared agent instruction review (#4220)
## Summary

- render shared-agent instructions as literal text so Markdown cannot
conceal spoiler contents, link destinations, or image sources
- reject non-reviewable Unicode controls at every agent-definition
boundary while preserving legitimate rendered emoji sequences
- verify shared catalog event IDs and signatures before trusting
authorship, coordinates, pagination, or executable content
- preserve the exact system-prompt bytes between review and execution
instead of silently stripping or normalizing content

## Security rationale

Shared system prompts are executable configuration. Previously, catalog
prompts were projected through the chat Markdown renderer, which could
hide text, replace link destinations with benign labels, and turn image
syntax into remote loads. Zero-width and bidirectional controls could
also make reviewed text differ from what the agent executes.

This change establishes a review invariant: the prompt a user sees is
the prompt the agent executes. Definitions that cannot be reviewed
faithfully are rejected rather than rewritten. Catalog events must also
pass Nostr ID/signature verification before they can claim a publisher,
coordinate, or cursor.

## What changed

- catalog instructions render as exact literal text rather than rich
Markdown
- catalog relay events are verified on a fresh wire-shaped object before
paging, coordinate selection, attribution, or projection
- forged content, pubkeys, signatures, and invalid newer heads are
ignored and cannot shadow a valid signed definition
- TypeScript catalog parsing rejects unsafe remote definitions before
they reach the UI
- shared Rust validation covers persona create/update/import, inbound
relay sync, definition-less managed-agent sync, and catalog publication
paths
- definition-less managed agents now fail closed on local create, local
update, and publication before persistence or relay retention
- linked managed agents validate their local name while treating the
persona definition as authoritative; their inert record-level prompt is
not executed or published
- names reject layout controls; prompts retain ordinary newlines and
tabs
- legitimate emoji composition is supported, including contextual VS16,
ZWJ, skin-tone, family, flag, and keycap sequences
- detached selectors/joiners, bidirectional controls, tag characters,
zero-width concealment, and other default-ignorables remain rejected
- names are bounded to 128 characters and prompts to 64 KiB
- contributor guidance documents the byte-for-byte review requirement
for future sharing paths

Validation reports the offending code point and never silently removes
it.

## E2E recording


[buzz-shared-agent-security-e2e.webm](https://github.com/user-attachments/assets/44d6b75f-0877-490f-bda4-a716fae3f700)

The recording demonstrates:

- a safe definition remains visible
- a prompt containing zero-width `U+200B` is rejected
- a name containing bidi override `U+202E` is rejected
- the prompt is preserved exactly
- spoiler, link, and image syntax remains literal and does not render or
load

## Verification

Passed locally:

- `just test`: all 10 unit and Docker-backed integration stages
- desktop frontend unit suite: 4,295 tests
- persona catalog relay unit suite: 32 tests, including forged-event and
cursor-shadowing cases
- focused Rust definition-validation coverage: 3 local create/update
tests and 6 publication-filtered tests
- complete desktop Tauri library suite after rebase: 2,263 passed, 14
ignored, 0 failed
- desktop Tauri clippy with warnings denied and Rust formatting
- complete agent Playwright spec: 34 tests
- the exact formerly failing `inbox-edit` immediate-attachment smoke
test after rebase: 1 test
- focused shared-agent publish, literal-review, hidden-control,
signature, and cross-member import Playwright coverage
- desktop E2E production build and TypeScript typecheck
- changed-file formatting/lint and file-size ratchet
- pre-commit secret scan and DCO signoff

The branch was rebased onto current `main`, which includes the upstream
attachment-button label fix. Fresh post-rebase GitHub CI is green for
every required and selected check: Desktop Core, all four Desktop Smoke
E2E shards, both Desktop E2E Integration shards and their aggregate,
Desktop E2E Relay, Desktop Build (macOS), Windows Rust, Rust Lint, DCO,
security scanners, and Desktop Release Candidate. The previously failing
`Desktop Smoke E2E (3)` shard now passes.

The repository-wide desktop check also reports existing CSS
formatting/`!important` findings in `components.css` and `terminal.css`;
neither file is changed by this PR. GitHub's Desktop Core lint and
format stage passes on the rebased branch.

---------

Signed-off-by: Alex Rosenzweig <arosenzweig@squareup.com>
2026-08-13 13:11:45 +10:00
Wes
9e0c6b4320 chore(release): release Buzz Desktop version 0.5.11 (#5714)
## Buzz Desktop release v0.5.11

- **Frozen main:** `4749bc7be3cdb78c2db4ce4864775ba7ab60b4cc`
- **Reviewed candidate:** `248b9d1b7666aacbcb1485b76e81de30a271ba0e`
- **Previous desktop release:** `desktop-v0.5.10`
- **Proposed immutable tag:** `desktop-v0.5.11`

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>
2026-08-12 16:15:18 -07:00
Atish Patel
4749bc7be3 feat(acp): report standard adapter usage (#4950)
## Why
Claude Code and Codex expose standard ACP prompt-response usage, but
Buzz only consumed Goose’s private cumulative usage notification. Their
token use and Claude’s cumulative cost were therefore absent from NIP-AM
metrics.

## What
- Read per-turn `session/prompt` response usage for known Claude and
Codex adapters
- Publish Claude’s raw cumulative cost separately from per-turn tokens
without changing the NIP-AM schema
- Keep Goose usage exclusive and cover Claude/Codex wire serialization

## Risk Assessment
Low-to-medium: changes best-effort observability only and does not
affect prompt execution. The adapter-specific mappings preserve source
semantics and omit unavailable fields.

## References
- Validated with `cargo fmt --check`, `cargo test -p buzz-acp --no-run`,
and full `cargo test -p buzz-acp` (678 passed at `652e373a` before
merge-trailer amendment).

Generated with Codex

---------

Signed-off-by: Atish Patel <atish@squareup.com>
Signed-off-by: Brainy Bumble <0ed7657b57c0e8a9f5288390dd6c8d5d0a3a06abe9b01b9006814f52077d6cdf@buzz.block.builderlab.xyz>
Co-authored-by: WorkerBeeGPT <c5c455215c2506cb8ba776518cec804af62d3a0526e32d496a22072e395042b9@buzz.block.builderlab.xyz>
Co-authored-by: Brainy Bumble <0ed7657b57c0e8a9f5288390dd6c8d5d0a3a06abe9b01b9006814f52077d6cdf@buzz.block.builderlab.xyz>
2026-08-12 18:18:01 -04:00
Logan Johnson
7634fe7456 fix(mobile): settle hydrated threads on latest reply (#4702)
🤖
## Summary

Mobile threads could open above the newest reply because the reply query
hydrates across relay pages while the list is still being laid out.
Ordinary thread opens now wait for authoritative hydration and late
layout before settling on the latest reply.

The initial settle is generation-guarded: if another reply arrives while
it is pending, the stale target is discarded and the current tail
becomes the target. Explicit deep links still own their requested
position, existing threads only follow remote replies when the previous
tail was visible, and local sends remain visible.

### Related issue

No matching issue found. This is separate from the channel
unread-navigation behavior in #4239.

Originating Buzz thread:
`buzz://message?channel=a9081ecd-9be0-400b-8bf9-2e8e0d385b80&id=bfb289fc53754f62f641fbf58bf2d7a9c181a3e6eb09a6ba762aeb6904b6cde4&thread=bfb289fc53754f62f641fbf58bf2d7a9c181a3e6eb09a6ba762aeb6904b6cde4`

### Testing

- Added a widget regression covering paginated hydration plus a live
reply arriving during the initial settle.
- Full mobile Flutter test suite passed; `flutter analyze` passed.
- GitHub CI passed, including the Mobile job.
- Built, installed, and launched the debug app on an iPad Pro 11-inch
(M4), iOS 18.6 simulator. An authenticated manual thread traversal was
not performed because the fresh app was not paired to a relay account.

---------

Signed-off-by: npub13n66s06epmqf2kc3v373ez8hj65cuzyvxzjf93vwpervxqn2u7jq2qd9je <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
Signed-off-by: loganj <loganj@squareup.com>
Signed-off-by: npub1em3jmyn4vu57urqf03txrwreccvejvwdy5c4er8nnrwt7rc4tncscs3ssu <cee32d92756729ee0c097c5661b879c6199931cd25315c8cf398dcbf0f155cf1@buzz.block.builderlab.xyz>
Signed-off-by: Brother Darryl <146fb160a3266e6165bfa385f6048c975eda9e21cf65da097a0b5ea7952532a5@buzz.block.builderlab.xyz>
Signed-off-by: Larry <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
Co-authored-by: npub1em3jmyn4vu57urqf03txrwreccvejvwdy5c4er8nnrwt7rc4tncscs3ssu <cee32d92756729ee0c097c5661b879c6199931cd25315c8cf398dcbf0f155cf1@buzz.block.builderlab.xyz>
Co-authored-by: npub13n66s06epmqf2kc3v373ez8hj65cuzyvxzjf93vwpervxqn2u7jq2qd9je <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Brother Darryl <146fb160a3266e6165bfa385f6048c975eda9e21cf65da097a0b5ea7952532a5@buzz.block.builderlab.xyz>
2026-08-12 14:25:32 -07:00
Wes
c86443c599 perf(desktop): persist channel snapshot hash (#5684)
## Summary

- persist each relay/identity's complete channel list and server hash as
one integrity-checked snapshot
- paint the snapshot immediately on cold boot, then revalidate with
`knownHash`
- fail slow-never-wrong: malformed/legacy/partial snapshots and
mismatched not-modified responses force an unhashed full fetch
- add sidebar boot diagnostics and deterministic unit/E2E coverage for
boot, identity/relay isolation, partial writes, mismatch fallback, and
community switches

## Safety invariants

- channel list and hash are serialized in one localStorage document and
replaced together
- snapshot ownership is scoped to normalized relay URL plus identity
pubkey
- a not-modified response is accepted only when its hash exactly matches
the hash describing the available list
- any missing or impossible hash/list pairing retries
`getChannels(null)` before replacing persistence

## Validation

At exact commit `19ca25d23c434cc0b8893a93691aaf4c77794f60` with a clean
working tree:

- `cd desktop && pnpm check && pnpm typecheck` — passed (existing
informational Biome findings only)
- `cd desktop && pnpm test` — 4,723 passed
- `cd desktop && node --import ./test-loader.mjs
--experimental-strip-types --test
src/features/channels/channelSnapshot.test.mjs` — 13 passed
- `cd desktop && pnpm exec playwright test e2e/sidebar-snapshot.spec.ts
--grep "cold boot paints" --repeat-each=5` — 5 passed
- `cd desktop && pnpm exec playwright test e2e/sidebar-snapshot.spec.ts`
— 8 passed
- push hooks repeated desktop check/typecheck and all 4,723 unit tests
successfully

The Playwright suite uses injected bridge delays. Its roughly 0.5–0.6 s
snapshot paint and 3.0 s snapshot-to-live readings are synthetic
invariant evidence, not production desktop performance measurements.

## Measurement context

The controlled current-main investigation is documented separately in
`RESEARCH/DESKTOP_PERF_DEEP_DIVE_2026_08_12.md`; its raw local artifacts
are `.scratch/summer-perf-deepdive-results-v2.json`,
`.scratch/summer-perf-deepdive-run.log`,
`.scratch/summer-perf-deepdive-run-2.log`, and
`.scratch/summer-perf-deepdive-build-2.log`. Those original timings are
also synthetic Chromium/mock-bridge measurements and are not presented
as shipped Tauri/WKWebView or production-relay numbers.


## Latest review delta

At exact tip `e8e2b1d617aac7ea008258ad9974bbf8da9cd2eb`, storage-denial
reads fail open to the live fetch, hashless retries reject `channels:
null` before pair/persistence updates, identity-read failure enables a
hashless live fetch, and repeated consumers reuse snapshot
parsing/integrity validation by storage key + raw document. The four
remaining review nits are deferred as non-blocking follow-ups.

Validation at this tip: sidebar snapshot E2E 30/30 serial; desktop unit
suite 4,725/4,725; full push gate green (desktop check/typecheck/unit,
Rust, Tauri).

---------

Signed-off-by: Summer <1fdd3cc104e2911eb3b2da6f97d1b25f4a7f3550ded4492b24ff1d95acd66766@buzz.block.builderlab.xyz>
Co-authored-by: Summer <1fdd3cc104e2911eb3b2da6f97d1b25f4a7f3550ded4492b24ff1d95acd66766@buzz.block.builderlab.xyz>
2026-08-12 14:23:41 -07:00
Atish Patel
72d56e7bd3 fix(agent): raise output limit and allow 3 recoveries (#5475)
## Summary

Raise the built-in output and recovery defaults so long-running agents
have more room to finish useful work instead of terminating after
repeated 32,768-token reasoning-only responses.

- Raise `BUZZ_AGENT_MAX_OUTPUT_TOKENS` from 32,768 to 65,536
- Raise the finite output-truncation recovery allowance from 2 to 3 via
`BUZZ_AGENT_MAX_TOKEN_RECOVERIES`; `0` still disables recovery
- Strengthen the recovery prompt so the model stops prolonged reasoning,
uses tools immediately, and builds scripts or artifacts in small
verifiable steps
- Preserve the safety invariant that incomplete truncated tool calls are
discarded and never executed
- Keep proactive handoff independently at 90% of
`BUZZ_AGENT_MAX_CONTEXT_TOKENS` (180,000 tokens with the 200,000
default), regardless of the output allowance
- Add request-loop and configuration regressions for exact-N recovery,
disabled recovery, successful tool-first recovery, discarded truncated
calls, and finite round bounds

`BUZZ_AGENT_MAX_OUTPUT_TOKENS` remains an explicit per-agent deployment
setting. Operators should configure it at or below the served model's
output limit; this PR does not perform live provider capability
discovery or automatic clamping.

**Risk:** Medium — this increases the default request size and permits
one additional recovery attempt by default. Recovery remains finite and
bounded by `BUZZ_AGENT_MAX_ROUNDS`. Deployments whose served model
rejects 65,536 output tokens must set a lower per-agent value.

Current output limits
- model - output token max
- DeepSeek V4 Flash - 384,000 tokens
- Qwen 3.8 (Max) - 131,072 tokens
- GLM 5.2 - 131,072 tokens
- GPT 5.6 - 128,000 tokens
- Claude Opus 5 - 128,000 tokens
- Gemini 3.6 Flash - 65,536 tokens
- Kimi K3 (Moonshot)- 131,072 tokens

### Related issue

None found. Originating benchmark analysis:
`buzz://message?channel=c3252dd2-0142-4e01-88c7-a2183c3960a5&id=91e991aab5fd49094583c3937477f6c12db57a41d86edf7fd4745d0d57d10017`

### Testing

- `cargo fmt --all -- --check`
- `cargo test -p buzz-agent` — 595 passed, 0 failed, 0 ignored at
`bd6de557b367850f50325bafdd3c046131942bef`
- `cargo clippy -p buzz-agent --all-targets -- -D warnings`
- Previously failing
`cancelled_turn_with_usage_emits_notification_before_response` passed
alone and in the full rerun
- Push hooks passed: organization guard, branch skew, Rust tests, and
Desktop Tauri checks

### Update — 2026-08-11

Per review feedback, the recovery default is 3. The OpenRouter live
`/models` output-cap discovery, cache, request clamp, and related
tests/documentation were removed. Per-agent output configuration is now
the sole output-cap mechanism. Proactive handoff and its pre-usage byte
fallback now depend only on 90% of `BUZZ_AGENT_MAX_CONTEXT_TOKENS`; with
the 200,000 default, the handoff threshold is 180,000 regardless of
`BUZZ_AGENT_MAX_OUTPUT_TOKENS`.

Generated with Brainy Bumble


### Targeted validation — 2026-08-11

Ran the exact PR binary once on each of the 11 benchmark tasks causally
affected by the previous 32,768-token ceiling, using OpenRouter with
`deepseek/deepseek-v4-flash-0731` pinned to Fireworks and maximum
reasoning effort. Relay-429 collection failures were excluded and rerun
at concurrency 2.

- **6/11 passed:** `circuit-fibsqrt`, `feal-linear-cryptanalysis`,
`model-extraction-relu-logits`, `path-tracing`,
`schemelike-metacircular-eval`, and `sqlite-db-truncate`
- **5/11 reached the benchmark deadline:** `adaptive-rejection-sampler`,
`dna-assembly`, `path-tracing-reverse`, `regex-chess`, and
`write-compressor`
- `regex-chess` reached exactly 65,536 output tokens, triggered one
output-limit recovery, and then reached the deadline. This directly
confirms that the larger ceiling and recovery path were active, but not
that recovery guarantees completion.

For context, ten of these tasks were 0/5 in the historical baseline;
`sqlite-db-truncate`, the clean control, was 4/5. This is targeted
one-attempt-per-task validation rather than a statistically powered
comparison. The result should not be attributed solely to the recovery
default of 3: this PR also raises the output ceiling and strengthens
recovery behavior, and OpenRouter routing conditions may differ from the
historical direct-Fireworks runs.

Generated with Brainy Bumble

---------

Signed-off-by: Atish Patel <atish@squareup.com>
Signed-off-by: Brainy Bumble <0ed7657b57c0e8a9f5288390dd6c8d5d0a3a06abe9b01b9006814f52077d6cdf@buzz.block.builderlab.xyz>
Signed-off-by: Hardworking Honey <c5c455215c2506cb8ba776518cec804af62d3a0526e32d496a22072e395042b9@buzz.block.builderlab.xyz>
Co-authored-by: Brainy Bumble <0ed7657b57c0e8a9f5288390dd6c8d5d0a3a06abe9b01b9006814f52077d6cdf@buzz.block.builderlab.xyz>
Co-authored-by: Hardworking Honey <c5c455215c2506cb8ba776518cec804af62d3a0526e32d496a22072e395042b9@buzz.block.builderlab.xyz>
2026-08-12 16:57:11 -04:00
Wes
59f613c404 fix(desktop): defer foreground resume work (#5696)
## Summary

- defer foreground resume work until the activation task has returned, a
frame has painted, and a trailing task gets a turn
- centralize app-focus subscribers and remove the broad TanStack
`refetchOnWindowFocus` fan-out
- coalesce relay recovery and preserve an explicit deferred refresh only
for workflow data without a polling/push freshness path
- defer the notification permission native check while keeping blur and
cheap correctness signals immediate

## Why

Buzz Desktop 0.5.10 can spend roughly 1.5 seconds in the WebKit
window-focus listener/microtask checkpoint before returning to the run
loop. Focus currently fans out into query refetches, React polling
updates, relay reconnect/replay, and native work in one activation turn.
This patch establishes an interaction-first foreground boundary rather
than letting those consumers compete with the activating input and first
paint.

## Validation

- focused foreground/workflow/relay tests: 18/18 passed before commit
- `pnpm --dir desktop typecheck`: passed before commit
- pre-commit desktop check and file-size gate: passed
- pre-push desktop check, typecheck, and full desktop unit suite:
4,743/4,743 passed at `704e7b4b6618fafce655bb2b07c7a9fe0fc8c643`
- Princess Donut independent adversarial review: PASS after two
lifecycle/freshness blockers were resolved

## Manual test

1. Install the PR build and use Buzz long enough to populate channels,
home, workflows, agents, and other polling surfaces.
2. Switch to another app for 30-60 seconds.
3. Return by clicking Buzz and immediately click a channel or scroll.
4. Confirm the first interaction and paint are prompt, then confirm
channels/home/workflows refresh and a degraded relay reconnects after
the activation boundary.
5. Repeat while rapidly switching away again to verify no resume work
starts after focus has been lost.

---------

Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
2026-08-12 13:46:49 -07:00
Will Pfleger
c6c6e7eca7 perf(desktop): coalesce thread-activity localStorage writes (#5693)
Each incoming thread reply drove a full `JSON.stringify` + `setItem` of
the ~600 KB thread-activity buffer. A burst of replies serialized the
whole blob once per event on the main thread, which is one of the
renderer stalls under load in the desktop-longevity arc.

This collapses the burst into a single debounced write, applying the
coalescing pattern Wes introduced for read-state persistence in #5591
(`readStateManager`) to the thread-activity path.

## What changed

- **`threadActivityStorage.ts`** — coalescing primitives:
- `scheduleThreadActivityWrite` — first-writer-wins (a pending timer is
*not* reset), 1s trailing edge. The timer reads the live buffer *at fire
time* and re-checks the loaded scope, so N replies within the window
persist exactly once with the burst's final state, and a write that
outlives a scope switch can neither land under the new key nor persist
the wrong buffer.
- `flushThreadActivityWrite` — synchronous persist + timer cancel; a
no-op when nothing is pending.
- `removeLegacyThreadActivityKey` — idempotent one-time cleanup of the
orphaned pre-relay-scoping `buzz-thread-activity.v1:<pubkey>` key.
- **`useThreadActivityPersistence.ts`** (new companion hook) — owns the
loaded scope, the write timer, the `pagehide` /
`visibilitychange`→hidden / unmount flush, and hydration + legacy
cleanup on identity/relay change. Mirrors the existing
`useObservedUnreadPersistence` sibling.
- **`useUnreadChannels.ts`** — rewired to instantiate the hook and call
`activityPersistence.schedule(...)` at both writer sites instead of
writing per event. The buffer (`threadActivityRef`) stays parent-owned;
the hook decides when it is durably persisted. Net **990** lines (was
1021), back under the 1000-line ceiling.

## Durability

`pagehide`, `visibilitychange`→hidden, unmount, and scope-reseed all
flush synchronously, so the last burst of replies survives a `Cmd+R` or
an idle reload that tears the webview down inside the coalescing window.

## Tests

- `threadActivityWriteScheduler.test.mjs` — fake-timer unit coverage:
burst→one `setItem`, live-buffer-at-fire-time, scope-mismatch rejection,
stale-scope timer abort, flush persists+cancels, flush no-op, legacy-key
removal.
- `useThreadActivityPersistence.test.mjs` — mounts the real hook via
`createRoot`+`act`: `pagehide` / visibility / unmount flush of the live
buffer, scope switch flushing A under A's key without leaking into B,
B-bucket rehydration, legacy-key cleanup, and the empty-scope write
fence.

## Related

Based on [#5591](https://github.com/block/buzz/pull/5591) (Wes) —
`perf(desktop): coalesce read state localStorage persistence`, the
proven first-writer-wins coalescing pattern this extends to thread
activity.

Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
2026-08-12 12:06:43 -07:00