Skip to content

[upstream-sync] block/buzz 9e0c6b432..eedcd886a (14 commits) - #28

Open
adrienlacombe wants to merge 18 commits into
mainfrom
upstream-sync-20260814
Open

[upstream-sync] block/buzz 9e0c6b432..eedcd886a (14 commits)#28
adrienlacombe wants to merge 18 commits into
mainfrom
upstream-sync-20260814

Conversation

@adrienlacombe

@adrienlacombe adrienlacombe commented Aug 14, 2026

Copy link
Copy Markdown
Owner

Syncs block/buzz 9e0c6b432..eedcd886a14 commits, 150 files, +10957/−1815.

What changed upstream

Desktop — Inbox message delete action (block#5779); agent-mention authorization enforced at send boundaries (block#5681); workflow run history made authoritative (block#5780); compact link previews reworked (block#5629, block#5711, block#5799); shared agent instruction review hardened (block#4220).

Huddle / voice — voice-turn time-to-first-audio cut ~1.0 s → ~0.35 s behind env gates (block#5671); glass Huddle tray behavior polished (block#5590); initial DM load sped up (block#5658).

Relay / db — complete channel member rosters (block#5765); workflow run error codes as a stable classification column, with a new migration (block#5780).

Mobile — community invites (block#5641); composer input regressions fixed (block#5594). 33 files.

CI — new desktop-release-smoke job plus scripts/run-desktop-release-smoke.sh and scripts/e2e-large-channel-roster.sh (block#5699).

Conflicts

Three, all at documented fork patch sites.

migrations/ + crates/buzz-db/src/migration.rs — upstream's 0031_workflow_run_error_codes.sql renumbered to 0033.
The fork holds 0027 and 0028 and both have run on the live database; sqlx checksums applied migrations, so the fork's cannot move. Upstream's has never run here, so it is the one that renumbers. Contents byte-identical — the rename is the whole change.

This is the dangerous shape again: upstream's 0031 landed directly on the fork's 0031_community_deletion.sql, so the two files sorted adjacent and the tree looked plausible. ls migrations/*.sql | cut -d_ -f1 | sort | uniq -d is now empty.

Assertions moved with it — only the count arrived as a conflict, the rest as clean context:

Assertion Was Now
migrations.len() 31 (upstream) / 32 (fork) 33
workflow_run_error_codes_… index migrations[30] migrations[32]
same test's version version == 31 version == 33
same test's find(|m| m.version == 1) unchanged — that is the initial schema, not a renumber site

That last row is the trap worth naming: AGENTS.md says to sweep for version == N literals, and this test has one that must not move.

.github/workflows/release.ymlassemble-manifest was made unreachable again, with no conflict marker.
Upstream block#5699 added desktop-release-smoke, pinned if: github.repository == 'block/buzz', and added needs.desktop-release-smoke.result == 'success' to assemble-manifest's gate. Only the needs: list conflicted — the gate condition merged in as clean context. In this fork that job always reports skipped, so the gate could never be satisfied and latest.json would never be published while every updater archive and .sig uploaded fine.

Resolved as success || skipped, matching the existing release-macos-x64 treatment. block/buzz still requires every lane to succeed. This is the third instance of this exact pattern (after block#3568 and the -ge 3 platform count), so AGENTS.md now records it as a recurring shape rather than an incident.

desktop/src-tauri/src/relay.rs — kept both sides: the fork's pub mod allowlist; and upstream's new mod get; pub use get::get_relay_json;.

Also in this PR

fix(sync): re-resolve root Cargo.lock — the merged lock left buzz-admin's uuid entry undisambiguated once upstream's buzz-admin change brought a second uuid (0.8.2) into the tree. Regenerated, not hand-edited; no dependency version moved. Local gates read the working tree, so this fails only in CI if left unstaged.

Verification

All run locally on the committed state.

Gate Result
cargo fmt --all --check pass
cargo fmt --manifest-path desktop/src-tauri/Cargo.toml --all --check pass
cargo clippy --workspace --all-targets -- -D warnings pass
cargo clippy --manifest-path desktop/src-tauri/Cargo.toml --all-targets -- -D warnings pass
cargo metadata --locked (root) pass (after the re-resolve above)
cargo metadata --locked (desktop) pass
scripts/test-release-ref-contract.sh release ref contract passed
scripts/test-oss-desktop-promotion.sh passed
scripts/test-oss-desktop-promotion-behavior.sh passed
scripts/test-mobile-worktree-overrides.sh passed
just test-unit 335 + 21 + 345 + 105 + 22 + 15 + 158 pass, 0 fail
dart format --set-exit-if-changed . 387 files, 0 changed
flutter analyze No issues found!
flutter test 1331 pass

Migration tests specifically confirmed green: embedded_migrator_contains_consolidated_initial_schema, workflow_run_error_codes_are_additive_and_backfilled_without_parsing_diagnostics, deletion_surface_parity_between_migration_0029_and_schema_sql.

The release-ref contract was run in a clean clone — from the working checkout it copies target/ (~53 GB).

Needs a human look

This PR trips tripwire 1 (new migration) and tripwire 4 (conflict in release.yml), so it is deliberately not auto-merged.

  1. migrations/0033_workflow_run_error_codes.sql runs DDL against production on merge. It is ALTER TABLE workflow_runs ADD COLUMN error_code TEXT plus a backfill of legacy_unclassified over rows already in ('failed','cancelled'). Additive and lock_timeout = '5s', but infra/aws/ecs.tf sets BUZZ_AUTO_MIGRATE=true, so merging applies it at relay boot. Worth a look at the workflow_runs row count before merging.

  2. The release.yml gate fix is only exercised at desktop release time, not by this PR's CI. If it is wrong, the symptom is a silently missing latest.json rather than a red check.

  3. Not caused by this sync, but still true and still blocking real releases: rolling-manifest promotion remains unreachable in this fork (upstream ci(release): gate OSS desktop auto-update promotion block/buzz#5398). assemble-manifest stages updater-manifest.json on the versioned release, but nothing promotes it to buzz-desktop-latest, and scripts/promote-oss-desktop-release.sh requires exactly the four upstream platform triples where this fork produces three. Installed clients are not seeing new versions regardless of this PR.

No wire-format changes. No event-kind changes. No fork-local patch deleted.


Merge with a merge commit, not squash. A squash drops the second parent, leaves the merge base stale, and makes every future sync re-resolve these same conflicts from the same base.


Update — CI round 1, and a clean-merge breakage it caught

First CI run came back 2 red: Desktop Core and Desktop (the latter is only the gate depending on the former). Those are two different failures and it matters which is which.

Fixed here: relay.rs breached the file-size ratchet

Desktop file size ratchet failed (base HEAD^1):
- src-tauri/src/relay.rs: 999 -> 1002 (+3) lines (allowed 1000)

Caused by my conflict resolution, and a textbook clean-merge breakage — the merge reported nothing, just test-unit was green, and it surfaced only as a red job. desktop/scripts/check-file-sizes.mjs enforces a hard 1000. Upstream's new mod get; was +3; the fork's allowlist block and release-relay fallback are +14 over upstream's 987.

Fixed in 841c5ede6 by condensing the fork's own two comment blocks → 995 (8 over upstream, 5 of headroom). Deliberately did not split or reorganise upstream's relay.rs: that trades five lines for a permanent conflict surface in a file upstream is actively developing — it is extracting submodules from it already. The full reasoning for both fork patches lives in the AGENTS.md patch table, which is the durable record; the in-file comments only need to mark the hunk.

just desktop-check now exits 0, and desktop fmt + clippy were re-run after the edit — both clean.

There is a wider point recorded in AGENTS.md: this file's constraint is now the thing to watch on every sync. The fork moved pub mod allowlist; out of lib.rs in the 2026-08-01 sync precisely because lib.rs was at the ratchet — and relay.rs has now become the constrained file in turn. It announces itself as a red Desktop Core, never as a conflict.

Not fixed here: Desktop Core is already red on main

main at 67dc367d6 fails the same job at a different stepdesktop-test, not desktop-check:

AssertionError: expected href: 'buzz://message?channel=…&id=root-event'

Upstream's messageLink / remarkMessageLinks tests hardcode buzz:// against this fork's renamed bitcoinmarkets:// scheme. Pre-existing, unrelated to this sync, and not mine to fix here — it predates this PR and will keep any sync PR's Desktop Core red until someone decides how to handle it (the options are carrying a test patch or teaching the tests to read the scheme constant).

So expect this PR to settle with Desktop Core still red for that reason. The ratchet breach — the part this sync actually caused — is fixed. Every other check passed on round 1, including Mobile, all four Desktop Smoke E2E shards, Desktop E2E Relay, Backend Integration, Unit Tests, Rust Lint, both cross-compiles, and all four CodeQL analyses.

shellz-n-stuff and others added 17 commits August 13, 2026 13:11
## Summary

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

## Security rationale

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

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

## What changed

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

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

## E2E recording


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

The recording demonstrates:

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

## Verification

Passed locally:

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

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

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

---------

Signed-off-by: Alex Rosenzweig <arosenzweig@squareup.com>
## Summary
- add a permission-gated mobile community invite page
- create, copy, and natively share configurable invite links
- invite a validated npub directly with member/admin role selection
- reuse Buzz profile actions, search styling, settings rows, and modal
sheets

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

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Signed-off-by: Kenny Lopez <klopez4212@gmail.com>
Signed-off-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz>
Co-authored-by: Carl <3c4caeafb646d23867f1c4832e68211d77e2561946171625f75c3ce1a3f2670f@buzz.block.builderlab.xyz>
Co-authored-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz>
## Summary

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

## Validation

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

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Signed-off-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz
Signed-off-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz>
Co-authored-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz>
**Category:** improvement
**User Impact:** Compact link previews now use a single-line title and
smaller thumbnail, making conversations easier to scan.

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

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

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

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

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

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

</details>

## Reproduction steps

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

## Screenshot

![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>
## Summary

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

## Validation

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

## Remaining gate

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

---------

Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
Co-authored-by: Mongo <5c25403eab7271f9f94ddd4f2b270e8cac2c92e2c830c51877cca6ec974ffb3f@buzz.block.builderlab.xyz>
Co-authored-by: Princess Donut <68157ebd23b3897c1991015c3038658ea916200c67d3a54620b0754d1b92f6e0@buzz.block.builderlab.xyz>
…oxy (block#5799)

**Category:** fix (CI)
**User Impact:** None — test-only change that unblocks `main` and every
open PR.

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

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

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

Signed-off-by: Thomas Petersen <thomasp@squareup.com>
Co-authored-by: Wintermute <3f1797424fd9ad6653a83665c660517777cd7f8c228c0d5907f49e01537f3ca5@buzz.block.builderlab.xyz>
…lock#5681)

## Summary
- allow channel-member remote/headless agents only with current kind
`10100` directory evidence, while stale member identities remain hidden
- fail closed while managed/relay directories load, error, or
background-refetch across channel, forum, and cached autocomplete
surfaces
- revalidate agent mention authorization immediately before normal sends
and message-edit saves, including after deferred uploads
- in owner-only builds, fetch fresh authoritative profile ownership at
send time and deny missing, changed-owner, or unavailable proofs
- preserve human mention tags when agent authorization is revoked or
unknown

Supersedes block#5536 because its contributor-fork head cannot be updated by
maintainers.

## Validation
Exact head: `7278cdd5fbcee676c7b858ea098503c62eeeff0d`

- mandatory pre-push suites passed: desktop check/typecheck/tests, Rust
tests, mobile tests, desktop Tauri checks, branch-skew
- desktop unit tests: 4,732 passed
- focused edit/ownership regressions: 8 passed
- focused mention E2E: 5 passed (remote positive, stale-member negative,
directory error, pre-send revocation, mid-send revocation)
- file-size ratchet passed

One first focused E2E batch had a timing-only miss where the send click
did not emit; the isolated rerun passed. One separate pre-push attempt
hit the existing randomized passphrase separator test; the successful
exact-head push reran and passed the mandatory suite.

---------

Signed-off-by: JDiz00 <174381550+JDiz00@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: JDiz00 <174381550+JDiz00@users.noreply.github.com>
Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
### What changed?

Inbox message action menus now show a standalone Delete action beside
Edit for manageable messages. Delete reuses the existing confirmation
and targets the message whose menu was opened, while the existing
empty-edit deletion path remains unchanged.

### Why?

Inbox users can delete a message directly without first entering edit
mode. Thread context can contain multiple messages, so the action must
preserve the active Inbox selection and delete only the chosen row.

### How is it tested?

Desktop checks, typechecking, builds, and test suites pass.

Added tests:

- [Inbox edit and delete E2E
coverage](https://github.com/block/buzz/tree/main/desktop/tests/e2e/inbox-edit.spec.ts)

Signed-off-by: Tom Brow <tomb@block.xyz>
Co-authored-by: Codex <noreply@openai.com>
## Summary

- return complete channel rosters instead of truncating at 1,000 members
- chunk `event_mentions` inserts inside one transaction so large kind
`39002` snapshots remain discoverable by every `p` tag
- add a targeted `buzz-admin reconcile-channels --channel <uuid>`
force-republish path for stale discovery snapshots
- cover a 1,501-member roster, 11,000-tag mention index, and kind
`39002` tag construction past member 1,000

## Why

The relay builds NIP-29 discovery and several authorization decisions
from `get_members()`, but that helper silently returned only the first
1,000 active members. Desktop then counted the truncated kind `39002`
event, while late members could be rejected by roster-scanning member
actions.

Removing the roster cap exposes PostgreSQL's 65,535 bind-parameter
ceiling in mention indexing, so the insert is chunked transactionally to
preserve all-or-nothing indexing.

The existing reconcilers only fill missing discovery events. The
targeted admin option bypasses the separately known 1,000-channel
reconciliation-list ceiling and replaces an existing channel snapshot
using the configured production relay key.

## Attribution

This supersedes and builds on block#3166 by @LordMelkor. Thank you for
identifying the roster boundary and contributing the original
complete-roster and mention-index patch. The production roster/query
changes and the two PostgreSQL regressions retain that work's shape;
this PR rebases it onto current `main`, adds relay coverage, and adds
the targeted repair operation requested for rollout.

## Validation

Exact pushed head: `24d02e4f3824150ed84913c9d230e675502e5b12`

- `cargo check -p buzz-db -p buzz-admin`
- `cargo test -p buzz-db
channel::tests::get_members_returns_full_roster_beyond_1000 -- --ignored
--exact --nocapture`
- `cargo test -p buzz-db
feed::tests::insert_mentions_indexes_rosters_past_bind_parameter_cap --
--ignored --exact --nocapture`
- `cargo test -p buzz-relay --lib
handlers::side_effects::tests::group_members_snapshot_keeps_members_past_one_thousand
-- --exact`
- `cargo run -q -p buzz-admin -- reconcile-channels --help`
- mandatory pre-push hook: branch-skew, desktop checks/typecheck/tests,
mobile tests, Rust tests, and desktop Tauri checks all passed on the
pushed head

## Rollout

1. Deploy the relay/backend build.
2. Run `buzz-admin reconcile-channels --channel <general-channel-uuid>`
with `BUZZ_RELAY_PRIVATE_KEY` configured.
3. Verify the replacement kind `39002` roster count matches the active
database membership count.

No schema migration or desktop release is required.

Fixes block#3156
Supersedes block#3166

---------

Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
## Summary

- add `just desktop-release-smoke`, a deterministic desktop
correctness/reachability smoke against an ephemeral real local relay
- preserve existing DM history when the first live DM enters a pageless
query window, the desktop-v0.5.10 disappearing-DM regression
- enforce foreground JS ordering: a frame and actionable sidebar input
must dispatch before mounted stale queries begin resume refetches, while
separately requiring the navigation to commit promptly
- seed a 10,000-event dense-second fixture and verify exact event-ID
reachability, SHA-256 identity, ordering, duplicate absence, bounded
mounted rows, and drained render work
- isolate Postgres per run, serialize the shared Redis DB, retain
phase/relay/Playwright diagnostics, and gate desktop release manifest
assembly on the smoke

This is deliberately **not a performance-regression gate**. CDP and
action timing fields are informational only. There is no
candidate/baseline comparison or threshold. A future performance lane
needs repeated equivalent fixtures, discrete interaction samples, and an
explicit comparator/noise policy.

The diagnostics record the fixture version, row count, wall-clock base
timestamp (`fixtureSecond`), expected event-ID hash, observed state, and
measurements. Because the created-at floor requires a current timestamp,
paired comparison remains disabled.

The release job runs on an isolated GitHub-hosted runner. The script
also guards automatic local runs with a Redis allocation lock. Its
remaining direct-PID cleanup and free-port selection race mean it should
not be repurposed onto a persistent concurrent shared runner without
first hardening process-group cleanup and port reservation.

### Related issue

N/A

### Testing

- `pnpm --dir desktop typecheck`
- focused real-local-relay release smoke passed after adversarial review
fixes
- identical DM witness passed current and failed `desktop-v0.5.10` with
the history-loss signature
- identical foreground witness bytes
(`2c1e97df04c9b8ca0304b66bbbe9bdb4d08924ad8ce0f68a9c490458fcc3aca8`)
failed `desktop-v0.5.10` structurally: the first resume fetch was marker
1, before first frame/sidebar dispatch at marker 8
- with PR block#5696 (`59f613c40`) merged, the witness showed focus at 951.3
ms, first frame at 951.6 ms, click dispatch at 952.1 ms, first resume
fetch at 968.9 ms, and route commit at 992.4 ms
- the gate therefore protects first paint and actionable input dispatch;
route commit is a bounded responsiveness witness, not a prerequisite for
resume work
- the corrected focused foreground scenario passed at
`6d9b5be40da58bbee92a856b04c3558946d0a950`; the prior merged-tree full
run passed DM retention and 10k reachability before exposing this
contract mismatch
- pre-push passed on exact pushed head
`6d9b5be40da58bbee92a856b04c3558946d0a950`, including desktop checks,
typecheck, desktop tests, Rust tests, mobile tests, and Tauri checks
- full 10,000-event scenario reached 10,000/10,000 exact IDs with
matching SHA-256, 199 continuation requests, and 95 mounted rows in
about 4.4 minutes
- reduced-row review run passed in 18.4 seconds

### Foreground witness boundary

The Chromium test is a deterministic JS policy gate. Headless Chromium
does not expose an honest blur/focus transition in this fixture, so the
test drives the production focus listener and `document.hasFocus()`
predicate together and records that simulation explicitly. It proves
refetch fan-out ordering, not AppKit activation, WKWebView paint, or an
activating physical click. A packaged macOS native lane is still
required before claiming the actual desktop activation experience is
certified.

---------

Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
## Summary

- inset the in-app Huddle tray with four rounded corners and even 8px
spacing when Glass background is enabled
- keep the popped-out Huddle dock full-width
- hide and suppress Glass background on Linux

## Why

The in-app tray reused the opaque backing needed by non-glass windows,
which covered the native vibrancy around it. Linux does not support this
window treatment.

## Testing

- `pnpm -C desktop build:e2e`
- focused Appearance and Huddle Playwright smoke tests
- pre-push desktop checks, typecheck, and 4,666 unit tests

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Signed-off-by: Princess Donut <b238ea756dee4d98afa5883fc7f1de61eeabe65bf700e3a5a5a80db5e42e2c2b@buzz.block.builderlab.xyz>
Co-authored-by: Princess Donut <b238ea756dee4d98afa5883fc7f1de61eeabe65bf700e3a5a5a80db5e42e2c2b@buzz.block.builderlab.xyz>
## Summary

- avoid blocking first-DM navigation on a full channel-list refresh
- publish the initial message through the acknowledged HTTP path instead
of waiting on a missing WebSocket acknowledgement

## Validation

- 4,715 desktop unit tests
- desktop typecheck and checks
- focused new-DM Playwright coverage

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Co-authored-by: Mongo <9cfd347903944d5b85aa6c93d2ab67381b978a92a31914bca69998968752a1d7@buzz.block.builderlab.xyz>
… s (env-gated latency levers) (block#5671)

## Overview

**Category:** feat (env-gated experiment + one exact always-on
optimization)
**Problem:** Speech-end -> first TTS audio through the desktop huddle
pipeline measures **924–1087 ms** on an M4 Max with a 0 ms LLM leg.
Voice turns feel sluggish no matter how fast the agent replies. Baseline
breakdown: ~300 ms hardcoded VAD silence flush + ~150–250 ms Parakeet
decode + ~380–550 ms TTS synthesis before the first player append.
**Outcome:** With all levers enabled, e2e time-to-first-audio measures
**347–384 ms** (307–357 ms on a longer utterance) on the same hardware,
harness, and production pipelines. Defaults preserve production behavior
everywhere except one deterministic, bit-exact cache win.

## What's in here

### Levers (all default-off, env-gated)

| Lever | Env | Effect (measured medians, short utterance) |
|---|---|---|
| Speculative Parakeet decode | `BUZZ_STT_SPECULATIVE=1` | STT leg ->
~max(flush, decode) |
| Streaming TTS synthesis | `BUZZ_TTS_STREAMING=1`,
`BUZZ_TTS_EMIT_FRAMES` | first audio 380–550 -> 211–320 ms (emit=12,
bit-exact) |
| ONNX intra-op threads | `BUZZ_STT_THREADS`, `BUZZ_TTS_THREADS` | TTS
first audio 211–320 -> 129–180 ms (4 threads) |

- **Speculative decode** starts the Parakeet decode at the *first*
silent VAD frame, overlapping it with the flush window. Resumed speech
invalidates the result (voiced-frame-count check); held silence emits it
instantly at the flush boundary.
- **Streaming TTS**: new `synth_chunk_streaming` (buzz-voice)
interleaves the Flow LM frame loop with incremental *stateful* Mimi
decoding, emitting PCM deltas to the player via the existing
`PlaybackChunkAudio` decoration. At `emit_frames=12` (the decoder's
native chunk) streamed audio is **bit-identical** to the batch path —
verified by the ignored test
`incremental_stateful_decode_matches_batch_decode` (max|diff|=0).
Smaller deltas are faster but diverge (~23 dB SNR; decoder intra-chunk
lookahead), hence the default of 12.

> **Removed after live testing:** the `BUZZ_STT_FLUSH_MS` flush-window
override. Lowering the silence window below natural mid-sentence pauses
(the fast-path recipe said 150 ms) split single spoken sentences into
multiple messages and confused the listening agents. The window is a
turn-taking quality knob, not a latency lever — it is now fixed at the
production 300 ms value.

### Push-to-talk grouping fix (always-on)

A held push-to-talk shortcut is an explicit "I am not done talking"
signal, so silence never ends the utterance while it is held — even when
the microphone is also manually open. The utterance flushes on shortcut
release (existing transmit-edge flush); a manually open mic with the
shortcut up keeps normal VAD pause flushing. Gate is the pure
`vad_flush_allowed` function with a unit-test truth table.

### Always-on (exact): voice-conditioning cache

Phase profiling (`BUZZ_TTS_PHASE_LOG=1`) showed a fixed ~160 ms
`condition_voice` Flow-LM pass on *every* chunk, re-deriving the same
post-conditioning state for the same reference voice. The state is now
snapshotted after first computation and restored per chunk (dtype-tagged
tensor copies, keyed identically to the existing `cached_voice`).
Deterministic — same tensors in, same tensors out. The default path's
TTS leg drops from 380–550 ms to 225–355 ms with no configuration.

### Bench harness

`huddle::latency_bench` (`#[cfg(test)]` + `#[ignore]`) drives the real
`SttPipeline` and `TtsPipeline`, feeding a 48 kHz WAV in real-time 100
ms batches (AudioWorklet cadence) with a configurable fake LLM in place
of the relay leg, timing speech-end -> transcript -> speak() -> first
accepted player append.

```
BUZZ_STT_SPECULATIVE=1 BUZZ_TTS_STREAMING=1 \
BUZZ_TTS_THREADS=4 BUZZ_STT_THREADS=2 \
BUZZ_BENCH_WAV=<48k f32 mono wav> \
cargo test --release -p buzz-desktop --lib huddle::latency_bench -- --ignored --nocapture
```

## Tradeoffs to weigh before promoting any lever to a default

- **Speculative decode**: the speculative buffer has ~1 silent tail
frame vs ~19; observed one CTC wobble ("fail" vs "failed") in 24 turns.
Mitigation if productionized: zero-pad the speculative buffer to match
the flush-path shape.
- **Threads**: defaults stay 1 pending the min-spec (4-core Intel) A/B
flagged in the existing `STT_NUM_THREADS` comment.
- **Streaming at emit<12** is NOT the same waveform — don't ship below
12 without an ear pass.

## Validation

- Full desktop lib suite: **2408 passed / 0 failed** at this head
(`18fab2e1c`).
- buzz-voice suite green; bit-exactness test passes against the
production batch decode.
- Defaults-only bench rerun stays in the baseline family everywhere
except the exact conditioning-cache win (stt 525–532, tts 225–355).
- `cargo clippy --workspace --all-targets -- -D warnings` + fmt clean
(pre-push hook battery green).

Measurement notes with per-lever logs: Eva's workspace,
`RESEARCH/HUDDLE_E2E_LATENCY_OPTIMIZATION_2026_08_12.md` +
`RESEARCH/HUDDLE_E2E_STT_FAKELLM_TTS_BASELINE_2026_08_12.md`.

## Suggested promotion order

1. Conditioning cache (in this PR, always-on, exact).
2. Streaming TTS at emit=12: bit-exact audio, biggest UX win — needs the
env-gate removed + barge-in soak + an ear pass on a real huddle.
3. Speculative decode with silence padding: near-free ~100–150 ms.
4. Threads: after min-spec A/B.

---------

Signed-off-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
Signed-off-by: Wren <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@buzz.block.builderlab.xyz>
Signed-off-by: Max <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@buzz.block.builderlab.xyz>
Signed-off-by: Mari <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@buzz.block.builderlab.xyz>
Signed-off-by: tlongwell-block <tlongwell@block.xyz>
Co-authored-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
Co-authored-by: Wren <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@buzz.block.builderlab.xyz>
Co-authored-by: Max <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@buzz.block.builderlab.xyz>
Co-authored-by: Mari <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@buzz.block.builderlab.xyz>
Co-authored-by: tlongwell-block <tlongwell@block.xyz>
…ell (block#5711)

## Problem

In compact link preview cards with an image, the thumbnail's corners
looked inconsistent — the flush left side and the interior right side
read as different shapes.

## Cause

The `Attachment` shell rounds its corners with a **smooth-corner
(squircle) clip path** via `useSmoothCorners`, not a plain
`border-radius`. In compact image mode the shell has `p-0`, so the
thumbnail sits flush against its left, top, and bottom edges.

That means:

- **Left corners** are carved by the shell's smoothed clip path.
- **Right corners** are drawn by the thumbnail's own plain
`border-radius`.

A circular arc and a smoothed corner of the *same* radius are different
shapes (at 16px the smoothed curve starts 25.6px along the edge instead
of 16px). So the two sides could never match by picking a radius value —
the thumbnail's class has no effect on its left corners at all.

## Fix

Give the thumbnail the same `useSmoothCorners` treatment as the shell,
so both sides share one curve.

- Radius token unchanged: `rounded-2xl` (16px).
- The shell and the shared `Attachment` component are untouched, so no
other `Attachment` consumer changes.

Verified on a rendered card — thumbnail vs shell now agree on all three:
arc radius (16), smoothing (0.6), and curve start (25.6px).

## Hardening

The underlying issue is an invariant that lived nowhere: **a child flush
against a smooth-cornered parent must share its corner treatment.** This
is why the bug was easy to introduce and hard to diagnose.

- Documented the invariant in `smoothCorners.ts`, where anyone reaching
for the hook will see it.
- Added an `expectSmoothCorners()` guard to the existing compact-preview
e2e test. Confirmed it **fails** when the fix is reverted, so it
genuinely bites.

Note: this cannot be a lint rule — "flush" is a runtime layout fact, not
visible in the source.

## Known follow-up (not in this PR)

The composer link preview (`useComposerLinkPreviews.tsx`) has the same
latent issue: a flush thumbnail with a hand-copied `rounded-l-2xl` that
happens to match the shell's current 16px. It is correct today only by
coincidence of two literals agreeing. Left for a separate PR rather than
expanding scope here.

## Screenshots

The same compact card and content before and after the change.

| Before | After |
| --- | --- |
| Original `rounded-xl` (12px) thumbnail: left corners are clipped by
the card’s 16px smooth silhouette while the right corners keep the
thumbnail’s smaller plain radius | `rounded-2xl` (16px) thumbnail with
the same smooth-corner treatment as the card |
| ![Before: compact link preview with the original 12px thumbnail
corners](https://raw.githubusercontent.com/block/buzz/9911631a0698cae25df4d41471dde69faa4169dc/pr-5711--before.png)
| ![After: compact link preview with matching 16px smooth thumbnail
corners](https://raw.githubusercontent.com/block/buzz/9911631a0698cae25df4d41471dde69faa4169dc/pr-5711--after.png)
|

## Verification

- `pnpm exec biome check` on all three touched files
- `pnpm exec tsc --noEmit`
- `node --test src/shared/ui/smoothCorners.test.mjs` — 3 passed
- All 18 link-preview e2e tests pass
- Guard verified to fail without the fix, then pass with it

Signed-off-by: morgmart <98432065+morgmart@users.noreply.github.com>
Sync 14 upstream commits (9e0c6b4..eedcd88).

Conflicts, all at documented fork patch sites:

- migrations/: upstream's 0031_workflow_run_error_codes.sql renumbered to
  0033. The fork holds 0027 and 0028 and both have run on the live database,
  so sqlx checksums mean the fork's cannot move; upstream's has never run
  here, so it is the one that renumbers. Contents byte-identical.

- crates/buzz-db/src/migration.rs: count 32 -> 33, and upstream's new
  workflow_run_error_codes test shifted from migrations[30]/version 31 to
  migrations[32]/version 33. Only the count arrived as a conflict; the
  indexed assertions merged as clean context.

- .github/workflows/release.yml: upstream block#5699 added desktop-release-smoke,
  pinned to block/buzz, and required its success in assemble-manifest. Only
  the needs: list conflicted -- the gate condition merged silently. In a fork
  that job always reports skipped, so requiring success would strand
  latest.json again, the same breakage as block#3568. Accept success||skipped,
  matching the release-macos-x64 treatment.

- desktop/src-tauri/src/relay.rs: kept both the fork's `pub mod allowlist;`
  and upstream's new `mod get;`.

Signed-off-by: adrienlacombe <6303520+adrienlacombe@users.noreply.github.com>
The merged lock left buzz-admin's `uuid` entry undisambiguated. Upstream's
buzz-admin change brings a second uuid version (0.8.2) into the tree
alongside 1.23.1, so the bare name no longer resolves and
`cargo metadata --locked` fails.

Regenerated rather than hand-edited, per AGENTS.md. The only change is the
disambiguating version suffix; no dependency version moved.

Local gates read the working tree, so an unstaged re-resolve passes here and
fails only in CI -- verify both locks from the committed state.

Signed-off-by: adrienlacombe <6303520+adrienlacombe@users.noreply.github.com>
…ssion

Two shape changes from this sync:

- migrations/: upstream's 0031_workflow_run_error_codes.sql is 0033 here.
  Fifth renumbered migration across four syncs -- it has now fired on every
  sync that touched migrations/, so the note says to expect it by default
  rather than treating it as a possibility. The renumber table gains a row,
  including that upstream's new test also carries a `version == 1` lookup
  that must NOT move: a version literal is not automatically a renumber
  site, which the previous "sweep for version == N" advice did not qualify.

- release.yml: assemble-manifest now accepts `skipped` from
  desktop-release-smoke as well as release-macos-x64. Recorded as a pattern
  rather than an incident -- this is the third time upstream has added a
  block/buzz-pinned lane to that gate, and all three arrived as clean
  context in the `if:` block while only the `needs:` list conflicted.

Signed-off-by: adrienlacombe <6303520+adrienlacombe@users.noreply.github.com>
@adrienlacombe adrienlacombe added upstream-sync needs-human Sync stopped on a tripwire; a human must review and merge labels Aug 14, 2026
The merge resolution pushed desktop/src-tauri/src/relay.rs to 1002 lines
against the hard 1000-line limit in desktop/scripts/check-file-sizes.mjs,
failing Desktop Core. Upstream's new `mod get;` was +3; the fork's allowlist
block and release-relay fallback are +14 over upstream's 987.

Condensed the fork's own two comment blocks to 995 rather than touching
upstream code. The full reasoning for both patches already lives in
AGENTS.md's patch table, which is the durable record -- the in-file comments
only need to mark the hunk as fork-local.

Deliberately not splitting or reorganising upstream's relay.rs to make room:
that would trade five lines for a permanent conflict surface in a file
upstream is actively developing. Upstream is extracting submodules from it
anyway.

This is a clean-merge breakage, not a conflict -- nothing in the merge output
pointed at it, and it surfaced only as a red Desktop Core.

Signed-off-by: adrienlacombe <6303520+adrienlacombe@users.noreply.github.com>
@adrienlacombe

Copy link
Copy Markdown
Owner Author

CI round 2 — settled: 31 pass, 2 fail, 3 skipping

The ratchet fix in 841c5ede6 took. Desktop Core got past desktop-check this time (4m36s vs 1m31s — it now reaches the test step instead of dying at lint) and there is no file size ratchet line anywhere in the log.

The 2 remaining reds are the pre-existing main failure, not this sync.

Desktop Core now fails at Desktop unit tests / just desktop-test:

AssertionError: expected href: 'buzz://message?channel=…&id=root-event'
AssertionError: input did not match /data-href="buzz:\/\/message\?channel=.*&amp;id=/

Byte-identical to main at 67dc367d6 (run 31697816502). Upstream's messageLink / remarkMessageLinks tests hardcode buzz:// while this fork emits bitcoinmarkets://. Desktop is a gate job whose only step is Check desktop jobs, so it is a cascade of the above, not a second defect.

Worth recording that the two failures were at different steps of the same job, since desktop-check runs before desktop-test: my ratchet breach failed the job early enough that this scheme failure never ran. Waving the first run off as "the usual Desktop Core redness" would have shipped a real regression.

Everything else is green — Mobile, all four Desktop Smoke E2E shards, Desktop E2E Relay, both Desktop E2E Integration shards, Backend Integration, Relay E2E, Relay-Driven Mesh Lifecycle Smoke, Unit Tests, Rust Lint, Security, both server cross-compiles, Windows Rust, all four Docker builds, and all four CodeQL analyses.


Still not auto-merged, by design. Tripwires 1 (new migration 0033) and 4 (conflict in release.yml) both fired, and tripwire 5 (any check red) stands too — though that last one is unfixable from inside a sync PR while the scheme failure sits on main.

Fixing the buzz:// test literals on main is what restores unattended syncs; the idiom is already in the sibling messageLink.test.mjs (a FORK-LOCAL const SCHEME the assertions derive from). Note that only literals asserting output may move — buzz:// must still parse, since old links exist in message history.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-human Sync stopped on a tripwire; a human must review and merge upstream-sync

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants